Home | History | Annotate | Download | only in http
      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 
    481