fix exception to GSS error code mapping
authorLuke Howard <lukeh@padl.com>
Wed, 30 Mar 2011 04:00:04 +0000 (15:00 +1100)
committerLuke Howard <lukeh@padl.com>
Wed, 30 Mar 2011 04:00:04 +0000 (15:00 +1100)
mech_eap/util_attr.cpp
mech_eap/util_attr.h
mech_eap/util_json.cpp
mech_eap/util_json.h
mech_eap/util_radius.cpp
mech_eap/util_saml.cpp
mech_eap/util_shib.cpp

index a25d2ff..4ded612 100644 (file)
@@ -40,7 +40,6 @@
 #include <string>
 #include <sstream>
 #include <exception>
-#include <stdexcept>
 #include <new>
 
 /* lazy initialisation */
@@ -534,7 +533,7 @@ gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
 
     major = gss_create_empty_buffer_set(&minor, attrs);
     if (GSS_ERROR(major))
-        throw new std::bad_alloc;
+        throw std::bad_alloc();
 
     args.attrs = *attrs;
 
@@ -642,7 +641,7 @@ gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
     s = obj.dump(JSON_COMPACT);
 
     if (GSS_ERROR(makeStringBuffer(&minor, s, buffer)))
-        throw new std::bad_alloc;
+        throw std::bad_alloc();
 }
 
 /*
@@ -683,12 +682,10 @@ gss_eap_attr_ctx::mapException(OM_uint32 *minor, std::exception &e) const
         major = GSS_S_FAILURE;
         *minor = ENOMEM;
         goto cleanup;
-    } else if (typeid(e) == typeid(std::runtime_error)) {
+    } else if (typeid(e) == typeid(JSONException)) {
         major = GSS_S_BAD_NAME;
         *minor = GSSEAP_BAD_ATTR_TOKEN;
-        goto cleanup;
-    } else if (this == NULL) {
-        major = GSS_S_FAILURE;
+        gssEapSaveStatusInfo(*minor, "%s", e.what());
         goto cleanup;
     }
 
@@ -712,11 +709,6 @@ gss_eap_attr_ctx::mapException(OM_uint32 *minor, std::exception &e) const
     }
 
 cleanup:
-#if 0
-    /* rethrow for now for debugging */
-    throw e;
-#endif
-
     assert(GSS_ERROR(major));
 
     return major;
