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
19namespace net {
20
21extern gss_OID CHROME_GSS_C_NT_HOSTBASED_SERVICE_X;
22extern gss_OID CHROME_GSS_C_NT_HOSTBASED_SERVICE;
23extern 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.
29class GSSAPILibrary {
30 public:
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.
101class 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.
199class ScopedSecurityContext {
200 public:
201  explicit ScopedSecurityContext(GSSAPILibrary* gssapi_lib);
202  ~ScopedSecurityContext();
203
204  gss_ctx_id_t get() const { return security_context_; }
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.
216class 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