util_radius: radius only permits 253 octets
[mech_eap.orig] / util_attr.cpp
index 57af9cd..9266b6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, JANET(UK)
+ * Copyright (c) 2011, JANET(UK)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * SUCH DAMAGE.
  */
 
+/*
+ * Attribute provider mechanism.
+ */
+
 #include "gssapiP_eap.h"
 
 #include <typeinfo>
@@ -349,7 +353,7 @@ gss_eap_attr_ctx::getPrimaryProvider(void) const
 /*
  * Set an attribute
  */
-void
+bool
 gss_eap_attr_ctx::setAttribute(int complete,
                                const gss_buffer_t attr,
                                const gss_buffer_t value)
@@ -357,34 +361,39 @@ gss_eap_attr_ctx::setAttribute(int complete,
     gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
     unsigned int type;
     gss_eap_attr_provider *provider;
+    bool ret = false;
 
     decomposeAttributeName(attr, &type, &suffix);
 
     provider = m_providers[type];
     if (provider != NULL) {
-        provider->setAttribute(complete,
-                               (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
-                               value);
-    } else {
-        /* XXX TODO throw exception */
+        ret = provider->setAttribute(complete,
+                                     (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
+                                     value);
     }
+
+    return ret;
 }
 
 /*
  * Delete an attrbiute
  */
-void
+bool
 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
 {
     gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
     unsigned int type;
     gss_eap_attr_provider *provider;
+    bool ret = false;
 
     decomposeAttributeName(attr, &type, &suffix);
 
     provider = m_providers[type];
-    if (provider != NULL)
-        provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
+    if (provider != NULL) {
+        ret = provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
+    }
+
+    return ret;
 }
 
 /*
@@ -592,25 +601,47 @@ gss_eap_attr_ctx::getExpiryTime(void) const
     return expiryTime;
 }
 
-/*
- * Map C++ exception to GSS status
- */
-static OM_uint32
-mapException(OM_uint32 *minor, std::exception &e)
+OM_uint32
+gss_eap_attr_ctx::mapException(OM_uint32 *minor, std::exception &e) const
 {
-    OM_uint32 major = GSS_S_FAILURE;
+    unsigned int i;
+    OM_uint32 major;
+
+    /* Errors we handle ourselves */
+    major = GSS_S_FAILURE;
 
-    /* XXX TODO implement other mappings */
-    if (typeid(e) == typeid(std::bad_alloc))
+    if (typeid(e) == typeid(std::bad_alloc)) {
         *minor = ENOMEM;
-    else
-        *minor = 0;
+        goto cleanup;
+    }
 
-#ifdef GSSEAP_DEBUG
+    /* Errors we delegate to providers */
+    major = GSS_S_CONTINUE_NEEDED;
+
+    for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
+        gss_eap_attr_provider *provider = m_providers[i];
+
+        if (provider == NULL)
+            continue;
+
+        major = provider->mapException(minor, e);
+        if (major != GSS_S_CONTINUE_NEEDED)
+            break;
+    }
+
+    if (major == GSS_S_CONTINUE_NEEDED) {
+        *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
+        major = GSS_S_FAILURE;
+    }
+
+cleanup:
+#if 0
     /* rethrow for now for debugging */
     throw e;
 #endif
 
+    assert(GSS_ERROR(major));
+
     return major;
 }
 
@@ -748,7 +779,7 @@ gssEapInquireName(OM_uint32 *minor,
             return GSS_S_UNAVAILABLE;
         }
     } catch (std::exception &e) {
-        return mapException(minor, e);
+        return name->attrCtx->mapException(minor, e);
     }
 
     return GSS_S_COMPLETE;
@@ -795,7 +826,7 @@ gssEapGetNameAttribute(OM_uint32 *minor,
             return GSS_S_UNAVAILABLE;
         }
     } catch (std::exception &e) {
-        return mapException(minor, e);
+        return name->attrCtx->mapException(minor, e);
     }
 
     return GSS_S_COMPLETE;
