A bunch of changes as the command line now works.
authorMark Donnelly <mark@painless-security.com>
Fri, 12 Sep 2014 15:42:14 +0000 (11:42 -0400)
committerMark Donnelly <mark@painless-security.com>
Fri, 12 Sep 2014 15:42:14 +0000 (11:42 -0400)
* Move the main processing into a shared library
* Add processing in main() to read input, call the library commands,
  and output
* Correct copy-and-paste error in GSSNameCache that precluded it from
  being used along with GSSContextCache
* GSSAcquireCred now honors the desired_name parameter
* GSSCommand now an abstract class, with pure virtual methods
* GSSCreateSecContextCommand::execute() now uses datamodel objects
  instead of raw GSS types
* GSSCreateSecContextCommand now accepts cached names and contexts
  instead of raw GSS types
* GSSName operator= now duplicates GSS name instead of copying the
  data out of the other GSSName object, thus rendering their
  destruction independent
* GSSCreateSecContext now defaults to using the Moonshot mechanism
* Add a description of the JSON protocol for json_gssapi
* Clean up some of the compiler warnings about casting the result
  of rand() into a pointer

12 files changed:
json_gssapi/CMakeLists.txt
json_gssapi/json_protocol.txt [new file with mode: 0644]
json_gssapi/main.cpp
json_gssapi/src/cache/GSSNameCache.h
json_gssapi/src/commands/GSSAcquireCred.cpp
json_gssapi/src/commands/GSSAcquireCred.h
json_gssapi/src/commands/GSSCommand.h
json_gssapi/src/commands/GSSCreateSecContextCommand.cpp
json_gssapi/src/commands/GSSCreateSecContextCommand.h
json_gssapi/src/datamodel/GSSName.cpp
json_gssapi/test/GSSCreateSecContextTest.cpp
json_gssapi/test/NameCacheTest.cpp

index 9d791b2..4c8c50d 100644 (file)
@@ -4,27 +4,32 @@ project(json_gssapi)
 
 include_directories(src/)
 
-add_executable(json_gssapi src/datamodel/GSSName.cpp
-                           src/datamodel/GSSOID.cpp
-                           src/datamodel/GSSOIDSet.cpp
-                           src/datamodel/GSSBuffer.cpp
-                           src/datamodel/GSSCredential.cpp
-                           src/GSSException.cpp
-                           src/commands/GSSGetMic.cpp
-                           src/commands/GSSCreateSecContextCommand.cpp
-                           src/commands/GSSCommand.cpp 
-                           src/commands/GSSImportName.cpp
-                           src/commands/GSSAcquireCred.cpp 
-                           src/commands/GSSPseudoRandom.cpp
-                           src/commands/GSSWrap.cpp  
-                           src/commands/GSSUnwrap.cpp
-                           src/util_json.cpp
-                           src/cache/GSSContextCache.cpp
-                           src/cache/GSSNameCache.cpp
-                           src/datamodel/GSSContext.cpp
-                           src/util/base64.cpp
-                           main.cpp)
-target_link_libraries(json_gssapi gssapi_krb5 jansson crypto)
+add_library(jsongssapi SHARED 
+                       src/datamodel/GSSName.cpp
+                       src/datamodel/GSSOID.cpp
+                       src/datamodel/GSSOIDSet.cpp
+                       src/datamodel/GSSBuffer.cpp
+                       src/datamodel/GSSCredential.cpp
+                       src/GSSException.cpp
+                       src/commands/GSSGetMic.cpp
+                       src/commands/GSSCreateSecContextCommand.cpp
+                       src/commands/GSSCommand.cpp 
+                       src/commands/GSSImportName.cpp
+                       src/commands/GSSAcquireCred.cpp 
+                       src/commands/GSSPseudoRandom.cpp
+                       src/commands/GSSWrap.cpp  
+                       src/commands/GSSUnwrap.cpp
+                       src/util_json.cpp
+                       src/cache/GSSContextCache.cpp
+                       src/cache/GSSNameCache.cpp
+                       src/datamodel/GSSContext.cpp
+                       src/util/base64.cpp
+                      )
+
+target_link_libraries(jsongssapi gssapi_krb5 jansson crypto)
+
+add_executable(json_gssapi main.cpp)
+target_link_libraries(json_gssapi gssapi_krb5 jansson crypto jsongssapi)
 
 find_package (PkgConfig)
 pkg_check_modules (GLIB2   glib-2.0)
