Move util_ files into utils directory, move main.cpp into src
[gssweb.git] / json_gssapi / test / GSSCreateSecContextTest.cpp
index bfc0478..cf3be56 100644 (file)
@@ -7,17 +7,21 @@
 
 
 #include "GSSCreateSecContextTest.h"
-#include "GSSCreateSecContextCommand.h"
-#include "InitSecContextMock.h"
+#include "GSSInitSecContext.h"
+#include "command_mocks/InitSecContextMock.h"
 #include <iostream>
 #include <string.h>
 #include <exception>
-#include "util_json.h"
+#include "utils/util_json.h"
+#include <cache/GSSContextCache.h>
+#include <cache/GSSNameCache.h>
+#include <datamodel/GSSContext.h>
+#include <utils/util_base64.h>
 
 // Registers the fixture into the 'registry'
 CPPUNIT_TEST_SUITE_REGISTRATION( GSSCreateSecContextTest );
 
-
+using std::cout;
 
 static OM_uint32 KRB5_CALLCONV
 mock_init_sec(
@@ -35,6 +39,8 @@ mock_init_sec(
     OM_uint32             *ret_flags,
     OM_uint32             *time_rec)
 {
+  gss_ctx_id_t tmpContext;
+  
   InitSecContextMock::visited = true;
   
   /* Copy in the input to this function */
@@ -57,13 +63,9 @@ mock_init_sec(
   *time_rec = InitSecContextMock::time_rec;
   
   /* Handle the one that's I/O */
-    if (*context_handle == GSS_C_NO_CONTEXT)
-  {
-    *context_handle = InitSecContextMock::context_handle;
-  } else if (*context_handle != InitSecContextMock::context_handle)
-  {
-    InitSecContextMock::invalidContextHandle = true;
-  }
+  tmpContext = *context_handle;
+  *context_handle = InitSecContextMock::context_handle;
+  InitSecContextMock::context_handle = tmpContext;
 
   return InitSecContextMock::retVal;
 }
@@ -83,61 +85,104 @@ GSSCreateSecContextTest::tearDown()
 void
 GSSCreateSecContextTest::testConstructor()
 {
-  GSSCreateSecContextCommand cmd = GSSCreateSecContextCommand();
-  void *cmdFn;
-  void *GSSFn;
+  GSSInitSecContext cmd = GSSInitSecContext();
+  init_sec_context_type cmdFn;
+  init_sec_context_type GSSFn;
   
   cmdFn = cmd.getGSSFunction();
-  GSSFn = (void *)&gss_init_sec_context;
-  CPPUNIT_ASSERT_MESSAGE("The default constructor for GSSCreateSecContextCommand should assign the function gss_init_sec_context", cmdFn == GSSFn);
+  GSSFn = &gss_init_sec_context;
+  CPPUNIT_ASSERT_MESSAGE(
+    "The default constructor for GSSCreateSecContextCommand should assign the function gss_init_sec_context", 
+    cmdFn == GSSFn);
+  
+  // Check that we defaut to the moonshot OID
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The mech_type default value is unexpected.",
+    std::string("{ 1 3 6 1 5 5 15 1 1 18 }"),
+    cmd.getMechType().toString()
+  );
 }
 
-
+/* JSON Input:
+ * { 
+ *   "method": "gss_create_sec_context",
+ *   "arguments": 
+ *   {
+ *     "req_flags": "1",
+ *     "time_req": "2",
+ *     "mech_type": "{ 1 2 840 113554 1 2 1 4 }",
+ *     "target_name": "me@my.sha/DOW"
+ *   }
+ * }
+ */
 void GSSCreateSecContextTest::testConstructorWithJSONObject()
 {
-  const char* input = "{\"method\": \"gss_create_sec_context\", \
-    \"arguments\": {\"req_flags\": \"1\", \
+  OM_uint32 major, minor;
+  gss_name_t src;
+  GSSName source;
+  char *source_name = (char *)"HTTP@localhost\0";
+  
+  
+  major = gss_import_name(&minor, GSSBuffer(source_name).toGss(), GSS_C_NT_HOSTBASED_SERVICE, &src);
+  if (GSS_ERROR(major))
+  {
+    OM_uint32 min, context;
+    gss_buffer_desc buf;
+    
+    std::cout << "Error in importing name." << std::endl;
+    gss_display_status(&min, major, GSS_C_GSS_CODE, GSS_C_NT_HOSTBASED_SERVICE, &context, &buf);
+    std::cout << "  message: " << (char *)buf.value << std::endl;
+  }
+  CPPUNIT_ASSERT_MESSAGE(
+    "Could not generate a name to test GSSCreateSecContext JSON parsing.",
+    !GSS_ERROR(major)
+  );
+  source.setValue(src);
+  std::string key = GSSNameCache::instance()->store(source);
+
+  std::string input = "{\"req_flags\": \"1\", \
     \"time_req\": \"2\", \
     \"mech_type\": \"{ 1 2 840 113554 1 2 1 4 }\", \
-    \"target_name\": \"me@my.sha/DOW\"}}";
+    \"target_name\": \"";
+  input = input + key + "\"}";
 
   json_error_t jsonErr;
-  JSONObject json = JSONObject::load(input, 0, &jsonErr);
+  const char *in = input.c_str();
+  JSONObject json = JSONObject::load(in, 0, &jsonErr);
   
-  GSSCreateSecContextCommand cmd = GSSCreateSecContextCommand(
+  GSSInitSecContext cmd = GSSInitSecContext(
     &json, 
-    (void *)&mock_init_sec
+    &mock_init_sec
   );
-  
-  
-  const char *from_json = json["arguments"]["target_name"].string();
+
   const char *from_cmd = cmd.getTargetDisplayName();
   
   CPPUNIT_ASSERT_MESSAGE(
     "The object does not have a target name.",
-    ( strcmp(from_json, from_cmd) == 0 )
+    ( strcmp(source_name, from_cmd) == 0 )
   );
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The context_handle values differ.",
-    json["arguments"]["context_handle"].integer(),
+    json["context_handle"].integer(),
     (json_int_t)cmd.getContextHandle()
   );
   
-  CPPUNIT_ASSERT_MESSAGE(
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The mech_type values differ.",
-    ( strcmp(json["arguments"]["mech_type"].string(), cmd.getMechType()) == 0 )
+    std::string(json["mech_type"].string()), 
+    cmd.getMechType().toString()
   );
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The req_flags differ.",
-    (int)json["arguments"]["req_flags"].integer(),
+    (int)json["req_flags"].integer(),
     (int)cmd.getReqFlags()
   );
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The req_flags differ.",
-    (int)json["arguments"]["time_req"].integer(),
+    (int)json["time_req"].integer(),
     (int)cmd.getTimeReq()
   );
   
