Example #1
0
 protected static string StringConverter(FilterBase filter, string suggestedAdProperty)
 {
     return(filter.Value != null ?
            $"({suggestedAdProperty}={ADUtils.PAPIQueryToLdapQueryString((string)filter.Value)})" :
            $"(!({suggestedAdProperty}=*))");
 }
Example #2
0
        private void DoLDAPDirectoryInitNoContainer()
        {
            byte[] USERS_CONTAINER_GUID     = new byte[] { 0xa9, 0xd1, 0xca, 0x15, 0x76, 0x88, 0x11, 0xd1, 0xad, 0xed, 0x00, 0xc0, 0x4f, 0xd8, 0xd5, 0xcd };
            byte[] COMPUTERS_CONTAINER_GUID = new byte[] { 0xaa, 0x31, 0x28, 0x25, 0x76, 0x88, 0x11, 0xd1, 0xad, 0xed, 0x00, 0xc0, 0x4f, 0xd8, 0xd5, 0xcd };

            // The StoreCtxs that will be used in the PrincipalContext, and their associated DirectoryEntry objects.
            DirectoryEntry deUserGroupOrg = null;
            DirectoryEntry deComputer     = null;
            DirectoryEntry deBase         = null;

            ADStoreCtx storeCtxUserGroupOrg = null;
            ADStoreCtx storeCtxComputer     = null;
            ADStoreCtx storeCtxBase         = null;

            GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "Entering DoLDAPDirectoryInitNoContainer");

            //
            // Build a DirectoryEntry that represents the root of the domain.
            //

            // Use the RootDSE to find the default naming context
            DirectoryEntry deRootDse = null;
            string         adsPathBase;

            // use the servername if they gave us one, else let ADSI figure it out
            string serverName = "";

            if (_name != null)
            {
                serverName = _name + "/";
            }

            GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInitNoContainer: serverName is " + serverName);

            // use the options they specified
            AuthenticationTypes authTypes = SDSUtils.MapOptionsToAuthTypes(_options);

            GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInitNoContainer: authTypes is " + authTypes.ToString());

            try
            {
                deRootDse = new DirectoryEntry("LDAP://" + serverName + "rootDse", _username, _password, authTypes);

                // This will also detect if the server is down or nonexistent
                string domainNC = (string)deRootDse.Properties["defaultNamingContext"][0];
                adsPathBase = "LDAP://" + serverName + domainNC;

                GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInitNoContainer: domainNC is " + domainNC);
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInitNoContainer: adsPathBase is " + adsPathBase);
            }
            finally
            {
                // Don't allow the DE to leak
                if (deRootDse != null)
                {
                    deRootDse.Dispose();
                }
            }

            try
            {
                // Build a DE for the root of the domain using the retrieved naming context
                deBase = new DirectoryEntry(adsPathBase, _username, _password, authTypes);

                // Set the password port to the ssl port read off of the rootDSE.  Without this
                // password change/set won't work when we connect without SSL and ADAM is running
                // on non-standard port numbers.  We have already verified directory connectivity at this point
                // so this should always succeed.
                if (_serverProperties.portSSL > 0)
                {
                    deBase.Options.PasswordPort = _serverProperties.portSSL;
                }

                //
                // Use the wellKnownObjects attribute to determine the default location
                // for users and computers.
                //
                string adsPathUserGroupOrg = null;
                string adsPathComputer     = null;

                PropertyValueCollection wellKnownObjectValues = deBase.Properties["wellKnownObjects"];

                foreach (UnsafeNativeMethods.IADsDNWithBinary value in wellKnownObjectValues)
                {
                    if (Utils.AreBytesEqual(USERS_CONTAINER_GUID, (byte[])value.BinaryValue))
                    {
                        Debug.Assert(adsPathUserGroupOrg == null);
                        adsPathUserGroupOrg = "LDAP://" + serverName + value.DNString;

                        GlobalDebug.WriteLineIf(
                            GlobalDebug.Info,
                            "PrincipalContext",
                            "DoLDAPDirectoryInitNoContainer: found USER, adsPathUserGroupOrg is " + adsPathUserGroupOrg);
                    }

                    // Is it the computer container?
                    if (Utils.AreBytesEqual(COMPUTERS_CONTAINER_GUID, (byte[])value.BinaryValue))
                    {
                        Debug.Assert(adsPathComputer == null);
                        adsPathComputer = "LDAP://" + serverName + value.DNString;

                        GlobalDebug.WriteLineIf(
                            GlobalDebug.Info,
                            "PrincipalContext",
                            "DoLDAPDirectoryInitNoContainer: found COMPUTER, adsPathComputer is " + adsPathComputer);
                    }
                }

                if ((adsPathUserGroupOrg == null) || (adsPathComputer == null))
                {
                    // Something's wrong with the domain, it's not exposing the proper
                    // well-known object fields.
                    throw new PrincipalOperationException(SR.ContextNoWellKnownObjects);
                }

                //
                // Build DEs for the Users and Computers containers.
                // The Users container will also be used as the default for Groups.
                // The reason there are different contexts for groups, users and computers is so that
                // when a principal is created it will go into the appropriate default container.  This is so users don't
                // be default create principals in the root of their directory.  When a search happens the base context is used so that
                // the whole directory will be covered.
                //
                deUserGroupOrg = new DirectoryEntry(adsPathUserGroupOrg, _username, _password, authTypes);
                deComputer     = new DirectoryEntry(adsPathComputer, _username, _password, authTypes);

                StoreCtx userStore = CreateContextFromDirectoryEntry(deUserGroupOrg);

                _userCtx       = userStore;
                _groupCtx      = userStore;
                deUserGroupOrg = null;  // since we handed off ownership to the StoreCtx

                _computerCtx = CreateContextFromDirectoryEntry(deComputer);

                deComputer = null;

                _queryCtx = CreateContextFromDirectoryEntry(deBase);

                _connectedServer = ADUtils.GetServerName(deBase);

                deBase = null;
            }
            catch (Exception e)
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Error,
                                        "PrincipalContext",
                                        "DoLDAPDirectoryInitNoContainer: caught exception of type "
                                        + e.GetType().ToString() +
                                        " and message " + e.Message);

                // Cleanup on failure.  Once a DE has been successfully handed off to a ADStoreCtx,
                // that ADStoreCtx will handle Dispose()'ing it
                if (deUserGroupOrg != null)
                {
                    deUserGroupOrg.Dispose();
                }

                if (deComputer != null)
                {
                    deComputer.Dispose();
                }

                if (deBase != null)
                {
                    deBase.Dispose();
                }

                if (storeCtxUserGroupOrg != null)
                {
                    storeCtxUserGroupOrg.Dispose();
                }

                if (storeCtxComputer != null)
                {
                    storeCtxComputer.Dispose();
                }

                if (storeCtxBase != null)
                {
                    storeCtxBase.Dispose();
                }

                throw;
            }
        }