diff --git a/json_gssapi/json_protocol.txt b/json_gssapi/json_protocol.txt
new file mode 100644 (file)
index 0000000..270dac6
--- /dev/null
@@ -0,0 +1,147 @@
+The json_gssapi layer provides an interface to calling the GSSAPI using JSON
+to communicate its data.  The messages are passed to the layer to initiate
+a call into GSSAPI, and results are returned.  The calling messages into the
+layer are expected to run one per line.
+
+The calls have a general structure of:
+{
+  "method": "gss_api_call_name",
+  "arguments":
+  {
+    "argument_1": "string value",
+    "argument_2": 0000, /* Number */
+    "argument_3": ["array","of","values"]
+  }
+}
+
+Returns have a genaral structure of:
+{
+  "method": "gss_api_call_name",
+  "return_values":
+  {
+    "major_status": 0,
+    "minor_status": 0,
+    "return_1": "return value"
+  }
+}
+
+Background: data types
+----------------------------------------------------------------------------
+GSS defines several data types, including names, security contexts,
+credentials, and OIDs.  The json_gssapi layer consumes and emits these as
+javascript strings, but each type expects its strings to conform to a
+specific format.
+
+Data Type    Format
+------------ --------------------------------------------------------
+Context      A Base64 encoded string.  json_gssapi users should never
+             generate these.  Instead, users should use the value
+             returned from the gss_init_sec_context method whenever
+             a context is needed.
+Credential   A Base64 encoded string.  json_gssapi users should never
+             generate these.  Instead, users should use the value
+             returned from the gss_acquire_cred method whenever a
+             credential is needed.
+Name         A Base64 encoded string.  json_gssapi users should never
+             generate these.  Instead, users should use the value
+             returned from the gss_import_name function whenever a
+             name is needed.
+OID          A character string representing an OID 
+             (http://en.wikipedia.org/wiki/Object_identifier).  These
+             will be either in the format of "{ # # ## # }" or in the
+             format of "#.#.##.#"
+
+
+GSS Import Name
+------------------------------------------------------------------------
+The gss_import_name call is used to convert a text string name into an
+internal representation that other GSS functions will use.  The call
+takes two arguments:
+    input_name        The textual name to be imported
+    input_name_type   The OID that specifies how input_name is
+                      interpreted.
+
+The call returns three values:
+    major_status      Major status return code; 0 on success.
+    minor_status      Minor status return code; 0 on success.
+    gss_name          The Base64 encoded string representing the GSSAPI
+                      name object.  (Note that this is a hash table
+                      lookup key for the object, not the object itself)
+
+The input_name string will have different formats, depending on the
+input_name_type specified.  Some popular combinations are:
+    
+  input_name_type          expected input_name formatting
+  ----------------------   ---------------------------------------------
+  1.2.840.113554.1.2.1.1   username@realm
+                           postmaster@example.com
+
+  1.2.840.113554.1.2.1.4   service@hostname
+                           HTTP@www.example.com
+
+Example message:
+  {"method":"gss_import_name","arguments":{"input_name":"HTTP@localhost","input_name_type":"{1 2 840 113554 1 2 1 4 }"}}
+
+GSS Initialize Security Context
+------------------------------------------------------------------------------
+The gss_init_sec_context call is used to initialize a security context.  This
+is a two-party process.  The originating party will call gss_init_sec_context
+to generate (1) a GSS context return, and (2) a token to send to the other
+party.  The token is then communicated to the other party, which uses that as
+input to generate its own token in return.  The originating party then calls
+gss_init_sec_context again, including as parameters the token generated by
+the other side and the context generated by the first call to
+gss_init_sec_context.
+
+Perhaps an illustration will be easier:
+
+Initiating party                    Accepting party
+----------------------------------- -----------------------------------
+Call gss_init_sec_context
+   Receive back Token_I1
+   Receive back context_I1
+Send Token_I1 to acceptor
+                                     Receive Token_A1
+                                     Call gss_accept_sec_context
+                                        Receive back Token_A2
+                                        Receive back Context_A2
+                                     Send Token_A2 to initiator
+Call gss_init_sec_context
+   Receive back Token_I3
+   Receive back Context_I3
+Send Token_I3 to acceptor
+                            ...
+
+The back-and-forth communication negotiates a session, called a security
+context, between the two parties.  It continues while the
+gss_init_sec_context command returns a major_status value of 1,
+"GSS_CONTINUE_NEEDED".  Success is indicated by a major_status value of 
+0.
+
+The call takes arguments:
+  target_name      The Base64 handle to the GSS name generated by
+                   gss_import_name.  This name needs to match the name
+                   that the acceptor calls itself.
+  context_handle   The Base64 handle to the GSS context generated by the
+                   previous call to gss_init_sec_context.  If this is
+                   the first call, do not specify this argument.
+  input_token      The token received back from the acceptor.  Omit this
+                   parameter for the first call to gss_init_sec_context.
+  mech_type        An OID of the security mechanism desired.  Omit this
+                   to use the default mechanism.  (GSS_C_NO_OID)
+  time_req         The number of seconds this security context (session)
+                   should remain valid.  Omitting or setting a value of
+                   0 results in the default of two hours.
+  req_flags        An integer of a bitmask of flags representing
+                   requested GSS services.  Omit unless you have reason
+                   to include it.
+
+Example messages:
+  First invocation:
+    {"method":"gss_create_sec_context","arguments":{"target_name":""}}
+  Subsequent invocation:
+    {"method":"gss_create_sec_context","arguments":{"target_name":"","context_handle":"","input_token":""}}
+  ... where the target name comes from gss_import_name, the context
+  handle comes from previous calls to gss_init_sec_contest, and the
+  input token comes from the acceptor.
+
index 8bb47f1..ec3cb53 100644 (file)
@@ -1,6 +1,89 @@
+#include <commands/GSSImportName.h>
+#include <commands/GSSCreateSecContextCommand.h>
+#include <commands/GSSAcquireCred.h>
+#include <datamodel/GSSBuffer.h>
+#include <exception>
 #include <iostream>
+#include <string>
+#include <util_json.h>
+
+using std::cin;
+using std::cout;
+using std::endl;
+using std::getline;
+using std::string;
 
 int main(int argc, char **argv) {
-    std::cout << "Hello, world!" << std::endl;
-    return 0;
+  /* Variables */
+  string input, method;
+  const char* c_str;
+  JSONObject json;
+  JSONObject *result;
+  json_error_t jsonErr;
+  GSSCommand *cmd;
+  
+  /* Error checking */
+  
+  /* Setup */
+  
+  /* Main processing */
+  do 
+  {
+    try 
+    {
+      cout << "Give me some JSON: ";
+      getline(cin, input);
+      
+      c_str = input.c_str();
+      JSONObject json = JSONObject::load(c_str, 0, &jsonErr);
+      
+      // Oh, how I wish I could simply use: switch(json.get("method"))
+      c_str = json.get("method").string();
+      method = c_str;
+      if ("gss_import_name" == method)
+      {
+        cmd = new GSSImportName(&json);
+      }
+      else if ("gss_create_sec_context" == method)
+      {
+        cmd = new GSSCreateSecContextCommand(&json);
+      }
+      else if ("gss_acquire_cred" == method)
+      {
+        cmd = new GSSAcquireCred(&json);
+      }
+      else 
+      {
+        JSONObject response;
+        response.set("method", "unknown");
+        response.set("error_message", "Did not find a valid method to execute.");
+        cout << response.dump() << endl;
+      
+        continue;
+      }
+
+      cmd->execute();
+      result = cmd->toJSON();
+      delete cmd;
+      
+      cout << result->dump( JSON_INDENT(4) ) << endl;
+
+    }
+    catch ( std::bad_alloc )
+    {
+      JSONObject response;
+      JSONObject error;
+      response.set("method", "unknown");
+      response.set("error_message", "Could not parse the input JSON");
+      error.set("text", jsonErr.text);
+      error.set("source", jsonErr.source);
+      error.set("line", jsonErr.line);
+      error.set("column", jsonErr.column);
+      error.set("position", jsonErr.position);
+      response.set("error", error);
+      cout << response.dump() << endl;
+    }
+  } while(1);
+  
+  return 0;
 }
index b395af9..d469b8a 100644 (file)
@@ -5,8 +5,8 @@
  *
  */
 
-#ifndef GSSCONTEXTCACHE_H
-#define GSSCONTEXTCACHE_H
+#ifndef GSSNAMECACHE_H
+#define GSSNAMECACHE_H
 
 #include <map>
 #include <string>
@@ -37,4 +37,4 @@ private:
     static GSSNameCache* _instance;
 };
 
