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/")
--- /dev/null
+#
+# 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)
--- /dev/null
+/*
+ * Copyright (c) 2014 <copyright holder> <email>
+ *
+ * For license details, see the LICENSE file in the root of this project.
+ *
+ */
+
+#include "GSSCommand.h"
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+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)
--- /dev/null
+/*
+ * 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
+ );
+}
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+// ? #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;
+}