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.add;
21  
22  
23  import javax.naming.NamingEnumeration;
24  import javax.naming.NamingException;
25  import javax.naming.directory.Attribute;
26  import javax.naming.directory.Attributes;
27  import javax.naming.directory.BasicAttribute;
28  import javax.naming.directory.BasicAttributes;
29  import javax.naming.directory.DirContext;
30  import javax.naming.directory.SearchControls;
31  import javax.naming.directory.SearchResult;
32  
33  import org.apache.directory.server.core.integ.Level;
34  import org.apache.directory.server.core.integ.annotations.CleanupLevel;
35  import org.apache.directory.server.integ.SiRunner;
36  import org.apache.directory.server.integ.ServerIntegrationUtils;
37  import org.apache.directory.server.ldap.LdapService;
38  
39  import org.junit.Test;
40  import org.junit.runner.RunWith;
41  import static org.junit.Assert.assertTrue;
42  import static org.junit.Assert.assertEquals;
43  import static org.junit.Assert.assertNotNull;
44  
45  
46  /**
47   * Test case to demonstrate DIRSERVER-631 ("Creation of entry with special (and
48   * escaped) character in RDN leads to wrong attribute value").
49   * 
50   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
51   */
52  @RunWith( SiRunner.class )
53  @CleanupLevel( Level.SUITE )
54  public class AddingEntriesWithSpecialCharactersInRDNIT
55  {
56      public static LdapService ldapService;
57  
58  
59      protected Attributes getPersonAttributes( String sn, String cn )
60      {
61          Attributes attrs = new BasicAttributes( true );
62          Attribute ocls = new BasicAttribute( "objectClass" );
63          ocls.add( "top" );
64          ocls.add( "person" );
65          attrs.put( ocls );
66          attrs.put( "cn", cn );
67          attrs.put( "sn", sn );
68  
69          return attrs;
70      }
71  
72  
73      protected Attributes getOrgUnitAttributes( String ou )
74      {
75          Attributes attrs = new BasicAttributes( true );
76          Attribute ocls = new BasicAttribute( "objectClass" );
77          ocls.add( "top" );
78          ocls.add( "organizationalUnit" );
79          attrs.put( ocls );
80          attrs.put( "ou", ou );
81  
82          return attrs;
83      }
84  
85  
86      /**
87       * adding an entry with hash sign (#) in RDN.
88       * 
89       * @throws NamingException 
90       */
91      @Test
92      public void testAddingWithHashRdn() throws Exception
93      {
94          DirContext ctx = ( DirContext ) ServerIntegrationUtils.getWiredContext( ldapService ).lookup( "ou=system" );
95  
96          Attributes attrs = getPersonAttributes( "Bush", "Kate#Bush" );
97          String rdn = "cn=Kate\\#Bush";
98          ctx.createSubcontext( rdn, attrs );
99  
100         SearchControls sctls = new SearchControls();
101         sctls.setSearchScope( SearchControls.SUBTREE_SCOPE );
102 
103         NamingEnumeration<SearchResult> enm = ctx.search( "", "(cn=Kate\\#Bush)", sctls );
104         assertEquals( "entry found", true, enm.hasMore() );
105 
106         while ( enm.hasMore() )
107         {
108             SearchResult sr = enm.next();
109             attrs = sr.getAttributes();
110             Attribute cn = sr.getAttributes().get( "cn" );
111             assertNotNull( cn );
112             assertTrue( cn.contains( "Kate#Bush" ) );
113         }
114 
115         ctx.destroySubcontext( rdn );
116     }
117 
118 
119     /**
120      * adding an entry with comma sign (,) in RDN.
121      *    
122      * @throws NamingException 
123      */
124     @Test
125     public void testAddingWithCommaInRdn() throws Exception
126     {
127         DirContext ctx = ( DirContext ) ServerIntegrationUtils.getWiredContext( ldapService ).lookup( "ou=system" );
128 
129         Attributes attrs = getPersonAttributes( "Bush", "Bush, Kate" );
130         String rdn = "cn=Bush\\, Kate";
131         ctx.createSubcontext( rdn, attrs );
132 
133         SearchControls sctls = new SearchControls();
134         sctls.setSearchScope( SearchControls.SUBTREE_SCOPE );
135 
136         NamingEnumeration<SearchResult> enm = ctx.search( "", "(cn=Bush, Kate)", sctls );
137         assertEquals( "entry found", true, enm.hasMore() );
138 
139         while ( enm.hasMore() )
140         {
141             SearchResult sr = enm.next();
142             attrs = sr.getAttributes();
143             Attribute cn = sr.getAttributes().get( "cn" );
144             assertNotNull( cn );
145             assertTrue( cn.contains( "Bush, Kate" ) );
146             assertEquals( "cn=Bush\\, Kate", sr.getName() );
147         }
148 
149         ctx.destroySubcontext( rdn );
150     }
151 
152 
153     /**
154      * adding an entry with quotes (") in RDN.
155      */
156     /*   public void testAddingWithQuotesInRdn() throws NamingException {
157 
158            Attributes attrs = getPersonAttributes("Messer",
159                    "Mackie \\\\\\\"The Knife\" Messer");
160            String rdn = "cn=Mackie \\\"The Knife\" Messer";
161            ctx.createSubcontext(rdn, attrs);
162 
163            SearchControls sctls = new SearchControls();
164            sctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
165 
166            NamingEnumeration enm = ctx.search("",
167                    "(cn=Mackie \"The Knife\" Messer)", sctls);
168            assertEquals("entry found", true, enm.hasMore());
169            while (enm.hasMore()) {
170                SearchResult sr = (SearchResult) enm.next();
171                attrs = sr.getObject();
172                Attribute cn = sr.getObject().get("cn");
173                assertNotNull(cn);
174                assertTrue(cn.contains("Mackie \"The Knife\" Messer"));
175            }
176 
177            ctx.destroySubcontext(rdn);
178        }
179     */
180     /**
181      * adding an entry with backslash (\) in RDN.
182      */
183     /*   public void testAddingWithBackslashInRdn() throws NamingException {
184 
185            Attributes attrs = getOrgUnitAttributes("AC\\DC");
186            String rdn = "ou=AC\\\\DC";
187            ctx.createSubcontext(rdn, attrs);
188 
189            SearchControls sctls = new SearchControls();
190            sctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
191 
192            NamingEnumeration enm = ctx.search("", "(ou=AC\\DC)", sctls);
193            assertEquals("entry found", true, enm.hasMore());
194            while (enm.hasMore()) {
195                SearchResult sr = (SearchResult) enm.next();
196                attrs = sr.getObject();
197                Attribute ou = sr.getObject().get("ou");
198                assertNotNull(ou);
199                assertTrue(ou.contains("AC\\DC"));
200            }
201 
202            ctx.destroySubcontext(rdn);
203        }
204     */
205 
206     /**
207      * adding an entry with greater sign (>) in RDN.
208      * 
209      * @throws NamingException 
210      */
211     @Test
212     public void testAddingWithGreaterSignInRdn() throws Exception
213     {
214         DirContext ctx = ( DirContext ) ServerIntegrationUtils.getWiredContext( ldapService ).lookup( "ou=system" );
215 
216         Attributes attrs = getOrgUnitAttributes( "East -> West" );
217         String rdn = "ou=East -\\> West";
218         ctx.createSubcontext( rdn, attrs );
219 
220         SearchControls sctls = new SearchControls();
221         sctls.setSearchScope( SearchControls.SUBTREE_SCOPE );
222 
223         NamingEnumeration<SearchResult> enm = ctx.search( "", "(ou=East -> West)", sctls );
224         assertEquals( "entry found", true, enm.hasMore() );
225 
226         while ( enm.hasMore() )
227         {
228             SearchResult sr = enm.next();
229             attrs = sr.getAttributes();
230             Attribute ou = sr.getAttributes().get( "ou" );
231             assertNotNull( ou );
232             assertTrue( ou.contains( "East -> West" ) );
233         }
234 
235         ctx.destroySubcontext( rdn );
236     }
237 
238 
239     /**
240      * adding an entry with less sign (<) in RDN.
241      * 
242      * @throws NamingException 
243      */
244     @Test
245     public void testAddingWithLessSignInRdn() throws Exception
246     {
247         DirContext ctx = ( DirContext ) ServerIntegrationUtils.getWiredContext( ldapService ).lookup( "ou=system" );
248 
249         Attributes attrs = getOrgUnitAttributes( "Scissors 8<" );
250         String rdn = "ou=Scissors 8\\<";
251         ctx.createSubcontext( rdn, attrs );
252 
253         SearchControls sctls = new SearchControls();
254         sctls.setSearchScope( SearchControls.SUBTREE_SCOPE );
255 
256         NamingEnumeration<SearchResult> enm = ctx.search( "", "(ou=Scissors 8<)", sctls );
257         assertEquals( "entry found", true, enm.hasMore() );
258 
259         while ( enm.hasMore() )
260         {
261             SearchResult sr = enm.next();
262             attrs = sr.getAttributes();
263             Attribute ou = sr.getAttributes().get( "ou" );
264             assertNotNull( ou );
265             assertTrue( ou.contains( "Scissors 8<" ) );
266         }
267 
268         ctx.destroySubcontext( rdn );
269     }
270 
271 
272     /**
273      * adding an entry with semicolon (;) in RDN.
274      * 
275      * @throws NamingException 
276      */
277     @Test
278     public void testAddingWithSemicolonInRdn() throws Exception
279     {
280         DirContext ctx = ( DirContext ) ServerIntegrationUtils.getWiredContext( ldapService ).lookup( "ou=system" );
281 
282         Attributes attrs = getOrgUnitAttributes( "semicolon group;" );
283         String rdn = "ou=semicolon group\\;";
284         ctx.createSubcontext( rdn, attrs );
285 
286         SearchControls sctls = new SearchControls();
287         sctls.setSearchScope( SearchControls.SUBTREE_SCOPE );
288 
289         NamingEnumeration<SearchResult> enm = ctx.search( "", "(ou=semicolon group;)", sctls );
290         assertEquals( "entry found", true, enm.hasMore() );
291 
292         while ( enm.hasMore() )
293         {
294             SearchResult sr = enm.next();
295             attrs = sr.getAttributes();
296             Attribute ou = sr.getAttributes().get( "ou" );
297             assertNotNull( ou );
298             assertTrue( ou.contains( "semicolon group;" ) );
299         }
300 
301         ctx.destroySubcontext( rdn );
302     }
303 
304 
305     /**
306      * adding an entry with equals sign (=) in RDN.
307      * 
308      * @throws NamingException 
309      */
310     @Test
311     public void testAddingWithEqualsInRdn() throws Exception
312     {
313         DirContext ctx = ( DirContext ) ServerIntegrationUtils.getWiredContext( ldapService ).lookup( "ou=system" );
314 
315         Attributes attrs = getOrgUnitAttributes( "nomen=omen" );
316         String rdn = "ou=nomen\\=omen";
317         ctx.createSubcontext( rdn, attrs );
318 
319         SearchControls sctls = new SearchControls();
320         sctls.setSearchScope( SearchControls.SUBTREE_SCOPE );
321 
322         NamingEnumeration<SearchResult> enm = ctx.search( "", "(ou=nomen=omen)", sctls );
323         assertEquals( "entry found", true, enm.hasMore() );
324 
325         while ( enm.hasMore() )
326         {
327             SearchResult sr = enm.next();
328             attrs = sr.getAttributes();
329             Attribute ou = sr.getAttributes().get( "ou" );
330             assertNotNull( ou );
331             assertTrue( ou.contains( "nomen=omen" ) );
332         }
333 
334         ctx.destroySubcontext( rdn );
335     }
336 }