-#endif // GSSCONTEXTCACHE_H
+#endif // GSSNAMECACHE_H
index 2c76627..fe86d15 100644 (file)
@@ -7,12 +7,13 @@
 
 #include "GSSAcquireCred.h"
 #include "GSSException.h"
+#include <cache/GSSNameCache.h>
 
 #include <stdexcept>
 
 GSSAcquireCred::GSSAcquireCred(gss_acq_cred_type fn) : function(fn)
 {
-
+  desired_name = GSS_C_NO_NAME;
 }
 
 GSSAcquireCred::GSSAcquireCred ( const GSSAcquireCred& other )
@@ -55,6 +56,9 @@ bool GSSAcquireCred::loadParameters(JSONObject *params)
   // Easy stuff(*params)
   this->time_req = (*params)["arguments"]["time_req"].integer();
 
+  /**************
+   * cred_usage *
+   **************/
   if ( ! params->get("arguments").get("cred_usage").isNull() )
   {
     if (params->get("arguments").get("cred_usage").isString())
@@ -74,6 +78,9 @@ bool GSSAcquireCred::loadParameters(JSONObject *params)
       throw std::invalid_argument( "Unrecognized argument type for cred_usage." );
       }
   
+  /*****************
+   * desired_mechs *
+   *****************/
   if ( params->get("arguments").get("desired_mechs").isArray() )
   {
     for (nDesiredMechs = 0; 
@@ -85,6 +92,16 @@ bool GSSAcquireCred::loadParameters(JSONObject *params)
     }
   } else
     throw std::invalid_argument("Unrecognized desired_mechs array.");
