File: WindowsUserNameSecurityTokenHandler.cs

package info (click to toggle)
mono 4.6.2.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 778,148 kB
  • ctags: 914,052
  • sloc: cs: 5,779,509; xml: 2,773,713; ansic: 432,645; sh: 14,749; makefile: 12,361; perl: 2,488; python: 1,434; cpp: 849; asm: 531; sql: 95; sed: 16; php: 1
file content (145 lines) | stat: -rw-r--r-- 6,311 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//------------------------------------------------------------------------------
//     Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IdentityModel.Tokens;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Xml;
using System.Security.Claims;
using System.IdentityModel.Configuration;
using System.Collections.Generic;
using System.Runtime;

namespace System.IdentityModel.Tokens
{
    /// <summary>
    /// The token handler will validated the Windows Username token.
    /// </summary>
    public class WindowsUserNameSecurityTokenHandler : UserNameSecurityTokenHandler
    {
        /// <summary>
        /// Initializes an instance of <see cref="WindowsUserNameSecurityTokenHandler"/>
        /// </summary>
        public WindowsUserNameSecurityTokenHandler()
        {
        }

        /// <summary>
        /// Returns true to indicate that the token handler can Validate
        /// UserNameSecurityToken.
        /// </summary>
        public override bool CanValidateToken
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Validates a <see cref="UserNameSecurityToken"/>.
        /// </summary>
        /// <param name="token">The <see cref="UserNameSecurityToken"/> to validate.</param>
        /// <returns>A <see cref="ReadOnlyCollection{T}"/> of <see cref="ClaimsIdentity"/> representing the identities contained in the token.</returns>
        /// <exception cref="ArgumentNullException">The parameter 'token' is null.</exception>
        /// <exception cref="ArgumentException">The token is not assignable from<see cref="UserNameSecurityToken"/>.</exception>
        /// <exception cref="InvalidOperationException">Configuration <see cref="SecurityTokenHandlerConfiguration"/>is null.</exception>
        /// <exception cref="ArgumentException">If username is not if the form 'user\domain'.</exception>
        /// <exception cref="SecurityTokenValidationException">LogonUser using the given token failed.</exception>
        public override ReadOnlyCollection<ClaimsIdentity> ValidateToken(SecurityToken token)
        {
            if (token == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token");
            }

            UserNameSecurityToken usernameToken = token as UserNameSecurityToken;
            if (usernameToken == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("token", SR.GetString(SR.ID0018, typeof(UserNameSecurityToken)));
            }

            if (this.Configuration == null)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4274));
            }

            try
            {
                string userName = usernameToken.UserName;
                string password = usernameToken.Password;
                string domain = null;
                string[] strings = usernameToken.UserName.Split('\\');
                if (strings.Length != 1)
                {
                    if (strings.Length != 2 || string.IsNullOrEmpty(strings[0]))
                    {
                        // Only support one slash and domain cannot be empty (consistent with windowslogon).
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("token", SR.GetString(SR.ID4062));
                    }

                    // This is the downlevel case - domain\userName
                    userName = strings[1];
                    domain = strings[0];
                }

                const uint LOGON32_PROVIDER_DEFAULT = 0;
                const uint LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
                SafeCloseHandle tokenHandle = null;
                try
                {
                    if (!NativeMethods.LogonUser(userName, domain, password, LOGON32_LOGON_NETWORK_CLEARTEXT, LOGON32_PROVIDER_DEFAULT, out tokenHandle))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenValidationException(SR.GetString(SR.ID4063, userName), new Win32Exception(error)));
                    }

                    WindowsIdentity windowsIdentity = new WindowsIdentity(tokenHandle.DangerousGetHandle(), AuthenticationTypes.Password, WindowsAccountType.Normal, true);

                    // PARTIAL TRUST: will fail when adding claims, AddClaim is SecurityCritical.
                    windowsIdentity.AddClaim(new Claim(ClaimTypes.AuthenticationInstant, XmlConvert.ToString(DateTime.UtcNow, DateTimeFormats.Generated), ClaimValueTypes.DateTime));
                    windowsIdentity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.Password));

                    if (this.Configuration.SaveBootstrapContext)
                    {
                        if (RetainPassword)
                        {
                            windowsIdentity.BootstrapContext = new BootstrapContext(usernameToken, this);
                        }
                        else
                        {
                            windowsIdentity.BootstrapContext = new BootstrapContext(new UserNameSecurityToken(usernameToken.UserName, null), this);
                        }
                    }

                    this.TraceTokenValidationSuccess(token);

                    List<ClaimsIdentity> identities = new List<ClaimsIdentity>(1);
                    identities.Add(windowsIdentity);
                    return identities.AsReadOnly();
                }
                finally
                {
                    if (tokenHandle != null)
                    {
                        tokenHandle.Close();
                    }
                }
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }

                this.TraceTokenValidationFailure(token, e.Message);
                throw e;
            }
        }
    }
}