From e063ba4e45d12dbc1a397653f9e77228835e4a2b Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Mon, 28 Mar 2011 02:21:27 +1100 Subject: [PATCH] use JSON instead of DDF marshalling use our own base64 routines --- Makefile.am | 3 +- acinclude.m4 | 38 ++++++++++++++ configure.ac | 1 + util.h | 1 + util_attr.cpp | 133 ++++++++++++++++++++++++++++-------------------- util_attr.h | 21 ++++---- util_base64.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++ util_base64.h | 65 ++++++++++++++++++++++++ util_radius.cpp | 114 ++++++++++++++++++++++++----------------- util_radius.h | 9 ++-- util_saml.cpp | 42 ---------------- util_saml.h | 35 ++++--------- util_shib.cpp | 153 +++++++++++++++++++++++++++++++++++++++++++++++++------- util_shib.h | 9 ++-- 14 files changed, 555 insertions(+), 206 deletions(-) create mode 100644 util_base64.c create mode 100644 util_base64.h diff --git a/Makefile.am b/Makefile.am index f87406a..d2c8583 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,7 +16,7 @@ mech_eap_la_LDFLAGS = -avoid-version -module \ -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 \ @@ -70,6 +70,7 @@ mech_eap_la_SOURCES = \ unwrap_iov.c \ userok.c \ util_attr.cpp \ + util_base64.c \ util_buffer.c \ util_context.c \ util_cksum.c \ diff --git a/acinclude.m4 b/acinclude.m4 index ad31df8..eab00b4 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -220,3 +220,41 @@ else 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 diff --git a/configure.ac b/configure.ac index 0115b0b..a7e6942 100644 --- a/configure.ac +++ b/configure.ac @@ -51,5 +51,6 @@ AX_CHECK_EAP AX_CHECK_SHIBSP AX_CHECK_SHIBRESOLVER AX_CHECK_RADSEC +AX_CHECK_JANSSON AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/util.h b/util.h index 90256ca..31c89f2 100644 --- a/util.h +++ b/util.h @@ -846,6 +846,7 @@ gssBufferToKrbData(gss_buffer_t buffer, krb5_data *data) #endif #include "util_attr.h" +#include "util_base64.h" #ifdef GSSEAP_ENABLE_REAUTH #include "util_reauth.h" #endif diff --git a/util_attr.cpp b/util_attr.cpp index 80d2781..28e6356 100644 --- a/util_attr.cpp +++ b/util_attr.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include /* lazy initialisation */ @@ -274,55 +275,43 @@ gss_eap_attr_ctx::initFromGssContext(const gss_cred_id_t cred, return ret; } -static DDF -findSourceForProvider(DDF &sources, const char *key) -{ - DDF source = sources.first(); - - while (!source.isnull()) { - DDF obj = source.getmember(key); - - if (strcmp(key, source.name()) == 0) - break; - - source = sources.next(); - } - - return source; -} - bool -gss_eap_attr_ctx::unmarshallAndInit(DDF &obj) +gss_eap_attr_ctx::initWithJsonObject(json_t *obj) { bool ret = false; bool foundSource[ATTR_TYPE_MAX + 1]; unsigned int type; + json_t *sources; for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++) foundSource[type] = false; - if (obj["version"].integer() != 1) + if (json_integer_value(json_object_get(obj, "version")) != 1) return false; - m_flags = obj["flags"].integer(); + m_flags = json_integer_value(json_object_get(obj, "flags")); - DDF sources = obj["sources"]; + sources = json_object_get(obj, "sources"); /* Initialize providers from serialized state */ for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++) { + gss_eap_attr_provider *provider; + const char *key; + json_t *source; + if (!providerEnabled(type)) { releaseProvider(type); continue; } - gss_eap_attr_provider *provider = m_providers[type]; - const char *key = provider->marshallingKey(); + provider = m_providers[type]; + key = provider->name(); if (key == NULL) continue; - DDF source = findSourceForProvider(sources, key); - if (source.isnull() || - !provider->unmarshallAndInit(this, source)) { + source = json_object_get(sources, key); + if (source != NULL && + !provider->initWithJsonObject(this, source)) { releaseProvider(type); return false; } @@ -330,7 +319,7 @@ gss_eap_attr_ctx::unmarshallAndInit(DDF &obj) foundSource[type] = true; } - /* Initialize remaining providers from initialized providers */ + /* Initialize remaining providers from initialized providers */ for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++) { gss_eap_attr_provider *provider; @@ -351,31 +340,45 @@ gss_eap_attr_ctx::unmarshallAndInit(DDF &obj) return true; } -DDF -gss_eap_attr_ctx::marshall(void) const +json_t * +gss_eap_attr_ctx::jsonRepresentation(void) const { - DDF obj(NULL); + json_t *obj, *sources; unsigned int i; - obj.addmember("version").integer(1); - obj.addmember("flags").integer(m_flags); + obj = json_object(); + if (obj == NULL) { + throw new std::bad_alloc; + } - DDF sources = obj.addmember("sources").list(); + /* FIXME check json_object_set_new return value */ + json_object_set_new(obj, "version", json_integer(1)); + json_object_set_new(obj, "flags", json_integer(m_flags)); + + sources = json_object(); + if (sources == NULL) { + json_decref(obj); + throw new std::bad_alloc; + } for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) { - gss_eap_attr_provider *provider = m_providers[i]; + gss_eap_attr_provider *provider; + const char *key; + provider = m_providers[i]; if (provider == NULL) continue; /* provider not initialised */ - const char *key = provider->marshallingKey(); + key = provider->name(); if (key == NULL) continue; /* provider does not have state */ - DDF source = provider->marshall(); - sources.add(source.name(key)); + json_t *source = provider->jsonRepresentation(); + json_object_set_new(sources, key, source); } + json_object_set_new(obj, "sources", sources); + return obj; } @@ -385,20 +388,24 @@ gss_eap_attr_ctx::marshall(void) const bool gss_eap_attr_ctx::initFromBuffer(const gss_buffer_t buffer) { + OM_uint32 major, minor; bool ret; + char *s; + json_error_t error; + json_t *obj; - if (buffer->length == 0) + major = bufferToString(&minor, buffer, &s); + if (GSS_ERROR(major)) return false; - DDF obj(NULL); - std::string str((const char *)buffer->value, buffer->length); - std::istringstream source(str); + obj = json_loads(s, 0, &error); + if (obj != NULL) { + ret = initWithJsonObject(obj); + json_decref(obj); + } else + ret = false; - source >> obj; - - ret = unmarshallAndInit(obj); - - obj.destroy(); + GSSEAP_FREE(s); return ret; } @@ -536,10 +543,8 @@ gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs) 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; @@ -635,15 +640,33 @@ gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id, void gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const { - DDF obj = marshall(); - std::ostringstream sink; + OM_uint32 minor; + json_t *obj; + char *s; + + obj = jsonRepresentation(); + if (obj == NULL) { + std::string error("gss_eap_attr_ctx::exportToBuffer::jsonRepresentation"); + throw new std::runtime_error(error); /* XXX */ + } + +#if 0 + json_dumpf(obj, stdout, JSON_INDENT(3)); +#endif - sink << obj; - std::string str = sink.str(); + s = json_dumps(obj, JSON_COMPACT); + if (s == NULL) { + json_decref(obj); + std::string error("gss_eap_attr_ctx::exportToBuffer: json_dumps"); + throw new std::runtime_error(error); /* XXX */ + } - duplicateBuffer(str, buffer); + if (GSS_ERROR(makeStringBuffer(&minor, s, buffer))) { + json_decref(obj); + throw new std::bad_alloc; + } - obj.destroy(); + json_decref(obj); } /* diff --git a/util_attr.h b/util_attr.h index 347842a..1a427f7 100644 --- a/util_attr.h +++ b/util_attr.h @@ -41,9 +41,7 @@ #include #include -#include - -using namespace shibsp; +#include struct gss_eap_attr_provider; struct gss_eap_attr_ctx; @@ -131,25 +129,28 @@ public: { } + /* prefix to be prepended to attributes emitted by gss_get_name_attribute */ virtual const char *prefix(void) const { return NULL; } - virtual const char *marshallingKey(void) const + /* optional key for storing JSON dictionary */ + virtual const char *name(void) const { return NULL; } - virtual bool unmarshallAndInit(const gss_eap_attr_ctx *manager, - DDF &object GSSEAP_UNUSED) + virtual bool initWithJsonObject(const gss_eap_attr_ctx *manager, + json_t *object GSSEAP_UNUSED) { return initWithManager(manager); } - virtual DDF marshall(void) const + + virtual json_t *jsonRepresentation(void) const { - return DDF(NULL); + return NULL; } virtual time_t getExpiryTime(void) const { return 0; } @@ -253,8 +254,8 @@ private: unsigned int attributePrefixToType(const gss_buffer_t prefix) const; gss_buffer_desc attributeTypeToPrefix(unsigned int type) const; - bool unmarshallAndInit(DDF &object); - DDF marshall(void) const; + bool initWithJsonObject(json_t *object); + json_t *jsonRepresentation(void) const; gss_eap_attr_provider *getPrimaryProvider(void) const; diff --git a/util_base64.c b/util_base64.c new file mode 100644 index 0000000..8d13aaf --- /dev/null +++ b/util_base64.c @@ -0,0 +1,137 @@ +/* + * 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; +} diff --git a/util_base64.h b/util_base64.h new file mode 100644 index 0000000..98f0c1f --- /dev/null +++ b/util_base64.h @@ -0,0 +1,65 @@ +/* + * 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_ + +#ifndef ROKEN_LIB_FUNCTION +#ifdef _WIN32 +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL __cdecl +#else +#define ROKEN_LIB_FUNCTION +#define ROKEN_LIB_CALL +#endif +#endif + +#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 diff --git a/util_radius.cpp b/util_radius.cpp index a272759..4e2f6e0 100644 --- a/util_radius.cpp +++ b/util_radius.cpp @@ -36,8 +36,6 @@ #include "gssapiP_eap.h" -#include - /* stuff that should be provided by libradsec/libfreeradius-radius */ #define VENDORATTR(vendor, attr) (((vendor) << 16) | (attr)) @@ -505,7 +503,7 @@ gssEapRadiusAddAvp(OM_uint32 *minor, VALUE_PAIR *vp; size_t n = remain; - /* + /* * There's an extra byte of padding; RADIUS AVPs can only * be 253 octets. */ @@ -621,12 +619,18 @@ gssEapRadiusAttrProviderFinalize(OM_uint32 *minor) return GSS_S_COMPLETE; } -static DDF -avpMarshall(const VALUE_PAIR *vp) +static json_t * +avpToJson(const VALUE_PAIR *vp) { - DDF obj(NULL); + json_t *obj = json_object(); - obj.addmember("type").integer(vp->attribute); + if (obj == NULL) { + throw new std::bad_alloc; + return NULL; + } + + /* FIXME check json_object_set_new return value */ + json_object_set_new(obj, "type", json_integer(vp->attribute)); assert(vp->length <= MAX_STRING_LEN); @@ -634,20 +638,21 @@ avpMarshall(const VALUE_PAIR *vp) case PW_TYPE_INTEGER: case PW_TYPE_IPADDR: case PW_TYPE_DATE: - obj.addmember("value").integer(vp->lvalue); + json_object_set_new(obj, "value", json_integer(vp->lvalue)); break; case PW_TYPE_STRING: - obj.addmember("value").string(vp->vp_strvalue); + json_object_set_new(obj, "value", json_string(vp->vp_strvalue)); break; default: { - XMLSize_t len; - XMLByte *b64 = xercesc::Base64::encode(vp->vp_octets, vp->length, &len); + char *b64; - if (b64[len - 1] == '\n') - b64[--len] = '\0'; /* XXX there may be embedded newlines */ + if (base64Encode(vp->vp_octets, vp->length, &b64) < 0) { + json_decref(obj); + throw new std::bad_alloc; + } - obj.addmember("value").string((char *)b64); - delete b64; + json_object_set_new(obj, "value", json_string(b64)); + GSSEAP_FREE(b64); break; } } @@ -656,14 +661,19 @@ avpMarshall(const VALUE_PAIR *vp) } static bool -avpUnmarshall(VALUE_PAIR **pVp, DDF &obj) +jsonToAvp(VALUE_PAIR **pVp, json_t *obj) { VALUE_PAIR *vp = NULL; DICT_ATTR *da; uint32_t attrid; + json_t *type, *value; - attrid = obj["type"].integer(); + type = json_object_get(obj, "type"); + value = json_object_get(obj, "value"); + if (type == NULL || value == NULL) + goto fail; + attrid = json_integer_value(type); da = dict_attrbyvalue(attrid); if (da != NULL) { vp = pairalloc(da); @@ -680,12 +690,13 @@ avpUnmarshall(VALUE_PAIR **pVp, DDF &obj) case PW_TYPE_IPADDR: case PW_TYPE_DATE: vp->length = 4; - vp->lvalue = obj["value"].integer();; + vp->lvalue = json_integer_value(value); break; case PW_TYPE_STRING: { - const char *str = obj["value"].string(); - size_t len = strlen(str); - if (str == NULL || len >= MAX_STRING_LEN) + const char *str = json_string_value(value); + size_t len; + + if (str == NULL || (len = strlen(str)) >= MAX_STRING_LEN) goto fail; vp->length = len; @@ -694,18 +705,20 @@ avpUnmarshall(VALUE_PAIR **pVp, DDF &obj) } case PW_TYPE_OCTETS: default: { - XMLSize_t len; - const XMLByte *b64 = (const XMLByte *)obj["value"].string(); - XMLByte *data = xercesc::Base64::decode(b64, &len); - if (data == NULL || len >= MAX_STRING_LEN) { - delete data; + const char *str = json_string_value(value); + int len; + + /* this optimization requires base64Decode only understand packed encoding */ + if (str == NULL || + strlen(str) >= BASE64_EXPAND(MAX_STRING_LEN)) + goto fail; + + len = base64Decode(str, vp->vp_octets); + if (len < 0) goto fail; - } vp->length = len; - memcpy(vp->vp_octets, data, len); vp->vp_octets[len] = '\0'; - delete data; break; } } @@ -722,33 +735,33 @@ fail: } const char * -gss_eap_radius_attr_provider::marshallingKey(void) const +gss_eap_radius_attr_provider::name(void) const { return "radius"; } bool -gss_eap_radius_attr_provider::unmarshallAndInit(const gss_eap_attr_ctx *ctx, - DDF &obj) +gss_eap_radius_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx, + json_t *obj) { VALUE_PAIR **pNext = &m_vps; + json_t *attrs; + size_t i; - if (!gss_eap_attr_provider::unmarshallAndInit(ctx, obj)) + if (!gss_eap_attr_provider::initWithJsonObject(ctx, obj)) return false; - DDF attrs = obj["attributes"]; - DDF attr = attrs.first(); + attrs = json_object_get(obj, "attributes"); - while (!attr.isnull()) { + for (i = 0; i < json_array_size(attrs); i++) { + json_t *attr = json_array_get(attrs, i); VALUE_PAIR *vp; - if (!avpUnmarshall(&vp, attr)) + if (!jsonToAvp(&vp, attr)) return false; *pNext = vp; pNext = &vp->next; - - attr = attrs.next(); } return true; @@ -760,17 +773,28 @@ gss_eap_radius_attr_provider::prefix(void) const return "urn:ietf:params:gss-eap:radius-avp"; } -DDF -gss_eap_radius_attr_provider::marshall(void) const +json_t * +gss_eap_radius_attr_provider::jsonRepresentation(void) const { - DDF obj(NULL); - DDF attrs = obj.structure().addmember("attributes").list(); + json_t *obj, *attrs; + + attrs = json_array(); + if (attrs == NULL) + throw new std::bad_alloc; for (VALUE_PAIR *vp = m_vps; vp != NULL; vp = vp->next) { - DDF attr = avpMarshall(vp); - attrs.add(attr); + json_t *attr = avpToJson(vp); + json_array_append_new(attrs, attr); } + obj = json_object(); + if (obj == NULL) { + json_decref(attrs); + throw new std::bad_alloc; + } + + json_object_set_new(obj, "attributes", attrs); + return obj; } diff --git a/util_radius.h b/util_radius.h index 0335dc8..656f1b7 100644 --- a/util_radius.h +++ b/util_radius.h @@ -67,11 +67,10 @@ public: gss_any_t input) const; const char *prefix(void) const; - const char *marshallingKey(void) const; - - bool unmarshallAndInit(const gss_eap_attr_ctx *manager, - DDF &object GSSEAP_UNUSED); - DDF marshall(void) const; + const char *name(void) const; + bool initWithJsonObject(const gss_eap_attr_ctx *manager, + json_t *obj); + json_t *jsonRepresentation(void) const; bool getAttribute(uint32_t attribute, int *authenticated, diff --git a/util_saml.cpp b/util_saml.cpp index 1a2c81e..8722b84 100644 --- a/util_saml.cpp +++ b/util_saml.cpp @@ -304,33 +304,12 @@ gss_eap_saml_assertion_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSE delete ((saml2::Assertion *)input); } -<<<<<<< HEAD -<<<<<<< HEAD const char * gss_eap_saml_assertion_provider::prefix(void) const { return "urn:ietf:params:gss-eap:saml-aaa-assertion"; } -void -gss_eap_saml_assertion_provider::exportToBuffer(gss_buffer_t buffer) const -======= -DDF -gss_eap_saml_assertion_provider::marshall(void) const ->>>>>>> 1ef293a... in progress use DDF to serialise names -{ - return DDF(NULL); -} - -bool -gss_eap_saml_assertion_provider::unmarshallAndInit(const gss_eap_attr_ctx *ctx GSSEAP_UNUSED, - DDF &object GSSEAP_UNUSED) -{ - return false; -} - -======= ->>>>>>> eef7b3b... get DDF marshalling working bool gss_eap_saml_assertion_provider::init(void) { @@ -695,33 +674,12 @@ gss_eap_saml_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UN { } -<<<<<<< HEAD -<<<<<<< HEAD const char * gss_eap_saml_attr_provider::prefix(void) const { return "urn:ietf:params:gss-eap:saml-attr"; } -void -gss_eap_saml_attr_provider::exportToBuffer(gss_buffer_t buffer) const -======= -DDF -gss_eap_saml_attr_provider::marshall(void) const ->>>>>>> 1ef293a... in progress use DDF to serialise names -{ - return DDF(NULL); -} - -bool -gss_eap_saml_attr_provider::unmarshallAndInit(const gss_eap_attr_ctx *ctx GSSEAP_UNUSED, - DDF &object GSSEAP_UNUSED) -{ - return false; -} - -======= ->>>>>>> eef7b3b... get DDF marshalling working bool gss_eap_saml_attr_provider::init(void) { diff --git a/util_saml.h b/util_saml.h index 351e70d..0a14d3e 100644 --- a/util_saml.h +++ b/util_saml.h @@ -75,15 +75,13 @@ public: gss_any_t input) const; const char *prefix(void) const; - const char *marshallingKey(void) const { - return NULL; - } - bool unmarshallAndInit(const gss_eap_attr_ctx *manager GSSEAP_UNUSED, - DDF &object GSSEAP_UNUSED) { + const char *name(void) const { return NULL; } + bool initWithJsonObject(const gss_eap_attr_ctx *manager GSSEAP_UNUSED, + json_t *object GSSEAP_UNUSED) { return false; } - DDF marshall(void) const { - return DDF(NULL); + json_t *jsonRepresentation(void) const { + return NULL; } opensaml::saml2::Assertion *initAssertion(void); @@ -137,30 +135,17 @@ public: void releaseAnyNameMapping(gss_buffer_t type_id, gss_any_t input) const; -<<<<<<< HEAD -<<<<<<< HEAD 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); -======= - bool unmarshallAndInit(const gss_eap_attr_ctx *manager, - DDF &object GSSEAP_UNUSED); - DDF marshall(void) const; ->>>>>>> 1ef293a... in progress use DDF to serialise names -======= - const char *marshallingKey(void) const { + const char *name(void) const { return NULL; } - bool unmarshallAndInit(const gss_eap_attr_ctx *manager GSSEAP_UNUSED, - DDF &object GSSEAP_UNUSED) { + bool initWithJsonObject(const gss_eap_attr_ctx *manager GSSEAP_UNUSED, + json_t *object GSSEAP_UNUSED) { return false; } - DDF marshall(void) const { - return DDF(NULL); + json_t *jsonRepresentation(void) const { + return NULL; } ->>>>>>> eef7b3b... get DDF marshalling working bool getAttribute(const gss_buffer_t attr, int *authenticated, diff --git a/util_shib.cpp b/util_shib.cpp index a53a476..14757d1 100644 --- a/util_shib.cpp +++ b/util_shib.cpp @@ -385,52 +385,169 @@ gss_eap_shib_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UN } const char * -<<<<<<< HEAD gss_eap_shib_attr_provider::prefix(void) const { return NULL; -======= -gss_eap_shib_attr_provider::marshallingKey(void) const +} + +const char * +gss_eap_shib_attr_provider::name(void) const { return "local"; ->>>>>>> eef7b3b... get DDF marshalling working } -DDF -gss_eap_shib_attr_provider::marshall(void) const +static json_t * +ddfToJson(DDF &ddf) { - DDF obj(NULL); + json_t *json; + + if (ddf.isstruct()) { + DDF elem = ddf.first(); + json = json_array(); + if (json == NULL) + throw new std::bad_alloc; + + while (!elem.isnull()) { + if (json_array_append_new(json, ddfToJson(elem)) != 0) { + json_decref(json); + throw new std::bad_alloc; + } - obj.addmember("authenticated").integer(m_authenticated); + elem = ddf.next(); + } + } else if (ddf.islist()) { + DDF elem = ddf.first(); + json = json_object(); + if (json == NULL) + throw new std::bad_alloc; + + while (!elem.isnull()) { + if (json_object_set(json, elem.name(), ddfToJson(elem)) != 0) { + json_decref(json); + throw new std::bad_alloc; + } + + elem = ddf.next(); + } + } else if (ddf.isstring()) { + json = json_string(ddf.string()); + } else if (ddf.isint()) { + json = json_integer(ddf.integer()); + } else if (ddf.isfloat()) { + json = json_real(ddf.floating()); + } else if (ddf.isempty() || ddf.ispointer()) { + json = json_object(); + } else if (ddf.isnull()) { + json = json_null(); + } else { + assert(0 && "Invalid DDF object"); + } + + if (json == NULL) + throw new std::bad_alloc; + + return json; +} + +static DDF +jsonToDdf(json_t *json) +{ + DDF ddf(NULL); + + switch (json_typeof(json)) { + case JSON_OBJECT: { + void *iter = json_object_iter(json); + + while (iter != NULL) { + const char *key = json_object_iter_key(iter); + json_t *value = json_object_iter_value(iter); + ddf.add(jsonToDdf(value).name(key)); + iter = json_object_iter_next(json, iter); + } + break; + } + case JSON_ARRAY: { + size_t i; + + for (i = 0; i < json_array_size(json); i++) { + DDF value = jsonToDdf(json_array_get(json, i)); + ddf.add(value); + } + break; + } + case JSON_STRING: + ddf.string(json_string_value(json)); + break; + case JSON_INTEGER: + ddf.integer(json_integer_value(json)); + break; + case JSON_REAL: + ddf.floating(json_real_value(json)); + break; + case JSON_TRUE: + ddf.integer(1L); + break; + case JSON_FALSE: + ddf.integer(0L); + break; + case JSON_NULL: + break; + } + + return ddf; +} + +json_t * +gss_eap_shib_attr_provider::jsonRepresentation(void) const +{ + json_t *obj, *attrs; + + obj = json_object(); + if (obj == NULL) + throw new std::bad_alloc; + + /* FIXME check json_object_set_new return value */ + json_object_set_new(obj, "authenticated", json_integer(m_authenticated)); + + attrs = json_array(); + if (attrs == NULL) { + json_decref(obj); + throw new std::bad_alloc; + } - DDF attrs = obj.addmember("attributes").list(); for (vector::const_iterator a = m_attributes.begin(); a != m_attributes.end(); ++a) { DDF attr = (*a)->marshall(); - attrs.add(attr); + /* FIXME check json_array_append_new return value */ + json_array_append_new(attrs, ddfToJson(attr)); } + json_object_set_new(obj, "attributes", attrs); + return obj; } bool -gss_eap_shib_attr_provider::unmarshallAndInit(const gss_eap_attr_ctx *ctx, - DDF &obj) +gss_eap_shib_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx, + json_t *obj) { - if (!gss_eap_attr_provider::unmarshallAndInit(ctx, obj)) + size_t i; + json_t *attrs; + + if (!gss_eap_attr_provider::initWithJsonObject(ctx, obj)) return false; assert(m_authenticated == false); assert(m_attributes.size() == 0); - m_authenticated = (obj["authenticated"].integer() != 0); + m_authenticated = json_integer_value(json_object_get(obj, "authenticated")); + + attrs = json_object_get(obj, "attributes"); - DDF attrs = obj["attributes"]; - DDF attr = attrs.first(); - while (!attr.isnull()) { + for (i = 0; i < json_array_size(attrs); i++) { + DDF attr = jsonToDdf(json_array_get(attrs, i)); Attribute *attribute = Attribute::unmarshall(attr); m_attributes.push_back(attribute); - attr = attrs.next(); } return true; diff --git a/util_shib.h b/util_shib.h index db931fb..7cacd66 100644 --- a/util_shib.h +++ b/util_shib.h @@ -77,11 +77,10 @@ public: gss_any_t input) const; const char *prefix(void) const; - - const char *marshallingKey(void) const; - bool unmarshallAndInit(const gss_eap_attr_ctx *manager, - DDF &object GSSEAP_UNUSED); - DDF marshall(void) const; + const char *name(void) const; + bool initWithJsonObject(const gss_eap_attr_ctx *manager, + json_t *obj); + json_t *jsonRepresentation(void) const; static bool init(void); static void finalize(void); -- 2.1.4