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