@@ -146,25 +191,22 @@ void GSSCreateSecContextTest::testConstructorWithJSONObject()
 void
 GSSCreateSecContextTest::testEmptyCall()
 {
-  GSSCreateSecContextCommand cmd ((void *)&mock_init_sec);
+  gss_ctx_id_t expectedResult, expectedArgument;
+  
+  GSSInitSecContext cmd (&mock_init_sec);
   
   /* Set expectations on what the GSS function will be called with */
   cmd.time_req = rand() % 1024;
   cmd.req_flags = rand() % 1024;
   cmd.target_name = NULL;
-  cmd.context_handle = GSS_C_NO_CONTEXT;
-  
-  CPPUNIT_ASSERT_MESSAGE(
-    "The mech_type values differ.",
-    ( strcmp("{ 1 2 840 113554 1 2 1 4 }", cmd.getMechType()) == 0 )
-  );
+  cmd.context_handle = expectedArgument = (gss_ctx_id_t)(long)rand();
   
   
   
   /* Set expectations on what the GSS function will produce */
   InitSecContextMock::retVal = rand() % 1024;
   InitSecContextMock::minor_status = rand() % 1024;
-  InitSecContextMock::context_handle = GSS_C_NO_CONTEXT;
+  InitSecContextMock::context_handle = expectedResult = (gss_ctx_id_t)(long)rand();
   InitSecContextMock::actual_mech_type = NULL;
   InitSecContextMock::output_token.value = (void *)"http@project-moonshot.org/PROJECT-MOONSHOT.ORG\0";
   InitSecContextMock::output_token.length = strlen((char *)InitSecContextMock::output_token.value);
@@ -190,7 +232,7 @@ GSSCreateSecContextTest::testEmptyCall()
   );
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The mech_type field was not used in the call to init_sec_context",
-    cmd.mech_type,
+    cmd.getMechType().toGss(),
     InitSecContextMock::mech_type
   );
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
@@ -213,13 +255,18 @@ GSSCreateSecContextTest::testEmptyCall()
   );
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "context_handle was not copied back to the command.",
-    InitSecContextMock::context_handle,
+    expectedResult,
     cmd.context_handle
   );
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "context_handle was not copied back to the command.",
+    expectedArgument,
+    InitSecContextMock::context_handle
+  );
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "actual_mech_type was not copied back to the command.",
     InitSecContextMock::actual_mech_type,
-    cmd.actual_mech_type
+    cmd.getActualMechType().toGss()
   );
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "output_token was not copied back to the command.",
@@ -236,21 +283,45 @@ GSSCreateSecContextTest::testEmptyCall()
     InitSecContextMock::time_rec,
     cmd.time_rec
   );
