public SspiCredentials(string principal, string username, string password, string domain) { long expiry = 0; var authenticationData = new SEC_WINNT_AUTH_IDENTITY { User = username, UserLength = username.Length, Domain = domain, DomainLength = domain.Length, Password = password, PasswordLength = password.Length, Flags = SspiInterop.SEC_WINNT_AUTH_IDENTITY_UNICODE }; var result = SspiInterop.AcquireCredentialsHandle( principal, SecurityPackage, SspiInterop.SECPKG_CRED_BOTH, IntPtr.Zero, authenticationData, 0, IntPtr.Zero, ref _credentials, ref expiry); if (result != SspiInterop.SEC_E_OK) { throw new Exception($"Unable to aquire credentials for {principal}, SECURITY_STATUS 0x{result:x8}"); } Credentials = _credentials; }
private static IEnumerable <string> GetMemebershipSids(IntPtr token) { var length = 0; SspiInterop.GetTokenInformation(token, TokenInformationClass.TokenGroups, IntPtr.Zero, length, out length); var buffer = Marshal.AllocHGlobal(length); if (SspiInterop.GetTokenInformation(token, TokenInformationClass.TokenGroups, buffer, length, out length)) { var groups = Marshal.PtrToStructure <TOKEN_GROUPS>(buffer); var sidAndAttrSize = Marshal.SizeOf(new SID_AND_ATTRIBUTES()); for (var i = 0; i < groups.GroupCount; i++) { var sidAndAttributes = Marshal.PtrToStructure <SID_AND_ATTRIBUTES>( new IntPtr(buffer.ToInt64() + i * sidAndAttrSize + IntPtr.Size)); SspiInterop.ConvertSidToStringSid(sidAndAttributes.Sid, out var pstr); var sidString = Marshal.PtrToStringAuto(pstr); SspiInterop.LocalFree(pstr); yield return(sidString); } } else { throw new AuthenticationException($"An unhandled exception occurred obtaining group membership from the context (Win32 error {Marshal.GetLastWin32Error()})"); } Marshal.FreeHGlobal(buffer); }
private static string GetPrincipalNameFromContext(SecurityHandle context) { // We must pass SSPI a pointer to a structure, where upon SSPI will allocate additional memory for the // fields of the structure. We have to call back into SSPI to free the buffers it allocated, this code is // pretty verbose, probably should be refactored var name = new SecurityContextNamesBuffer(); var namePtr = Marshal.AllocHGlobal(Marshal.SizeOf(name)); Marshal.StructureToPtr(name, namePtr, false); var status = SspiInterop.QueryContextAttributes(ref context, SspiInterop.SECPKG_ATTR_NATIVE_NAMES, namePtr); if (status != SspiInterop.SEC_E_OK) { Marshal.FreeHGlobal(namePtr); throw new AuthenticationException($"An unhandled exception occurred obtaining the username from the context (QueryContextAttributes returned: {status})"); } var usernamePtr = Marshal.PtrToStructure <SecurityContextNamesBuffer>(namePtr).clientname; var servernamePtr = Marshal.PtrToStructure <SecurityContextNamesBuffer>(namePtr).servername; var username = Marshal.PtrToStringUni(usernamePtr); SspiInterop.FreeContextBuffer(usernamePtr); SspiInterop.FreeContextBuffer(servernamePtr); Marshal.FreeHGlobal(namePtr); return(username); }
public SspiCredentials() { long expiry = 0; var result = SspiInterop.AcquireCredentialsHandle( IntPtr.Zero, SecurityPackage, SspiInterop.SECPKG_CRED_BOTH, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero, ref _credentials, ref expiry); if (result != SspiInterop.SEC_E_OK) { throw new Exception($"Unable to aquire credentials for current user, SECURITY_STATUS 0x{result:x8}"); } Credentials = _credentials; }
private static string[] GetGroupMembershipFromContext(SecurityHandle context) { // Query the context to obtain the Win32 Access Token, this will enable us to get the list of SID's that // represent group membership for the principal, we will use these to populate the Roles property var accessToken = new SecurityContextBuffer(); var accessTokenPtr = Marshal.AllocHGlobal(Marshal.SizeOf(accessToken)); Marshal.StructureToPtr(accessToken, accessTokenPtr, false); var status = SspiInterop.QueryContextAttributes(ref context, SspiInterop.SECPKG_ATTR_ACCESS_TOKEN, accessTokenPtr); if (status != SspiInterop.SEC_E_OK) { Marshal.FreeHGlobal(accessTokenPtr); throw new AuthenticationException($"An unhandled exception occurred obtaining the access token from the context (QueryContextAttributes returned: {status})"); } // who closes the access token, I assume when we delete the context var tokenPtr = Marshal.PtrToStructure <SecurityContextBuffer>(accessTokenPtr).Buffer; var groups = GetMemebershipSids(tokenPtr).ToArray(); Marshal.FreeHGlobal(accessTokenPtr); return(groups); }