public List <LdapEntry> ExecuteSearch(string searchBase, string filter = "") { var results = new List <LdapEntry>(); var lcm = LdapConnectionManager.Instance; var conn = lcm.GetConnection(); var sb = searchBase + config.searchBase; LdapControl[] requestControls = new LdapControl[1]; LdapSortKey[] keys = new LdapSortKey[1]; keys[0] = new LdapSortKey("cn"); //samaccountname // Create the sort control requestControls[0] = new LdapSortControl(keys, true); // Set the controls to be sent as part of search request LdapSearchConstraints cons = conn.SearchConstraints; cons.SetControls(requestControls); conn.Constraints = cons; LdapSearchResults resps = (LdapSearchResults)conn.Search(sb, LdapConnection.ScopeSub, filter, null, false, (LdapSearchConstraints)null); //var resps = SendSearch(searchBase, type, filter); while (resps.HasMore()) { /* Get next returned entry. Note that we should expect a Ldap- * Exception object as well just in case something goes wrong */ LdapEntry nextEntry = null; try { nextEntry = resps.Next(); results.Add(nextEntry); } catch (Exception e) { if (e is LdapReferralException) { continue; } else { logger.Error("Search stopped with exception " + e.ToString()); break; } } /* Print out the returned Entries distinguished name. */ logger.Debug(nextEntry.Dn); } return(results); }
public static void Main(System.String[] args) { /* Check if we have the correct number of command line arguments */ if (args.Length != 4) { System.Console.Error.WriteLine("Usage: mono VLVControl <host name> <login dn>" + " <password> <container>"); System.Console.Error.WriteLine("Example: mono VLVControl Acme.com \"cn=admin,o=Acme\" secret" + " \"ou=Sales,o=Acme\""); System.Environment.Exit(1); } /* Parse the command line arguments */ System.String LdapHost = args[0]; System.String loginDN = args[1]; System.String password = args[2]; System.String searchBase = args[3]; int LdapPort = LdapConnection.DEFAULT_PORT; int LdapVersion = LdapConnection.Ldap_V3; LdapConnection conn = new LdapConnection(); try { // connect to the server conn.Connect(LdapHost, LdapPort); // bind to the server conn.Bind(LdapVersion, loginDN, password); System.Console.Out.WriteLine("Succesfully logged in to server: " + LdapHost); /* Set default filter - Change this line if you need a different set * of search restrictions. Read the "NDS and Ldap Integration Guide" * for information on support by Novell eDirectory of this * functionaliry. */ System.String MY_FILTER = "cn=*"; /* We are requesting that the givenname and cn fields for each * object be returned */ System.String[] attrs = new System.String[2]; attrs[0] = "givenname"; attrs[1] = "cn"; // We will be sending two controls to the server LdapControl[] requestControls = new LdapControl[2]; /* Create the sort key to be used by the sort control * Results should be sorted based on the cn attribute. * See the "NDS and Ldap Integration Guide" for information on * Novell eDirectory support of this functionaliry. */ LdapSortKey[] keys = new LdapSortKey[1]; keys[0] = new LdapSortKey("cn"); // Create the sort control requestControls[0] = new LdapSortControl(keys, true); /* Create the VLV Control. * These two fields in the VLV Control identify the before and * after count of entries to be returned */ int beforeCount = 0; int afterCount = 2; /* The VLV control request can specify the index * using one of the two methods described below: * * TYPED INDEX: Here we request all objects that have cn greater * than or equal to the letter "a" */ requestControls[1] = new LdapVirtualListControl("a", beforeCount, afterCount); /* The following code needs to be enabled to specify the index * directly * int offset = 0; - offset of the index * int contentCount = 3; - our estimate of the search result size * requestControls[1] = new LdapVirtualListControl(offset, * beforeCount, afterCount, contentCount); */ // Set the controls to be sent as part of search request LdapSearchConstraints cons = conn.SearchConstraints; cons.setControls(requestControls); conn.Constraints = cons; // Send the search request - Synchronous Search is being used here System.Console.Out.WriteLine("Calling Asynchronous Search..."); LdapSearchResults res = conn.Search(searchBase, LdapConnection.SCOPE_SUB, MY_FILTER, attrs, false, (LdapSearchConstraints)null); // Loop through the results and print them out while (res.HasMore()) { /* Get next returned entry. Note that we should expect a Ldap- * Exception object as well just in case something goes wrong */ LdapEntry nextEntry = null; try { nextEntry = res.Next(); } catch (LdapException e) { if (e is LdapReferralException) { continue; } else { System.Console.Out.WriteLine("Search stopped with exception " + e.ToString()); break; } } /* Print out the returned Entries distinguished name. */ System.Console.Out.WriteLine(); System.Console.Out.WriteLine(nextEntry.DN); /* Get the list of attributes for the current entry */ LdapAttributeSet findAttrs = nextEntry.getAttributeSet(); /* Convert attribute list to Enumeration */ System.Collections.IEnumerator enumAttrs = findAttrs.GetEnumerator(); System.Console.Out.WriteLine("Attributes: "); /* Loop through all attributes in the enumeration */ while (enumAttrs.MoveNext()) { LdapAttribute anAttr = (LdapAttribute)enumAttrs.Current; /* Print out the attribute name */ System.String attrName = anAttr.Name; System.Console.Out.WriteLine("" + attrName); // Loop through all values for this attribute and print them System.Collections.IEnumerator enumVals = anAttr.StringValues; while (enumVals.MoveNext()) { System.String aVal = (System.String)enumVals.Current; System.Console.Out.WriteLine("" + aVal); } } } // Server should send back a control irrespective of the // status of the search request LdapControl[] controls = res.ResponseControls; if (controls == null) { System.Console.Out.WriteLine("No controls returned"); } else { // We are likely to have multiple controls returned for (int i = 0; i < controls.Length; i++) { /* Is this the Sort Response Control. */ if (controls[i] is LdapSortResponse) { System.Console.Out.WriteLine("Received Ldap Sort Control from " + "Server"); /* We could have an error code and maybe a string * identifying erring attribute in the response control. */ System.String bad = ((LdapSortResponse)controls[i]).FailedAttribute; int result = ((LdapSortResponse)controls[i]).ResultCode; // Print out error code (0 if no error) and any // returned attribute System.Console.Out.WriteLine("Error code: " + result); if ((System.Object)bad != null) { System.Console.Out.WriteLine("Offending " + "attribute: " + bad); } else { System.Console.Out.WriteLine("No offending " + "attribute " + "returned"); } } /* Is this a VLV Response Control */ if (controls[i] is LdapVirtualListResponse) { System.Console.Out.WriteLine("Received VLV Response Control from " + "Server..."); /* Get all returned fields */ int firstPosition = ((LdapVirtualListResponse)controls[i]).FirstPosition; int ContentCount = ((LdapVirtualListResponse)controls[i]).ContentCount; int resultCode = ((LdapVirtualListResponse)controls[i]).ResultCode; System.String context = ((LdapVirtualListResponse)controls[i]).Context; /* Print out the returned fields. Typically you would * have used these fields to reissue another VLV request * or to display the list on a GUI */ System.Console.Out.WriteLine("Result Code => " + resultCode); System.Console.Out.WriteLine("First Position => " + firstPosition); System.Console.Out.WriteLine("Content Count => " + ContentCount); if ((System.Object)context != null) { System.Console.Out.WriteLine("Context String => " + context); } else { System.Console.Out.WriteLine("No Context String in returned" + " control"); } } } } /* We are done - disconnect */ if (conn.Connected) { conn.Disconnect(); } } catch (LdapException e) { System.Console.Out.WriteLine(e.ToString()); } catch (System.IO.IOException e) { System.Console.Out.WriteLine("Error: " + e.ToString()); } catch (Exception e) { System.Console.WriteLine("Error: " + e.Message); } }
public IEnumerable <User> GetUsers(string searchFilter) { _connection.Connect(_config.Url, _config.Port); _connection.Bind(_config.BindDn, _config.BindCredentials); int startIndex = 1; int contentCount = 0; int afterIndex = 1000; int count = 0; do { LdapVirtualListControl ctrl = new LdapVirtualListControl(startIndex, 0, afterIndex, contentCount); LdapSortKey[] keys = new LdapSortKey[1]; keys[0] = new LdapSortKey("samaccountname"); LdapSortControl sort = new LdapSortControl(keys, true); LdapSearchConstraints constraints = _connection.SearchConstraints; constraints.setControls(new LdapControl[] { ctrl, sort }); _connection.Constraints = constraints; LdapSearchResults lsc = _connection.Search( _config.SearchBase, LdapConnection.SCOPE_SUB, searchFilter, new[] { MemberOfAttribute, DisplayNameAttribute, SamAccountNameAttribute, "sn", "givenName", "mail", "displayName" }, false, constraints); foreach (var item in lsc.ToList()) { var user = new User { DisplayName = $"{item.getAttribute("displayName")?.StringValue ?? "noSn"}", Sam = item.getAttribute(SamAccountNameAttribute)?.StringValue ?? "noSam", IsAdmin = item.getAttribute(MemberOfAttribute)?.StringValueArray.Contains(_config.AdminCn) ?? false, Subordinates = null, Email = item.getAttribute("mail")?.StringValue ?? "noMail" }; yield return(user); } LdapControl[] controls = lsc.ResponseControls; if (controls == null) { Console.Out.WriteLine("No controls returned"); } else { foreach (LdapControl control in controls) { if (control.ID == "2.16.840.1.113730.3.4.10") { LdapVirtualListResponse response = new LdapVirtualListResponse(control.ID, control.Critical, control.getValue()); startIndex += afterIndex + 1; contentCount = response.ContentCount; count += afterIndex; } } } // Console.WriteLine(i); } while (count <= contentCount); yield break; }
/// <summary> /// Executes the paged search. /// </summary> /// <returns>The paged search.</returns> /// <param name="searchBase">Search base.</param> /// <param name="filter">Filter.</param> /// <param name="cookie">Cookie to restore last search.</param> public LdapPagedResponse ExecutePagedSearch(string searchBase, string filter, string cookie = "") { var results = new List <LdapEntry>(); var lcm = LdapConnectionManager.Instance; var conn = lcm.GetConnection(); var sb = searchBase + config.searchBase; // We will be sending two controls to the server LdapControl[] requestControls = new LdapControl[2]; /* Create the sort key to be used by the sort control * Results should be sorted based on the cn attribute. * See the "NDS and Ldap Integration Guide" for information on * Novell eDirectory support of this functionaliry. */ LdapSortKey[] keys = new LdapSortKey[1]; keys[0] = new LdapSortKey("cn"); // Create the sort control requestControls[0] = new LdapSortControl(keys, true); /* Create the VLV Control. * These two fields in the VLV Control identify the before and * after count of entries to be returned */ //int beforeCount = 0; //int afterCount = 0; //int afterCount = config.maxResults -1; //System.String cookie = ""; if (cookie != "") { byte[] data = System.Convert.FromBase64String(cookie); cookie = System.Text.Encoding.UTF8.GetString(data); //cookie = System.Text.ASCIIEncoding.ASCII.GetString(data); } requestControls[1] = new LdapPagedResultsControl(config.maxResults, cookie); // Set the controls to be sent as part of search request LdapSearchConstraints cons = conn.SearchConstraints; cons.SetControls(requestControls); conn.Constraints = cons; // Send the search request - Synchronous Search is being used here logger.Debug("Calling Asynchronous Search..."); string[] attrs = null; ILdapSearchResults res = (LdapSearchResults)conn.Search(sb, LdapConnection.ScopeSub, filter, attrs, false, (LdapSearchConstraints)null); // Loop through the results and print them out while (res.HasMore()) { /* Get next returned entry. Note that we should expect a Ldap- * Exception object as well just in case something goes wrong */ LdapEntry nextEntry = null; try { nextEntry = res.Next(); results.Add(nextEntry); } catch (Exception e) { if (e is LdapReferralException) { continue; } else { logger.Error("Search stopped with exception " + e.ToString()); break; } } /* Print out the returned Entries distinguished name. */ logger.Debug(nextEntry.Dn); } var response = new LdapPagedResponse { Entries = results }; // Server should send back a control irrespective of the // status of the search request LdapControl[] controls = ((LdapSearchResults)res).ResponseControls; if (controls == null) { logger.Debug("No controls returned"); } else { // We are likely to have multiple controls returned for (int i = 0; i < controls.Length; i++) { /* Is this the Sort Response Control. */ if (controls[i] is LdapPagedResultsResponse) { logger.Debug("Received Ldap Paged Control from Server"); LdapPagedResultsResponse cresp = new LdapPagedResultsResponse(controls[i].Id, controls[i].Critical, controls[i].GetValue()); cookie = cresp.Cookie; byte[] hexCookie = System.Text.Encoding.UTF8.GetBytes(cookie); response.Cookie = Convert.ToBase64String(hexCookie); /* * // Cookie is an opaque octet string. The chacters it contains might not be printable. * byte[] hexCookie = System.Text.Encoding.ASCII.GetBytes(cookie); * StringBuilder hex = new StringBuilder(hexCookie.Length); * foreach (byte b in hexCookie) * hex.AppendFormat("{0:x}", b); * * System.Console.Out.WriteLine("Cookie: {0}", hex.ToString()); * System.Console.Out.WriteLine("Size: {0}", cresp.Size); */ } } } return(response); }
/// <summary> /// Executes the limited search. /// </summary> /// <returns>The limited search.</returns> /// <param name="searchBase">Search base.</param> /// <param name="filter">Filter.</param> /// <param name="start">Must be 1 or greater</param> /// <param name="end">End.</param> public List <LdapEntry> ExecuteLimitedSearch(string searchBase, string filter, int start, int end) { int sSize = getSearchSize(searchBase, filter); //int sSize = 1000; var results = new List <LdapEntry>(); var lcm = LdapConnectionManager.Instance; var conn = lcm.GetConnection(); var sb = searchBase + config.searchBase; LdapControl[] requestControls = new LdapControl[2]; LdapSortKey[] keys = new LdapSortKey[1]; keys[0] = new LdapSortKey("cn"); //samaccountname // Create the sort control requestControls[0] = new LdapSortControl(keys, true); logger.Debug("Search Size:" + sSize); requestControls[1] = new LdapVirtualListControl(start, 0, end, sSize); //requestControls[1] = new LdapVirtualListControl(filter,0, end, null); // Set the controls to be sent as part of search request LdapSearchConstraints cons = conn.SearchConstraints; cons.SetControls(requestControls); conn.Constraints = cons; // Send the search request - Synchronous Search is being used here logger.Debug("Calling Asynchronous Search..."); LdapSearchResults res = (LdapSearchResults)conn.Search(sb, LdapConnection.ScopeSub, filter, null, false, (LdapSearchConstraints)null); // Loop through the results and print them out while (res.HasMore()) { /* Get next returned entry. Note that we should expect a Ldap- * Exception object as well just in case something goes wrong */ LdapEntry nextEntry = null; try { nextEntry = res.Next(); results.Add(nextEntry); } catch (Exception e) { if (e is LdapReferralException) { continue; } else { logger.Error("Search stopped with exception " + e.ToString()); break; } } /* Print out the returned Entries distinguished name. */ logger.Debug(nextEntry.Dn); } // Server should send back a control irrespective of the // status of the search request LdapControl[] controls = res.ResponseControls; if (controls == null) { logger.Debug("No controls returned"); } else { // We are likely to have multiple controls returned for (int i = 0; i < controls.Length; i++) { /* Is this the Sort Response Control. */ if (controls[i] is LdapSortResponse) { logger.Debug("Received Ldap Sort Control from " + "Server"); /* We could have an error code and maybe a string * identifying erring attribute in the response control. */ System.String bad = ((LdapSortResponse)controls[i]).FailedAttribute; int result = ((LdapSortResponse)controls[i]).ResultCode; // Print out error code (0 if no error) and any // returned attribute logger.Debug("Error code: " + result); if ((System.Object)bad != null) { logger.Debug("Offending " + "attribute: " + bad); } else { logger.Debug("No offending " + "attribute " + "returned"); } } /* Is this a VLV Response Control */ if (controls[i] is LdapVirtualListResponse) { logger.Debug("Received VLV Response Control from " + "Server..."); /* Get all returned fields */ int firstPosition = ((LdapVirtualListResponse)controls[i]).FirstPosition; int ContentCount = ((LdapVirtualListResponse)controls[i]).ContentCount; int resultCode = ((LdapVirtualListResponse)controls[i]).ResultCode; System.String context = ((LdapVirtualListResponse)controls[i]).Context; /* Print out the returned fields. Typically you would * have used these fields to reissue another VLV request * or to display the list on a GUI */ logger.Debug("Result Code => " + resultCode); logger.Debug("First Position => " + firstPosition); logger.Debug("Content Count => " + ContentCount); if ((System.Object)context != null) { logger.Debug("Context String => " + context); } else { logger.Debug("No Context String in returned" + " control"); } } } } return(results); }
private int getSearchSize(string searchBase, string filter) { var results = new List <LdapEntry>(); var lcm = LdapConnectionManager.Instance; var conn = lcm.GetConnection(); var sb = searchBase + config.searchBase; LdapControl[] requestControls = new LdapControl[2]; LdapSortKey[] keys = new LdapSortKey[1]; keys[0] = new LdapSortKey("cn"); //samaccountname // Create the sort control requestControls[0] = new LdapSortControl(keys, true); requestControls[1] = new LdapVirtualListControl(1, 0, 1, config.maxResults); //requestControls[1] = new LdapVirtualListControl(sb,0, config.maxResults, null); // Set the controls to be sent as part of search request LdapSearchConstraints cons = conn.SearchConstraints; cons.SetControls(requestControls); conn.Constraints = cons; // Send the search request - Synchronous Search is being used here logger.Debug("Calling Asynchronous Search..."); LdapSearchResults res = (LdapSearchResults)conn.Search(sb, LdapConnection.ScopeOne, filter, null, false, (LdapSearchConstraints)null); while (res.HasMore()) { res.Next(); } // Server should send back a control irrespective of the // status of the search request LdapControl[] controls = res.ResponseControls; if (controls == null) { logger.Debug("No controls returned"); } else { // We are likely to have multiple controls returned for (int i = 0; i < controls.Length; i++) { /* Is this a VLV Response Control */ if (controls[i] is LdapVirtualListResponse) { logger.Debug("Received VLV Response Control from " + "Server..."); /* Get all returned fields */ int firstPosition = ((LdapVirtualListResponse)controls[i]).FirstPosition; int ContentCount = ((LdapVirtualListResponse)controls[i]).ContentCount; int resultCode = ((LdapVirtualListResponse)controls[i]).ResultCode; System.String context = ((LdapVirtualListResponse)controls[i]).Context; /* Print out the returned fields. Typically you would * have used these fields to reissue another VLV request * or to display the list on a GUI */ logger.Debug("Result Code => " + resultCode); logger.Debug("First Position => " + firstPosition); logger.Debug("Content Count => " + ContentCount); if ((System.Object)context != null) { logger.Debug("Context String => " + context); } else { logger.Debug("No Context String in returned" + " control"); } return(ContentCount); } } } return(-1); }
static void Main(string[] args) { if (args.Length != 6) { Console.WriteLine("Usage: mono SortSearch <host name> <ldap port> <login dn>" + " <password> <search base>" + " <search filter>"); Console.WriteLine("Example: mono SortSearch Acme.com 389" + " \"cn=admin,o=Acme\"" + " secret \"ou=sales,o=Acme\"" + " \"(objectclass=*)\""); return; } string ldapHost = args[0]; int ldapPort = System.Convert.ToInt32(args[1]); String loginDN = args[2]; String password = args[3]; String searchBase = args[4]; String searchFilter = args[5]; String[] attrs = new String[1]; attrs[0] = "sn"; LdapSortKey[] keys = new LdapSortKey[1]; keys[0] = new LdapSortKey("sn"); try { LdapConnection conn = new LdapConnection(); conn.Connect(ldapHost, ldapPort); conn.Bind(loginDN, password); // Create a LDAPSortControl object - Fail if cannot sort LdapSortControl sort = new LdapSortControl(keys, true); // Set the Sort control to be sent as part of search request LdapSearchConstraints cons = conn.SearchConstraints; cons.setControls(sort); conn.Constraints = cons; Console.WriteLine("Connecting to:" + ldapHost); LdapSearchResults lsc = conn.Search(searchBase, LdapConnection.SCOPE_SUB, searchFilter, attrs, false, (LdapSearchConstraints)null); while (lsc.hasMore()) { LdapEntry nextEntry = null; try { nextEntry = lsc.next(); } catch (LdapException e) { Console.WriteLine("Error: " + e.LdapErrorMessage); // Exception is thrown, go for next entry continue; } Console.WriteLine("\n" + nextEntry.DN); LdapAttributeSet attributeSet = nextEntry.getAttributeSet(); System.Collections.IEnumerator ienum = attributeSet.GetEnumerator(); while (ienum.MoveNext()) { LdapAttribute attribute = (LdapAttribute)ienum.Current; string attributeName = attribute.Name; string attributeVal = attribute.StringValue; Console.WriteLine(attributeName + "value:" + attributeVal); } } conn.Disconnect(); } catch (LdapException e) { Console.WriteLine("Error:" + e.LdapErrorMessage); Console.WriteLine("Error:" + e.ToString()); return; } catch (Exception e) { Console.WriteLine("Error:" + e.Message); return; } }
public static void Main(String[] args) { // Verify correct number of parameters if (args.Length != 4) { Console.WriteLine("Usage: mono AsynchronousSortControl <host name> " + "<login dn> <password> <container>"); Console.WriteLine("Example: mono AsynchronousSortControl Acme.com" + " \"cn=admin,o=Acme\" secret \"ou=Sales,o=Acme\""); Environment.Exit(0); } // Read command line arguments String ldapHost = args[0]; String loginDN = args[1]; String password = args[2]; String searchBase = args[3]; int MY_PORT = 389; int ldapVersion = LdapConnection.Ldap_V3; try { // Create a LdapConnection object LdapConnection lc = new LdapConnection(); // Connect to server lc.Connect(ldapHost, MY_PORT); lc.Bind(ldapVersion, loginDN, password); Console.WriteLine("Login succeeded"); // We will be searching for all objects String MY_FILTER = "(objectClass=*)"; // Results of the search should include givenname and cn String[] attrs = new String[2]; attrs[0] = "givenname"; attrs[1] = "cn"; // The results should be sorted using the cn attribute LdapSortKey[] keys = new LdapSortKey[1]; keys[0] = new LdapSortKey("cn"); // Create a LdapSortControl object - Fail if cannot sort LdapSortControl sort = new LdapSortControl(keys, true); // Set the Sort control to be sent as part of search request LdapSearchConstraints cons = lc.SearchConstraints; cons.setControls(sort); lc.Constraints = cons; // Perform the search - ASYNCHRONOUS SEARCH USED HERE Console.WriteLine("Calling search request"); LdapSearchQueue queue = lc.Search(searchBase, LdapConnection.SCOPE_SUB, MY_FILTER, attrs, false, (LdapSearchQueue)null, (LdapSearchConstraints)null); LdapMessage message; while ((message = queue.getResponse()) != null) { // OPTION 1: the message is a search result reference if (message is LdapSearchResultReference) { // Not following referrals to keep things simple String[] urls = ((LdapSearchResultReference)message).Referrals; Console.WriteLine("Search result references:"); for (int i = 0; i < urls.Length; i++) { Console.WriteLine(urls[i]); } } // OPTION 2:the message is a search result else if (message is LdapSearchResult) { // Get the object name LdapEntry entry = ((LdapSearchResult)message).Entry; Console.WriteLine("\n" + entry.DN); Console.WriteLine("\tAttributes: "); // Get the attributes and print them out LdapAttributeSet attributeSet = entry.getAttributeSet(); IEnumerator allAttributes = attributeSet.GetEnumerator(); while (allAttributes.MoveNext()) { LdapAttribute attribute = (LdapAttribute)allAttributes.Current; String attributeName = attribute.Name; Console.WriteLine("\t\t" + attributeName); // Print all values of the attribute IEnumerator allValues = attribute.StringValues; if (allValues != null) { while (allValues.MoveNext()) { String Value = (String)allValues.Current; Console.WriteLine("\t\t\t" + Value); } } } } // OPTION 3: The message is a search response else { LdapResponse response = (LdapResponse)message; int status = response.ResultCode; // the return code is Ldap success if (status == LdapException.SUCCESS) { Console.WriteLine("Asynchronous search succeeded."); } // the return code is referral exception else if (status == LdapException.REFERRAL) { String[] urls = ((LdapResponse)message).Referrals; Console.WriteLine("Referrals:"); for (int i = 0; i < urls.Length; i++) { Console.WriteLine(urls[i]); } } else { Console.WriteLine("Asynchronous search failed."); Console.WriteLine(response.ErrorMessage); } // Server should send back a control irrespective of the // status of the search request LdapControl[] controls = response.Controls; if (controls != null) { // Theoritically we could have multiple controls returned for (int i = 0; i < controls.Length; i++) { // We are looking for the LdapSortResponse Control class - the control // sent back in response to LdapSortControl if (controls[i] is LdapSortResponse) { Console.WriteLine("Received Ldap Sort Control fromserver"); // We must have an error code and maybe a string identifying // erring attribute in the response control. Get these. String bad = ((LdapSortResponse)controls[i]).FailedAttribute; int result = ((LdapSortResponse)controls[i]).ResultCode; // Print out error ccode (0 if no error) and any returned // attribute Console.WriteLine("Error code: " + result); if (bad != null) { Console.WriteLine("Offending " + "attribute: " + bad); } else { Console.WriteLine("No offending " + "attribute " + "returned"); } } } } } } // All done - disconnect if (lc.Connected == true) { lc.Disconnect(); } } catch (LdapException e) { Console.WriteLine(e.ToString()); } catch (Exception e) { Console.WriteLine("Error: " + e.ToString()); } }