You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LdapAuthenticationTest.java 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. /*
  2. * Copyright 2012 John Crygier
  3. * Copyright 2012 gitblit.com
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package com.gitblit.tests;
  18. import static org.junit.Assume.*;
  19. import java.io.File;
  20. import java.util.Arrays;
  21. import java.util.Collection;
  22. import java.util.EnumSet;
  23. import java.util.HashMap;
  24. import java.util.Map;
  25. import org.apache.commons.io.FileUtils;
  26. import org.junit.AfterClass;
  27. import org.junit.Before;
  28. import org.junit.BeforeClass;
  29. import org.junit.Rule;
  30. import org.junit.Test;
  31. import org.junit.rules.TemporaryFolder;
  32. import org.junit.runner.RunWith;
  33. import org.junit.runners.Parameterized;
  34. import org.junit.runners.Parameterized.Parameter;
  35. import org.junit.runners.Parameterized.Parameters;
  36. import com.gitblit.Constants.AccountType;
  37. import com.gitblit.IStoredSettings;
  38. import com.gitblit.Keys;
  39. import com.gitblit.auth.LdapAuthProvider;
  40. import com.gitblit.manager.AuthenticationManager;
  41. import com.gitblit.manager.IUserManager;
  42. import com.gitblit.manager.RuntimeManager;
  43. import com.gitblit.manager.UserManager;
  44. import com.gitblit.models.TeamModel;
  45. import com.gitblit.models.UserModel;
  46. import com.gitblit.tests.mock.MemorySettings;
  47. import com.gitblit.utils.XssFilter;
  48. import com.gitblit.utils.XssFilter.AllowXssFilter;
  49. import com.unboundid.ldap.listener.InMemoryDirectoryServer;
  50. import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
  51. import com.unboundid.ldap.listener.InMemoryDirectoryServerSnapshot;
  52. import com.unboundid.ldap.listener.InMemoryListenerConfig;
  53. import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedRequest;
  54. import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedResult;
  55. import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchEntry;
  56. import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchRequest;
  57. import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
  58. import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSimpleBindResult;
  59. import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
  60. import com.unboundid.ldap.sdk.BindRequest;
  61. import com.unboundid.ldap.sdk.BindResult;
  62. import com.unboundid.ldap.sdk.LDAPException;
  63. import com.unboundid.ldap.sdk.LDAPResult;
  64. import com.unboundid.ldap.sdk.OperationType;
  65. import com.unboundid.ldap.sdk.ResultCode;
  66. import com.unboundid.ldap.sdk.SearchResult;
  67. import com.unboundid.ldap.sdk.SearchScope;
  68. import com.unboundid.ldap.sdk.SimpleBindRequest;
  69. import com.unboundid.ldif.LDIFReader;
  70. /**
  71. * An Integration test for LDAP that tests going against an in-memory UnboundID
  72. * LDAP server.
  73. *
  74. * @author jcrygier
  75. *
  76. */
  77. @RunWith(Parameterized.class)
  78. public class LdapAuthenticationTest extends GitblitUnitTest {
  79. private static final String RESOURCE_DIR = "src/test/resources/ldap/";
  80. private static final String DIRECTORY_MANAGER = "cn=Directory Manager";
  81. private static final String USER_MANAGER = "cn=UserManager";
  82. private static final String ACCOUNT_BASE = "OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain";
  83. private static final String GROUP_BASE = "OU=Groups,OU=UserControl,OU=MyOrganization,DC=MyDomain";
  84. /**
  85. * Enumeration of different test modes, representing different use scenarios.
  86. * With ANONYMOUS anonymous binds are used to search LDAP.
  87. * DS_MANAGER will use a DIRECTORY_MANAGER to search LDAP. Normal users are prohibited to search the DS.
  88. * With USR_MANAGER, a USER_MANAGER account is used to search in LDAP. This account can only search users
  89. * but not groups. Normal users can search groups, though.
  90. *
  91. */
  92. enum AuthMode {
  93. ANONYMOUS(1389),
  94. DS_MANAGER(2389),
  95. USR_MANAGER(3389);
  96. private int ldapPort;
  97. private InMemoryDirectoryServer ds;
  98. private InMemoryDirectoryServerSnapshot dsSnapshot;
  99. AuthMode(int port) {
  100. this.ldapPort = port;
  101. }
  102. int ldapPort() {
  103. return this.ldapPort;
  104. }
  105. void setDS(InMemoryDirectoryServer ds) {
  106. if (this.ds == null) {
  107. this.ds = ds;
  108. this.dsSnapshot = ds.createSnapshot();
  109. };
  110. }
  111. InMemoryDirectoryServer getDS() {
  112. return ds;
  113. }
  114. void restoreSnapshot() {
  115. ds.restoreSnapshot(dsSnapshot);
  116. }
  117. };
  118. @Parameter
  119. public AuthMode authMode;
  120. @Rule
  121. public TemporaryFolder folder = new TemporaryFolder();
  122. private File usersConf;
  123. private LdapAuthProvider ldap;
  124. private IUserManager userManager;
  125. private AuthenticationManager auth;
  126. private MemorySettings settings;
  127. /**
  128. * Run the tests with each authentication scenario once.
  129. */
  130. @Parameters(name = "{0}")
  131. public static Collection<Object[]> data() {
  132. return Arrays.asList(new Object[][] { {AuthMode.ANONYMOUS}, {AuthMode.DS_MANAGER}, {AuthMode.USR_MANAGER} });
  133. }
  134. /**
  135. * Create three different in memory DS.
  136. *
  137. * Each DS has a different configuration:
  138. * The first allows anonymous binds.
  139. * The second requires authentication for all operations. It will only allow the DIRECTORY_MANAGER account
  140. * to search for users and groups.
  141. * The third one is like the second, but it allows users to search for users and groups, and restricts the
  142. * USER_MANAGER from searching for groups.
  143. */
  144. @BeforeClass
  145. public static void init() throws Exception {
  146. InMemoryDirectoryServer ds;
  147. InMemoryDirectoryServerConfig config = createInMemoryLdapServerConfig(AuthMode.ANONYMOUS);
  148. config.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig("default", AuthMode.ANONYMOUS.ldapPort()));
  149. ds = createInMemoryLdapServer(config);
  150. AuthMode.ANONYMOUS.setDS(ds);
  151. config = createInMemoryLdapServerConfig(AuthMode.DS_MANAGER);
  152. config.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig("default", AuthMode.DS_MANAGER.ldapPort()));
  153. config.setAuthenticationRequiredOperationTypes(EnumSet.allOf(OperationType.class));
  154. ds = createInMemoryLdapServer(config);
  155. AuthMode.DS_MANAGER.setDS(ds);
  156. config = createInMemoryLdapServerConfig(AuthMode.USR_MANAGER);
  157. config.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig("default", AuthMode.USR_MANAGER.ldapPort()));
  158. config.setAuthenticationRequiredOperationTypes(EnumSet.allOf(OperationType.class));
  159. ds = createInMemoryLdapServer(config);
  160. AuthMode.USR_MANAGER.setDS(ds);
  161. }
  162. @AfterClass
  163. public static void destroy() throws Exception {
  164. for (AuthMode am : AuthMode.values()) {
  165. am.getDS().shutDown(true);
  166. }
  167. }
  168. public static InMemoryDirectoryServer createInMemoryLdapServer(InMemoryDirectoryServerConfig config) throws Exception {
  169. InMemoryDirectoryServer imds = new InMemoryDirectoryServer(config);
  170. imds.importFromLDIF(true, RESOURCE_DIR + "sampledata.ldif");
  171. imds.startListening();
  172. return imds;
  173. }
  174. public static InMemoryDirectoryServerConfig createInMemoryLdapServerConfig(AuthMode authMode) throws Exception {
  175. InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=MyDomain");
  176. config.addAdditionalBindCredentials(DIRECTORY_MANAGER, "password");
  177. config.addAdditionalBindCredentials(USER_MANAGER, "passwd");
  178. config.setSchema(null);
  179. config.addInMemoryOperationInterceptor(new AccessInterceptor(authMode));
  180. return config;
  181. }
  182. @Before
  183. public void setup() throws Exception {
  184. authMode.restoreSnapshot();
  185. usersConf = folder.newFile("users.conf");
  186. FileUtils.copyFile(new File(RESOURCE_DIR + "users.conf"), usersConf);
  187. settings = getSettings();
  188. ldap = newLdapAuthentication(settings);
  189. auth = newAuthenticationManager(settings);
  190. }
  191. private LdapAuthProvider newLdapAuthentication(IStoredSettings settings) {
  192. XssFilter xssFilter = new AllowXssFilter();
  193. RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start();
  194. userManager = new UserManager(runtime, null).start();
  195. LdapAuthProvider ldap = new LdapAuthProvider();
  196. ldap.setup(runtime, userManager);
  197. return ldap;
  198. }
  199. private AuthenticationManager newAuthenticationManager(IStoredSettings settings) {
  200. XssFilter xssFilter = new AllowXssFilter();
  201. RuntimeManager runtime = new RuntimeManager(settings, xssFilter, GitBlitSuite.BASEFOLDER).start();
  202. AuthenticationManager auth = new AuthenticationManager(runtime, userManager);
  203. auth.addAuthenticationProvider(newLdapAuthentication(settings));
  204. return auth;
  205. }
  206. private MemorySettings getSettings() {
  207. Map<String, Object> backingMap = new HashMap<String, Object>();
  208. backingMap.put(Keys.realm.userService, usersConf.getAbsolutePath());
  209. switch(authMode) {
  210. case ANONYMOUS:
  211. backingMap.put(Keys.realm.ldap.server, "ldap://localhost:" + authMode.ldapPort());
  212. backingMap.put(Keys.realm.ldap.username, "");
  213. backingMap.put(Keys.realm.ldap.password, "");
  214. break;
  215. case DS_MANAGER:
  216. backingMap.put(Keys.realm.ldap.server, "ldap://localhost:" + authMode.ldapPort());
  217. backingMap.put(Keys.realm.ldap.username, DIRECTORY_MANAGER);
  218. backingMap.put(Keys.realm.ldap.password, "password");
  219. break;
  220. case USR_MANAGER:
  221. backingMap.put(Keys.realm.ldap.server, "ldap://localhost:" + authMode.ldapPort());
  222. backingMap.put(Keys.realm.ldap.username, USER_MANAGER);
  223. backingMap.put(Keys.realm.ldap.password, "passwd");
  224. break;
  225. default:
  226. throw new RuntimeException("Unimplemented AuthMode case!");
  227. }
  228. backingMap.put(Keys.realm.ldap.maintainTeams, "true");
  229. backingMap.put(Keys.realm.ldap.accountBase, ACCOUNT_BASE);
  230. backingMap.put(Keys.realm.ldap.accountPattern, "(&(objectClass=person)(sAMAccountName=${username}))");
  231. backingMap.put(Keys.realm.ldap.groupBase, GROUP_BASE);
  232. backingMap.put(Keys.realm.ldap.groupMemberPattern, "(&(objectClass=group)(member=${dn}))");
  233. backingMap.put(Keys.realm.ldap.admins, "UserThree @Git_Admins \"@Git Admins\"");
  234. backingMap.put(Keys.realm.ldap.displayName, "displayName");
  235. backingMap.put(Keys.realm.ldap.email, "email");
  236. backingMap.put(Keys.realm.ldap.uid, "sAMAccountName");
  237. MemorySettings ms = new MemorySettings(backingMap);
  238. return ms;
  239. }
  240. @Test
  241. public void testAuthenticate() {
  242. UserModel userOneModel = ldap.authenticate("UserOne", "userOnePassword".toCharArray());
  243. assertNotNull(userOneModel);
  244. assertNotNull(userOneModel.getTeam("git_admins"));
  245. assertNotNull(userOneModel.getTeam("git_users"));
  246. assertTrue(userOneModel.canAdmin);
  247. UserModel userOneModelFailedAuth = ldap.authenticate("UserOne", "userTwoPassword".toCharArray());
  248. assertNull(userOneModelFailedAuth);
  249. UserModel userTwoModel = ldap.authenticate("UserTwo", "userTwoPassword".toCharArray());
  250. assertNotNull(userTwoModel);
  251. assertNotNull(userTwoModel.getTeam("git_users"));
  252. assertNull(userTwoModel.getTeam("git_admins"));
  253. assertNotNull(userTwoModel.getTeam("git admins"));
  254. assertTrue(userTwoModel.canAdmin);
  255. UserModel userThreeModel = ldap.authenticate("UserThree", "userThreePassword".toCharArray());
  256. assertNotNull(userThreeModel);
  257. assertNotNull(userThreeModel.getTeam("git_users"));
  258. assertNull(userThreeModel.getTeam("git_admins"));
  259. assertTrue(userThreeModel.canAdmin);
  260. UserModel userFourModel = ldap.authenticate("UserFour", "userFourPassword".toCharArray());
  261. assertNotNull(userFourModel);
  262. assertNotNull(userFourModel.getTeam("git_users"));
  263. assertNull(userFourModel.getTeam("git_admins"));
  264. assertNull(userFourModel.getTeam("git admins"));
  265. assertFalse(userFourModel.canAdmin);
  266. }
  267. @Test
  268. public void testDisplayName() {
  269. UserModel userOneModel = ldap.authenticate("UserOne", "userOnePassword".toCharArray());
  270. assertNotNull(userOneModel);
  271. assertEquals("User One", userOneModel.displayName);
  272. // Test more complicated scenarios - concat
  273. MemorySettings ms = getSettings();
  274. ms.put("realm.ldap.displayName", "${personalTitle}. ${givenName} ${surname}");
  275. ldap = newLdapAuthentication(ms);
  276. userOneModel = ldap.authenticate("UserOne", "userOnePassword".toCharArray());
  277. assertNotNull(userOneModel);
  278. assertEquals("Mr. User One", userOneModel.displayName);
  279. }
  280. @Test
  281. public void testEmail() {
  282. UserModel userOneModel = ldap.authenticate("UserOne", "userOnePassword".toCharArray());
  283. assertNotNull(userOneModel);
  284. assertEquals("userone@gitblit.com", userOneModel.emailAddress);
  285. // Test more complicated scenarios - concat
  286. MemorySettings ms = getSettings();
  287. ms.put("realm.ldap.email", "${givenName}.${surname}@gitblit.com");
  288. ldap = newLdapAuthentication(ms);
  289. userOneModel = ldap.authenticate("UserOne", "userOnePassword".toCharArray());
  290. assertNotNull(userOneModel);
  291. assertEquals("User.One@gitblit.com", userOneModel.emailAddress);
  292. }
  293. @Test
  294. public void testLdapInjection() {
  295. // Inject so "(&(objectClass=person)(sAMAccountName=${username}))" becomes "(&(objectClass=person)(sAMAccountName=*)(userPassword=userOnePassword))"
  296. // Thus searching by password
  297. UserModel userOneModel = ldap.authenticate("*)(userPassword=userOnePassword", "userOnePassword".toCharArray());
  298. assertNull(userOneModel);
  299. }
  300. @Test
  301. public void checkIfUsersConfContainsAllUsersFromSampleDataLdif() throws Exception {
  302. SearchResult searchResult = getDS().search(ACCOUNT_BASE, SearchScope.SUB, "objectClass=person");
  303. assertEquals("Number of ldap users in gitblit user model", searchResult.getEntryCount(), countLdapUsersInUserManager());
  304. }
  305. @Test
  306. public void addingUserInLdapShouldNotUpdateGitBlitUsersAndGroups() throws Exception {
  307. getDS().addEntries(LDIFReader.readEntries(RESOURCE_DIR + "adduser.ldif"));
  308. ldap.sync();
  309. assertEquals("Number of ldap users in gitblit user model", 5, countLdapUsersInUserManager());
  310. }
  311. @Test
  312. public void addingUserInLdapShouldUpdateGitBlitUsersAndGroups() throws Exception {
  313. settings.put(Keys.realm.ldap.synchronize, "true");
  314. getDS().addEntries(LDIFReader.readEntries(RESOURCE_DIR + "adduser.ldif"));
  315. ldap.sync();
  316. assertEquals("Number of ldap users in gitblit user model", 6, countLdapUsersInUserManager());
  317. }
  318. @Test
  319. public void addingGroupsInLdapShouldNotUpdateGitBlitUsersAndGroups() throws Exception {
  320. getDS().addEntries(LDIFReader.readEntries(RESOURCE_DIR + "addgroup.ldif"));
  321. ldap.sync();
  322. assertEquals("Number of ldap groups in gitblit team model", 0, countLdapTeamsInUserManager());
  323. }
  324. @Test
  325. public void addingGroupsInLdapShouldUpdateGitBlitUsersAndGroups() throws Exception {
  326. // This test only makes sense if the authentication mode allows for synchronization.
  327. assumeTrue(authMode == AuthMode.ANONYMOUS || authMode == AuthMode.DS_MANAGER);
  328. settings.put(Keys.realm.ldap.synchronize, "true");
  329. getDS().addEntries(LDIFReader.readEntries(RESOURCE_DIR + "addgroup.ldif"));
  330. ldap.sync();
  331. assertEquals("Number of ldap groups in gitblit team model", 1, countLdapTeamsInUserManager());
  332. }
  333. @Test
  334. public void testAuthenticationManager() {
  335. UserModel userOneModel = auth.authenticate("UserOne", "userOnePassword".toCharArray(), null);
  336. assertNotNull(userOneModel);
  337. assertNotNull(userOneModel.getTeam("git_admins"));
  338. assertNotNull(userOneModel.getTeam("git_users"));
  339. assertTrue(userOneModel.canAdmin);
  340. UserModel userOneModelFailedAuth = auth.authenticate("UserOne", "userTwoPassword".toCharArray(), null);
  341. assertNull(userOneModelFailedAuth);
  342. UserModel userTwoModel = auth.authenticate("UserTwo", "userTwoPassword".toCharArray(), null);
  343. assertNotNull(userTwoModel);
  344. assertNotNull(userTwoModel.getTeam("git_users"));
  345. assertNull(userTwoModel.getTeam("git_admins"));
  346. assertNotNull(userTwoModel.getTeam("git admins"));
  347. assertTrue(userTwoModel.canAdmin);
  348. UserModel userThreeModel = auth.authenticate("UserThree", "userThreePassword".toCharArray(), null);
  349. assertNotNull(userThreeModel);
  350. assertNotNull(userThreeModel.getTeam("git_users"));
  351. assertNull(userThreeModel.getTeam("git_admins"));
  352. assertTrue(userThreeModel.canAdmin);
  353. UserModel userFourModel = auth.authenticate("UserFour", "userFourPassword".toCharArray(), null);
  354. assertNotNull(userFourModel);
  355. assertNotNull(userFourModel.getTeam("git_users"));
  356. assertNull(userFourModel.getTeam("git_admins"));
  357. assertNull(userFourModel.getTeam("git admins"));
  358. assertFalse(userFourModel.canAdmin);
  359. }
  360. @Test
  361. public void testBindWithUser() {
  362. // This test only makes sense if the user is not prevented from reading users and teams.
  363. assumeTrue(authMode != AuthMode.DS_MANAGER);
  364. settings.put(Keys.realm.ldap.bindpattern, "CN=${username},OU=US," + ACCOUNT_BASE);
  365. settings.put(Keys.realm.ldap.username, "");
  366. settings.put(Keys.realm.ldap.password, "");
  367. UserModel userOneModel = auth.authenticate("UserOne", "userOnePassword".toCharArray(), null);
  368. assertNotNull(userOneModel);
  369. UserModel userOneModelFailedAuth = auth.authenticate("UserOne", "userTwoPassword".toCharArray(), null);
  370. assertNull(userOneModelFailedAuth);
  371. }
  372. private InMemoryDirectoryServer getDS()
  373. {
  374. return authMode.getDS();
  375. }
  376. private int countLdapUsersInUserManager() {
  377. int ldapAccountCount = 0;
  378. for (UserModel userModel : userManager.getAllUsers()) {
  379. if (AccountType.LDAP.equals(userModel.accountType)) {
  380. ldapAccountCount++;
  381. }
  382. }
  383. return ldapAccountCount;
  384. }
  385. private int countLdapTeamsInUserManager() {
  386. int ldapAccountCount = 0;
  387. for (TeamModel teamModel : userManager.getAllTeams()) {
  388. if (AccountType.LDAP.equals(teamModel.accountType)) {
  389. ldapAccountCount++;
  390. }
  391. }
  392. return ldapAccountCount;
  393. }
  394. /**
  395. * Operation interceptor for the in memory DS. This interceptor
  396. * implements access restrictions for certain user/DN combinations.
  397. *
  398. * The USER_MANAGER is only allowed to search for users, but not for groups.
  399. * This is to test the original behaviour where the teams were searched under
  400. * the user binding.
  401. * When running in a DIRECTORY_MANAGER scenario, only the manager account
  402. * is allowed to search for users and groups, while a normal user may not do so.
  403. * This tests the scenario where a normal user cannot read teams and thus the
  404. * manager account needs to be used for all searches.
  405. *
  406. */
  407. private static class AccessInterceptor extends InMemoryOperationInterceptor {
  408. AuthMode authMode;
  409. Map<Long,String> lastSuccessfulBindDN = new HashMap<>();
  410. Map<Long,Boolean> resultProhibited = new HashMap<>();
  411. public AccessInterceptor(AuthMode authMode) {
  412. this.authMode = authMode;
  413. }
  414. @Override
  415. public void processSimpleBindResult(InMemoryInterceptedSimpleBindResult bind) {
  416. BindResult result = bind.getResult();
  417. if (result.getResultCode() == ResultCode.SUCCESS) {
  418. BindRequest bindRequest = bind.getRequest();
  419. lastSuccessfulBindDN.put(bind.getConnectionID(), ((SimpleBindRequest)bindRequest).getBindDN());
  420. resultProhibited.remove(bind.getConnectionID());
  421. }
  422. }
  423. @Override
  424. public void processSearchRequest(InMemoryInterceptedSearchRequest request) throws LDAPException {
  425. String bindDN = getLastBindDN(request);
  426. if (USER_MANAGER.equals(bindDN)) {
  427. if (request.getRequest().getBaseDN().endsWith(GROUP_BASE)) {
  428. throw new LDAPException(ResultCode.NO_SUCH_OBJECT);
  429. }
  430. }
  431. else if(authMode == AuthMode.DS_MANAGER && !DIRECTORY_MANAGER.equals(bindDN)) {
  432. throw new LDAPException(ResultCode.NO_SUCH_OBJECT);
  433. }
  434. }
  435. @Override
  436. public void processSearchEntry(InMemoryInterceptedSearchEntry entry) {
  437. String bindDN = getLastBindDN(entry);
  438. boolean prohibited = false;
  439. if (USER_MANAGER.equals(bindDN)) {
  440. if (entry.getSearchEntry().getDN().endsWith(GROUP_BASE)) {
  441. prohibited = true;
  442. }
  443. }
  444. else if(authMode == AuthMode.DS_MANAGER && !DIRECTORY_MANAGER.equals(bindDN)) {
  445. prohibited = true;
  446. }
  447. if (prohibited) {
  448. // Found entry prohibited for bound user. Setting entry to null.
  449. entry.setSearchEntry(null);
  450. resultProhibited.put(entry.getConnectionID(), Boolean.TRUE);
  451. }
  452. }
  453. @Override
  454. public void processSearchResult(InMemoryInterceptedSearchResult result) {
  455. String bindDN = getLastBindDN(result);
  456. boolean prohibited = false;
  457. Boolean rspb = resultProhibited.get(result.getConnectionID());
  458. if (USER_MANAGER.equals(bindDN)) {
  459. if (rspb != null && rspb) {
  460. prohibited = true;
  461. }
  462. }
  463. else if(authMode == AuthMode.DS_MANAGER && !DIRECTORY_MANAGER.equals(bindDN)) {
  464. if (rspb != null && rspb) {
  465. prohibited = true;
  466. }
  467. }
  468. if (prohibited) {
  469. // Result prohibited for bound user. Returning error
  470. result.setResult(new LDAPResult(result.getMessageID(), ResultCode.INSUFFICIENT_ACCESS_RIGHTS));
  471. resultProhibited.remove(result.getConnectionID());
  472. }
  473. }
  474. private String getLastBindDN(InMemoryInterceptedResult result) {
  475. String bindDN = lastSuccessfulBindDN.get(result.getConnectionID());
  476. if (bindDN == null) {
  477. return "UNKNOWN";
  478. }
  479. return bindDN;
  480. }
  481. private String getLastBindDN(InMemoryInterceptedRequest request) {
  482. String bindDN = lastSuccessfulBindDN.get(request.getConnectionID());
  483. if (bindDN == null) {
  484. return "UNKNOWN";
  485. }
  486. return bindDN;
  487. }
  488. }
  489. }