check radsec config when acquiring acceptor cred
[mech_eap.orig] / mech_eap / util_radius.cpp
index 5462acc..9111e20 100644 (file)
@@ -96,7 +96,7 @@ gss_eap_radius_attr_provider::initWithGssContext(const gss_eap_attr_ctx *manager
                 return false;
 
             /* We assume libradsec validated this for us */
-            assert(pairfind(m_vps, PW_MESSAGE_AUTHENTICATOR) != NULL);
+            GSSEAP_ASSERT(pairfind(m_vps, PW_MESSAGE_AUTHENTICATOR) != NULL);
             m_authenticated = true;
         }
     }
@@ -151,11 +151,21 @@ isInternalAttributeP(uint16_t attrid, uint16_t vendor)
     bool bInternalAttribute = false;
 
     /* should have been filtered */
-    assert(!isSecretAttributeP(attrid, vendor));
+    GSSEAP_ASSERT(!isSecretAttributeP(attrid, vendor));
 
     switch (vendor) {
     case VENDORPEC_UKERNA:
-        bInternalAttribute = true;
+        switch (attrid) {
+        case PW_GSS_ACCEPTOR_SERVICE_NAME:
+        case PW_GSS_ACCEPTOR_HOST_NAME:
+        case PW_GSS_ACCEPTOR_SERVICE_SPECIFIC:
+        case PW_GSS_ACCEPTOR_REALM_NAME:
+        case PW_SAML_AAA_ASSERTION:
+            bInternalAttribute = true;
+            break;
+        default:
+            break;
+        }
         break;
     default:
         break;
@@ -170,6 +180,20 @@ isInternalAttributeP(uint32_t attribute)
     return isInternalAttributeP(ATTRID(attribute), VENDOR(attribute));
 }
 
+static bool
+isFragmentedAttributeP(uint16_t attrid, uint16_t vendor)
+{
+    /* A bit of a hack for the PAC for now. Should be configurable. */
+    return (vendor == VENDORPEC_UKERNA) &&
+        !isInternalAttributeP(attrid, vendor);
+}
+
+static bool
+isFragmentedAttributeP(uint32_t attribute)
+{
+    return isFragmentedAttributeP(ATTRID(attribute), VENDOR(attribute));
+}
+
 /*
  * Copy AVP list, same as paircopy except it filters out attributes
  * containing keys.
@@ -350,6 +374,15 @@ gss_eap_radius_attr_provider::getAttribute(uint32_t attrid,
     if (i == -1)
         i = 0;
 
+    if (isSecretAttributeP(attrid) || isInternalAttributeP(attrid)) {
+        return false;
+    } else if (isFragmentedAttributeP(attrid)) {
+        return getFragmentedAttribute(attrid,
+                                      authenticated,
+                                      complete,
+                                      value);
+    }
+
     for (vp = pairfind(m_vps, attrid);
          vp != NULL;
          vp = pairfind(vp->next, attrid)) {
@@ -372,7 +405,8 @@ gss_eap_radius_attr_provider::getAttribute(uint32_t attrid,
         duplicateBuffer(valueBuf, value);
     }
 
-    if (display_value != GSS_C_NO_BUFFER) {
+    if (display_value != GSS_C_NO_BUFFER &&
+        vp->type != PW_TYPE_OCTETS) {
         char displayString[MAX_STRING_LEN];
         gss_buffer_desc displayBuf;
 
@@ -411,6 +445,16 @@ gss_eap_radius_attr_provider::getFragmentedAttribute(uint16_t attribute,
 }
 
 bool
+gss_eap_radius_attr_provider::getFragmentedAttribute(uint32_t attrid,
+                                                     int *authenticated,
+                                                     int *complete,
+                                                     gss_buffer_t value) const
+{
+    return getFragmentedAttribute(ATTRID(attrid), VENDOR(attrid),
+                                  authenticated, complete, value);
+}
+
+bool
 gss_eap_radius_attr_provider::getAttribute(uint16_t attribute,
                                            uint16_t vendor,
                                            int *authenticated,
@@ -446,32 +490,8 @@ gss_eap_radius_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_
 bool
 gss_eap_radius_attr_provider::init(void)
 {
-    struct rs_context *radContext;
-
     gss_eap_attr_ctx::registerProvider(ATTR_TYPE_RADIUS, createAttrContext);
 
-#if 1
-    /*
-     * This hack is necessary in order to force the loading of the global
-     * dictionary, otherwise accepting reauthentication tokens fails unless
-     * the acceptor has already accepted a normal authentication token.
-     */
-    if (rs_context_create(&radContext) != 0)
-        return false;
-
-    if (rs_context_read_config(radContext, RS_CONFIG_FILE) != 0) {
-        rs_context_destroy(radContext);
-        return false;
-    }
-
-    if (rs_context_init_freeradius_dict(radContext, NULL)) {
-        rs_context_destroy(radContext);
-        return false;
-    }
-
-    rs_context_destroy(radContext);
-#endif
-
     return true;
 }
 
