Parse gss_init_sec_context parameters out of a JSON string
authorMark Donnelly <mark@painless-security.com>
Fri, 18 Apr 2014 12:49:33 +0000 (08:49 -0400)
committerMark Donnelly <mark@painless-security.com>
Fri, 18 Apr 2014 12:49:33 +0000 (08:49 -0400)
17 files changed:
json_gssapi/CMakeLists.txt
json_gssapi/cmake_modules/FindCPPUNIT.cmake [new file with mode: 0644]
json_gssapi/src/CMakeLists.txt [new file with mode: 0644]
json_gssapi/src/GSSCommand.cpp [new file with mode: 0644]
json_gssapi/src/GSSCommand.h [new file with mode: 0644]
json_gssapi/src/GSSCreateSecContextCommand.cpp [new file with mode: 0644]
json_gssapi/src/GSSCreateSecContextCommand.h [new file with mode: 0644]
json_gssapi/src/util_json.cpp [new file with mode: 0644]
json_gssapi/src/util_json.h [new file with mode: 0644]
json_gssapi/test/CMakeLists.txt [new file with mode: 0644]
json_gssapi/test/GSSCreateSecContextTest.cpp [new file with mode: 0644]
json_gssapi/test/GSSCreateSecContextTest.h [new file with mode: 0644]
json_gssapi/test/InitSecContextMock.cpp [new file with mode: 0644]
json_gssapi/test/InitSecContextMock.h [new file with mode: 0644]
json_gssapi/test/JSONParseTest.cpp [new file with mode: 0644]
json_gssapi/test/JSONParseTest.h [new file with mode: 0644]
json_gssapi/test/test_run.cpp [new file with mode: 0644]

index 7b68788..cb2d217 100644 (file)
@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 2.8)
 
 project(json_gssapi)
 
-add_executable(json_gssapi src/GSSCreateSecContextCommand.cpp src/GSSCommand.cpp main.cpp)
-target_link_libraries(json_gssapi gss)
+add_executable(json_gssapi src/GSSCreateSecContextCommand.cpp src/GSSCommand.cpp src/util_json.cpp main.cpp)
+target_link_libraries(json_gssapi gssapi_krb5 jansson)
 
 
 set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules/")
