protected static string StringConverter(FilterBase filter, string suggestedAdProperty) { return(filter.Value != null ? $"({suggestedAdProperty}={ADUtils.PAPIQueryToLdapQueryString((string)filter.Value)})" : $"(!({suggestedAdProperty}=*))"); }
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; } }
// 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; } } }
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(); } } }
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)); }
internal static string SecurityIdentifierToLdapHexFilterString(SecurityIdentifier sid) { return(ADUtils.HexStringToLdapHexString(Utils.SecurityIdentifierToLdapHexBindingString(sid))); }
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)); } } }
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())); } } }