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