Example #3
0
        // Must be called inside of lock(domainInfoLock)
        override protected void LoadDomainInfo()
        {
            GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadComputerInfo");

            Debug.Assert(this.ctxBase != null);

            //
            // DNS Domain Name
            //
            this.dnsHostName = ADUtils.GetServerName(this.ctxBase);
            // Treat the user supplied server name as the domain and forest name...
            this.domainFlatName = userSuppliedServerName;
            this.forestDnsName  = userSuppliedServerName;
            this.domainDnsName  = userSuppliedServerName;

            //
            // Find the partition in which the supplied ctxBase belongs by comparing it with the list of partitions hosted by this
            // LDS (ADAM) instance.
            //
            using (DirectoryEntry rootDse = new DirectoryEntry("LDAP://" + this.userSuppliedServerName + "/rootDse", "", "", AuthenticationTypes.Anonymous))
            {
                string ctxBaseDN      = (string)this.ctxBase.Properties["distinguishedName"][0];
                int    maxMatchLength = -1;
                foreach (string partitionDN in rootDse.Properties["namingContexts"])
                {
                    if ((partitionDN.Length > maxMatchLength) && ctxBaseDN.EndsWith(partitionDN, StringComparison.OrdinalIgnoreCase))
                    {
                        maxMatchLength = partitionDN.Length;
                        this.contextBasePartitionDN = partitionDN;
                    }
                }
            }

            //
            // User supplied name
            //
            UnsafeNativeMethods.Pathname     pathCracker = new UnsafeNativeMethods.Pathname();
            UnsafeNativeMethods.IADsPathname pathName    = (UnsafeNativeMethods.IADsPathname)pathCracker;

            pathName.Set(this.ctxBase.Path, 1 /* ADS_SETTYPE_FULL */);

            try
            {
                this.userSuppliedServerName = pathName.Retrieve(9 /*ADS_FORMAT_SERVER */);
                GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadComputerInfo: using user-supplied name {0}", this.userSuppliedServerName);
            }
            catch (COMException e)
            {
                if (((uint)e.ErrorCode) == ((uint)0x80005000))  // E_ADS_BAD_PATHNAME
                {
                    // Serverless path
                    GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "LoadComputerInfo: using empty string as user-supplied name");
                    this.userSuppliedServerName = "";
                }
                else
                {
                    GlobalDebug.WriteLineIf(GlobalDebug.Error,
                                            "ADStoreCtx",
                                            "LoadComputerInfo: caught COMException {0} {1} looking for user-supplied name",
                                            e.ErrorCode,
                                            e.Message);

                    throw;
                }
            }
        }