+
+  /****************
+   * desired_name *
+   ****************/
+  if ( ! params->get("arguments").get("desired_name").isNull() )
+  {
+    std::string key = params->get("arguments").get("desired_name").string();
+    this->desired_name = GSSNameCache::instance()->retrieve(key);
+  }
+
   
   /* Cleanup */
   /* Return */
index a4c6d48..6473a7e 100644 (file)
@@ -14,7 +14,7 @@
 #include "datamodel/GSSName.h"
 #include <gssapi/gssapi.h>
 
-class GSSAcquireCred :  GSSCommand
+class GSSAcquireCred : public GSSCommand
 {
 public:
     GSSAcquireCred( gss_acq_cred_type fn = &gss_acquire_cred );
index 6665c5b..b99eb47 100644 (file)
@@ -17,8 +17,10 @@ public:
   GSSCommand() {};
   GSSCommand(JSONObject params) : parameters(params) { };
   
-  virtual void execute() { std::cout << "\ninside GSSCommand::invoke()\n"; };  
-  virtual JSONObject *toJSON() { return new JSONObject(); }
+  virtual ~GSSCommand() {};
+  
+  virtual void execute() = 0; // { std::cout << "\ninside GSSCommand::invoke()\n"; };  
+  virtual JSONObject *toJSON() = 0; // { return new JSONObject(); }
   
 protected:
   JSONObject parameters;
index 2d1fa51..54be5b5 100644 (file)
@@ -8,7 +8,10 @@
 #include "GSSCreateSecContextCommand.h"
 #include "GSSException.h"
 #include <cache/GSSContextCache.h>
+#include <cache/GSSNameCache.h>
+#include <datamodel/GSSName.h>
 #include <gssapi.h>
+#include <stdexcept>
 #include <stdlib.h>
 #include <string.h>
 
@@ -28,56 +31,26 @@ typedef OM_uint32 (*init_sec_context)(
     OM_uint32 *         /* time_req */
 );
 
-/* Helper function - import the OID from a string */
-static gss_OID str_to_oid(const char *mech_type_str = NULL)
-{
-  /* Variables */
-  gss_buffer_desc gssbuffOID;
-  gss_OID gssoidTargetOID;
-  OM_uint32 major;
-  OM_uint32 minor;
-  
-  /* Error checking */
-  if (mech_type_str == NULL ||
-      *mech_type_str == 0)
-    return NULL;
-  
-  /* Setup */
-  /* Main */
-  gssbuffOID.value = (void *)(mech_type_str);
-  gssbuffOID.length = strlen(mech_type_str);
-  major = gss_str_to_oid(&minor, 
-                        &gssbuffOID, 
-                        &gssoidTargetOID);
-  if (major != GSS_S_COMPLETE)
-    throw GSSException("Error converting string to OID", major, minor);
-
-  /* Cleanup */
-  
-  /* Return */
-  return gssoidTargetOID;
-}
-
 void
 GSSCreateSecContextCommand::execute()
 {
   /* Variables */
   init_sec_context fn = (init_sec_context)function;
+  gss_OID actual_mech_type;
   
   /* Error checking */
   
   /* Setup */
   if (output_token.length > 0)
     retVal = gss_release_buffer(&minor_status, &output_token);
-  
+
   /* Main */
-  
   retVal = fn(
     &minor_status,
     GSS_C_NO_CREDENTIAL,
     &context_handle,
-    target_name,
-    mech_type,
+    targetName.toGss(),
+    mechType.toGss(),
     req_flags,
     time_req,
     GSS_C_NO_CHANNEL_BINDINGS,
@@ -87,6 +60,15 @@ GSSCreateSecContextCommand::execute()
     &ret_flags,
     &time_rec);
   
+  if ( GSS_ERROR(this->retVal) )
+  {
+    std::string errMsg;
+    errMsg += "Cannot init_sec_context: ";
+    throw GSSException(errMsg.c_str(), this->retVal, this->minor_status, mechType.toGss());
+  }
+  
+  actualMechType.setValue(actual_mech_type);
+  
   context.setContext(context_handle, true);
   contextKey = GSSContextCache::instance()->store(context);
   
@@ -120,88 +102,77 @@ const char* GSSCreateSecContextCommand::getTargetDisplayName()
   return( ret );
 }
 
-const char* GSSCreateSecContextCommand::getActualMechType()
-{
-  return(this->oidToStr(this->actual_mech_type));
-}
-
-const char* GSSCreateSecContextCommand::getMechType()
-{
-  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 (oid == NULL)
-    return NULL;
-
-  /* Setup */  
-  
-  /* main */
-  major = gss_oid_to_str(&minor, oid, &output);
-  if (major == GSS_S_COMPLETE)
-    retVal = (const char *)output.value;
-  else
-    retVal = NULL;
-  
-  /* cleanup */
-  
-  /* return */
-  return( retVal );
-}
-
 bool GSSCreateSecContextCommand::loadParameters(JSONObject *params)
 {
   /* Variables */
-  OM_uint32 major, minor;
-  gss_buffer_desc gssbuffTargetName;
-  const char *buffer;
+  std::string key;
   
   /* Error checking */
+  if ( params->get("arguments").isNull() )
+    return true;
   
   /* Setup */
   // Should I zeroOut?
   
   /* Main processing */
   // Easy stuff(*params)
-  this->time_req = (OM_uint32)( (*params)["arguments"]["time_req"].integer() );
-  this->req_flags = (OM_uint32)( (*params)["arguments"]["req_flags"].integer() );
+  if ( !params->get("arguments").get("time_req").isNull() )
+    this->time_req = params->get("arguments").get("time_req").integer();
+  
+  if ( !params->get("arguments").get("req_flags").isNull() )
+    this->req_flags = params->get("arguments").get("req_flags").integer();
   
   // context_handle
-  //   -- just treat the value passed in as correct.
-  context_handle = (gss_ctx_id_t)( (*params)["arguments"]["context_handle"].integer() );
+  if ( ! params->get("arguments").get("context_handle").isNull() )
+  {
+    this->context_handle = GSS_C_NO_CONTEXT;
+    if (params->get("arguments").get("context_handle").isString())
+    {
+      key = params->get("arguments").get("context_handle").string();
+      context = GSSContextCache::instance()->retrieve( key.c_str() );
+      this->context_handle = context.getContext();
+    }
+    if (GSS_C_NO_CONTEXT == this->context_handle)
+      throw std::invalid_argument( "Could not find the context_handle." );
+  }
   
   // target_name
-  buffer = (*params)["arguments"]["target_name"].string();
-  if (buffer != NULL && *buffer != 0)
+  if ( ! params->get("arguments").get("target_name").isNull() )
   {
-    gssbuffTargetName.value = (void *)buffer;
-    gssbuffTargetName.length = strlen( buffer );
-    
-    major = gss_import_name(&minor, 
-                           &gssbuffTargetName, 
-                           GSS_C_NO_OID, 
-                           &target_name);
-    if (major != GSS_S_COMPLETE)
-      throw GSSException("Error importing target_name", major, minor);
+    this->target_name = GSS_C_NO_NAME;
+    if (params->get("arguments").get("target_name").isString())
+    {
+      key = params->get("arguments").get("target_name").string();
+      
+      targetName = GSSNameCache::instance()->retrieve(key);
+      
+      this->target_name = targetName.toGss();
+    }
+    if (GSS_C_NO_NAME == this->target_name)
+      throw std::invalid_argument( "Could not find the target_name" );
   }
   
   // mech_type  
-  mech_type = str_to_oid( (*params)["arguments"]["mech_type"].string() );
+  if ( ! params->get("arguments").get("mech_type").isNull() )
+  {
+    key.clear();
+    if (params->get("arguments").get("mech_type").isString())
+    {
+      key = params->get("arguments").get("mech_type").string();
+      mechType.setValue(key);
+    }
+    if (GSS_C_NO_OID == this->mechType.toGss() )
+      throw std::invalid_argument( std::string() + "Could not create a mech_type OID from '" + key + "'");
+  }
   
   // input_token
-  buffer = (*params)["arguments"]["input_token"].string();
-  if (buffer != NULL && *buffer != 0)
+  if ( ! params->get("arguments").get("input_token").isNull() )
   {
-    this->input_token.value = (void *)buffer;
-    this->input_token.length = strlen(buffer);
+    key = params->get("arguments").get("input_token").string();
+    this->input_token.value = (void *)key.c_str();
+    this->input_token.length = key.length();
   }
-  
+
   /* Cleanup */
   
   
@@ -228,12 +199,6 @@ bool GSSCreateSecContextCommand::zeroOut(bool initialized)
     if (this->target_name != NULL)
       gss_release_name(&minor, &(this->target_name));
       
-    if (mech_type != NULL)
-      gss_release_oid(&minor, &(this->mech_type));
-    
-    if (this->actual_mech_type != NULL)
-      gss_release_oid(&minor, &(this->actual_mech_type));
-    
     if (this->output_token.length > 0)
       gss_release_buffer(&minor, &output_token);
     
@@ -251,10 +216,9 @@ 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->mechType.setValue( (char *)"{ 1 3 6 1 5 5 15 1 1 18 }" );
   this->input_token.length = 0;
   this->input_token.value = NULL;
-  this->actual_mech_type = GSS_C_NO_OID;
   this->output_token.length = 0;
   this->output_token.value = NULL;
 
@@ -277,7 +241,7 @@ JSONObject *GSSCreateSecContextCommand::toJSON()
   values->set("major_status", this->retVal);
   values->set("minor_status", this->minor_status);
   values->set("context_handle", this->contextKey.c_str());
-  values->set("actual_mech_type", this->getActualMechType());
+  values->set("actual_mech_type", this->getActualMechType().toString().c_str());
   values->set("output_token", (const char *)this->output_token.value);
   values->set("ret_flags", this->ret_flags);
   values->set("time_rec", this->time_rec);
index 364d69e..6593afe 100644 (file)
@@ -10,6 +10,8 @@
 
 #include "GSSCommand.h"
 #include <datamodel/GSSContext.h>
+#include <datamodel/GSSName.h>
+#include <datamodel/GSSOID.h>
 #include <gssapi.h>
 
 class GSSCreateSecContextCommand : public GSSCommand
@@ -20,11 +22,9 @@ public:
     OM_uint32 minor_status;
     gss_ctx_id_t context_handle;
     gss_name_t target_name;
-    gss_OID mech_type;
     OM_uint32 req_flags;
     OM_uint32 time_req;
     gss_buffer_desc input_token;
-    gss_OID actual_mech_type;
     gss_buffer_desc output_token;
     OM_uint32 ret_flags;
     OM_uint32 time_rec;
@@ -44,16 +44,18 @@ public:
     OM_uint32 getTimeReq() { return time_req; }
     gss_ctx_id_t getContextHandle() { return context_handle; }
     void *getGSSFunction() { return function; }
+    GSSOID getMechType() { return mechType; };
+    GSSOID getActualMechType() { return actualMechType; };
     
     // complex accessors
     const char * getTargetDisplayName();
-    const char * getMechType();
-    const char * getActualMechType();
     
 private:
     void *function;
-    const char * oidToStr(gss_OID oid);
     GSSContext context;
+    GSSOID mechType;
+    GSSOID actualMechType;
+    GSSName targetName;
     std::string contextKey;
 };
 
index 7a1b446..e98d447 100644 (file)
@@ -93,10 +93,21 @@ GSSName& GSSName::operator= ( const GSSName& rhs )
   if (rhs.toGss() != this->toGss())
   {
     this->function = rhs.function;
-    this->minor_status = rhs.minor_status;
-    this->major_status = rhs.major_status;
-    this->name = rhs.name;
-    this->hashKey = rhs.hashKey;
+    if (GSS_C_NO_NAME == rhs.name)
+    {
+      major_status = 0;
+      minor_status = 0;
+      name = GSS_C_NO_NAME;
+    }
+    else
+    {
+      this->major_status = gss_duplicate_name(&minor_status, rhs.name, &name);
+      if ( GSS_ERROR(major_status) )
+      {
+       throw GSSException("Cannot copy a GSS name.", major_status, minor_status);
+      }
+    }
+    this->hashKey = "";
     this->skipRelease = rhs.skipRelease;
   }
   return *this;
index 572a939..8669267 100644 (file)
@@ -14,6 +14,7 @@
 #include <exception>
 #include "util_json.h"
 #include <cache/GSSContextCache.h>
+#include <cache/GSSNameCache.h>
 #include <datamodel/GSSContext.h>
 
 // Registers the fixture into the 'registry'
@@ -92,6 +93,13 @@ GSSCreateSecContextTest::testConstructor()
   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:
@@ -108,27 +116,50 @@ GSSCreateSecContextTest::testConstructor()
  */
 void GSSCreateSecContextTest::testConstructorWithJSONObject()
 {
-  const char* input = "{\"method\": \"gss_create_sec_context\", \
+  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 = "{\"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\": \"";
+  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(
     &json, 
     (void *)&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(
@@ -137,9 +168,10 @@ void GSSCreateSecContextTest::testConstructorWithJSONObject()
     (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["arguments"]["mech_type"].string()), 
+    cmd.getMechType().toString()
   );
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
@@ -167,19 +199,14 @@ GSSCreateSecContextTest::testEmptyCall()
   cmd.time_req = rand() % 1024;
   cmd.req_flags = rand() % 1024;
   cmd.target_name = NULL;
-  cmd.context_handle = expectedArgument = (gss_ctx_id_t)rand();
-  
-  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 = expectedResult = (gss_ctx_id_t)rand();
+  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);
@@ -205,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(
@@ -239,7 +266,7 @@ GSSCreateSecContextTest::testEmptyCall()
   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.",
@@ -292,9 +319,9 @@ void GSSCreateSecContextTest::testJSONMarshal()
   
   /* Setup */
   // Set expectations on what the GSS function will produce
-  InitSecContextMock::retVal = GSS_S_BAD_MECH;
-  InitSecContextMock::minor_status = 20;
-  InitSecContextMock::context_handle = expectedResult = (gss_ctx_id_t)rand();
+  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);
index 883a9cb..d36bd3a 100644 (file)
@@ -28,12 +28,28 @@ void NameCacheTest::tearDown()
 void NameCacheTest::testStore()
 {
   /* Variables      */
+  gss_name_t src;
   std::string  key;
-  GSSName      source( (gss_name_t)rand(), true), target;
+  GSSName      source, target;
+  OM_uint32 major, minor;
   
   /* Error checking */
   /* Setup          */
-
+  major = gss_import_name(&minor, GSSBuffer((char *)"HTTP@localhost").toGss(), GSS_C_NT_HOSTBASED_SERVICE, &src);
+  if (GSS_ERROR(major))
+  {
+    OM_uint32 maj, min, context;
+    gss_buffer_desc buf;
+    
+    std::cout << "Error in importing name." << std::endl;
+    maj = 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 storing into the cache.",
+    !GSS_ERROR(major)
+  );
+  source.setValue(src);
   
   /* Main           */
   
@@ -45,8 +61,8 @@ void NameCacheTest::testStore()
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The name cache did not store and retrieve the same data",
-    source.toGss(),
-    target.toGss()
+    source.toString(),
+    target.toString()
   );
 
   /* Cleanup        */