JSON Marshalling, updates from code review
authorMark Donnelly <mark@painless-security.com>
Tue, 22 Apr 2014 19:30:11 +0000 (15:30 -0400)
committerMark Donnelly <mark@painless-security.com>
Tue, 22 Apr 2014 19:30:11 +0000 (15:30 -0400)
* Implement JSON Marshalling in GSSCreateSecContext.
* Implement GSSException class
* Remove malloc()'d memory management in GSSCreateSecContext
* Change the expected JSON data structure as input to
  GSSCreateSecContext.

13 files changed:
json_gssapi/CMakeLists.txt
json_gssapi/src/GSSCommand.h
json_gssapi/src/GSSCreateSecContextCommand.cpp
json_gssapi/src/GSSCreateSecContextCommand.h
json_gssapi/src/GSSException.cpp [new file with mode: 0644]
json_gssapi/src/GSSException.h [new file with mode: 0644]
json_gssapi/test/CMakeLists.txt
json_gssapi/test/GSSCreateSecContextTest.cpp
json_gssapi/test/GSSCreateSecContextTest.h
json_gssapi/test/GSSExceptionTest.cpp [new file with mode: 0644]
json_gssapi/test/GSSExceptionTest.h [new file with mode: 0644]
json_gssapi/test/InitSecContextMock.cpp
json_gssapi/test/InitSecContextMock.h

index cb2d217..059a6b6 100644 (file)
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8)
 
 project(json_gssapi)
 
-add_executable(json_gssapi src/GSSCreateSecContextCommand.cpp src/GSSCommand.cpp src/util_json.cpp main.cpp)
+add_executable(json_gssapi src/GSSException.cpp src/GSSCreateSecContextCommand.cpp src/GSSCommand.cpp src/util_json.cpp main.cpp)
 target_link_libraries(json_gssapi gssapi_krb5 jansson)
 
 
index 20955af..261b3aa 100644 (file)
@@ -16,13 +16,14 @@ class GSSCommand
 public:
   GSSCommand() {};
   GSSCommand(void *fn) : function(fn) {};
-  GSSCommand(JSONObject params, void *fn) : parameters(params), function(fn) { };
+  GSSCommand(JSONObject params, void *fn) : function(fn) { };
   
   void *getGSSFunction() { return function; };
   virtual void execute() { std::cout << "\ninside GSSCommand::invoke()\n"; };  
+  virtual JSONObject *toJSON() { return new JSONObject(); }
+  
 protected:
   void *function;
-  JSONObject parameters;
 };
 
 #endif // GSSCOMMAND_H
index 94719d1..7e35b45 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "GSSCreateSecContextCommand.h"
+#include "GSSException.h"
 #include <gssapi.h>
 #include <stdlib.h>
 #include <string.h>
@@ -27,10 +28,10 @@ typedef OM_uint32 (*init_sec_context)(
 );
 
 /* Helper function - import the OID from a string */