Example #4
0
        private void DoLDAPDirectoryInit()
        {
            // use the servername if they gave us one, else let ADSI figure it out
            string serverName = "";

            if (_name != null)
            {
                if (_contextType == ContextType.ApplicationDirectory)
                {
                    serverName = _serverProperties.dnsHostName + ":" +
                                 ((ContextOptions.SecureSocketLayer & _options) > 0 ? _serverProperties.portSSL : _serverProperties.portLDAP);
                }
                else
                {
                    serverName = _name;
                }

                serverName += "/";
            }

            GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInit: serverName is " + serverName);

            // use the options they specified
            AuthenticationTypes authTypes = SDSUtils.MapOptionsToAuthTypes(_options);

            GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "DoLDAPDirectoryInit: authTypes is " + authTypes.ToString());

            DirectoryEntry de = new DirectoryEntry("LDAP://" + serverName + _container, _username, _password, authTypes);

            try
            {
                // Set the password port to the ssl port read off of the rootDSE.  Without this
                // password change/set won't work when we connect without SSL and ADAM is running
                // on non-standard port numbers.  We have already verified directory connectivity at this point
                // so this should always succeed.
                if (_serverProperties.portSSL > 0)
                {
                    de.Options.PasswordPort = _serverProperties.portSSL;
                }

                StoreCtx storeCtx = CreateContextFromDirectoryEntry(de);

                _queryCtx    = storeCtx;
                _userCtx     = storeCtx;
                _groupCtx    = storeCtx;
                _computerCtx = storeCtx;

                _connectedServer = ADUtils.GetServerName(de);
                de = null;
            }
            catch (System.Runtime.InteropServices.COMException e)
            {
                throw ExceptionHelper.GetExceptionFromCOMException(e);
            }
            catch (Exception e)
            {
                GlobalDebug.WriteLineIf(GlobalDebug.Error, "PrincipalContext",
                                        "DoLDAPDirectoryInit: caught exception of type "
                                        + e.GetType().ToString() +
                                        " and message " + e.Message);

                throw;
            }
            finally
            {
                // Cleanup the DE on failure
                if (de != null)
                {
                    de.Dispose();
                }
            }
        }
Example #5
0
 private static bool IsOfObjectClass(SearchResult sr, string className)
 {
     Debug.Assert(sr.Path.StartsWith("LDAP:", StringComparison.Ordinal) || sr.Path.StartsWith("GC:", StringComparison.Ordinal));
     return(ADUtils.IsOfObjectClass(sr, className));
 }
Example #6
0
 internal static string SecurityIdentifierToLdapHexFilterString(SecurityIdentifier sid)
 {
     return(ADUtils.HexStringToLdapHexString(Utils.SecurityIdentifierToLdapHexBindingString(sid)));
 }
Example #7
0
 internal static Principal DirectoryEntryAsPrincipal(DirectoryEntry de, ADStoreCtx storeCtx)
 {
     if (ADUtils.IsOfObjectClass(de, "computer") || ADUtils.IsOfObjectClass(de, "user") || ADUtils.IsOfObjectClass(de, "group"))
     {
         return(storeCtx.GetAsPrincipal(de, null));
     }
     else
     {
         if (!ADUtils.IsOfObjectClass(de, "foreignSecurityPrincipal"))
         {
             return(storeCtx.GetAsPrincipal(de, null));
         }
         else
         {
             return(storeCtx.ResolveCrossStoreRefToPrincipal(de));
         }
     }
 }
Example #8
0
 internal static Principal SearchResultAsPrincipal(SearchResult sr, ADStoreCtx storeCtx, object discriminant)
 {
     if (ADUtils.IsOfObjectClass(sr, "computer") || ADUtils.IsOfObjectClass(sr, "user") || ADUtils.IsOfObjectClass(sr, "group"))
     {
         return(storeCtx.GetAsPrincipal(sr, discriminant));
     }
     else
     {
         if (!ADUtils.IsOfObjectClass(sr, "foreignSecurityPrincipal"))
         {
             return(storeCtx.GetAsPrincipal(sr, discriminant));
         }
         else
         {
             return(storeCtx.ResolveCrossStoreRefToPrincipal(sr.GetDirectoryEntry()));
         }
     }
 }