@@ -1009,29 +1001,38 @@ gssEapImportAttrContext(OM_uint32 *minor,
                         gss_name_t name)
 {
     gss_eap_attr_ctx *ctx = NULL;
+    OM_uint32 major = GSS_S_FAILURE;
 
     assert(name->attrCtx == NULL);
 
     if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
         return GSS_S_UNAVAILABLE;
 
-    if (buffer->length != 0) {
-        try {
-            ctx = new gss_eap_attr_ctx();
+    if (buffer->length == 0)
+        return GSS_S_COMPLETE;
 
-            if (!ctx->initFromBuffer(buffer)) {
-                delete ctx;
-                *minor = GSSEAP_BAD_ATTR_TOKEN;
-                return GSS_S_BAD_NAME;
-            }
+    try {
+        ctx = new gss_eap_attr_ctx();
+
+        if (ctx->initFromBuffer(buffer)) {
             name->attrCtx = ctx;
-        } catch (std::exception &e) {
-            delete ctx;
-            return name->attrCtx->mapException(minor, e);
+            major = GSS_S_COMPLETE;
+            *minor = 0;
+        } else {
+            major = GSS_S_BAD_NAME;
+            *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
         }
+    } catch (std::exception &e) {
+        if (ctx != NULL)
+            major = ctx->mapException(minor, e);
     }
 
-    return GSS_S_COMPLETE;
+    assert(major == GSS_S_COMPLETE || name->attrCtx == NULL);
+
+    if (GSS_ERROR(major))
+        delete ctx;
+
+    return major;
 }
 
 OM_uint32
@@ -1040,27 +1041,38 @@ gssEapDuplicateAttrContext(OM_uint32 *minor,
                            gss_name_t out)
 {
     gss_eap_attr_ctx *ctx = NULL;
+    OM_uint32 major = GSS_S_FAILURE;
 
     assert(out->attrCtx == NULL);
 
+    if (in->attrCtx == NULL) {
+        *minor = 0;
+        return GSS_S_COMPLETE;
+    }
+
     if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
         return GSS_S_UNAVAILABLE;
 
     try {
-        if (in->attrCtx != NULL) {
-            ctx = new gss_eap_attr_ctx();
-            if (!ctx->initFromExistingContext(in->attrCtx)) {
-                delete ctx;
-                *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
-                return GSS_S_FAILURE;
-            }
+        ctx = new gss_eap_attr_ctx();
+
+        if (ctx->initFromExistingContext(in->attrCtx)) {
             out->attrCtx = ctx;
+            major = GSS_S_COMPLETE;
+            *minor = 0;
+        } else {
+            major = GSS_S_FAILURE;
+            *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
         }
     } catch (std::exception &e) {
-        delete ctx;
-        return in->attrCtx->mapException(minor, e);
+        major = in->attrCtx->mapException(minor, e);
     }
 
+    assert(major == GSS_S_COMPLETE || out->attrCtx == NULL);
+
+    if (GSS_ERROR(major))
+        delete ctx;
+
     return GSS_S_COMPLETE;
 }
 
@@ -1140,18 +1152,21 @@ gssEapCreateAttrContext(OM_uint32 *minor,
 
     assert(gssCtx != GSS_C_NO_CONTEXT);
 
+    *pAttrContext = NULL;
+
     major = gssEapAttrProvidersInit(minor);
     if (GSS_ERROR(major))
         return major;
 
-    *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
-    major = GSS_S_FAILURE;
-
     try {
-        *pAttrContext = ctx = new gss_eap_attr_ctx();
+        ctx = new gss_eap_attr_ctx();
+
         if (ctx->initFromGssContext(gssCred, gssCtx)) {
-            *minor = 0;
             major = GSS_S_COMPLETE;
+            *minor = 0;
+        } else {
+            major = GSS_S_FAILURE;
+            *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
         }
     } catch (std::exception &e) {
         if (ctx != NULL)
@@ -1160,10 +1175,11 @@ gssEapCreateAttrContext(OM_uint32 *minor,
 
     if (major == GSS_S_COMPLETE) {
         *pExpiryTime = ctx->getExpiryTime();
-    } else {
-        delete ctx;
-        *pAttrContext = NULL;
+        *pAttrContext = ctx;
     }
 
+    if (GSS_ERROR(major))
+        delete ctx;
+
     return major;
 }
index e391df1..c727e82 100644 (file)
@@ -281,7 +281,7 @@ duplicateBuffer(gss_buffer_desc &src, gss_buffer_t dst)
     OM_uint32 minor;
 
     if (GSS_ERROR(duplicateBuffer(&minor, &src, dst)))
-        throw new std::bad_alloc();
+        throw std::bad_alloc();
 }
 
 static inline void
index 0e4c215..0133772 100644 (file)
 #include <string>
 #include <sstream>
 #include <exception>
-#include <stdexcept>
 #include <new>
 
 #define JSON_INIT(obj) do {                                     \
         if ((obj) == NULL)                                      \
-            throw new std::bad_alloc;                           \
+            throw std::bad_alloc();                             \
         m_obj = (obj);                                          \
     } while (0)
 
 #define JSON_CHECK_CONTAINER() do {                             \
         if (!json_is_object(m_obj) && !json_is_array(m_obj)) {  \
             std::string s("JSONObject is not a container");     \
-            throw new std::runtime_error(s);                    \
+            throw JSONException(m_obj);                         \
         }                                                       \
     } while (0)
 
 #define JSON_CHECK_OBJECT() do {                                \
         if (!json_is_object(m_obj)) {                           \
             std::string s("JSONObject is not a dictionary");    \
-            throw new std::runtime_error(s);                    \
+            throw JSONException(m_obj, JSON_OBJECT);            \
         }                                                       \
     } 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);                    \
+            throw JSONException(m_obj, JSON_ARRAY);             \
         }                                                       \
     } while (0)
 
-#define JSON_CHECK(s) do {              \
-        if ((s) != 0)                   \
-            throw new std::bad_alloc;   \
+#define JSON_CHECK(s) do {                                      \
+        if ((s) != 0)                                           \
+            throw JSONException();                              \
     } while (0)
 
 JSONObject
@@ -101,7 +99,7 @@ JSONObject::dump(size_t flags) const
     char *s = json_dumps(m_obj, flags);
 
     if (s == NULL)
-        throw new std::bad_alloc;
+        throw std::bad_alloc();
 
     return s;
 }
@@ -112,7 +110,7 @@ JSONObject::dump(FILE *fp, size_t flags) const
     int r = json_dumpf(m_obj, fp, flags);
 
     if (r != 0)
-        throw new std::bad_alloc;
+        throw std::bad_alloc();
 }
 
 size_t
@@ -362,7 +360,7 @@ JSONObject::ddf(DDF &ddf)
     }
 
     std::string s("Unbridgeable DDF object");
-    throw new std::runtime_error(s);
+    throw JSONException();
 }
 
 DDF
@@ -476,3 +474,38 @@ JSONIterator::next(void)
     m_iter = json_object_iter_next(m_obj, m_iter);
     return m_iter != NULL;
 }