@@ -815,9 +846,14 @@ gssEapDeleteNameAttribute(OM_uint32 *minor,
         return GSS_S_UNAVAILABLE;
 
     try {
-        name->attrCtx->deleteAttribute(attr);
-    } catch (std::exception &ex) {
-        return mapException(minor, ex);
+        if (!name->attrCtx->deleteAttribute(attr)) {
+            *minor = GSSEAP_NO_SUCH_ATTR;
+            gssEapSaveStatusInfo(*minor, "Unknown naming attribute %.*s",
+                                 (int)attr->length, (char *)attr->value);
+            return GSS_S_UNAVAILABLE;
+        }
+    } catch (std::exception &e) {
+        return name->attrCtx->mapException(minor, e);
     }
 
     return GSS_S_COMPLETE;
@@ -839,9 +875,14 @@ gssEapSetNameAttribute(OM_uint32 *minor,
         return GSS_S_UNAVAILABLE;
 
     try {
-        name->attrCtx->setAttribute(complete, attr, value);
-    } catch (std::exception &ex) {
-        return mapException(minor, ex);
+        if (!name->attrCtx->setAttribute(complete, attr, value)) {
+             *minor = GSSEAP_NO_SUCH_ATTR;
+            gssEapSaveStatusInfo(*minor, "Unknown naming attribute %.*s",
+                                 (int)attr->length, (char *)attr->value);
+            return GSS_S_UNAVAILABLE;
+        }
+    } catch (std::exception &e) {
+        return name->attrCtx->mapException(minor, e);
     }
 
     return GSS_S_COMPLETE;
@@ -865,7 +906,7 @@ gssEapExportAttrContext(OM_uint32 *minor,
     try {
         name->attrCtx->exportToBuffer(buffer);
     } catch (std::exception &e) {
-        return mapException(minor, e);
+        return name->attrCtx->mapException(minor, e);
     }
 
     return GSS_S_COMPLETE;
@@ -895,7 +936,7 @@ gssEapImportAttrContext(OM_uint32 *minor,
             name->attrCtx = ctx;
         } catch (std::exception &e) {
             delete ctx;
-            return mapException(minor, e);
+            return name->attrCtx->mapException(minor, e);
         }
     }
 
@@ -926,7 +967,7 @@ gssEapDuplicateAttrContext(OM_uint32 *minor,
         }
     } catch (std::exception &e) {
         delete ctx;
-        return mapException(minor, e);
+        return in->attrCtx->mapException(minor, e);
     }
 
     return GSS_S_COMPLETE;
@@ -950,7 +991,7 @@ gssEapMapNameToAny(OM_uint32 *minor,
     try {
         *output = name->attrCtx->mapToAny(authenticated, type_id);
     } catch (std::exception &e) {
-        return mapException(minor, e);
+        return name->attrCtx->mapException(minor, e);
     }
 
     return GSS_S_COMPLETE;
@@ -975,7 +1016,7 @@ gssEapReleaseAnyNameMapping(OM_uint32 *minor,
             name->attrCtx->releaseAnyNameMapping(type_id, *input);
         *input = NULL;
     } catch (std::exception &e) {
-        return mapException(minor, e);
+        return name->attrCtx->mapException(minor, e);
     }
 
     return GSS_S_COMPLETE;
@@ -995,25 +1036,38 @@ gssEapReleaseAttrContext(OM_uint32 *minor,
  * Public accessor for initialisng a context from a GSS context. Also
  * sets expiry time on GSS context as a side-effect.
  */
-struct gss_eap_attr_ctx *
-gssEapCreateAttrContext(gss_cred_id_t gssCred,
-                        gss_ctx_id_t gssCtx)
+OM_uint32
+gssEapCreateAttrContext(OM_uint32 *minor,
+                        gss_cred_id_t gssCred,
+                        gss_ctx_id_t gssCtx,
+                        struct gss_eap_attr_ctx **pAttrContext,
+                        time_t *pExpiryTime)
 {
     gss_eap_attr_ctx *ctx;
-    OM_uint32 tmpMinor;
+    OM_uint32 major;
 
     assert(gssCtx != GSS_C_NO_CONTEXT);
 
-    if (GSS_ERROR(gssEapAttrProvidersInit(&tmpMinor)))
-        return NULL;
+    major = gssEapAttrProvidersInit(minor);
+    if (GSS_ERROR(major))
+        return major;
 
-    ctx = new gss_eap_attr_ctx();
-    if (!ctx->initFromGssContext(gssCred, gssCtx)) {
+    try {
+        ctx = new gss_eap_attr_ctx();
+        if (!ctx->initFromGssContext(gssCred, gssCtx)) {
+            delete ctx;
+            *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
+            return GSS_S_FAILURE;
+        }
+    } catch (std::exception &e) {
+        major = ctx->mapException(minor, e);
         delete ctx;
-        return NULL;
+        return major;
     }
 
-    gssCtx->expiryTime = ctx->getExpiryTime();
+    *pAttrContext = ctx;
+    *pExpiryTime = ctx->getExpiryTime();
 
-    return ctx;
+    *minor = 0;
+    return GSS_S_COMPLETE;
 }