1111 * Header, with the fields enclosed by brackets [] replaced by your own identifying
1212 * information: "Portions Copyright [year] [name of copyright owner]".
1313 *
14- * Copyright 2024 3A Systems, LLC.
14+ * Copyright 2024-2025 3A Systems, LLC.
1515 */
1616package org .openidentityplatform .opendj ;
1717
2323import org .opends .server .DirectoryServerTestCase ;
2424import org .opends .server .TestCaseUtils ;
2525
26+ import org .opends .server .types .Entry ;
2627import org .testng .annotations .BeforeClass ;
2728import org .testng .annotations .Test ;
2829
@@ -60,6 +61,61 @@ public void startServer() throws Exception {
6061 "objectclass: extensibleobject" ,
6162 "cn: President" ,
6263 "aliasedobjectname: cn=John Doe, o=MyCompany, o=test" ,
64+ "" ,
65+
66+ "dn: ou=employees,o=test" ,
67+ "objectClass: top" ,
68+ "objectClass: organizationalUnit" ,
69+ "ou: employees" ,
70+ "description: All employees" ,
71+ "" ,
72+ "dn: uid=jdoe,ou=employees,o=test" ,
73+ "objectClass: alias" ,
74+ "objectClass: top" ,
75+ "objectClass: extensibleObject" ,
76+ "aliasedObjectName: uid=jdoe,ou=researchers,o=test" ,
77+ "uid: jdoe" ,
78+ "" ,
79+ "dn: ou=researchers,o=test" ,
80+ "objectClass: top" ,
81+ "objectClass: organizationalUnit" ,
82+ "ou: researchers" ,
83+ "description: All reasearchers" ,
84+ "" ,
85+ "dn: uid=jdoe,ou=researchers,o=test" ,
86+ "objectClass: alias" ,
87+ "objectClass: top" ,
88+ "objectClass: extensibleObject" ,
89+ "aliasedObjectName: uid=jdoe,ou=employees,o=test" ,
90+ "uid: jdoe" ,
91+
92+ "" ,
93+ "dn: ou=students,o=test" ,
94+ "objectClass: top" ,
95+ "objectClass: organizationalUnit" ,
96+ "ou: students" ,
97+ "description: All students" ,
98+ "" ,
99+ "dn: uid=janedoe,ou=students,o=test" ,
100+ "objectClass: alias" ,
101+ "objectClass: top" ,
102+ "objectClass: extensibleObject" ,
103+ "aliasedObjectName: uid=janedoe,ou=researchers,o=test" ,
104+ "uid: janedoe" ,
105+ "" ,
106+ "dn: uid=janedoe,ou=researchers,o=test" ,
107+ "objectClass: alias" ,
108+ "objectClass: top" ,
109+ "objectClass: extensibleObject" ,
110+ "aliasedObjectName: uid=janedoe,ou=employees,o=test" ,
111+ "uid: janedoe" ,
112+ "" ,
113+ "dn: uid=janedoe,ou=employees,o=test" ,
114+ "objectClass: alias" ,
115+ "objectClass: top" ,
116+ "objectClass: extensibleObject" ,
117+ "aliasedObjectName: uid=janedoe,ou=students,o=test" ,
118+ "uid: janedoe" ,
63119 ""
64120 );
65121
@@ -70,7 +126,11 @@ public void startServer() throws Exception {
70126 }
71127
72128 public HashMap <String ,SearchResultEntry > search (SearchScope scope ,DereferenceAliasesPolicy policy ) throws SearchResultReferenceIOException , LdapException {
73- final SearchRequest request =Requests .newSearchRequest ("ou=Area1,o=test" , scope ,"(objectclass=*)" )
129+ return search ("ou=Area1,o=test" , scope , policy );
130+ }
131+
132+ public HashMap <String ,SearchResultEntry > search (String dn , SearchScope scope ,DereferenceAliasesPolicy policy ) throws SearchResultReferenceIOException , LdapException {
133+ final SearchRequest request =Requests .newSearchRequest (dn , scope ,"(objectclass=*)" )
74134 .setDereferenceAliasesPolicy (policy );
75135 System .out .println ("---------------------------------------------------------------------------------------" );
76136 System .out .println (request );
@@ -125,7 +185,7 @@ public void test_base_find() throws SearchResultReferenceIOException, LdapExcept
125185 // It returns ou=Area1,o=test.
126186 @ Test
127187 public void test_base_search () throws SearchResultReferenceIOException , LdapException {
128- HashMap <String ,SearchResultEntry > res =search (SearchScope .BASE_OBJECT ,DereferenceAliasesPolicy .IN_SEARCHING );
188+ HashMap <String ,SearchResultEntry > res =search (SearchScope .BASE_OBJECT , DereferenceAliasesPolicy .IN_SEARCHING );
129189
130190 assertThat (res .containsKey ("ou=Area1,o=test" )).isTrue ();
131191 assertThat (res .containsKey ("o=MyCompany,o=test" )).isFalse ();
@@ -308,4 +368,39 @@ public void test_sub_always() throws SearchResultReferenceIOException, LdapExcep
308368 assertThat (res .containsKey ("cn=John Doe,o=MyCompany,o=test" )).isTrue ();
309369 }
310370
371+ // Dereferencing recursion avoidance test.
372+ @ Test
373+ public void test_alias_recursive () throws LdapException , SearchResultReferenceIOException {
374+ HashMap <String , SearchResultEntry > res = search ("uid=jdoe,ou=employees,o=test" , SearchScope .WHOLE_SUBTREE , DereferenceAliasesPolicy .ALWAYS );
375+
376+ assertThat (res .containsKey ("uid=jdoe,ou=employees,o=test" )).isTrue ();
377+ assertThat (res .containsKey ("uid=jdoe,ou=researchers,o=test" )).isFalse ();
378+ }
379+
380+ @ Test
381+ public void test_alias_recursive_loop () throws LdapException , SearchResultReferenceIOException {
382+ HashMap <String , SearchResultEntry > res = search ("uid=janedoe,ou=students,o=test" , SearchScope .WHOLE_SUBTREE , DereferenceAliasesPolicy .ALWAYS );
383+
384+ assertThat (res .containsKey ("uid=janedoe,ou=students,o=test" )).isTrue ();
385+ assertThat (res .containsKey ("uid=janedoe,ou=researches,o=test" )).isFalse ();
386+ assertThat (res .containsKey ("uid=janedoe,ou=employees,o=test" )).isFalse ();
387+ }
388+
389+ @ Test (expectedExceptions = LdapException .class )
390+ public void test_stackoverflow () throws Exception {
391+
392+ String entryTemplate = "dn: uid={uid},ou=employees,o=test\n " +
393+ "objectClass: alias\n " +
394+ "objectClass: top\n " +
395+ "objectClass: extensibleObject\n " +
396+ "aliasedObjectName: uid={alias},ou=employees,o=test \n " +
397+ "uid: {uid}\n " ;
398+ final String firstDn = "uid=jdoe0,ou=employees,o=test" ;
399+ for (int i = 0 ; i < 10000 ; i ++) {
400+ String entryStr = entryTemplate .replace ("{uid}" , "jdoe" + i ).replace ("{alias}" , "jdoe" + (i + 1 ));
401+ Entry entry = TestCaseUtils .makeEntry (entryStr );
402+ TestCaseUtils .addEntry (entry );
403+ }
404+ search (firstDn , SearchScope .WHOLE_SUBTREE , DereferenceAliasesPolicy .ALWAYS );
405+ }
311406}
0 commit comments