/// <summary> /// Build a LDAP Query String. Dependant on SearchBuilder. /// </summary> /// <param name="Attrib"></param> /// <param name="Data"></param> /// <returns></returns> string SearchStringBuilder(CaseLDAPSearchAttributes Attrib, string Data) { string retVal = null; switch (Attrib) { case CaseLDAPSearchAttributes.WholeName: retVal = "(cn=" + Data + ")"; break; case CaseLDAPSearchAttributes.LastName: retVal = "(sn=" + Data + ")"; break; case CaseLDAPSearchAttributes.Telephone: if (Data.Length == 4) Data = "216368" + Data; else if (Data.Length == 7) Data = "216" + Data; retVal = "(telephonenumber=" + Data + ")"; break; case CaseLDAPSearchAttributes.UserID: retVal = "(uid=" + Data + ")"; break; case CaseLDAPSearchAttributes.Language: retVal = "(preferredLanguage=" + Data + ")"; break; case CaseLDAPSearchAttributes.DeptNumber: retVal = "(departmentNumber=" + Data + ")"; break; case CaseLDAPSearchAttributes.Raw: retVal = Data; break; default: throw new Exception("Invalid type of search"); } return retVal; }
public CaseLDAPReturn Search(CaseLDAPSearchAttributes searchMethod, string Term, bool getDetails = false) { TimeSpan ADSTime = new TimeSpan(0); if(searchMethod == CaseLDAPSearchAttributes.ADSGroup) //if we are searching ADS user groups.. { searchMethod = CaseLDAPSearchAttributes.UserID; //We are expecting a list of case ids. Stopwatch searchADSTime = new Stopwatch(); //Time our search searchADSTime.Start(); Term = string.Join(",", ads.UsersInGroup(Term)); //combine our users into a comma seperated string. Our serach builders already handle this searchADSTime.Stop(); ADSTime = searchADSTime.Elapsed; } DirectoryEntry entry = new DirectoryEntry(Options.LDAPServer, null, null, AuthenticationTypes.Anonymous); //Connect to LDAP //entry.Username = "******"; //entry.Password = "******"; DirectorySearcher mySearcher = new DirectorySearcher { SearchRoot = entry, SearchScope = SearchScope.Subtree, Filter = SearchBuilder(searchMethod, Term) }; Stopwatch searchTime = new Stopwatch(); //Time our search searchTime.Start(); SearchResultCollection results = mySearcher.FindAll(); //Query LDAP _retval.ResultsCount = results.Count; if (results.Count > 0) { StringBuilder resultsOutput = new StringBuilder(); foreach (SearchResult result in results) { CaseLDAPSearchResults sr = new CaseLDAPSearchResults(); //Our Results object is meant to be serializable from ldap. We had to create a seperate object to handle this. Later we us reflection to publish to this object. /* Another way. DirectoryEntry e = result.GetDirectoryEntry(); foreach(PropertyValueCollection property in entry.Properties) { foreach(var val in property) { string key = property.PropertyName string value = val.ToString() ... } } */ if (!getDetails) //if a less detailed search is requested { sr.cn = (result.Properties["cn"].Count > 0) ? result.Properties["cn"][0].ToString() : null; sr.uid = (result.Properties["uid"].Count > 0) ? result.Properties["uid"][0].ToString() : null; sr.telephonenumber = (result.Properties["telephonenumber"].Count > 0) ? result.Properties["telephonenumber"][0].ToString() : null; sr.mail = (result.Properties["mail"].Count > 0) ? result.Properties["mail"][0].ToString() : null; sr.physicaldeliveryofficename = (result.Properties["physicaldeliveryofficename"].Count > 0) ? result.Properties["physicaldeliveryofficename"][0].ToString() : null; sr.title = (result.Properties["title"].Count > 0) ? result.Properties["title"][0].ToString() : null; sr.ou = (result.Properties["ou"].Count > 0) ? result.Properties["ou"][0].ToString() : null; foreach (var m in result.Properties["mailequivalentaddress"]) { sr.mailequivalentaddress.Add(m.ToString()); } } else { foreach (string key in result.Properties.PropertyNames) //Loop through our keys and properties. The way it's setup is kind of odd. so we have nested loops. { foreach (object val in result.Properties[key]) { //resultsOutput.Append(String.Format("{0}: {1}, ", key, property.ToString())); //_retval.SearchResults.Add(new KeyValuePair<string, string>(key, property.ToString())); //UGH. Using reflection to store our values into a serializable object. var prop = sr.GetType().GetProperty(key); //Get the property of our results object that matches the key. if (prop != null) //if there is a different key than what is in LDAP then put it in an array of other stuff. { if (prop.PropertyType == typeof(string)) //There are two types of properties in our results object. string and list of string. { prop.SetValue(sr, val.ToString()); } else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) { switch (prop.Name) //if there is many values for an ldap object put in in an array and we'll serialize that to JSON. { case "mailequivalentaddress": sr.mailequivalentaddress.Add(val.ToString()); break; case "objectclass": sr.objectclass.Add(val.ToString()); break; default: sr.otherstuff.Add(new KeyValuePair<string, string>(key, val.ToString())); break; } } } else { sr.otherstuff.Add(new KeyValuePair<string, string>(key, val.ToString())); } } } } _retval.SearchResults.Add(sr); //add our results to be serialized. } } searchTime.Stop(); TimeSpan ts = searchTime.Elapsed; ts = ts.Add(ADSTime); //if there was an ADS Search add that to our search time.. _retval.SearchTime = String.Format("{0:00}.{1:0000}", ts.Seconds, ts.Milliseconds); return _retval; }
/// <summary> /// Entry Point to build our query for LDAP, We don't allow complex queries when the attribute is not raw. if they need more they can make thier own damn query. /// </summary> /// <param name="Attrib">Our Attributes</param> /// <param name="Data">our data to convert to LDAP srting</param> /// <returns></returns> private string SearchBuilder(CaseLDAPSearchAttributes Attrib, string Data) { StringBuilder BatchRetVal = new StringBuilder(); string[] batch = Data.Split(new string[] { "\n", "," }, StringSplitOptions.RemoveEmptyEntries); //We are expecting if (batch.Length > 1) //allowing for single searches in a batch box. BatchRetVal.Append("(|"); //if there is more than one the query (|(query=data)(query2=data2)...(queryN=dataN)) works. So we need to appead the OR operation foreach (string data in batch) BatchRetVal.Append(SearchStringBuilder(Attrib, data)); if (batch.Length > 1) //allowing for single searches in a batch box. Close our expresion. BatchRetVal.Append(")"); return BatchRetVal.ToString(); }