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