xref: /aosp_15_r20/external/cronet/net/http/http_auth_sspi_win.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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