• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 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 #ifndef NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_
6 #define NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_
7 #pragma once
8 
9 #include <string>
10 
11 #include "base/gtest_prod_util.h"
12 #include "base/native_library.h"
13 #include "base/string16.h"
14 #include "net/http/http_auth.h"
15 
16 #define GSS_USE_FUNCTION_POINTERS
17 #include "net/third_party/gssapi/gssapi.h"
18 
19 namespace net {
20 
21 extern gss_OID CHROME_GSS_C_NT_HOSTBASED_SERVICE_X;
22 extern gss_OID CHROME_GSS_C_NT_HOSTBASED_SERVICE;
23 extern gss_OID CHROME_GSS_KRB5_MECH_OID_DESC;
24 
25 // GSSAPILibrary is introduced so unit tests can mock the calls to the GSSAPI
26 // library. The default implementation attempts to load one of the standard
27 // GSSAPI library implementations, then simply passes the arguments on to
28 // that implementation.
29 class GSSAPILibrary {
30  public:
~GSSAPILibrary()31   virtual ~GSSAPILibrary() {}
32 
33   // Initializes the library, including any necessary dynamic libraries.
34   // This is done separately from construction (which happens at startup time)
35   // in order to delay work until the class is actually needed.
36   virtual bool Init() = 0;
37 
38   // These methods match the ones in the GSSAPI library.
39   virtual OM_uint32 import_name(
40       OM_uint32* minor_status,
41       const gss_buffer_t input_name_buffer,
42       const gss_OID input_name_type,
43       gss_name_t* output_name) = 0;
44   virtual OM_uint32 release_name(
45       OM_uint32* minor_status,
46       gss_name_t* input_name) = 0;
47   virtual OM_uint32 release_buffer(
48       OM_uint32* minor_status,
49       gss_buffer_t buffer) = 0;
50   virtual OM_uint32 display_name(
51       OM_uint32* minor_status,
52       const gss_name_t input_name,
53       gss_buffer_t output_name_buffer,
54       gss_OID* output_name_type) = 0;
55   virtual OM_uint32 display_status(
56       OM_uint32* minor_status,
57       OM_uint32 status_value,
58       int status_type,
59       const gss_OID mech_type,
60       OM_uint32* message_contex,
61       gss_buffer_t status_string) = 0;
62   virtual OM_uint32 init_sec_context(
63       OM_uint32* minor_status,
64       const gss_cred_id_t initiator_cred_handle,
65       gss_ctx_id_t* context_handle,
66       const gss_name_t target_name,
67       const gss_OID mech_type,
68       OM_uint32 req_flags,
69       OM_uint32 time_req,
70       const gss_channel_bindings_t input_chan_bindings,
71       const gss_buffer_t input_token,
72       gss_OID* actual_mech_type,
73       gss_buffer_t output_token,
74       OM_uint32* ret_flags,
75       OM_uint32* time_rec) = 0;
76   virtual OM_uint32 wrap_size_limit(
77       OM_uint32* minor_status,
78       const gss_ctx_id_t context_handle,
79       int conf_req_flag,
80       gss_qop_t qop_req,
81       OM_uint32 req_output_size,
82       OM_uint32* max_input_size) = 0;
83   virtual OM_uint32 delete_sec_context(
84       OM_uint32* minor_status,
85       gss_ctx_id_t* context_handle,
86       gss_buffer_t output_token) = 0;
87   virtual OM_uint32 inquire_context(
88       OM_uint32* minor_status,
89       const gss_ctx_id_t context_handle,
90       gss_name_t* src_name,
91       gss_name_t* targ_name,
92       OM_uint32* lifetime_rec,
93       gss_OID* mech_type,
94       OM_uint32* ctx_flags,
95       int* locally_initiated,
96       int* open) = 0;
97 
98 };
99 
100 // GSSAPISharedLibrary class is defined here so that unit tests can access it.
101 class GSSAPISharedLibrary : public GSSAPILibrary {
102  public:
103   // If |gssapi_library_name| is empty, hard-coded default library names are
104   // used.
105   explicit GSSAPISharedLibrary(const std::string& gssapi_library_name);
106   virtual ~GSSAPISharedLibrary();
107 
108   // GSSAPILibrary methods:
109   virtual bool Init();
110   virtual OM_uint32 import_name(
111       OM_uint32* minor_status,
112       const gss_buffer_t input_name_buffer,
113       const gss_OID input_name_type,
114       gss_name_t* output_name);
115   virtual OM_uint32 release_name(
116       OM_uint32* minor_status,
117       gss_name_t* input_name);
118   virtual OM_uint32 release_buffer(
119       OM_uint32* minor_status,
120       gss_buffer_t buffer);
121   virtual OM_uint32 display_name(
122       OM_uint32* minor_status,
123       const gss_name_t input_name,
124       gss_buffer_t output_name_buffer,
125       gss_OID* output_name_type);
126   virtual OM_uint32 display_status(
127       OM_uint32* minor_status,
128       OM_uint32 status_value,
129       int status_type,
130       const gss_OID mech_type,
131       OM_uint32* message_contex,
132       gss_buffer_t status_string);
133   virtual OM_uint32 init_sec_context(
134       OM_uint32* minor_status,
135       const gss_cred_id_t initiator_cred_handle,
136       gss_ctx_id_t* context_handle,
137       const gss_name_t target_name,
138       const gss_OID mech_type,
139       OM_uint32 req_flags,
140       OM_uint32 time_req,
141       const gss_channel_bindings_t input_chan_bindings,
142       const gss_buffer_t input_token,
143       gss_OID* actual_mech_type,
144       gss_buffer_t output_token,
145       OM_uint32* ret_flags,
146       OM_uint32* time_rec);
147   virtual OM_uint32 wrap_size_limit(
148       OM_uint32* minor_status,
149       const gss_ctx_id_t context_handle,
150       int conf_req_flag,
151       gss_qop_t qop_req,
152       OM_uint32 req_output_size,
153       OM_uint32* max_input_size);
154   virtual OM_uint32 delete_sec_context(
155       OM_uint32* minor_status,
156       gss_ctx_id_t* context_handle,
157       gss_buffer_t output_token);
158   virtual OM_uint32 inquire_context(
159       OM_uint32* minor_status,
160       const gss_ctx_id_t context_handle,
161       gss_name_t* src_name,
162       gss_name_t* targ_name,
163       OM_uint32* lifetime_rec,
164       gss_OID* mech_type,
165       OM_uint32* ctx_flags,
166       int* locally_initiated,
167       int* open);
168 
169  private:
170   FRIEND_TEST_ALL_PREFIXES(HttpAuthGSSAPIPOSIXTest, GSSAPIStartup);
171 
172   bool InitImpl();
173   // Finds a usable dynamic library for GSSAPI and loads it.  The criteria are:
174   //   1. The library must exist.
175   //   2. The library must export the functions we need.
176   base::NativeLibrary LoadSharedLibrary();
177   bool BindMethods(base::NativeLibrary lib);
178 
179   bool initialized_;
180 
181   std::string gssapi_library_name_;
182   // Need some way to invalidate the library.
183   base::NativeLibrary gssapi_library_;
184 
185   // Function pointers
186   gss_import_name_type import_name_;
187   gss_release_name_type release_name_;
188   gss_release_buffer_type release_buffer_;
189   gss_display_name_type display_name_;
190   gss_display_status_type display_status_;
191   gss_init_sec_context_type init_sec_context_;
192   gss_wrap_size_limit_type wrap_size_limit_;
193   gss_delete_sec_context_type delete_sec_context_;
194   gss_inquire_context_type inquire_context_;
195 };
196 
197 // ScopedSecurityContext releases a gss_ctx_id_t when it goes out of
198 // scope.
199 class ScopedSecurityContext {
200  public:
201   explicit ScopedSecurityContext(GSSAPILibrary* gssapi_lib);
202   ~ScopedSecurityContext();
203 
get()204   gss_ctx_id_t get() const { return security_context_; }
receive()205   gss_ctx_id_t* receive() { return &security_context_; }
206 
207  private:
208   gss_ctx_id_t security_context_;
209   GSSAPILibrary* gssapi_lib_;
210 
211   DISALLOW_COPY_AND_ASSIGN(ScopedSecurityContext);
212 };
213 
214 
215 // TODO(ahendrickson): Share code with HttpAuthSSPI.
216 class HttpAuthGSSAPI {
217  public:
218   HttpAuthGSSAPI(GSSAPILibrary* library,
219                  const std::string& scheme,
220                  const gss_OID gss_oid);
221   ~HttpAuthGSSAPI();
222 
223   bool Init();
224 
225   bool NeedsIdentity() const;
226 
227   HttpAuth::AuthorizationResult ParseChallenge(
228       HttpAuth::ChallengeTokenizer* tok);
229 
230   // Generates an authentication token.
231   // The return value is an error code. If it's not |OK|, the value of
232   // |*auth_token| is unspecified.
233   // |spn| is the Service Principal Name of the server that the token is
234   // being generated for.
235   // If this is the first round of a multiple round scheme, credentials are
236   // obtained using |*username| and |*password|. If |username| and |password|
237   // are NULL, the default credentials are used instead.
238   int GenerateAuthToken(const string16* username,
239                         const string16* password,
240                         const std::wstring& spn,
241                         std::string* auth_token);
242 
243   // Delegation is allowed on the Kerberos ticket. This allows certain servers
244   // to act as the user, such as an IIS server retrieiving data from a
245   // Kerberized MSSQL server.
246   void Delegate();
247 
248  private:
249   int GetNextSecurityToken(const std::wstring& spn,
250                            gss_buffer_t in_token,
251                            gss_buffer_t out_token);
252 
253   std::string scheme_;
254   gss_OID gss_oid_;
255   GSSAPILibrary* library_;
256   std::string decoded_server_auth_token_;
257   ScopedSecurityContext scoped_sec_context_;
258   bool can_delegate_;
259 };
260 
261 }  // namespace net
262 
263 #endif  // NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_
264