Advertisement
EmilySamantha80

Full featured Active Directory client in C# ADContext.cs

Dec 8th, 2016
253
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 30.02 KB | None | 0 0
  1. // Title:  Full featured Active Directory client in C#
  2. // Author: Emily Heiner
  3. // Date:   2016-12-08
  4. //
  5. // MIT License
  6. // Copyright(c) 2017 Emily Heiner (emilysamantha80@gmail.com)
  7. //
  8. // Permission is hereby granted, free of charge, to any person obtaining a copy
  9. // of this software and associated documentation files (the "Software"), to deal
  10. // in the Software without restriction, including without limitation the rights
  11. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. // copies of the Software, and to permit persons to whom the Software is
  13. // furnished to do so, subject to the following conditions:
  14. //
  15. // The above copyright notice and this permission notice shall be included in all
  16. // copies or substantial portions of the Software.
  17. //
  18. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. // SOFTWARE.
  25.  
  26.  
  27. using System;
  28. using System.Collections.Generic;
  29. using System.DirectoryServices;
  30. using System.DirectoryServices.ActiveDirectory;
  31. using System.DirectoryServices.AccountManagement;
  32. using System.Security;
  33. using System.Runtime.InteropServices;
  34. using System.Text.RegularExpressions;
  35. using System.Linq;
  36.  
  37. /// <summary>
  38. /// Full featured C# Active Directory client
  39. /// </summary>
  40. namespace ESH.Utility.ActiveDirectory
  41. {
  42.     /// <summary>
  43.     ///     Specifies the different schema classes of an Active Directory object.
  44.     ///     The application can set multiple options that are linked with a bitwise OR operation.
  45.     ///     SchemaClass.Any represents all of the schema classes.
  46.     /// </summary>
  47.     [Serializable]
  48.     [Flags]
  49.     public enum SchemaClass
  50.     {
  51.         //Any Schema Class
  52.         Any = 1,
  53.         //Organizational Unit
  54.         organizationalUnit = 2,
  55.         //Container
  56.         container = 4,
  57.         //Built-in Domain Container
  58.         builtinDomain = 8,
  59.         //Group
  60.         group = 16,
  61.         //User
  62.         user = 32,
  63.         //Computer
  64.         computer = 64,
  65.         //Printer
  66.         printer = 128,
  67.         //Contact
  68.         contact = 256,
  69.         //Shared Folder
  70.         volume = 512,
  71.         //InetOrgPerson
  72.         inetOrgPerson = 1024,
  73.         //Query-based distribution Group
  74.         msExchDynamicDistributionList = 2048
  75.     }
  76.  
  77.     /// <summary>
  78.     /// This object represents the connection to the Active Directory server.
  79.     /// It also contains methods to manipulate Active Directory objects.
  80.     /// </summary>
  81.     public class ADContext
  82.     {
  83.         /// <summary>
  84.         /// Used for GetNewDirectoryEntry(). It is set when you connect to the server.
  85.         /// </summary>
  86.         private Principal _DefaultPrincipal;
  87.  
  88.  
  89.         private ContextType _ContextType = ContextType.Domain;
  90.         /// <summary>
  91.         /// The ContextType of the current connection to the server.
  92.         /// </summary>
  93.         public ContextType ContextType
  94.         {
  95.             get
  96.             {
  97.                 return _ContextType;
  98.             }
  99.         }
  100.  
  101.         private string _Container = String.Empty;
  102.         /// <summary>
  103.         /// The distinguished name of the container that the current connection is bound to
  104.         /// </summary>
  105.         public string Container
  106.         {
  107.             get
  108.             {
  109.                 return _Container;
  110.             }
  111.         }
  112.  
  113.         private string _Server = String.Empty;
  114.         /// <summary>
  115.         /// The Active Directory server that is currently connected.
  116.         /// </summary>
  117.         public string Server
  118.         {
  119.             get
  120.             {
  121.                 return _Server;
  122.             }
  123.         }
  124.  
  125.         private string _UserName = String.Empty;
  126.         /// <summary>
  127.         /// The username that was used to connect to the Active Directory Server.
  128.         /// If connected using the applicatoin's credentials, this will be empty.
  129.         /// </summary>
  130.         public string UserName
  131.         {
  132.             get
  133.             {
  134.                 return _UserName;
  135.             }
  136.         }
  137.  
  138.         private SecureString _Password = new SecureString();
  139.         /// <summary>
  140.         /// The password that was used to connect to the Active Directory Server.
  141.         /// If connected using the applicatoin's credentials, this will be empty.
  142.         /// </summary>
  143.         public SecureString Password
  144.         {
  145.             get
  146.             {
  147.                 return _Password;
  148.             }
  149.         }
  150.  
  151.         private bool _ConnectedUsingPassword = false;
  152.         /// <summary>
  153.         /// Returns true if connected to the server by specifying a username and password, false if connected using the application's credentials.
  154.         /// </summary>
  155.         public bool ConnectedUsingPassword
  156.         {
  157.             get
  158.             {
  159.                 return _ConnectedUsingPassword;
  160.             }
  161.         }
  162.  
  163.         private ContextOptions _ContextOptions = (ContextOptions.ServerBind | ContextOptions.Negotiate);
  164.         /// <summary>
  165.         /// The ContextOptions that were used to connect to the server.
  166.         /// </summary>
  167.         public ContextOptions ContextOptions
  168.         {
  169.             get
  170.             {
  171.                 return _ContextOptions;
  172.             }
  173.         }
  174.  
  175.         /// <summary>
  176.         /// The PrincipalContext object that is used for Active Directory operations.
  177.         /// </summary>
  178.         private PrincipalContext _PrincipalContext;
  179.         public PrincipalContext PrincipalContext
  180.         {
  181.             get
  182.             {
  183.                 return _PrincipalContext;
  184.             }
  185.         }
  186.  
  187.         /// <summary>
  188.         /// Creates a new ADContext instance.
  189.         /// </summary>
  190.         public ADContext()
  191.         {
  192.         }
  193.  
  194.         /// <summary>
  195.         /// Connects to an Active Directory server using the application's credentials.
  196.         /// </summary>
  197.         /// <param name="server">The Active Directory server to connect to.</param>
  198.         /// <param name="container">The distinguished name of the container to bind to</param>
  199.         public void Connect(string server, string container)
  200.         {
  201.             Connect(server, container, this.ContextOptions);
  202.         }
  203.  
  204.         /// <summary>
  205.         /// Connects to an Active Directory server using the application's credentials.
  206.         /// </summary>
  207.         /// <param name="server">The Active Directory server to connect to.</param>
  208.         /// <param name="container">The distinguished name of the container to bind to</param>
  209.         /// <param name="contextOptions">The options that are used to bind to the server</param>
  210.         public void Connect(string server, string container, ContextOptions contextOptions)
  211.         {
  212.             this._Server = server;
  213.             this._Container = container;
  214.             this._UserName = String.Empty;
  215.             this._Password = new SecureString();
  216.             this._ContextOptions = contextOptions;
  217.             this._ConnectedUsingPassword = false;
  218.             Match match = Regex.Match(container, @"(DC\=.*)", RegexOptions.CultureInvariant);
  219.             if (match.Groups.Count > 0)
  220.             {
  221.                 _PrincipalContext = new PrincipalContext(this._ContextType, this._Server, match.Groups[0].Value, this._ContextOptions);
  222.                 _DefaultPrincipal = ADUserPrincipal.FindOneByAttribute(_PrincipalContext, "sAMAccountName", "*");
  223.                 if (_DefaultPrincipal == null)
  224.                 {
  225.                     _DefaultPrincipal = ADGroupPrincipal.FindOneByAttribute(_PrincipalContext, "sAMAccountName", "*");
  226.                 }
  227.                 ChangeContainer(container);
  228.             }
  229.             else
  230.             {
  231.                 _PrincipalContext = new PrincipalContext(this._ContextType, this._Server, this._Container, this._ContextOptions);
  232.                 _DefaultPrincipal = ADUserPrincipal.FindOneByAttribute(_PrincipalContext, "sAMAccountName", "*");
  233.                 if (_DefaultPrincipal == null)
  234.                 {
  235.                     _DefaultPrincipal = ADGroupPrincipal.FindOneByAttribute(_PrincipalContext, "sAMAccountName", "*");
  236.                 }
  237.             }
  238.         }
  239.  
  240.         /// <summary>
  241.         /// Connects to an Active Directory server specifying the username and password.
  242.         /// </summary>
  243.         /// <param name="server">The Active Directory server to connect to.</param>
  244.         /// <param name="container">The distinguished name of the container to bind to</param>
  245.         /// <param name="userName">The username to connect using</param>
  246.         /// <param name="password">The password to connect using</param>
  247.         public void Connect(string server, string container, string userName, string password)
  248.         {
  249.             Connect(server, container, userName, ToSecureString(password));
  250.         }
  251.  
  252.         /// <summary>
  253.         /// Connects to an Active Directory server specifying the username and password.
  254.         /// </summary>
  255.         /// <param name="server">The Active Directory server to connect to.</param>
  256.         /// <param name="container">The distinguished name of the container to bind to</param>
  257.         /// <param name="userName">The username to connect using</param>
  258.         /// <param name="password">The password to connect using</param>
  259.         public void Connect(string server, string container, string userName, SecureString password)
  260.         {
  261.             Connect(server, container, userName, password, this.ContextOptions);
  262.         }
  263.  
  264.         /// <summary>
  265.         /// Connects to an Active Directory server specifying the username and password.
  266.         /// </summary>
  267.         /// <param name="server">The Active Directory server to connect to.</param>
  268.         /// <param name="container">The distinguished name of the container to bind to</param>
  269.         /// <param name="userName">The username to connect using</param>
  270.         /// <param name="password">The password to connect using</param>
  271.         /// <param name="contextOptions">The options that are used to bind to the server</param>
  272.         public void Connect(string server, string container, string userName, string password, ContextOptions contextOptions)
  273.         {
  274.             Connect(server, container, userName, ToSecureString(password), contextOptions);
  275.         }
  276.  
  277.         /// <summary>
  278.         /// Connects to an Active Directory server specifying the username and password.
  279.         /// </summary>
  280.         /// <param name="server">The Active Directory server to connect to.</param>
  281.         /// <param name="container">The distinguished name of the container to bind to</param>
  282.         /// <param name="userName">The username to connect using</param>
  283.         /// <param name="password">The password to connect using</param>
  284.         /// <param name="contextOptions">The options that are used to bind to the server</param>
  285.         public void Connect(string server, string container, string userName, SecureString password, ContextOptions contextOptions)
  286.         {
  287.             this._Server = server;
  288.             this._Container = container;
  289.             this._UserName = userName;
  290.             this._Password = password;
  291.             this._ContextOptions = contextOptions;
  292.             this._ConnectedUsingPassword = true;
  293.             if (_ContextType != ContextType.Machine)
  294.             {
  295.                 Match match = Regex.Match(container, @"(DC\=.*)", RegexOptions.CultureInvariant);
  296.                 if (match.Groups.Count > 0)
  297.                 {
  298.                     _PrincipalContext = new PrincipalContext(this._ContextType, this._Server, match.Groups[0].Value, this._ContextOptions, this._UserName, ToInsecureString(this._Password));
  299.                     _DefaultPrincipal = ADUserPrincipal.FindOneByAttribute(_PrincipalContext, "sAMAccountName", "*");
  300.                     if (_DefaultPrincipal == null)
  301.                     {
  302.                         _DefaultPrincipal = ADGroupPrincipal.FindOneByAttribute(_PrincipalContext, "sAMAccountName", "*");
  303.                     }
  304.                     ChangeContainer(container);
  305.                 }
  306.                 else
  307.                 {
  308.                     _PrincipalContext = new PrincipalContext(this._ContextType, this._Server, this._Container, this._ContextOptions, this._UserName, ToInsecureString(this._Password));
  309.                     _DefaultPrincipal = ADUserPrincipal.FindOneByAttribute(_PrincipalContext, "sAMAccountName", "*");
  310.                     if (_DefaultPrincipal == null)
  311.                     {
  312.                         _DefaultPrincipal = ADGroupPrincipal.FindOneByAttribute(_PrincipalContext, "sAMAccountName", "*");
  313.                     }
  314.                 }
  315.             }
  316.             else
  317.             {
  318.                 _PrincipalContext = new PrincipalContext(this._ContextType, this._Server);
  319.             }
  320.  
  321.         }
  322.  
  323.         /// <summary>
  324.         /// Boolean value representing the connection state. Returns true if connected, false if not connected.
  325.         /// </summary>
  326.         public bool IsConnected
  327.         {
  328.             get
  329.             {
  330.                 bool result = false;
  331.                 if (_PrincipalContext != null && !String.IsNullOrEmpty(_PrincipalContext.ConnectedServer))
  332.                 {
  333.                     result = true;
  334.                 }
  335.                 return result;
  336.             }
  337.         }
  338.  
  339.         /// <summary>
  340.         /// Gets all of the DirectoryEntry objects in the current container.
  341.         /// </summary>
  342.         /// <returns>A List object containing the returned DirectoryEntry objects.</returns>
  343.         public List<DirectoryEntry> GetDirectoryEntries()
  344.         {
  345.             return GetDirectoryEntries(SchemaClass.Any, this._Container);
  346.         }
  347.  
  348.         /// <summary>
  349.         /// Gets all of the DirectoryEntry objects in the specified container.
  350.         /// </summary>
  351.         /// <param name="container">The distinguished name of the container to bind to</param>
  352.         /// <returns>A List object containing the returned DirectoryEntry objects.</returns>
  353.         public List<DirectoryEntry> GetDirectoryEntries(string container)
  354.         {
  355.             return GetDirectoryEntries(SchemaClass.Any, container);
  356.         }
  357.  
  358.         /// <summary>
  359.         /// Gets all of the DirectoryEntry objects in the current container that are in a particular SchemaClass.
  360.         /// </summary>
  361.         /// <param name="schemaClass">The SchemaClass to retrieve. The application can set multiple options that are linked with a bitwise OR operation.</param>
  362.         /// <returns>A List object containing the returned DirectoryEntry objects.</returns>
  363.         public List<DirectoryEntry> GetDirectoryEntries(SchemaClass schemaClass)
  364.         {
  365.             return GetDirectoryEntries(schemaClass, this._Container);
  366.         }
  367.  
  368.         /// <summary>
  369.         /// Gets all of the DirectoryEntry objects in the specified container that are in a particular SchemaClass.
  370.         /// </summary>
  371.         /// <param name="schemaClass">The SchemaClass to retrieve. The application can set multiple options that are linked with a bitwise OR operation.</param>
  372.         /// <param name="container">The distinguished name of the container to bind to</param>
  373.         /// <returns>A List object containing the returned DirectoryEntry objects.</returns>
  374.         public List<DirectoryEntry> GetDirectoryEntries(SchemaClass schemaClass, string container)
  375.         {
  376.             var entries = new List<DirectoryEntry>();
  377.             var principal = new UserPrincipal(_PrincipalContext);
  378.             var baseEntry = GetNewDirectoryEntry(container);
  379.  
  380.             foreach (DirectoryEntry entry in baseEntry.Children)
  381.             {
  382.                 if (schemaClass.HasFlag(SchemaClass.Any))
  383.                     entries.Add(entry);
  384.                 else if (schemaClass.HasFlag(SchemaClass.organizationalUnit) && entry.SchemaClassName == SchemaClass.organizationalUnit.ToString())
  385.                     entries.Add(entry);
  386.                 else if (schemaClass.HasFlag(SchemaClass.container) && entry.SchemaClassName == SchemaClass.container.ToString())
  387.                     entries.Add(entry);
  388.                 else if (schemaClass.HasFlag(SchemaClass.builtinDomain) && entry.SchemaClassName == SchemaClass.builtinDomain.ToString())
  389.                     entries.Add(entry);
  390.                 else if (schemaClass.HasFlag(SchemaClass.group) && entry.SchemaClassName == SchemaClass.group.ToString())
  391.                     entries.Add(entry);
  392.                 else if (schemaClass.HasFlag(SchemaClass.user) && entry.SchemaClassName == SchemaClass.user.ToString())
  393.                     entries.Add(entry);
  394.                 else if (schemaClass.HasFlag(SchemaClass.computer) && entry.SchemaClassName == SchemaClass.computer.ToString())
  395.                     entries.Add(entry);
  396.                 else if (schemaClass.HasFlag(SchemaClass.printer) && entry.SchemaClassName == SchemaClass.printer.ToString())
  397.                     entries.Add(entry);
  398.                 else if (schemaClass.HasFlag(SchemaClass.contact) && entry.SchemaClassName == SchemaClass.contact.ToString())
  399.                     entries.Add(entry);
  400.                 else if (schemaClass.HasFlag(SchemaClass.volume) && entry.SchemaClassName == SchemaClass.volume.ToString())
  401.                     entries.Add(entry);
  402.                 else if (schemaClass.HasFlag(SchemaClass.inetOrgPerson) && entry.SchemaClassName == SchemaClass.inetOrgPerson.ToString())
  403.                     entries.Add(entry);
  404.                 else if (schemaClass.HasFlag(SchemaClass.msExchDynamicDistributionList) && entry.SchemaClassName == SchemaClass.msExchDynamicDistributionList.ToString())
  405.                     entries.Add(entry);
  406.             }
  407.             return entries;
  408.         }
  409.  
  410.         /// <summary>
  411.         /// Change the current connection's container.
  412.         /// This will disconnect and reconnect to the Active Directory server.
  413.         /// </summary>
  414.         /// <param name="container">The distinguished name of the container to bind to</param>
  415.         public void ChangeContainer(string container)
  416.         {
  417.             if (this._ConnectedUsingPassword)
  418.             {
  419.                 _PrincipalContext = new PrincipalContext(this._ContextType, this._Server, container, this._ContextOptions, this._UserName, ToInsecureString(this._Password));
  420.             }
  421.             else
  422.             {
  423.                 _PrincipalContext = new PrincipalContext(this._ContextType, this._Server, container, this._ContextOptions);
  424.             }
  425.         }
  426.  
  427.         /// <summary>
  428.         /// Gets a new DirectoryEntry object with the connection information from the current connection.
  429.         /// The DirectoryEntry object will be bound to the current connection's container.
  430.         /// If there is no current connection to an Active Directory server, an ActiveDirectoryOperationException will be thrown.
  431.         /// NOTE: There must be at least one user or group object on the Active Directory server for this function to work.
  432.         /// </summary>
  433.         /// <param name="container">The distinguished name of the container to bind to</param>
  434.         /// <returns>A new DirectoryEntry object with connection information and container set</returns>
  435.         public DirectoryEntry GetNewDirectoryEntry()
  436.         {
  437.             return GetNewDirectoryEntry(_Container);
  438.         }
  439.  
  440.         /// <summary>
  441.         /// Gets a new DirectoryEntry object with the connection information from the current connection.
  442.         /// The DirectoryEntry object will be bound to the container specified.
  443.         /// If there is no current connection to an Active Directory server, an ActiveDirectoryOperationException will be thrown.
  444.         /// NOTE: There must be at least one user or group object on the Active Directory server for this function to work.
  445.         /// </summary>
  446.         /// <param name="container">The distinguished name of the container to bind to</param>
  447.         /// <returns>A new DirectoryEntry object with connection information and container set</returns>
  448.         public DirectoryEntry GetNewDirectoryEntry(string container)
  449.         {
  450.             if (!IsConnected)
  451.             {
  452.                 throw new ActiveDirectoryOperationException("There is no current connection to an Active Directory server.");
  453.             }
  454.  
  455.             if (_DefaultPrincipal == null)
  456.             {
  457.                 throw new ActiveDirectoryOperationException("The default principal object does not exist.");
  458.             }
  459.             var sourceEntry = (DirectoryEntry)_DefaultPrincipal.GetUnderlyingObject();
  460.  
  461.             DirectoryEntry destinationEntry = new DirectoryEntry();
  462.             if (_ConnectedUsingPassword)
  463.             {
  464.                 destinationEntry.AuthenticationType = sourceEntry.AuthenticationType;
  465.                 destinationEntry.Username = this._UserName;
  466.                 destinationEntry.Password = ToInsecureString(this._Password);
  467.             }
  468.             else
  469.             {
  470.                 destinationEntry.AuthenticationType = sourceEntry.AuthenticationType;
  471.             }
  472.             string pathPrefix = String.Empty;
  473.             if (this._ContextType == ContextType.Domain || this._ContextType == ContextType.ApplicationDirectory)
  474.             {
  475.                 pathPrefix = "LDAP://";
  476.             }
  477.             else if (this._ContextType == ContextType.Machine)
  478.             {
  479.                 pathPrefix = "WinNT://";
  480.             }
  481.             string separator = "/";
  482.             if (String.IsNullOrEmpty(container))
  483.             {
  484.                 separator = "";
  485.             }
  486.  
  487.             destinationEntry.Path = pathPrefix + this._Server + separator + container;
  488.  
  489.             return destinationEntry;
  490.         }
  491.  
  492.         /// <summary>
  493.         /// Moves a Principal to a different container.
  494.         /// If there is no current connection to an Active Directory server, an ActiveDirectoryOperationException will be thrown.
  495.         /// </summary>
  496.         /// <param name="principal">The Principal to move.</param>
  497.         /// <param name="container">The distinguished name of the new container.</param>
  498.         public void MovePrincipal(Principal principal, string container)
  499.         {
  500.             if (!IsConnected)
  501.             {
  502.                 throw new ActiveDirectoryOperationException("There is no current connection to an Active Directory server.");
  503.             }
  504.             DirectoryEntry sourceEntry = (DirectoryEntry)principal.GetUnderlyingObject();
  505.             DirectoryEntry destinationEntry = GetNewDirectoryEntry(container);
  506.             sourceEntry.MoveTo(destinationEntry);
  507.         }
  508.  
  509.         /// <summary>
  510.         /// Returns the NetBIOS name of the Active Directory domain that is currently connected.
  511.         /// If there is no current connection to an Active Directory server, an ActiveDirectoryOperationException will be thrown.
  512.         /// </summary>
  513.         public string NetBiosName
  514.         {
  515.             get
  516.             {
  517.                 if (!IsConnected)
  518.                 {
  519.                     throw new ActiveDirectoryOperationException("There is no current connection to an Active Directory server.");
  520.                 }
  521.                 DirectoryEntry rootDse = GetNewDirectoryEntry("RootDSE");
  522.  
  523.                 string configurationNamingContext = rootDse.Properties["configurationNamingContext"][0].ToString();
  524.                 string rootDomainName = rootDse.Properties["ldapServiceName"][0].ToString().Split(':')[0];
  525.  
  526.                 DirectoryEntry searchRoot = GetNewDirectoryEntry("cn=Partitions," + configurationNamingContext);
  527.  
  528.                 DirectorySearcher searcher = new DirectorySearcher(searchRoot);
  529.                 searcher.SearchScope = SearchScope.OneLevel;
  530.                 searcher.PropertiesToLoad.Add("nETBIOSName");
  531.                 searcher.Filter = string.Format("(&(objectcategory=Crossref)(dnsRoot={0})(nETBIOSName=*))", rootDomainName);
  532.  
  533.                 SearchResult result = searcher.FindOne();
  534.  
  535.                 if (result != null)
  536.                     return result.Properties["nETBIOSName"][0].ToString();
  537.                 else
  538.                     return null;
  539.             }
  540.         }
  541.  
  542.         /// <summary>
  543.         /// Returns the root DNS domain name of the Active Directory domain that is currently connected.
  544.         /// If there is no current connection to an Active Directory server, an ActiveDirectoryOperationException will be thrown.
  545.         /// </summary>
  546.         public string DnsDomainName
  547.         {
  548.             get
  549.             {
  550.                 if (!IsConnected)
  551.                 {
  552.                     throw new ActiveDirectoryOperationException("There is no current connection to an Active Directory server.");
  553.                 }
  554.                 DirectoryEntry rootDse = GetNewDirectoryEntry("RootDSE");
  555.  
  556.                 string rootDomainName = rootDse.Properties["ldapServiceName"][0].ToString().Split(':')[0];
  557.  
  558.                 return rootDomainName;
  559.             }
  560.         }
  561.  
  562.         /// <summary>
  563.         /// Creates the connections to the server and returns a Boolean value that specifies
  564.         /// whether the specified username and password are valid.
  565.         /// </summary>
  566.         /// <param name="userName">The username that is validated on the server.</param>
  567.         /// <param name="password">The password that is validated on the server.</param>
  568.         /// <returns>true if the credentials are valid; otherwise false.</returns>
  569.         public bool ValidateCredentials(string userName, string password)
  570.         {
  571.             return _PrincipalContext.ValidateCredentials(userName, password);
  572.         }
  573.  
  574.         /// <summary>
  575.         /// Creates the connections to the server and returns a Boolean value that specifies
  576.         /// whether the specified username and password are valid.
  577.         /// </summary>
  578.         /// <param name="userName">The username that is validated on the server.</param>
  579.         /// <param name="password">The password that is validated on the server.</param>
  580.         /// <param name="principal">The ADUserPrincipal of the user that was validated. If validation fails, this object will be null.</param>
  581.         /// <returns>true if the credentials are valid; otherwise false.</returns>
  582.         public bool ValidateCredentials(string userName, string password, out ADUserPrincipal principal)
  583.         {
  584.             string resultText = String.Empty;
  585.             return ValidateCredentials(userName, password, out principal, out resultText);
  586.         }
  587.  
  588.         /// <summary>
  589.         /// Creates the connections to the server and returns a Boolean value that specifies
  590.         /// whether the specified username and password are valid.
  591.         /// </summary>
  592.         /// <param name="userName">The username that is validated on the server.</param>
  593.         /// <param name="password">The password that is validated on the server.</param>
  594.         /// <param name="principal">The ADUserPrincipal of the user that was validated. If validation fails, this object will be null.</param>
  595.         /// <param name="resultText">A text string with the result of the validation.</param>
  596.         /// <returns>true if the credentials are valid; otherwise false.</returns>
  597.         public bool ValidateCredentials(string userName, string password, out ADUserPrincipal principal, out string resultText)
  598.         {
  599.             bool result = false;
  600.             principal = null;
  601.             resultText = string.Empty;
  602.  
  603.             //Always check the return result to verify the full validation of the user.
  604.  
  605.             try
  606.             {
  607.                 principal = ADUserPrincipal.FindByIdentity(_PrincipalContext, IdentityType.SamAccountName, userName);
  608.             }
  609.             catch
  610.             {
  611.                 result = false;
  612.                 principal = null;
  613.                 resultText = "Failed to query user!";
  614.                 return result;
  615.             }
  616.  
  617.             if (principal == null)
  618.             {
  619.                 result = false;
  620.                 resultText = "User does not exist!";
  621.                 return result;
  622.             }
  623.  
  624.             try
  625.             {
  626.                 result = _PrincipalContext.ValidateCredentials(userName, password);
  627.             }
  628.             catch
  629.             {
  630.                 result = false;
  631.                 principal = null;
  632.                 resultText = "Failed to validate user credentials!";
  633.                 return result;
  634.             }
  635.  
  636.             if (result == false)
  637.             {
  638.                 resultText = "Invalid Password!";
  639.                 return result;
  640.             }
  641.  
  642.             result = true;
  643.             resultText = "User Validated!";
  644.             return result;
  645.         }
  646.  
  647.         /// <summary>
  648.         /// Converts a SecureString to a String
  649.         /// </summary>
  650.         /// <param name="input">SecureString to convert</param>
  651.         /// <returns>String containing the value of the SecureString input</returns>
  652.         public static string ToInsecureString(SecureString input)
  653.         {
  654.             if (input == null)
  655.                 return null;
  656.  
  657.             IntPtr unmanagedString = IntPtr.Zero;
  658.             try
  659.             {
  660.                 unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(input);
  661.                 return Marshal.PtrToStringUni(unmanagedString);
  662.             }
  663.             finally
  664.             {
  665.                 Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
  666.             }
  667.         }
  668.  
  669.         /// <summary>
  670.         /// Converts a String to a SecureString
  671.         /// </summary>
  672.         /// <param name="input">String to convert</param>
  673.         /// <returns>SecureString containing the value of the input String</returns>
  674.         public static SecureString ToSecureString(string input)
  675.         {
  676.             if (input == null)
  677.             {
  678.                 return null;
  679.             }
  680.             else
  681.             {
  682.                 var output = new SecureString();
  683.                 input.ToList().ForEach(output.AppendChar);
  684.                 return output;
  685.             }
  686.         }
  687.     }
  688.  
  689. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement