OLD | NEW |
| (Empty) |
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 #include "net/http/mock_gssapi_library_posix.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/strings/string_util.h" | |
9 #include "base/strings/stringprintf.h" | |
10 #include "testing/gtest/include/gtest/gtest.h" | |
11 | |
12 namespace net { | |
13 | |
14 namespace test { | |
15 | |
16 struct GssNameMockImpl { | |
17 std::string name; | |
18 gss_OID_desc name_type; | |
19 }; | |
20 | |
21 } // namespace test | |
22 | |
23 namespace { | |
24 | |
25 // gss_OID helpers. | |
26 // NOTE: gss_OID's do not own the data they point to, which should be static. | |
27 void ClearOid(gss_OID dest) { | |
28 if (!dest) | |
29 return; | |
30 dest->length = 0; | |
31 dest->elements = NULL; | |
32 } | |
33 | |
34 void SetOid(gss_OID dest, const void* src, size_t length) { | |
35 if (!dest) | |
36 return; | |
37 ClearOid(dest); | |
38 if (!src) | |
39 return; | |
40 dest->length = length; | |
41 if (length) | |
42 dest->elements = const_cast<void*>(src); | |
43 } | |
44 | |
45 void CopyOid(gss_OID dest, const gss_OID_desc* src) { | |
46 if (!dest) | |
47 return; | |
48 ClearOid(dest); | |
49 if (!src) | |
50 return; | |
51 SetOid(dest, src->elements, src->length); | |
52 } | |
53 | |
54 // gss_buffer_t helpers. | |
55 void ClearBuffer(gss_buffer_t dest) { | |
56 if (!dest) | |
57 return; | |
58 dest->length = 0; | |
59 delete [] reinterpret_cast<char*>(dest->value); | |
60 dest->value = NULL; | |
61 } | |
62 | |
63 void SetBuffer(gss_buffer_t dest, const void* src, size_t length) { | |
64 if (!dest) | |
65 return; | |
66 ClearBuffer(dest); | |
67 if (!src) | |
68 return; | |
69 dest->length = length; | |
70 if (length) { | |
71 dest->value = new char[length]; | |
72 memcpy(dest->value, src, length); | |
73 } | |
74 } | |
75 | |
76 void CopyBuffer(gss_buffer_t dest, const gss_buffer_t src) { | |
77 if (!dest) | |
78 return; | |
79 ClearBuffer(dest); | |
80 if (!src) | |
81 return; | |
82 SetBuffer(dest, src->value, src->length); | |
83 } | |
84 | |
85 std::string BufferToString(const gss_buffer_t src) { | |
86 std::string dest; | |
87 if (!src) | |
88 return dest; | |
89 const char* string = reinterpret_cast<char*>(src->value); | |
90 dest.assign(string, src->length); | |
91 return dest; | |
92 } | |
93 | |
94 void BufferFromString(const std::string& src, gss_buffer_t dest) { | |
95 if (!dest) | |
96 return; | |
97 SetBuffer(dest, src.c_str(), src.length()); | |
98 } | |
99 | |
100 // gss_name_t helpers. | |
101 void ClearName(gss_name_t dest) { | |
102 if (!dest) | |
103 return; | |
104 test::GssNameMockImpl* name = reinterpret_cast<test::GssNameMockImpl*>(dest); | |
105 name->name.clear(); | |
106 ClearOid(&name->name_type); | |
107 } | |
108 | |
109 void SetName(gss_name_t dest, const void* src, size_t length) { | |
110 if (!dest) | |
111 return; | |
112 ClearName(dest); | |
113 if (!src) | |
114 return; | |
115 test::GssNameMockImpl* name = reinterpret_cast<test::GssNameMockImpl*>(dest); | |
116 name->name.assign(reinterpret_cast<const char*>(src), length); | |
117 } | |
118 | |
119 std::string NameToString(const gss_name_t& src) { | |
120 std::string dest; | |
121 if (!src) | |
122 return dest; | |
123 test::GssNameMockImpl* string = | |
124 reinterpret_cast<test::GssNameMockImpl*>(src); | |
125 dest = string->name; | |
126 return dest; | |
127 } | |
128 | |
129 void NameFromString(const std::string& src, gss_name_t dest) { | |
130 if (!dest) | |
131 return; | |
132 SetName(dest, src.c_str(), src.length()); | |
133 } | |
134 | |
135 } // namespace | |
136 | |
137 namespace test { | |
138 | |
139 GssContextMockImpl::GssContextMockImpl() | |
140 : lifetime_rec(0), | |
141 ctx_flags(0), | |
142 locally_initiated(0), | |
143 open(0) { | |
144 ClearOid(&mech_type); | |
145 } | |
146 | |
147 GssContextMockImpl::GssContextMockImpl(const GssContextMockImpl& other) | |
148 : src_name(other.src_name), | |
149 targ_name(other.targ_name), | |
150 lifetime_rec(other.lifetime_rec), | |
151 ctx_flags(other.ctx_flags), | |
152 locally_initiated(other.locally_initiated), | |
153 open(other.open) { | |
154 CopyOid(&mech_type, &other.mech_type); | |
155 } | |
156 | |
157 GssContextMockImpl::GssContextMockImpl(const char* src_name_in, | |
158 const char* targ_name_in, | |
159 OM_uint32 lifetime_rec_in, | |
160 const gss_OID_desc& mech_type_in, | |
161 OM_uint32 ctx_flags_in, | |
162 int locally_initiated_in, | |
163 int open_in) | |
164 : src_name(src_name_in ? src_name_in : ""), | |
165 targ_name(targ_name_in ? targ_name_in : ""), | |
166 lifetime_rec(lifetime_rec_in), | |
167 ctx_flags(ctx_flags_in), | |
168 locally_initiated(locally_initiated_in), | |
169 open(open_in) { | |
170 CopyOid(&mech_type, &mech_type_in); | |
171 } | |
172 | |
173 GssContextMockImpl::~GssContextMockImpl() { | |
174 ClearOid(&mech_type); | |
175 } | |
176 | |
177 void GssContextMockImpl::Assign( | |
178 const GssContextMockImpl& other) { | |
179 if (&other == this) | |
180 return; | |
181 src_name = other.src_name; | |
182 targ_name = other.targ_name; | |
183 lifetime_rec = other.lifetime_rec; | |
184 CopyOid(&mech_type, &other.mech_type); | |
185 ctx_flags = other.ctx_flags; | |
186 locally_initiated = other.locally_initiated; | |
187 open = other.open; | |
188 } | |
189 | |
190 MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery() | |
191 : expected_package(), | |
192 response_code(0), | |
193 minor_response_code(0), | |
194 context_info() { | |
195 expected_input_token.length = 0; | |
196 expected_input_token.value = NULL; | |
197 output_token.length = 0; | |
198 output_token.value = NULL; | |
199 } | |
200 | |
201 MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery( | |
202 const std::string& in_expected_package, | |
203 OM_uint32 in_response_code, | |
204 OM_uint32 in_minor_response_code, | |
205 const test::GssContextMockImpl& in_context_info, | |
206 const char* in_expected_input_token, | |
207 const char* in_output_token) | |
208 : expected_package(in_expected_package), | |
209 response_code(in_response_code), | |
210 minor_response_code(in_minor_response_code), | |
211 context_info(in_context_info) { | |
212 if (in_expected_input_token) { | |
213 expected_input_token.length = strlen(in_expected_input_token); | |
214 expected_input_token.value = const_cast<char*>(in_expected_input_token); | |
215 } else { | |
216 expected_input_token.length = 0; | |
217 expected_input_token.value = NULL; | |
218 } | |
219 | |
220 if (in_output_token) { | |
221 output_token.length = strlen(in_output_token); | |
222 output_token.value = const_cast<char*>(in_output_token); | |
223 } else { | |
224 output_token.length = 0; | |
225 output_token.value = NULL; | |
226 } | |
227 } | |
228 | |
229 MockGSSAPILibrary::SecurityContextQuery::~SecurityContextQuery() {} | |
230 | |
231 MockGSSAPILibrary::MockGSSAPILibrary() { | |
232 } | |
233 | |
234 MockGSSAPILibrary::~MockGSSAPILibrary() { | |
235 } | |
236 | |
237 void MockGSSAPILibrary::ExpectSecurityContext( | |
238 const std::string& expected_package, | |
239 OM_uint32 response_code, | |
240 OM_uint32 minor_response_code, | |
241 const GssContextMockImpl& context_info, | |
242 const gss_buffer_desc& expected_input_token, | |
243 const gss_buffer_desc& output_token) { | |
244 SecurityContextQuery security_query; | |
245 security_query.expected_package = expected_package; | |
246 security_query.response_code = response_code; | |
247 security_query.minor_response_code = minor_response_code; | |
248 security_query.context_info.Assign(context_info); | |
249 security_query.expected_input_token = expected_input_token; | |
250 security_query.output_token = output_token; | |
251 expected_security_queries_.push_back(security_query); | |
252 } | |
253 | |
254 bool MockGSSAPILibrary::Init() { | |
255 return true; | |
256 } | |
257 | |
258 // These methods match the ones in the GSSAPI library. | |
259 OM_uint32 MockGSSAPILibrary::import_name( | |
260 OM_uint32* minor_status, | |
261 const gss_buffer_t input_name_buffer, | |
262 const gss_OID input_name_type, | |
263 gss_name_t* output_name) { | |
264 if (minor_status) | |
265 *minor_status = 0; | |
266 if (!output_name) | |
267 return GSS_S_BAD_NAME; | |
268 if (!input_name_buffer) | |
269 return GSS_S_CALL_BAD_STRUCTURE; | |
270 if (!input_name_type) | |
271 return GSS_S_BAD_NAMETYPE; | |
272 GssNameMockImpl* output = new GssNameMockImpl; | |
273 if (output == NULL) | |
274 return GSS_S_FAILURE; | |
275 output->name_type.length = 0; | |
276 output->name_type.elements = NULL; | |
277 | |
278 // Save the data. | |
279 output->name = BufferToString(input_name_buffer); | |
280 CopyOid(&output->name_type, input_name_type); | |
281 *output_name = reinterpret_cast<gss_name_t>(output); | |
282 | |
283 return GSS_S_COMPLETE; | |
284 } | |
285 | |
286 OM_uint32 MockGSSAPILibrary::release_name( | |
287 OM_uint32* minor_status, | |
288 gss_name_t* input_name) { | |
289 if (minor_status) | |
290 *minor_status = 0; | |
291 if (!input_name) | |
292 return GSS_S_BAD_NAME; | |
293 if (!*input_name) | |
294 return GSS_S_COMPLETE; | |
295 GssNameMockImpl* name = *reinterpret_cast<GssNameMockImpl**>(input_name); | |
296 ClearName(*input_name); | |
297 delete name; | |
298 *input_name = NULL; | |
299 return GSS_S_COMPLETE; | |
300 } | |
301 | |
302 OM_uint32 MockGSSAPILibrary::release_buffer( | |
303 OM_uint32* minor_status, | |
304 gss_buffer_t buffer) { | |
305 if (minor_status) | |
306 *minor_status = 0; | |
307 if (!buffer) | |
308 return GSS_S_BAD_NAME; | |
309 ClearBuffer(buffer); | |
310 return GSS_S_COMPLETE; | |
311 } | |
312 | |
313 OM_uint32 MockGSSAPILibrary::display_name( | |
314 OM_uint32* minor_status, | |
315 const gss_name_t input_name, | |
316 gss_buffer_t output_name_buffer, | |
317 gss_OID* output_name_type) { | |
318 if (minor_status) | |
319 *minor_status = 0; | |
320 if (!input_name) | |
321 return GSS_S_BAD_NAME; | |
322 if (!output_name_buffer) | |
323 return GSS_S_CALL_BAD_STRUCTURE; | |
324 if (!output_name_type) | |
325 return GSS_S_CALL_BAD_STRUCTURE; | |
326 std::string name(NameToString(input_name)); | |
327 BufferFromString(name, output_name_buffer); | |
328 GssNameMockImpl* internal_name = | |
329 *reinterpret_cast<GssNameMockImpl**>(input_name); | |
330 if (output_name_type) | |
331 *output_name_type = internal_name ? &internal_name->name_type : NULL; | |
332 return GSS_S_COMPLETE; | |
333 } | |
334 | |
335 OM_uint32 MockGSSAPILibrary::display_status( | |
336 OM_uint32* minor_status, | |
337 OM_uint32 status_value, | |
338 int status_type, | |
339 const gss_OID mech_type, | |
340 OM_uint32* message_context, | |
341 gss_buffer_t status_string) { | |
342 if (minor_status) | |
343 *minor_status = 0; | |
344 std::string msg = base::StringPrintf("Value: %u, Type %u", | |
345 status_value, | |
346 status_type); | |
347 if (message_context) | |
348 *message_context = 0; | |
349 BufferFromString(msg, status_string); | |
350 return GSS_S_COMPLETE; | |
351 } | |
352 | |
353 OM_uint32 MockGSSAPILibrary::init_sec_context( | |
354 OM_uint32* minor_status, | |
355 const gss_cred_id_t initiator_cred_handle, | |
356 gss_ctx_id_t* context_handle, | |
357 const gss_name_t target_name, | |
358 const gss_OID mech_type, | |
359 OM_uint32 req_flags, | |
360 OM_uint32 time_req, | |
361 const gss_channel_bindings_t input_chan_bindings, | |
362 const gss_buffer_t input_token, | |
363 gss_OID* actual_mech_type, | |
364 gss_buffer_t output_token, | |
365 OM_uint32* ret_flags, | |
366 OM_uint32* time_rec) { | |
367 if (minor_status) | |
368 *minor_status = 0; | |
369 if (!context_handle) | |
370 return GSS_S_CALL_BAD_STRUCTURE; | |
371 GssContextMockImpl** internal_context_handle = | |
372 reinterpret_cast<test::GssContextMockImpl**>(context_handle); | |
373 // Create it if necessary. | |
374 if (!*internal_context_handle) { | |
375 *internal_context_handle = new GssContextMockImpl; | |
376 } | |
377 EXPECT_TRUE(*internal_context_handle); | |
378 GssContextMockImpl& context = **internal_context_handle; | |
379 if (expected_security_queries_.empty()) { | |
380 return GSS_S_UNAVAILABLE; | |
381 } | |
382 SecurityContextQuery security_query = expected_security_queries_.front(); | |
383 expected_security_queries_.pop_front(); | |
384 EXPECT_EQ(std::string("Negotiate"), security_query.expected_package); | |
385 OM_uint32 major_status = security_query.response_code; | |
386 if (minor_status) | |
387 *minor_status = security_query.minor_response_code; | |
388 context.src_name = security_query.context_info.src_name; | |
389 context.targ_name = security_query.context_info.targ_name; | |
390 context.lifetime_rec = security_query.context_info.lifetime_rec; | |
391 CopyOid(&context.mech_type, &security_query.context_info.mech_type); | |
392 context.ctx_flags = security_query.context_info.ctx_flags; | |
393 context.locally_initiated = security_query.context_info.locally_initiated; | |
394 context.open = security_query.context_info.open; | |
395 if (!input_token) { | |
396 EXPECT_FALSE(security_query.expected_input_token.length); | |
397 } else { | |
398 EXPECT_EQ(input_token->length, security_query.expected_input_token.length); | |
399 if (input_token->length) { | |
400 EXPECT_EQ(0, memcmp(input_token->value, | |
401 security_query.expected_input_token.value, | |
402 input_token->length)); | |
403 } | |
404 } | |
405 CopyBuffer(output_token, &security_query.output_token); | |
406 if (actual_mech_type) | |
407 CopyOid(*actual_mech_type, mech_type); | |
408 if (ret_flags) | |
409 *ret_flags = req_flags; | |
410 return major_status; | |
411 } | |
412 | |
413 OM_uint32 MockGSSAPILibrary::wrap_size_limit( | |
414 OM_uint32* minor_status, | |
415 const gss_ctx_id_t context_handle, | |
416 int conf_req_flag, | |
417 gss_qop_t qop_req, | |
418 OM_uint32 req_output_size, | |
419 OM_uint32* max_input_size) { | |
420 if (minor_status) | |
421 *minor_status = 0; | |
422 ADD_FAILURE(); | |
423 return GSS_S_UNAVAILABLE; | |
424 } | |
425 | |
426 OM_uint32 MockGSSAPILibrary::delete_sec_context( | |
427 OM_uint32* minor_status, | |
428 gss_ctx_id_t* context_handle, | |
429 gss_buffer_t output_token) { | |
430 if (minor_status) | |
431 *minor_status = 0; | |
432 if (!context_handle) | |
433 return GSS_S_CALL_BAD_STRUCTURE; | |
434 GssContextMockImpl** internal_context_handle = | |
435 reinterpret_cast<GssContextMockImpl**>(context_handle); | |
436 if (*internal_context_handle) { | |
437 delete *internal_context_handle; | |
438 *internal_context_handle = NULL; | |
439 } | |
440 return GSS_S_COMPLETE; | |
441 } | |
442 | |
443 OM_uint32 MockGSSAPILibrary::inquire_context( | |
444 OM_uint32* minor_status, | |
445 const gss_ctx_id_t context_handle, | |
446 gss_name_t* src_name, | |
447 gss_name_t* targ_name, | |
448 OM_uint32* lifetime_rec, | |
449 gss_OID* mech_type, | |
450 OM_uint32* ctx_flags, | |
451 int* locally_initiated, | |
452 int* open) { | |
453 if (minor_status) | |
454 *minor_status = 0; | |
455 if (!context_handle) | |
456 return GSS_S_CALL_BAD_STRUCTURE; | |
457 GssContextMockImpl* internal_context_ptr = | |
458 reinterpret_cast<GssContextMockImpl*>(context_handle); | |
459 GssContextMockImpl& context = *internal_context_ptr; | |
460 if (src_name) | |
461 NameFromString(context.src_name, *src_name); | |
462 if (targ_name) | |
463 NameFromString(context.targ_name, *targ_name); | |
464 if (lifetime_rec) | |
465 *lifetime_rec = context.lifetime_rec; | |
466 if (mech_type) | |
467 CopyOid(*mech_type, &context.mech_type); | |
468 if (ctx_flags) | |
469 *ctx_flags = context.ctx_flags; | |
470 if (locally_initiated) | |
471 *locally_initiated = context.locally_initiated; | |
472 if (open) | |
473 *open = context.open; | |
474 return GSS_S_COMPLETE; | |
475 } | |
476 | |
477 } // namespace test | |
478 | |
479 } // namespace net | |
480 | |
OLD | NEW |