OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // This file contains common routines used by NTLM and Negotiate authentication | |
6 // using the SSPI API on Windows. | |
7 | |
8 #ifndef NET_HTTP_HTTP_AUTH_SSPI_WIN_H_ | |
9 #define NET_HTTP_HTTP_AUTH_SSPI_WIN_H_ | |
10 | |
11 // security.h needs to be included for CredHandle. Unfortunately CredHandle | |
12 // is a typedef and can't be forward declared. | |
13 #define SECURITY_WIN32 1 | |
14 #include <windows.h> | |
15 #include <security.h> | |
16 | |
17 #include <string> | |
18 | |
19 #include "base/strings/string16.h" | |
20 #include "net/base/net_export.h" | |
21 #include "net/http/http_auth.h" | |
22 | |
23 namespace net { | |
24 | |
25 class HttpAuthChallengeTokenizer; | |
26 | |
27 // SSPILibrary is introduced so unit tests can mock the calls to Windows' SSPI | |
28 // implementation. The default implementation simply passes the arguments on to | |
29 // the SSPI implementation provided by Secur32.dll. | |
30 // NOTE(cbentzel): I considered replacing the Secur32.dll with a mock DLL, but | |
31 // decided that it wasn't worth the effort as this is unlikely to be performance | |
32 // sensitive code. | |
33 class SSPILibrary { | |
34 public: | |
35 virtual ~SSPILibrary() {} | |
36 | |
37 virtual SECURITY_STATUS AcquireCredentialsHandle(LPWSTR pszPrincipal, | |
38 LPWSTR pszPackage, | |
39 unsigned long fCredentialUse, | |
40 void* pvLogonId, | |
41 void* pvAuthData, | |
42 SEC_GET_KEY_FN pGetKeyFn, | |
43 void* pvGetKeyArgument, | |
44 PCredHandle phCredential, | |
45 PTimeStamp ptsExpiry) = 0; | |
46 | |
47 virtual SECURITY_STATUS InitializeSecurityContext(PCredHandle phCredential, | |
48 PCtxtHandle phContext, | |
49 SEC_WCHAR* pszTargetName, | |
50 unsigned long fContextReq, | |
51 unsigned long Reserved1, | |
52 unsigned long TargetDataRep, | |
53 PSecBufferDesc pInput, | |
54 unsigned long Reserved2, | |
55 PCtxtHandle phNewContext, | |
56 PSecBufferDesc pOutput, | |
57 unsigned long* contextAttr, | |
58 PTimeStamp ptsExpiry) = 0; | |
59 | |
60 virtual SECURITY_STATUS QuerySecurityPackageInfo(LPWSTR pszPackageName, | |
61 PSecPkgInfoW *pkgInfo) = 0; | |
62 | |
63 virtual SECURITY_STATUS FreeCredentialsHandle(PCredHandle phCredential) = 0; | |
64 | |
65 virtual SECURITY_STATUS DeleteSecurityContext(PCtxtHandle phContext) = 0; | |
66 | |
67 virtual SECURITY_STATUS FreeContextBuffer(PVOID pvContextBuffer) = 0; | |
68 }; | |
69 | |
70 class SSPILibraryDefault : public SSPILibrary { | |
71 public: | |
72 SSPILibraryDefault() {} | |
73 virtual ~SSPILibraryDefault() {} | |
74 | |
75 virtual SECURITY_STATUS AcquireCredentialsHandle(LPWSTR pszPrincipal, | |
76 LPWSTR pszPackage, | |
77 unsigned long fCredentialUse, | |
78 void* pvLogonId, | |
79 void* pvAuthData, | |
80 SEC_GET_KEY_FN pGetKeyFn, | |
81 void* pvGetKeyArgument, | |
82 PCredHandle phCredential, | |
83 PTimeStamp ptsExpiry) { | |
84 return ::AcquireCredentialsHandle(pszPrincipal, pszPackage, fCredentialUse, | |
85 pvLogonId, pvAuthData, pGetKeyFn, | |
86 pvGetKeyArgument, phCredential, | |
87 ptsExpiry); | |
88 } | |
89 | |
90 virtual SECURITY_STATUS InitializeSecurityContext(PCredHandle phCredential, | |
91 PCtxtHandle phContext, | |
92 SEC_WCHAR* pszTargetName, | |
93 unsigned long fContextReq, | |
94 unsigned long Reserved1, | |
95 unsigned long TargetDataRep, | |
96 PSecBufferDesc pInput, | |
97 unsigned long Reserved2, | |
98 PCtxtHandle phNewContext, | |
99 PSecBufferDesc pOutput, | |
100 unsigned long* contextAttr, | |
101 PTimeStamp ptsExpiry) { | |
102 return ::InitializeSecurityContext(phCredential, phContext, pszTargetName, | |
103 fContextReq, Reserved1, TargetDataRep, | |
104 pInput, Reserved2, phNewContext, pOutput, | |
105 contextAttr, ptsExpiry); | |
106 } | |
107 | |
108 virtual SECURITY_STATUS QuerySecurityPackageInfo(LPWSTR pszPackageName, | |
109 PSecPkgInfoW *pkgInfo) { | |
110 return ::QuerySecurityPackageInfo(pszPackageName, pkgInfo); | |
111 } | |
112 | |
113 virtual SECURITY_STATUS FreeCredentialsHandle(PCredHandle phCredential) { | |
114 return ::FreeCredentialsHandle(phCredential); | |
115 } | |
116 | |
117 virtual SECURITY_STATUS DeleteSecurityContext(PCtxtHandle phContext) { | |
118 return ::DeleteSecurityContext(phContext); | |
119 } | |
120 | |
121 virtual SECURITY_STATUS FreeContextBuffer(PVOID pvContextBuffer) { | |
122 return ::FreeContextBuffer(pvContextBuffer); | |
123 } | |
124 }; | |
125 | |
126 class NET_EXPORT_PRIVATE HttpAuthSSPI { | |
127 public: | |
128 HttpAuthSSPI(SSPILibrary* sspi_library, | |
129 const std::string& scheme, | |
130 const SEC_WCHAR* security_package, | |
131 ULONG max_token_length); | |
132 ~HttpAuthSSPI(); | |
133 | |
134 bool NeedsIdentity() const; | |
135 | |
136 bool AllowsExplicitCredentials() const; | |
137 | |
138 HttpAuth::AuthorizationResult ParseChallenge( | |
139 HttpAuthChallengeTokenizer* tok); | |
140 | |
141 // Generates an authentication token for the service specified by the | |
142 // Service Principal Name |spn| and stores the value in |*auth_token|. | |
143 // If the return value is not |OK|, then the value of |*auth_token| is | |
144 // unspecified. ERR_IO_PENDING is not a valid return code. | |
145 // If this is the first round of a multiple round scheme, credentials are | |
146 // obtained using |*credentials|. If |credentials| is NULL, the credentials | |
147 // for the currently logged in user are used instead. | |
148 int GenerateAuthToken(const AuthCredentials* credentials, | |
149 const std::string& spn, | |
150 std::string* auth_token); | |
151 | |
152 // Delegation is allowed on the Kerberos ticket. This allows certain servers | |
153 // to act as the user, such as an IIS server retrieiving data from a | |
154 // Kerberized MSSQL server. | |
155 void Delegate(); | |
156 | |
157 private: | |
158 int OnFirstRound(const AuthCredentials* credentials); | |
159 | |
160 int GetNextSecurityToken( | |
161 const std::string& spn, | |
162 const void* in_token, | |
163 int in_token_len, | |
164 void** out_token, | |
165 int* out_token_len); | |
166 | |
167 void ResetSecurityContext(); | |
168 | |
169 SSPILibrary* library_; | |
170 std::string scheme_; | |
171 const SEC_WCHAR* security_package_; | |
172 std::string decoded_server_auth_token_; | |
173 ULONG max_token_length_; | |
174 CredHandle cred_; | |
175 CtxtHandle ctxt_; | |
176 bool can_delegate_; | |
177 }; | |
178 | |
179 // Splits |combined| into domain and username. | |
180 // If |combined| is of form "FOO\bar", |domain| will contain "FOO" and |user| | |
181 // will contain "bar". | |
182 // If |combined| is of form "bar", |domain| will be empty and |user| will | |
183 // contain "bar". | |
184 // |domain| and |user| must be non-NULL. | |
185 NET_EXPORT_PRIVATE void SplitDomainAndUser(const base::string16& combined, | |
186 base::string16* domain, | |
187 base::string16* user); | |
188 | |
189 // Determines the maximum token length in bytes for a particular SSPI package. | |
190 // | |
191 // |library| and |max_token_length| must be non-NULL pointers to valid objects. | |
192 // | |
193 // If the return value is OK, |*max_token_length| contains the maximum token | |
194 // length in bytes. | |
195 // | |
196 // If the return value is ERR_UNSUPPORTED_AUTH_SCHEME, |package| is not an | |
197 // known SSPI authentication scheme on this system. |*max_token_length| is not | |
198 // changed. | |
199 // | |
200 // If the return value is ERR_UNEXPECTED, there was an unanticipated problem | |
201 // in the underlying SSPI call. The details are logged, and |*max_token_length| | |
202 // is not changed. | |
203 NET_EXPORT_PRIVATE int DetermineMaxTokenLength(SSPILibrary* library, | |
204 const std::wstring& package, | |
205 ULONG* max_token_length); | |
206 | |
207 } // namespace net | |
208 | |
209 #endif // NET_HTTP_HTTP_AUTH_SSPI_WIN_H_ | |
OLD | NEW |