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; } }
internal override void Move(StoreCtx originalStore, Principal p) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Move"); }
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 void Save(PrincipalContext context) { this.CheckDisposedOrDeleted(); this.CheckFakePrincipal(); if (context.ContextType == ContextType.Machine || this.ctx.ContextType == ContextType.Machine) { throw new InvalidOperationException(StringResources.SaveToNotSupportedAgainstMachineStore); } else { if (context != null) { if (context != this.ctx) { if (context.ContextType == this.ctx.ContextType) { StoreCtx storeCtxToUse = this.GetStoreCtxToUse(); this.ctx = context; StoreCtx storeCtx = this.GetStoreCtxToUse(); if (!this.unpersisted) { this.unpersisted = true; bool flag = this.nameChanged == LoadState.Changed; string str = null; if (flag) { string str1 = this.name; this.ctx.QueryCtx.Load(this, "Principal.Name"); str = this.name; this.Name = str1; } storeCtx.Move(storeCtxToUse, this); try { this.unpersisted = false; storeCtx.Update(this); } catch (SystemException systemException2) { SystemException systemException = systemException2; try { if (flag) { this.Name = str; } storeCtxToUse.Move(storeCtx, this); } catch (SystemException systemException1) { } if (systemException as COMException == null) { throw systemException; } else { throw ExceptionHelper.GetExceptionFromCOMException((COMException)systemException); } } } else { storeCtx.Insert(this); this.unpersisted = false; } this.ctx.QueryCtx = storeCtx; return; } else { throw new InvalidOperationException(StringResources.SaveToMustHaveSamecontextType); } } else { this.Save(); return; } } else { throw new InvalidOperationException(StringResources.NullArguments); } } }
internal static 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(SR.Format(SR.StoreCtxUnsupportedPrincipalTypeForSave, p.GetType())); } // 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); } } }
private void DoLDAPDirectoryInitNoContainer() { string str = null; string str1 = null; byte[] numArray = new byte[] { 169, 209, 202, 21, 118, 136, 17, 209, 173, 237, 0, 192, 79, 216, 213, 205 }; byte[] numArray1 = numArray; byte[] numArray2 = new byte[] { 170, 49, 40, 37, 118, 136, 17, 209, 173, 237, 0, 192, 79, 216, 213, 205 }; byte[] numArray3 = numArray2; DirectoryEntry directoryEntry = null; DirectoryEntry directoryEntry1 = null; DirectoryEntry directoryEntry2 = null; ADStoreCtx aDStoreCtx = null; ADStoreCtx aDStoreCtx1 = null; ADStoreCtx aDStoreCtx2 = null; DirectoryEntry directoryEntry3 = null; string str2 = ""; if (this.name != null) { str2 = string.Concat(this.name, "/"); } AuthenticationTypes authTypes = SDSUtils.MapOptionsToAuthTypes(this.options); using (directoryEntry3) { directoryEntry3 = new DirectoryEntry(string.Concat("LDAP://", str2, "rootDse"), this.username, this.password, authTypes); string item = (string)directoryEntry3.Properties["defaultNamingContext"][0]; str = string.Concat("LDAP://", str2, item); } try { directoryEntry2 = new DirectoryEntry(str, this.username, this.password, authTypes); if (this.serverProperties.portSSL > 0) { directoryEntry2.Options.PasswordPort = this.serverProperties.portSSL; } string str3 = null; PropertyValueCollection propertyValueCollection = directoryEntry2.Properties["wellKnownObjects"]; foreach (UnsafeNativeMethods.IADsDNWithBinary aDsDNWithBinary in propertyValueCollection) { if (Utils.AreBytesEqual(numArray1, (byte[])aDsDNWithBinary.BinaryValue)) { str3 = string.Concat("LDAP://", str2, aDsDNWithBinary.DNString); } if (!Utils.AreBytesEqual(numArray3, (byte[])aDsDNWithBinary.BinaryValue)) { continue; } str1 = string.Concat("LDAP://", str2, aDsDNWithBinary.DNString); } if (str3 == null || str1 == null) { throw new PrincipalOperationException(StringResources.ContextNoWellKnownObjects); } else { directoryEntry = new DirectoryEntry(str3, this.username, this.password, authTypes); directoryEntry1 = new DirectoryEntry(str1, this.username, this.password, authTypes); StoreCtx storeCtx = this.CreateContextFromDirectoryEntry(directoryEntry); this.userCtx = storeCtx; this.groupCtx = storeCtx; directoryEntry = null; this.computerCtx = this.CreateContextFromDirectoryEntry(directoryEntry1); directoryEntry1 = null; this.queryCtx = this.CreateContextFromDirectoryEntry(directoryEntry2); this.connectedServer = ADUtils.GetServerName(directoryEntry2); directoryEntry2 = null; } } catch (Exception exception) { if (directoryEntry != null) { directoryEntry.Dispose(); } if (directoryEntry1 != null) { directoryEntry1.Dispose(); } if (directoryEntry2 != null) { directoryEntry2.Dispose(); } if (aDStoreCtx != null) { aDStoreCtx.Dispose(); } if (aDStoreCtx1 != null) { aDStoreCtx1.Dispose(); } if (aDStoreCtx2 != null) { aDStoreCtx2.Dispose(); } throw; } }
internal abstract ResultSet GetGroupsMemberOf(Principal foreignPrincipal, StoreCtx foreignContext);
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 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; } }
// Get groups from this ctx which contain a principal corresponding to foreignPrincipal // (which is a principal from foreignContext) internal abstract ResultSet GetGroupsMemberOf(Principal foreignPrincipal, StoreCtx foreignContext);
internal abstract void Move(StoreCtx originalStore, Principal p);
internal override void Move(StoreCtx originalStore, Principal p) { }
internal override ResultSet GetGroupsMemberOf(Principal foreignPrincipal, StoreCtx foreignContext) { if (!foreignPrincipal.fakePrincipal) { SecurityIdentifier sid = foreignPrincipal.Sid; if (sid != null) { UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(base.OwningContext, IdentityType.Sid, sid.ToString()); if (userPrincipal != null) { return this.GetGroupsMemberOf(userPrincipal); } else { return new EmptySet(); } } else { throw new InvalidOperationException(StringResources.StoreCtxNeedValueSecurityIdentityClaimToQuery); } } else { return this.GetGroupsMemberOf(foreignPrincipal); } }
internal AuthZSet( byte[] userSid, NetCred credentials, ContextOptions contextOptions, string flatUserAuthority, StoreCtx userStoreCtx, object userCtxBase) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "AuthZSet: SID={0}, authority={1}, storeCtx={2}", Utils.ByteArrayToString(userSid), flatUserAuthority, userStoreCtx.GetType()); _userType = userStoreCtx.OwningContext.ContextType; _userCtxBase = userCtxBase; _userStoreCtx = userStoreCtx; _credentials = credentials; _contextOptions = contextOptions; // flatUserAuthority is flat domain name if userType == Domain, // flat host name if userType == LocalMachine _flatUserAuthority = flatUserAuthority; // Preload the PrincipalContext cache with the user's PrincipalContext _contexts[flatUserAuthority] = userStoreCtx.OwningContext; IntPtr hUser = IntPtr.Zero; // // Get the SIDs of the groups to which the user belongs // IntPtr pClientContext = IntPtr.Zero; IntPtr pResManager = IntPtr.Zero; IntPtr pBuffer = IntPtr.Zero; try { UnsafeNativeMethods.LUID luid = new UnsafeNativeMethods.LUID(); luid.low = 0; luid.high = 0; _psMachineSid = new SafeMemoryPtr(Utils.GetMachineDomainSid()); _psUserSid = new SafeMemoryPtr(Utils.ConvertByteArrayToIntPtr(userSid)); bool f; int lastError = 0; GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Initializing resource manager"); // Create a resource manager f = UnsafeNativeMethods.AuthzInitializeResourceManager( UnsafeNativeMethods.AUTHZ_RM_FLAG.AUTHZ_RM_FLAG_NO_AUDIT, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null, out pResManager ); if (f) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Getting ctx from SID"); // Construct a context for the user based on the user's SID f = UnsafeNativeMethods.AuthzInitializeContextFromSid( 0, // default flags _psUserSid.DangerousGetHandle(), pResManager, IntPtr.Zero, luid, IntPtr.Zero, out pClientContext ); if (f) { int bufferSize = 0; GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Getting info from ctx"); // Extract the group SIDs from the user's context. Determine the size of the buffer we need. f = UnsafeNativeMethods.AuthzGetInformationFromContext( pClientContext, 2, // AuthzContextInfoGroupsSids 0, out bufferSize, IntPtr.Zero ); if (!f && (bufferSize > 0) && (Marshal.GetLastWin32Error() == 122) /*ERROR_INSUFFICIENT_BUFFER*/) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Getting info from ctx (size={0})", bufferSize); Debug.Assert(bufferSize > 0); // Set up the needed buffer pBuffer = Marshal.AllocHGlobal(bufferSize); // Extract the group SIDs from the user's context, into our buffer.0 f = UnsafeNativeMethods.AuthzGetInformationFromContext( pClientContext, 2, // AuthzContextInfoGroupsSids bufferSize, out bufferSize, pBuffer ); if (f) { // Marshall the native buffer into managed SID_AND_ATTR structures. // The native buffer holds a TOKEN_GROUPS structure: // // struct TOKEN_GROUPS { // DWORD GroupCount; // SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]; // }; // // Extract TOKEN_GROUPS.GroupCount UnsafeNativeMethods.TOKEN_GROUPS tokenGroups = (UnsafeNativeMethods.TOKEN_GROUPS)Marshal.PtrToStructure(pBuffer, typeof(UnsafeNativeMethods.TOKEN_GROUPS)); int groupCount = tokenGroups.groupCount; GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Found {0} groups", groupCount); // Extract TOKEN_GROUPS.Groups, by iterating over the array and marshalling // each native SID_AND_ATTRIBUTES into a managed SID_AND_ATTR. UnsafeNativeMethods.SID_AND_ATTR[] groups = new UnsafeNativeMethods.SID_AND_ATTR[groupCount]; IntPtr currentItem = new IntPtr(pBuffer.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.TOKEN_GROUPS)) - Marshal.SizeOf(typeof(IntPtr))); for (int i = 0; i < groupCount; i++) { groups[i] = (UnsafeNativeMethods.SID_AND_ATTR)Marshal.PtrToStructure(currentItem, typeof(UnsafeNativeMethods.SID_AND_ATTR)); currentItem = new IntPtr(currentItem.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.SID_AND_ATTR))); } _groupSidList = new SidList(groups); } else { lastError = Marshal.GetLastWin32Error(); } } else { lastError = Marshal.GetLastWin32Error(); // With a zero-length buffer, this should have never succeeded Debug.Assert(false); } } else { lastError = Marshal.GetLastWin32Error(); } } else { lastError = Marshal.GetLastWin32Error(); } if (!f) { GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "Failed to retrieve group list, {0}", lastError); throw new PrincipalOperationException( String.Format( CultureInfo.CurrentCulture, StringResources.AuthZFailedToRetrieveGroupList, lastError)); } // Save off the buffer since it still holds the native SIDs referenced by SidList _psBuffer = new SafeMemoryPtr(pBuffer); pBuffer = IntPtr.Zero; } catch (Exception e) { GlobalDebug.WriteLineIf(GlobalDebug.Error, "AuthZSet", "Caught exception {0} with message {1}", e.GetType(), e.Message); if (_psBuffer != null && !_psBuffer.IsInvalid) _psBuffer.Close(); if (_psUserSid != null && !_psUserSid.IsInvalid) _psUserSid.Close(); if (_psMachineSid != null && !_psMachineSid.IsInvalid) _psMachineSid.Close(); // We're on a platform that doesn't have the AuthZ library if (e is DllNotFoundException) throw new NotSupportedException(StringResources.AuthZNotSupported, e); if (e is EntryPointNotFoundException) throw new NotSupportedException(StringResources.AuthZNotSupported, e); throw; } finally { if (pClientContext != IntPtr.Zero) UnsafeNativeMethods.AuthzFreeContext(pClientContext); if (pResManager != IntPtr.Zero) UnsafeNativeMethods.AuthzFreeResourceManager(pResManager); if (pBuffer != IntPtr.Zero) Marshal.FreeHGlobal(pBuffer); } }
// Get groups from this ctx which contain a principal corresponding to foreignPrincipal // (which is a principal from foreignContext) internal override ResultSet GetGroupsMemberOf(Principal foreignPrincipal, StoreCtx foreignContext) { // If it's a fake principal, we don't need to do any of the lookup to find a local representation. // We'll skip straight to GetGroupsMemberOf(Principal), which will lookup the groups to which it belongs via its SID. if (foreignPrincipal.fakePrincipal) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetGroupsMemberOf(ctx): is fake principal"); return GetGroupsMemberOf(foreignPrincipal); } // Get the Principal's SID, so we can look it up by SID in our store SecurityIdentifier Sid = foreignPrincipal.Sid; if (Sid == null) { GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "GetGroupsMemberOf(ctx): no SID IC"); throw new InvalidOperationException(StringResources.StoreCtxNeedValueSecurityIdentityClaimToQuery); } // In SAM, only users can be member of SAM groups (no nested groups) UserPrincipal u = UserPrincipal.FindByIdentity(this.OwningContext, IdentityType.Sid, Sid.ToString()); // If no corresponding principal exists in this store, then by definition the principal isn't // a member of any groups in this store. if (u == null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "GetGroupsMemberOf(ctx): no corresponding user, returning empty set"); return new EmptySet(); } // Now that we got the principal in our store, enumerating its group membership can be handled the // usual way. return GetGroupsMemberOf(u); }
public bool Remove(Principal principal) { CheckDisposed(); if (principal == null) { throw new ArgumentNullException(nameof(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 an 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); }
private void DoLDAPDirectoryInit() { int num; string str = ""; if (this.name != null) { if (this.contextType != ContextType.ApplicationDirectory) { str = this.name; } else { string str1 = this.serverProperties.dnsHostName; string str2 = ":"; if ((ContextOptions.SecureSocketLayer & this.options) > 0) { num = this.serverProperties.portSSL; } else { num = this.serverProperties.portLDAP; } str = string.Concat(str1, str2, num); } str = string.Concat(str, "/"); } AuthenticationTypes authTypes = SDSUtils.MapOptionsToAuthTypes(this.options); using (DirectoryEntry directoryEntry = new DirectoryEntry(string.Concat("LDAP://", str, this.container), this.username, this.password, authTypes)) { try { if (this.serverProperties.portSSL > 0) { directoryEntry.Options.PasswordPort = this.serverProperties.portSSL; } StoreCtx storeCtx = this.CreateContextFromDirectoryEntry(directoryEntry); this.queryCtx = storeCtx; this.userCtx = storeCtx; this.groupCtx = storeCtx; this.computerCtx = storeCtx; this.connectedServer = ADUtils.GetServerName(directoryEntry); } catch (COMException cOMException1) { COMException cOMException = cOMException1; throw ExceptionHelper.GetExceptionFromCOMException(cOMException); } catch (Exception exception) { throw; } } }
internal override void Move(StoreCtx originalStore, Principal p) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Move"); }
private void DoMachineInit() { DirectoryEntry directoryEntry = null; try { string computerFlatName = this.name; if (computerFlatName == null) { computerFlatName = Utils.GetComputerFlatName(); } AuthenticationTypes authTypes = SDSUtils.MapOptionsToAuthTypes(this.options); directoryEntry = new DirectoryEntry(string.Concat("WinNT://", computerFlatName, ",computer"), this.username, this.password, authTypes); directoryEntry.RefreshCache(); StoreCtx storeCtx = this.CreateContextFromDirectoryEntry(directoryEntry); this.queryCtx = storeCtx; this.userCtx = storeCtx; this.groupCtx = storeCtx; this.computerCtx = storeCtx; this.connectedServer = computerFlatName; directoryEntry = null; } catch (Exception exception) { if (directoryEntry != null) { directoryEntry.Dispose(); } throw; } }
internal AuthZSet( byte[] userSid, NetCred credentials, ContextOptions contextOptions, string flatUserAuthority, StoreCtx userStoreCtx, object userCtxBase) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "AuthZSet: SID={0}, authority={1}, storeCtx={2}", Utils.ByteArrayToString(userSid), flatUserAuthority, userStoreCtx.GetType()); _userType = userStoreCtx.OwningContext.ContextType; _userCtxBase = userCtxBase; _userStoreCtx = userStoreCtx; _credentials = credentials; _contextOptions = contextOptions; // flatUserAuthority is flat domain name if userType == Domain, // flat host name if userType == LocalMachine _flatUserAuthority = flatUserAuthority; // Preload the PrincipalContext cache with the user's PrincipalContext _contexts[flatUserAuthority] = userStoreCtx.OwningContext; IntPtr hUser = IntPtr.Zero; // // Get the SIDs of the groups to which the user belongs // IntPtr pClientContext = IntPtr.Zero; IntPtr pResManager = IntPtr.Zero; IntPtr pBuffer = IntPtr.Zero; try { UnsafeNativeMethods.LUID luid = new UnsafeNativeMethods.LUID(); luid.low = 0; luid.high = 0; _psMachineSid = new SafeMemoryPtr(Utils.GetMachineDomainSid()); _psUserSid = new SafeMemoryPtr(Utils.ConvertByteArrayToIntPtr(userSid)); bool f; int lastError = 0; GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Initializing resource manager"); // Create a resource manager f = UnsafeNativeMethods.AuthzInitializeResourceManager( UnsafeNativeMethods.AUTHZ_RM_FLAG.AUTHZ_RM_FLAG_NO_AUDIT, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null, out pResManager ); if (f) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Getting ctx from SID"); // Construct a context for the user based on the user's SID f = UnsafeNativeMethods.AuthzInitializeContextFromSid( 0, // default flags _psUserSid.DangerousGetHandle(), pResManager, IntPtr.Zero, luid, IntPtr.Zero, out pClientContext ); if (f) { int bufferSize = 0; GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Getting info from ctx"); // Extract the group SIDs from the user's context. Determine the size of the buffer we need. f = UnsafeNativeMethods.AuthzGetInformationFromContext( pClientContext, 2, // AuthzContextInfoGroupsSids 0, out bufferSize, IntPtr.Zero ); if (!f && (bufferSize > 0) && (Marshal.GetLastWin32Error() == 122) /*ERROR_INSUFFICIENT_BUFFER*/) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Getting info from ctx (size={0})", bufferSize); Debug.Assert(bufferSize > 0); // Set up the needed buffer pBuffer = Marshal.AllocHGlobal(bufferSize); // Extract the group SIDs from the user's context, into our buffer.0 f = UnsafeNativeMethods.AuthzGetInformationFromContext( pClientContext, 2, // AuthzContextInfoGroupsSids bufferSize, out bufferSize, pBuffer ); if (f) { // Marshall the native buffer into managed SID_AND_ATTR structures. // The native buffer holds a TOKEN_GROUPS structure: // // struct TOKEN_GROUPS { // DWORD GroupCount; // SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]; // }; // // Extract TOKEN_GROUPS.GroupCount UnsafeNativeMethods.TOKEN_GROUPS tokenGroups = (UnsafeNativeMethods.TOKEN_GROUPS)Marshal.PtrToStructure(pBuffer, typeof(UnsafeNativeMethods.TOKEN_GROUPS)); int groupCount = tokenGroups.groupCount; GlobalDebug.WriteLineIf(GlobalDebug.Info, "AuthZSet", "Found {0} groups", groupCount); // Extract TOKEN_GROUPS.Groups, by iterating over the array and marshalling // each native SID_AND_ATTRIBUTES into a managed SID_AND_ATTR. UnsafeNativeMethods.SID_AND_ATTR[] groups = new UnsafeNativeMethods.SID_AND_ATTR[groupCount]; IntPtr currentItem = new IntPtr(pBuffer.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.TOKEN_GROUPS)) - IntPtr.Size); for (int i = 0; i < groupCount; i++) { groups[i] = (UnsafeNativeMethods.SID_AND_ATTR)Marshal.PtrToStructure(currentItem, typeof(UnsafeNativeMethods.SID_AND_ATTR)); currentItem = new IntPtr(currentItem.ToInt64() + Marshal.SizeOf(typeof(UnsafeNativeMethods.SID_AND_ATTR))); } _groupSidList = new SidList(groups); } else { lastError = Marshal.GetLastWin32Error(); } } else { lastError = Marshal.GetLastWin32Error(); Debug.Fail("With a zero-length buffer, this should have never succeeded"); } } else { lastError = Marshal.GetLastWin32Error(); } } else { lastError = Marshal.GetLastWin32Error(); } if (!f) { GlobalDebug.WriteLineIf(GlobalDebug.Warn, "AuthZSet", "Failed to retrieve group list, {0}", lastError); throw new PrincipalOperationException( SR.Format( SR.AuthZFailedToRetrieveGroupList, lastError)); } // Save off the buffer since it still holds the native SIDs referenced by SidList _psBuffer = new SafeMemoryPtr(pBuffer); pBuffer = IntPtr.Zero; } catch (Exception e) { GlobalDebug.WriteLineIf(GlobalDebug.Error, "AuthZSet", "Caught exception {0} with message {1}", e.GetType(), e.Message); if (_psBuffer != null && !_psBuffer.IsInvalid) { _psBuffer.Close(); } if (_psUserSid != null && !_psUserSid.IsInvalid) { _psUserSid.Close(); } if (_psMachineSid != null && !_psMachineSid.IsInvalid) { _psMachineSid.Close(); } // We're on a platform that doesn't have the AuthZ library if (e is DllNotFoundException) { throw new NotSupportedException(SR.AuthZNotSupported, e); } if (e is EntryPointNotFoundException) { throw new NotSupportedException(SR.AuthZNotSupported, e); } throw; } finally { if (pClientContext != IntPtr.Zero) { UnsafeNativeMethods.AuthzFreeContext(pClientContext); } if (pResManager != IntPtr.Zero) { UnsafeNativeMethods.AuthzFreeResourceManager(pResManager); } if (pBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(pBuffer); } } }
internal abstract void Move(StoreCtx originalStore, Principal p);
internal AuthZSet(byte[] userSid, NetCred credentials, ContextOptions contextOptions, string flatUserAuthority, StoreCtx userStoreCtx, object userCtxBase) { this.currentGroup = -1; this.contexts = new Hashtable(); this.localMachineIsDC = null; this.userType = userStoreCtx.OwningContext.ContextType; this.userCtxBase = userCtxBase; this.userStoreCtx = userStoreCtx; this.credentials = credentials; this.contextOptions = contextOptions; this.flatUserAuthority = flatUserAuthority; this.contexts[flatUserAuthority] = userStoreCtx.OwningContext; IntPtr zero = IntPtr.Zero; IntPtr intPtr = IntPtr.Zero; IntPtr zero1 = IntPtr.Zero; try { try { UnsafeNativeMethods.LUID lUID = new UnsafeNativeMethods.LUID(); lUID.low = 0; lUID.high = 0; this.psMachineSid = new AuthZSet.SafeMemoryPtr(Utils.GetMachineDomainSid()); this.psUserSid = new AuthZSet.SafeMemoryPtr(Utils.ConvertByteArrayToIntPtr(userSid)); int lastWin32Error = 0; bool flag = UnsafeNativeMethods.AuthzInitializeResourceManager(UnsafeNativeMethods.AUTHZ_RM_FLAG.AUTHZ_RM_FLAG_NO_AUDIT, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null, out intPtr); if (!flag) { lastWin32Error = Marshal.GetLastWin32Error(); } else { flag = UnsafeNativeMethods.AuthzInitializeContextFromSid(0, this.psUserSid.DangerousGetHandle(), intPtr, IntPtr.Zero, lUID, IntPtr.Zero, out zero); if (!flag) { lastWin32Error = Marshal.GetLastWin32Error(); } else { int num = 0; flag = UnsafeNativeMethods.AuthzGetInformationFromContext(zero, 2, 0, out num, IntPtr.Zero); if (flag || num <= 0 || Marshal.GetLastWin32Error() != 122) { lastWin32Error = Marshal.GetLastWin32Error(); } else { zero1 = Marshal.AllocHGlobal(num); flag = UnsafeNativeMethods.AuthzGetInformationFromContext(zero, 2, num, out num, zero1); if (!flag) { lastWin32Error = Marshal.GetLastWin32Error(); } else { UnsafeNativeMethods.TOKEN_GROUPS structure = (UnsafeNativeMethods.TOKEN_GROUPS)Marshal.PtrToStructure(zero1, typeof(UnsafeNativeMethods.TOKEN_GROUPS)); int num1 = structure.groupCount; UnsafeNativeMethods.SID_AND_ATTR[] sIDANDATTRArray = new UnsafeNativeMethods.SID_AND_ATTR[num1]; IntPtr intPtr1 = new IntPtr(zero1.ToInt64() + (long)Marshal.SizeOf(typeof(UnsafeNativeMethods.TOKEN_GROUPS)) - (long)Marshal.SizeOf(typeof(IntPtr))); for (int i = 0; i < num1; i++) { sIDANDATTRArray[i] = (UnsafeNativeMethods.SID_AND_ATTR)Marshal.PtrToStructure(intPtr1, typeof(UnsafeNativeMethods.SID_AND_ATTR)); intPtr1 = new IntPtr(intPtr1.ToInt64() + (long)Marshal.SizeOf(typeof(UnsafeNativeMethods.SID_AND_ATTR))); } this.groupSidList = new SidList(sIDANDATTRArray); } } } } if (flag) { this.psBuffer = new AuthZSet.SafeMemoryPtr(zero1); zero1 = IntPtr.Zero; } else { object[] objArray = new object[1]; objArray[0] = lastWin32Error; throw new PrincipalOperationException(string.Format(CultureInfo.CurrentCulture, StringResources.AuthZFailedToRetrieveGroupList, objArray)); } } catch (Exception exception1) { Exception exception = exception1; if (this.psBuffer != null && !this.psBuffer.IsInvalid) { this.psBuffer.Close(); } if (this.psUserSid != null && !this.psUserSid.IsInvalid) { this.psUserSid.Close(); } if (this.psMachineSid != null && !this.psMachineSid.IsInvalid) { this.psMachineSid.Close(); } if (exception as DllNotFoundException == null) { if (exception as EntryPointNotFoundException == null) { throw; } else { throw new NotSupportedException(StringResources.AuthZNotSupported, exception); } } else { throw new NotSupportedException(StringResources.AuthZNotSupported, exception); } } } finally { if (zero != IntPtr.Zero) { UnsafeNativeMethods.AuthzFreeContext(zero); } if (intPtr != IntPtr.Zero) { UnsafeNativeMethods.AuthzFreeResourceManager(intPtr); } if (zero1 != IntPtr.Zero) { Marshal.FreeHGlobal(zero1); } } }