A bunch of changes as the command line now works.
[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 "GSSCreateSecContextCommand.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
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   GSSCreateSecContextCommand cmd = GSSCreateSecContextCommand();
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 = "{\"method\": \"gss_create_sec_context\", \
143     \"arguments\": {\"req_flags\": \"1\", \
144     \"time_req\": \"2\", \
145     \"mech_type\": \"{ 1 2 840 113554 1 2 1 4 }\", \
146     \"target_name\": \"";
147   input = input + key + "\"}}";
148
149   json_error_t jsonErr;
150   const char *in = input.c_str();
151   JSONObject json = JSONObject::load(in, 0, &jsonErr);
152   
153   GSSCreateSecContextCommand cmd = GSSCreateSecContextCommand(
154     &json, 
155     (void *)&mock_init_sec
156   );
157
158   const char *from_cmd = cmd.getTargetDisplayName();
159   
160   CPPUNIT_ASSERT_MESSAGE(
161     "The object does not have a target name.",
162     ( strcmp(source_name, from_cmd) == 0 )
163   );
164   
165   CPPUNIT_ASSERT_EQUAL_MESSAGE(
166     "The context_handle values differ.",
167     json["arguments"]["context_handle"].integer(),
168     (json_int_t)cmd.getContextHandle()
169   );
170   
171   CPPUNIT_ASSERT_EQUAL_MESSAGE(
172     "The mech_type values differ.",
173     std::string(json["arguments"]["mech_type"].string()), 
174     cmd.getMechType().toString()
175   );
176   
177   CPPUNIT_ASSERT_EQUAL_MESSAGE(
178     "The req_flags differ.",
179     (int)json["arguments"]["req_flags"].integer(),
180     (int)cmd.getReqFlags()
181   );
182   
183   CPPUNIT_ASSERT_EQUAL_MESSAGE(
184     "The req_flags differ.",
185     (int)json["arguments"]["time_req"].integer(),
186     (int)cmd.getTimeReq()
187   );
188   
189 }
190
191 void
192 GSSCreateSecContextTest::testEmptyCall()
193 {
194   gss_ctx_id_t expectedResult, expectedArgument;
195   
196   GSSCreateSecContextCommand cmd ((void *)&mock_init_sec);
197   
198   /* Set expectations on what the GSS function will be called with */
199   cmd.time_req = rand() % 1024;
200   cmd.req_flags = rand() % 1024;
201   cmd.target_name = NULL;
202   cmd.context_handle = expectedArgument = (gss_ctx_id_t)(long)rand();
203   
204   
205   
206   /* Set expectations on what the GSS function will produce */
207   InitSecContextMock::retVal = rand() % 1024;
208   InitSecContextMock::minor_status = rand() % 1024;
209   InitSecContextMock::context_handle = expectedResult = (gss_ctx_id_t)(long)rand();
210   InitSecContextMock::actual_mech_type = NULL;
211   InitSecContextMock::output_token.value = (void *)"http@project-moonshot.org/PROJECT-MOONSHOT.ORG\0";
212   InitSecContextMock::output_token.length = strlen((char *)InitSecContextMock::output_token.value);
213   InitSecContextMock::ret_flags = rand() % 1024;
214   InitSecContextMock::time_req = rand() % 1024;
215   
216   cmd.execute();
217   
218   /* Check that init_sec_context's inputs are sent correctly */
219   CPPUNIT_ASSERT_MESSAGE(
220     "The GSS function was not invoked!",
221     InitSecContextMock::visited
222   );
223   CPPUNIT_ASSERT_EQUAL_MESSAGE(
224     "The time_req field was not used in the call to init_sec_context",
225     cmd.time_req,
226     InitSecContextMock::time_req
227   );
228   CPPUNIT_ASSERT_EQUAL_MESSAGE(
229     "The req_flags field was not used in the call to init_sec_context",
230     cmd.req_flags,
231     InitSecContextMock::req_flags
232   );
233   CPPUNIT_ASSERT_EQUAL_MESSAGE(
234     "The mech_type field was not used in the call to init_sec_context",
235     cmd.getMechType().toGss(),
236     InitSecContextMock::mech_type
237   );
238   CPPUNIT_ASSERT_EQUAL_MESSAGE(
239     "The target_name field was not used in the call to init_sec_context",
240     cmd.target_name,
241     InitSecContextMock::target_name
242   );
243   
244   
245   /* Check that init_sec_context's outputs are captured correctly */
246   CPPUNIT_ASSERT_EQUAL_MESSAGE(
247     "Return value was not copied back to the command.",
248     InitSecContextMock::retVal,
249     cmd.retVal
250   );
251   CPPUNIT_ASSERT_EQUAL_MESSAGE(
252     "Status was not copied back to the command.",
253     InitSecContextMock::minor_status,
254     cmd.minor_status
255   );
256   CPPUNIT_ASSERT_EQUAL_MESSAGE(
257     "context_handle was not copied back to the command.",
258     expectedResult,
259     cmd.context_handle
260   );
261   CPPUNIT_ASSERT_EQUAL_MESSAGE(
262     "context_handle was not copied back to the command.",
263     expectedArgument,
264     InitSecContextMock::context_handle
265   );
266   CPPUNIT_ASSERT_EQUAL_MESSAGE(
267     "actual_mech_type was not copied back to the command.",
268     InitSecContextMock::actual_mech_type,
269     cmd.getActualMechType().toGss()
270   );
271   CPPUNIT_ASSERT_EQUAL_MESSAGE(
272     "output_token was not copied back to the command.",
273     InitSecContextMock::output_token.value,
274     cmd.output_token.value
275   );
276   CPPUNIT_ASSERT_EQUAL_MESSAGE(
277     "ret_flags was not copied back to the command.",
278     InitSecContextMock::ret_flags,
279     cmd.ret_flags
280   );
281   CPPUNIT_ASSERT_EQUAL_MESSAGE(
282     "time_rec was not copied back to the command.",
283     InitSecContextMock::time_rec,
284     cmd.time_rec
285   );
286   
287   // Set this to no context, or cleanup attempts to free the not-a-real-pointer.
288   InitSecContextMock::context_handle = GSS_C_NO_CONTEXT;
289   
290 }
291
292 /* Expected JSON output:
293  * 
294  * {
295  *   "command": "gss_init_sec_context", 
296  *   "return_values": 
297  *   {
298  *     "context_handle": "base64_encoded_string", 
299  *     "major_status": ##, 
300  *     "output_token": "http@project-moonshot.org/PROJECT-MOONSHOT.ORG", 
301  *     "actual_mech_type": "{ 1 3 6 1 5 5 13 4 }", 
302  *     "minor_status": ##, 
303  *     ret_flags": ##, 
304  *     "time_rec": ##
305  *   }
306  * }
307  * 
308  */
309 void GSSCreateSecContextTest::testJSONMarshal()
310 {
311   /* Variables */
312   GSSCreateSecContextCommand cmd ((void *)&mock_init_sec);
313   JSONObject *result;
314   GSSContextCache *cache = GSSContextCache::instance();
315   GSSContext context;
316   gss_ctx_id_t expectedResult;
317   
318   /* Error checking */
319   
320   /* Setup */
321   // Set expectations on what the GSS function will produce
322   InitSecContextMock::retVal = GSS_S_CONTINUE_NEEDED;
323   InitSecContextMock::minor_status = 0;
324   InitSecContextMock::context_handle = expectedResult = (gss_ctx_id_t)(long)rand();
325   InitSecContextMock::actual_mech_type = (gss_OID)GSS_C_MA_MECH_NEGO;
326   InitSecContextMock::output_token.value = (void *)"http@project-moonshot.org/PROJECT-MOONSHOT.ORG\0";
327   InitSecContextMock::output_token.length = strlen((char *)InitSecContextMock::output_token.value);
328   InitSecContextMock::ret_flags = GSS_C_MUTUAL_FLAG | 
329       GSS_C_REPLAY_FLAG | 
330       GSS_C_SEQUENCE_FLAG | 
331       GSS_C_CONF_FLAG | 
332       GSS_C_INTEG_FLAG | 
333       GSS_C_ANON_FLAG | 
334       GSS_C_PROT_READY_FLAG;
335   InitSecContextMock::time_req = GSS_C_INDEFINITE;
336   
337   /* Main */
338   cmd.execute();
339   result = cmd.toJSON();
340 /*  
341   std::cout << "create sec context json: " << result->dump() << "\n";*/
342   
343   CPPUNIT_ASSERT_MESSAGE(
344     "The command name is incorrect",
345     ( strcmp("gss_init_sec_context", 
346              (*result)["command"].string() ) == 0 )
347   );
348   
349   
350   CPPUNIT_ASSERT_EQUAL_MESSAGE(
351     "The return value was reported incorrectly",
352     (int)InitSecContextMock::retVal,
353     (int)( (*result)["return_values"]["major_status"].integer() )
354   );
355   
356   CPPUNIT_ASSERT_EQUAL_MESSAGE(
357     "The minor_status value was reported incorrectly",
358     (int)InitSecContextMock::minor_status,
359     (int)( (*result)["return_values"]["minor_status"].integer() )
360   );
361   
362   CPPUNIT_ASSERT_MESSAGE(
363     "The actual_mech_type value was reported incorrectly",
364     ( strcmp("{ 1 3 6 1 5 5 13 4 }", 
365              (*result)["return_values"]["actual_mech_type"].string() ) == 0 )
366   );
367   
368   CPPUNIT_ASSERT_MESSAGE(
369     "The output_token value was reported incorrectly",
370     ( strcmp((const char *)(InitSecContextMock::output_token.value), 
371              (*result)["return_values"]["output_token"].string() ) == 0 )
372   );
373   
374   CPPUNIT_ASSERT_EQUAL_MESSAGE(
375     "The minor_status value was reported incorrectly",
376     (int)InitSecContextMock::ret_flags,
377     (int)( (*result)["return_values"]["ret_flags"].integer() )
378   );
379   
380   CPPUNIT_ASSERT_EQUAL_MESSAGE(
381     "The minor_status value was reported incorrectly",
382     (int)InitSecContextMock::time_rec,
383     (int)( (*result)["return_values"]["time_rec"].integer() )
384   );
385   
386   context = cache->retrieve( (*result)["return_values"]["context_handle"].string() );
387   
388   CPPUNIT_ASSERT_EQUAL_MESSAGE(
389     "The returned context was reported incorrectly",
390     (long)expectedResult,
391     (long)context.getContext()
392   );
393   
394   /* Cleanup */
395   /* Return */
396 }
397
398