2 * Copyright (c) 2014, 2015 JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "GSSCreateSecContextTest.h"
37 #include "GSSInitSecContext.h"
38 #include "command_mocks/InitSecContextMock.h"
42 #include "utils/util_json.h"
43 #include <cache/GSSContextCache.h>
44 #include <cache/GSSNameCache.h>
45 #include <datamodel/GSSContext.h>
46 #include <utils/util_base64.h>
48 // Registers the fixture into the 'registry'
49 CPPUNIT_TEST_SUITE_REGISTRATION( GSSCreateSecContextTest );
53 static OM_uint32 KRB5_CALLCONV
55 OM_uint32 *minor_status,
56 gss_cred_id_t claimant_cred_handle,
57 gss_ctx_id_t *context_handle,
58 gss_name_t target_name,
62 gss_channel_bindings_t input_chan_bindings,
63 gss_buffer_t input_token,
64 gss_OID *actual_mech_type,
65 gss_buffer_t output_token,
69 gss_ctx_id_t tmpContext;
71 InitSecContextMock::visited = true;
73 /* Copy in the input to this function */
74 InitSecContextMock::claimant_cred_handle = claimant_cred_handle;
75 InitSecContextMock::target_name = target_name;
76 InitSecContextMock::mech_type = mech_type;
77 InitSecContextMock::req_flags = req_flags;
78 InitSecContextMock::time_req = time_req;
79 InitSecContextMock::input_chan_bindings = input_chan_bindings;
80 InitSecContextMock::input_token.length = input_token->length;
81 InitSecContextMock::input_token.value = input_token->value;
84 /* Copy out the output from this function */
85 *minor_status = InitSecContextMock::minor_status;
86 *actual_mech_type = InitSecContextMock::actual_mech_type;
87 output_token->length = InitSecContextMock::output_token.length;
88 output_token->value = InitSecContextMock::output_token.value;
89 *ret_flags = InitSecContextMock::ret_flags;
90 *time_rec = InitSecContextMock::time_rec;
92 /* Handle the one that's I/O */
93 tmpContext = *context_handle;
94 *context_handle = InitSecContextMock::context_handle;
95 InitSecContextMock::context_handle = tmpContext;
97 return InitSecContextMock::retVal;
102 GSSCreateSecContextTest::setUp()
104 InitSecContextMock::reset();
108 GSSCreateSecContextTest::tearDown()
113 GSSCreateSecContextTest::testConstructor()
115 GSSInitSecContext cmd = GSSInitSecContext();
116 init_sec_context_type cmdFn;
117 init_sec_context_type GSSFn;
119 cmdFn = cmd.getGSSFunction();
120 GSSFn = &gss_init_sec_context;
121 CPPUNIT_ASSERT_MESSAGE(
122 "The default constructor for GSSCreateSecContextCommand should assign the function gss_init_sec_context",
125 // Check that we defaut to the moonshot OID
126 CPPUNIT_ASSERT_EQUAL_MESSAGE(
127 "The mech_type default value is unexpected.",
128 std::string("{ 1 3 6 1 5 5 15 1 1 18 }"),
129 cmd.getMechType().toString()
135 * "method": "gss_create_sec_context",
140 * "mech_type": "{ 1 2 840 113554 1 2 1 4 }",
141 * "target_name": "me@my.sha/DOW"
145 void GSSCreateSecContextTest::testConstructorWithJSONObject()
147 OM_uint32 major, minor;
150 char *source_name = (char *)"HTTP@localhost\0";
153 major = gss_import_name(&minor, GSSBuffer(source_name).toGss(), GSS_C_NT_HOSTBASED_SERVICE, &src);
154 if (GSS_ERROR(major))
156 OM_uint32 min, context;
159 std::cout << "Error in importing name." << std::endl;
160 gss_display_status(&min, major, GSS_C_GSS_CODE, GSS_C_NT_HOSTBASED_SERVICE, &context, &buf);
161 std::cout << " message: " << (char *)buf.value << std::endl;
163 CPPUNIT_ASSERT_MESSAGE(
164 "Could not generate a name to test GSSCreateSecContext JSON parsing.",
167 source.setValue(src);
168 std::string key = GSSNameCache::instance()->store(source);
170 std::string input = "{\"req_flags\": \"1\", \
171 \"time_req\": \"2\", \
172 \"mech_type\": \"{ 1 2 840 113554 1 2 1 4 }\", \
173 \"target_name\": \"";
174 input = input + key + "\"}";
176 json_error_t jsonErr;
177 const char *in = input.c_str();
178 JSONObject json = JSONObject::load(in, 0, &jsonErr);
180 GSSInitSecContext cmd = GSSInitSecContext(
185 const char *from_cmd = cmd.getTargetDisplayName();
187 CPPUNIT_ASSERT_MESSAGE(
188 "The object does not have a target name.",
189 ( strcmp(source_name, from_cmd) == 0 )
192 CPPUNIT_ASSERT_EQUAL_MESSAGE(
193 "The context_handle values differ.",
194 json["context_handle"].integer(),
195 (json_int_t)cmd.getContextHandle()
198 CPPUNIT_ASSERT_EQUAL_MESSAGE(
199 "The mech_type values differ.",
200 std::string(json["mech_type"].string()),
201 cmd.getMechType().toString()
204 CPPUNIT_ASSERT_EQUAL_MESSAGE(
205 "The req_flags differ.",
206 (int)json["req_flags"].integer(),
207 (int)cmd.getReqFlags()
210 CPPUNIT_ASSERT_EQUAL_MESSAGE(
211 "The req_flags differ.",
212 (int)json["time_req"].integer(),
213 (int)cmd.getTimeReq()
219 GSSCreateSecContextTest::testEmptyCall()
221 gss_ctx_id_t expectedResult, expectedArgument;
223 GSSInitSecContext cmd (&mock_init_sec);
225 /* Set expectations on what the GSS function will be called with */
226 cmd.time_req = rand() % 1024;
227 cmd.req_flags = rand() % 1024;
228 cmd.target_name = NULL;
229 cmd.context_handle = expectedArgument = (gss_ctx_id_t)(long)rand();
233 /* Set expectations on what the GSS function will produce */
234 InitSecContextMock::retVal = rand() % 1024;
235 InitSecContextMock::minor_status = rand() % 1024;
236 InitSecContextMock::context_handle = expectedResult = (gss_ctx_id_t)(long)rand();
237 InitSecContextMock::actual_mech_type = NULL;
238 InitSecContextMock::output_token.value = (void *)"http@project-moonshot.org/PROJECT-MOONSHOT.ORG\0";
239 InitSecContextMock::output_token.length = strlen((char *)InitSecContextMock::output_token.value);
240 InitSecContextMock::ret_flags = rand() % 1024;
241 InitSecContextMock::time_req = rand() % 1024;
245 /* Check that init_sec_context's inputs are sent correctly */
246 CPPUNIT_ASSERT_MESSAGE(
247 "The GSS function was not invoked!",
248 InitSecContextMock::visited
250 CPPUNIT_ASSERT_EQUAL_MESSAGE(
251 "The time_req field was not used in the call to init_sec_context",
253 InitSecContextMock::time_req
255 CPPUNIT_ASSERT_EQUAL_MESSAGE(
256 "The req_flags field was not used in the call to init_sec_context",
258 InitSecContextMock::req_flags
260 CPPUNIT_ASSERT_EQUAL_MESSAGE(
261 "The mech_type field was not used in the call to init_sec_context",
262 cmd.getMechType().toGss(),
263 InitSecContextMock::mech_type
265 CPPUNIT_ASSERT_EQUAL_MESSAGE(
266 "The target_name field was not used in the call to init_sec_context",
268 InitSecContextMock::target_name
272 /* Check that init_sec_context's outputs are captured correctly */
273 CPPUNIT_ASSERT_EQUAL_MESSAGE(
274 "Return value was not copied back to the command.",
275 InitSecContextMock::retVal,
278 CPPUNIT_ASSERT_EQUAL_MESSAGE(
279 "Status was not copied back to the command.",
280 InitSecContextMock::minor_status,
283 CPPUNIT_ASSERT_EQUAL_MESSAGE(
284 "context_handle was not copied back to the command.",
288 CPPUNIT_ASSERT_EQUAL_MESSAGE(
289 "context_handle was not copied back to the command.",
291 InitSecContextMock::context_handle
293 CPPUNIT_ASSERT_EQUAL_MESSAGE(
294 "actual_mech_type was not copied back to the command.",
295 InitSecContextMock::actual_mech_type,
296 cmd.getActualMechType().toGss()
298 CPPUNIT_ASSERT_EQUAL_MESSAGE(
299 "output_token was not copied back to the command.",
300 InitSecContextMock::output_token.value,
301 cmd.output_token.value
303 CPPUNIT_ASSERT_EQUAL_MESSAGE(
304 "ret_flags was not copied back to the command.",
305 InitSecContextMock::ret_flags,
308 CPPUNIT_ASSERT_EQUAL_MESSAGE(
309 "time_rec was not copied back to the command.",
310 InitSecContextMock::time_rec,
314 // Set this to no context, or cleanup attempts to free the not-a-real-pointer.
315 InitSecContextMock::context_handle = GSS_C_NO_CONTEXT;
319 /* Expected JSON output:
322 * "command": "gss_init_sec_context",
325 * "context_handle": "base64_encoded_string",
326 * "major_status": ##,
327 * "output_token": "http@project-moonshot.org/PROJECT-MOONSHOT.ORG",
328 * "actual_mech_type": "{ 1 3 6 1 5 5 13 4 }",
329 * "minor_status": ##,
336 void GSSCreateSecContextTest::testJSONMarshal()
339 GSSInitSecContext cmd (&mock_init_sec);
341 GSSContextCache *cache = GSSContextCache::instance();
343 gss_ctx_id_t expectedResult;
348 // Set expectations on what the GSS function will produce
349 InitSecContextMock::retVal = GSS_S_CONTINUE_NEEDED;
350 InitSecContextMock::minor_status = 0;
351 InitSecContextMock::context_handle = expectedResult = (gss_ctx_id_t)(long)rand();
352 InitSecContextMock::actual_mech_type = (gss_OID)GSS_C_MA_MECH_NEGO;
353 InitSecContextMock::output_token.value = (void *)"http@project-moonshot.org/PROJECT-MOONSHOT.ORG\0";
354 InitSecContextMock::output_token.length = strlen((char *)InitSecContextMock::output_token.value);
355 InitSecContextMock::ret_flags = GSS_C_MUTUAL_FLAG |
357 GSS_C_SEQUENCE_FLAG |
361 GSS_C_PROT_READY_FLAG;
362 InitSecContextMock::time_req = GSS_C_INDEFINITE;
366 result = cmd.toJSON();
368 std::cout << "create sec context json: " << result->dump() << "\n";*/
370 CPPUNIT_ASSERT_EQUAL_MESSAGE(
371 "The return value was reported incorrectly",
372 (int)InitSecContextMock::retVal,
373 (int)( (*result)["major_status"].integer() )
376 CPPUNIT_ASSERT_EQUAL_MESSAGE(
377 "The minor_status value was reported incorrectly",
378 (int)InitSecContextMock::minor_status,
379 (int)( (*result)["minor_status"].integer() )
382 CPPUNIT_ASSERT_MESSAGE(
383 "The actual_mech_type value was reported incorrectly",
384 ( strcmp("{ 1 3 6 1 5 5 13 4 }",
385 (*result)["actual_mech_type"].string() ) == 0 )
390 std::string str = (*result)["output_token"].string();
392 void *decoded = base64Decode(str.c_str(), &len);
393 CPPUNIT_ASSERT_MESSAGE(
394 "The decoded token size is incorrect",
395 ( len == InitSecContextMock::output_token.length )
397 CPPUNIT_ASSERT_MESSAGE(
398 "The output_token value was reported incorrectly",
399 ( memcmp(InitSecContextMock::output_token.value,
400 decoded, len ) == 0 )
404 CPPUNIT_ASSERT_EQUAL_MESSAGE(
405 "The minor_status value was reported incorrectly",
406 (int)InitSecContextMock::ret_flags,
407 (int)( (*result)["ret_flags"].integer() )
410 CPPUNIT_ASSERT_EQUAL_MESSAGE(
411 "The minor_status value was reported incorrectly",
412 (int)InitSecContextMock::time_rec,
413 (int)( (*result)["time_rec"].integer() )
416 context = cache->retrieve( (*result)["context_handle"].string() );
418 CPPUNIT_ASSERT_EQUAL_MESSAGE(
419 "The returned context was reported incorrectly",
420 (long)expectedResult,
421 (long)context.getContext()