+
+JSONException::JSONException(json_t *obj, json_type type)
+{
+    char *s = NULL;
+    const char *t;
+
+    m_obj = json_incref(obj);
+    m_type = type;
+
+    if (obj != NULL)
+        s = json_dumps(m_obj, 0);
+
+    switch (type) {
+    case JSON_OBJECT:   t = "OBJECT";   break;
+    case JSON_ARRAY:    t = "ARRAY";    break;
+    case JSON_STRING:   t = "STRING";   break;
+    case JSON_INTEGER:  t = "INTEGER";  break;
+    case JSON_REAL:     t = "REAL";     break;
+    case JSON_TRUE:     t = "TRUE";     break;
+    case JSON_FALSE:    t = "FALSE";    break;
+    case JSON_NULL:     t = "NULL";     break;
+    default:            t = "UNKNOWN";  break;
+    }
+
+    if (obj != NULL) {
+        m_reason = "Invalid JSON object: " + std::string(s);
+        if (type != JSON_NULL)
+            m_reason += " (excepted type " + std::string(t) + ")";
+    } else {
+        m_reason = "Internal JSON error";
+    }
+
+    if (s != NULL)
+        GSSEAP_FREE(s);
+}
index 43d3275..e2c5e29 100644 (file)
@@ -49,6 +49,24 @@ using namespace shibsp;
 namespace gss_eap_util {
     class JSONObject;
 
+    class JSONException : public std::exception {
+    public:
+        JSONException(json_t *obj = NULL, json_type type = JSON_NULL);
+
+        ~JSONException(void) throw() {
+            json_decref(m_obj);
+        }
+
+        virtual const char *what(void) const throw() {
+            return m_reason.c_str();
+        }
+
+    private:
+        json_t *m_obj;
+        json_type m_type;
+        std::string m_reason;
+    };
+
     class JSONIterator {
     public:
         JSONIterator(const JSONObject &obj);
index 05d697e..09f4559 100644 (file)
@@ -189,7 +189,7 @@ copyAvps(const VALUE_PAIR *src)
         vpcopy = paircopyvp(vp);
         if (vpcopy == NULL) {
             pairfree(&dst);
-            throw new std::bad_alloc;
+            throw std::bad_alloc();
             return NULL;
         }
         *pDst = vpcopy;
@@ -639,7 +639,7 @@ avpToJson(const VALUE_PAIR *vp)
         char *b64;
 
         if (base64Encode(vp->vp_octets, vp->length, &b64) < 0)
-            throw new std::bad_alloc;
+            throw std::bad_alloc();
 
         obj.set("value", b64);
         GSSEAP_FREE(b64);
@@ -674,7 +674,7 @@ jsonToAvp(VALUE_PAIR **pVp, JSONObject &obj)
         vp = paircreate(attrid, PW_TYPE_OCTETS);
     }
     if (vp == NULL) {
-        throw new std::bad_alloc;
+        throw std::bad_alloc();
         goto fail;
     }
 
@@ -722,6 +722,7 @@ jsonToAvp(VALUE_PAIR **pVp, JSONObject &obj)
         size_t valueLen = base64Decode(str, vp->vp_octets);
         if (valueLen < 0) {
             if (da == NULL && stringLen < MAX_STRING_LEN) {
+                vp->type = PW_TYPE_STRING;
                 vp->length = stringLen;
                 memcpy(vp->vp_strvalue, str, stringLen + 1);
             } else
index 8722b84..2187f48 100644 (file)
@@ -252,6 +252,8 @@ gss_eap_saml_assertion_provider::mapException(OM_uint32 *minor,
     else
         return GSS_S_CONTINUE_NEEDED;
 
+    gssEapSaveStatusInfo(*minor, "%s", e.what());
+
     return GSS_S_FAILURE;
 }
 
index 84a9584..dd4fe3f 100644 (file)
@@ -130,7 +130,7 @@ exportMechSecContext(OM_uint32 *minor,
     mechContext->value = p = (unsigned char *)GSSEAP_MALLOC(mechContext->length);
     if (mechContext->value == NULL) {
         gss_release_buffer(minor, &exportedCtx);
-        throw new std::bad_alloc;
+        throw std::bad_alloc();
     }
 
     p = store_oid(gssCtx->mechanismUsed, p);
@@ -186,6 +186,7 @@ gss_eap_shib_attr_provider::initFromGssContext(const gss_eap_attr_ctx *manager,
         m_attributes = resolver->getResolvedAttributes();
         resolver->getResolvedAttributes().clear();
     } catch (exception &e) {
+        return false;
     }
 
     m_authenticated = true;
@@ -407,13 +408,9 @@ gss_eap_shib_attr_provider::jsonRepresentation(void) const
 
     for (vector<Attribute*>::const_iterator a = m_attributes.begin();
          a != m_attributes.end(); ++a) {
-        try {
-            DDF attr = (*a)->marshall();
-            JSONObject jattr = JSONObject::ddf(attr);
-            jattrs.append(jattr);
-        } catch (AttributeException &e) {
-            /* XXX FIXME ignore attribute exceptions? */
-        }
+        DDF attr = (*a)->marshall();
+        JSONObject jattr = JSONObject::ddf(attr);
+        jattrs.append(jattr);
     }
 
     obj.set("attributes", jattrs);
@@ -439,13 +436,9 @@ gss_eap_shib_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx,
     for (size_t i = 0; i < nelems; i++) {
         JSONObject jattr = jattrs.get(i);
 
-        try {
-            DDF attr = jattr.ddf();
-            Attribute *attribute = Attribute::unmarshall(attr);
-            m_attributes.push_back(attribute);
-        } catch (AttributeException &e) {
-            return false;
-        }
+        DDF attr = jattr.ddf();
+        Attribute *attribute = Attribute::unmarshall(attr);
+        m_attributes.push_back(attribute);
     }
 
     m_authenticated = obj["authenticated"].integer();