• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
ClearOid(gss_OID dest)27 void ClearOid(gss_OID dest) {
28   if (!dest)
29     return;
30   dest->length = 0;
31   dest->elements = NULL;
32 }
33 
SetOid(gss_OID dest,const void * src,size_t length)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 
CopyOid(gss_OID dest,const gss_OID_desc * src)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.
ClearBuffer(gss_buffer_t dest)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 
SetBuffer(gss_buffer_t dest,const void * src,size_t length)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 
CopyBuffer(gss_buffer_t dest,const gss_buffer_t src)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 
BufferToString(const gss_buffer_t src)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 
BufferFromString(const std::string & src,gss_buffer_t dest)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.
ClearName(gss_name_t dest)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 
SetName(gss_name_t dest,const void * src,size_t length)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 
NameToString(const gss_name_t & src)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 
NameFromString(const std::string & src,gss_name_t dest)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 
GssContextMockImpl()139 GssContextMockImpl::GssContextMockImpl()
140   : lifetime_rec(0),
141     ctx_flags(0),
142     locally_initiated(0),
143     open(0) {
144   ClearOid(&mech_type);
145 }
146 
GssContextMockImpl(const GssContextMockImpl & other)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 
GssContextMockImpl(const char * src_name_in,const char * targ_name_in,OM_uint32 lifetime_rec_in,const gss_OID_desc & mech_type_in,OM_uint32 ctx_flags_in,int locally_initiated_in,int open_in)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 
~GssContextMockImpl()173 GssContextMockImpl::~GssContextMockImpl() {
174   ClearOid(&mech_type);
175 }
176 
Assign(const GssContextMockImpl & other)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 
SecurityContextQuery()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 
SecurityContextQuery(const std::string & in_expected_package,OM_uint32 in_response_code,OM_uint32 in_minor_response_code,const test::GssContextMockImpl & in_context_info,const char * in_expected_input_token,const char * in_output_token)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 
~SecurityContextQuery()229 MockGSSAPILibrary::SecurityContextQuery::~SecurityContextQuery() {}
230 
MockGSSAPILibrary()231 MockGSSAPILibrary::MockGSSAPILibrary() {
232 }
233 
~MockGSSAPILibrary()234 MockGSSAPILibrary::~MockGSSAPILibrary() {
235 }
236 
ExpectSecurityContext(const std::string & expected_package,OM_uint32 response_code,OM_uint32 minor_response_code,const GssContextMockImpl & context_info,const gss_buffer_desc & expected_input_token,const gss_buffer_desc & output_token)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 
Init()254 bool MockGSSAPILibrary::Init() {
255   return true;
256 }
257 
258 // These methods match the ones in the GSSAPI library.
import_name(OM_uint32 * minor_status,const gss_buffer_t input_name_buffer,const gss_OID input_name_type,gss_name_t * output_name)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 
release_name(OM_uint32 * minor_status,gss_name_t * input_name)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 
release_buffer(OM_uint32 * minor_status,gss_buffer_t buffer)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 
display_name(OM_uint32 * minor_status,const gss_name_t input_name,gss_buffer_t output_name_buffer,gss_OID * output_name_type)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 
display_status(OM_uint32 * minor_status,OM_uint32 status_value,int status_type,const gss_OID mech_type,OM_uint32 * message_context,gss_buffer_t status_string)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 
init_sec_context(OM_uint32 * minor_status,const gss_cred_id_t initiator_cred_handle,gss_ctx_id_t * context_handle,const gss_name_t target_name,const gss_OID mech_type,OM_uint32 req_flags,OM_uint32 time_req,const gss_channel_bindings_t input_chan_bindings,const gss_buffer_t input_token,gss_OID * actual_mech_type,gss_buffer_t output_token,OM_uint32 * ret_flags,OM_uint32 * time_rec)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 
wrap_size_limit(OM_uint32 * minor_status,const gss_ctx_id_t context_handle,int conf_req_flag,gss_qop_t qop_req,OM_uint32 req_output_size,OM_uint32 * max_input_size)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 
delete_sec_context(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,gss_buffer_t output_token)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 
inquire_context(OM_uint32 * minor_status,const gss_ctx_id_t context_handle,gss_name_t * src_name,gss_name_t * targ_name,OM_uint32 * lifetime_rec,gss_OID * mech_type,OM_uint32 * ctx_flags,int * locally_initiated,int * open)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 
481