private bool IsOfCorrectType(DirectoryEntry de) { bool flag; List <string> .Enumerator enumerator = this.schemaTypes.GetEnumerator(); try { while (enumerator.MoveNext()) { string current = enumerator.Current; if (!SAMUtils.IsOfObjectClass(de, current)) { continue; } flag = true; return(flag); } return(false); } finally { enumerator.Dispose(); } return(flag); }
static internal Principal DirectoryEntryAsPrincipal(DirectoryEntry de, StoreCtx storeCtx) { string className = de.SchemaClassName; // Unlike AD, we don't have to worry about cross-store refs here. In AD, if there's // a cross-store ref, we'll get back a DirectoryEntry of the FPO object. In the WinNT ADSI // provider, we'll get back the DirectoryEntry of the remote object itself --- ADSI does // the domain vs. local resolution for us. if (SAMUtils.IsOfObjectClass(de, "Computer") || SAMUtils.IsOfObjectClass(de, "User") || SAMUtils.IsOfObjectClass(de, "Group")) { return(storeCtx.GetAsPrincipal(de, null)); } else { Debug.Fail(String.Format( CultureInfo.CurrentCulture, "SAMUtils.DirectoryEntryAsPrincipal: fell off end, Path={0}, SchemaClassName={1}", de.Path, de.SchemaClassName)); return(null); } }
private static bool IsOfObjectClass(DirectoryEntry de, string className) { if (!de.Path.StartsWith("WinNT:", StringComparison.Ordinal)) { return(ADUtils.IsOfObjectClass(de, className)); } else { return(SAMUtils.IsOfObjectClass(de, className)); } }
internal static Principal DirectoryEntryAsPrincipal(DirectoryEntry de, StoreCtx storeCtx) { if (SAMUtils.IsOfObjectClass(de, "Computer") || SAMUtils.IsOfObjectClass(de, "User") || SAMUtils.IsOfObjectClass(de, "Group")) { return(storeCtx.GetAsPrincipal(de, null)); } else { return(null); } }
private static bool WildcardStringMatch(FilterBase filter, string wildcardFilter, string property) { Regex extra = filter.Extra as Regex; if (extra == null) { extra = new Regex(SAMUtils.PAPIQueryToRegexString(wildcardFilter), RegexOptions.Singleline); filter.Extra = extra; } Match match = extra.Match(property); return(match.Success); }
private bool IsOfCorrectType(DirectoryEntry de) { // Is the object in question one of the desired types? foreach (string schemaType in _schemaTypes) { if (SAMUtils.IsOfObjectClass(de, schemaType)) { return(true); } } return(false); }
// Throws exception if ctxBase is not a computer object public SAMStoreCtx(DirectoryEntry ctxBase, bool ownCtxBase, string username, string password, ContextOptions options) { Debug.Assert(ctxBase != null); GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Constructing SAMStoreCtx for {0}", ctxBase.Path); Debug.Assert(SAMUtils.IsOfObjectClass(ctxBase, "Computer")); _ctxBase = ctxBase; _ownCtxBase = ownCtxBase; if (username != null && password != null) { _credentials = new NetCred(username, password); } _contextOptions = options; _authTypes = SDSUtils.MapOptionsToAuthTypes(options); }
// // Conversion routines // private static bool WildcardStringMatch(FilterBase filter, string wildcardFilter, string property) { // Build a Regex that matches valueToMatch, and store it on the Filter (so that we don't have // to have the CLR constantly reparse the regex string). // Ideally, we'd like to use a compiled Regex (RegexOptions.Compiled) for performance, // but the CLR cannot release generated MSIL. Thus, our memory usage would grow without bound // each time a query was performed. Regex regex = filter.Extra as Regex; if (regex == null) { regex = new Regex(SAMUtils.PAPIQueryToRegexString(wildcardFilter), RegexOptions.Singleline); filter.Extra = regex; } return(regex.IsMatch(property)); }
internal static bool GetOSVersion(DirectoryEntry computerDE, out int versionMajor, out int versionMinor) { Debug.Assert(SAMUtils.IsOfObjectClass(computerDE, "Computer")); versionMajor = 0; versionMinor = 0; string version = null; try { if (computerDE.Properties["OperatingSystemVersion"].Count > 0) { Debug.Assert(computerDE.Properties["OperatingSystemVersion"].Count == 1); version = (string)computerDE.Properties["OperatingSystemVersion"].Value; } } catch (COMException e) { GlobalDebug.WriteLineIf(GlobalDebug.Error, "SAMUtils", "GetOSVersion: caught COMException with message " + e.Message); // Couldn't retrieve the value if (e.ErrorCode == unchecked ((int)0x80070035)) // ERROR_BAD_NETPATH { return(false); } throw; } // Couldn't retrieve the value if (version == null || version.Length == 0) { return(false); } // This string should be in the form "M.N", where M and N are integers. // We'll also accept "M", which we'll treat as "M.0". // // We'll split the string into its period-separated components, and parse // each component into an int. string[] versionComponents = version.Split(new char[] { '.' }); Debug.Assert(versionComponents.Length >= 1); // since version was a non-empty string try { versionMajor = Int32.Parse(versionComponents[0], CultureInfo.InvariantCulture); if (versionComponents.Length > 1) { versionMinor = Int32.Parse(versionComponents[1], CultureInfo.InvariantCulture); } // Sanity check: there are no negetive OS versions, nor is there a version "0". if (versionMajor <= 0 || versionMinor < 0) { Debug.Fail(String.Format( CultureInfo.CurrentCulture, "SAMUtils.GetOSVersion: {0} claims to have negetive OS version, {1}", computerDE.Path, version)); return(false); } } catch (FormatException) { Debug.Fail(String.Format( CultureInfo.CurrentCulture, "SAMUtils.GetOSVersion: FormatException on {0} for {1}", version, computerDE.Path)); return(false); } catch (OverflowException) { Debug.Fail(String.Format( CultureInfo.CurrentCulture, "SAMUtils.GetOSVersion: OverflowException on {0} for {1}", version, computerDE.Path)); return(false); } return(true); }
// computerInfoLock must be held coming in here private void LoadComputerInfo() { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo"); Debug.Assert(_ctxBase != null); Debug.Assert(SAMUtils.IsOfObjectClass(_ctxBase, "Computer")); // // Target OS version // int versionMajor; int versionMinor; if (!SAMUtils.GetOSVersion(_ctxBase, out versionMajor, out versionMinor)) { throw new PrincipalOperationException(SR.SAMStoreCtxUnableToRetrieveVersion); } Debug.Assert(versionMajor > 0); Debug.Assert(versionMinor >= 0); if (versionMajor >= 6) // 6.0 == Longhorn { _isLSAM = true; } else { _isLSAM = false; } GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo: ver={0}.{1}", versionMajor, versionMinor); // // Machine user-supplied name // // This ADSI property stores the machine name as supplied by the user in the ADsPath. // It could be a flat name or a DNS name. if (_ctxBase.Properties["Name"].Count > 0) { Debug.Assert(_ctxBase.Properties["Name"].Count == 1); _machineUserSuppliedName = (string)_ctxBase.Properties["Name"].Value; GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo: machineUserSuppliedName={0}", _machineUserSuppliedName); } else { throw new PrincipalOperationException(SR.SAMStoreCtxUnableToRetrieveMachineName); } // // Machine flat name // IntPtr buffer = IntPtr.Zero; try { // This function takes in a flat or DNS name, and returns the flat name of the computer int err = UnsafeNativeMethods.NetWkstaGetInfo(_machineUserSuppliedName, 100, ref buffer); if (err == 0) { UnsafeNativeMethods.WKSTA_INFO_100 wkstaInfo = (UnsafeNativeMethods.WKSTA_INFO_100)Marshal.PtrToStructure(buffer, typeof(UnsafeNativeMethods.WKSTA_INFO_100)); _machineFlatName = wkstaInfo.wki100_computername; GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "LoadComputerInfo: machineFlatName={0}", _machineFlatName); } else { throw new PrincipalOperationException( SR.Format( SR.SAMStoreCtxUnableToRetrieveFlatMachineName, err)); } } finally { if (buffer != IntPtr.Zero) { UnsafeNativeMethods.NetApiBufferFree(buffer); } } }
private bool MoveNextLocal() { bool needToRetry; do { needToRetry = false; bool f = _membersEnumerator.MoveNext(); if (f) // got a value { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: got a value from the enumerator"); UnsafeNativeMethods.IADs nativeMember = (UnsafeNativeMethods.IADs)_membersEnumerator.Current; // If we encountered a group member corresponding to a fake principal such as // NT AUTHORITY/NETWORK SERVICE, construct and prepare to return the fake principal. byte[] sid = (byte[])nativeMember.Get("objectSid"); SidType sidType = Utils.ClassifySID(sid); if (sidType == SidType.FakeObject) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: fake principal, sid={0}", Utils.ByteArrayToString(sid)); _currentFakePrincipal = _storeCtx.ConstructFakePrincipalFromSID(sid); _current = null; _currentForeign = null; if (_foreignResultSet != null) { _foreignResultSet.Dispose(); } _foreignResultSet = null; return(true); } // We do this, rather than using the DirectoryEntry constructor that takes a native IADs object, // is so the credentials get transferred to the new DirectoryEntry. If we just use the native // object constructor, the native object will have the right credentials, but the DirectoryEntry // will have default (null) credentials, which it'll use anytime it needs to use credentials. DirectoryEntry de = SDSUtils.BuildDirectoryEntry( _storeCtx.Credentials, _storeCtx.AuthTypes); if (sidType == SidType.RealObjectFakeDomain) { // Transform the "WinNT://BUILTIN/foo" path to "WinNT://machineName/foo" string builtinADsPath = nativeMember.ADsPath; UnsafeNativeMethods.Pathname pathCracker = new UnsafeNativeMethods.Pathname(); UnsafeNativeMethods.IADsPathname pathName = (UnsafeNativeMethods.IADsPathname)pathCracker; pathName.Set(builtinADsPath, 1 /* ADS_SETTYPE_FULL */); // Build the "WinNT://" portion of the new path StringBuilder adsPath = new StringBuilder(); adsPath.Append("WinNT://"); //adsPath.Append(pathName.Retrieve(9 /*ADS_FORMAT_SERVER */)); // Build the "WinNT://machineName/" portion of the new path adsPath.Append(_storeCtx.MachineUserSuppliedName); adsPath.Append('/'); // Build the "WinNT://machineName/foo" portion of the new path int cElements = pathName.GetNumElements(); Debug.Assert(cElements >= 2); // "WinNT://BUILTIN/foo" == 2 elements // Note that the ADSI WinNT provider indexes them backwards, e.g., in // "WinNT://BUILTIN/A/B", BUILTIN == 2, A == 1, B == 0. for (int i = cElements - 2; i >= 0; i--) { adsPath.Append(pathName.GetElement(i)); adsPath.Append('/'); } adsPath.Remove(adsPath.Length - 1, 1); // remove the trailing "/" de.Path = adsPath.ToString(); GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: fake domain: {0} --> {1}", builtinADsPath, adsPath); } else { Debug.Assert(sidType == SidType.RealObject); de.Path = nativeMember.ADsPath; GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: real domain {0}", de.Path); } // Debug.Assert(Utils.AreBytesEqual(sid, (byte[]) de.Properties["objectSid"].Value)); if (IsLocalMember(sid)) { // If we're processing recursively, and the member is a group, // we don't return it but instead treat it as something to recursively // visit (expand) later. if (!_recursive || !SAMUtils.IsOfObjectClass(de, "Group")) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: setting current to {0}", de.Path); // Not recursive, or not a group. Return the principal. _current = de; _currentFakePrincipal = null; _currentForeign = null; if (_foreignResultSet != null) { _foreignResultSet.Dispose(); } _foreignResultSet = null; return(true); } else { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: adding {0} to groupsToVisit", de.Path); // Save off for later, if we haven't done so already. if (!_groupsVisited.Contains(de.Path) && !_groupsToVisit.Contains(de.Path)) { _groupsToVisit.Add(de.Path); } needToRetry = true; continue; } } else { // It's a foreign principal (e..g, an AD user or group). // Save it off for later. GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: adding {0} to foreignMembers", de.Path); _foreignMembers.Add(de); needToRetry = true; continue; } } else { // We reached the end of this group's membership. // If we're supposed to be recursively expanding, we need to expand // any remaining non-foreign groups we earlier visited. if (_recursive) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: recursive processing, groupsToVisit={0}", _groupsToVisit.Count); if (_groupsToVisit.Count > 0) { // Pull off the next group to visit string groupPath = _groupsToVisit[0]; GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMMembersSet", "MoveNextLocal: recursively processing {0}", groupPath); _groupsToVisit.RemoveAt(0); _groupsVisited.Add(groupPath); // Set up for the next round of enumeration DirectoryEntry de = SDSUtils.BuildDirectoryEntry( groupPath, _storeCtx.Credentials, _storeCtx.AuthTypes); _group = (UnsafeNativeMethods.IADsGroup)de.NativeObject; UnsafeNativeMethods.IADsMembers iADsMembers = _group.Members(); _membersEnumerator = ((IEnumerable)iADsMembers).GetEnumerator(); // and go on to the first member of this new group needToRetry = true; continue; } } } }while (needToRetry); return(false); }
private bool MoveNextLocal() { bool flag; do { flag = false; bool flag1 = this.membersEnumerator.MoveNext(); if (!flag1) { if (!this.recursive || this.groupsToVisit.Count <= 0) { continue; } string item = this.groupsToVisit[0]; this.groupsToVisit.RemoveAt(0); this.groupsVisited.Add(item); DirectoryEntry directoryEntry = SDSUtils.BuildDirectoryEntry(item, this.storeCtx.Credentials, this.storeCtx.AuthTypes); this.@group = (UnsafeNativeMethods.IADsGroup)directoryEntry.NativeObject; UnsafeNativeMethods.IADsMembers aDsMember = [email protected](); this.membersEnumerator = ((IEnumerable)aDsMember).GetEnumerator(); flag = true; } else { UnsafeNativeMethods.IADs current = (UnsafeNativeMethods.IADs) this.membersEnumerator.Current; byte[] numArray = (byte[])current.Get("objectSid"); SidType sidType = Utils.ClassifySID(numArray); if (sidType != SidType.FakeObject) { DirectoryEntry aDsPath = SDSUtils.BuildDirectoryEntry(this.storeCtx.Credentials, this.storeCtx.AuthTypes); if (sidType != SidType.RealObjectFakeDomain) { aDsPath.Path = current.ADsPath; } else { string str = current.ADsPath; UnsafeNativeMethods.Pathname pathname = new UnsafeNativeMethods.Pathname(); UnsafeNativeMethods.IADsPathname aDsPathname = (UnsafeNativeMethods.IADsPathname)pathname; aDsPathname.Set(str, 1); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("WinNT://"); stringBuilder.Append(this.storeCtx.MachineUserSuppliedName); stringBuilder.Append("/"); int numElements = aDsPathname.GetNumElements(); for (int i = numElements - 2; i >= 0; i--) { stringBuilder.Append(aDsPathname.GetElement(i)); stringBuilder.Append("/"); } stringBuilder.Remove(stringBuilder.Length - 1, 1); aDsPath.Path = stringBuilder.ToString(); } if (!this.IsLocalMember(numArray)) { this.foreignMembers.Add(aDsPath); flag = true; } else { if (!this.recursive || !SAMUtils.IsOfObjectClass(aDsPath, "Group")) { this.current = aDsPath; this.currentFakePrincipal = null; this.currentForeign = null; if (this.foreignResultSet != null) { this.foreignResultSet.Dispose(); } this.foreignResultSet = null; return(true); } else { if (!this.groupsVisited.Contains(aDsPath.Path) && !this.groupsToVisit.Contains(aDsPath.Path)) { this.groupsToVisit.Add(aDsPath.Path); } flag = true; } } } else { this.currentFakePrincipal = this.storeCtx.ConstructFakePrincipalFromSID(numArray); this.current = null; this.currentForeign = null; if (this.foreignResultSet != null) { this.foreignResultSet.Dispose(); } this.foreignResultSet = null; return(true); } } }while (flag); return(false); }