[submodule "openssh"]
path = openssh
url = http://www.project-moonshot.org/git/openssh.git
+[submodule "jansson"]
+ path = jansson
+ url = git://github.com/akheron/jansson.git
+ " -Wl,-rpath="+prefix+"/lib'",
'CPPFLAGS="-I '+prefix+'/include"',
'--with-system-libtool', '--with-system-libltdl',
- '--enable-tls',
+ '--enable-tls', '--with-gssapi='+prefix,
"--with-xmltooling="+prefix,
]
if options.configure_opts is not None:
--- /dev/null
+Subproject commit 279d8bf108bd1367bdd3647e881146e1acf0123d
-export-symbols mech_eap.exports -no-undefined \
@EAP_LDFLAGS@ @RADSEC_LDFLAGS@ @TARGET_LDFLAGS@
mech_eap_la_LIBADD = @KRB5_LIBS@ @EAP_LIBS@ @RADSEC_LIBS@ \
- @SHIBRESOLVER_LIBS@ @SHIBSP_LIBS@
+ @SHIBRESOLVER_LIBS@ @SHIBSP_LIBS@ @JANSSON_LIBS@
mech_eap_la_SOURCES = \
accept_sec_context.c \
unwrap_iov.c \
userok.c \
util_attr.cpp \
+ util_base64.c \
util_buffer.c \
util_context.c \
util_cksum.c \
util_cred.c \
util_crypt.c \
+ util_json.cpp \
util_krb.c \
util_lucid.c \
util_mech.c \
AC_SUBST(RADSEC_LIBS)
fi
])dnl
+
+AC_DEFUN([AX_CHECK_JANSSON],
+[AC_MSG_CHECKING(for jansson)
+JANSSON_DIR=
+found_jansson="no"
+AC_ARG_WITH(jansson,
+ AC_HELP_STRING([--with-jansson],
+ [Use jansson (in specified installation directory)]),
+ [check_jansson_dir="$withval"],
+ [check_jansson_dir=])
+for dir in $check_jansson_dir $prefix /usr /usr/local ; do
+ janssondir="$dir"
+ if test -f "$dir/include/jansson.h"; then
+ found_jansson="yes";
+ JANSSON_DIR="${janssondir}"
+ JANSSON_CFLAGS="-I$janssondir/include";
+ break;
+ fi
+done
+AC_MSG_RESULT($found_jansson)
+if test x_$found_jansson != x_yes; then
+ AC_MSG_ERROR([
+----------------------------------------------------------------------
+ Cannot find jansson libraries.
+
+ Please install libjansson or specify installation directory with
+ --with-jansson=(dir).
+----------------------------------------------------------------------
+])
+else
+ printf "jansson found in $janssondir\n";
+ JANSSON_LIBS="-ljansson";
+ JANSSON_LDFLAGS="-L$janssondir/lib";
+ AC_SUBST(JANSSON_CFLAGS)
+ AC_SUBST(JANSSON_LDFLAGS)
+ AC_SUBST(JANSSON_LIBS)
+fi
+])dnl
AX_CHECK_SHIBSP
AX_CHECK_SHIBRESOLVER
AX_CHECK_RADSEC
+AX_CHECK_JANSSON
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
if (ctx->acceptorCtx.radConn != NULL) {
if (rs_conn_get_current_peer(ctx->acceptorCtx.radConn,
serverBuf, sizeof(serverBuf)) != 0) {
+#if 0
return gssEapRadiusMapError(minor,
rs_err_conn_pop(ctx->acceptorCtx.radConn));
+#else
+ serverBuf[0] = '\0'; /* not implemented yet */
+#endif
}
serverLen = strlen(serverBuf);
}
return major;
}
-static OM_uint32
+OM_uint32
gssEapExportSecContext(OM_uint32 *minor,
gss_ctx_id_t ctx,
gss_buffer_t token)
if (GSS_ERROR(major))
goto cleanup;
}
+
if (ctx->acceptorName != GSS_C_NO_NAME) {
major = gssEapExportNameInternal(minor, ctx->acceptorName,
&acceptorName,
* The partial context is only transmitted for unestablished acceptor
* contexts.
*/
- if (!CTX_IS_INITIATOR(ctx) &&
- !CTX_IS_ESTABLISHED(ctx) &&
- ((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0)) {
- major = exportPartialRadiusContext(minor, ctx, &partialCtx);
+ if (!CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx) &&
+ (ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) {
+ major = gssEapExportPartialContext(minor, ctx, &partialCtx);
if (GSS_ERROR(major))
goto cleanup;
}
#define IS_WIRE_ERROR(err) ((err) > GSSEAP_RESERVED && \
(err) <= GSSEAP_RADIUS_PROT_FAILURE)
+/* export_sec_context.c */
+OM_uint32
+gssEapExportSecContext(OM_uint32 *minor,
+ gss_ctx_id_t ctx,
+ gss_buffer_t token);
+
+
#ifdef __cplusplus
}
#endif
gssEapSaslNameToOid(const gss_buffer_t name);
/* util_name.c */
-#define EXPORT_NAME_FLAG_OID 0x1
-#define EXPORT_NAME_FLAG_COMPOSITE 0x2
+#define EXPORT_NAME_FLAG_OID 0x1
+#define EXPORT_NAME_FLAG_COMPOSITE 0x2
OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName);
OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName);
OM_uint32 gssEapExportNameInternal(OM_uint32 *minor,
const gss_name_t name,
gss_buffer_t exportedName,
- unsigned int flags);
+ OM_uint32 flags);
OM_uint32 gssEapImportName(OM_uint32 *minor,
const gss_buffer_t input_name_buffer,
const gss_OID input_name_type,
OM_uint32 gssEapImportNameInternal(OM_uint32 *minor,
const gss_buffer_t input_name_buffer,
gss_name_t *output_name,
- unsigned int flags);
+ OM_uint32 flags);
OM_uint32
gssEapDuplicateName(OM_uint32 *minor,
const gss_name_t input_name,
}
#endif
+#include "util_json.h"
#include "util_attr.h"
+#include "util_base64.h"
#ifdef GSSEAP_ENABLE_REAUTH
#include "util_reauth.h"
#endif
#include <typeinfo>
#include <string>
+#include <sstream>
#include <exception>
+#include <stdexcept>
#include <new>
/* lazy initialisation */
return ret;
}
-#define UPDATE_REMAIN(n) do { \
- p += (n); \
- remain -= (n); \
- } while (0)
-
-#define CHECK_REMAIN(n) do { \
- if (remain < (n)) { \
- return false; \
- } \
- } while (0)
-
-/*
- * Initialize a context from an exported context or name token
- */
bool
-gss_eap_attr_ctx::initFromBuffer(const gss_buffer_t buffer)
+gss_eap_attr_ctx::initWithJsonObject(JSONObject &obj)
{
bool ret = false;
- size_t remain = buffer->length;
- unsigned char *p = (unsigned char *)buffer->value;
- bool didInit[ATTR_TYPE_MAX + 1];
+ bool foundSource[ATTR_TYPE_MAX + 1];
unsigned int type;
for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++)
- didInit[type] = false;
-
- /* flags */
- CHECK_REMAIN(4);
- m_flags = load_uint32_be(p);
- UPDATE_REMAIN(4);
+ foundSource[type] = false;
- while (remain) {
- OM_uint32 type;
- gss_buffer_desc providerToken;
- gss_eap_attr_provider *provider;
-
- /* TLV encoding of provider type, length, value */
- CHECK_REMAIN(4);
- type = load_uint32_be(p);
- UPDATE_REMAIN(4);
+ if (obj["version"].integer() != 1)
+ return false;
- CHECK_REMAIN(4);
- providerToken.length = load_uint32_be(p);
- UPDATE_REMAIN(4);
+ m_flags = obj["flags"].integer();
- CHECK_REMAIN(providerToken.length);
- providerToken.value = p;
- UPDATE_REMAIN(providerToken.length);
+ JSONObject sources = obj["sources"];
- if (type < ATTR_TYPE_MIN || type > ATTR_TYPE_MAX ||
- didInit[type])
- return false;
+ /* Initialize providers from serialized state */
+ for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++) {
+ gss_eap_attr_provider *provider;
+ const char *key;
if (!providerEnabled(type)) {
releaseProvider(type);
}
provider = m_providers[type];
+ key = provider->name();
+ if (key == NULL)
+ continue;
- ret = provider->initFromBuffer(this, &providerToken);
- if (ret == false) {
+ JSONObject source = sources.get(key);
+ if (!source.isnull() &&
+ !provider->initWithJsonObject(this, source)) {
releaseProvider(type);
- break;
+ return false;
}
- didInit[type] = true;
- }
- if (ret == false)
- return ret;
+ foundSource[type] = true;
+ }
- /*
- * The call the initFromGssContext methods for attribute
- * providers that can initialize themselves from other
- * providers.
- */
+ /* Initialize remaining providers from initialized providers */
for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++) {
gss_eap_attr_provider *provider;
- if (didInit[type] || !providerEnabled(type))
+ if (foundSource[type] || !providerEnabled(type))
continue;
provider = m_providers[type];
return true;
}
+JSONObject
+gss_eap_attr_ctx::jsonRepresentation(void) const
+{
+ JSONObject obj, sources;
+ unsigned int i;
+
+ obj.set("version", 1);
+ obj.set("flags", m_flags);
+
+ for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
+ gss_eap_attr_provider *provider;
+ const char *key;
+
+ provider = m_providers[i];
+ if (provider == NULL)
+ continue; /* provider not initialised */
+
+ key = provider->name();
+ if (key == NULL)
+ continue; /* provider does not have state */
+
+ JSONObject source = provider->jsonRepresentation();
+ sources.set(key, source);
+ }
+
+ obj.set("sources", sources);
+
+ return obj;
+}
+
+/*
+ * Initialize a context from an exported context or name token
+ */
+bool
+gss_eap_attr_ctx::initFromBuffer(const gss_buffer_t buffer)
+{
+ OM_uint32 major, minor;
+ bool ret;
+ char *s;
+ json_error_t error;
+
+ major = bufferToString(&minor, buffer, &s);
+ if (GSS_ERROR(major))
+ return false;
+
+ JSONObject obj = JSONObject::load(s, 0, &error);
+ if (!obj.isnull()) {
+ ret = initWithJsonObject(obj);
+ } else
+ ret = false;
+
+ GSSEAP_FREE(s);
+
+ return ret;
+}
+
gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
{
for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++)
unsigned int i;
major = gss_create_empty_buffer_set(&minor, attrs);
- if (GSS_ERROR(major)) {
+ if (GSS_ERROR(major))
throw new std::bad_alloc;
- return false;
- }
args.attrs = *attrs;
void
gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
{
- OM_uint32 tmpMinor;
- gss_buffer_desc providerTokens[ATTR_TYPE_MAX + 1];
- size_t length = 4; /* m_flags */
- unsigned char *p;
- unsigned int i;
+ OM_uint32 minor;
+ char *s;
- for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
- providerTokens[i].length = 0;
- providerTokens[i].value = NULL;
- }
+ JSONObject obj = jsonRepresentation();
- for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
- gss_eap_attr_provider *provider = m_providers[i];
-
- if (provider == NULL)
- continue;
-
- provider->exportToBuffer(&providerTokens[i]);
+#if 0
+ obj.dump(stdout, JSON_INDENT(3));
+#endif
- if (providerTokens[i].value != NULL)
- length += 8 + providerTokens[i].length;
- }
+ s = obj.dump(JSON_COMPACT);
- buffer->length = length;
- buffer->value = GSSEAP_MALLOC(length);
- if (buffer->value == NULL)
+ if (GSS_ERROR(makeStringBuffer(&minor, s, buffer)))
throw new std::bad_alloc;
-
- p = (unsigned char *)buffer->value;
- store_uint32_be(m_flags, p);
- p += 4;
-
- for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
- if (providerTokens[i].value == NULL)
- continue;
-
- store_uint32_be(i, p);
- p += 4;
- store_uint32_be(providerTokens[i].length, p);
- p += 4;
- memcpy(p, providerTokens[i].value, providerTokens[i].length);
- p += providerTokens[i].length;
-
- gss_release_buffer(&tmpMinor, &providerTokens[i]);
- }
}
/*
major = GSS_S_FAILURE;
try {
- ctx = new gss_eap_attr_ctx();
+ *pAttrContext = ctx = new gss_eap_attr_ctx();
if (ctx->initFromGssContext(gssCred, gssCtx)) {
*minor = 0;
major = GSS_S_COMPLETE;
- } else {
- delete ctx;
}
} catch (std::exception &e) {
if (ctx != NULL)
}
if (major == GSS_S_COMPLETE) {
- *pAttrContext = ctx;
*pExpiryTime = ctx->getExpiryTime();
+ } else {
+ delete ctx;
+ *pAttrContext = NULL;
}
return major;
#include <string>
#include <new>
+using namespace gss_eap_util;
+
struct gss_eap_attr_provider;
struct gss_eap_attr_ctx;
{
return NULL;
}
+
virtual void releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
gss_any_t input GSSEAP_UNUSED) const
{
}
+ /* prefix to be prepended to attributes emitted by gss_get_name_attribute */
virtual const char *prefix(void) const
{
return NULL;
}
- virtual void exportToBuffer(gss_buffer_t buffer GSSEAP_UNUSED) const
+ /* optional key for storing JSON dictionary */
+ virtual const char *name(void) const
{
+ return NULL;
}
- virtual bool initFromBuffer(const gss_eap_attr_ctx *manager,
- const gss_buffer_t buffer GSSEAP_UNUSED)
+ virtual bool initWithJsonObject(const gss_eap_attr_ctx *manager,
+ JSONObject &object GSSEAP_UNUSED)
{
return initWithManager(manager);
}
+
+ virtual JSONObject jsonRepresentation(void) const
+ {
+ return JSONObject::null();
+ }
+
virtual time_t getExpiryTime(void) const { return 0; }
virtual OM_uint32 mapException(OM_uint32 *minor GSSEAP_UNUSED,
unsigned int attributePrefixToType(const gss_buffer_t prefix) const;
gss_buffer_desc attributeTypeToPrefix(unsigned int type) const;
+ bool initWithJsonObject(JSONObject &object);
+ JSONObject jsonRepresentation(void) const;
+
gss_eap_attr_provider *getPrimaryProvider(void) const;
/* make non-copyable */
--- /dev/null
+/*
+ * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#include "gssapiP_eap.h"
+
+static const char base64_chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static int
+pos(char c)
+{
+ const char *p;
+ for (p = base64_chars; *p; p++)
+ if (*p == c)
+ return p - base64_chars;
+ return -1;
+}
+
+int
+base64Encode(const void *data, int size, char **str)
+{
+ char *s, *p;
+ int i;
+ int c;
+ const unsigned char *q;
+
+ if (size > INT_MAX/4 || size < 0) {
+ *str = NULL;
+ return -1;
+ }
+
+ p = s = (char *)GSSEAP_MALLOC(BASE64_EXPAND(size));
+ if (p == NULL) {
+ *str = NULL;
+ return -1;
+ }
+ q = (const unsigned char *) data;
+
+ for (i = 0; i < size;) {
+ c = q[i++];
+ c *= 256;
+ if (i < size)
+ c += q[i];
+ i++;
+ c *= 256;
+ if (i < size)
+ c += q[i];
+ i++;
+ p[0] = base64_chars[(c & 0x00fc0000) >> 18];
+ p[1] = base64_chars[(c & 0x0003f000) >> 12];
+ p[2] = base64_chars[(c & 0x00000fc0) >> 6];
+ p[3] = base64_chars[(c & 0x0000003f) >> 0];
+ if (i > size)
+ p[3] = '=';
+ if (i > size + 1)
+ p[2] = '=';
+ p += 4;
+ }
+ *p = 0;
+ *str = s;
+ return (int) strlen(s);
+}
+
+#define DECODE_ERROR 0xffffffff
+
+static unsigned int
+token_decode(const char *token)
+{
+ int i;
+ unsigned int val = 0;
+ int marker = 0;
+ if (strlen(token) < 4)
+ return DECODE_ERROR;
+ for (i = 0; i < 4; i++) {
+ val *= 64;
+ if (token[i] == '=')
+ marker++;
+ else if (marker > 0)
+ return DECODE_ERROR;
+ else
+ val += pos(token[i]);
+ }
+ if (marker > 2)
+ return DECODE_ERROR;
+ return (marker << 24) | val;
+}
+
+int
+base64Decode(const char *str, void *data)
+{
+ const char *p;
+ unsigned char *q;
+
+ q = data;
+ for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) {
+ unsigned int val = token_decode(p);
+ unsigned int marker = (val >> 24) & 0xff;
+ if (val == DECODE_ERROR)
+ return -1;
+ *q++ = (val >> 16) & 0xff;
+ if (marker < 2)
+ *q++ = (val >> 8) & 0xff;
+ if (marker < 1)
+ *q++ = val & 0xff;
+ }
+ return q - (unsigned char *) data;
+}
--- /dev/null
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 the Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id$ */
+
+#ifndef _UTIL_BASE64_H_
+#define _UTIL_BASE64_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+base64Encode(const void *, int, char **);
+
+int
+base64Decode(const char *, void *);
+
+#define BASE64_EXPAND(n) (n * 4 / 3 + 4)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /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 "gssapiP_eap.h"
+
+#include <typeinfo>
+#include <string>
+#include <sstream>
+#include <exception>
+#include <stdexcept>
+#include <new>
+
+#define JSON_INIT(obj) do { \
+ if ((obj) == NULL) \
+ throw new 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 new std::runtime_error(s); \
+ } \
+ } while (0)
+
+#define JSON_CHECK_OBJECT() do { \
+ if (!json_is_object(m_obj)) { \
+ std::string s("JSONObject is not a dictionary"); \
+ throw new std::runtime_error(s); \
+ } \
+ } while (0)
+
+#define JSON_CHECK_ARRAY() do { \
+ if (!json_is_array(m_obj)) { \
+ std::string s("JSONObject is not an array"); \
+ throw new std::runtime_error(s); \
+ } \
+ } while (0)
+
+#define JSON_CHECK(s) do { \
+ if ((s) != 0) \
+ throw new std::bad_alloc; \
+ } 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 new 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 new 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::isnull(void) const
+{
+ return json_is_null(m_obj);
+}
+
+JSONObject::JSONObject(DDF &ddf)
+{
+ if (ddf.isstruct()) {
+ DDF elem = ddf.first();
+ JSONObject jobj = JSONObject::array();
+
+ while (!elem.isnull()) {
+ JSONObject jtmp(elem);
+ jobj.append(jtmp);
+ elem = ddf.next();
+ }
+ } else if (ddf.islist()) {
+ DDF elem = ddf.first();
+ JSONObject jobj = JSONObject::object();
+
+ while (!elem.isnull()) {
+ JSONObject jtmp(elem);
+ jobj.set(elem.name(), jtmp);
+ elem = ddf.next();
+ }
+ } else if (ddf.isstring()) {
+ JSONObject(ddf.string());
+ } else if (ddf.isint()) {
+ JSONObject((json_int_t)ddf.integer());
+ } else if (ddf.isfloat()) {
+ JSONObject(ddf.floating());
+ } else if (ddf.isempty() || ddf.ispointer()) {
+ JSONObject::object();
+ } else if (ddf.isnull()) {
+ JSONObject::null();
+ }
+
+ std::string s("Unbridgeable DDF object");
+ throw new std::runtime_error(s);
+}
+
+DDF
+JSONObject::ddf(void) const
+{
+ DDF ddf(NULL);
+
+ switch (type()) {
+ case JSON_OBJECT: {
+ JSONIterator iter = iterator();
+
+ do {
+ const char *key = iter.key();
+ DDF value = iter.value().ddf();
+ ddf.add(value.name(key));
+ } while (iter.next());
+ break;
+ }
+ case JSON_ARRAY: {
+ size_t i, nelems = size();
+
+ for (i = 0; i < nelems; i++) {
+ DDF value = get(i).ddf();
+ ddf.add(value);
+ }
+ break;
+ }
+ case JSON_STRING:
+ ddf.string(string());
+ break;
+ case JSON_INTEGER:
+ ddf.integer(integer());
+ break;
+ case JSON_REAL:
+ ddf.floating(real());
+ break;
+ case JSON_TRUE:
+ ddf.integer(1L);
+ break;
+ case JSON_FALSE:
+ ddf.integer(0L);
+ break;
+ case JSON_NULL:
+ break;
+ }
+
+ return DDF(NULL);
+}
+
+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;
+}
--- /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>
+#include <shibsp/remoting/ddf.h>
+
+using namespace shibsp;
+
+namespace gss_eap_util {
+ class JSONObject;
+
+ 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 = 0) const;
+
+ json_type type(void) const { return json_typeof(m_obj); }
+ size_t size(void) const;
+
+ JSONObject(void);
+ JSONObject(DDF &value);
+ 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;
+ bool isnull(void) const;
+ DDF ddf(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);
+
+ json_t *m_obj;
+ };
+}
+
+#endif /* __cplusplus */
+
+#endif /* _UTIL_JSON_H_ */
gssEapImportNameInternal(OM_uint32 *minor,
const gss_buffer_t nameBuffer,
gss_name_t *pName,
- unsigned int flags)
+ OM_uint32 flags)
{
OM_uint32 major, tmpMinor;
krb5_context krbContext;
gssEapExportNameInternal(OM_uint32 *minor,
const gss_name_t name,
gss_buffer_t exportedName,
- unsigned int flags)
+ OM_uint32 flags)
{
OM_uint32 major = GSS_S_FAILURE, tmpMinor;
gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
VALUE_PAIR *vp;
size_t n = remain;
- /*
+ /*
* There's an extra byte of padding; RADIUS AVPs can only
* be 253 octets.
*/
return GSS_S_COMPLETE;
}
-/*
- * Encoding is:
- * 4 octet NBO attribute ID | 4 octet attribute length | attribute data
- */
-static size_t
-avpSize(const VALUE_PAIR *vp)
-{
- size_t size = 4 + 1;
-
- if (vp != NULL)
- size += vp->length;
-
- return size;
-}
-
-static bool
-avpExport(const VALUE_PAIR *vp,
- unsigned char **pBuffer,
- size_t *pRemain)
+static JSONObject
+avpToJson(const VALUE_PAIR *vp)
{
- unsigned char *p = *pBuffer;
- size_t remain = *pRemain;
+ JSONObject obj;
- assert(remain >= avpSize(vp));
-
- store_uint32_be(vp->attribute, p);
+ assert(vp->length <= MAX_STRING_LEN);
switch (vp->type) {
case PW_TYPE_INTEGER:
case PW_TYPE_IPADDR:
case PW_TYPE_DATE:
- p[4] = 4;
- store_uint32_be(vp->lvalue, p + 5);
+ obj.set("value", vp->lvalue);
break;
- default:
- assert(vp->length <= MAX_STRING_LEN);
- p[4] = (uint8_t)vp->length;
- memcpy(p + 5, vp->vp_octets, vp->length);
+ case PW_TYPE_STRING:
+ obj.set("value", vp->vp_strvalue);
break;
- }
+ default: {
+ char *b64;
+
+ if (base64Encode(vp->vp_octets, vp->length, &b64) < 0)
+ throw new std::bad_alloc;
- *pBuffer += 5 + p[4];
- *pRemain -= 5 + p[4];
+ obj.set("value", b64);
+ GSSEAP_FREE(b64);
+ break;
+ }
+ }
- return true;
+ obj.set("type", vp->attribute);
+ return obj;
}
static bool
-avpImport(VALUE_PAIR **pVp,
- unsigned char **pBuffer,
- size_t *pRemain)
+jsonToAvp(VALUE_PAIR **pVp, JSONObject &obj)
{
- unsigned char *p = *pBuffer;
- size_t remain = *pRemain;
VALUE_PAIR *vp = NULL;
DICT_ATTR *da;
uint32_t attrid;
- if (remain < avpSize(NULL))
+ JSONObject type = obj["type"];
+ JSONObject value = obj["value"];
+ if (type.isnull() || value.isnull())
goto fail;
- attrid = load_uint32_be(p);
- p += 4;
- remain -= 4;
-
+ attrid = type.integer();
da = dict_attrbyvalue(attrid);
if (da != NULL) {
vp = pairalloc(da);
goto fail;
}
- if (remain < p[0])
- goto fail;
-
switch (vp->type) {
case PW_TYPE_INTEGER:
case PW_TYPE_IPADDR:
case PW_TYPE_DATE:
- if (p[0] != 4)
- goto fail;
-
vp->length = 4;
- vp->lvalue = load_uint32_be(p + 1);
- p += 5;
- remain -= 5;
+ vp->lvalue = value.integer();
break;
- case PW_TYPE_STRING:
- default:
- if (p[0] >= MAX_STRING_LEN)
+ case PW_TYPE_STRING: {
+ const char *str = value.string();
+ size_t len;
+
+ if (str == NULL || (len = strlen(str)) >= MAX_STRING_LEN)
goto fail;
- vp->length = (uint32_t)p[0];
- memcpy(vp->vp_octets, p + 1, vp->length);
+ vp->length = len;
+ memcpy(vp->vp_strvalue, str, len + 1);
+ break;
+ }
+ case PW_TYPE_OCTETS:
+ default: {
+ const char *str = value.string();
+ int len;
+
+ /* this optimization requires base64Decode only understand packed encoding */
+ if (str == NULL ||
+ strlen(str) >= BASE64_EXPAND(MAX_STRING_LEN))
+ goto fail;
- if (vp->type == PW_TYPE_STRING)
- vp->vp_strvalue[vp->length] = '\0';
+ len = base64Decode(str, vp->vp_octets);
+ if (len < 0)
+ goto fail;
- p += 1 + vp->length;
- remain -= 1 + vp->length;
+ vp->length = len;
+ vp->vp_octets[len] = '\0';
break;
}
+ }
*pVp = vp;
- *pBuffer = p;
- *pRemain = remain;
return true;
return false;
}
+const char *
+gss_eap_radius_attr_provider::name(void) const
+{
+ return "radius";
+}
+
bool
-gss_eap_radius_attr_provider::initFromBuffer(const gss_eap_attr_ctx *ctx,
- const gss_buffer_t buffer)
+gss_eap_radius_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx,
+ JSONObject &obj)
{
- unsigned char *p = (unsigned char *)buffer->value;
- size_t remain = buffer->length;
VALUE_PAIR **pNext = &m_vps;
- if (!gss_eap_attr_provider::initFromBuffer(ctx, buffer))
+ if (!gss_eap_attr_provider::initWithJsonObject(ctx, obj))
return false;
- do {
- VALUE_PAIR *attr;
+ JSONObject attrs = obj["attributes"];
+ size_t nelems = attrs.size();
- if (!avpImport(&attr, &p, &remain))
+ for (size_t i = 0; i < nelems; i++) {
+ JSONObject attr = attrs[i];
+ VALUE_PAIR *vp;
+
+ if (!jsonToAvp(&vp, attr))
return false;
- *pNext = attr;
- pNext = &attr->next;
- } while (remain != 0);
+ *pNext = vp;
+ pNext = &vp->next;
+ }
return true;
}
return "urn:ietf:params:gss-eap:radius-avp";
}
-void
-gss_eap_radius_attr_provider::exportToBuffer(gss_buffer_t buffer) const
+JSONObject
+gss_eap_radius_attr_provider::jsonRepresentation(void) const
{
- VALUE_PAIR *vp;
- unsigned char *p;
- size_t remain = 0;
+ JSONObject obj, attrs = JSONObject::array();
- for (vp = m_vps; vp != NULL; vp = vp->next) {
- remain += avpSize(vp);
+ for (VALUE_PAIR *vp = m_vps; vp != NULL; vp = vp->next) {
+ JSONObject attr = avpToJson(vp);
+ attrs.append(attr);
}
- buffer->value = GSSEAP_MALLOC(remain);
- if (buffer->value == NULL) {
- throw new std::bad_alloc;
- return;
- }
- buffer->length = remain;
-
- p = (unsigned char *)buffer->value;
-
- for (vp = m_vps; vp != NULL; vp = vp->next) {
- avpExport(vp, &p, &remain);
- }
+ obj.set("attributes", attrs);
- assert(remain == 0);
+ return obj;
}
time_t
gss_any_t input) const;
const char *prefix(void) const;
-
- void exportToBuffer(gss_buffer_t buffer) const;
- bool initFromBuffer(const gss_eap_attr_ctx *ctx,
- const gss_buffer_t buffer);
+ const char *name(void) const;
+ bool initWithJsonObject(const gss_eap_attr_ctx *manager,
+ JSONObject &obj);
+ JSONObject jsonRepresentation(void) const;
bool getAttribute(uint32_t attribute,
int *authenticated,
return "urn:ietf:params:gss-eap:saml-aaa-assertion";
}
-void
-gss_eap_saml_assertion_provider::exportToBuffer(gss_buffer_t buffer) const
-{
- buffer->length = 0;
- buffer->value = NULL;
-}
-
-bool
-gss_eap_saml_assertion_provider::initFromBuffer(const gss_eap_attr_ctx *ctx GSSEAP_UNUSED,
- const gss_buffer_t buffer GSSEAP_UNUSED)
-{
- return false;
-}
-
bool
gss_eap_saml_assertion_provider::init(void)
{
return "urn:ietf:params:gss-eap:saml-attr";
}
-void
-gss_eap_saml_attr_provider::exportToBuffer(gss_buffer_t buffer) const
-{
- buffer->length = 0;
- buffer->value = NULL;
-}
-
-bool
-gss_eap_saml_attr_provider::initFromBuffer(const gss_eap_attr_ctx *ctx GSSEAP_UNUSED,
- const gss_buffer_t buffer GSSEAP_UNUSED)
-{
- return false;
-}
-
bool
gss_eap_saml_attr_provider::init(void)
{
gss_any_t input) const;
const char *prefix(void) const;
- void exportToBuffer(gss_buffer_t buffer) const;
-
- bool initFromBuffer(const gss_eap_attr_ctx *ctx,
- const gss_buffer_t buffer);
+ const char *name(void) const { return NULL; }
+ bool initWithJsonObject(const gss_eap_attr_ctx *manager GSSEAP_UNUSED,
+ JSONObject &object GSSEAP_UNUSED) {
+ return false;
+ }
+ JSONObject jsonRepresentation(void) const {
+ return JSONObject::null();
+ }
opensaml::saml2::Assertion *initAssertion(void);
gss_any_t input) const;
const char *prefix(void) const;
-
- void exportToBuffer(gss_buffer_t buffer) const;
- bool initFromBuffer(const gss_eap_attr_ctx *ctx,
- const gss_buffer_t buffer);
+ const char *name(void) const {
+ return NULL;
+ }
+ bool initWithJsonObject(const gss_eap_attr_ctx *manager GSSEAP_UNUSED,
+ JSONObject &object GSSEAP_UNUSED) {
+ return false;
+ }
+ JSONObject jsonRepresentation(void) const {
+ return JSONObject::null();
+ }
bool getAttribute(const gss_buffer_t attr,
int *authenticated,
gss_eap_shib_attr_provider::gss_eap_shib_attr_provider(void)
{
+ m_initialized = false;
m_authenticated = false;
}
m_authenticated = shib->authenticated();
}
- return true;
-}
-
-bool
-addRadiusAttribute(const gss_eap_attr_ctx *manager,
- const gss_eap_attr_provider *provider,
- const gss_buffer_t attribute,
- void *data)
-{
- const gss_eap_radius_attr_provider *radius;
- const gss_eap_shib_attr_provider *shib;
- int authenticated, complete, more = -1;
- vector <string> attributeIds(1);
- SimpleAttribute *a;
-
- radius = static_cast<const gss_eap_radius_attr_provider *>(provider);
- shib = static_cast<const gss_eap_shib_attr_provider *>(data);
-
- assert(radius != NULL && shib != NULL);
-
- string attributeName =
- manager->composeAttributeName(ATTR_TYPE_RADIUS, attribute);
-
- attributeIds.push_back(attributeName);
- a = new SimpleAttribute(attributeIds);
- if (a == NULL)
- return false;
-
- while (more != 0) {
- gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
- OM_uint32 minor;
-
- if (!radius->getAttribute(attribute,
- &authenticated,
- &complete,
- &value,
- NULL,
- &more))
- return false;
-
- string attributeValue((char *)value.value, value.length);
- a->getValues().push_back(attributeValue);
-
- gss_release_buffer(&minor, &value);
- }
-
- shib->getAttributes().push_back(a);
+ m_initialized = true;
return true;
}
const gss_ctx_id_t gssCtx)
{
const gss_eap_saml_assertion_provider *saml;
- const gss_eap_radius_attr_provider *radius;
+ gss_buffer_desc exportedCtx = GSS_C_EMPTY_BUFFER;
+ OM_uint32 major, minor;
+
#if 0
gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
- OM_uint32 minor;
#endif
if (!gss_eap_attr_provider::initFromGssContext(manager, gssCred, gssCtx))
return false;
saml = static_cast<const gss_eap_saml_assertion_provider *>
(m_manager->getProvider(ATTR_TYPE_SAML_ASSERTION));
- radius = static_cast<const gss_eap_radius_attr_provider *>
- (m_manager->getProvider(ATTR_TYPE_RADIUS));
auto_ptr<ShibbolethResolver> resolver(ShibbolethResolver::create());
}
#endif
- m_authenticated = false;
-
- if (radius != NULL) {
- radius->getAttributeTypes(addRadiusAttribute, (void *)this);
- m_authenticated = radius->authenticated();
+ major = gssEapExportSecContext(&minor, gssCtx, &exportedCtx);
+ if (major == GSS_S_COMPLETE) {
+ resolver->addToken(&exportedCtx);
+ gss_release_buffer(&minor, &exportedCtx);
}
if (saml != NULL && saml->getAssertion() != NULL) {
resolver->addToken(saml->getAssertion());
- if (m_authenticated)
- m_authenticated = saml->authenticated();
+ m_authenticated = saml->authenticated();
}
try {
#endif
}
+ m_initialized = true;
+
return true;
}
{
int i = 0;
+ assert(m_initialized);
+
for (vector<Attribute *>::const_iterator a = m_attributes.begin();
a != m_attributes.end();
++a)
vector <string> ids(1, attrStr);
SimpleAttribute *a = new SimpleAttribute(ids);
+ assert(m_initialized);
+
if (value->length != 0) {
string valueStr((char *)value->value, value->length);
{
int i;
+ assert(m_initialized);
+
i = getAttributeIndex(attr);
if (i >= 0)
m_attributes.erase(m_attributes.begin() + i);
gss_eap_shib_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
void *data) const
{
+ assert(m_initialized);
+
for (vector<Attribute*>::const_iterator a = m_attributes.begin();
a != m_attributes.end();
++a)
{
const Attribute *ret = NULL;
+ assert(m_initialized);
+
for (vector<Attribute *>::const_iterator a = m_attributes.begin();
a != m_attributes.end();
++a)
gss_buffer_desc buf;
int nvalues, i = *more;
+ assert(m_initialized);
+
*more = 0;
shibAttr = getAttribute(attr);
{
gss_any_t output;
+ assert(m_initialized);
+
if (authenticated && !m_authenticated)
return (gss_any_t)NULL;
gss_eap_shib_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
gss_any_t input) const
{
+ assert(m_initialized);
+
vector <Attribute *> *v = ((vector <Attribute *> *)input);
delete v;
}
return NULL;
}
-void
-gss_eap_shib_attr_provider::exportToBuffer(gss_buffer_t buffer) const
+const char *
+gss_eap_shib_attr_provider::name(void) const
+{
+ return "local";
+}
+
+JSONObject
+gss_eap_shib_attr_provider::jsonRepresentation(void) const
{
- DDF obj(NULL);
- DDF attrs(NULL);
+ JSONObject obj;
- buffer->length = 0;
- buffer->value = NULL;
+ if (m_initialized == false)
+ return obj; /* don't export incomplete context */
- obj.addmember("version").integer(1);
- obj.addmember("authenticated").integer(m_authenticated);
+ JSONObject attrs = JSONObject::array();
- attrs = obj.addmember("attributes").list();
for (vector<Attribute*>::const_iterator a = m_attributes.begin();
a != m_attributes.end(); ++a) {
DDF attr = (*a)->marshall();
- attrs.add(attr);
+ JSONObject jobj(attr);
+ attrs.append(jobj);
}
- ostringstream sink;
- sink << obj;
- string str = sink.str();
+ obj.set("attributes", attrs);
- duplicateBuffer(str, buffer);
+ obj.set("authenticated", m_authenticated);
- attrs.destroy();
+ return obj;
}
bool
-gss_eap_shib_attr_provider::initFromBuffer(const gss_eap_attr_ctx *ctx,
- const gss_buffer_t buffer)
+gss_eap_shib_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx,
+ JSONObject &obj)
{
- if (!gss_eap_attr_provider::initFromBuffer(ctx, buffer))
+ if (!gss_eap_attr_provider::initWithJsonObject(ctx, obj))
return false;
- if (buffer->length == 0)
- return true;
-
assert(m_authenticated == false);
assert(m_attributes.size() == 0);
- DDF obj(NULL);
- string str((const char *)buffer->value, buffer->length);
- istringstream source(str);
-
- source >> obj;
-
- if (obj["version"].integer() != 1)
- return false;
-
- m_authenticated = (obj["authenticated"].integer() != 0);
+ JSONObject attrs = obj["attributes"];
+ size_t nelems = attrs.size();
- DDF attrs = obj["attributes"];
- DDF attr = attrs.first();
- while (!attr.isnull()) {
+ for (size_t i = 0; i < nelems; i++) {
+ DDF attr = attrs.get(i).ddf();
Attribute *attribute = Attribute::unmarshall(attr);
m_attributes.push_back(attribute);
- attr = attrs.next();
}
- attrs.destroy();
+ m_authenticated = obj["authenticated"].integer();
+ m_initialized = true;
return true;
}
gss_any_t input) const;
const char *prefix(void) const;
-
- void exportToBuffer(gss_buffer_t buffer) const;
- bool initFromBuffer(const gss_eap_attr_ctx *ctx,
- const gss_buffer_t buffer);
+ const char *name(void) const;
+ bool initWithJsonObject(const gss_eap_attr_ctx *manager,
+ JSONObject &obj);
+ JSONObject jsonRepresentation(void) const;
static bool init(void);
static void finalize(void);
bool authenticated(void) const { return m_authenticated; }
- friend bool
- addRadiusAttribute(const gss_eap_attr_provider *source,
- const gss_buffer_t attribute,
- void *data);
-
+ bool m_initialized;
+ bool m_authenticated;
std::vector<shibsp::Attribute *> m_attributes;
- int m_authenticated;
};
-
extern "C" {
#endif
-Subproject commit 420cc8ae67db726cb6d22ae2a8dbcdeabb547ad6
+Subproject commit 28fb7b606f379cda416cbc4239d2690b6a1c161f
-Subproject commit 4c22d78d500385b10bd0fbb4a291b47a840ba4ad
+Subproject commit ec12184bd72287b88af4301bde2df916fc475615
shibboleth/resolver
libradsec/lib
libeap
+jansson
mech_eap