-gss_OID str_to_oid(const char *mech_type_str = NULL)
+static gss_OID str_to_oid(const char *mech_type_str = NULL)
 {
   /* Variables */
-  gss_buffer_t gssbuffOID;
+  gss_buffer_desc gssbuffOID;
   gss_OID gssoidTargetOID;
   OM_uint32 major;
   OM_uint32 minor;
@@ -41,19 +42,16 @@ gss_OID str_to_oid(const char *mech_type_str = NULL)
     return NULL;
   
   /* Setup */
-  gssbuffOID = (gss_buffer_t)malloc(sizeof(gss_buffer_desc_struct));
-
   /* Main */
-  gssbuffOID->value = (void *)(mech_type_str);
-  gssbuffOID->length = strlen(mech_type_str);
+  gssbuffOID.value = (void *)(mech_type_str);
+  gssbuffOID.length = strlen(mech_type_str);
   major = gss_str_to_oid(&minor, 
-                        gssbuffOID, 
+                        &gssbuffOID, 
                         &gssoidTargetOID);
   if (major != GSS_S_COMPLETE)
-    throw "Error converting string to OID: " + minor;
+    throw GSSException("Error converting string to OID", major, minor);
 
   /* Cleanup */
-  free(gssbuffOID);
   
   /* Return */
   return gssoidTargetOID;
@@ -62,10 +60,16 @@ gss_OID str_to_oid(const char *mech_type_str = NULL)
 void
 GSSCreateSecContextCommand::execute()
 {
+  /* Variables */
   init_sec_context fn = (init_sec_context)function;
   
-  input_token = GSS_C_NO_BUFFER;
-  output_token = (gss_buffer_t)malloc(sizeof(gss_buffer_desc));
+  /* Error checking */
+  
+  /* Setup */
+  if (output_token.length > 0)
+    retVal = gss_release_buffer(&minor_status, &output_token);
+  
+  /* Main */
   
   retVal = fn(
     &minor_status,
@@ -76,17 +80,21 @@ GSSCreateSecContextCommand::execute()
     req_flags,
     time_req,
     GSS_C_NO_CHANNEL_BINDINGS,
-    input_token,
+    &input_token,
     &actual_mech_type,
-    output_token,
+    &output_token,
     &ret_flags,
     &time_rec);
+  
+  /* Cleanup */
+  
+  /* Return */
 }
 
 const char* GSSCreateSecContextCommand::getTargetDisplayName()
 {
   /* Variables */
-  gss_buffer_t output_name;
+  gss_buffer_desc output_name;
   gss_OID output_type;
   OM_uint32 major, minor;
   const char *ret;
@@ -94,46 +102,50 @@ const char* GSSCreateSecContextCommand::getTargetDisplayName()
   /* error checking */
   
   /* Setup */
-  output_name = (gss_buffer_t)malloc(sizeof(gss_buffer_desc_struct));
-  output_type = (gss_OID)malloc(sizeof(gss_OID_desc_struct));
   
   /* Main */
-  major = gss_display_name(&minor, target_name, output_name, &output_type);
+  major = gss_display_name(&minor, target_name, &output_name, &output_type);
   if (major == GSS_S_COMPLETE)
-    ret = (const char *)output_name->value;
+    ret = (const char *)output_name.value;
   else
     ret = NULL;
   
   /* cleanup */
-  free(output_name);
-  free(output_type);
   
   /* return */
-  return( (char *)(output_name->value) );
+  return( ret );
+}
+
+const char* GSSCreateSecContextCommand::getActualMechType()
+{
+  return(this->oidToStr(this->actual_mech_type));
 }
 
 const char* GSSCreateSecContextCommand::getMechType()
 {
-  gss_buffer_t output;
+  return(this->oidToStr(this->mech_type));
+}
+
+const char* GSSCreateSecContextCommand::oidToStr(gss_OID oid)
+{
+  gss_buffer_desc output;
   OM_uint32 major, minor;
   const char *retVal;
 
   /* error checking */
-  if (mech_type == NULL)
+  if (oid == NULL)
     return NULL;
 
   /* Setup */  
-  output = (gss_buffer_t)malloc(sizeof(gss_buffer_desc_struct));
   
   /* main */
-  major = gss_oid_to_str(&minor, mech_type, output);
+  major = gss_oid_to_str(&minor, oid, &output);
   if (major == GSS_S_COMPLETE)
-    retVal = (const char *)output->value;
+    retVal = (const char *)output.value;
   else
     retVal = NULL;
   
   /* cleanup */
-  free(output);
   
   /* return */
   return( retVal );
@@ -143,51 +155,47 @@ bool GSSCreateSecContextCommand::loadParameters(JSONObject *params)
 {
   /* Variables */
   OM_uint32 major, minor;
-  gss_buffer_t gssbuffTargetName;
+  gss_buffer_desc gssbuffTargetName;
   const char *buffer;
   
   /* Error checking */
-  // Should I zeroOut?
   
   /* Setup */
+  // Should I zeroOut?
   
   /* Main processing */
-  // Easy stuff
-  this->time_req = (OM_uint32)( (*params)["time_req"].integer() );
-  this->req_flags = (OM_uint32)( (*params)["req_flags"].integer() );
+  // Easy stuff(*params)
+  this->time_req = (OM_uint32)( (*params)["arguments"]["time_req"].integer() );
+  this->req_flags = (OM_uint32)( (*params)["arguments"]["req_flags"].integer() );
   
   // context_handle
   //   -- just treat the value passed in as correct.
-  context_handle = (gss_ctx_id_t)( (*params)["context_handle"].integer() );
+  context_handle = (gss_ctx_id_t)( (*params)["arguments"]["context_handle"].integer() );
   
   // target_name
-  buffer = (*params)["target_name"].string();
+  buffer = (*params)["arguments"]["target_name"].string();
   if (buffer != NULL && *buffer != 0)
   {
-    gssbuffTargetName = (gss_buffer_t)malloc(sizeof(gss_buffer_desc_struct));
-    gssbuffTargetName->value = (void *)buffer;
-    gssbuffTargetName->length = strlen( buffer );
+    gssbuffTargetName.value = (void *)buffer;
+    gssbuffTargetName.length = strlen( buffer );
     
     major = gss_import_name(&minor, 
-                           gssbuffTargetName, 
+                           &gssbuffTargetName, 
                            GSS_C_NO_OID, 
                            &target_name);
     if (major != GSS_S_COMPLETE)
-      throw "Error importing target_name: " + minor;
-    
-    free(gssbuffTargetName);
+      throw GSSException("Error importing target_name", major, minor);
   }
   
   // mech_type  
-  mech_type = str_to_oid( (*params)["mech_type"].string() );
+  mech_type = str_to_oid( (*params)["arguments"]["mech_type"].string() );
   
   // input_token
-  buffer = (*params)["input_token"].string();
+  buffer = (*params)["arguments"]["input_token"].string();
   if (buffer != NULL && *buffer != 0)
   {
-    this->input_token = (gss_buffer_t)malloc(sizeof(gss_buffer_desc_struct));
-    this->input_token->value = (void *)buffer;
-    this->input_token->length = strlen(buffer);
+    this->input_token.value = (void *)buffer;
+    this->input_token.length = strlen(buffer);
   }
   
   /* Cleanup */
@@ -202,18 +210,16 @@ bool GSSCreateSecContextCommand::zeroOut(bool initialized)
   /* Error checking */
   /* Variables */
   OM_uint32 minor;
-  gss_buffer_t output;
+  gss_buffer_desc output;
   
   /* Setup */
-  output = (gss_buffer_t)malloc(sizeof(gss_buffer_desc_struct));
-  
   /* Main */
 
   // Free up existing memory if it's been set.  
   if (initialized)
   {
     if (this->context_handle != NULL)
-      gss_delete_sec_context(&minor, &(this->context_handle), output);
+      gss_delete_sec_context(&minor, &(this->context_handle), &output);
     
     if (this->target_name != NULL)
       gss_release_name(&minor, &(this->target_name));
@@ -221,20 +227,14 @@ bool GSSCreateSecContextCommand::zeroOut(bool initialized)
     if (mech_type != NULL)
       gss_release_oid(&minor, &(this->mech_type));
     
-    if (this->input_token != NULL)
-    {
-      gss_release_buffer(&minor, this->input_token);
-      free(this->input_token);
-    }
-
     if (this->actual_mech_type != NULL)
       gss_release_oid(&minor, &(this->actual_mech_type));
-  
-    if (this->output_token != NULL)
-    {
-      gss_release_buffer(&minor, this->output_token);
-      free( this->output_token );
-    }
+    
+    if (this->output_token.length > 0)
+      gss_release_buffer(&minor, &output_token);
+    
+    if (this->input_token.length > 0)
+      gss_release_buffer(&minor, &input_token);
   }
 
   // Now set things to reasonable defaults
@@ -248,18 +248,44 @@ bool GSSCreateSecContextCommand::zeroOut(bool initialized)
   this->context_handle = GSS_C_NO_CONTEXT;
   this->target_name = GSS_C_NO_NAME;
   mech_type = str_to_oid( "{ 1 2 840 113554 1 2 1 4 }" );
-  this->input_token = GSS_C_NO_BUFFER;
+  this->input_token.length = 0;
+  this->input_token.value = NULL;
   this->actual_mech_type = GSS_C_NO_OID;
-  this->output_token = GSS_C_NO_BUFFER;
-  memset((void *)&(this->parameters), 0, sizeof(JSONObject));
+  this->output_token.length = 0;
+  this->output_token.value = NULL;
 
   /* Cleanup */
-  free(output);
-  
   /* Return */
   return(true);
 }
 
+JSONObject *GSSCreateSecContextCommand::toJSON()
+{
+  /* Variables */
+  JSONObject *ret = new JSONObject();
+  JSONObject *values = new JSONObject();
+  
+  /* Error checking */
+  
+  /* Setup */
+  
+  /* Main */
+  values->set("major_status", this->retVal);
+  values->set("minor_status", this->minor_status);
+  values->set("context_handle", (json_int_t)0);
+  values->set("actual_mech_type", this->getActualMechType());
+  values->set("output_token", (const char *)this->output_token.value);
+  values->set("ret_flags", this->ret_flags);
+  values->set("time_rec", this->time_rec);
+  ret->set("command", "gss_init_sec_context");
+  ret->set("return_values", *values);
+  
+  /* Cleanup */
+  
+  /* Return */
+  return(ret);
+}
+
 GSSCreateSecContextCommand::GSSCreateSecContextCommand(
   JSONObject *params, 
   void *fn) : GSSCommand(params, fn)
@@ -271,4 +297,5 @@ GSSCreateSecContextCommand::GSSCreateSecContextCommand(
 GSSCreateSecContextCommand::GSSCreateSecContextCommand(void *fn) : GSSCommand(fn)
 {
   zeroOut(false);
-}
\ No newline at end of file
+}
+
index 4eb1bdf..915084d 100644 (file)
@@ -22,14 +22,15 @@ public:
     gss_OID mech_type;
     OM_uint32 req_flags;
     OM_uint32 time_req;
-    gss_buffer_t input_token;
+    gss_buffer_desc input_token;
     gss_OID actual_mech_type;
-    gss_buffer_t output_token;
+    gss_buffer_desc output_token;
     OM_uint32 ret_flags;
     OM_uint32 time_rec;
     
   
     void execute();
+    JSONObject *toJSON();
     GSSCreateSecContextCommand(void *fn = (void *)&gss_init_sec_context);
     GSSCreateSecContextCommand(JSONObject *params, void *fn = (void *)&gss_init_sec_context);
     
@@ -45,8 +46,10 @@ public:
     // complex accessors
     const char * getTargetDisplayName();
     const char * getMechType();
+    const char * getActualMechType();
     
 private:
+    const char * oidToStr(gss_OID oid);
 };
 
 #endif // GSSCREATESECCONTEXTCOMMAND_H
diff --git a/json_gssapi/src/GSSException.cpp b/json_gssapi/src/GSSException.cpp
new file mode 100644 (file)
index 0000000..61294e0
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+#include "GSSException.h"
+#include <sstream>
+#include <ios>
+#include <iostream>
+
+static void disp_status(OM_uint32 status, int status_type, gss_OID mech, std::ostream &output_stream)
+{
+  OM_uint32 disp_major, disp_minor, disp_context;
+  gss_buffer_desc disp_buf;
+
+  disp_context = 0;
+  do
+  {
+    disp_major = gss_display_status(&disp_minor, 
+                                   status, 
+                                   status_type,
+                                   mech, 
+                                   &disp_context, 
+                                   &disp_buf);
+    if (GSS_ERROR(disp_major))
+    {
+      disp_context = 0; // Get out of this loop.
+      output_stream << "    An error occurred, and then another error" << std::endl <<
+         "    occurred in creating a message to describe the first one. " << std::endl <<
+         "    How embarrassing. It's time to quit before it gets any worse." <<  std::endl <<
+         "    For now, the error code itself was 0x" << std::hex << status << std::dec;
+      std::cout << "\n     -------------------------\n    Something wonky happened in displaying status:\n";
+      std::cout << "     gss_display_status(&disp_minor, " << status << ", " << (int)status_type << ", " << (long int)mech << ", " << disp_context << ", &buf);\n";
+      disp_status(disp_major, GSS_C_GSS_CODE, mech, std::cout);
+      disp_status(disp_minor, GSS_C_MECH_CODE, mech, std::cout);
+    } else
+      output_stream << "    " << (char *)disp_buf.value << std::endl;
+  } while (disp_context != 0);
+}
+
+GSSException::GSSException(std::string message, 
+                          OM_uint32 major, 
+                          OM_uint32 minor, 
+                          gss_OID mech)
+{
+  /* Error checking */
+  
+  /* Variables */
+  std::stringstream output_stream;
+  /* Setup */
+  
+  /* Main */
+  output_stream << message << std::endl;
+  output_stream << "GSS Error message:" << std::endl;
+  output_stream << "  Major status:" << std::endl;
+  disp_status(major, GSS_C_GSS_CODE, mech, output_stream);
+  output_stream << std::endl;
+  output_stream << "  Minor status details: " << std::endl;
+  disp_status(minor, GSS_C_MECH_CODE, mech, output_stream);
+  reason = output_stream.str();
+  
+  
+  /* Cleanup */
+  /* Return */
+}
diff --git a/json_gssapi/src/GSSException.h b/json_gssapi/src/GSSException.h
new file mode 100644 (file)
index 0000000..551d875
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+#ifndef GSSEXCEPTION_H
+#define GSSEXCEPTION_H
+
+#include <exception>
+#include <string>
+
+#include <gssapi.h>
+
+class GSSException : public std::exception
+{
+public:
+    GSSException(std::string msg, OM_uint32 major = 0, OM_uint32 minor = 0 , gss_OID mech = GSS_C_NO_OID);
+    ~GSSException(void) throw() {  }
+      
+    virtual const char* what(void) const throw() { return reason.c_str(); }
+    
+    
+private:
+    std::string reason;
+};
+
+#endif // GSSEXCEPTION_H
index f43e6e5..8717060 100644 (file)
@@ -1,6 +1,9 @@
 include_directories(${CMAKE_SOURCE_DIR}/src)
 
-add_executable(test InitSecContextMock.cpp GSSCreateSecContextTest.cpp test_run.cpp JSONParseTest.cpp ../src/GSSCreateSecContextCommand.cpp ../src/util_json.cpp)
+add_executable(test GSSExceptionTest.cpp InitSecContextMock.cpp 
+                    GSSCreateSecContextTest.cpp test_run.cpp 
+                    ../src/GSSCreateSecContextCommand.cpp 
+                    ../src/util_json.cpp ../src/GSSException.cpp)
 
 target_link_libraries(test cppunit gssapi_krb5 jansson)
 
index 0cf7ad5..bfc0478 100644 (file)
@@ -19,7 +19,7 @@ CPPUNIT_TEST_SUITE_REGISTRATION( GSSCreateSecContextTest );
 
 
 
-OM_uint32 KRB5_CALLCONV
+static OM_uint32 KRB5_CALLCONV
 mock_init_sec(
     OM_uint32             *minor_status,
     gss_cred_id_t          claimant_cred_handle,
@@ -44,13 +44,15 @@ mock_init_sec(
   InitSecContextMock::req_flags = req_flags;
   InitSecContextMock::time_req = time_req;
   InitSecContextMock::input_chan_bindings = input_chan_bindings;
-  InitSecContextMock::input_token = input_token;
+  InitSecContextMock::input_token.length = input_token->length;
+  InitSecContextMock::input_token.value = input_token->value;
+  
   
   /* Copy out the output from this function */
   *minor_status = InitSecContextMock::minor_status;
   *actual_mech_type = InitSecContextMock::actual_mech_type;
-  output_token->length = InitSecContextMock::output_token->length;
-  output_token->value = InitSecContextMock::output_token->value;
+  output_token->length = InitSecContextMock::output_token.length;
+  output_token->value = InitSecContextMock::output_token.value;
   *ret_flags = InitSecContextMock::ret_flags;
   *time_rec = InitSecContextMock::time_rec;
   
@@ -93,10 +95,11 @@ GSSCreateSecContextTest::testConstructor()
 
 void GSSCreateSecContextTest::testConstructorWithJSONObject()
 {
-  const char* input = "{\"req_flags\": \"1\", \
+  const char* 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\"}";
+    \"target_name\": \"me@my.sha/DOW\"}}";
 
   json_error_t jsonErr;
   JSONObject json = JSONObject::load(input, 0, &jsonErr);
@@ -107,7 +110,7 @@ void GSSCreateSecContextTest::testConstructorWithJSONObject()
   );
   
   
-  const char *from_json = json["target_name"].string();
+  const char *from_json = json["arguments"]["target_name"].string();
   const char *from_cmd = cmd.getTargetDisplayName();
   
   CPPUNIT_ASSERT_MESSAGE(
@@ -117,28 +120,27 @@ void GSSCreateSecContextTest::testConstructorWithJSONObject()
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The context_handle values differ.",
-    json["context_handle"].integer(),
+    json["arguments"]["context_handle"].integer(),
     (json_int_t)cmd.getContextHandle()
   );
   
   CPPUNIT_ASSERT_MESSAGE(
     "The mech_type values differ.",
-    ( strcmp(json["mech_type"].string(), cmd.getMechType()) == 0 )
+    ( strcmp(json["arguments"]["mech_type"].string(), cmd.getMechType()) == 0 )
   );
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The req_flags differ.",
-    (int)json["req_flags"].integer(),
+    (int)json["arguments"]["req_flags"].integer(),
     (int)cmd.getReqFlags()
   );
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The req_flags differ.",
-    (int)json["time_req"].integer(),
+    (int)json["arguments"]["time_req"].integer(),
     (int)cmd.getTimeReq()
   );
   
-  
 }
 
 void
