Adding GSS Pseudo Random
authorMark Donnelly <mark@painless-security.com>
Mon, 18 Aug 2014 21:12:21 +0000 (17:12 -0400)
committerMark Donnelly <mark@painless-security.com>
Mon, 18 Aug 2014 21:12:21 +0000 (17:12 -0400)
json_gssapi/CMakeLists.txt
json_gssapi/src/GSSPseudoRandom.cpp [new file with mode: 0644]
json_gssapi/src/GSSPseudoRandom.h [new file with mode: 0644]
json_gssapi/test/CMakeLists.txt
json_gssapi/test/GSSAcquireCredTest.cpp
json_gssapi/test/GSSPseudoRandomTest.cpp [new file with mode: 0644]
json_gssapi/test/GSSPseudoRandomTest.h [new file with mode: 0644]
json_gssapi/test/command_mocks/MockPseudoRandom.cpp [new file with mode: 0644]
json_gssapi/test/command_mocks/MockPseudoRandom.h [new file with mode: 0644]

index 16b7441..da009af 100644 (file)
@@ -13,6 +13,7 @@ add_executable(json_gssapi src/datamodel/GSSName.cpp
                            src/GSSCommand.cpp 
                            src/GSSImportName.cpp
                            src/GSSAcquireCred.cpp 
+                           src/GSSPseudoRandom.cpp
                            src/GSSWrap.cpp  
                            src/GSSUnwrap.cpp
                            src/util_json.cpp 
diff --git a/json_gssapi/src/GSSPseudoRandom.cpp b/json_gssapi/src/GSSPseudoRandom.cpp
new file mode 100644 (file)
index 0000000..fbb111b
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ *
+ * For license details, see the LICENSE file in the root of this project.
+ *
+ */
+
+#include <stdexcept>
+
+#include "GSSPseudoRandom.h"
+
+GSSPseudoRandom::GSSPseudoRandom(JSONObject *params, 
+                                              gss_pseudo_random_type fn) : GSSCommand(params)
+{
+  /* Variables */
+  /* Error checking */
+  /* Setup */
+  /* Main */
+  loadParameters(params);
+  function = fn;
+  /* Cleanup */
+  /* Return */
+  
+}
+
+/* JSON input
+ * 
+ * {"method":    "gss_pseudo_random",
+ *  "arguments": 
+ *   {
+ *     "context_handle":     "########",
+ *     "prf_key":            ###,
+ *     "prf_in":             "la la la input message",
+ *     "desired_output_len": ####
+ *   }
+ * 
+ */
+bool GSSPseudoRandom::loadParameters ( JSONObject* params )
+{
+  /* Variables */
+  std::string sInputMessage;
+  
+  /* Error checking */
+  /* Setup */
+  /* Main */
+  
+  /***********
+   * prf_key *
+   ***********/
+  if ( ! params->get("arguments").get("prf_key").isNull() )
+  {
+    if (params->get("arguments").get("prf_key").isInteger())
+      this->key = params->get("arguments").get("prf_key").integer();
+    else
+      throw std::invalid_argument( "Unrecognized argument type for prf_key." );
+  }  
+
+  
+  /**********************
+   * desired_output_len *
+   **********************/
+  if ( ! params->get("arguments").get("desired_output_len").isNull() )
+  {
+    if (params->get("arguments").get("desired_output_len").isInteger())
+      this->desiredOutputLength = params->get("arguments").get("desired_output_len").integer();
+    else
+      throw std::invalid_argument( "Unrecognized argument type for desired_output_len." );
+  }  
+
+  
+  /**********
+   * prf_in *
+   **********/
+  if ( ! params->get("arguments").get("prf_in").isNull() )
+  {
+    if (params->get("arguments").get("prf_in").isString())
+    {
+      sInputMessage = params->get("arguments").get("prf_in").string();
+      this->inputMessage.setValue(sInputMessage);
+    }
+  }
+  
+  /* Cleanup */
+  /* Return */
+  return true;
+}
+
+
+void GSSPseudoRandom::execute()
+{
+  /* Variables */
+  gss_buffer_desc output_buf;
+  OM_uint32 minor = 0;
+  
+  retVal = function(
+    &minor,
+    this->context,
+    this->key,
+    this->inputMessage.toGss(),
+    this->desiredOutputLength,
+    &output_buf
+  );
+  
+  this->minor_status = minor;
+  this->outputMessage.setValue( (char *)output_buf.value, output_buf.length );
+}
+
+/* Desired JSON output:
+ * 
+ * {
+ *  "command":       "gss_pseudo_random",
+ *  "return_values": 
+ *  {
+ *      "major_status": 0,
+ *      "minor_status": 0,
+ *      "random_bytes": "asdf"
+ *  }
+ * }
+ */
+JSONObject* GSSPseudoRandom::toJSON()
+{
+  /* Variables */
+  JSONObject *ret = new JSONObject();
+  JSONObject *values = new JSONObject();
+  
+  /* Error checking */
+  
+  /* Setup */
+  
+  /* Main */
+  // Return Values
+  // Easy stuff
+  values->set("major_status", this->retVal);
+  values->set("minor_status", this->minor_status);
+  
+  values->set(
+    "random_bytes",
+    this->outputMessage.toString().c_str()
+  );
+  
+  // Put it all together.
+  ret->set("command", "gss_pseudo_random");
+  ret->set("return_values", *values);
+  
+  /* Cleanup */
+  
+  /* Return */
+  return(ret);
+}
+
diff --git a/json_gssapi/src/GSSPseudoRandom.h b/json_gssapi/src/GSSPseudoRandom.h
new file mode 100644 (file)
index 0000000..11d06df
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ *
+ * For license details, see the LICENSE file in the root of this project.
+ *
+ */
+
+#ifndef GSSPSEUDORANDOMCOMMAND_H
+#define GSSPSEUDORANDOMCOMMAND_H
+
+#include <openssl/rand.h>
+#include <gssapi/gssapi.h>
+
+#include "datamodel/GSSBuffer.h"
+#include "GSSCommand.h"
+
+typedef OM_uint32 (*gss_pseudo_random_type) (
+    OM_uint32 *,        /* minor_status */
+    gss_ctx_id_t,       /* context */
+    int,                /* prf_key */
+    const gss_buffer_t, /* prf_in */
+    ssize_t,            /* desired_output_len */
+    gss_buffer_t);      /* prf_out */
+
+class GSSPseudoRandom : public GSSCommand
+{
+public:
+    GSSPseudoRandom(gss_pseudo_random_type fn = &gss_pseudo_random) : function(fn) {};
+    GSSPseudoRandom(JSONObject *params, 
+                           gss_pseudo_random_type fn = &gss_pseudo_random);
+    void execute();
+    JSONObject* toJSON();
+    bool loadParameters(JSONObject *params);
+    
+    /* Setters */
+    void setContextHandle ( gss_ctx_id_t desiredContext ) { context = (desiredContext); };
+    void setKey ( int prf_in ) { key = (prf_in); };
+    void setInputMessage ( const GSSBuffer prf_in ) { inputMessage.setValue(prf_in.toString()); };
+    void setDesiredOutputLength ( int desired_output_len ) { desiredOutputLength =desired_output_len; };
+    
+    /* Getters */
+    GSSBuffer getInputMessage() { return inputMessage; }
+    GSSBuffer getOutputMessage() { return outputMessage; }
+    OM_uint32 getRetVal() { return(retVal); }
+    OM_uint32 getMinorStatus() { return(minor_status); }
+    int       getKey() { return(key); }
+    int       getDesiredOutputLength() { return(desiredOutputLength); }
+    gss_pseudo_random_type getGSSFunction() { return function; };
+    
+private:
+    OM_uint32 retVal, minor_status;
+    gss_pseudo_random_type function;
+    gss_ctx_id_t context;
+    int key, desiredOutputLength;
+    GSSBuffer inputMessage;
+    GSSBuffer outputMessage;
+};
+
+#endif // GSSPSEUDORANDOMCOMMAND_H
index 6098aa8..e262b50 100644 (file)
@@ -3,11 +3,13 @@ include_directories(${CMAKE_SOURCE_DIR}/src)
 add_executable(test GSSExceptionTest.cpp 
                     GSSAcquireCredTest.cpp 
                     GSSGetMicTest.cpp
+                    GSSPseudoRandomTest.cpp 
                     GSSWrapTest.cpp 
                     GSSUnwrapTest.cpp
                     command_mocks/InitSecContextMock.cpp
                     command_mocks/MockAcquireCred.cpp
                     command_mocks/MockGetMic.cpp
+                    command_mocks/MockPseudoRandom.cpp 
                     command_mocks/MockUnwrap.cpp
                     command_mocks/MockWrap.cpp 
                     GSSCreateSecContextTest.cpp 
@@ -20,6 +22,7 @@ add_executable(test GSSExceptionTest.cpp
                     ../src/GSSException.cpp
                     ../src/GSSGetMic.cpp
                     ../src/GSSAcquireCred.cpp
+                    ../src/GSSPseudoRandom.cpp
                     ../src/GSSUnwrap.cpp
                     ../src/GSSWrap.cpp
                     ../src/datamodel/GSSBuffer.cpp
@@ -31,7 +34,7 @@ add_executable(test GSSExceptionTest.cpp
                     datamodel/GSSOIDSetTest.cpp
   )
 
-target_link_libraries(test cppunit gssapi_krb5 jansson)
+target_link_libraries(test cppunit gssapi_krb5 jansson crypto)
 
 # install(TARGETS test RUNTIME DESTINATION bin)
 
index f5d1f5d..b4b552d 100644 (file)
@@ -221,7 +221,7 @@ void GSSAcquireCredTest::testEmptyCall()
  *     "cred_handle": "###########",
  *     "actual_mechs": [
  *       "{ 1 2 3 4 }",
- *       "{ 5 6 7 8 }"
+ *       "{ 5 6 7 8 }"
  *     ],
  *     "time_rec": 0
  *   }
@@ -237,7 +237,7 @@ void GSSAcquireCredTest::testJSONMarshal()
   /* Error checking */
   /* Setup */
   actualMechs.addOID( GSSOID( (char *)"{ 1 2 3 4 }" ) );
-  actualMechs.addOID( GSSOID( (char *)"{ 5 6 7 8 }" ) );
+  actualMechs.addOID( GSSOID( (char *)"{ 5 6 7 8 }" ) );
   MockAcquireCred::reset();
   MockAcquireCred::retVal = 0;
   MockAcquireCred::minor_status = 0;
@@ -278,7 +278,7 @@ void GSSAcquireCredTest::testJSONMarshal()
   
   CPPUNIT_ASSERT_EQUAL_MESSAGE(
     "The gss_name was reported incorrectly",
-    std::string("{ 5 6 7 8 }"),
+    std::string("{ 5 6 7 8 }"),
     std::string( (*result)["return_values"]["actual_mechs"][(size_t)1].string() )
   );
   
diff --git a/json_gssapi/test/GSSPseudoRandomTest.cpp b/json_gssapi/test/GSSPseudoRandomTest.cpp
new file mode 100644 (file)
index 0000000..12693ad
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ *
+ * For license details, see the LICENSE file in the root of this project.
+ *
+ */
+
+#include <algorithm>
+
+//#include <cppunit/TestFixture.h>
+//#include <cppunit/extensions/HelperMacros.h>
+#include <openssl/rand.h>
+
+#include "GSSPseudoRandom.h"
+#include "GSSPseudoRandomTest.h"
+#include "command_mocks/MockPseudoRandom.h"
+
+// Registers the fixture into the 'registry'
+CPPUNIT_TEST_SUITE_REGISTRATION( GSSPseudoRandomTest );
+
+
+// typedef OM_uint32 (*gss_pseudo_random_type) (
+//     OM_uint32 *,        /* minor_status */
+//     gss_ctx_id_t,       /* context */
+//     int,                /* prf_key */
+//     const gss_buffer_t, /* prf_in */
+//     ssize_t,            /* desired_output_len */
+//     gss_buffer_t);      /* prf_out */
+OM_uint32 mock_gss_pseudo_random(
+    OM_uint32 *minor_status,
+    gss_ctx_id_t  context,
+    int prf_key,
+    const gss_buffer_t prf_in,
+    ssize_t desired_output_len,
+    gss_buffer_t prf_out)
+{
+  /* Variables */
+  std::string buffer;
+  /* Error checking */
+  /* Setup */
+  /* Main */
+  MockPseudoRandom::context_handle = context;
+  MockPseudoRandom::key = prf_key;
+  MockPseudoRandom::inputMessageBuffer.setValue(prf_in);
+  MockPseudoRandom::desiredOutputLength = desired_output_len;
+  
+  buffer = MockPseudoRandom::outputMessageBuffer.toString();
+  prf_out->length = buffer.length();
+  prf_out->value = (void *)buffer.c_str();
+  
+  /* Cleanup */
+  /* Return */
+  return 0;
+}
+
+
+void GSSPseudoRandomTest::setUp()
+{
+  CppUnit::TestFixture::setUp();
+  MockPseudoRandom::reset();
+}
+
+
+void GSSPseudoRandomTest::testConstructor()
+{
+  /* Variables */
+  GSSPseudoRandom cmd = GSSPseudoRandom();
+  
+  /* Error checking */
+  /* Setup */
+  /* Main */
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The GSSPseudoRandom object has the wrong GSS function",
+    (void *)&gss_pseudo_random,
+    (void *)cmd.getGSSFunction()
+  );
+  
+  /* Cleanup */
+  /* Return */
+}
+
+/* 
+ * Test that the command calls into gss_pseudo_random with
+ * all of the correct values, and that the command reads
+ * all of the appropriate values back out of it.
+ */
+void GSSPseudoRandomTest::testEmptyCall()
+{
+  /* Variables */
+  GSSPseudoRandom cmd = GSSPseudoRandom(&mock_gss_pseudo_random);
+  gss_ctx_id_t desiredContext;
+  int prf_key;
+  ssize_t desired_output_len;
+  GSSBuffer prf_in((char *)"Input message");
+  
+  /* Error Checking */
+  /* Setup */
+  
+  // Populate cmd with what will be used to call into gss_pseudo_random
+    // taking the address of prf_key should be plenty random for testing the empty call.
+  desiredContext = (gss_ctx_id_t)&prf_key;
+  prf_key = rand();
+  desired_output_len = (ssize_t)(rand() + 50);  // Must be at least fifty bytes long
+  
+  cmd.setContextHandle(desiredContext);
+  cmd.setKey(prf_key);
+  cmd.setInputMessage( prf_in );
+  cmd.setDesiredOutputLength(desired_output_len);
+  
+  
+  // Populate the mock with what will be returned from gss_pseudo_random
+  MockPseudoRandom::minor_status = 0;
+  MockPseudoRandom::retVal = 0;
+  MockPseudoRandom::outputMessageBuffer.setValue((char *)"Output message");
+
+  
+  /* Main */
+  cmd.execute();
+  
+  // Do we populate the call to gss_pseudo_random correctly?
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The requested GSS context handle is not correct",
+    desiredContext,
+    MockPseudoRandom::context_handle
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The requested pseudo random function key is not correct",
+    prf_key,
+    MockPseudoRandom::key
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The requested desired output length is not correct",
+    desired_output_len,
+    MockPseudoRandom::desiredOutputLength
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The requested input message is not correct",
+    prf_in.toString(),
+    MockPseudoRandom::inputMessageBuffer.toString()
+  );
+  
+  // Do we read the results of gss_pseudo_random correctly?
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The requested output message is not correct",
+    MockPseudoRandom::outputMessageBuffer.toString(),
+    cmd.getOutputMessage().toString()
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The return value is not correct",
+    MockPseudoRandom::retVal,
+    cmd.getRetVal()
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The minor status value is not correct",
+    MockPseudoRandom::minor_status,
+    cmd.getMinorStatus()
+  );
+  
+  
+  
+  /* Cleanup */
+  /* Return */
+}
+
+/* JSON input
+ * 
+ * {"method":    "gss_pseudo_random",
+ *  "arguments": 
+ *   {
+ *     "context_handle":     "########",
+ *     "prf_key":            ###,
+ *     "prf_in":             "la la la input message",
+ *     "desired_output_len": ####
+ *   }
+ * 
+ */
+void GSSPseudoRandomTest::testConstructorWithJSONObject()
+{
+  /* Variables */
+  const char* input = "{\"method\": \"gss_pseudo_random\", \
+    \"arguments\": \
+    { \
+         \"context_handle\": \"#######\", \
+         \"prf_key\": 1234567890, \
+         \"prf_in\": \"mary had a little lamb\", \
+         \"desired_output_len\": 256 \
+    }\
+  }";
+  json_error_t jsonErr;
+  JSONObject json = JSONObject::load(input, 0, &jsonErr);
+  
+  GSSPseudoRandom cmd = GSSPseudoRandom(&json, &mock_gss_pseudo_random);
+
+  /* Error Checking */
+  /* Setup */
+  /* Main */
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "GSSPseudoRandom did not parse the prf_key argument correctly.",
+    1234567890,
+    cmd.getKey()
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "GSSPseudoRandom did not parse the prf_in argument correctly.",
+    std::string("mary had a little lamb"),
+    cmd.getInputMessage().toString()
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "GSSPseudoRandom did not parse the desired_output_len argument correctly.",
+    256,
+    cmd.getDesiredOutputLength()
+  );
+  
+  /* Cleanup */
+  /* Return */
+}
+
+/* Desired JSON output:
+ * 
+ * {
+ *  "command":       "gss_pseudo_random",
+ *  "return_values": 
+ *  {
+ *      "major_status": 0,
+ *      "minor_status": 0,
+ *      "random_bytes": "asdf"
+ *  }
+ * }
+ */
+void GSSPseudoRandomTest::testJSONMarshal()
+{
+
+  /* Variables */
+  std::string output("dns@google.com");
+  JSONObject *result;
+  GSSPseudoRandom cmd = GSSPseudoRandom(&mock_gss_pseudo_random);
+  
+  /* Error checking */
+  /* Setup */
+  MockPseudoRandom::minor_status = 0;
+  MockPseudoRandom::retVal = 0;
+  MockPseudoRandom::outputMessageBuffer.setValue(output);
+  
+  /* Main */
+  cmd.execute();
+  result = cmd.toJSON();
+//   std::cout << "\nGSSWrap JSON: \n" << result->dump() << "\n";
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The command name is incorrect",
+    std::string("gss_pseudo_random"),
+    std::string( (*result)["command"].string() )
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The return value was reported incorrectly",
+    (int)MockPseudoRandom::retVal,
+    (int)( (*result)["return_values"]["major_status"].integer() )
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The minor_status value was reported incorrectly",
+    (int)MockPseudoRandom::minor_status,
+    (int)( (*result)["return_values"]["minor_status"].integer() )
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The random bytes were reported incorrectly",
+    MockPseudoRandom::outputMessageBuffer.toString(),
+    std::string( (*result)["return_values"]["random_bytes"].string() )
+  );
+  
+  
+  /* Cleanup */
+  /* Return */
+}
+
+  /* Variables */
+  /* Error Checking */
+  /* Setup */
+  /* Main */
+  /* Cleanup */
+  /* Return */
diff --git a/json_gssapi/test/GSSPseudoRandomTest.h b/json_gssapi/test/GSSPseudoRandomTest.h
new file mode 100644 (file)
index 0000000..f2d9a11
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ *
+ * For license details, see the LICENSE file in the root of this project.
+ *
+ */
+
+#ifndef GSSPSEUDORANDOMTEST_H
+#define GSSPSEUDORANDOMTEST_H
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+class GSSPseudoRandomTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( GSSPseudoRandomTest );
+  CPPUNIT_TEST( testConstructor );
+  CPPUNIT_TEST( testEmptyCall );
+  CPPUNIT_TEST( testConstructorWithJSONObject );
+  CPPUNIT_TEST( testJSONMarshal );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+    void setUp();
+    
+    void testJSONMarshal();
+    void testEmptyCall();
+    void testConstructor();
+    void testConstructorWithJSONObject();
+};
+
+#endif // GSSPSEUDORANDOMTEST_H
diff --git a/json_gssapi/test/command_mocks/MockPseudoRandom.cpp b/json_gssapi/test/command_mocks/MockPseudoRandom.cpp
new file mode 100644 (file)
index 0000000..8dcdc7e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ *
+ * For license details, see the LICENSE file in the root of this project.
+ *
+ */
+
+#include "MockPseudoRandom.h"
+
+/*
+ * static OM_uint32     retVal;
+ * static OM_uint32     minor_status;
+ * 
+ * static gss_ctx_id_t  context_handle;
+ * static int           key;
+ * static GSSBuffer     inputMessageBuffer;
+ * static ssize_t       desiredOutputLength;
+ * static GSSBuffer     outputMessageBuffer;
+ * 
+ * static void reset();
+ */
+
+OM_uint32    MockPseudoRandom::retVal;
+OM_uint32    MockPseudoRandom::minor_status;
+gss_ctx_id_t MockPseudoRandom::context_handle;
+int          MockPseudoRandom::key;
+GSSBuffer    MockPseudoRandom::inputMessageBuffer;
+ssize_t      MockPseudoRandom::desiredOutputLength;
+GSSBuffer    MockPseudoRandom::outputMessageBuffer;
+
+void MockPseudoRandom::reset()
+{
+  retVal = 0;
+  minor_status = 0;
+  context_handle = GSS_C_NO_CONTEXT;
+  key = 0;
+  inputMessageBuffer.setValue(std::string());
+  desiredOutputLength = 0;
+  outputMessageBuffer.setValue(std::string());
+  
+  return;
+}
+
diff --git a/json_gssapi/test/command_mocks/MockPseudoRandom.h b/json_gssapi/test/command_mocks/MockPseudoRandom.h
new file mode 100644 (file)
index 0000000..02e6e03
--- /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 MOCKPSEUDORANDOM_H
+#define MOCKPSEUDORANDOM_H
+
+#include <datamodel/GSSBuffer.h>
+#include <gssapi/gssapi.h>
+
+class MockPseudoRandom
+{
+public:
+  static OM_uint32     retVal;
+  static OM_uint32     minor_status;
+  
+  static gss_ctx_id_t  context_handle;
+  static int           key;
+  static GSSBuffer     inputMessageBuffer;
+  static ssize_t       desiredOutputLength;
+  static GSSBuffer     outputMessageBuffer;
+  
+  static void reset();
+};
+
+#endif // MOCKPSEUDORANDOM_H