8926e7b1cc53ebe5bc9fb1768d184f622c2bb62f
[gssweb.git] / json_gssapi / test / GSSCreateSecContextTest.cpp
1 /*
2  * Copyright (c) 2014 <copyright holder> <email>
3  * 
4  * For license details, see the LICENSE file in the root of this project.
5  * 
6  */
7
8
9 #include "GSSCreateSecContextTest.h"
10 #include "GSSInitSecContext.h"
11 #include "command_mocks/InitSecContextMock.h"
12 #include <iostream>
13 #include <string.h>
14 #include <exception>
15 #include "util_json.h"
16 #include <cache/GSSContextCache.h>
17 #include <cache/GSSNameCache.h>
18 #include <datamodel/GSSContext.h>
19
20 // Registers the fixture into the 'registry'
21 CPPUNIT_TEST_SUITE_REGISTRATION( GSSCreateSecContextTest );
22
23 using std::cout;
24
25 static OM_uint32 KRB5_CALLCONV
26 mock_init_sec(
27     OM_uint32             *minor_status,
28     gss_cred_id_t          claimant_cred_handle,
29     gss_ctx_id_t          *context_handle,
30     gss_name_t             target_name,
31     gss_OID                mech_type,
32     OM_uint32              req_flags,
33     OM_uint32              time_req,
34     gss_channel_bindings_t input_chan_bindings,
35     gss_buffer_t           input_token,
36     gss_OID               *actual_mech_type,
37     gss_buffer_t           output_token,
38     OM_uint32             *ret_flags,
39     OM_uint32             *time_rec)
40 {
41   gss_ctx_id_t tmpContext;
42   
43   InitSecContextMock::visited = true;
44   
45   /* Copy in the input to this function */
46   InitSecContextMock::claimant_cred_handle = claimant_cred_handle;
47   InitSecContextMock::target_name = target_name;
48   InitSecContextMock::mech_type = mech_type;
49   InitSecContextMock::req_flags = req_flags;
50   InitSecContextMock::time_req = time_req;
51   InitSecContextMock::input_chan_bindings = input_chan_bindings;
52   InitSecContextMock::input_token.length = input_token->length;
53   InitSecContextMock::input_token.value = input_token->value;
54   
55   
56   /* Copy out the output from this function */
57   *minor_status = InitSecContextMock::minor_status;
58   *actual_mech_type = InitSecContextMock::actual_mech_type;
59   output_token->length = InitSecContextMock::output_token.length;
60   output_token->value = InitSecContextMock::output_token.value;
61   *ret_flags = InitSecContextMock::ret_flags;
62   *time_rec = InitSecContextMock::time_rec;
63   
64   /* Handle the one that's I/O */
65   tmpContext = *context_handle;
66   *context_handle = InitSecContextMock::context_handle;
67   InitSecContextMock::context_handle = tmpContext;
68
69   return InitSecContextMock::retVal;
70 }
71
72
73 void
74 GSSCreateSecContextTest::setUp()
75 {
76   InitSecContextMock::reset();
77 }
78
79 void
80 GSSCreateSecContextTest::tearDown()
81 {
82 }
83
84 void
85 GSSCreateSecContextTest::testConstructor()
86 {
87   GSSInitSecContext cmd = GSSInitSecContext();
88   void *cmdFn;
89   void *GSSFn;
90   
91   cmdFn = cmd.getGSSFunction();
92   GSSFn = (void *)&gss_init_sec_context;
93   CPPUNIT_ASSERT_MESSAGE(
94     "The default constructor for GSSCreateSecContextCommand should assign the function gss_init_sec_context", 
95     cmdFn == GSSFn);
96   
97   // Check that we defaut to the moonshot OID
98   CPPUNIT_ASSERT_EQUAL_MESSAGE(
99     "The mech_type default value is unexpected.",
100     std::string("{ 1 3 6 1 5 5 15 1 1 18 }"),
101     cmd.getMechType().toString()
102   );
103 }
104
105 /* JSON Input:
106  * { 
107  *   "method": "gss_create_sec_context",
108  *   "arguments": 
109  *   {
110  *     "req_flags": "1",
111  *     "time_req": "2",
112  *     "mech_type": "{ 1 2 840 113554 1 2 1 4 }",
113  *     "target_name": "me@my.sha/DOW"
114  *   }
115  * }
116  */
117 void GSSCreateSecContextTest::testConstructorWithJSONObject()
118 {
119   OM_uint32 major, minor;
120   gss_name_t src;
121   GSSName source;
122   char *source_name = (char *)"HTTP@localhost\0";
123   
124   
125   major = gss_import_name(&minor, GSSBuffer(source_name).toGss(), GSS_C_NT_HOSTBASED_SERVICE, &src);
126   if (GSS_ERROR(major))
127   {
128     OM_uint32 min, context;
129     gss_buffer_desc buf;
130     
131     std::cout << "Error in importing name." << std::endl;
132     gss_display_status(&min, major, GSS_C_GSS_CODE, GSS_C_NT_HOSTBASED_SERVICE, &context, &buf);
133     std::cout << "  message: " << (char *)buf.value << std::endl;
134   }
135   CPPUNIT_ASSERT_MESSAGE(
136     "Could not generate a name to test GSSCreateSecContext JSON parsing.",
137     !GSS_ERROR(major)
138   );
139   source.setValue(src);
140   std::string key = GSSNameCache::instance()->store(source);
141
142   std::string input = "{\"req_flags\": \"1\", \
143     \"time_req\": \"2\", \
144     \"mech_type\": \"{ 1 2 840 113554 1 2 1 4 }\", \
145     \"target_name\": \"";
146   input = input + key + "\"}";
147
148   json_error_t jsonErr;
149   const char *in = input.c_str();
150   JSONObject json = JSONObject::load(in, 0, &jsonErr);
151   
152   GSSInitSecContext cmd = GSSInitSecContext(
153     &json, 
154     (void *)&mock_init_sec
155   );
156
157   const char *from_cmd = cmd.getTargetDisplayName();
158   
159   CPPUNIT_ASSERT_MESSAGE(
160     "The object does not have a target name.",
161     ( strcmp(source_name, from_cmd) == 0 )
162   );
163   
164   CPPUNIT_ASSERT_EQUAL_MESSAGE(
165     "The context_handle values differ.",
166     json["arguments"]["context_handle"].integer(),
167     (json_int_t)cmd.getContextHandle()
168   );
169   
170   CPPUNIT_ASSERT_EQUAL_MESSAGE(
171     "The mech_type values differ.",
172     std::string(json["arguments"]["mech_type"].string()), 
173     cmd.getMechType().toString()
174   );
175   
176   CPPUNIT_ASSERT_EQUAL_MESSAGE(
177     "The req_flags differ.",
178     (int)json["arguments"]["req_flags"].integer(),
179     (int)cmd.getReqFlags()
180   );
181   
182   CPPUNIT_ASSERT_EQUAL_MESSAGE(
183     "The req_flags differ.",
184     (int)json["arguments"]["time_req"].integer(),
185     (int)cmd.getTimeReq()
186   );
187   
188 }
189
190 void
191 GSSCreateSecContextTest::testEmptyCall()
192 {
193   gss_ctx_id_t expectedResult, expectedArgument;
194   
195   GSSInitSecContext cmd ((void *)&mock_init_sec);
196   
197   /* Set expectations on what the GSS function will be called with */
198   cmd.time_req = rand() % 1024;
199   cmd.req_flags = rand() % 1024;
200   cmd.target_name = NULL;
201   cmd.context_handle = expectedArgument = (gss_ctx_id_t)(long)rand();
202   
203   
204   
205   /* Set expectations on what the GSS function will produce */
206   InitSecContextMock::retVal = rand() % 1024;
207   InitSecContextMock::minor_status = rand() % 1024;
208   InitSecContextMock::context_handle = expectedResult = (gss_ctx_id_t)(long)rand();
209   InitSecContextMock::actual_mech_type = NULL;
210   InitSecContextMock::output_token.value = (void *)"http@project-moonshot.org/PROJECT-MOONSHOT.ORG\0";
211   InitSecContextMock::output_token.length = strlen((char *)InitSecContextMock::output_token.value);
212   InitSecContextMock::ret_flags = rand() % 1024;
213   InitSecContextMock::time_req = rand() % 1024;
214   
215   cmd.execute();
216   
217   /* Check that init_sec_context's inputs are sent correctly */
218   CPPUNIT_ASSERT_MESSAGE(
219     "The GSS function was not invoked!",
220     InitSecContextMock::visited
221   );
222   CPPUNIT_ASSERT_EQUAL_MESSAGE(
223     "The time_req field was not used in the call to init_sec_context",
224     cmd.time_req,
225     InitSecContextMock::time_req
226   );
227   CPPUNIT_ASSERT_EQUAL_MESSAGE(
228     "The req_flags field was not used in the call to init_sec_context",
229     cmd.req_flags,
230     InitSecContextMock::req_flags
231   );
232   CPPUNIT_ASSERT_EQUAL_MESSAGE(
233     "The mech_type field was not used in the call to init_sec_context",
234     cmd.getMechType().toGss(),
235     InitSecContextMock::mech_type
236   );
237   CPPUNIT_ASSERT_EQUAL_MESSAGE(
238     "The target_name field was not used in the call to init_sec_context",
239     cmd.target_name,
240     InitSecContextMock::target_name
241   );
242   
243   
244   /* Check that init_sec_context's outputs are captured correctly */
245   CPPUNIT_ASSERT_EQUAL_MESSAGE(
246     "Return value was not copied back to the command.",
247     InitSecContextMock::retVal,
248     cmd.retVal
249   );
250   CPPUNIT_ASSERT_EQUAL_MESSAGE(
251     "Status was not copied back to the command.",
252     InitSecContextMock::minor_status,
253     cmd.minor_status
254   );
255   CPPUNIT_ASSERT_EQUAL_MESSAGE(
256     "context_handle was not copied back to the command.",
257     expectedResult,
258     cmd.context_handle
259   );
260   CPPUNIT_ASSERT_EQUAL_MESSAGE(
261     "context_handle was not copied back to the command.",
262     expectedArgument,
263     InitSecContextMock::context_handle
264   );
265   CPPUNIT_ASSERT_EQUAL_MESSAGE(
266     "actual_mech_type was not copied back to the command.",
267     InitSecContextMock::actual_mech_type,
268     cmd.getActualMechType().toGss()
269   );
270   CPPUNIT_ASSERT_EQUAL_MESSAGE(
271     "output_token was not copied back to the command.",
272     InitSecContextMock::output_token.value,
273     cmd.output_token.value
274   );
275   CPPUNIT_ASSERT_EQUAL_MESSAGE(
276     "ret_flags was not copied back to the command.",
277     InitSecContextMock::ret_flags,
278     cmd.ret_flags
279   );
280   CPPUNIT_ASSERT_EQUAL_MESSAGE(
281     "time_rec was not copied back to the command.",
282     InitSecContextMock::time_rec,
283     cmd.time_rec
284   );
285   
286   // Set this to no context, or cleanup attempts to free the not-a-real-pointer.
287   InitSecContextMock::context_handle = GSS_C_NO_CONTEXT;
288   
289 }
290
291 /* Expected JSON output:
292  * 
293  * {
294  *   "command": "gss_init_sec_context", 
295  *   "return_values": 
296  *   {
297  *     "context_handle": "base64_encoded_string", 
298  *     "major_status": ##, 
299  *     "output_token": "http@project-moonshot.org/PROJECT-MOONSHOT.ORG", 
300  *     "actual_mech_type": "{ 1 3 6 1 5 5 13 4 }", 
301  *     "minor_status": ##, 
302  *     ret_flags": ##, 
303  *     "time_rec": ##
304  *   }
305  * }
306  * 
307  */
308 void GSSCreateSecContextTest::testJSONMarshal()
309 {
310   /* Variables */
311   GSSInitSecContext cmd ((void *)&mock_init_sec);
312   JSONObject *result;
313   GSSContextCache *cache = GSSContextCache::instance();
314   GSSContext context;
315   gss_ctx_id_t expectedResult;
316   
317   /* Error checking */
318   
319   /* Setup */
320   // Set expectations on what the GSS function will produce
321   InitSecContextMock::retVal = GSS_S_CONTINUE_NEEDED;
322   InitSecContextMock::minor_status = 0;
323   InitSecContextMock::context_handle = expectedResult = (gss_ctx_id_t)(long)rand();
324   InitSecContextMock::actual_mech_type = (gss_OID)GSS_C_MA_MECH_NEGO;
325   InitSecContextMock::output_token.value = (void *)"http@project-moonshot.org/PROJECT-MOONSHOT.ORG\0";
326   InitSecContextMock::output_token.length = strlen((char *)InitSecContextMock::output_token.value);
327   InitSecContextMock::ret_flags = GSS_C_MUTUAL_FLAG | 
328       GSS_C_REPLAY_FLAG | 
329       GSS_C_SEQUENCE_FLAG | 
330       GSS_C_CONF_FLAG | 
331       GSS_C_INTEG_FLAG | 
332       GSS_C_ANON_FLAG | 
333       GSS_C_PROT_READY_FLAG;
334   InitSecContextMock::time_req = GSS_C_INDEFINITE;
335   
336   /* Main */
337   cmd.execute();
338   result = cmd.toJSON();
339 /*  
340   std::cout << "create sec context json: " << result->dump() << "\n";*/
341   
342   CPPUNIT_ASSERT_EQUAL_MESSAGE(
343     "The return value was reported incorrectly",
344     (int)InitSecContextMock::retVal,
345     (int)( (*result)["major_status"].integer() )
346   );
347   
348   CPPUNIT_ASSERT_EQUAL_MESSAGE(
349     "The minor_status value was reported incorrectly",
350     (int)InitSecContextMock::minor_status,
351     (int)( (*result)["minor_status"].integer() )
352   );
353   
354   CPPUNIT_ASSERT_MESSAGE(
355     "The actual_mech_type value was reported incorrectly",
356     ( strcmp("{ 1 3 6 1 5 5 13 4 }", 
357              (*result)["actual_mech_type"].string() ) == 0 )
358   );
359   
360   CPPUNIT_ASSERT_MESSAGE(
361     "The output_token value was reported incorrectly",
362     ( strcmp((const char *)(InitSecContextMock::output_token.value), 
363              (*result)["output_token"].string() ) == 0 )
364   );
365   
366   CPPUNIT_ASSERT_EQUAL_MESSAGE(
367     "The minor_status value was reported incorrectly",
368     (int)InitSecContextMock::ret_flags,
369     (int)( (*result)["ret_flags"].integer() )
370   );
371   
372   CPPUNIT_ASSERT_EQUAL_MESSAGE(
373     "The minor_status value was reported incorrectly",
374     (int)InitSecContextMock::time_rec,
375     (int)( (*result)["time_rec"].integer() )
376   );
377   
378   context = cache->retrieve( (*result)["context_handle"].string() );
379   
380   CPPUNIT_ASSERT_EQUAL_MESSAGE(
381     "The returned context was reported incorrectly",
382     (long)expectedResult,
383     (long)context.getContext()
384   );
385   
386   /* Cleanup */
387   /* Return */
388 }
389
390