@@ -164,9 +166,8 @@ GSSCreateSecContextTest::testEmptyCall()
   InitSecContextMock::minor_status = rand() % 1024;
   InitSecContextMock::context_handle = GSS_C_NO_CONTEXT;
   InitSecContextMock::actual_mech_type = NULL;
-  InitSecContextMock::output_token = (gss_buffer_t)malloc(sizeof(gss_buffer_desc));
-  InitSecContextMock::output_token->value = (void *)"http@project-moonshot.org/PROJECT-MOONSHOT.ORG\0";
-  InitSecContextMock::output_token->length = strlen((char *)InitSecContextMock::output_token->value);
+  InitSecContextMock::output_token.value = (void *)"http@project-moonshot.org/PROJECT-MOONSHOT.ORG\0";
+  InitSecContextMock::output_token.length = strlen((char *)InitSecContextMock::output_token.value);
   InitSecContextMock::ret_flags = rand() % 1024;
   InitSecContextMock::time_req = rand() % 1024;
   
@@ -222,8 +223,8 @@ GSSCreateSecContextTest::testEmptyCall()
   );
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "output_token was not copied back to the command.",
-    InitSecContextMock::output_token->value,
-    cmd.output_token->value
+    InitSecContextMock::output_token.value,
+    cmd.output_token.value
   );
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "ret_flags was not copied back to the command.",
@@ -237,3 +238,81 @@ GSSCreateSecContextTest::testEmptyCall()
   );
 }
 
