internal SidList(List <byte[]> sidListByteFormat, string target, NetCred credentials) { this.entries = new List <SidListEntry>(); IntPtr zero = IntPtr.Zero; int count = sidListByteFormat.Count; IntPtr[] intPtr = new IntPtr[count]; for (int i = 0; i < count; i++) { intPtr[i] = Utils.ConvertByteArrayToIntPtr(sidListByteFormat[i]); } try { if (credentials != null) { Utils.BeginImpersonation(credentials, out zero); } this.TranslateSids(target, intPtr); } finally { if (zero != IntPtr.Zero) { Utils.EndImpersonation(zero); } } }
internal static DirectoryEntry BuildDirectoryEntry(NetCred credentials, AuthenticationTypes authTypes) { string userName; string password; DirectoryEntry directoryEntry = new DirectoryEntry(); DirectoryEntry directoryEntry1 = directoryEntry; if (credentials != null) { userName = credentials.UserName; } else { userName = null; } directoryEntry1.Username = userName; DirectoryEntry directoryEntry2 = directoryEntry; if (credentials != null) { password = credentials.Password; } else { password = null; } directoryEntry2.Password = password; directoryEntry.AuthenticationType = authTypes; return(directoryEntry); }
internal SidList(List<Byte[]> sidListByteFormat, string target, NetCred credentials) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SidList", "SidList: processing {0} ByteFormat SIDs", sidListByteFormat.Count); GlobalDebug.WriteLineIf(GlobalDebug.Info, "SidList", "SidList: Targetting {0} ", (target != null) ? target : "local store"); // Build the list of SIDs to resolve IntPtr hUser = IntPtr.Zero; int sidCount = sidListByteFormat.Count; IntPtr[] pSids = new IntPtr[sidCount]; for (int i = 0; i < sidCount; i++) { pSids[i] = Utils.ConvertByteArrayToIntPtr(sidListByteFormat[i]); } try { if (credentials != null) { Utils.BeginImpersonation(credentials, out hUser); } TranslateSids(target, pSids); } finally { if (hUser != IntPtr.Zero) Utils.EndImpersonation(hUser); } }
internal SidList(List <Byte[]> sidListByteFormat, string target, NetCred credentials) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SidList", "SidList: processing {0} ByteFormat SIDs", sidListByteFormat.Count); GlobalDebug.WriteLineIf(GlobalDebug.Info, "SidList", "SidList: Targetting {0} ", (target != null) ? target : "local store"); // Build the list of SIDs to resolve IntPtr hUser = IntPtr.Zero; int sidCount = sidListByteFormat.Count; IntPtr[] pSids = new IntPtr[sidCount]; for (int i = 0; i < sidCount; i++) { pSids[i] = Utils.ConvertByteArrayToIntPtr(sidListByteFormat[i]); } try { if (credentials != null) { Utils.BeginImpersonation(credentials, out hUser); } TranslateSids(target, pSids); } finally { if (hUser != IntPtr.Zero) { Utils.EndImpersonation(hUser); } } }
internal static DirectoryEntry BuildDirectoryEntry(string path, NetCred credentials, AuthenticationTypes authTypes) { string userName; string password; string str = path; if (credentials != null) { userName = credentials.UserName; } else { userName = null; } if (credentials != null) { password = credentials.Password; } else { password = null; } DirectoryEntry directoryEntry = new DirectoryEntry(str, userName, password, authTypes); return(directoryEntry); }
internal SidList(List<byte[]> sidListByteFormat, string target, NetCred credentials) { this.entries = new List<SidListEntry>(); IntPtr zero = IntPtr.Zero; int count = sidListByteFormat.Count; IntPtr[] intPtr = new IntPtr[count]; for (int i = 0; i < count; i++) { intPtr[i] = Utils.ConvertByteArrayToIntPtr(sidListByteFormat[i]); } try { if (credentials != null) { Utils.BeginImpersonation(credentials, out zero); } this.TranslateSids(target, intPtr); } finally { if (zero != IntPtr.Zero) { Utils.EndImpersonation(zero); } } }
static internal DirectoryEntry BuildDirectoryEntry(string path, NetCred credentials, AuthenticationTypes authTypes) { DirectoryEntry de = new DirectoryEntry(path, credentials != null ? credentials.UserName : null, credentials != null ? credentials.Password : null, authTypes); GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "BuildDirectoryEntry (1): built DE for " + de.Path); return(de); }
internal static int LookupSid(string serverName, NetCred credentials, byte[] sid, out string name, out string domainName, out int accountUsage) { int num; IntPtr zero = IntPtr.Zero; int num1 = 0; int num2 = 0; accountUsage = 0; name = null; domainName = null; IntPtr intPtr = IntPtr.Zero; try { zero = Utils.ConvertByteArrayToIntPtr(sid); Utils.BeginImpersonation(credentials, out intPtr); bool flag = UnsafeNativeMethods.LookupAccountSid(serverName, zero, null, ref num1, null, ref num2, ref accountUsage); int lastWin32Error = Marshal.GetLastWin32Error(); if (lastWin32Error == 122) { StringBuilder stringBuilder = new StringBuilder(num1); StringBuilder stringBuilder1 = new StringBuilder(num2); flag = UnsafeNativeMethods.LookupAccountSid(serverName, zero, stringBuilder, ref num1, stringBuilder1, ref num2, ref accountUsage); if (flag) { name = stringBuilder.ToString(); domainName = stringBuilder1.ToString(); num = 0; } else { lastWin32Error = Marshal.GetLastWin32Error(); num = lastWin32Error; } } else { num = lastWin32Error; } } finally { if (zero != IntPtr.Zero) { Marshal.FreeHGlobal(zero); } if (intPtr != IntPtr.Zero) { Utils.EndImpersonation(intPtr); } } return(num); }
static internal DirectoryEntry BuildDirectoryEntry(NetCred credentials, AuthenticationTypes authTypes) { DirectoryEntry de = new DirectoryEntry(); de.Username = credentials != null ? credentials.UserName : null; de.Password = credentials != null ? credentials.Password : null; de.AuthenticationType = authTypes; GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "BuildDirectoryEntry (2): built DE"); return(de); }
internal static bool BeginImpersonation(NetCred credential, out IntPtr hUserToken) { hUserToken = IntPtr.Zero; IntPtr zero = IntPtr.Zero; if (credential != null) { string parsedUserName = credential.ParsedUserName; string password = credential.Password; string domain = credential.Domain; if (parsedUserName != null || password != null) { int num = UnsafeNativeMethods.LogonUser(parsedUserName, domain, password, 9, 3, ref zero); if (num != 0) { num = UnsafeNativeMethods.ImpersonateLoggedOnUser(zero); if (num != 0) { hUserToken = zero; return(true); } else { int lastWin32Error = Marshal.GetLastWin32Error(); UnsafeNativeMethods.CloseHandle(zero); object[] objArray = new object[1]; objArray[0] = lastWin32Error; throw new PrincipalOperationException(string.Format(CultureInfo.CurrentCulture, StringResources.UnableToImpersonateCredentials, objArray)); } } else { int lastWin32Error1 = Marshal.GetLastWin32Error(); object[] objArray1 = new object[1]; objArray1[0] = lastWin32Error1; throw new PrincipalOperationException(string.Format(CultureInfo.CurrentCulture, StringResources.UnableToImpersonateCredentials, objArray1)); } } else { return(false); } } else { return(false); } }
internal static bool BeginImpersonation(NetCred credential, out IntPtr hUserToken) { hUserToken = IntPtr.Zero; IntPtr zero = IntPtr.Zero; if (credential != null) { string parsedUserName = credential.ParsedUserName; string password = credential.Password; string domain = credential.Domain; if (parsedUserName != null || password != null) { int num = UnsafeNativeMethods.LogonUser(parsedUserName, domain, password, 9, 3, ref zero); if (num != 0) { num = UnsafeNativeMethods.ImpersonateLoggedOnUser(zero); if (num != 0) { hUserToken = zero; return true; } else { int lastWin32Error = Marshal.GetLastWin32Error(); UnsafeNativeMethods.CloseHandle(zero); object[] objArray = new object[1]; objArray[0] = lastWin32Error; throw new PrincipalOperationException(string.Format(CultureInfo.CurrentCulture, StringResources.UnableToImpersonateCredentials, objArray)); } } else { int lastWin32Error1 = Marshal.GetLastWin32Error(); object[] objArray1 = new object[1]; objArray1[0] = lastWin32Error1; throw new PrincipalOperationException(string.Format(CultureInfo.CurrentCulture, StringResources.UnableToImpersonateCredentials, objArray1)); } } else { return false; } } else { return false; } }
// Throws exception if ctxBase is not a computer object public SAMStoreCtx(DirectoryEntry ctxBase, bool ownCtxBase, string username, string password, ContextOptions options) { Debug.Assert(ctxBase != null); GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Constructing SAMStoreCtx for {0}", ctxBase.Path); Debug.Assert(SAMUtils.IsOfObjectClass(ctxBase, "Computer")); _ctxBase = ctxBase; _ownCtxBase = ownCtxBase; if (username != null && password != null) { _credentials = new NetCred(username, password); } _contextOptions = options; _authTypes = SDSUtils.MapOptionsToAuthTypes(options); }
static internal void ApplyChangesToDirectory( Principal p, StoreCtx storeCtx, GroupMembershipUpdater updateGroupMembership, NetCred credentials, AuthenticationTypes authTypes) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "Entering ApplyChangesToDirectory"); Debug.Assert(storeCtx != null); Debug.Assert(storeCtx is ADStoreCtx || storeCtx is SAMStoreCtx || storeCtx is ADAMStoreCtx); Debug.Assert(p != null); Debug.Assert(updateGroupMembership != null); // Update the properties in the DirectoryEntry. Note that this does NOT // update group membership. DirectoryEntry de = (DirectoryEntry)storeCtx.PushChangesToNative(p); Debug.Assert(de == p.UnderlyingObject); // Commit the property update try { de.CommitChanges(); } catch (System.Runtime.InteropServices.COMException e) { GlobalDebug.WriteLineIf(GlobalDebug.Error, "SDSUtils", "ApplyChangesToDirectory: caught COMException with message " + e.Message); throw (ExceptionHelper.GetExceptionFromCOMException(e)); } if ((p is GroupPrincipal) && (p.GetChangeStatusForProperty(PropertyNames.GroupMembers))) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "ApplyChangesToDirectory: Updating group membership"); // It's a group, and it's membership has changed. Commit those membership changes. // Note that this is an immediate operation, because it goes through IADsGroup, // and does not require a call to de.CommitChanges(). updateGroupMembership(p, de, credentials, authTypes); } }
public SAMStoreCtx(DirectoryEntry ctxBase, bool ownCtxBase, string username, string password, ContextOptions options) { this.ctxBaseLock = new object(); this.computerInfoLock = new object(); this.isLSAM = null; this.ctxBase = ctxBase; this.ownCtxBase = ownCtxBase; if (username != null && password != null) { this.credentials = new NetCred(username, password); } this.contextOptions = options; this.authTypes = SDSUtils.MapOptionsToAuthTypes(options); }
// Throws exception if ctxBase is not a computer object public SAMStoreCtx(DirectoryEntry ctxBase, bool ownCtxBase, string username, string password, ContextOptions options) { Debug.Assert(ctxBase != null); GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Constructing SAMStoreCtx for {0}", ctxBase.Path); Debug.Assert(SAMUtils.IsOfObjectClass(ctxBase, "Computer")); _ctxBase = ctxBase; _ownCtxBase = ownCtxBase; if (username != null && password != null) _credentials = new NetCred(username, password); _contextOptions = options; _authTypes = SDSUtils.MapOptionsToAuthTypes(options); }
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); } }
public PrincipalContext GetContext(string name, NetCred credentials, ContextOptions contextOptions) { string nT4UserName; PrincipalContext target; PrincipalContext principalContext; ContextType contextType; string userName; string password; Hashtable hashtables; Hashtable hashtables1; string domainName = name; bool flag = false; if (credentials == null || credentials.UserName == null) { nT4UserName = Utils.GetNT4UserName(); } else { if (credentials.Domain == null) { nT4UserName = credentials.UserName; } else { nT4UserName = string.Concat(credentials.Domain, "\\", credentials.UserName); } flag = true; } if (!this.isSAM) { int num = 0x40000110; UnsafeNativeMethods.DomainControllerInfo dcName = Utils.GetDcName(null, domainName, null, num); domainName = dcName.DomainName; } ManualResetEvent manualResetEvent = null; while (true) { Hashtable hashtables2 = null; if (manualResetEvent != null) { manualResetEvent.WaitOne(); } manualResetEvent = null; lock (this.tableLock) { SDSCache.CredHolder item = (SDSCache.CredHolder)this.table[domainName]; if (item != null) { if (flag) { hashtables1 = item.explicitCreds; } else { hashtables1 = item.defaultCreds; } hashtables2 = hashtables1; object obj = hashtables2[nT4UserName]; if (obj as SDSCache.Placeholder == null) { WeakReference weakReference = obj as WeakReference; if (weakReference != null) { target = (PrincipalContext)weakReference.Target; if (target == null || target.Disposed) { hashtables2.Remove(nT4UserName); } else { principalContext = target; break; } } } else { manualResetEvent = ((SDSCache.Placeholder)obj).contextReadyEvent; continue; } } if (item == null) { item = new SDSCache.CredHolder(); this.table[domainName] = item; if (flag) { hashtables = item.explicitCreds; } else { hashtables = item.defaultCreds; } hashtables2 = hashtables; } hashtables2[nT4UserName] = new SDSCache.Placeholder(); if (this.isSAM) { contextType = ContextType.Machine; } else { contextType = ContextType.Domain; } string str = domainName; object obj1 = null; ContextOptions contextOption = contextOptions; if (credentials != null) { userName = credentials.UserName; } else { userName = null; } if (credentials != null) { password = credentials.Password; } else { password = null; } target = new PrincipalContext(contextType, str, obj1, contextOption, userName, password); lock (this.tableLock) { SDSCache.Placeholder placeholder = (SDSCache.Placeholder)hashtables2[nT4UserName]; hashtables2[nT4UserName] = new WeakReference(target); placeholder.contextReadyEvent.Set(); } return target; } } return principalContext; }
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 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 PrincipalContext GetContext(string name, NetCred credentials, ContextOptions contextOptions) { string nT4UserName; PrincipalContext target; PrincipalContext principalContext; ContextType contextType; string userName; string password; Hashtable hashtables; Hashtable hashtables1; string domainName = name; bool flag = false; if (credentials == null || credentials.UserName == null) { nT4UserName = Utils.GetNT4UserName(); } else { if (credentials.Domain == null) { nT4UserName = credentials.UserName; } else { nT4UserName = string.Concat(credentials.Domain, "\\", credentials.UserName); } flag = true; } if (!this.isSAM) { int num = 0x40000110; UnsafeNativeMethods.DomainControllerInfo dcName = Utils.GetDcName(null, domainName, null, num); domainName = dcName.DomainName; } ManualResetEvent manualResetEvent = null; while (true) { Hashtable hashtables2 = null; if (manualResetEvent != null) { manualResetEvent.WaitOne(); } manualResetEvent = null; lock (this.tableLock) { SDSCache.CredHolder item = (SDSCache.CredHolder) this.table[domainName]; if (item != null) { if (flag) { hashtables1 = item.explicitCreds; } else { hashtables1 = item.defaultCreds; } hashtables2 = hashtables1; object obj = hashtables2[nT4UserName]; if (obj as SDSCache.Placeholder == null) { WeakReference weakReference = obj as WeakReference; if (weakReference != null) { target = (PrincipalContext)weakReference.Target; if (target == null || target.Disposed) { hashtables2.Remove(nT4UserName); } else { principalContext = target; break; } } } else { manualResetEvent = ((SDSCache.Placeholder)obj).contextReadyEvent; continue; } } if (item == null) { item = new SDSCache.CredHolder(); this.table[domainName] = item; if (flag) { hashtables = item.explicitCreds; } else { hashtables = item.defaultCreds; } hashtables2 = hashtables; } hashtables2[nT4UserName] = new SDSCache.Placeholder(); if (this.isSAM) { contextType = ContextType.Machine; } else { contextType = ContextType.Domain; } string str = domainName; object obj1 = null; ContextOptions contextOption = contextOptions; if (credentials != null) { userName = credentials.UserName; } else { userName = null; } if (credentials != null) { password = credentials.Password; } else { password = null; } target = new PrincipalContext(contextType, str, obj1, contextOption, userName, password); lock (this.tableLock) { SDSCache.Placeholder placeholder = (SDSCache.Placeholder)hashtables2[nT4UserName]; hashtables2[nT4UserName] = new WeakReference(target); placeholder.contextReadyEvent.Set(); } return(target); } } return(principalContext); }
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); } } }
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 != null ? credentials.UserName : null), (credentials != null ? credentials.Password : null) ); 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 == true); } return ctx; } }
internal static void WriteAttribute(string dePath, string attribute, int value, NetCred credentials, AuthenticationTypes authTypes) { DirectoryEntry directoryEntry = null; using (directoryEntry) { try { directoryEntry = SDSUtils.BuildDirectoryEntry(dePath, credentials, authTypes); string[] strArrays = new string[1]; strArrays[0] = attribute; directoryEntry.RefreshCache(strArrays); directoryEntry.Properties[attribute].Value = value; directoryEntry.CommitChanges(); } catch (COMException cOMException1) { COMException cOMException = cOMException1; throw ExceptionHelper.GetExceptionFromCOMException(cOMException); } } }
internal static void InsertPrincipal(Principal p, StoreCtx storeCtx, SDSUtils.GroupMembershipUpdater updateGroupMembership, NetCred credentials, AuthenticationTypes authTypes, bool needToSetPassword) { if (p as UserPrincipal != null || p as GroupPrincipal != null || p as AuthenticablePrincipal != null || p as ComputerPrincipal != null) { SDSUtils.ApplyChangesToDirectory(p, storeCtx, updateGroupMembership, credentials, authTypes); if (needToSetPassword && p.GetChangeStatusForProperty("AuthenticablePrincipal.PasswordInfo.Password")) { string valueForProperty = (string)p.GetValueForProperty("AuthenticablePrincipal.PasswordInfo.Password"); storeCtx.SetPassword((AuthenticablePrincipal)p, valueForProperty); } if (p.GetChangeStatusForProperty("AuthenticablePrincipal.PasswordInfo.ExpireImmediately")) { bool flag = (bool)p.GetValueForProperty("AuthenticablePrincipal.PasswordInfo.ExpireImmediately"); if (flag) { storeCtx.ExpirePassword((AuthenticablePrincipal)p); } } return; } else { object[] str = new object[1]; str[0] = p.GetType().ToString(); throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxUnsupportedPrincipalTypeForSave, str)); } }
internal static Principal ConstructFakePrincipalFromSID(byte[] sid, PrincipalContext ctx, string serverName, NetCred credentials, string authorityName) { string str = null; string str1 = null; string str2; string str3 = ""; int num = 0; int num1 = Utils.LookupSid(serverName, credentials, sid, out str, out str1, out num); if (num1 == 0) { if (!string.IsNullOrEmpty(str1)) { str2 = string.Concat(str1, "\\"); } else { str2 = ""; } str3 = string.Concat(str2, str); } GroupPrincipal groupPrincipal = GroupPrincipal.MakeGroup(ctx); groupPrincipal.fakePrincipal = true; groupPrincipal.unpersisted = false; groupPrincipal.LoadValueIntoProperty("Principal.DisplayName", str3); groupPrincipal.LoadValueIntoProperty("Principal.Name", str); groupPrincipal.LoadValueIntoProperty("Principal.SamAccountName", str); SecurityIdentifier securityIdentifier = new SecurityIdentifier(Utils.ConvertSidToSDDL(sid)); groupPrincipal.LoadValueIntoProperty("Principal.Sid", securityIdentifier); groupPrincipal.LoadValueIntoProperty("GroupPrincipal.IsSecurityGroup", (bool)1); return(groupPrincipal); }
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); } }
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); } } }
static internal void WriteAttribute(string dePath, string attribute, int value, NetCred credentials, AuthenticationTypes authTypes) { GlobalDebug.WriteLineIf( GlobalDebug.Info, "SDSUtils", "WriteAttribute: writing {0} to {1} on {2}", value.ToString(CultureInfo.InvariantCulture), attribute, dePath); Debug.Assert(attribute != null && attribute.Length > 0); // Ideally, we'd just like to set the property in the principal's DirectoryEntry and write // the changes to the store. However, there might be other changes in the DirectoryEntry, // and we don't want to write all of them to the store. So we must make // a fresh DirectoryEntry and write using that. DirectoryEntry copyOfDe = null; try { copyOfDe = SDSUtils.BuildDirectoryEntry(dePath, credentials, authTypes); Debug.Assert(copyOfDe != null); // So we don't do a implicit GetInfo() and retrieve every attribute copyOfDe.RefreshCache(new string[] { attribute }); copyOfDe.Properties[attribute].Value = value; copyOfDe.CommitChanges(); } catch (System.Runtime.InteropServices.COMException e) { GlobalDebug.WriteLineIf( GlobalDebug.Error, "SDSUtils", "WriteAttribute: caught exception with message '{0}' writing {1} to {2} on {3}", e.Message, value.ToString(CultureInfo.InvariantCulture), attribute, dePath); // ADSI threw an exception trying to write the change throw ExceptionHelper.GetExceptionFromCOMException(e); } finally { if (copyOfDe != null) { copyOfDe.Dispose(); } } }
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; }
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); }
private static void UpdateGroupMembership(Principal group, DirectoryEntry de, NetCred credentials, AuthenticationTypes authTypes) { Debug.Assert(group.fakePrincipal == false); PrincipalCollection members = (PrincipalCollection)group.GetValueForProperty(PropertyNames.GroupMembers); UnsafeNativeMethods.IADsGroup iADsGroup = (UnsafeNativeMethods.IADsGroup)de.NativeObject; try { // // Process clear // if (members.Cleared) { // Unfortunately, there's no quick way to clear a group's membership in SAM. // So we remove each member in turn, by enumerating over the group membership // and calling remove on each. GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "UpdateGroupMembership: clearing {0}", de.Path); // Prepare the COM Interopt enumeration UnsafeNativeMethods.IADsMembers iADsMembers = iADsGroup.Members(); IEnumVARIANT enumerator = (IEnumVARIANT)iADsMembers._NewEnum; object[] nativeMembers = new object[1]; int hr; do { hr = enumerator.Next(1, nativeMembers, IntPtr.Zero); if (hr == 0) // S_OK { // Found a member, remove it. UnsafeNativeMethods.IADs iADs = (UnsafeNativeMethods.IADs)nativeMembers[0]; iADsGroup.Remove(iADs.ADsPath); } } while (hr == 0); // Either hr == S_FALSE (1), which means we completed the enumerator, // or we encountered an error if (hr != 1) { // Error occurred. GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SAMStoreCtx", "UpdateGroupMembership: error while clearing, hr={0}", hr); throw new PrincipalOperationException( String.Format( CultureInfo.CurrentCulture, StringResources.SAMStoreCtxFailedToClearGroup, hr.ToString(CultureInfo.InvariantCulture))); } } // // Process inserted members // List<Principal> insertedMembers = members.Inserted; // First, validate the members to be added foreach (Principal member in insertedMembers) { Type memberType = member.GetType(); if ((memberType != typeof(UserPrincipal)) && (!memberType.IsSubclassOf(typeof(UserPrincipal))) && (memberType != typeof(ComputerPrincipal)) && (!memberType.IsSubclassOf(typeof(ComputerPrincipal))) && (memberType != typeof(GroupPrincipal)) && (!memberType.IsSubclassOf(typeof(GroupPrincipal)))) { throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxUnsupportedPrincipalTypeForGroupInsert, memberType.ToString())); } // Can't inserted unpersisted principal if (member.unpersisted) throw new InvalidOperationException(StringResources.StoreCtxGroupHasUnpersistedInsertedPrincipal); Debug.Assert(member.Context != null); // There's no restriction on the type of principal to be inserted (AD/reg-SAM/MSAM), but it needs // to have a SID IdentityClaim. We'll check that as we go. } // Now add each member to the group foreach (Principal member in insertedMembers) { // We'll add the member via its SID. This works for both MSAM members and AD members. // Build a SID ADsPath string memberSidPath = GetSidADsPathFromPrincipal(member); if (memberSidPath == null) throw new InvalidOperationException(StringResources.SAMStoreCtxCouldntGetSIDForGroupMember); GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "UpdateGroupMembership: inserting {0}", memberSidPath); // Add the member to the group iADsGroup.Add(memberSidPath); } // // Process removed members // List<Principal> removedMembers = members.Removed; foreach (Principal member in removedMembers) { // Since we don't allow any of these to be inserted, none of them should ever // show up in the removal list Debug.Assert(member.unpersisted == false); // If the collection was cleared, there should be no original members to remove Debug.Assert(members.Cleared == false); // Like insertion, we'll remove by SID. // Build a SID ADsPath string memberSidPath = GetSidADsPathFromPrincipal(member); if (memberSidPath == null) throw new InvalidOperationException(StringResources.SAMStoreCtxCouldntGetSIDForGroupMember); GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "UpdateGroupMembership: removing {0}", memberSidPath); // Remove the member from the group iADsGroup.Remove(memberSidPath); } } catch (System.Runtime.InteropServices.COMException e) { GlobalDebug.WriteLineIf(GlobalDebug.Error, "SAMStoreCtx", "UpdateGroupMembership: caught COMException, message={0}, code={1}", e.Message, e.ErrorCode); // ADSI threw an exception trying to update the group membership throw ExceptionHelper.GetExceptionFromCOMException(e); } }
// {PropertyNames.GroupMembers, "members", null, new ToLdapConverterDelegate(GroupMembersToLdapConverter)}, protected static void UpdateGroupMembership(Principal group, DirectoryEntry de, NetCred credentials, AuthenticationTypes authTypes) { Debug.Assert(group.fakePrincipal == false); PrincipalCollection members = (PrincipalCollection)group.GetValueForProperty(PropertyNames.GroupMembers); DirectoryEntry groupDe = null; try { // // Process clear // if (members.Cleared) { DirectoryEntry copyOfDe = null; try { GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UpdateGroupMembership: clearing {0}", de.Path); copyOfDe = SDSUtils.BuildDirectoryEntry( de.Path, credentials, authTypes); Debug.Assert(copyOfDe != null); copyOfDe.Properties["member"].Clear(); copyOfDe.CommitChanges(); } finally { if (copyOfDe != null) copyOfDe.Dispose(); } } // // Process inserted members // List<Principal> insertedMembers = members.Inserted; List<Principal> removedMembers = members.Removed; if (insertedMembers.Count > 0 || removedMembers.Count > 0) { groupDe = SDSUtils.BuildDirectoryEntry( de.Path, credentials, authTypes); } // First, validate the members to be added foreach (Principal member in insertedMembers) { Type memberType = member.GetType(); if ((memberType != typeof(UserPrincipal)) && (!memberType.IsSubclassOf(typeof(UserPrincipal))) && (memberType != typeof(ComputerPrincipal)) && (!memberType.IsSubclassOf(typeof(ComputerPrincipal))) && (memberType != typeof(GroupPrincipal)) && (!memberType.IsSubclassOf(typeof(GroupPrincipal))) && (!memberType.IsSubclassOf(typeof(AuthenticablePrincipal)))) { throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxUnsupportedPrincipalTypeForGroupInsert, memberType.ToString())); } // Can't inserted unpersisted principal if (member.unpersisted) throw new InvalidOperationException(StringResources.StoreCtxGroupHasUnpersistedInsertedPrincipal); Debug.Assert(member.Context != null); // Can only insert AD principals (no reg-SAM/MSAM principals) if (member.ContextType == ContextType.Machine) throw new InvalidOperationException(StringResources.ADStoreCtxUnsupportedPrincipalContextForGroupInsert); } // Now add each member to the group foreach (Principal member in insertedMembers) { // For objects in the current domain or any other domains in the forest we need to use the objects DN // SID path would work for current domain but would not work for child or parent domains. // For foreign objects we must use SID path e.g. "<SID=...>" so that the necessary FPO gets autocreated by AD. // It also works in the "fake principal" case (which are always represented as FPOs). if (!member.fakePrincipal && ADUtils.ArePrincipalsInSameForest(group, member)) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UpdateGroupMembership: add {0}", member.DistinguishedName); groupDe.Properties["member"].Add(member.DistinguishedName); } else { // Build a SID DN. This needs to be a DN path not an ADSI sid path with the LDAP prefix. string memberSidDN = GetSidPathFromPrincipal(member); if (memberSidDN == null) throw new PrincipalOperationException(StringResources.ADStoreCtxCouldntGetSIDForGroupMember); GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UpdateGroupMembership: add {0}", memberSidDN); // Add the member to the group groupDe.Properties["member"].Add(memberSidDN); } } // If we had any members then commit them. if (insertedMembers.Count > 0) groupDe.CommitChanges(); // // Process removed members // foreach (Principal member in removedMembers) { // Since we don't allow any of these to be inserted, none of them should ever // show up in the removal list Debug.Assert(member.unpersisted == false); Debug.Assert(member.ContextType == ContextType.Domain || member.ContextType == ContextType.ApplicationDirectory); // If the collection was cleared, there should be no original members to remove Debug.Assert(members.Cleared == false); // Since we are using PropertyValueCollection to do the item removal we are constrainted to items that are in the collection // For principals that are in the same forest just use their DN to do the removal. This is how they are represented in the member attr. // For foreign principals we must represent them with their SID binding string since they are locally represented by an FSP object. if (!member.fakePrincipal && ADUtils.ArePrincipalsInSameForest(group, member)) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UpdateGroupMembership: remove via DN {0}", member.DistinguishedName); // Remove the member from the group groupDe.Properties["member"].Remove(member.DistinguishedName); } else { // SID DN case // Build a SID DN. string memberSidDN = GetSidPathFromPrincipal(member); if (memberSidDN == null) throw new PrincipalOperationException(StringResources.ADStoreCtxCouldntGetSIDForGroupMember); GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "UpdateGroupMembership: remove via SID {0}", memberSidDN); // Remove the member from the group groupDe.Properties["member"].Remove(memberSidDN); } } // If we used the collection to do a modification then commit it. if (removedMembers.Count > 0) groupDe.CommitChanges(); } catch (System.Runtime.InteropServices.COMException e) { throw ExceptionHelper.GetExceptionFromCOMException(e); } finally { if (null != groupDe) groupDe.Dispose(); } }
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); } } }
internal static int LookupSid(string serverName, NetCred credentials, byte[] sid, out string name, out string domainName, out int accountUsage) { int num; IntPtr zero = IntPtr.Zero; int num1 = 0; int num2 = 0; accountUsage = 0; name = null; domainName = null; IntPtr intPtr = IntPtr.Zero; try { zero = Utils.ConvertByteArrayToIntPtr(sid); Utils.BeginImpersonation(credentials, out intPtr); bool flag = UnsafeNativeMethods.LookupAccountSid(serverName, zero, null, ref num1, null, ref num2, ref accountUsage); int lastWin32Error = Marshal.GetLastWin32Error(); if (lastWin32Error == 122) { StringBuilder stringBuilder = new StringBuilder(num1); StringBuilder stringBuilder1 = new StringBuilder(num2); flag = UnsafeNativeMethods.LookupAccountSid(serverName, zero, stringBuilder, ref num1, stringBuilder1, ref num2, ref accountUsage); if (flag) { name = stringBuilder.ToString(); domainName = stringBuilder1.ToString(); num = 0; } else { lastWin32Error = Marshal.GetLastWin32Error(); num = lastWin32Error; } } else { num = lastWin32Error; } } finally { if (zero != IntPtr.Zero) { Marshal.FreeHGlobal(zero); } if (intPtr != IntPtr.Zero) { Utils.EndImpersonation(intPtr); } } return num; }
private static void UpdateGroupMembership(Principal group, DirectoryEntry de, NetCred credentials, AuthenticationTypes authTypes) { int num; PrincipalCollection valueForProperty = (PrincipalCollection)group.GetValueForProperty("GroupPrincipal.Members"); UnsafeNativeMethods.IADsGroup nativeObject = (UnsafeNativeMethods.IADsGroup)de.NativeObject; try { if (valueForProperty.Cleared) { UnsafeNativeMethods.IADsMembers aDsMember = nativeObject.Members(); IEnumVARIANT enumVARIANT = (IEnumVARIANT)aDsMember._NewEnum; object[] objArray = new object[1]; do { num = enumVARIANT.Next(1, objArray, IntPtr.Zero); if (num != 0) { continue; } UnsafeNativeMethods.IADs aD = (UnsafeNativeMethods.IADs)objArray[0]; nativeObject.Remove(aD.ADsPath); } while (num == 0); if (num != 1) { object[] str = new object[1]; str[0] = num.ToString(CultureInfo.InvariantCulture); throw new PrincipalOperationException(string.Format(CultureInfo.CurrentCulture, StringResources.SAMStoreCtxFailedToClearGroup, str)); } } List<Principal> inserted = valueForProperty.Inserted; foreach (Principal principal in inserted) { Type type = principal.GetType(); if (!(type != typeof(UserPrincipal)) || type.IsSubclassOf(typeof(UserPrincipal)) || !(type != typeof(ComputerPrincipal)) || type.IsSubclassOf(typeof(ComputerPrincipal)) || !(type != typeof(GroupPrincipal)) || type.IsSubclassOf(typeof(GroupPrincipal))) { if (!principal.unpersisted) { continue; } throw new InvalidOperationException(StringResources.StoreCtxGroupHasUnpersistedInsertedPrincipal); } else { object[] str1 = new object[1]; str1[0] = type.ToString(); throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxUnsupportedPrincipalTypeForGroupInsert, str1)); } } foreach (Principal principal1 in inserted) { string sidADsPathFromPrincipal = SAMStoreCtx.GetSidADsPathFromPrincipal(principal1); if (sidADsPathFromPrincipal != null) { nativeObject.Add(sidADsPathFromPrincipal); } else { throw new InvalidOperationException(StringResources.SAMStoreCtxCouldntGetSIDForGroupMember); } } List<Principal> removed = valueForProperty.Removed; foreach (Principal principal2 in removed) { string sidADsPathFromPrincipal1 = SAMStoreCtx.GetSidADsPathFromPrincipal(principal2); if (sidADsPathFromPrincipal1 != null) { nativeObject.Remove(sidADsPathFromPrincipal1); } else { throw new InvalidOperationException(StringResources.SAMStoreCtxCouldntGetSIDForGroupMember); } } } catch (COMException cOMException1) { COMException cOMException = cOMException1; throw ExceptionHelper.GetExceptionFromCOMException(cOMException); } }
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); } } }
static internal void WriteAttribute <T>(string dePath, string attribute, T value, NetCred credentials, AuthenticationTypes authTypes) { Debug.Assert(attribute != null && attribute.Length > 0); // Ideally, we'd just like to set the property in the principal's DirectoryEntry and write // the changes to the store. However, there might be other changes in the DirectoryEntry, // and we don't want to write all of them to the store. So we must make // a fresh DirectoryEntry and write using that. DirectoryEntry copyOfDe = null; try { copyOfDe = SDSUtils.BuildDirectoryEntry(dePath, credentials, authTypes); Debug.Assert(copyOfDe != null); // So we don't do a implicit GetInfo() and retrieve every attribute copyOfDe.RefreshCache(new string[] { attribute }); copyOfDe.Properties[attribute].Value = value; copyOfDe.CommitChanges(); } catch (System.Runtime.InteropServices.COMException e) { // ADSI threw an exception trying to write the change throw ExceptionHelper.GetExceptionFromCOMException(e); } finally { if (copyOfDe != null) { copyOfDe.Dispose(); } } }
internal static void ApplyChangesToDirectory(Principal p, StoreCtx storeCtx, SDSUtils.GroupMembershipUpdater updateGroupMembership, NetCred credentials, AuthenticationTypes authTypes) { DirectoryEntry native = (DirectoryEntry)storeCtx.PushChangesToNative(p); try { native.CommitChanges(); } catch (COMException cOMException1) { COMException cOMException = cOMException1; throw ExceptionHelper.GetExceptionFromCOMException(cOMException); } if (p as GroupPrincipal != null && p.GetChangeStatusForProperty("GroupPrincipal.Members")) { updateGroupMembership(p, native, credentials, authTypes); } }
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); } } }
internal static Principal ConstructFakePrincipalFromSID(byte[] sid, PrincipalContext ctx, string serverName, NetCred credentials, string authorityName) { string str = null; string str1 = null; string str2; string str3 = ""; int num = 0; int num1 = Utils.LookupSid(serverName, credentials, sid, out str, out str1, out num); if (num1 == 0) { if (!string.IsNullOrEmpty(str1)) { str2 = string.Concat(str1, "\\"); } else { str2 = ""; } str3 = string.Concat(str2, str); } GroupPrincipal groupPrincipal = GroupPrincipal.MakeGroup(ctx); groupPrincipal.fakePrincipal = true; groupPrincipal.unpersisted = false; groupPrincipal.LoadValueIntoProperty("Principal.DisplayName", str3); groupPrincipal.LoadValueIntoProperty("Principal.Name", str); groupPrincipal.LoadValueIntoProperty("Principal.SamAccountName", str); SecurityIdentifier securityIdentifier = new SecurityIdentifier(Utils.ConvertSidToSDDL(sid)); groupPrincipal.LoadValueIntoProperty("Principal.Sid", securityIdentifier); groupPrincipal.LoadValueIntoProperty("GroupPrincipal.IsSecurityGroup", (bool)1); return groupPrincipal; }
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); }