+  
+  // Set this to no context, or cleanup attempts to free the not-a-real-pointer.
+  InitSecContextMock::context_handle = GSS_C_NO_CONTEXT;
+  
 }
 
+/* Expected JSON output:
+ * 
+ * {
+ *   "command": "gss_init_sec_context", 
+ *   "return_values": 
+ *   {
+ *     "context_handle": "base64_encoded_string", 
+ *     "major_status": ##, 
+ *     "output_token": "http@project-moonshot.org/PROJECT-MOONSHOT.ORG", 
+ *     "actual_mech_type": "{ 1 3 6 1 5 5 13 4 }", 
+ *     "minor_status": ##, 
+ *     ret_flags": ##, 
+ *     "time_rec": ##
+ *   }
+ * }
+ * 
+ */
 void GSSCreateSecContextTest::testJSONMarshal()
 {
   /* Variables */
-  GSSCreateSecContextCommand cmd ((void *)&mock_init_sec);
+  GSSInitSecContext cmd (&mock_init_sec);
   JSONObject *result;
+  GSSContextCache *cache = GSSContextCache::instance();
+  GSSContext context;
+  gss_ctx_id_t expectedResult;
   
   /* Error checking */
   
   /* Setup */
   // Set expectations on what the GSS function will produce
-  InitSecContextMock::retVal = GSS_S_BAD_MECH;
-  InitSecContextMock::minor_status = 20;
-  InitSecContextMock::context_handle = GSS_C_NO_CONTEXT;
+  InitSecContextMock::retVal = GSS_S_CONTINUE_NEEDED;
+  InitSecContextMock::minor_status = 0;
+  InitSecContextMock::context_handle = expectedResult = (gss_ctx_id_t)(long)rand();
   InitSecContextMock::actual_mech_type = (gss_OID)GSS_C_MA_MECH_NEGO;
   InitSecContextMock::output_token.value = (void *)"http@project-moonshot.org/PROJECT-MOONSHOT.ORG\0";
   InitSecContextMock::output_token.length = strlen((char *)InitSecContextMock::output_token.value);
@@ -266,50 +337,62 @@ void GSSCreateSecContextTest::testJSONMarshal()
   /* Main */
   cmd.execute();
   result = cmd.toJSON();
-  
-  CPPUNIT_ASSERT_MESSAGE(
-    "The command name is incorrect",
-    ( strcmp("gss_init_sec_context", 
-            (*result)["command"].string() ) == 0 )
-  );
-  
+/*  
+  std::cout << "create sec context json: " << result->dump() << "\n";*/
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The return value was reported incorrectly",
     (int)InitSecContextMock::retVal,
-    (int)( (*result)["return_values"]["major_status"].integer() )
+    (int)( (*result)["major_status"].integer() )
   );
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The minor_status value was reported incorrectly",
     (int)InitSecContextMock::minor_status,
-    (int)( (*result)["return_values"]["minor_status"].integer() )
+    (int)( (*result)["minor_status"].integer() )
   );
   
   CPPUNIT_ASSERT_MESSAGE(
     "The actual_mech_type value was reported incorrectly",
     ( strcmp("{ 1 3 6 1 5 5 13 4 }", 
-            (*result)["return_values"]["actual_mech_type"].string() ) == 0 )
+            (*result)["actual_mech_type"].string() ) == 0 )
   );
+
   
+  
+  std::string str = (*result)["output_token"].string();
+  size_t len;
+  void *decoded = base64Decode(str.c_str(), &len);
+  CPPUNIT_ASSERT_MESSAGE(
+    "The decoded token size is incorrect",
+    ( len == InitSecContextMock::output_token.length )
+  );
   CPPUNIT_ASSERT_MESSAGE(
     "The output_token value was reported incorrectly",
-    ( strcmp((const char *)(InitSecContextMock::output_token.value), 
-            (*result)["return_values"]["output_token"].string() ) == 0 )
+    ( memcmp(InitSecContextMock::output_token.value,
+             decoded, len ) == 0 )
   );
+  base64Free(decoded);
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The minor_status value was reported incorrectly",
     (int)InitSecContextMock::ret_flags,
-    (int)( (*result)["return_values"]["ret_flags"].integer() )
+    (int)( (*result)["ret_flags"].integer() )
   );
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The minor_status value was reported incorrectly",
     (int)InitSecContextMock::time_rec,
-    (int)( (*result)["return_values"]["time_rec"].integer() )
+    (int)( (*result)["time_rec"].integer() )
   );
   
+  context = cache->retrieve( (*result)["context_handle"].string() );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The returned context was reported incorrectly",
+    (long)expectedResult,
+    (long)context.getContext()
+  );
   
   /* Cleanup */
   /* Return */