use JSON instead of DDF marshalling
authorLuke Howard <lukeh@padl.com>
Sun, 27 Mar 2011 15:21:27 +0000 (02:21 +1100)
committerLuke Howard <lukeh@padl.com>
Sun, 27 Mar 2011 23:01:14 +0000 (10:01 +1100)
use our own base64 routines

14 files changed:
Makefile.am
acinclude.m4
configure.ac
util.h
util_attr.cpp
util_attr.h
util_base64.c [new file with mode: 0644]
util_base64.h [new file with mode: 0644]
util_radius.cpp
util_radius.h
util_saml.cpp
util_saml.h
util_shib.cpp
util_shib.h

index f87406a..d2c8583 100644 (file)
@@ -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                            \
index ad31df8..eab00b4 100644 (file)
@@ -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
index 0115b0b..a7e6942 100644 (file)
@@ -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 (file)
--- 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
index 80d2781..28e6356 100644 (file)
@@ -40,6 +40,7 @@
 #include <string>
 #include <sstream>
 #include <exception>
+#include <stdexcept>
 #include <new>
 
 /* 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);
 }
 
 /*
index 347842a..1a427f7 100644 (file)
@@ -41,9 +41,7 @@
 #include <string>
 #include <new>
 
-#include <shibsp/remoting/ddf.h>
-
-using namespace shibsp;
+#include <jansson.h>
 
 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 (file)
index 0000000..8d13aaf
--- /dev/null
@@ -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 (file)
index 0000000..98f0c1f
--- /dev/null
@@ -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
index a272759..4e2f6e0 100644 (file)
@@ -36,8 +36,6 @@
 
 #include "gssapiP_eap.h"
 
-#include <xercesc/util/Base64.hpp>
-
 /* 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;
 }
 
index 0335dc8..656f1b7 100644 (file)
@@ -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,
index 1a2c81e..8722b84 100644 (file)
@@ -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)
 {
index 351e70d..0a14d3e 100644 (file)
@@ -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,
index a53a476..14757d1 100644 (file)
@@ -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<Attribute*>::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;
index db931fb..7cacd66 100644 (file)
@@ -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);