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.
5 #ifndef NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_
6 #define NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_
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"
15 #if defined(OS_MACOSX)
16 // The OSX 10.9+ SDKs mark the functions in Kereberos.framework as deprecated,
17 // so the warnings must be manually suppressed.
18 #if defined(MAC_OS_X_VERSION_10_9) && \
19 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
20 #define GSSKRB_APPLE_DEPRECATED(x)
23 // Chrome supports OSX 10.6, which doesn't have access to GSS.framework. Chrome
24 // always dlopens libgssapi_krb5.dylib, which is provided by
25 // Kerberos.framework. On OSX 10.7+ this is an ABI comptabile shim that loads
27 #include <Kerberos/gssapi.h>
28 #elif defined(OS_FREEBSD)
29 #include <gssapi/gssapi.h>
36 class HttpAuthChallengeTokenizer
;
38 // Mechanism OID for GSSAPI. We always use SPNEGO.
39 NET_EXPORT_PRIVATE
extern gss_OID CHROME_GSS_SPNEGO_MECH_OID_DESC
;
41 // GSSAPILibrary is introduced so unit tests can mock the calls to the GSSAPI
42 // library. The default implementation attempts to load one of the standard
43 // GSSAPI library implementations, then simply passes the arguments on to
44 // that implementation.
45 class NET_EXPORT_PRIVATE GSSAPILibrary
{
47 virtual ~GSSAPILibrary() {}
49 // Initializes the library, including any necessary dynamic libraries.
50 // This is done separately from construction (which happens at startup time)
51 // in order to delay work until the class is actually needed.
52 virtual bool Init() = 0;
54 // These methods match the ones in the GSSAPI library.
55 virtual OM_uint32
import_name(
56 OM_uint32
* minor_status
,
57 const gss_buffer_t input_name_buffer
,
58 const gss_OID input_name_type
,
59 gss_name_t
* output_name
) = 0;
60 virtual OM_uint32
release_name(
61 OM_uint32
* minor_status
,
62 gss_name_t
* input_name
) = 0;
63 virtual OM_uint32
release_buffer(
64 OM_uint32
* minor_status
,
65 gss_buffer_t buffer
) = 0;
66 virtual OM_uint32
display_name(
67 OM_uint32
* minor_status
,
68 const gss_name_t input_name
,
69 gss_buffer_t output_name_buffer
,
70 gss_OID
* output_name_type
) = 0;
71 virtual OM_uint32
display_status(
72 OM_uint32
* minor_status
,
73 OM_uint32 status_value
,
75 const gss_OID mech_type
,
76 OM_uint32
* message_contex
,
77 gss_buffer_t status_string
) = 0;
78 virtual OM_uint32
init_sec_context(
79 OM_uint32
* minor_status
,
80 const gss_cred_id_t initiator_cred_handle
,
81 gss_ctx_id_t
* context_handle
,
82 const gss_name_t target_name
,
83 const gss_OID mech_type
,
86 const gss_channel_bindings_t input_chan_bindings
,
87 const gss_buffer_t input_token
,
88 gss_OID
* actual_mech_type
,
89 gss_buffer_t output_token
,
91 OM_uint32
* time_rec
) = 0;
92 virtual OM_uint32
wrap_size_limit(
93 OM_uint32
* minor_status
,
94 const gss_ctx_id_t context_handle
,
97 OM_uint32 req_output_size
,
98 OM_uint32
* max_input_size
) = 0;
99 virtual OM_uint32
delete_sec_context(
100 OM_uint32
* minor_status
,
101 gss_ctx_id_t
* context_handle
,
102 gss_buffer_t output_token
) = 0;
103 virtual OM_uint32
inquire_context(
104 OM_uint32
* minor_status
,
105 const gss_ctx_id_t context_handle
,
106 gss_name_t
* src_name
,
107 gss_name_t
* targ_name
,
108 OM_uint32
* lifetime_rec
,
110 OM_uint32
* ctx_flags
,
111 int* locally_initiated
,
115 // GSSAPISharedLibrary class is defined here so that unit tests can access it.
116 class NET_EXPORT_PRIVATE GSSAPISharedLibrary
: public GSSAPILibrary
{
118 // If |gssapi_library_name| is empty, hard-coded default library names are
120 explicit GSSAPISharedLibrary(const std::string
& gssapi_library_name
);
121 ~GSSAPISharedLibrary() override
;
123 // GSSAPILibrary methods:
124 bool Init() override
;
125 OM_uint32
import_name(OM_uint32
* minor_status
,
126 const gss_buffer_t input_name_buffer
,
127 const gss_OID input_name_type
,
128 gss_name_t
* output_name
) override
;
129 OM_uint32
release_name(OM_uint32
* minor_status
,
130 gss_name_t
* input_name
) override
;
131 OM_uint32
release_buffer(OM_uint32
* minor_status
,
132 gss_buffer_t buffer
) override
;
133 OM_uint32
display_name(OM_uint32
* minor_status
,
134 const gss_name_t input_name
,
135 gss_buffer_t output_name_buffer
,
136 gss_OID
* output_name_type
) override
;
137 OM_uint32
display_status(OM_uint32
* minor_status
,
138 OM_uint32 status_value
,
140 const gss_OID mech_type
,
141 OM_uint32
* message_contex
,
142 gss_buffer_t status_string
) override
;
143 OM_uint32
init_sec_context(OM_uint32
* minor_status
,
144 const gss_cred_id_t initiator_cred_handle
,
145 gss_ctx_id_t
* context_handle
,
146 const gss_name_t target_name
,
147 const gss_OID mech_type
,
150 const gss_channel_bindings_t input_chan_bindings
,
151 const gss_buffer_t input_token
,
152 gss_OID
* actual_mech_type
,
153 gss_buffer_t output_token
,
154 OM_uint32
* ret_flags
,
155 OM_uint32
* time_rec
) override
;
156 OM_uint32
wrap_size_limit(OM_uint32
* minor_status
,
157 const gss_ctx_id_t context_handle
,
160 OM_uint32 req_output_size
,
161 OM_uint32
* max_input_size
) override
;
162 OM_uint32
delete_sec_context(OM_uint32
* minor_status
,
163 gss_ctx_id_t
* context_handle
,
164 gss_buffer_t output_token
) override
;
165 OM_uint32
inquire_context(OM_uint32
* minor_status
,
166 const gss_ctx_id_t context_handle
,
167 gss_name_t
* src_name
,
168 gss_name_t
* targ_name
,
169 OM_uint32
* lifetime_rec
,
171 OM_uint32
* ctx_flags
,
172 int* locally_initiated
,
176 typedef decltype(&gss_import_name
) gss_import_name_type
;
177 typedef decltype(&gss_release_name
) gss_release_name_type
;
178 typedef decltype(&gss_release_buffer
) gss_release_buffer_type
;
179 typedef decltype(&gss_display_name
) gss_display_name_type
;
180 typedef decltype(&gss_display_status
) gss_display_status_type
;
181 typedef decltype(&gss_init_sec_context
) gss_init_sec_context_type
;
182 typedef decltype(&gss_wrap_size_limit
) gss_wrap_size_limit_type
;
183 typedef decltype(&gss_delete_sec_context
) gss_delete_sec_context_type
;
184 typedef decltype(&gss_inquire_context
) gss_inquire_context_type
;
186 FRIEND_TEST_ALL_PREFIXES(HttpAuthGSSAPIPOSIXTest
, GSSAPIStartup
);
189 // Finds a usable dynamic library for GSSAPI and loads it. The criteria are:
190 // 1. The library must exist.
191 // 2. The library must export the functions we need.
192 base::NativeLibrary
LoadSharedLibrary();
193 bool BindMethods(base::NativeLibrary lib
);
197 std::string gssapi_library_name_
;
198 // Need some way to invalidate the library.
199 base::NativeLibrary gssapi_library_
;
202 gss_import_name_type import_name_
;
203 gss_release_name_type release_name_
;
204 gss_release_buffer_type release_buffer_
;
205 gss_display_name_type display_name_
;
206 gss_display_status_type display_status_
;
207 gss_init_sec_context_type init_sec_context_
;
208 gss_wrap_size_limit_type wrap_size_limit_
;
209 gss_delete_sec_context_type delete_sec_context_
;
210 gss_inquire_context_type inquire_context_
;
213 // ScopedSecurityContext releases a gss_ctx_id_t when it goes out of
215 class ScopedSecurityContext
{
217 explicit ScopedSecurityContext(GSSAPILibrary
* gssapi_lib
);
218 ~ScopedSecurityContext();
220 gss_ctx_id_t
get() const { return security_context_
; }
221 gss_ctx_id_t
* receive() { return &security_context_
; }
224 gss_ctx_id_t security_context_
;
225 GSSAPILibrary
* gssapi_lib_
;
227 DISALLOW_COPY_AND_ASSIGN(ScopedSecurityContext
);
231 // TODO(ahendrickson): Share code with HttpAuthSSPI.
232 class NET_EXPORT_PRIVATE HttpAuthGSSAPI
{
234 HttpAuthGSSAPI(GSSAPILibrary
* library
,
235 const std::string
& scheme
,
236 const gss_OID gss_oid
);
241 bool NeedsIdentity() const;
243 bool AllowsExplicitCredentials() const;
245 HttpAuth::AuthorizationResult
ParseChallenge(
246 HttpAuthChallengeTokenizer
* tok
);
248 // Generates an authentication token.
249 // The return value is an error code. If it's not |OK|, the value of
250 // |*auth_token| is unspecified.
251 // |spn| is the Service Principal Name of the server that the token is
252 // being generated for.
253 // If this is the first round of a multiple round scheme, credentials are
254 // obtained using |*credentials|. If |credentials| is NULL, the default
255 // credentials are used instead.
256 int GenerateAuthToken(const AuthCredentials
* credentials
,
257 const std::string
& spn
,
258 std::string
* auth_token
);
260 // Delegation is allowed on the Kerberos ticket. This allows certain servers
261 // to act as the user, such as an IIS server retrieiving data from a
262 // Kerberized MSSQL server.
266 int GetNextSecurityToken(const std::string
& spn
,
267 gss_buffer_t in_token
,
268 gss_buffer_t out_token
);
272 GSSAPILibrary
* library_
;
273 std::string decoded_server_auth_token_
;
274 ScopedSecurityContext scoped_sec_context_
;
280 #endif // NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_