diff --git a/json_gssapi/cmake_modules/FindCPPUNIT.cmake b/json_gssapi/cmake_modules/FindCPPUNIT.cmake
new file mode 100644 (file)
index 0000000..4ee0094
--- /dev/null
@@ -0,0 +1,54 @@
+#
+# Find the CppUnit includes and library
+#
+# This module defines
+# CPPUNIT_INCLUDE_DIR, where to find tiff.h, etc.
+# CPPUNIT_LIBRARIES, the libraries to link against to use CppUnit.
+# CPPUNIT_FOUND, If false, do not try to use CppUnit.
+
+# also defined, but not for general use are
+# CPPUNIT_LIBRARY, where to find the CppUnit library.
+# CPPUNIT_DEBUG_LIBRARY, where to find the CppUnit library in debug
+# mode.
+
+SET(CPPUNIT_FOUND "NO")
+
+FIND_PATH(CPPUNIT_INCLUDE_DIR cppunit/TestCase.h /usr/local/include /usr/include)
+
+# With Win32, important to have both
+IF(WIN32)
+  FIND_LIBRARY(CPPUNIT_LIBRARY cppunit
+               ${CPPUNIT_INCLUDE_DIR}/../lib
+               /usr/local/lib
+               /usr/lib)
+  FIND_LIBRARY(CPPUNIT_DEBUG_LIBRARY cppunitd
+               ${CPPUNIT_INCLUDE_DIR}/../lib
+               /usr/local/lib
+               /usr/lib)
+ELSE(WIN32)
+  # On unix system, debug and release have the same name
+  FIND_LIBRARY(CPPUNIT_LIBRARY cppunit
+               ${CPPUNIT_INCLUDE_DIR}/../lib
+               /usr/local/lib
+               /usr/lib)
+  FIND_LIBRARY(CPPUNIT_DEBUG_LIBRARY cppunit
+               ${CPPUNIT_INCLUDE_DIR}/../lib
+               /usr/local/lib
+               /usr/lib)
+ENDIF(WIN32)
+
+IF(CPPUNIT_INCLUDE_DIR)
+  IF(CPPUNIT_LIBRARY)
+    SET(CPPUNIT_FOUND "YES")
+    SET(CPPUNIT_LIBRARIES ${CPPUNIT_LIBRARY} ${CMAKE_DL_LIBS})
+    SET(CPPUNIT_DEBUG_LIBRARIES ${CPPUNIT_DEBUG_LIBRARY} ${CMAKE_DL_LIBS})
+  ELSE (CPPUNIT_LIBRARY)
+    IF (CPPUNIT_FIND_REQUIRED)
+      MESSAGE(SEND_ERROR "Could not find library CppUnit.")
+    ENDIF (CPPUNIT_FIND_REQUIRED)
+  ENDIF(CPPUNIT_LIBRARY)
+ELSE(CPPUNIT_INCLUDE_DIR)
+  IF (CPPUNIT_FIND_REQUIRED)
+    MESSAGE(SEND_ERROR "Could not find library CppUnit.")
+  ENDIF(CPPUNIT_FIND_REQUIRED)
+ENDIF(CPPUNIT_INCLUDE_DIR)
diff --git a/json_gssapi/src/CMakeLists.txt b/json_gssapi/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/json_gssapi/src/GSSCommand.cpp b/json_gssapi/src/GSSCommand.cpp
new file mode 100644 (file)
index 0000000..22993da
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+#include "GSSCommand.h"
diff --git a/json_gssapi/src/GSSCommand.h b/json_gssapi/src/GSSCommand.h
new file mode 100644 (file)
index 0000000..20955af
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+#ifndef GSSCOMMAND_H
+#define GSSCOMMAND_H
+
+#include "util_json.h"
+#include <iostream>
+
+class GSSCommand
+{
+public:
+  GSSCommand() {};
+  GSSCommand(void *fn) : function(fn) {};
+  GSSCommand(JSONObject params, void *fn) : parameters(params), function(fn) { };
+  
+  void *getGSSFunction() { return function; };
+  virtual void execute() { std::cout << "\ninside GSSCommand::invoke()\n"; };  
+protected:
+  void *function;
+  JSONObject parameters;
+};
+
+#endif // GSSCOMMAND_H
diff --git a/json_gssapi/src/GSSCreateSecContextCommand.cpp b/json_gssapi/src/GSSCreateSecContextCommand.cpp
new file mode 100644 (file)
index 0000000..94719d1
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+#include "GSSCreateSecContextCommand.h"
+#include <gssapi.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef OM_uint32 (*init_sec_context)(
+    OM_uint32 *,        /* minor_status */
+    gss_cred_id_t,      /* claimant_cred_handle */
+    gss_ctx_id_t *,     /* context_handle */
+    gss_name_t,         /* target_name */
+    gss_OID,            /* mech_type (used to be const) */
+    OM_uint32,          /* req_flags */
+    OM_uint32,          /* time_req */
+    gss_channel_bindings_t,     /* input_chan_bindings */
+    gss_buffer_t,       /* input_token */
+    gss_OID *,          /* actual_mech_type */
+    gss_buffer_t,       /* output_token */
+    OM_uint32 *,        /* ret_flags */
+    OM_uint32 *         /* time_req */
+);
+
+/* Helper function - import the OID from a string */
+gss_OID str_to_oid(const char *mech_type_str = NULL)
+{
+  /* Variables */
+  gss_buffer_t gssbuffOID;
+  gss_OID gssoidTargetOID;
+  OM_uint32 major;
+  OM_uint32 minor;
+  
+  /* Error checking */
+  if (mech_type_str == NULL ||
+      *mech_type_str == 0)
+    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);
+  major = gss_str_to_oid(&minor, 
+                        gssbuffOID, 
+                        &gssoidTargetOID);
+  if (major != GSS_S_COMPLETE)
+    throw "Error converting string to OID: " + minor;
+
+  /* Cleanup */
+  free(gssbuffOID);
+  
+  /* Return */
+  return gssoidTargetOID;
+}
+
+void
+GSSCreateSecContextCommand::execute()
+{
+  init_sec_context fn = (init_sec_context)function;
+  
+  input_token = GSS_C_NO_BUFFER;
+  output_token = (gss_buffer_t)malloc(sizeof(gss_buffer_desc));
+  
+  retVal = fn(
+    &minor_status,
+    GSS_C_NO_CREDENTIAL,
+    &context_handle,
+    target_name,
+    mech_type,
+    req_flags,
+    time_req,
+    GSS_C_NO_CHANNEL_BINDINGS,
+    input_token,
+    &actual_mech_type,
+    output_token,
+    &ret_flags,
+    &time_rec);
+}
+
+const char* GSSCreateSecContextCommand::getTargetDisplayName()
+{
+  /* Variables */
+  gss_buffer_t output_name;
+  gss_OID output_type;
+  OM_uint32 major, minor;
+  const char *ret;
+  
+  /* 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);
+  if (major == GSS_S_COMPLETE)
+    ret = (const char *)output_name->value;
+  else
+    ret = NULL;
+  
+  /* cleanup */
+  free(output_name);
+  free(output_type);
+  
+  /* return */
+  return( (char *)(output_name->value) );
+}
+
+const char* GSSCreateSecContextCommand::getMechType()
+{
+  gss_buffer_t output;
+  OM_uint32 major, minor;
+  const char *retVal;
+
+  /* error checking */
+  if (mech_type == NULL)
+    return NULL;
+
+  /* Setup */  
+  output = (gss_buffer_t)malloc(sizeof(gss_buffer_desc_struct));
+  
+  /* main */
+  major = gss_oid_to_str(&minor, mech_type, output);
+  if (major == GSS_S_COMPLETE)
+    retVal = (const char *)output->value;
+  else
+    retVal = NULL;
+  
+  /* cleanup */
+  free(output);
+  
+  /* return */
+  return( retVal );
+}
+
+bool GSSCreateSecContextCommand::loadParameters(JSONObject *params)
+{
+  /* Variables */
+  OM_uint32 major, minor;
+  gss_buffer_t gssbuffTargetName;
+  const char *buffer;
+  
+  /* Error checking */
+  // Should I zeroOut?
+  
+  /* Setup */
+  
+  /* Main processing */
+  // Easy stuff
+  this->time_req = (OM_uint32)( (*params)["time_req"].integer() );
+  this->req_flags = (OM_uint32)( (*params)["req_flags"].integer() );
+  
+  // context_handle
+  //   -- just treat the value passed in as correct.
+  context_handle = (gss_ctx_id_t)( (*params)["context_handle"].integer() );
+  
+  // target_name
+  buffer = (*params)["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 );
+    
+    major = gss_import_name(&minor, 
+                           gssbuffTargetName, 
+                           GSS_C_NO_OID, 
+                           &target_name);
+    if (major != GSS_S_COMPLETE)
+      throw "Error importing target_name: " + minor;
+    
+    free(gssbuffTargetName);
+  }
+  
+  // mech_type  
+  mech_type = str_to_oid( (*params)["mech_type"].string() );
+  
+  // input_token
+  buffer = (*params)["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);
+  }
+  
+  /* Cleanup */
+  
+  
+  /* Return */
+  return true;
+}
+
+bool GSSCreateSecContextCommand::zeroOut(bool initialized)
+{
+  /* Error checking */
+  /* Variables */
+  OM_uint32 minor;
+  gss_buffer_t 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);
+    
+    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->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 );
+    }
+  }
+
+  // Now set things to reasonable defaults
+  this->retVal = 0;
+  this->minor_status = 0;
+  this->req_flags = 0;
+  this->time_req = 0;
+  this->ret_flags = 0;
+  this->time_rec = 0;
+
+  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->actual_mech_type = GSS_C_NO_OID;
+  this->output_token = GSS_C_NO_BUFFER;
+  memset((void *)&(this->parameters), 0, sizeof(JSONObject));
+
+  /* Cleanup */
+  free(output);
+  
+  /* Return */
+  return(true);
+}
+
+GSSCreateSecContextCommand::GSSCreateSecContextCommand(
+  JSONObject *params, 
+  void *fn) : GSSCommand(params, fn)
+{
+  zeroOut(false);
+  loadParameters(params);
+}
+
+GSSCreateSecContextCommand::GSSCreateSecContextCommand(void *fn) : GSSCommand(fn)
+{
+  zeroOut(false);
+}
\ No newline at end of file
diff --git a/json_gssapi/src/GSSCreateSecContextCommand.h b/json_gssapi/src/GSSCreateSecContextCommand.h
new file mode 100644 (file)
index 0000000..4eb1bdf
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+#ifndef GSSCREATESECCONTEXTCOMMAND_H
+#define GSSCREATESECCONTEXTCOMMAND_H
+
+#include "GSSCommand.h"
+#include <gssapi.h>
+
+class GSSCreateSecContextCommand : public GSSCommand
+{
+public:
+
+    OM_uint32 retVal;
+    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_t input_token;
+    gss_OID actual_mech_type;
+    gss_buffer_t output_token;
+    OM_uint32 ret_flags;
+    OM_uint32 time_rec;
+    
+  
+    void execute();
+    GSSCreateSecContextCommand(void *fn = (void *)&gss_init_sec_context);
+    GSSCreateSecContextCommand(JSONObject *params, void *fn = (void *)&gss_init_sec_context);
+    
+    bool loadParameters(JSONObject *params);
+    bool zeroOut(bool initialized = true);
+    
+    
+    // accessors
+    OM_uint32 getReqFlags() { return req_flags; }
+    OM_uint32 getTimeReq() { return time_req; }
+    gss_ctx_id_t getContextHandle() { return context_handle; }
+    
+    // complex accessors
+    const char * getTargetDisplayName();
+    const char * getMechType();
+    
+private:
+};
+
+#endif // GSSCREATESECCONTEXTCOMMAND_H
diff --git a/json_gssapi/src/util_json.cpp b/json_gssapi/src/util_json.cpp
new file mode 100644 (file)
index 0000000..dbd453e
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2011, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * JSONObject utilities.
+ */
+
+#include "util_json.h"
+
+#include <typeinfo>
+#include <string>
+#include <sstream>
+#include <exception>
+#include <new>
+
+#define JSON_INIT(obj) do {                                     \
+        if ((obj) == NULL)                                      \
+            throw std::bad_alloc();                             \
+        m_obj = (obj);                                          \
+    } while (0)
+
+#define JSON_CHECK_CONTAINER() do {                             \
+        if (!json_is_object(m_obj) && !json_is_array(m_obj)) {  \
+            std::string s("JSONObject is not a container");     \
+            throw JSONException(m_obj);                         \
+        }                                                       \
+    } while (0)
+
+#define JSON_CHECK_OBJECT() do {                                \
+        if (!json_is_object(m_obj)) {                           \
+            std::string s("JSONObject is not a dictionary");    \
+            throw JSONException(m_obj, JSON_OBJECT);            \
+        }                                                       \
+    } while (0)
+
+#define JSON_CHECK_ARRAY() do {                                 \
+        if (!json_is_array(m_obj)) {                            \
+            throw JSONException(m_obj, JSON_ARRAY);             \
+        }                                                       \
+    } while (0)
+
+#define JSON_CHECK(s) do {                                      \
+        if ((s) != 0)                                           \
+            throw JSONException();                              \
+    } while (0)
+
+JSONObject
+JSONObject::load(const char *input, size_t flags, json_error_t *error)
+{
+    json_t *obj;
+
+    obj = json_loads(input, flags, error);
+
+    return JSONObject(obj, false);
+}
+
+JSONObject
+JSONObject::load(FILE *fp, size_t flags, json_error_t *error)
+{
+    json_t *obj;
+
+    obj = json_loadf(fp, flags, error);
+
+    return JSONObject(obj, false);
+}
+
+char *
+JSONObject::dump(size_t flags) const
+{
+    char *s = json_dumps(m_obj, flags);
+
+    if (s == NULL)
+        throw std::bad_alloc();
+
+    return s;
+}
+
+void
+JSONObject::dump(FILE *fp, size_t flags) const
+{
+    int r = json_dumpf(m_obj, fp, flags);
+
+    if (r != 0)
+        throw std::bad_alloc();
+}
+
+size_t
+JSONObject::size(void) const
+{
+    if (json_is_object(m_obj))
+        return json_object_size(m_obj);
+    else if (json_is_array(m_obj))
+        return json_array_size(m_obj);
+    else
+        return 0;
+}
+
+JSONObject::JSONObject(json_t *obj, bool retain)
+{
+    if (retain)
+        json_incref(obj);
+    JSON_INIT(obj);
+}
+
+JSONObject::JSONObject(const char *value)
+{
+    json_t *obj = json_string(value);
+
+    JSON_INIT(obj);
+}
+
+JSONObject::JSONObject(json_int_t value)
+{
+    json_t *obj = json_integer(value);
+
+    JSON_INIT(obj);
+}
+
+JSONObject::JSONObject(double value)
+{
+    json_t *obj = json_real(value);
+
+    JSON_INIT(obj);
+}
+
+JSONObject::JSONObject(bool value)
+{
+    json_t *obj = value ? json_true() : json_false();
+
+    JSON_INIT(obj);
+}
+
+JSONObject::JSONObject(void)
+{
+    json_t *obj = json_object();
+
+    JSON_INIT(obj);
+}
+
+JSONObject
+JSONObject::object(void)
+{
+    return JSONObject();
+}
+
+JSONObject
+JSONObject::null(void)
+{
+    return JSONObject(json_null(), false);
+}
+
+JSONObject
+JSONObject::array(void)
+{
+    return JSONObject(json_array(), false);
+}
+
+void
+JSONObject::set(const char *key, JSONObject &value)
+{
+    JSON_CHECK_OBJECT();
+    JSON_CHECK(json_object_set_new(m_obj, key, value.get()));
+}
+
+void
+JSONObject::set(const char *key, const char *value)
+{
+    JSONObject jobj(value);
+    set(key, jobj);
+}
+
+void
+JSONObject::set(const char *key, json_int_t value)
+{
+    JSONObject jobj(value);
+    set(key, jobj);
+}
+
+void
+JSONObject::del(const char *key)
+{
+    json_object_del(m_obj, key);
+}
+
+JSONObject
+JSONObject::get(const char *key) const
+{
+    json_t *obj;
+
+    obj = json_object_get(m_obj, key);
+    if (obj == NULL)
+        return JSONObject::null();
+
+    return JSONObject(obj, true);
+}
+
+JSONObject
+JSONObject::get(size_t index) const
+{
+    json_t *obj;
+
+    obj = json_array_get(m_obj, index);
+    if (obj == NULL)
+        return JSONObject::null();
+
+    return JSONObject(obj, true);
+}
+
+void
+JSONObject::update(JSONObject &value)
+{
+    JSON_CHECK_OBJECT();
+    json_t *other = value.get();
+    JSON_CHECK(json_object_update(m_obj, other));
+    json_decref(other);
+}
+
+JSONObject
+JSONObject::operator[](size_t index) const
+{
+    return get(index);
+}
+
+JSONObject
+JSONObject::operator[](const char *key) const
+{
+    return get(key);
+}
+
+void
+JSONObject::append(JSONObject &value)
+{
+    JSON_CHECK_ARRAY();
+    JSON_CHECK(json_array_append_new(m_obj, value.get()));
+}
+
+void
+JSONObject::insert(size_t index, JSONObject &value)
+{
+    JSON_CHECK_ARRAY();
+    JSON_CHECK(json_array_insert_new(m_obj, index, value.get()));
+}
+
+void
+JSONObject::remove(size_t index)
+{
+    JSON_CHECK_ARRAY();
+    JSON_CHECK(json_array_remove(m_obj, index));
+}
+
+void
+JSONObject::clear(void)
+{
+    JSON_CHECK_CONTAINER();
+
+    if (json_is_object(m_obj)) {
+        JSON_CHECK(json_object_clear(m_obj));
+    } else if (json_is_array(m_obj)) {
+        JSON_CHECK(json_array_clear(m_obj));
+    }
+}
+
+void
+JSONObject::extend(JSONObject &value)
+{
+    JSON_CHECK_ARRAY();
+    json_t *other = value.get();
+    JSON_CHECK(json_array_extend(m_obj, other));
+    json_decref(other);
+}
+
+const char *
+JSONObject::string(void) const
+{
+    return json_string_value(m_obj);
+}
+
+json_int_t
+JSONObject::integer(void) const
+{
+    return json_integer_value(m_obj);
+}
+
+double
+JSONObject::real(void) const
+{
+    return json_real_value(m_obj);
+}
+
+double
+JSONObject::number(void) const
+{
+    return json_number_value(m_obj);
+}
+
+bool JSONObject::isObject(void) const
+{
+    return json_is_object(m_obj);
+}
+
+bool JSONObject::isArray(void) const
+{
+    return json_is_array(m_obj);
+}
+
+bool JSONObject::isString(void) const
+{
+    return json_is_string(m_obj);
+}
+
+bool JSONObject::isInteger(void) const
+{
+    return json_is_integer(m_obj);
+}
+
+bool JSONObject::isNumber(void) const
+{
+    return json_is_number(m_obj);
+}
+
+bool JSONObject::isBoolean(void) const
+{
+    return json_is_boolean(m_obj);
+}
+
+bool JSONObject::isNull(void) const
+{
+    return json_is_null(m_obj);
+}
+
+JSONIterator::JSONIterator(const JSONObject &obj)
+{
+    m_obj = obj.get();
+    m_iter = json_object_iter(m_obj);
+}
+
+JSONIterator::~JSONIterator(void)
+{
+    json_decref(m_obj);
+}
+
+const char *
+JSONIterator::key(void) const
+{
+    return json_object_iter_key(m_iter);
+}
+
+JSONObject
+JSONIterator::value(void) const
+{
+    return JSONObject(json_object_iter_value(m_iter));
+}
+
+bool
+JSONIterator::next(void)
+{
+    m_iter = json_object_iter_next(m_obj, m_iter);
+    return m_iter != NULL;
+}
+
+JSONException::JSONException(json_t *obj, json_type type)
+{
+    char *s = NULL;
+    const char *t;
+
+    m_obj = json_incref(obj);
+    m_type = type;
+
+    if (obj != NULL)
+        s = json_dumps(m_obj, 0);
+
+    switch (type) {
+    case JSON_OBJECT:   t = "OBJECT";   break;
+    case JSON_ARRAY:    t = "ARRAY";    break;
+    case JSON_STRING:   t = "STRING";   break;
+    case JSON_INTEGER:  t = "INTEGER";  break;
+    case JSON_REAL:     t = "REAL";     break;
+    case JSON_TRUE:     t = "TRUE";     break;
+    case JSON_FALSE:    t = "FALSE";    break;
+    case JSON_NULL:     t = "NULL";     break;
+    default:            t = "UNKNOWN";  break;
+    }
+
+    if (obj != NULL) {
+        m_reason = "Invalid JSON object: " + std::string(s);
+        if (type != JSON_NULL)
+            m_reason += " (excepted type " + std::string(t) + ")";
+    } else {
+        m_reason = "Internal JSON error";
+    }
+
+    if (s != NULL)
+        free(s);
+}
diff --git a/json_gssapi/src/util_json.h b/json_gssapi/src/util_json.h
new file mode 100644 (file)
index 0000000..c9358df
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2011, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * JSON object wrapper with not-entirely-toll-free DDF bridging.
+ */
+
+#ifndef _UTIL_JSON_H_
+#define _UTIL_JSON_H_ 1
+
+#ifdef __cplusplus
+#include <string>
+#include <new>
+
+#include <jansson.h>
+
+
+class JSONObject;
+
+class JSONException : public std::exception {
+public:
+    JSONException(json_t *obj = NULL, json_type type = JSON_NULL);
+
+    ~JSONException(void) throw() {
+       json_decref(m_obj);
+    }
+
+    virtual const char *what(void) const throw() {
+       return m_reason.c_str();
+    }
+
+private:
+    json_t *m_obj;
+    json_type m_type;
+    std::string m_reason;
+};
+
+class JSONIterator {
+public:
+    JSONIterator(const JSONObject &obj);
+    ~JSONIterator(void);
+    const char *key(void) const;
+    JSONObject value(void) const;
+    bool next(void);
+
+private:
+    json_t *m_obj;
+    void *m_iter;
+};
+
+class JSONObject {
+public:
+    static JSONObject load(const char *input, size_t flags, json_error_t *error);
+    static JSONObject load(FILE *, size_t flags, json_error_t *error);
+
+    static JSONObject object(void);
+    static JSONObject array(void);
+    static JSONObject null(void);
+
+    char *dump(size_t flags = 0) const;
+    void dump(FILE *fp, size_t flags = JSON_INDENT(4)) const;
+
+    json_type type(void) const { return json_typeof(m_obj); }
+    size_t size(void) const;
+
+    JSONObject(void);
+    JSONObject(const char *value);
+    JSONObject(json_int_t value);
+    JSONObject(double value);
+    JSONObject(bool value);
+
+    void set(const char *key, JSONObject &value);
+    void set(const char *key, const char *value);
+    void set(const char *key, json_int_t value);
+    void del(const char *key);
+    void update(JSONObject &value);
+    JSONIterator iterator(void) const { return JSONIterator(*this); }
+    JSONObject get(const char *key) const;
+    JSONObject operator[](const char *key) const;
+
+    JSONObject get(size_t index) const;
+    JSONObject operator[](size_t index) const;
+    void append(JSONObject &value);
+    void insert(size_t index, JSONObject &value);
+    void remove(size_t index);
+    void clear(void);
+    void extend(JSONObject &value);
+
+    const char *string(void) const;
+    json_int_t integer(void) const;
+    double real(void) const;
+    double number(void) const;
+#ifdef HAVE_SHIBRESOLVER
+    DDF ddf(void) const;
+#endif
+
+    bool isObject(void) const;
+    bool isArray(void) const;
+    bool isString(void) const;
+    bool isInteger(void) const;
+    bool isNumber(void) const;
+    bool isBoolean(void) const;
+    bool isNull(void) const;
+
+    ~JSONObject(void)
+    {
+       if (m_obj != NULL)
+           json_decref(m_obj);
+    }
+
+    JSONObject(const JSONObject &obj)
+    {
+       m_obj = json_incref(obj.m_obj);
+    }
+
+    JSONObject& operator=(const JSONObject &obj)
+    {
+       if (this != &obj)
+           set(obj.m_obj);
+       return *this;
+    }
+
+private:
+    friend class JSONIterator;
+
+    json_t *get(void) const {
+       return json_incref(m_obj);
+    }
+
+    void set(json_t *obj) {
+       if (m_obj != obj) {
+           json_decref(m_obj);
+           m_obj = json_incref(m_obj);
+       }
+    }
+
+    JSONObject(json_t *obj, bool retain = true);
+
+    json_t *m_obj;
+};
+
+
+#endif /* __cplusplus */
+
+#endif /* _UTIL_JSON_H_ */
diff --git a/json_gssapi/test/CMakeLists.txt b/json_gssapi/test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f43e6e5
--- /dev/null
@@ -0,0 +1,7 @@
+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)
+
+target_link_libraries(test cppunit gssapi_krb5 jansson)
+
+# install(TARGETS test RUNTIME DESTINATION bin)
diff --git a/json_gssapi/test/GSSCreateSecContextTest.cpp b/json_gssapi/test/GSSCreateSecContextTest.cpp
new file mode 100644 (file)
index 0000000..0cf7ad5
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+
+#include "GSSCreateSecContextTest.h"
+#include "GSSCreateSecContextCommand.h"
+#include "InitSecContextMock.h"
+#include <iostream>
+#include <string.h>
+#include <exception>
+#include "util_json.h"
+
+// Registers the fixture into the 'registry'
+CPPUNIT_TEST_SUITE_REGISTRATION( GSSCreateSecContextTest );
+
+
+
+OM_uint32 KRB5_CALLCONV
+mock_init_sec(
+    OM_uint32             *minor_status,
+    gss_cred_id_t          claimant_cred_handle,
+    gss_ctx_id_t          *context_handle,
+    gss_name_t             target_name,
+    gss_OID                mech_type,
+    OM_uint32              req_flags,
+    OM_uint32              time_req,
+    gss_channel_bindings_t input_chan_bindings,
+    gss_buffer_t           input_token,
+    gss_OID               *actual_mech_type,
+    gss_buffer_t           output_token,
+    OM_uint32             *ret_flags,
+    OM_uint32             *time_rec)
+{
+  InitSecContextMock::visited = true;
+  
+  /* Copy in the input to this function */
+  InitSecContextMock::claimant_cred_handle = claimant_cred_handle;
+  InitSecContextMock::target_name = target_name;
+  InitSecContextMock::mech_type = mech_type;
+  InitSecContextMock::req_flags = req_flags;
+  InitSecContextMock::time_req = time_req;
+  InitSecContextMock::input_chan_bindings = input_chan_bindings;
+  InitSecContextMock::input_token = input_token;
+  
+  /* 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;
+  *ret_flags = InitSecContextMock::ret_flags;
+  *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;
+  }
+
+  return InitSecContextMock::retVal;
+}
+
+
+void
+GSSCreateSecContextTest::setUp()
+{
+  InitSecContextMock::reset();
+}
+
+void
+GSSCreateSecContextTest::tearDown()
+{
+}
+
+void
+GSSCreateSecContextTest::testConstructor()
+{
+  GSSCreateSecContextCommand cmd = GSSCreateSecContextCommand();
+  void *cmdFn;
+  void *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);
+}
+
+
+void GSSCreateSecContextTest::testConstructorWithJSONObject()
+{
+  const char* input = "{\"req_flags\": \"1\", \
+    \"time_req\": \"2\", \
+    \"mech_type\": \"{ 1 2 840 113554 1 2 1 4 }\", \
+    \"target_name\": \"me@my.sha/DOW\"}";
+
+  json_error_t jsonErr;
+  JSONObject json = JSONObject::load(input, 0, &jsonErr);
+  
+  GSSCreateSecContextCommand cmd = GSSCreateSecContextCommand(
+    &json, 
+    (void *)&mock_init_sec
+  );
+  
+  
+  const char *from_json = json["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 )
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The context_handle values differ.",
+    json["context_handle"].integer(),
+    (json_int_t)cmd.getContextHandle()
+  );
+  
+  CPPUNIT_ASSERT_MESSAGE(
+    "The mech_type values differ.",
+    ( strcmp(json["mech_type"].string(), cmd.getMechType()) == 0 )
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The req_flags differ.",
+    (int)json["req_flags"].integer(),
+    (int)cmd.getReqFlags()
+  );
+  
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The req_flags differ.",
+    (int)json["time_req"].integer(),
+    (int)cmd.getTimeReq()
+  );
+  
+  
+}
+
+void
+GSSCreateSecContextTest::testEmptyCall()
+{
+  GSSCreateSecContextCommand cmd ((void *)&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 )
+  );
+  
+  
+  
+  /* 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::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::ret_flags = rand() % 1024;
+  InitSecContextMock::time_req = rand() % 1024;
+  
+  cmd.execute();
+  
+  /* Check that init_sec_context's inputs are sent correctly */
+  CPPUNIT_ASSERT_MESSAGE(
+    "The GSS function was not invoked!",
+    InitSecContextMock::visited
+  );
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The time_req field was not used in the call to init_sec_context",
+    cmd.time_req,
+    InitSecContextMock::time_req
+  );
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The req_flags field was not used in the call to init_sec_context",
+    cmd.req_flags,
+    InitSecContextMock::req_flags
+  );
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The mech_type field was not used in the call to init_sec_context",
+    cmd.mech_type,
+    InitSecContextMock::mech_type
+  );
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "The target_name field was not used in the call to init_sec_context",
+    cmd.target_name,
+    InitSecContextMock::target_name
+  );
+  
+  
+  /* Check that init_sec_context's outputs are captured correctly */
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "Return value was not copied back to the command.",
+    InitSecContextMock::retVal,
+    cmd.retVal
+  );
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "Status was not copied back to the command.",
+    InitSecContextMock::minor_status,
+    cmd.minor_status
+  );
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "context_handle was not copied back to the command.",
+    InitSecContextMock::context_handle,
+    cmd.context_handle
+  );
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "actual_mech_type was not copied back to the command.",
+    InitSecContextMock::actual_mech_type,
+    cmd.actual_mech_type
+  );
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "output_token was not copied back to the command.",
+    InitSecContextMock::output_token->value,
+    cmd.output_token->value
+  );
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "ret_flags was not copied back to the command.",
+    InitSecContextMock::ret_flags,
+    cmd.ret_flags
+  );
+  CPPUNIT_ASSERT_EQUAL_MESSAGE(
+    "time_rec was not copied back to the command.",
+    InitSecContextMock::time_rec,
+    cmd.time_rec
+  );
+}
+
diff --git a/json_gssapi/test/GSSCreateSecContextTest.h b/json_gssapi/test/GSSCreateSecContextTest.h
new file mode 100644 (file)
index 0000000..e2cb910
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+#ifndef GSSCREATESECCONTEXTTEST_H
+#define GSSCREATESECCONTEXTTEST_H
+
+// #include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <gssapi.h>
+#include "GSSCreateSecContextCommand.h"
+
+#include <stdlib.h>
+
+class GSSCreateSecContextTest :  public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( GSSCreateSecContextTest );
+  CPPUNIT_TEST( testConstructor );
+  CPPUNIT_TEST( testConstructorWithJSONObject );
+  CPPUNIT_TEST( testEmptyCall );
+  CPPUNIT_TEST_SUITE_END();
+  
+  
+  
+public:
+  void setUp();
+  void tearDown();
+
+  
+  void testConstructor();
+  void testConstructorWithJSONObject();
+  void testEmptyCall();
+  
+private:
+  GSSCreateSecContextCommand command;
+};
+
+#endif // GSSCREATESECCONTEXTTEST_H
diff --git a/json_gssapi/test/InitSecContextMock.cpp b/json_gssapi/test/InitSecContextMock.cpp
new file mode 100644 (file)
index 0000000..b18df38
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+#include "InitSecContextMock.h"
+#include <stdio.h>
+
+OM_uint32 InitSecContextMock::retVal = 0;
+OM_uint32 InitSecContextMock::minor_status = 0;
+OM_uint32 InitSecContextMock::req_flags = 0;
+OM_uint32 InitSecContextMock::time_req = 0;
+OM_uint32 InitSecContextMock::ret_flags = 0;
+OM_uint32 InitSecContextMock::time_rec = 0;
+
+bool InitSecContextMock::visited = false;
+bool InitSecContextMock::invalidContextHandle = false;
+
+gss_cred_id_t InitSecContextMock::claimant_cred_handle = NULL;
+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_OID       InitSecContextMock::actual_mech_type = NULL;
+gss_buffer_t  InitSecContextMock::output_token = NULL;
+
+void InitSecContextMock::reset()
+{
+  retVal = 0;
+  minor_status = 0;
+  nullify((void **)&claimant_cred_handle);
+  nullify((void **)&context_handle);
+  nullify((void **)&target_name);
+  nullify((void **)&mech_type);
+  req_flags = 0;
+  time_req = 0;
+  nullify((void **)&input_chan_bindings);
+  nullify((void **)&input_token);
+  nullify((void **)&actual_mech_type);
+  nullify((void **)&output_token);
+  ret_flags = 0;
+  time_rec = 0;
+  visited = false;
+  invalidContextHandle = false;
+
+}
diff --git a/json_gssapi/test/InitSecContextMock.h b/json_gssapi/test/InitSecContextMock.h
new file mode 100644 (file)
index 0000000..171bb41
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ * 
+ * For license details, see the LICENSE file in the root of this project.
+ * 
+ */
+
+#ifndef INITSECCONTEXTMOCK_H
+#define INITSECCONTEXTMOCK_H
+
+#include <gssapi.h>
+#include <stdlib.h>
+#include <iostream>
+
+class InitSecContextMock
+{
+public:
+  static OM_uint32              retVal;
+  static OM_uint32              minor_status;
+  static gss_cred_id_t          claimant_cred_handle;
+  static gss_ctx_id_t           context_handle;
+  static gss_name_t             target_name;
+  static gss_OID                mech_type;
+  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_OID                actual_mech_type;
+  static gss_buffer_t           output_token;
+  static OM_uint32              ret_flags;
+  static OM_uint32              time_rec;
+  
+  static bool                   visited;
+  static bool                   invalidContextHandle;
+  
+  static void nullify(void **ptr)
+  {
+    if (!ptr)
+    {
+      std::cout << std::endl << "Nullify called with a void ** that is NULL at the top level" << std::endl;
+      return;
+    }
+    if (*ptr)
+    {
+      free(*ptr);
+      *ptr = NULL;
+    }
+  }
+
+  static void reset();
+};
+
+#endif // INITSECCONTEXTMOCK_H
diff --git a/json_gssapi/test/JSONParseTest.cpp b/json_gssapi/test/JSONParseTest.cpp
new file mode 100644 (file)
index 0000000..ef51470
--- /dev/null
@@ -0,0 +1,23 @@
+#include "JSONParseTest.h"
+
+// Registers the fixture into the 'registry'
+CPPUNIT_TEST_SUITE_REGISTRATION( JSONParseTest );
+
+
+void 
+JSONParseTest::setUp()
+{
+}
+
+
+void 
+JSONParseTest::tearDown()
+{
+}
+
+
+void 
+JSONParseTest::testConstructor()
+{
+//   CPPUNIT_FAIL( "not implemented, go away" );
+}
\ No newline at end of file
diff --git a/json_gssapi/test/JSONParseTest.h b/json_gssapi/test/JSONParseTest.h
new file mode 100644 (file)
index 0000000..846b263
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef JSONPARSETEST_H
+#define JSONPARSETEST_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class JSONParseTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( JSONParseTest );
+  CPPUNIT_TEST( testConstructor );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void setUp();
+  void tearDown();
+
+  void testConstructor();
+};
+
+#endif  // JSONPARSETEST_H
\ No newline at end of file
diff --git a/json_gssapi/test/test_run.cpp b/json_gssapi/test/test_run.cpp
new file mode 100644 (file)
index 0000000..084feeb
--- /dev/null
@@ -0,0 +1,24 @@
+// ? #include "stdafx.h"
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+
+
+int main(int argc, char* argv[])
+{
+  // Get the top level suite from the registry
+  CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
+
+  // Adds the test to the list of test to run
+  CppUnit::TextUi::TestRunner runner;
+  runner.addTest( suite );
+
+  // Change the default outputter to a compiler error format outputter
+  runner.setOutputter( new CppUnit::CompilerOutputter( &runner.result(),
+                                                       std::cerr ) );
+  // Run the tests.
+  bool wasSucessful = runner.run();
+
+  // Return error code 1 if the one of test failed.
+  return wasSucessful ? 0 : 1;
+}