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