http_auth_sspi_win.h 8.6 KB

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