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: }