/// <summary> /// Returns the windows principal associated with a user name security token. /// </summary> /// <param name="identityToken">The identity token.</param> /// <param name="interactive">Whether to logon interactively (slow).</param> /// <returns>The impersonation context (must be disposed to reverse impersonation).</returns> public static ImpersonationContext LogonUser(UserNameSecurityToken identityToken, bool interactive) { if (identityToken == null) { throw ServiceResultException.Create(StatusCodes.BadIdentityTokenRejected, "Secuirty token is not a valid username token."); } // extract the username and domain from the security token. string username = identityToken.UserName; string domain = null; int index = username.IndexOf('\\'); if (index != -1) { domain = username.Substring(0, index); username = username.Substring(index + 1); } // validate the credentials. IntPtr handle = IntPtr.Zero; int result = Win32.LogonUserW( username, domain, identityToken.Password, (interactive) ? Win32.LOGON32_LOGON_INTERACTIVE : Win32.LOGON32_LOGON_NETWORK, Win32.LOGON32_PROVIDER_DEFAULT, ref handle); if (result == 0) { result = Marshal.GetLastWin32Error(); throw ServiceResultException.Create( StatusCodes.BadIdentityTokenRejected, "Could not logon as user '{0}'. Reason: {1}.", identityToken.UserName, result); } try { WindowsIdentity identity = new WindowsIdentity(handle); ImpersonationContext context = new ImpersonationContext(); context.Principal = new WindowsPrincipal(identity); context.Context = identity.Impersonate(); context.Handle = handle; return(context); } catch (Exception e) { Win32.CloseHandle(handle); throw e; } }
/// <summary> /// This method is called at the being of the thread that processes a request. /// </summary> protected override OperationContext ValidateRequest(RequestHeader requestHeader, RequestType requestType) { OperationContext context = base.ValidateRequest(requestHeader, requestType); if (requestType == RequestType.Write) { // reject all writes if no user provided. if (context.UserIdentity.TokenType == UserTokenType.Anonymous) { // construct translation object with default text. TranslationInfo info = new TranslationInfo( "NoWriteAllowed", "en-US", "Must provide a valid windows user before calling write."); // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( StatusCodes.BadUserAccessDenied, "NoWriteAllowed", Namespaces.UserAuthentication, new LocalizedText(info))); } SecurityToken securityToken = context.UserIdentity.GetSecurityToken(); // check for a kerberso token. KerberosReceiverSecurityToken kerberosToken = securityToken as KerberosReceiverSecurityToken; if (kerberosToken != null) { ImpersonationContext impersonationContext = new ImpersonationContext(); impersonationContext.Context = kerberosToken.WindowsIdentity.Impersonate(); lock (this.m_lock) { m_contexts.Add(context.RequestId, impersonationContext); } } // check for a user name token. UserNameSecurityToken userNameToken = securityToken as UserNameSecurityToken; if (userNameToken != null) { LogonUser(context, userNameToken); } } return context; }
/// <summary> /// Impersonates the windows user identifed by the security token. /// </summary> private void LogonUser(OperationContext context, UserNameSecurityToken securityToken) { IntPtr handle = IntPtr.Zero; const int LOGON32_PROVIDER_DEFAULT = 0; // const int LOGON32_LOGON_INTERACTIVE = 2; const int LOGON32_LOGON_NETWORK = 3; // const int LOGON32_LOGON_BATCH = 4; bool result = NativeMethods.LogonUser( securityToken.UserName, String.Empty, securityToken.Password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref handle); if (!result) { throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Login failed for user: {0}", securityToken.UserName); } WindowsIdentity identity = new WindowsIdentity(handle); ImpersonationContext impersonationContext = new ImpersonationContext(); impersonationContext.Handle = handle; impersonationContext.Context = identity.Impersonate(); lock (this.m_lock) { m_contexts.Add(context.RequestId, impersonationContext); } }
/// <summary> /// Returns the windows principal associated with a user name security token. /// </summary> /// <param name="identityToken">The identity token.</param> /// <param name="interactive">Whether to logon interactively (slow).</param> /// <returns>The impersonation context (must be disposed to reverse impersonation).</returns> public static ImpersonationContext LogonUser(UserNameSecurityToken identityToken, bool interactive) { if (identityToken == null) { throw ServiceResultException.Create(StatusCodes.BadIdentityTokenRejected, "Secuirty token is not a valid username token."); } // extract the username and domain from the security token. string username = identityToken.UserName; string domain = null; int index = username.IndexOf('\\'); if (index != -1) { domain = username.Substring(0, index); username = username.Substring(index+1); } // validate the credentials. IntPtr handle = IntPtr.Zero; int result = Win32.LogonUserW( username, domain, identityToken.Password, (interactive) ? Win32.LOGON32_LOGON_INTERACTIVE : Win32.LOGON32_LOGON_NETWORK, Win32.LOGON32_PROVIDER_DEFAULT, ref handle); if (result == 0) { result = Marshal.GetLastWin32Error(); throw ServiceResultException.Create( StatusCodes.BadIdentityTokenRejected, "Could not logon as user '{0}'. Reason: {1}.", identityToken.UserName, result); } try { WindowsIdentity identity = new WindowsIdentity(handle); ImpersonationContext context = new ImpersonationContext(); context.Principal = new WindowsPrincipal(identity); context.Context = identity.Impersonate(); context.Handle = handle; return context; } catch (Exception e) { Win32.CloseHandle(handle); throw e; } }