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