+void GSSCreateSecContextTest::testJSONMarshal()
+{
+  /* Variables */
+  GSSCreateSecContextCommand cmd ((void *)&mock_init_sec);
+  JSONObject *result;
+  
+  /* 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::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);
+  InitSecContextMock::ret_flags = GSS_C_MUTUAL_FLAG | 
+      GSS_C_REPLAY_FLAG | 
+      GSS_C_SEQUENCE_FLAG | 
+      GSS_C_CONF_FLAG | 
+      GSS_C_INTEG_FLAG | 
+      GSS_C_ANON_FLAG | 
+      GSS_C_PROT_READY_FLAG;
+  InitSecContextMock::time_req = GSS_C_INDEFINITE;
+  
+  /* Main */
+  cmd.execute();
+  result = cmd.toJSON();
+  
+  CPPUNIT_ASSERT_MESSAGE(
+    "The command name is incorrect",
+    ( strcmp("gss_init_sec_context", 
+            (*result)["command"].string() ) == 0 )
+  );
+  
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The return value was reported incorrectly",
+    (int)InitSecContextMock::retVal,
+    (int)( (*result)["return_values"]["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() )
+  );
+  
+  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 )
+  );
+  
+  CPPUNIT_ASSERT_MESSAGE(
+    "The output_token value was reported incorrectly",
+    ( strcmp((const char *)(InitSecContextMock::output_token.value), 
+            (*result)["return_values"]["output_token"].string() ) == 0 )
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The minor_status value was reported incorrectly",
+    (int)InitSecContextMock::ret_flags,
+    (int)( (*result)["return_values"]["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() )
+  );
+  
+  
+  /* Cleanup */
+  /* Return */
+}
+
+
index e2cb910..52d7f46 100644 (file)
@@ -22,6 +22,7 @@ class GSSCreateSecContextTest :  public CppUnit::TestFixture
   CPPUNIT_TEST( testConstructor );
   CPPUNIT_TEST( testConstructorWithJSONObject );
   CPPUNIT_TEST( testEmptyCall );
+  CPPUNIT_TEST( testJSONMarshal );
   CPPUNIT_TEST_SUITE_END();
   
   
@@ -34,6 +35,7 @@ public:
   void testConstructor();
   void testConstructorWithJSONObject();
   void testEmptyCall();
+  void testJSONMarshal();
   
 private:
   GSSCreateSecContextCommand command;
diff --git a/json_gssapi/test/GSSExceptionTest.cpp b/json_gssapi/test/GSSExceptionTest.cpp
new file mode 100644 (file)
index 0000000..c2fbb05
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+#include "GSSExceptionTest.h"
+#include "GSSException.h"
+#include <string>
+#include <iostream>
+
+
+// Registers the fixture into the 'registry'
+CPPUNIT_TEST_SUITE_REGISTRATION( GSSExceptionTest );
+
+void GSSExceptionTest::setUp()
+{
+  CppUnit::TestFixture::setUp();
+}
+
+void GSSExceptionTest::tearDown()
+{
+  CppUnit::TestFixture::tearDown();
+}
+
+
+void GSSExceptionTest::testWithMessage()
+{
+  try {
+    throw GSSException("Test message");
+  } catch (GSSException e)
+  {
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "GSSException message reporting is incorrect.",
+      std::string("Test message\n\
+GSS Error message:\n\
+  Major status:\n\
+    The routine completed successfully\n\
+\n\
+  Minor status details: \n\
+    Unknown error\n"), 
+      std::string(e.what())
+    );
+  }
+}
+
+void GSSExceptionTest::testWithMessageAndMajor()
+{
+  try {
+    throw GSSException("Test message", 524288);
+  } catch (GSSException e)
+  {
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "GSSException message reporting is incorrect.",
+      std::string("Test message\n\
+GSS Error message:\n\
+  Major status:\n\
+    No context has been established\n\
+\n\
+  Minor status details: \n\
+    Unknown error\n"), 
+      std::string(e.what())
+    );
+  }
+}
+
+void GSSExceptionTest::testWithMessageAndMajorAndMinor()
+{
+  OM_uint32 major, minor, context = 0;
+  gss_buffer_desc_struct buf;
+  
+  try {
+    major = gss_display_status(&minor, 2109382930, GSS_C_MECH_CODE, GSS_C_NO_OID, &context, &buf);
+    throw GSSException("Test message", major, minor);
+  } catch (GSSException e)
+  {
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "GSSException message reporting is incorrect.",
+      std::string("Test message\n\
+GSS Error message:\n\
+  Major status:\n\
+    An invalid status code was supplied\n\
+\n\
+  Minor status details: \n\
+    Invalid argument\n"), 
+      std::string(e.what())
+    );
+  }
+}
+
+void GSSExceptionTest::testWithMessageAndMajorAndMinorAndMechanism()
+{
+
+  OM_uint32 major, minor, context = 0;
+  gss_buffer_desc_struct buf;
+  
+  try {
+    major = gss_display_status(&minor, 2109382930, GSS_C_MECH_CODE, GSS_C_NO_OID, &context, &buf);
+    throw GSSException("Test message", major, minor, GSS_C_NO_OID);
+  } catch (GSSException e)
+  {
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(
+      "GSSException message reporting is incorrect.",
+      std::string("Test message\n\
+GSS Error message:\n\
+  Major status:\n\
+    An invalid status code was supplied\n\
+\n\
+  Minor status details: \n\
+    Invalid argument\n"), 
+      std::string(e.what())
+    );
+  }
+  
+}
diff --git a/json_gssapi/test/GSSExceptionTest.h b/json_gssapi/test/GSSExceptionTest.h
new file mode 100644 (file)
index 0000000..cb1ff52
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+#ifndef GSSEXCEPTIONTEST_H
+#define GSSEXCEPTIONTEST_H
+
+// #include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "GSSException.h"
+
+
+class GSSExceptionTest :  public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( GSSExceptionTest );
+  CPPUNIT_TEST( testWithMessage );
+  CPPUNIT_TEST( testWithMessageAndMajor );
+  CPPUNIT_TEST( testWithMessageAndMajorAndMinor );
+  CPPUNIT_TEST( testWithMessageAndMajorAndMinorAndMechanism );
+  CPPUNIT_TEST_SUITE_END();
+  
+  
+  
+public:
+  void setUp();
+  void tearDown();
+
+  
+  void testWithMessage();
+  void testWithMessageAndMajor();
+  void testWithMessageAndMajorAndMinor();
+  void testWithMessageAndMajorAndMinorAndMechanism();
+  
+};
+
+
+#endif // GSSEXCEPTIONTEST_H
index b18df38..472ebaf 100644 (file)
@@ -23,9 +23,9 @@ gss_ctx_id_t  InitSecContextMock::context_handle = NULL;
 gss_name_t    InitSecContextMock::target_name = NULL;
 gss_OID       InitSecContextMock::mech_type = NULL;
 gss_channel_bindings_t InitSecContextMock::input_chan_bindings = NULL;
