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