@@ -557,8 +577,10 @@ gssEapRadiusGetAvp(OM_uint32 *minor,
     unsigned char *p;
     uint32_t attr = VENDORATTR(vendor, attribute);
 
-    buffer->length = 0;
-    buffer->value = NULL;
+    if (buffer != GSS_C_NO_BUFFER) {
+        buffer->length = 0;
+        buffer->value = NULL;
+    }
 
     vp = pairfind(vps, attr);
     if (vp == NULL) {
@@ -566,23 +588,25 @@ gssEapRadiusGetAvp(OM_uint32 *minor,
         return GSS_S_UNAVAILABLE;
     }
 
-    do {
-        buffer->length += vp->length;
-    } while (concat && (vp = pairfind(vp->next, attr)) != NULL);
+    if (buffer != GSS_C_NO_BUFFER) {
+        do {
+            buffer->length += vp->length;
+        } while (concat && (vp = pairfind(vp->next, attr)) != NULL);
 
-    buffer->value = GSSEAP_MALLOC(buffer->length);
-    if (buffer->value == NULL) {
-        *minor = ENOMEM;
-        return GSS_S_FAILURE;
-    }
+        buffer->value = GSSEAP_MALLOC(buffer->length);
+        if (buffer->value == NULL) {
+            *minor = ENOMEM;
+            return GSS_S_FAILURE;
+        }
 
-    p = (unsigned char *)buffer->value;
+        p = (unsigned char *)buffer->value;
 
-    for (vp = pairfind(vps, attr);
-         concat && vp != NULL;
-         vp = pairfind(vp->next, attr)) {
-        memcpy(p, vp->vp_octets, vp->length);
-        p += vp->length;
+        for (vp = pairfind(vps, attr);
+             concat && vp != NULL;
+             vp = pairfind(vp->next, attr)) {
+            memcpy(p, vp->vp_octets, vp->length);
+            p += vp->length;
+        }
     }
 
     *minor = 0;
@@ -623,7 +647,7 @@ avpToJson(const VALUE_PAIR *vp)
 {
     JSONObject obj;
 
-    assert(vp->length <= MAX_STRING_LEN);
+    GSSEAP_ASSERT(vp->length <= MAX_STRING_LEN);
 
     switch (vp->type) {
     case PW_TYPE_INTEGER:
@@ -761,7 +785,7 @@ gss_eap_radius_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx,
         pNext = &vp->next;
     }
 
-    m_authenticated = obj["authenticated"].integer();
+    m_authenticated = obj["authenticated"].integer() ? true : false;
 
     return true;
 }
@@ -807,7 +831,7 @@ gssEapRadiusMapError(OM_uint32 *minor,
 {
     int code;
 
-    assert(err != NULL);
+    GSSEAP_ASSERT(err != NULL);
 
     code = rs_err_code(err, 0);
 
@@ -823,3 +847,53 @@ gssEapRadiusMapError(OM_uint32 *minor,
 
     return GSS_S_FAILURE;
 }
+
+OM_uint32
+gssEapCreateRadiusContext(OM_uint32 *minor,
+                          gss_cred_id_t cred,
+                          struct rs_context **pRadContext)
+{
+    const char *configFile = RS_CONFIG_FILE;
+    struct rs_context *radContext;
+    struct rs_alloc_scheme ralloc;
+    struct rs_error *err;
+    OM_uint32 major;
+
+    *pRadContext = NULL;
+
+    if (rs_context_create(&radContext) != 0) {
+        *minor = GSSEAP_RADSEC_CONTEXT_FAILURE;
+        return GSS_S_FAILURE;
+    }
+
+    if (cred->radiusConfigFile.value != NULL)
+        configFile = (const char *)cred->radiusConfigFile.value;
+
+    ralloc.calloc  = GSSEAP_CALLOC;
+    ralloc.malloc  = GSSEAP_MALLOC;
+    ralloc.free    = GSSEAP_FREE;
+    ralloc.realloc = GSSEAP_REALLOC;
+
+    rs_context_set_alloc_scheme(radContext, &ralloc);
+
+    if (rs_context_read_config(radContext, configFile) != 0) {
+        err = rs_err_ctx_pop(radContext);
+        goto fail;
+    }
+
+    if (rs_context_init_freeradius_dict(radContext, NULL) != 0) {
+        err = rs_err_ctx_pop(radContext);
+        goto fail;
+    }
+
+    *pRadContext = radContext;
+
+    *minor = 0;
+    return GSS_S_COMPLETE;
+
+fail:
+    major = gssEapRadiusMapError(minor, err);
+    rs_context_destroy(radContext);
+
+    return major;
+}