// Helper method: given a typeof(User/Computer/etc.), returns the userCtx/computerCtx/etc. internal StoreCtx ContextForType(Type t) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalContext", "ContextForType: type is " + t.ToString()); Initialize(); if (t == typeof(System.DirectoryServices.AccountManagement.UserPrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.UserPrincipal))) { return(_userCtx); } else if (t == typeof(System.DirectoryServices.AccountManagement.ComputerPrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.ComputerPrincipal))) { return(_computerCtx); } else if (t == typeof(System.DirectoryServices.AccountManagement.AuthenticablePrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.AuthenticablePrincipal))) { return(_userCtx); } else { Debug.Assert(t == typeof(System.DirectoryServices.AccountManagement.GroupPrincipal) || t.IsSubclassOf(typeof(System.DirectoryServices.AccountManagement.GroupPrincipal))); return(_groupCtx); } }
public Type GetUnderlyingSearcherType() { GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearcher", "Entering GetUnderlyingSearcherType"); CheckDisposed(); // We have to have a filter if (_qbeFilter == null) { throw new InvalidOperationException(StringResources.PrincipalSearcherMustSetFilter); } StoreCtx storeCtx = _ctx.QueryCtx; Debug.Assert(storeCtx != null); // The underlying context must actually support search (i.e., no MSAM/reg-SAM) if (storeCtx.SupportsSearchNatively == false) { throw new InvalidOperationException(StringResources.PrincipalSearcherNoUnderlying); } return(storeCtx.SearcherNativeType()); }
public bool Remove(PrincipalContext context, IdentityType identityType, string identityValue) { CheckDisposed(); if (context == null) { throw new ArgumentNullException("context"); } if (identityValue == null) { throw new ArgumentNullException("identityValue"); } Principal principal = Principal.FindByIdentity(context, identityType, identityValue); if (principal == null) { GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalCollection", "Remove(urn/urn): no match"); throw new NoMatchingPrincipalException(StringResources.NoMatchingPrincipalExceptionText); } return(Remove(principal)); }
static internal Principal ConstructFakePrincipalFromSID( byte[] sid, PrincipalContext ctx, string serverName, NetCred credentials, string authorityName) { GlobalDebug.WriteLineIf( GlobalDebug.Info, "Utils", "ConstructFakePrincipalFromSID: Build principal for SID={0}, server={1}, authority={2}", Utils.ByteArrayToString(sid), (serverName != null ? serverName : "NULL"), (authorityName != null ? authorityName : "NULL")); Debug.Assert(ClassifySID(sid) == SidType.FakeObject); // Get the name for it string nt4Name = ""; int accountUsage = 0; string name; string domainName; int err = Utils.LookupSid(serverName, credentials, sid, out name, out domainName, out accountUsage); if (err == 0) { // If it failed, we'll just live without a name //Debug.Assert(accountUsage == 5 /*WellKnownGroup*/); nt4Name = (!String.IsNullOrEmpty(domainName) ? domainName + "\\" : "") + name; } else { GlobalDebug.WriteLineIf( GlobalDebug.Warn, "Utils", "ConstructFakePrincipalFromSID: LookupSid failed (ignoring), serverName=" + serverName + ", err=" + err); } // Since LookupAccountSid indicates all of the NT AUTHORITY, etc., SIDs are WellKnownGroups, // we'll map them all to Group. // Create a Principal object to represent it GroupPrincipal g = GroupPrincipal.MakeGroup(ctx); g.fakePrincipal = true; g.unpersisted = false; // Set the display name on the object g.LoadValueIntoProperty(PropertyNames.PrincipalDisplayName, nt4Name); // Set the display name on the object g.LoadValueIntoProperty(PropertyNames.PrincipalName, name); // Set the display name on the object g.LoadValueIntoProperty(PropertyNames.PrincipalSamAccountName, name); // SID IdentityClaim SecurityIdentifier sidObj = new SecurityIdentifier(Utils.ConvertSidToSDDL(sid)); // Set the display name on the object g.LoadValueIntoProperty(PropertyNames.PrincipalSid, sidObj); g.LoadValueIntoProperty(PropertyNames.GroupIsSecurityGroup, true); return(g); }
internal static IntPtr GetMachineDomainSid() { IntPtr pPolicyHandle = IntPtr.Zero; IntPtr pBuffer = IntPtr.Zero; IntPtr pOA = IntPtr.Zero; try { UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES oa = new UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES(); pOA = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES))); Marshal.StructureToPtr(oa, pOA, false); int err = UnsafeNativeMethods.LsaOpenPolicy( IntPtr.Zero, pOA, 1, // POLICY_VIEW_LOCAL_INFORMATION ref pPolicyHandle); if (err != 0) { GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetMachineDomainSid: LsaOpenPolicy failed, gle=" + SafeNativeMethods.LsaNtStatusToWinError(err)); throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrievePolicy, SafeNativeMethods.LsaNtStatusToWinError(err))); } Debug.Assert(pPolicyHandle != IntPtr.Zero); err = UnsafeNativeMethods.LsaQueryInformationPolicy( pPolicyHandle, 5, // PolicyAccountDomainInformation ref pBuffer); if (err != 0) { GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetMachineDomainSid: LsaQueryInformationPolicy failed, gle=" + SafeNativeMethods.LsaNtStatusToWinError(err)); throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrievePolicy, SafeNativeMethods.LsaNtStatusToWinError(err))); } Debug.Assert(pBuffer != IntPtr.Zero); UnsafeNativeMethods.POLICY_ACCOUNT_DOMAIN_INFO info = (UnsafeNativeMethods.POLICY_ACCOUNT_DOMAIN_INFO) Marshal.PtrToStructure(pBuffer, typeof(UnsafeNativeMethods.POLICY_ACCOUNT_DOMAIN_INFO)); Debug.Assert(UnsafeNativeMethods.IsValidSid(info.domainSid)); // Now we make a copy of the SID to return int sidLength = UnsafeNativeMethods.GetLengthSid(info.domainSid); IntPtr pCopyOfSid = Marshal.AllocHGlobal(sidLength); bool success = UnsafeNativeMethods.CopySid(sidLength, pCopyOfSid, info.domainSid); if (!success) { int lastError = Marshal.GetLastWin32Error(); GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetMachineDomainSid: CopySid failed, errorcode=" + lastError); throw new PrincipalOperationException( String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrievePolicy, lastError)); } return(pCopyOfSid); } finally { if (pPolicyHandle != IntPtr.Zero) { UnsafeNativeMethods.LsaClose(pPolicyHandle); } if (pBuffer != IntPtr.Zero) { UnsafeNativeMethods.LsaFreeMemory(pBuffer); } if (pOA != IntPtr.Zero) { Marshal.FreeHGlobal(pOA); } } }
public bool Remove(Principal principal) { CheckDisposed(); if (principal == null) { throw new ArgumentNullException("principal"); } // Ask the StoreCtx to verify that this member can be removed. Right now, the only // reason it couldn't is if it's actually a member by virtue of its primaryGroupId // pointing to this group. // // If storeCtxToUse == null, then we must be unpersisted, in which case there clearly // can't be any such primary group members pointing to this group on the store. StoreCtx storeCtxToUse = _owningGroup.GetStoreCtxToUse(); string explanation; Debug.Assert(storeCtxToUse != null || _owningGroup.unpersisted == true); if ((storeCtxToUse != null) && (!storeCtxToUse.CanGroupMemberBeRemoved(_owningGroup, principal, out explanation))) { throw new InvalidOperationException(explanation); } bool removed = false; // If the value was previously inserted, we just remove it from insertedValuesPending. if (_insertedValuesPending.Contains(principal)) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Remove: removing from insertedValuesPending"); MarkChange(); _insertedValuesPending.Remove(principal); removed = true; // If they did a Remove(x) --> Save() --> Add(x) --> Remove(x), we'll end up with x in neither // the ResultSet or the removedValuesCompleted list. This is bad. Avoid that by adding x // back to the removedValuesCompleted list here. // // At worst, we end up with x on the removedValuesCompleted list even though it's not even in // resultSet. That's not a problem. The only thing we use the removedValuesCompleted list for // is deciding which values in resultSet to skip, anyway. if (!_removedValuesCompleted.Contains(principal)) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Remove: adding to removedValuesCompleted"); _removedValuesCompleted.Add(principal); } } else { // They're trying to remove a already-persisted value. We add it to the // removedValues list. Then, if it's already been loaded into insertedValuesCompleted, // we remove it from insertedValuesCompleted. removed = Contains(principal); GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "Remove: making it a pending remove, removed={0}", removed); if (removed) { MarkChange(); _removedValuesPending.Add(principal); // in case it's the result of a previous-but-already-committed insert _insertedValuesCompleted.Remove(principal); } } return(removed); }
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); }
internal ADEntriesSet(SearchResultCollection src, ADStoreCtx storeCtx, object discriminant) : this(src, storeCtx) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADEntriesSet", "Ctor"); _discriminant = discriminant; }
internal override bool MoveNext() { GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNConstraintLinkedAttrSet", "Entering MoveNext"); GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNConstraintLinkedAttrSet", "Filter {0}", _constraintData); bool match = false; string dn = "NotSet"; if (!base.MoveNext()) { return(false); } else { while (!match) { if (null == this.current) { return(false); } switch (_constraint) { case ConstraintType.ContainerStringMatch: if (this.current is SearchResult) { dn = ((SearchResult)this.current).Properties["distinguishedName"][0].ToString(); } else { dn = ((DirectoryEntry)this.current).Properties["distinguishedName"].Value.ToString(); } if (dn.EndsWith((string)_constraintData, StringComparison.Ordinal)) { match = true; } break; case ConstraintType.ResultValidatorDelegateMatch: { ResultValidator resultValidator = _constraintData as ResultValidator; if (resultValidator != null) { dSPropertyCollection resultPropCollection = null; if (this.current is SearchResult) { resultPropCollection = new dSPropertyCollection(((SearchResult)this.current).Properties); } else { resultPropCollection = new dSPropertyCollection(((DirectoryEntry)this.current).Properties); } match = resultValidator.Invoke(resultPropCollection); } else { Debug.Fail("ADStoreCtx.ADDNConstraintLinkedAttrSet: Invalid constraint data. Expected: object of type ResultValidator"); } break; } default: Debug.Fail("ADStoreCtx.ADDNConstraintLinkedAttrSet: fell off end looking for " + _constraint.ToString()); break; } GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADDNConstraintLinkedAttrSet", "Found {0} Match {1}", dn, match.ToString()); if (!match) { if (!this.MoveNext()) { return(false); } } } return(match); } }
// // Cross-store support // // Given a native store object that represents a "foreign" principal (e.g., a FPO object in this store that // represents a pointer to another store), maps that representation to the other store's StoreCtx and returns // a Principal from that other StoreCtx. The implementation of this method is highly dependent on the // details of the particular store, and must have knowledge not only of this StoreCtx, but also of how to // interact with other StoreCtxs to fulfill the request. // // This method is typically used by ResultSet implementations, when they're iterating over a collection // (e.g., of group membership) and encounter an entry that represents a foreign principal. internal override Principal ResolveCrossStoreRefToPrincipal(object o) { Debug.Assert(o is DirectoryEntry); // Get the SID of the foreign principal DirectoryEntry foreignDE = (DirectoryEntry)o; if (foreignDE.Properties["objectSid"].Count == 0) { GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "ResolveCrossStoreRefToPrincipal: no objectSid found"); throw new PrincipalOperationException(SR.SAMStoreCtxCantRetrieveObjectSidForCrossStore); } Debug.Assert(foreignDE.Properties["objectSid"].Count == 1); byte[] sid = (byte[])foreignDE.Properties["objectSid"].Value; // Ask the OS to resolve the SID to its target. int accountUsage = 0; string name; string domainName; int err = Utils.LookupSid(this.MachineUserSuppliedName, _credentials, sid, out name, out domainName, out accountUsage); if (err != 0) { GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "ResolveCrossStoreRefToPrincipal: LookupSid failed, err={0}, server={1}", err, this.MachineUserSuppliedName); throw new PrincipalOperationException( SR.Format(SR.SAMStoreCtxCantResolveSidForCrossStore, err)); } GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "ResolveCrossStoreRefToPrincipal: LookupSid found {0} in {1}", name, domainName); // Since this is SAM, the remote principal must be an AD principal. // Build a PrincipalContext for the store which owns the principal // Use the ad default options so we turn sign and seal back on. #if USE_CTX_CACHE PrincipalContext remoteCtx = SDSCache.Domain.GetContext(domainName, _credentials, DefaultContextOptions.ADDefaultContextOption); #else PrincipalContext remoteCtx = new PrincipalContext( ContextType.Domain, domainName, null, (this.credentials != null ? credentials.UserName : null), (this.credentials != null ? credentials.Password : null), DefaultContextOptions.ADDefaultContextOption); #endif SecurityIdentifier sidObj = new SecurityIdentifier(sid, 0); Principal p = remoteCtx.QueryCtx.FindPrincipalByIdentRef( typeof(Principal), UrnScheme.SidScheme, sidObj.ToString(), DateTime.UtcNow); if (p != null) { return(p); } else { GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "ResolveCrossStoreRefToPrincipal: no matching principal"); throw new PrincipalOperationException(SR.SAMStoreCtxFailedFindCrossStoreTarget); } }
// Get groups of which p is a direct member internal override ResultSet GetGroupsMemberOf(Principal p) { // Enforced by the methods that call us Debug.Assert(p.unpersisted == false); if (!p.fakePrincipal) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetGroupsMemberOf: is real principal"); // No nested groups or computers as members of groups in SAM if (!(p is UserPrincipal)) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetGroupsMemberOf: not a user, returning empty set"); return(new EmptySet()); } Debug.Assert(p.UnderlyingObject != null); DirectoryEntry userDE = (DirectoryEntry)p.UnderlyingObject; UnsafeNativeMethods.IADsMembers iadsMembers = (UnsafeNativeMethods.IADsMembers)userDE.Invoke("Groups"); ResultSet resultSet = new SAMGroupsSet(iadsMembers, this, _ctxBase); return(resultSet); } else { // ADSI's IADsGroups doesn't work for fake principals like NT AUTHORITY\NETWORK SERVICE // We use the same SAMQuery set that we use for query-by-example, but with a different // SAMMatcher class to match groups which contain the specified principal as a member // Get the entries we'll iterate over. Write access to Children is controlled through the // ctxBaseLock, but we don't want to have to hold that lock while we're iterating over all // the child entries. So we have to clone the ctxBase --- not ideal, but it prevents // multithreading issues. DirectoryEntries entries = SDSUtils.BuildDirectoryEntry(_ctxBase.Path, _credentials, _authTypes).Children; Debug.Assert(entries != null); // The SAMQuerySet will use this to restrict the types of DirectoryEntry objects returned. List <string> schemaTypes = GetSchemaFilter(typeof(GroupPrincipal)); SecurityIdentifier principalSid = p.Sid; byte[] SidB = new byte[principalSid.BinaryLength]; principalSid.GetBinaryForm(SidB, 0); if (principalSid == null) { GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "GetGroupsMemberOf: bad SID IC"); throw new InvalidOperationException(SR.StoreCtxNeedValueSecurityIdentityClaimToQuery); } // Create the ResultSet that will perform the client-side filtering SAMQuerySet resultSet = new SAMQuerySet( schemaTypes, entries, _ctxBase, -1, // no size limit this, new GroupMemberMatcher(SidB)); return(resultSet); } }
internal override void Move(StoreCtx originalStore, Principal p) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Move"); }
// 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); } } }
// Advance the enumerator to the next principal in the result set, pulling in additional pages // of results (or ranges of attribute values) as needed. // Returns true if successful, false if no more results to return. override internal bool MoveNext() { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "Entering MoveNext"); Debug.Assert(_enumerator != null); bool needToRetry = false; bool f; // Have we exceeded the requested size limit? if ((_sizeLimit != -1) && (_resultsReturned >= _sizeLimit)) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "MoveNext: exceeded sizelimit, ret={0}, limit={1}", _resultsReturned, _sizeLimit); _endReached = true; } // End was reached previously. Nothing more to do. if (_endReached) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "MoveNext: endReached"); return(false); } // Pull the next result. We may have to repeat this several times // until we find a result that matches the user's filter. do { f = _enumerator.MoveNext(); needToRetry = false; if (f) { DirectoryEntry entry = (DirectoryEntry)_enumerator.Current; // Does it match the user's properties? // // We'd like to use DirectoryEntries.SchemaFilter rather than calling // IsOfCorrectType here, but SchemaFilter has a bug // where multiple DirectoryEntries all share the same SchemaFilter --- // which would create multithreading issues for us. if (IsOfCorrectType(entry) && _matcher.Matches(entry)) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "MoveNext: found a match on {0}", entry.Path); // Yes. It's our new current object _current = entry; _resultsReturned++; } else { // No. Retry. needToRetry = true; } } }while (needToRetry); if (!f) { /* * // One more to try: the root object * if (IsOfCorrectType(this.ctxBase) && this.matcher.Matches(this.ctxBase)) * { * GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "MoveNext: found a match on root {0}", this.ctxBase); * * this.current = this.ctxBase; * this.resultsReturned++; * f = true; * } * else * { * endReached = true; * } * */ } return(f); }
// // Internal Constructors // // Note that resultSet can be null internal PrincipalSearchResult(ResultSet resultSet) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalSearchResult", "Ctor"); _resultSet = resultSet; }
private void BuildFilterSet(Principal p, string[] propertySet, QbeFilterDescription qbeFilterDescription) { foreach (string propertyName in propertySet) { if (p.GetChangeStatusForProperty(propertyName)) { // Property has changed. Add it to the filter set. object value = p.GetValueForProperty(propertyName); GlobalDebug.WriteLineIf( GlobalDebug.Info, "StoreCtx", "BuildFilterSet: type={0}, property name={1}, property value={2} of type {3}", p.GetType().ToString(), propertyName, value.ToString(), value.GetType().ToString()); // Build the right filter based on type of the property value if (value is PrincipalValueCollection <string> ) { PrincipalValueCollection <string> trackingList = (PrincipalValueCollection <string>)value; foreach (string s in trackingList.Inserted) { object filter = FilterFactory.CreateFilter(propertyName); ((FilterBase)filter).Value = (string)s; qbeFilterDescription.FiltersToApply.Add(filter); } } else if (value is X509Certificate2Collection) { // Since QBE filter objects are always unpersisted, any certs in the collection // must have been inserted by the application. X509Certificate2Collection certCollection = (X509Certificate2Collection)value; foreach (X509Certificate2 cert in certCollection) { object filter = FilterFactory.CreateFilter(propertyName); ((FilterBase)filter).Value = (X509Certificate2)cert; qbeFilterDescription.FiltersToApply.Add(filter); } } else { // It's not one of the multivalued cases. Try the scalar cases. object filter = FilterFactory.CreateFilter(propertyName); if (value == null) { ((FilterBase)filter).Value = null; } else if (value is bool) { ((FilterBase)filter).Value = (bool)value; } else if (value is string) { ((FilterBase)filter).Value = (string)value; } else if (value is GroupScope) { ((FilterBase)filter).Value = (GroupScope)value; } else if (value is byte[]) { ((FilterBase)filter).Value = (byte[])value; } else if (value is Nullable <DateTime> ) { ((FilterBase)filter).Value = (Nullable <DateTime>)value; } else if (value is ExtensionCache) { ((FilterBase)filter).Value = (ExtensionCache)value; } else if (value is QbeMatchType) { ((FilterBase)filter).Value = (QbeMatchType)value; } else { // Internal error. Didn't match either the known multivalued or scalar cases. Debug.Fail(String.Format( CultureInfo.CurrentCulture, "StoreCtx.BuildFilterSet: fell off end looking for {0} of type {1}", propertyName, value.GetType().ToString() )); } qbeFilterDescription.FiltersToApply.Add(filter); } } } }
static internal void InsertPrincipal( Principal p, StoreCtx storeCtx, GroupMembershipUpdater updateGroupMembership, NetCred credentials, AuthenticationTypes authTypes, bool needToSetPassword) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "Entering InsertPrincipal"); Debug.Assert(storeCtx != null); Debug.Assert(storeCtx is ADStoreCtx || storeCtx is SAMStoreCtx); Debug.Assert(p != null); if ((!(p is UserPrincipal)) && (!(p is GroupPrincipal)) && (!(p is AuthenticablePrincipal)) && (!(p is ComputerPrincipal))) { // It's not a type of Principal that we support GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SDSUtils", "InsertPrincipal: Bad principal type:" + p.GetType().ToString()); throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, SR.StoreCtxUnsupportedPrincipalTypeForSave, p.GetType().ToString())); } // Commit the properties SDSUtils.ApplyChangesToDirectory( p, storeCtx, updateGroupMembership, credentials, authTypes ); // Handle any saved-off operations // For SAM, we set password elsewhere prior to creating the principal, so needToSetPassword == false // For AD, we have to set the password after creating the principal, so needToSetPassword == true if (needToSetPassword && p.GetChangeStatusForProperty(PropertyNames.PwdInfoPassword)) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "InsertPrincipal: Setting password"); // Only AuthenticablePrincipals can have PasswordInfo Debug.Assert(p is AuthenticablePrincipal); string password = (string)p.GetValueForProperty(PropertyNames.PwdInfoPassword); Debug.Assert(password != null); // if null, PasswordInfo should not have indicated it was changed storeCtx.SetPassword((AuthenticablePrincipal)p, password); } if (p.GetChangeStatusForProperty(PropertyNames.PwdInfoExpireImmediately)) { // Only AuthenticablePrincipals can have PasswordInfo Debug.Assert(p is AuthenticablePrincipal); bool expireImmediately = (bool)p.GetValueForProperty(PropertyNames.PwdInfoExpireImmediately); if (expireImmediately) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "InsertPrincipal: Setting pwd expired"); storeCtx.ExpirePassword((AuthenticablePrincipal)p); } } }
protected void TranslateSids(string target, IntPtr[] pSids) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "SidList: processing {0} SIDs", pSids.Length); // if there are no SIDs to translate return if (pSids.Length == 0) { return; } // Build the list of SIDs to resolve int sidCount = pSids.Length; // Translate the SIDs in bulk IntPtr pOA = IntPtr.Zero; IntPtr pPolicyHandle = IntPtr.Zero; IntPtr pDomains = IntPtr.Zero; UnsafeNativeMethods.LSA_TRUST_INFORMATION[] domains; IntPtr pNames = IntPtr.Zero; UnsafeNativeMethods.LSA_TRANSLATED_NAME[] names; try { // // Get the policy handle // UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES oa = new UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES(); pOA = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_OBJECT_ATTRIBUTES))); Marshal.StructureToPtr(oa, pOA, false); int err = 0; if (target == null) { err = UnsafeNativeMethods.LsaOpenPolicy( IntPtr.Zero, pOA, 0x800, // POLICY_LOOKUP_NAMES ref pPolicyHandle); } else { // Build an entry. Note that LSA_UNICODE_STRING.length is in bytes, // while PtrToStringUni expects a length in characters. UnsafeNativeMethods.LSA_UNICODE_STRING_Managed lsaTargetString = new UnsafeNativeMethods.LSA_UNICODE_STRING_Managed(); lsaTargetString.buffer = target; lsaTargetString.length = (ushort)(target.Length * 2); lsaTargetString.maximumLength = lsaTargetString.length; IntPtr lsaTargetPr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_UNICODE_STRING))); try { Marshal.StructureToPtr(lsaTargetString, lsaTargetPr, false); err = UnsafeNativeMethods.LsaOpenPolicy( lsaTargetPr, pOA, 0x800, // POLICY_LOOKUP_NAMES ref pPolicyHandle); } finally { if (lsaTargetPr != IntPtr.Zero) { UnsafeNativeMethods.LSA_UNICODE_STRING lsaTargetUnmanagedPtr = (UnsafeNativeMethods.LSA_UNICODE_STRING)Marshal.PtrToStructure(lsaTargetPr, typeof(UnsafeNativeMethods.LSA_UNICODE_STRING)); if (lsaTargetUnmanagedPtr.buffer != IntPtr.Zero) { Marshal.FreeHGlobal(lsaTargetUnmanagedPtr.buffer); lsaTargetUnmanagedPtr.buffer = IntPtr.Zero; } Marshal.FreeHGlobal(lsaTargetPr); } } } if (err != 0) { GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "SidList: couldn't get policy handle, err={0}", err); throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture, StringResources.AuthZErrorEnumeratingGroups, SafeNativeMethods.LsaNtStatusToWinError(err))); } Debug.Assert(pPolicyHandle != IntPtr.Zero); // // Translate the SIDs // err = UnsafeNativeMethods.LsaLookupSids( pPolicyHandle, sidCount, pSids, out pDomains, out pNames); // ignore error STATUS_SOME_NOT_MAPPED = 0x00000107 and // STATUS_NONE_MAPPED = 0xC0000073 if (err != 0 && err != 263 && err != -1073741709) { GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "SidList: LsaLookupSids failed, err={0}", err); throw new PrincipalOperationException(String.Format(CultureInfo.CurrentCulture, StringResources.AuthZErrorEnumeratingGroups, SafeNativeMethods.LsaNtStatusToWinError(err))); } // // Get the group names in managed form // names = new UnsafeNativeMethods.LSA_TRANSLATED_NAME[sidCount]; IntPtr pCurrentName = pNames; for (int i = 0; i < sidCount; i++) { names[i] = (UnsafeNativeMethods.LSA_TRANSLATED_NAME) Marshal.PtrToStructure(pCurrentName, typeof(UnsafeNativeMethods.LSA_TRANSLATED_NAME)); pCurrentName = new IntPtr(pCurrentName.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_TRANSLATED_NAME))); } // // Get the domain names in managed form // // Extract LSA_REFERENCED_DOMAIN_LIST.Entries UnsafeNativeMethods.LSA_REFERENCED_DOMAIN_LIST referencedDomains = (UnsafeNativeMethods.LSA_REFERENCED_DOMAIN_LIST)Marshal.PtrToStructure(pDomains, typeof(UnsafeNativeMethods.LSA_REFERENCED_DOMAIN_LIST)); int domainCount = referencedDomains.entries; // Extract LSA_REFERENCED_DOMAIN_LIST.Domains, by iterating over the array and marshalling // each native LSA_TRUST_INFORMATION into a managed LSA_TRUST_INFORMATION. domains = new UnsafeNativeMethods.LSA_TRUST_INFORMATION[domainCount]; IntPtr pCurrentDomain = referencedDomains.domains; for (int i = 0; i < domainCount; i++) { domains[i] = (UnsafeNativeMethods.LSA_TRUST_INFORMATION)Marshal.PtrToStructure(pCurrentDomain, typeof(UnsafeNativeMethods.LSA_TRUST_INFORMATION)); pCurrentDomain = new IntPtr(pCurrentDomain.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.LSA_TRUST_INFORMATION))); } GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "SidList: got {0} groups in {1} domains", sidCount, domainCount); // // Build the list of entries // Debug.Assert(names.Length == sidCount); for (int i = 0; i < names.Length; i++) { UnsafeNativeMethods.LSA_TRANSLATED_NAME name = names[i]; // Build an entry. Note that LSA_UNICODE_STRING.length is in bytes, // while PtrToStringUni expects a length in characters. SidListEntry entry = new SidListEntry(); Debug.Assert(name.name.length % 2 == 0); entry.name = Marshal.PtrToStringUni(name.name.buffer, name.name.length / 2); // Get the domain associated with this name Debug.Assert(name.domainIndex < domains.Length); if (name.domainIndex >= 0) { UnsafeNativeMethods.LSA_TRUST_INFORMATION domain = domains[name.domainIndex]; Debug.Assert(domain.name.length % 2 == 0); entry.sidIssuerName = Marshal.PtrToStringUni(domain.name.buffer, domain.name.length / 2); } entry.pSid = pSids[i]; _entries.Add(entry); } // Sort the list so they are oriented by the issuer name. // this.entries.Sort( new SidListComparer()); } finally { if (pDomains != IntPtr.Zero) { UnsafeNativeMethods.LsaFreeMemory(pDomains); } if (pNames != IntPtr.Zero) { UnsafeNativeMethods.LsaFreeMemory(pNames); } if (pPolicyHandle != IntPtr.Zero) { UnsafeNativeMethods.LsaClose(pPolicyHandle); } if (pOA != IntPtr.Zero) { Marshal.FreeHGlobal(pOA); } } }
public void Save(PrincipalContext context) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Entering Save(Context)"); // Make sure we're not disposed or deleted. CheckDisposedOrDeleted(); // Make sure we're not a fake principal CheckFakePrincipal(); // We must have a PrincipalContext to save into. This should always be the case, unless we're unpersisted // and they never set a PrincipalContext. if (context == null) { Debug.Assert(this.unpersisted == true); throw new InvalidOperationException(SR.NullArguments); } if (context.ContextType == ContextType.Machine || _ctx.ContextType == ContextType.Machine) { throw new InvalidOperationException(SR.SaveToNotSupportedAgainstMachineStore); } // If the user is trying to save to the same context we are already set to then just save the changes if (context == _ctx) { Save(); return; } // If we already have a context set on this object then make sure the new // context is of the same type. if (context.ContextType != _ctx.ContextType) { Debug.Assert(this.unpersisted == true); throw new InvalidOperationException(SR.SaveToMustHaveSamecontextType); } StoreCtx originalStoreCtx = GetStoreCtxToUse(); _ctx = context; // Call the appropriate operation depending on whether this is an insert or update StoreCtx newStoreCtx = GetStoreCtxToUse(); Debug.Assert(newStoreCtx != null); // since we know this.ctx isn't null Debug.Assert(originalStoreCtx != null); // since we know this.ctx isn't null if (this.unpersisted) { // We have an unpersisted principal so we just want to create a principal in the new store. GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Save(context): inserting new principal of type {0} using {1}", this.GetType(), newStoreCtx.GetType()); Debug.Assert(newStoreCtx == _ctx.ContextForType(this.GetType())); newStoreCtx.Insert(this); this.unpersisted = false; // once we persist, we're no longer in the unpersisted state } else { // We have a principal that already exists. We need to move it to the new store. GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Save(context): Moving principal of type {0} using {1}", this.GetType(), newStoreCtx.GetType()); // we are now saving to a new store so this principal is unpersisted. this.unpersisted = true; // If the user has modified the name save away the current name so // if the move succeeds and the update fails we will move the item back to the original // store with the original name. bool nameModified = _nameChanged == LoadState.Changed; string previousName = null; if (nameModified) { string newName = _name; _ctx.QueryCtx.Load(this, PropertyNames.PrincipalName); previousName = _name; this.Name = newName; } newStoreCtx.Move(originalStoreCtx, this); try { this.unpersisted = false; // once we persist, we're no longer in the unpersisted state newStoreCtx.Update(this); } catch (System.SystemException e) { try { GlobalDebug.WriteLineIf(GlobalDebug.Error, "Principal", "Save(context):, Update Failed (attempting to move back) Exception {0} ", e.Message); if (nameModified) { this.Name = previousName; } originalStoreCtx.Move(newStoreCtx, this); GlobalDebug.WriteLineIf(GlobalDebug.Info, "Principal", "Move back succeeded"); } catch (System.SystemException deleteFail) { // The move back failed. Just continue we will throw the original exception below. GlobalDebug.WriteLineIf(GlobalDebug.Error, "Principal", "Save(context):, Move back Failed {0} ", deleteFail.Message); } if (e is System.Runtime.InteropServices.COMException) { throw ExceptionHelper.GetExceptionFromCOMException((System.Runtime.InteropServices.COMException)e); } else { throw; } } } _ctx.QueryCtx = newStoreCtx; // so Updates go to the right StoreCtx }
public PrincipalContext GetContext(string name, NetCred credentials, ContextOptions contextOptions) { string contextName = name; string userName = null; bool explicitCreds = false; if (credentials != null && credentials.UserName != null) { if (credentials.Domain != null) { userName = credentials.Domain + "\\" + credentials.UserName; } else { userName = credentials.UserName; } explicitCreds = true; } else { userName = Utils.GetNT4UserName(); } GlobalDebug.WriteLineIf( GlobalDebug.Info, "SDSCache", "GetContext: looking for context for server {0}, user {1}, explicitCreds={2}, options={3}", name, userName, explicitCreds.ToString(), contextOptions.ToString()); if (!_isSAM) { // Determine the domain DNS name // DS_RETURN_DNS_NAME | DS_DIRECTORY_SERVICE_REQUIRED | DS_BACKGROUND_ONLY int flags = unchecked ((int)(0x40000000 | 0x00000010 | 0x00000100)); UnsafeNativeMethods.DomainControllerInfo info = Utils.GetDcName(null, contextName, null, flags); contextName = info.DomainName; } GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: final contextName is " + contextName); ManualResetEvent contextReadyEvent = null; while (true) { Hashtable credTable = null; PrincipalContext ctx = null; // Wait for the PrincipalContext to be ready if (contextReadyEvent != null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: waiting"); contextReadyEvent.WaitOne(); } contextReadyEvent = null; lock (_tableLock) { CredHolder credHolder = (CredHolder)_table[contextName]; if (credHolder != null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: found a credHolder for " + contextName); credTable = (explicitCreds ? credHolder.explicitCreds : credHolder.defaultCreds); Debug.Assert(credTable != null); object o = credTable[userName]; if (o is Placeholder) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: credHolder for " + contextName + " has a Placeholder"); // A PrincipalContext is currently being constructed by another thread. // Wait for it. contextReadyEvent = ((Placeholder)o).contextReadyEvent; continue; } WeakReference refToContext = o as WeakReference; if (refToContext != null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: refToContext is non-null"); ctx = (PrincipalContext)refToContext.Target; // null if GC'ed // If the PrincipalContext hasn't been GCed or disposed, use it. // Otherwise, we'll need to create a new one if (ctx != null && ctx.Disposed == false) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: using found refToContext"); return(ctx); } else { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSCache", "GetContext: refToContext is GCed/disposed, removing"); credTable.Remove(userName); } } } // Either credHolder/credTable are null (no contexts exist for the contextName), or credHolder/credTable // are non-null (contexts exist, but none for the userName). Either way, we need to create a PrincipalContext. if (credHolder == null) { GlobalDebug.WriteLineIf( GlobalDebug.Info, "SDSCache", "GetContext: null credHolder for " + contextName + ", explicitCreds=" + explicitCreds.ToString()); // No contexts exist for the contextName. Create a CredHolder for the contextName so we have a place // to store the PrincipalContext we'll be creating. credHolder = new CredHolder(); _table[contextName] = credHolder; credTable = (explicitCreds ? credHolder.explicitCreds : credHolder.defaultCreds); } // Put a placeholder on the contextName/userName slot, so that other threads that come along after // we release the tableLock know we're in the process of creating the needed PrincipalContext and will wait for us credTable[userName] = new Placeholder(); } // Now we just need to create a PrincipalContext for the contextName and credentials GlobalDebug.WriteLineIf( GlobalDebug.Info, "SDSCache", "GetContext: creating context, contextName=" + contextName + ", options=" + contextOptions.ToString()); ctx = new PrincipalContext( (_isSAM ? ContextType.Machine : ContextType.Domain), contextName, null, contextOptions, credentials?.UserName, credentials?.Password ); lock (_tableLock) { Placeholder placeHolder = (Placeholder)credTable[userName]; // Replace the placeholder with the newly-created PrincipalContext credTable[userName] = new WeakReference(ctx); // Signal waiting threads to continue. We do this after inserting the PrincipalContext // into the table, so that the PrincipalContext is ready as soon as the other threads wake up. // (Actually, the order probably doesn't matter, since even if we did it in the // opposite order and the other thread woke up before we inserted the PrincipalContext, it would // just block as soon as it tries to acquire the tableLock that we're currently holding.) bool f = placeHolder.contextReadyEvent.Set(); Debug.Assert(f); } return(ctx); } }
// These are verbatim C# string ( @ ) where \ is actually \\ // Input Matches RegEx // ----- ------- ----- // * any ( 1 or more ) .* // // \* * \* // \ \ \\ // ( ( \( // \( ( \( // ) ) \) // \) ) \) // \\ \ \\ // x x x (where x is anything else) // Add \G to beginning and \z to the end so that the regex will be anchored at the either end of the property // \G = Regex must match at the beginning // \z = Regex must match at the end // ( ) * are special characters to Regex so they must be escaped with \\. We support these from teh user either raw or already escaped. // Any other \ in the input string are translated to an actual \ in the match because we cannot determine usage except for ( ) * // The user cannot enter any regex escape sequence they would like in their match string. Only * is supported. // // @"c:\Home" -> "c:\\\\Home" OR @"c:\\Home" // // static internal string PAPIQueryToRegexString(string papiString) { StringBuilder sb = new StringBuilder(papiString.Length); sb.Append(@"\G"); bool escapeMode = false; foreach (char c in papiString) { if (escapeMode == false) { switch (c) { case '(': sb.Append(@"\("); // ( --> \( break; case ')': sb.Append(@"\)"); // ) --> \) break; case '\\': escapeMode = true; break; case '*': sb.Append(@".*"); // * --> .* break; default: sb.Append(c.ToString()); // x --> x break; } } else { escapeMode = false; switch (c) { case '(': sb.Append(@"\("); // \( --> \( break; case ')': sb.Append(@"\)"); // \) --> \) break; case '*': sb.Append(@"\*"); // \* --> \* break; case '\\': sb.Append(@"\\\\"); // \\ --> \\ break; default: sb.Append(@"\\"); sb.Append(c.ToString()); // \x --> \x break; } } } // There was a '\\' but no character after it because we were at the // end of the string. // Append '\\\\' to match the '\\'. if (escapeMode) { sb.Append(@"\\"); } GlobalDebug.WriteLineIf( GlobalDebug.Info, "SAMUtils", "PAPIQueryToRegexString: mapped '{0}' to '{1}'", papiString, sb.ToString()); sb.Append(@"\z"); return(sb.ToString()); }
internal static unsafe int LookupSid(string serverName, NetCred credentials, byte[] sid, out string name, out string domainName, out int accountUsage) { int nameLength = 0; int domainNameLength = 0; accountUsage = 0; name = null; domainName = null; IntPtr hUser = IntPtr.Zero; try { Utils.BeginImpersonation(credentials, out hUser); // hUser could be null if no credentials were specified Debug.Assert(hUser != IntPtr.Zero || (credentials == null || (credentials.UserName == null && credentials.Password == null))); int f = Interop.Advapi32.LookupAccountSid(serverName, sid, null, ref nameLength, null, ref domainNameLength, out accountUsage); int lastErr = Marshal.GetLastWin32Error(); if (lastErr != 122) // ERROR_INSUFFICIENT_BUFFER { GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "LookupSid: LookupAccountSid (1st try) failed, gle=" + lastErr); return(lastErr); } Debug.Assert(f == 0); // should never succeed, with a 0 buffer size Debug.Assert(nameLength > 0); Debug.Assert(domainNameLength > 0); fixed(char *sbName = new char[nameLength]) fixed(char *sbDomainName = new char[domainNameLength]) { f = Interop.Advapi32.LookupAccountSid(serverName, sid, sbName, ref nameLength, sbDomainName, ref domainNameLength, out accountUsage); if (f == 0) { lastErr = Marshal.GetLastWin32Error(); Debug.Assert(lastErr != 0); GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "LookupSid: LookupAccountSid (2nd try) failed, gle=" + lastErr); return(lastErr); } name = new string(sbName); domainName = new string(sbDomainName); } return(0); } finally { if (hUser != IntPtr.Zero) { Utils.EndImpersonation(hUser); } } }
void ICollection.CopyTo(Array array, int index) { CheckDisposed(); // Parameter validation if (index < 0) { throw new ArgumentOutOfRangeException("index"); } if (array == null) { throw new ArgumentNullException("array"); } if (array.Rank != 1) { throw new ArgumentException(SR.PrincipalCollectionNotOneDimensional); } if (index >= array.GetLength(0)) { throw new ArgumentException(SR.PrincipalCollectionIndexNotInArray); } ArrayList tempArray = new ArrayList(); lock (_resultSet) { ResultSetBookmark bookmark = null; try { GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "CopyTo: bookmarking"); bookmark = _resultSet.BookmarkAndReset(); PrincipalCollectionEnumerator containmentEnumerator = new PrincipalCollectionEnumerator( _resultSet, this, _removedValuesCompleted, _removedValuesPending, _insertedValuesCompleted, _insertedValuesPending); int arraySize = array.GetLength(0) - index; int tempArraySize = 0; while (containmentEnumerator.MoveNext()) { tempArray.Add(containmentEnumerator.Current); checked { tempArraySize++; } // Make sure the array has enough space, allowing for the "index" offset. // We check inline, rather than doing a PrincipalCollection.Count upfront, // because counting is just as expensive as enumerating over all the results, so we // only want to do it once. if (arraySize < tempArraySize) { GlobalDebug.WriteLineIf(GlobalDebug.Warn, "PrincipalCollection", "CopyTo: array too small (has {0}, need >= {1}", arraySize, tempArraySize); throw new ArgumentException(SR.PrincipalCollectionArrayTooSmall); } } } finally { if (bookmark != null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "PrincipalCollection", "CopyTo: restoring from bookmark"); _resultSet.RestoreBookmark(bookmark); } } } foreach (object o in tempArray) { array.SetValue(o, index); checked { index++; } } }
// // Public methods // public bool MoveNext() { GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Entering MoveNext"); return(_inner.MoveNext()); }
internal static IntPtr GetCurrentUserSid() { IntPtr pTokenHandle = IntPtr.Zero; IntPtr pBuffer = IntPtr.Zero; try { // // Get the current user's SID // int error = 0; // Get the current thread's token if (!UnsafeNativeMethods.OpenThreadToken( UnsafeNativeMethods.GetCurrentThread(), 0x8, // TOKEN_QUERY true, ref pTokenHandle )) { if ((error = Marshal.GetLastWin32Error()) == 1008) // ERROR_NO_TOKEN { Debug.Assert(pTokenHandle == IntPtr.Zero); // Current thread doesn't have a token, try the process if (!UnsafeNativeMethods.OpenProcessToken( UnsafeNativeMethods.GetCurrentProcess(), 0x8, // TOKEN_QUERY ref pTokenHandle )) { int lastError = Marshal.GetLastWin32Error(); GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetCurrentUserSid: OpenProcessToken failed, gle=" + lastError); throw new PrincipalOperationException( String.Format(CultureInfo.CurrentCulture, StringResources.UnableToOpenToken, lastError)); } } else { GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetCurrentUserSid: OpenThreadToken failed, gle=" + error); throw new PrincipalOperationException( String.Format(CultureInfo.CurrentCulture, StringResources.UnableToOpenToken, error)); } } Debug.Assert(pTokenHandle != IntPtr.Zero); int neededBufferSize = 0; // Retrieve the user info from the current thread's token // First, determine how big a buffer we need. bool success = UnsafeNativeMethods.GetTokenInformation( pTokenHandle, 1, // TokenUser IntPtr.Zero, 0, ref neededBufferSize); int getTokenInfoError = 0; if ((getTokenInfoError = Marshal.GetLastWin32Error()) != 122) // ERROR_INSUFFICIENT_BUFFER { GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetCurrentUserSid: GetTokenInformation (1st try) failed, gle=" + getTokenInfoError); throw new PrincipalOperationException( String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrieveTokenInfo, getTokenInfoError)); } // Allocate the necessary buffer. Debug.Assert(neededBufferSize > 0); pBuffer = Marshal.AllocHGlobal(neededBufferSize); // Load the user info into the buffer success = UnsafeNativeMethods.GetTokenInformation( pTokenHandle, 1, // TokenUser pBuffer, neededBufferSize, ref neededBufferSize); if (!success) { int lastError = Marshal.GetLastWin32Error(); GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetCurrentUserSid: GetTokenInformation (2nd try) failed, neededBufferSize=" + neededBufferSize + ", gle=" + lastError); throw new PrincipalOperationException( String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrieveTokenInfo, lastError)); } // Retrieve the user's SID from the user info UnsafeNativeMethods.TOKEN_USER tokenUser = (UnsafeNativeMethods.TOKEN_USER)Marshal.PtrToStructure(pBuffer, typeof(UnsafeNativeMethods.TOKEN_USER)); IntPtr pUserSid = tokenUser.sidAndAttributes.pSid; // this is a reference into the NATIVE memory (into pBuffer) Debug.Assert(UnsafeNativeMethods.IsValidSid(pUserSid)); // Now we make a copy of the SID to return int userSidLength = UnsafeNativeMethods.GetLengthSid(pUserSid); IntPtr pCopyOfUserSid = Marshal.AllocHGlobal(userSidLength); success = UnsafeNativeMethods.CopySid(userSidLength, pCopyOfUserSid, pUserSid); if (!success) { int lastError = Marshal.GetLastWin32Error(); GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "GetCurrentUserSid: CopySid failed, errorcode=" + lastError); throw new PrincipalOperationException( String.Format(CultureInfo.CurrentCulture, StringResources.UnableToRetrieveTokenInfo, lastError)); } return(pCopyOfUserSid); } finally { if (pTokenHandle != IntPtr.Zero) { UnsafeNativeMethods.CloseHandle(pTokenHandle); } if (pBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(pBuffer); } } }
public void Reset() { GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Entering Reset"); _inner.Reset(); }
internal static int LookupSid(string serverName, NetCred credentials, byte[] sid, out string name, out string domainName, out int accountUsage) { IntPtr pSid = IntPtr.Zero; int nameLength = 0; int domainNameLength = 0; StringBuilder sbName; StringBuilder sbDomainName; accountUsage = 0; name = null; domainName = null; IntPtr hUser = IntPtr.Zero; try { pSid = ConvertByteArrayToIntPtr(sid); Utils.BeginImpersonation(credentials, out hUser); // hUser could be null if no credentials were specified Debug.Assert(hUser != IntPtr.Zero || (credentials == null || (credentials.UserName == null && credentials.Password == null))); bool f = UnsafeNativeMethods.LookupAccountSid(serverName, pSid, null, ref nameLength, null, ref domainNameLength, ref accountUsage); int lastErr = Marshal.GetLastWin32Error(); if (lastErr != 122) // ERROR_INSUFFICIENT_BUFFER { GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "LookupSid: LookupAccountSid (1st try) failed, gle=" + lastErr); return(lastErr); } Debug.Assert(f == false); // should never succeed, with a 0 buffer size Debug.Assert(nameLength > 0); Debug.Assert(domainNameLength > 0); sbName = new StringBuilder(nameLength); sbDomainName = new StringBuilder(domainNameLength); f = UnsafeNativeMethods.LookupAccountSid(serverName, pSid, sbName, ref nameLength, sbDomainName, ref domainNameLength, ref accountUsage); if (f == false) { lastErr = Marshal.GetLastWin32Error(); Debug.Assert(lastErr != 0); GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "LookupSid: LookupAccountSid (2nd try) failed, gle=" + lastErr); return(lastErr); } name = sbName.ToString(); domainName = sbDomainName.ToString(); return(0); } finally { if (pSid != IntPtr.Zero) { Marshal.FreeHGlobal(pSid); } if (hUser != IntPtr.Zero) { Utils.EndImpersonation(hUser); } } }
public void Dispose() { GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Entering Dispose"); _inner.Dispose(); }
internal static bool BeginImpersonation(NetCred credential, out IntPtr hUserToken) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "Entering BeginImpersonation"); hUserToken = IntPtr.Zero; IntPtr hToken = IntPtr.Zero; // default credential is specified, no need to do impersonation if (credential == null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "BeginImpersonation: nothing to impersonate"); return(false); } // Retrive the parsed username which has had the domain removed because LogonUser // expects creds this way. string userName = credential.ParsedUserName; string password = credential.Password; string domainName = credential.Domain; // no need to do impersonation as username and password are both null if (userName == null && password == null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "BeginImpersonation: nothing to impersonate (2)"); return(false); } GlobalDebug.WriteLineIf(GlobalDebug.Info, "Utils", "BeginImpersonation: trying to impersonate " + userName); int result = UnsafeNativeMethods.LogonUser( userName, domainName, password, 9, /* LOGON32_LOGON_NEW_CREDENTIALS */ 3, /* LOGON32_PROVIDER_WINNT50 */ ref hToken); // check the result if (result == 0) { int lastError = Marshal.GetLastWin32Error(); GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "BeginImpersonation: LogonUser failed, gle=" + lastError); throw new PrincipalOperationException( String.Format(CultureInfo.CurrentCulture, StringResources.UnableToImpersonateCredentials, lastError)); } result = UnsafeNativeMethods.ImpersonateLoggedOnUser(hToken); if (result == 0) { int lastError = Marshal.GetLastWin32Error(); GlobalDebug.WriteLineIf(GlobalDebug.Error, "Utils", "BeginImpersonation: ImpersonateLoggedOnUser failed, gle=" + lastError); // Close the token the was created above.... UnsafeNativeMethods.CloseHandle(hToken); throw new PrincipalOperationException( String.Format(CultureInfo.CurrentCulture, StringResources.UnableToImpersonateCredentials, lastError)); } hUserToken = hToken; return(true); }
// // Internal constructors // internal ValueCollectionEnumerator(TrackedCollection <T> trackingList, List <TrackedCollection <T> .ValueEl> combinedValues) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "ValueCollectionEnumerator", "Ctor"); _inner = new TrackedCollectionEnumerator <T>("ValueCollectionEnumerator", trackingList, combinedValues); }