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/completion_once_callback.h" 21 #include "net/base/net_errors.h" 22 #include "net/base/net_export.h" 23 #include "net/http/http_auth.h" 24 #include "net/http/http_auth_mechanism.h" 25 26 namespace net { 27 28 class HttpAuthChallengeTokenizer; 29 30 // SSPILibrary is introduced so unit tests can mock the calls to Windows' SSPI 31 // implementation. The default implementation simply passes the arguments on to 32 // the SSPI implementation provided by Secur32.dll. 33 // 34 // A single SSPILibrary can only be used with a single security package. Hence 35 // the package is bound at construction time. Overridable SSPI methods exclude 36 // the security package parameter since it is implicit. 37 class NET_EXPORT_PRIVATE SSPILibrary { 38 public: SSPILibrary(const wchar_t * package)39 explicit SSPILibrary(const wchar_t* package) : package_name_(package) {} ~SSPILibrary()40 virtual ~SSPILibrary() {} 41 42 // Determines the maximum token length in bytes for a particular SSPI package. 43 // 44 // |library| and |max_token_length| must be non-nullptr pointers to valid 45 // objects. 46 // 47 // If the return value is OK, |*max_token_length| contains the maximum token 48 // length in bytes. 49 // 50 // If the return value is ERR_UNSUPPORTED_AUTH_SCHEME, |package| is not an 51 // known SSPI authentication scheme on this system. |*max_token_length| is not 52 // changed. 53 // 54 // If the return value is ERR_UNEXPECTED, there was an unanticipated problem 55 // in the underlying SSPI call. The details are logged, and 56 // |*max_token_length| is not changed. 57 Error DetermineMaxTokenLength(ULONG* max_token_length); 58 59 virtual SECURITY_STATUS AcquireCredentialsHandle(LPWSTR pszPrincipal, 60 unsigned long fCredentialUse, 61 void* pvLogonId, 62 void* pvAuthData, 63 SEC_GET_KEY_FN pGetKeyFn, 64 void* pvGetKeyArgument, 65 PCredHandle phCredential, 66 PTimeStamp ptsExpiry) = 0; 67 68 virtual SECURITY_STATUS InitializeSecurityContext(PCredHandle phCredential, 69 PCtxtHandle phContext, 70 SEC_WCHAR* pszTargetName, 71 unsigned long fContextReq, 72 unsigned long Reserved1, 73 unsigned long TargetDataRep, 74 PSecBufferDesc pInput, 75 unsigned long Reserved2, 76 PCtxtHandle phNewContext, 77 PSecBufferDesc pOutput, 78 unsigned long* contextAttr, 79 PTimeStamp ptsExpiry) = 0; 80 81 virtual SECURITY_STATUS QueryContextAttributesEx(PCtxtHandle phContext, 82 ULONG ulAttribute, 83 PVOID pBuffer, 84 ULONG cbBuffer) = 0; 85 86 virtual SECURITY_STATUS QuerySecurityPackageInfo(PSecPkgInfoW* pkgInfo) = 0; 87 88 virtual SECURITY_STATUS FreeCredentialsHandle(PCredHandle phCredential) = 0; 89 90 virtual SECURITY_STATUS DeleteSecurityContext(PCtxtHandle phContext) = 0; 91 92 virtual SECURITY_STATUS FreeContextBuffer(PVOID pvContextBuffer) = 0; 93 94 protected: 95 // Security package used with DetermineMaxTokenLength(), 96 // QuerySecurityPackageInfo(), AcquireCredentialsHandle(). All of these must 97 // be consistent. 98 const std::wstring package_name_; 99 ULONG max_token_length_ = 0; 100 101 bool is_supported_ = true; 102 }; 103 104 class SSPILibraryDefault : public SSPILibrary { 105 public: SSPILibraryDefault(const wchar_t * package)106 explicit SSPILibraryDefault(const wchar_t* package) : SSPILibrary(package) {} ~SSPILibraryDefault()107 ~SSPILibraryDefault() override {} 108 109 SECURITY_STATUS AcquireCredentialsHandle(LPWSTR pszPrincipal, 110 unsigned long fCredentialUse, 111 void* pvLogonId, 112 void* pvAuthData, 113 SEC_GET_KEY_FN pGetKeyFn, 114 void* pvGetKeyArgument, 115 PCredHandle phCredential, 116 PTimeStamp ptsExpiry) override; 117 118 SECURITY_STATUS InitializeSecurityContext(PCredHandle phCredential, 119 PCtxtHandle phContext, 120 SEC_WCHAR* pszTargetName, 121 unsigned long fContextReq, 122 unsigned long Reserved1, 123 unsigned long TargetDataRep, 124 PSecBufferDesc pInput, 125 unsigned long Reserved2, 126 PCtxtHandle phNewContext, 127 PSecBufferDesc pOutput, 128 unsigned long* contextAttr, 129 PTimeStamp ptsExpiry) override; 130 131 SECURITY_STATUS QueryContextAttributesEx(PCtxtHandle phContext, 132 ULONG ulAttribute, 133 PVOID pBuffer, 134 ULONG cbBuffer) override; 135 136 SECURITY_STATUS QuerySecurityPackageInfo(PSecPkgInfoW* pkgInfo) override; 137 138 SECURITY_STATUS FreeCredentialsHandle(PCredHandle phCredential) override; 139 140 SECURITY_STATUS DeleteSecurityContext(PCtxtHandle phContext) override; 141 142 SECURITY_STATUS FreeContextBuffer(PVOID pvContextBuffer) override; 143 }; 144 145 class NET_EXPORT_PRIVATE HttpAuthSSPI : public HttpAuthMechanism { 146 public: 147 HttpAuthSSPI(SSPILibrary* sspi_library, HttpAuth::Scheme scheme); 148 ~HttpAuthSSPI() override; 149 150 // HttpAuthMechanism implementation: 151 bool Init(const NetLogWithSource& net_log) override; 152 bool NeedsIdentity() const override; 153 bool AllowsExplicitCredentials() const override; 154 HttpAuth::AuthorizationResult ParseChallenge( 155 HttpAuthChallengeTokenizer* tok) override; 156 int GenerateAuthToken(const AuthCredentials* credentials, 157 const std::string& spn, 158 const std::string& channel_bindings, 159 std::string* auth_token, 160 const NetLogWithSource& net_log, 161 CompletionOnceCallback callback) override; 162 void SetDelegation(HttpAuth::DelegationType delegation_type) override; 163 164 private: 165 int OnFirstRound(const AuthCredentials* credentials, 166 const NetLogWithSource& net_log); 167 168 int GetNextSecurityToken(const std::string& spn, 169 const std::string& channing_bindings, 170 const void* in_token, 171 int in_token_len, 172 const NetLogWithSource& net_log, 173 void** out_token, 174 int* out_token_len); 175 176 void ResetSecurityContext(); 177 178 SSPILibrary* library_; 179 HttpAuth::Scheme scheme_; 180 std::string decoded_server_auth_token_; 181 CredHandle cred_; 182 CtxtHandle ctxt_; 183 HttpAuth::DelegationType delegation_type_; 184 }; 185 186 // Splits |combined| into domain and username. 187 // If |combined| is of form "FOO\bar", |domain| will contain "FOO" and |user| 188 // will contain "bar". 189 // If |combined| is of form "bar", |domain| will be empty and |user| will 190 // contain "bar". 191 // |domain| and |user| must be non-nullptr. 192 NET_EXPORT_PRIVATE void SplitDomainAndUser(const base::string16& combined, 193 base::string16* domain, 194 base::string16* user); 195 196 } // namespace net 197 198 #endif // NET_HTTP_HTTP_AUTH_SSPI_WIN_H_ 199