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.
5 #include "net/http/mock_gssapi_library_posix.h"
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"
16 struct GssNameMockImpl
{
18 gss_OID_desc name_type
;
26 // NOTE: gss_OID's do not own the data they point to, which should be static.
27 void ClearOid(gss_OID dest
) {
31 dest
->elements
= NULL
;
34 void SetOid(gss_OID dest
, const void* src
, size_t length
) {
40 dest
->length
= length
;
42 dest
->elements
= const_cast<void*>(src
);
45 void CopyOid(gss_OID dest
, const gss_OID_desc
* src
) {
51 SetOid(dest
, src
->elements
, src
->length
);
54 // gss_buffer_t helpers.
55 void ClearBuffer(gss_buffer_t dest
) {
59 delete [] reinterpret_cast<char*>(dest
->value
);
63 void SetBuffer(gss_buffer_t dest
, const void* src
, size_t length
) {
69 dest
->length
= length
;
71 dest
->value
= new char[length
];
72 memcpy(dest
->value
, src
, length
);
76 void CopyBuffer(gss_buffer_t dest
, const gss_buffer_t src
) {
82 SetBuffer(dest
, src
->value
, src
->length
);
85 std::string
BufferToString(const gss_buffer_t src
) {
89 const char* string
= reinterpret_cast<char*>(src
->value
);
90 dest
.assign(string
, src
->length
);
94 void BufferFromString(const std::string
& src
, gss_buffer_t dest
) {
97 SetBuffer(dest
, src
.c_str(), src
.length());
100 // gss_name_t helpers.
101 void ClearName(gss_name_t dest
) {
104 test::GssNameMockImpl
* name
= reinterpret_cast<test::GssNameMockImpl
*>(dest
);
106 ClearOid(&name
->name_type
);
109 void SetName(gss_name_t dest
, const void* src
, size_t length
) {
115 test::GssNameMockImpl
* name
= reinterpret_cast<test::GssNameMockImpl
*>(dest
);
116 name
->name
.assign(reinterpret_cast<const char*>(src
), length
);
119 std::string
NameToString(const gss_name_t
& src
) {
123 test::GssNameMockImpl
* string
=
124 reinterpret_cast<test::GssNameMockImpl
*>(src
);
129 void NameFromString(const std::string
& src
, gss_name_t dest
) {
132 SetName(dest
, src
.c_str(), src
.length());
139 GssContextMockImpl::GssContextMockImpl()
142 locally_initiated(0),
144 ClearOid(&mech_type
);
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
),
154 CopyOid(&mech_type
, &other
.mech_type
);
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
,
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
),
170 CopyOid(&mech_type
, &mech_type_in
);
173 GssContextMockImpl::~GssContextMockImpl() {
174 ClearOid(&mech_type
);
177 void GssContextMockImpl::Assign(
178 const GssContextMockImpl
& other
) {
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
;
190 MockGSSAPILibrary::SecurityContextQuery::SecurityContextQuery()
191 : expected_package(),
193 minor_response_code(0),
195 expected_input_token
.length
= 0;
196 expected_input_token
.value
= NULL
;
197 output_token
.length
= 0;
198 output_token
.value
= NULL
;
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
);
216 expected_input_token
.length
= 0;
217 expected_input_token
.value
= NULL
;
220 if (in_output_token
) {
221 output_token
.length
= strlen(in_output_token
);
222 output_token
.value
= const_cast<char*>(in_output_token
);
224 output_token
.length
= 0;
225 output_token
.value
= NULL
;
229 MockGSSAPILibrary::SecurityContextQuery::~SecurityContextQuery() {}
231 MockGSSAPILibrary::MockGSSAPILibrary() {
234 MockGSSAPILibrary::~MockGSSAPILibrary() {
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
);
254 bool MockGSSAPILibrary::Init() {
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
) {
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
;
274 return GSS_S_FAILURE
;
275 output
->name_type
.length
= 0;
276 output
->name_type
.elements
= NULL
;
279 output
->name
= BufferToString(input_name_buffer
);
280 CopyOid(&output
->name_type
, input_name_type
);
281 *output_name
= reinterpret_cast<gss_name_t
>(output
);
283 return GSS_S_COMPLETE
;
286 OM_uint32
MockGSSAPILibrary::release_name(
287 OM_uint32
* minor_status
,
288 gss_name_t
* input_name
) {
292 return GSS_S_BAD_NAME
;
294 return GSS_S_COMPLETE
;
295 GssNameMockImpl
* name
= *reinterpret_cast<GssNameMockImpl
**>(input_name
);
296 ClearName(*input_name
);
299 return GSS_S_COMPLETE
;
302 OM_uint32
MockGSSAPILibrary::release_buffer(
303 OM_uint32
* minor_status
,
304 gss_buffer_t buffer
) {
308 return GSS_S_BAD_NAME
;
310 return GSS_S_COMPLETE
;
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
) {
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
;
335 OM_uint32
MockGSSAPILibrary::display_status(
336 OM_uint32
* minor_status
,
337 OM_uint32 status_value
,
339 const gss_OID mech_type
,
340 OM_uint32
* message_context
,
341 gss_buffer_t status_string
) {
344 std::string msg
= base::StringPrintf("Value: %u, Type %u",
348 *message_context
= 0;
349 BufferFromString(msg
, status_string
);
350 return GSS_S_COMPLETE
;
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
,
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
) {
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
;
377 EXPECT_TRUE(*internal_context_handle
);
378 GssContextMockImpl
& context
= **internal_context_handle
;
379 if (expected_security_queries_
.empty()) {
380 return GSS_S_UNAVAILABLE
;
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
;
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
;
396 EXPECT_FALSE(security_query
.expected_input_token
.length
);
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
));
405 CopyBuffer(output_token
, &security_query
.output_token
);
406 if (actual_mech_type
)
407 CopyOid(*actual_mech_type
, mech_type
);
409 *ret_flags
= req_flags
;
413 OM_uint32
MockGSSAPILibrary::wrap_size_limit(
414 OM_uint32
* minor_status
,
415 const gss_ctx_id_t context_handle
,
418 OM_uint32 req_output_size
,
419 OM_uint32
* max_input_size
) {
423 return GSS_S_UNAVAILABLE
;
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
) {
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
;
440 return GSS_S_COMPLETE
;
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
,
450 OM_uint32
* ctx_flags
,
451 int* locally_initiated
,
456 return GSS_S_CALL_BAD_STRUCTURE
;
457 GssContextMockImpl
* internal_context_ptr
=
458 reinterpret_cast<GssContextMockImpl
*>(context_handle
);
459 GssContextMockImpl
& context
= *internal_context_ptr
;
461 NameFromString(context
.src_name
, *src_name
);
463 NameFromString(context
.targ_name
, *targ_name
);
465 *lifetime_rec
= context
.lifetime_rec
;
467 CopyOid(*mech_type
, &context
.mech_type
);
469 *ctx_flags
= context
.ctx_flags
;
470 if (locally_initiated
)
471 *locally_initiated
= context
.locally_initiated
;
473 *open
= context
.open
;
474 return GSS_S_COMPLETE
;