/// <summary>Returns list of groups for a user.</summary> /// <remarks> /// Returns list of groups for a user. /// The LdapCtx which underlies the DirContext object is not thread-safe, so /// we need to block around this whole method. The caching infrastructure will /// ensure that performance stays in an acceptable range. /// </remarks> /// <param name="user">get groups for this user</param> /// <returns>list of groups for a given user</returns> /// <exception cref="System.IO.IOException"/> public virtual IList <string> GetGroups(string user) { lock (this) { IList <string> emptyResults = new AList <string>(); /* * Normal garbage collection takes care of removing Context instances when they are no longer in use. * Connections used by Context instances being garbage collected will be closed automatically. * So in case connection is closed and gets CommunicationException, retry some times with new new DirContext/connection. */ try { return(DoGetGroups(user)); } catch (CommunicationException) { Log.Warn("Connection is closed, will try to reconnect"); } catch (NamingException e) { Log.Warn("Exception trying to get groups for user " + user + ": " + e.Message); return(emptyResults); } int retryCount = 0; while (retryCount++ < ReconnectRetryCount) { //reset ctx so that new DirContext can be created with new connection this.ctx = null; try { return(DoGetGroups(user)); } catch (CommunicationException) { Log.Warn("Connection being closed, reconnecting failed, retryCount = " + retryCount ); } catch (NamingException e) { Log.Warn("Exception trying to get groups for user " + user + ":" + e.Message); return(emptyResults); } } return(emptyResults); } }
/// <exception cref="Javax.Naming.NamingException"/> internal virtual DirContext GetDirContext() { if (ctx == null) { // Set up the initial environment for LDAP connectivity Hashtable <string, string> env = new Hashtable <string, string>(); env[Context.InitialContextFactory] = typeof(LdapCtxFactory).FullName; env[Context.ProviderUrl] = ldapUrl; env[Context.SecurityAuthentication] = "simple"; // Set up SSL security, if necessary if (useSsl) { env[Context.SecurityProtocol] = "ssl"; Runtime.SetProperty("javax.net.ssl.keyStore", keystore); Runtime.SetProperty("javax.net.ssl.keyStorePassword", keystorePass); } env[Context.SecurityPrincipal] = bindUser; env[Context.SecurityCredentials] = bindPassword; ctx = new InitialDirContext(env); } return(ctx); }
/// <exception cref="Javax.Naming.NamingException"/> internal virtual IList <string> DoGetGroups(string user) { IList <string> groups = new AList <string>(); DirContext ctx = GetDirContext(); // Search for the user. We'll only ever need to look at the first result NamingEnumeration <SearchResult> results = ctx.Search(baseDN, userSearchFilter, new object[] { user }, SearchControls); if (results.MoveNext()) { SearchResult result = results.Current; string userDn = result.GetNameInNamespace(); NamingEnumeration <SearchResult> groupResults = ctx.Search(baseDN, "(&" + groupSearchFilter + "(" + groupMemberAttr + "={0}))", new object[] { userDn }, SearchControls); while (groupResults.MoveNext()) { SearchResult groupResult = groupResults.Current; Attribute groupName = groupResult.GetAttributes().Get(groupNameAttr); groups.AddItem(groupName.Get().ToString()); } } return(groups); }
public virtual void SetupMocks() { mockContext = Org.Mockito.Mockito.Mock <DirContext>(); Org.Mockito.Mockito.DoReturn(mockContext).When(mappingSpy).GetDirContext(); SearchResult mockUserResult = Org.Mockito.Mockito.Mock <SearchResult>(); // We only ever call hasMoreElements once for the user NamingEnum, so // we can just have one return value Org.Mockito.Mockito.When(mockUserNamingEnum.MoveNext()).ThenReturn(true); Org.Mockito.Mockito.When(mockUserNamingEnum.Current).ThenReturn(mockUserResult); Org.Mockito.Mockito.When(mockUserResult.GetNameInNamespace()).ThenReturn("CN=some_user,DC=test,DC=com" ); SearchResult mockGroupResult = Org.Mockito.Mockito.Mock <SearchResult>(); // We're going to have to define the loop here. We want two iterations, // to get both the groups Org.Mockito.Mockito.When(mockGroupNamingEnum.MoveNext()).ThenReturn(true, true, false ); Org.Mockito.Mockito.When(mockGroupNamingEnum.Current).ThenReturn(mockGroupResult); // Define the attribute for the name of the first group Attribute group1Attr = new BasicAttribute("cn"); group1Attr.Add(testGroups[0]); Attributes group1Attrs = new BasicAttributes(); group1Attrs.Put(group1Attr); // Define the attribute for the name of the second group Attribute group2Attr = new BasicAttribute("cn"); group2Attr.Add(testGroups[1]); Attributes group2Attrs = new BasicAttributes(); group2Attrs.Put(group2Attr); // This search result gets reused, so return group1, then group2 Org.Mockito.Mockito.When(mockGroupResult.GetAttributes()).ThenReturn(group1Attrs, group2Attrs); }