1   /*
2    *   Licensed to the Apache Software Foundation (ASF) under one
3    *   or more contributor license agreements.  See the NOTICE file
4    *   distributed with this work for additional information
5    *   regarding copyright ownership.  The ASF licenses this file
6    *   to you under the Apache License, Version 2.0 (the
7    *   "License"); you may not use this file except in compliance
8    *   with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing,
13   *   software distributed under the License is distributed on an
14   *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *   KIND, either express or implied.  See the License for the
16   *   specific language governing permissions and limitations
17   *   under the License.
18   *
19   */
20  package org.apache.directory.server.operations.compare;
21  
22  
23  import javax.naming.NamingEnumeration;
24  import javax.naming.ReferralException;
25  import javax.naming.directory.SearchControls;
26  import javax.naming.directory.SearchResult;
27  import javax.naming.ldap.LdapContext;
28  
29  import netscape.ldap.LDAPAttribute;
30  import netscape.ldap.LDAPConnection;
31  import netscape.ldap.LDAPConstraints;
32  import netscape.ldap.LDAPControl;
33  import netscape.ldap.LDAPException;
34  import netscape.ldap.LDAPResponse;
35  import netscape.ldap.LDAPResponseListener;
36  
37  import org.apache.directory.server.core.integ.Level;
38  import org.apache.directory.server.core.integ.annotations.ApplyLdifs;
39  import org.apache.directory.server.core.integ.annotations.CleanupLevel;
40  import org.apache.directory.server.integ.SiRunner;
41  import org.apache.directory.server.ldap.LdapService;
42  import org.apache.directory.shared.ldap.message.ResultCodeEnum;
43  import org.junit.Test;
44  import org.junit.runner.RunWith;
45  import org.slf4j.Logger;
46  import org.slf4j.LoggerFactory;
47  
48  import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredConnection;
49  import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContextThrowOnRefferal;
50  import static org.junit.Assert.assertEquals;
51  import static org.junit.Assert.assertFalse;
52  import static org.junit.Assert.assertTrue;
53  import static org.junit.Assert.fail;
54  
55  
56  /**
57   * Tests the server to make sure standard compare operations work properly.
58   *
59   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
60   * @version $Rev$, $Date$
61   */
62  @RunWith ( SiRunner.class ) 
63  @CleanupLevel ( Level.SUITE )
64  @ApplyLdifs( {
65      // Entry # 1
66      "dn: uid=akarasulu,ou=users,ou=system\n" +
67      "objectClass: uidObject\n" +
68      "objectClass: person\n" +
69      "objectClass: top\n" +
70      "uid: akarasulu\n" +
71      "cn: Alex Karasulu\n" +
72      "sn: karasulu\n\n" + 
73      // Entry # 2
74      "dn: ou=Computers,uid=akarasulu,ou=users,ou=system\n" +
75      "objectClass: organizationalUnit\n" +
76      "objectClass: top\n" +
77      "ou: computers\n" +
78      "description: Computers for Alex\n" +
79      "seeAlso: ou=Machines,uid=akarasulu,ou=users,ou=system\n\n" + 
80      // Entry # 3
81      "dn: uid=akarasuluref,ou=users,ou=system\n" +
82      "objectClass: uidObject\n" +
83      "objectClass: referral\n" +
84      "objectClass: top\n" +
85      "uid: akarasuluref\n" +
86      "ref: ldap://localhost:10389/uid=akarasulu,ou=users,ou=system\n" + 
87      "ref: ldap://foo:10389/uid=akarasulu,ou=users,ou=system\n" +
88      "ref: ldap://bar:10389/uid=akarasulu,ou=users,ou=system\n\n"
89      }
90  )
91  public class CompareIT
92  {
93      private static final Logger LOG = LoggerFactory.getLogger( CompareIT.class );
94      
95      public static LdapService ldapService;
96      
97  
98      /**
99       * Tests normal compare operation on normal non-referral entries without 
100      * the ManageDsaIT control.
101      */
102     @Test
103     public void testNormalCompare() throws Exception
104     {
105         LDAPConnection conn = getWiredConnection( ldapService );
106         
107         // comparison success
108         LDAPAttribute attribute = new LDAPAttribute( "sn", "karasulu" );
109         assertTrue( conn.compare( "uid=akarasulu,ou=users,ou=system", attribute ) );
110 
111         // comparison failure
112         attribute = new LDAPAttribute( "sn", "lecharny" );
113         assertFalse( conn.compare( "uid=akarasulu,ou=users,ou=system", attribute ) );
114         
115         conn.disconnect();
116     }
117     
118     
119     /**
120      * Tests normal compare operation on normal non-referral entries without 
121      * the ManageDsaIT control using an attribute that does not exist in the
122      * entry.
123      */
124     @Test
125     public void testNormalCompareMissingAttribute() throws Exception
126     {
127         LDAPConnection conn = getWiredConnection( ldapService );
128         
129         // comparison success
130         LDAPAttribute attribute = new LDAPAttribute( "sn", "karasulu" );
131         assertTrue( conn.compare( "uid=akarasulu,ou=users,ou=system", attribute ) );
132 
133         // non-existing attribute
134         attribute = new LDAPAttribute( "mail", "akarasulu@apache.org" );
135         
136         try
137         {
138             conn.compare( "uid=akarasulu,ou=users,ou=system", attribute );
139             fail( "Should never get here" );
140         }
141         catch ( LDAPException e )
142         {
143             assertEquals( ResultCodeEnum.NO_SUCH_ATTRIBUTE.getValue(), e.getLDAPResultCode() ); 
144         }
145         
146         conn.disconnect();
147     }
148     
149     
150     /**
151      * Tests compare operation on referral entry with the ManageDsaIT control.
152      */
153     @Test
154     public void testOnReferralWithManageDsaITControl() throws Exception
155     {
156         LDAPConnection conn = getWiredConnection( ldapService );
157         LDAPConstraints constraints = new LDAPConstraints();
158         constraints.setClientControls( new LDAPControl( LDAPControl.MANAGEDSAIT, true, new byte[0] ) );
159         constraints.setServerControls( new LDAPControl( LDAPControl.MANAGEDSAIT, true, new byte[0] ) );
160         conn.setConstraints( constraints );
161         
162         // comparison success
163         LDAPAttribute attribute = new LDAPAttribute( "uid", "akarasuluref" );
164         assertTrue( conn.compare( "uid=akarasuluref,ou=users,ou=system", attribute, constraints ) );
165 
166         // comparison failure
167         attribute = new LDAPAttribute( "uid", "elecharny" );
168         assertFalse( conn.compare( "uid=akarasuluref,ou=users,ou=system", attribute, constraints ) );
169         
170         conn.disconnect();
171     }
172     
173     
174     /**
175      * Tests compare operation on normal and referral entries without the 
176      * ManageDsaIT control. Referrals are sent back to the client with a
177      * non-success result code.
178      */
179     @Test
180     public void testOnReferral() throws Exception
181     {
182         LDAPConnection conn = getWiredConnection( ldapService );
183         LDAPConstraints constraints = new LDAPConstraints();
184         constraints.setReferrals( false );
185         conn.setConstraints( constraints );
186         
187         // comparison success
188         LDAPAttribute attribute = new LDAPAttribute( "uid", "akarasulu" );
189         assertTrue( conn.compare( "uid=akarasulu,ou=users,ou=system", attribute, constraints ) );
190 
191         // referrals failure
192         attribute = new LDAPAttribute( "uid", "akarasulu" );
193         LDAPResponseListener listener = null;
194         LDAPResponse response = null;
195 
196         listener = conn.compare( "uid=akarasuluref,ou=users,ou=system", attribute, null, constraints );
197         response = listener.getResponse();
198         assertEquals( ResultCodeEnum.REFERRAL.getValue(), response.getResultCode() );
199 
200         assertEquals( "ldap://localhost:10389/uid=akarasulu,ou=users,ou=system", response.getReferrals()[0] );
201         assertEquals( "ldap://foo:10389/uid=akarasulu,ou=users,ou=system", response.getReferrals()[1] );
202         assertEquals( "ldap://bar:10389/uid=akarasulu,ou=users,ou=system", response.getReferrals()[2] );
203 
204         conn.disconnect();
205     }
206     
207     
208     /**
209      * Tests compare operation on normal and referral entries without the 
210      * ManageDsaIT control using JNDI instead of the Netscape API. Referrals 
211      * are sent back to the client with a non-success result code.
212      */
213     @Test
214     public void testThrowOnReferralWithJndi() throws Exception
215     {
216         LdapContext ctx = getWiredContextThrowOnRefferal( ldapService );
217         SearchControls controls = new SearchControls();
218         controls.setReturningAttributes( new String[0] );
219         controls.setSearchScope( SearchControls.OBJECT_SCOPE );
220         
221         // comparison success
222         NamingEnumeration<SearchResult> answer = ctx.search( "uid=akarasulu,ou=users,ou=system", 
223             "(uid=akarasulu)", controls );
224         assertTrue( answer.hasMore() );
225         SearchResult result = answer.next();
226         assertEquals( "", result.getName() );
227         assertEquals( 0, result.getAttributes().size() );
228         assertFalse( answer.hasMore() );
229         answer.close();
230 
231         // referrals failure
232         try
233         {
234             answer = ctx.search( "uid=akarasuluref,ou=users,ou=system", 
235                 "(uid=akarasuluref)", controls );
236             fail( "Should never get here" );
237         }
238         catch ( ReferralException e )
239         {
240             // seems JNDI only returns the first referral URL and not all so we test for it
241             assertEquals( "ldap://localhost:10389/uid=akarasulu,ou=users,ou=system", e.getReferralInfo() );
242         }
243 
244         ctx.close();
245     }
246     
247     
248     /**
249      * Check that operation are not executed if we are now allowed to bind
250      * anonymous
251      * @throws LDAPException
252      */
253     @Test
254     public void testCompareWithoutAuthentication() throws LDAPException
255     {
256         ldapService.getDirectoryService().setAllowAnonymousAccess( false );
257         LDAPConnection conn = new LDAPConnection();
258         conn.connect( "localhost", ldapService.getIpPort() );
259         LDAPAttribute attr = new LDAPAttribute( "uid", "admin" );
260         
261         try
262         {
263             conn.compare( "uid=admin,ou=system", attr );
264             fail( "Compare success without authentication" );
265         }
266         catch ( LDAPException e )
267         {
268             assertEquals( "no permission exception", 50, e.getLDAPResultCode() );
269         }
270     }
271     
272     
273     /**
274      * Tests referral handling when an ancestor is a referral.
275      */
276     @Test 
277     public void testAncestorReferral() throws Exception
278     {
279         LOG.debug( "" );
280 
281         LDAPConnection conn = getWiredConnection( ldapService );
282         LDAPConstraints constraints = new LDAPConstraints();
283         conn.setConstraints( constraints );
284 
285         // referrals failure
286         LDAPAttribute attribute = new LDAPAttribute( "ou", "Computers" );
287         LDAPResponseListener listener = null;
288         LDAPResponse response = null;
289 
290         listener = conn.compare( "ou=Computers,uid=akarasuluref,ou=users,ou=system", attribute, null, constraints );
291         response = listener.getResponse();
292         assertEquals( ResultCodeEnum.REFERRAL.getValue(), response.getResultCode() );
293 
294         assertEquals( "ldap://localhost:10389/ou=Computers,uid=akarasulu,ou=users,ou=system", response.getReferrals()[0] );
295         assertEquals( "ldap://foo:10389/ou=Computers,uid=akarasulu,ou=users,ou=system", response.getReferrals()[1] );
296         assertEquals( "ldap://bar:10389/ou=Computers,uid=akarasulu,ou=users,ou=system", response.getReferrals()[2] );
297 
298         conn.disconnect();
299     }
300 }