1: /*
2: Copyright (c) 2010 <a href="http://www.gutgames.com">James Craig</a>
3:
4: Permission is hereby granted, free of charge, to any person obtaining a copy
5: of this software and associated documentation files (the "Software"), to deal
6: in the Software without restriction, including without limitation the rights
7: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8: copies of the Software, and to permit persons to whom the Software is
9: furnished to do so, subject to the following conditions:
10:
11: The above copyright notice and this permission notice shall be included in
12: all copies or substantial portions of the Software.
13:
14: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20: THE SOFTWARE.*/
21:
22: #region Usings
23: using System;
24: using System.Collections.Generic;
25: using System.DirectoryServices;
26: #endregion
27:
28: namespace Utilities.LDAP
29: { 30: /// <summary>
31: /// Class for helping with AD
32: /// </summary>
33: public class Directory : IDisposable
34: { 35: #region Constructors
36: /// <summary>
37: /// Constructor
38: /// </summary>
39: /// <param name="UserName">User name used to log in</param>
40: /// <param name="Password">Password used to log in</param>
41: /// <param name="Path">Path of the LDAP server</param>
42: /// <param name="Query">Query to use in the search</param>
43: public Directory(string Query, string UserName, string Password, string Path)
44: { 45: Entry = new DirectoryEntry(Path, UserName, Password, AuthenticationTypes.Secure);
46: this.Path = Path;
47: this.UserName = UserName;
48: this.Password = Password;
49: this.Query = Query;
50: Searcher = new DirectorySearcher(Entry);
51: Searcher.Filter = Query;
52: Searcher.PageSize = 1000;
53: }
54: #endregion
55:
56: #region Public Functions
57: /// <summary>
58: /// Finds a user by his user name
59: /// </summary>
60: /// <param name="UserName">User name to search by</param>
61: /// <returns>The user's entry</returns>
62: public Entry FindUserByUserName(string UserName)
63: { 64: List<Entry> Entries = FindUsers("samAccountName=" + UserName); 65: if (Entries.Count > 0)
66: { 67: return Entries[0];
68: }
69: return null;
70: }
71:
72: /// <summary>
73: /// Finds all active users
74: /// </summary>
75: /// <param name="Filter">Filter used to modify the query</param>
76: /// <param name="args">Additional arguments (used in string formatting</param>
77: /// <returns>A list of all active users' entries</returns>
78: public List<Entry> FindActiveUsers(string Filter, params object[] args)
79: { 80: Filter = string.Format(Filter, args);
81: Filter = string.Format("(&((userAccountControl:1.2.840.113556.1.4.803:=512)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(cn=*$)))({0}))", Filter); 82: return FindUsers(Filter);
83: }
84:
85: /// <summary>
86: /// Finds all users
87: /// </summary>
88: /// <param name="Filter">Filter used to modify the query</param>
89: /// <param name="args">Additional arguments (used in string formatting</param>
90: /// <returns>A list of all users meeting the specified Filter</returns>
91: public List<Entry> FindUsers(string Filter, params object[] args)
92: { 93: Filter = string.Format(Filter, args);
94: Filter = string.Format("(&(objectClass=User)(objectCategory=Person)({0}))", Filter); 95: Searcher.Filter = Filter;
96: return FindAll();
97: }
98:
99: /// <summary>
100: /// Finds all computers
101: /// </summary>
102: /// <param name="Filter">Filter used to modify the query</param>
103: /// <param name="args">Additional arguments (used in string formatting</param>
104: /// <returns>A list of all computers meeting the specified Filter</returns>
105: public List<Entry> FindComputers(string Filter, params object[] args)
106: { 107: Filter = string.Format(Filter, args);
108: Filter = string.Format("(&(objectClass=computer)({0}))", Filter); 109: Searcher.Filter = Filter;
110: return FindAll();
111: }
112:
113: /// <summary>
114: /// Finds all active users and groups
115: /// </summary>
116: /// <param name="Filter">Filter used to modify the query</param>
117: /// <param name="args">Additional arguments (used in string formatting</param>
118: /// <returns>A list of all active groups' entries</returns>
119: public List<Entry> FindActiveUsersAndGroups(string Filter, params object[] args)
120: { 121: Filter = string.Format(Filter, args);
122: Filter = string.Format("(&((userAccountControl:1.2.840.113556.1.4.803:=512)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(cn=*$)))({0}))", Filter); 123: return FindUsersAndGroups(Filter);
124: }
125:
126: /// <summary>
127: /// Finds all users and groups
128: /// </summary>
129: /// <param name="Filter">Filter used to modify the query</param>
130: /// <param name="args">Additional arguments (used in string formatting</param>
131: /// <returns>A list of all users and groups meeting the specified Filter</returns>
132: public List<Entry> FindUsersAndGroups(string Filter, params object[] args)
133: { 134: Filter = string.Format(Filter, args);
135: Filter = string.Format("(&(|(&(objectClass=Group)(objectCategory=Group))(&(objectClass=User)(objectCategory=Person)))({0}))", Filter); 136: Searcher.Filter = Filter;
137: return FindAll();
138: }
139:
140: /// <summary>
141: /// Finds all active groups
142: /// </summary>
143: /// <param name="Filter">Filter used to modify the query</param>
144: /// <param name="args">Additional arguments (used in string formatting</param>
145: /// <returns>A list of all active groups' entries</returns>
146: public List<Entry> FindActiveGroups(string Filter, params object[] args)
147: { 148: Filter = string.Format(Filter, args);
149: Filter = string.Format("(&((userAccountControl:1.2.840.113556.1.4.803:=512)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(cn=*$)))({0}))", Filter); 150: return FindGroups(Filter);
151: }
152:
153: /// <summary>
154: /// Finds all groups
155: /// </summary>
156: /// <param name="Filter">Filter used to modify the query</param>
157: /// <param name="args">Additional arguments (used in string formatting</param>
158: /// <returns>A list of all groups meeting the specified Filter</returns>
159: public List<Entry> FindGroups(string Filter, params object[] args)
160: { 161: Filter = string.Format(Filter, args);
162: Filter = string.Format("(&(objectClass=Group)(objectCategory=Group)({0}))", Filter); 163: Searcher.Filter = Filter;
164: return FindAll();
165: }
166:
167: /// <summary>
168: /// Returns a group's list of members
169: /// </summary>
170: /// <param name="GroupName">The group's name</param>
171: /// <returns>A list of the members</returns>
172: public List<Utilities.LDAP.Entry> FindActiveGroupMembers(string GroupName)
173: { 174: try
175: { 176: List<Utilities.LDAP.Entry> Entries = this.FindGroups("cn=" + GroupName); 177: if (Entries.Count < 1)
178: return new List<Utilities.LDAP.Entry>();
179:
180: return this.FindActiveUsersAndGroups("memberOf=" + Entries[0].DistinguishedName); 181: }
182: catch
183: { 184: return new List<Utilities.LDAP.Entry>();
185: }
186: }
187:
188: /// <summary>
189: /// Finds all entries that match the query
190: /// </summary>
191: /// <returns>A list of all entries that match the query</returns>
192: public List<Entry> FindAll()
193: { 194: List<Entry> ReturnedResults = new List<Entry>();
195: SearchResultCollection Results = Searcher.FindAll();
196: foreach (SearchResult Result in Results)
197: { 198: ReturnedResults.Add(new Entry(Result.GetDirectoryEntry()));
199: }
200: Results.Dispose();
201: return ReturnedResults;
202: }
203:
204: /// <summary>
205: /// Finds one entry that matches the query
206: /// </summary>
207: /// <returns>A single entry matching the query</returns>
208: public Entry FindOne()
209: { 210: SearchResult Result = Searcher.FindOne();
211: return new Entry(Result.GetDirectoryEntry());
212: }
213:
214: /// <summary>
215: /// Closes the directory
216: /// </summary>
217: public void Close()
218: { 219: Entry.Close();
220: }
221:
222: /// <summary>
223: /// Checks to see if the person was authenticated
224: /// </summary>
225: /// <returns>true if they were authenticated properly, false otherwise</returns>
226: public bool Authenticate()
227: { 228: try
229: { 230: if (!Entry.Guid.ToString().ToLower().Trim().Equals("")) 231: { 232: return true;
233: }
234: }
235: catch
236: { 237: }
238: return false;
239: }
240: #endregion
241:
242: #region Properties
243: /// <summary>
244: /// Path of the server
245: /// </summary>
246: public string Path
247: { 248: get { return _Path; } 249: set
250: { 251: _Path = value;
252: if (Entry != null)
253: { 254: Entry.Close();
255: }
256: Entry = new DirectoryEntry(_Path, _UserName, _Password, AuthenticationTypes.Secure);
257: Searcher = new DirectorySearcher(Entry);
258: Searcher.Filter = Query;
259: Searcher.PageSize = 1000;
260: }
261: }
262:
263: /// <summary>
264: /// User name used to log in
265: /// </summary>
266: public string UserName
267: { 268: get { return _UserName; } 269: set
270: { 271: _UserName = value;
272: if (Entry != null)
273: { 274: Entry.Close();
275: }
276: Entry = new DirectoryEntry(_Path, _UserName, _Password, AuthenticationTypes.Secure);
277: Searcher = new DirectorySearcher(Entry);
278: Searcher.Filter = Query;
279: Searcher.PageSize = 1000;
280: }
281: }
282:
283: /// <summary>
284: /// Password used to log in
285: /// </summary>
286: public string Password
287: { 288: get { return _Password; } 289: set
290: { 291: _Password = value;
292: if (Entry != null)
293: { 294: Entry.Close();
295: }
296: Entry = new DirectoryEntry(_Path, _UserName, _Password, AuthenticationTypes.Secure);
297: Searcher = new DirectorySearcher(Entry);
298: Searcher.Filter = Query;
299: Searcher.PageSize = 1000;
300: }
301: }
302:
303: /// <summary>
304: /// The query that is being made
305: /// </summary>
306: public string Query
307: { 308: get { return _Query; } 309: set
310: { 311: _Query = value;
312: Searcher.Filter = _Query;
313: }
314: }
315:
316: /// <summary>
317: /// Decides what to sort the information by
318: /// </summary>
319: public string SortBy
320: { 321: get { return _SortBy; } 322: set
323: { 324: _SortBy = value;
325: Searcher.Sort.PropertyName = _SortBy;
326: Searcher.Sort.Direction = SortDirection.Ascending;
327: }
328: }
329: #endregion
330:
331: #region Private Variables
332: private string _Path = "";
333: private string _UserName = "";
334: private string _Password = "";
335: private DirectoryEntry Entry = null;
336: private string _Query = "";
337: private DirectorySearcher Searcher = null;
338: private string _SortBy = "";
339: #endregion
340:
341: #region IDisposable Members
342:
343: public void Dispose()
344: { 345: if (Entry != null)
346: { 347: Entry.Dispose();
348: Entry = null;
349: }
350: if (Searcher != null)
351: { 352: Searcher.Dispose();
353: Searcher = null;
354: }
355: }
356:
357: #endregion
358: }
359: }
360:
361: /*
362: Copyright (c) 2010 <a href="http://www.gutgames.com">James Craig</a>
363:
364: Permission is hereby granted, free of charge, to any person obtaining a copy
365: of this software and associated documentation files (the "Software"), to deal
366: in the Software without restriction, including without limitation the rights
367: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
368: copies of the Software, and to permit persons to whom the Software is
369: furnished to do so, subject to the following conditions:
370:
371: The above copyright notice and this permission notice shall be included in
372: all copies or substantial portions of the Software.
373:
374: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
375: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
376: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
377: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
378: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
379: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
380: THE SOFTWARE.*/
381:
382: #region Usings
383: using System;
384: using System.Collections.Generic;
385: using System.DirectoryServices;
386: #endregion
387:
388: namespace Utilities.LDAP
389: { 390: /// <summary>
391: /// Directory entry class
392: /// </summary>
393: public class Entry : IDisposable
394: { 395: #region Constructors
396: /// <summary>
397: /// Constructor
398: /// </summary>
399: /// <param name="DirectoryEntry">Directory entry for the item</param>
400: public Entry(DirectoryEntry DirectoryEntry)
401: { 402: this._DirectoryEntry = DirectoryEntry;
403: }
404: #endregion
405:
406: #region Properties
407: /// <summary>
408: /// Actual base directory entry
409: /// </summary>
410: public DirectoryEntry DirectoryEntry
411: { 412: get { return _DirectoryEntry; } 413: set { _DirectoryEntry = value; } 414: }
415:
416: /// <summary>
417: /// Email property for this entry
418: /// </summary>
419: public string Email
420: { 421: get { return (string)GetValue("mail"); } 422: set { SetValue("mail", value); } 423: }
424:
425: /// <summary>
426: /// distinguished name property for this entry
427: /// </summary>
428: public string DistinguishedName
429: { 430: get { return (string)GetValue("distinguishedname"); } 431: set { SetValue("distinguishedname", value); } 432: }
433:
434: /// <summary>
435: /// country code property for this entry
436: /// </summary>
437: public string CountryCode
438: { 439: get { return (string)GetValue("countrycode"); } 440: set { SetValue("countrycode", value); } 441: }
442:
443: /// <summary>
444: /// company property for this entry
445: /// </summary>
446: public string Company
447: { 448: get { return (string)GetValue("company"); } 449: set { SetValue("company", value); } 450: }
451:
452: /// <summary>
453: /// MemberOf property for this entry
454: /// </summary>
455: public List<string> MemberOf
456: { 457: get
458: { 459: List<string> Values = new List<string>();
460: PropertyValueCollection Collection = DirectoryEntry.Properties["memberof"];
461: foreach (object Item in Collection)
462: { 463: Values.Add((string)Item);
464: }
465: return Values;
466: }
467: }
468:
469: /// <summary>
470: /// display name property for this entry
471: /// </summary>
472: public string DisplayName
473: { 474: get { return (string)GetValue("displayname"); } 475: set { SetValue("displayname", value); } 476: }
477:
478: /// <summary>
479: /// initials property for this entry
480: /// </summary>
481: public string Initials
482: { 483: get { return (string)GetValue("initials"); } 484: set { SetValue("initials", value); } 485: }
486:
487: /// <summary>
488: /// title property for this entry
489: /// </summary>
490: public string Title
491: { 492: get { return (string)GetValue("title"); } 493: set { SetValue("title", value); } 494: }
495:
496: /// <summary>
497: /// samaccountname property for this entry
498: /// </summary>
499: public string SamAccountName
500: { 501: get { return (string)GetValue("samaccountname"); } 502: set { SetValue("samaccountname", value); } 503: }
504:
505: /// <summary>
506: /// givenname property for this entry
507: /// </summary>
508: public string GivenName
509: { 510: get { return (string)GetValue("givenname"); } 511: set { SetValue("givenname", value); } 512: }
513:
514: /// <summary>
515: /// cn property for this entry
516: /// </summary>
517: public string CN
518: { 519: get { return (string)GetValue("cn"); } 520: set { SetValue("cn", value); } 521: }
522:
523: /// <summary>
524: /// name property for this entry
525: /// </summary>
526: public string Name
527: { 528: get { return (string)GetValue("name"); } 529: set { SetValue("name", value); } 530: }
531:
532: /// <summary>
533: /// office property for this entry
534: /// </summary>
535: public string Office
536: { 537: get { return (string)GetValue("physicaldeliveryofficename"); } 538: set { SetValue("physicaldeliveryofficename", value); } 539: }
540:
541: /// <summary>
542: /// telephone number property for this entry
543: /// </summary>
544: public string TelephoneNumber
545: { 546: get { return (string)GetValue("telephonenumber"); } 547: set { SetValue("telephonenumber", value); } 548: }
549: #endregion
550:
551: #region Public Functions
552: /// <summary>
553: /// Saves any changes that have been made
554: /// </summary>
555: public void Save()
556: { 557: _DirectoryEntry.CommitChanges();
558: }
559:
560: /// <summary>
561: /// Gets a value from the entry
562: /// </summary>
563: /// <param name="Property">Property you want the information about</param>
564: /// <returns>an object containing the property's information</returns>
565: public object GetValue(string Property)
566: { 567: PropertyValueCollection Collection = DirectoryEntry.Properties[Property];
568: if (Collection != null)
569: { 570: return Collection.Value;
571: }
572: return null;
573: }
574:
575: /// <summary>
576: /// Sets a property of the entry to a specific value
577: /// </summary>
578: /// <param name="Property">Property of the entry to set</param>
579: /// <param name="Value">Value to set the property to</param>
580: public void SetValue(string Property, object Value)
581: { 582: PropertyValueCollection Collection = DirectoryEntry.Properties[Property];
583: if (Collection != null)
584: { 585: Collection.Value = Value;
586: }
587: }
588: #endregion
589:
590: #region Private Variables
591: private DirectoryEntry _DirectoryEntry;
592: #endregion
593:
594: #region IDisposable Members
595:
596: public void Dispose()
597: { 598: if (_DirectoryEntry != null)
599: { 600: _DirectoryEntry.Dispose();
601: _DirectoryEntry = null;
602: }
603: }
604:
605: #endregion
606: }
607: }