-gss_buffer_t  InitSecContextMock::input_token = NULL;
+gss_buffer_desc  InitSecContextMock::input_token;
 gss_OID       InitSecContextMock::actual_mech_type = NULL;
-gss_buffer_t  InitSecContextMock::output_token = NULL;
+gss_buffer_desc  InitSecContextMock::output_token;
 
 void InitSecContextMock::reset()
 {
@@ -38,9 +38,11 @@ void InitSecContextMock::reset()
   req_flags = 0;
   time_req = 0;
   nullify((void **)&input_chan_bindings);
-  nullify((void **)&input_token);
+  input_token.length = 0;
+  input_token.value = NULL;
   nullify((void **)&actual_mech_type);
-  nullify((void **)&output_token);
+  output_token.length = 0;
+  output_token.value = 0;
   ret_flags = 0;
   time_rec = 0;
   visited = false;
index 171bb41..f26a2c5 100644 (file)
@@ -24,9 +24,9 @@ public:
   static OM_uint32              req_flags;
   static OM_uint32              time_req;
   static gss_channel_bindings_t input_chan_bindings;
-  static gss_buffer_t           input_token;
+  static gss_buffer_desc        input_token;
   static gss_OID                actual_mech_type;
-  static gss_buffer_t           output_token;
+  static gss_buffer_desc        output_token;
   static OM_uint32              ret_flags;
   static OM_uint32              time_rec;