X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=mech_eap%2Futil_radius.cpp;h=d8ec3df4d2550468bb7bdcd3c4b3dca1d520d8a6;hp=5462acc1f197ea8f030fdcc240c38304fb7e0110;hb=HEAD;hpb=10a3b578c38207140378a98c024c03d85941f837 diff --git a/mech_eap/util_radius.cpp b/mech_eap/util_radius.cpp index 5462acc..d8ec3df 100644 --- a/mech_eap/util_radius.cpp +++ b/mech_eap/util_radius.cpp @@ -35,20 +35,37 @@ */ #include "gssapiP_eap.h" +#include "util_radius.h" +#include "utils/radius_utils.h" -/* stuff that should be provided by libradsec/libfreeradius-radius */ -#define VENDORATTR(vendor, attr) (((vendor) << 16) | (attr)) +#ifdef GSSEAP_ENABLE_ACCEPTOR -#ifndef ATTRID -#define ATTRID(attr) ((attr) & 0xFFFF) -#endif +#define RS_MAP_ERROR(code) (ERROR_TABLE_BASE_rse + (code)) -static gss_buffer_desc radiusUrnPrefix = { - sizeof("urn:x-radius:") - 1, - (void *)"urn:x-radius:" -}; +static rs_avp *copyAvps(rs_const_avp *src); -static VALUE_PAIR *copyAvps(const VALUE_PAIR *src); +static OM_uint32 +gssEapRadiusGetAvp(OM_uint32 *minor, + rs_avp *vps, + const gss_eap_attrid &attrid, + gss_buffer_t buffer, + int concat); + +static OM_uint32 +gssEapRadiusAddAvp(OM_uint32 *minor, + rs_avp **vps, + const gss_eap_attrid &attrid, + const gss_buffer_t buffer); + +static gss_eap_attrid +avpToAttrId(rs_const_avp *vp) +{ + gss_eap_attrid attrid; + + rs_avp_attrid(vp, &attrid.second, &attrid.first); + + return attrid; +} gss_eap_radius_attr_provider::gss_eap_radius_attr_provider(void) { @@ -59,7 +76,7 @@ gss_eap_radius_attr_provider::gss_eap_radius_attr_provider(void) gss_eap_radius_attr_provider::~gss_eap_radius_attr_provider(void) { if (m_vps != NULL) - pairfree(&m_vps); + rs_avp_free(&m_vps); } bool @@ -74,7 +91,7 @@ gss_eap_radius_attr_provider::initWithExistingContext(const gss_eap_attr_ctx *ma radius = static_cast(ctx); if (radius->m_vps != NULL) - m_vps = copyAvps(const_cast(radius->getAvps())); + m_vps = copyAvps(radius->getAvps()); m_authenticated = radius->m_authenticated; @@ -96,7 +113,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(rs_avp_find(m_vps, PW_MESSAGE_AUTHENTICATOR, 0) != NULL); m_authenticated = true; } } @@ -105,12 +122,14 @@ gss_eap_radius_attr_provider::initWithGssContext(const gss_eap_attr_ctx *manager } static bool -alreadyAddedAttributeP(std::vector &attrs, VALUE_PAIR *vp) +alreadyAddedAttributeP(std::vector &attrs, + gss_eap_attrid &attrid) { - for (std::vector::const_iterator a = attrs.begin(); + for (std::vector::const_iterator a = attrs.begin(); a != attrs.end(); ++a) { - if (strcmp(vp->name, (*a).c_str()) == 0) + if (attrid.first == (*a).first && + attrid.second == (*a).second) return true; } @@ -118,13 +137,13 @@ alreadyAddedAttributeP(std::vector &attrs, VALUE_PAIR *vp) } static bool -isSecretAttributeP(uint16_t attrid, uint16_t vendor) +isSecretAttributeP(const gss_eap_attrid &attrid) { bool bSecretAttribute = false; - switch (vendor) { - case VENDORPEC_MS: - switch (attrid) { + switch (attrid.first) { + case VENDORPEC_MICROSOFT: + switch (attrid.second) { case PW_MS_MPPE_SEND_KEY: case PW_MS_MPPE_RECV_KEY: bSecretAttribute = true; @@ -140,22 +159,40 @@ isSecretAttributeP(uint16_t attrid, uint16_t vendor) } static bool -isSecretAttributeP(uint32_t attribute) +isSecretAttributeP(rs_const_avp *vp) { - return isSecretAttributeP(ATTRID(attribute), VENDOR(attribute)); + return isSecretAttributeP(avpToAttrId(vp)); } static bool -isInternalAttributeP(uint16_t attrid, uint16_t vendor) +isInternalAttributeP(const gss_eap_attrid &attrid) { bool bInternalAttribute = false; /* should have been filtered */ - assert(!isSecretAttributeP(attrid, vendor)); + GSSEAP_ASSERT(!isSecretAttributeP(attrid)); - switch (vendor) { + switch (attrid.first) { case VENDORPEC_UKERNA: - bInternalAttribute = true; + switch (attrid.second) { + case PW_SAML_AAA_ASSERTION: + bInternalAttribute = true; + break; + default: + break; + } + break; + case 0: + switch (attrid.second) { + case PW_GSS_ACCEPTOR_SERVICE_NAME: + case PW_GSS_ACCEPTOR_HOST_NAME: + case PW_GSS_ACCEPTOR_SERVICE_SPECIFICS: + case PW_GSS_ACCEPTOR_REALM_NAME: + bInternalAttribute = true; + break; + default: + break; + } break; default: break; @@ -165,34 +202,42 @@ isInternalAttributeP(uint16_t attrid, uint16_t vendor) } static bool -isInternalAttributeP(uint32_t attribute) +isInternalAttributeP(rs_const_avp *vp) { - return isInternalAttributeP(ATTRID(attribute), VENDOR(attribute)); + return isInternalAttributeP(avpToAttrId(vp)); +} + +static bool +isFragmentedAttributeP(const gss_eap_attrid &attrid) +{ + /* A bit of a hack for the PAC for now. Should be configurable. */ + return (attrid.first == VENDORPEC_UKERNA) && + !isInternalAttributeP(attrid); } /* * Copy AVP list, same as paircopy except it filters out attributes * containing keys. */ -static VALUE_PAIR * -copyAvps(const VALUE_PAIR *src) +static rs_avp * +copyAvps(rs_const_avp *src) { - const VALUE_PAIR *vp; - VALUE_PAIR *dst = NULL, **pDst = &dst; + rs_const_avp *vp; + rs_avp *dst = NULL; - for (vp = src; vp != NULL; vp = vp->next) { - VALUE_PAIR *vpcopy; + for (vp = src; vp != NULL; vp = rs_avp_next_const(vp)) { + rs_avp *vpcopy; - if (isSecretAttributeP(vp->attribute)) + if (isSecretAttributeP(vp)) continue; - vpcopy = paircopyvp(vp); + vpcopy = rs_avp_dup(vp); if (vpcopy == NULL) { - pairfree(&dst); + rs_avp_free(&dst); throw std::bad_alloc(); } - *pDst = vpcopy; - pDst = &vpcopy->next; + + rs_avp_append(&dst, vpcopy); } return dst; @@ -202,68 +247,78 @@ bool gss_eap_radius_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute, void *data) const { - VALUE_PAIR *vp; - std::vector seen; + rs_avp *vp; + std::vector seen; - for (vp = m_vps; vp != NULL; vp = vp->next) { - gss_buffer_desc attribute; - char attrid[64]; + for (vp = m_vps; vp != NULL; vp = rs_avp_next(vp)) { + gss_buffer_desc desc; + gss_eap_attrid attrid; + char buf[64]; /* Don't advertise attributes that are internal to the GSS-EAP mechanism */ - if (isInternalAttributeP(vp->attribute)) + if (isInternalAttributeP(vp)) continue; - if (alreadyAddedAttributeP(seen, vp)) + rs_avp_attrid(vp, &attrid.second, &attrid.first); + + if (alreadyAddedAttributeP(seen, attrid)) continue; - snprintf(attrid, sizeof(attrid), "%s%d", - (char *)radiusUrnPrefix.value, vp->attribute); + if (rs_attr_display_name(attrid.second, attrid.first, + buf, sizeof(buf), TRUE) != RSE_OK || + strncmp(buf, "Attr-", 5) != 0) + continue; - attribute.value = attrid; - attribute.length = strlen(attrid); + desc.value = &buf[5]; + desc.length = strlen((char *)desc.value); - if (!addAttribute(m_manager, this, &attribute, data)) + if (!addAttribute(m_manager, this, &desc, data)) return false; - seen.push_back(std::string(vp->name)); + seen.push_back(attrid); } return true; } -uint32_t -getAttributeId(const gss_buffer_t attr) +static bool +getAttributeId(const gss_buffer_t desc, + gss_eap_attrid *attrid) { - OM_uint32 tmpMinor; - gss_buffer_desc strAttr = GSS_C_EMPTY_BUFFER; - DICT_ATTR *da; - char *s; - uint32_t attrid = 0; + char *strAttr, *s; + int canon, code; - if (attr->length < radiusUrnPrefix.length || - memcmp(attr->value, radiusUrnPrefix.value, radiusUrnPrefix.length) != 0) - return 0; + if (desc->length == 0) + return false; + + canon = isdigit(*(char *)desc->value); /* need to duplicate because attr may not be NUL terminated */ - duplicateBuffer(*attr, &strAttr); - s = (char *)strAttr.value + radiusUrnPrefix.length; + strAttr = (char *)GSSEAP_MALLOC((canon ? 5 : 0) + desc->length + 1); + if (strAttr == NULL) + throw new std::bad_alloc(); - if (isdigit(*s)) { - attrid = strtoul(s, NULL, 10); - } else { - da = dict_attrbyname(s); - if (da != NULL) - attrid = da->attr; + s = strAttr; + + if (canon) { + memcpy(s, "Attr-", 5); + s += 5; } - gss_release_buffer(&tmpMinor, &strAttr); + memcpy(s, desc->value, desc->length); + s += desc->length; + *s = '\0'; - return attrid; + code = rs_attr_parse_name(strAttr, &attrid->second, &attrid->first); + + GSSEAP_FREE(strAttr); + + return (code == RSE_OK); } bool gss_eap_radius_attr_provider::setAttribute(int complete GSSEAP_UNUSED, - uint32_t attrid, + const gss_eap_attrid &attrid, const gss_buffer_t value) { OM_uint32 major = GSS_S_UNAVAILABLE, minor; @@ -272,9 +327,7 @@ gss_eap_radius_attr_provider::setAttribute(int complete GSSEAP_UNUSED, !isInternalAttributeP(attrid)) { deleteAttribute(attrid); - major = gssEapRadiusAddAvp(&minor, &m_vps, - ATTRID(attrid), VENDOR(attrid), - value); + major = gssEapRadiusAddAvp(&minor, &m_vps, attrid, value); } return !GSS_ERROR(major); @@ -285,32 +338,31 @@ gss_eap_radius_attr_provider::setAttribute(int complete, const gss_buffer_t attr, const gss_buffer_t value) { - uint32_t attrid = getAttributeId(attr); + gss_eap_attrid attrid; - if (!attrid) + if (!getAttributeId(attr, &attrid)) return false; return setAttribute(complete, attrid, value); } bool -gss_eap_radius_attr_provider::deleteAttribute(uint32_t attrid) +gss_eap_radius_attr_provider::deleteAttribute(const gss_eap_attrid &attrid) { - if (isSecretAttributeP(attrid) || isInternalAttributeP(attrid) || - pairfind(m_vps, attrid) == NULL) + if (isSecretAttributeP(attrid) || + isInternalAttributeP(attrid) || + rs_avp_find(m_vps, attrid.second, attrid.first) == NULL) return false; - pairdelete(&m_vps, attrid); - - return true; + return (rs_avp_delete(&m_vps, attrid.second, attrid.first) == RSE_OK); } bool gss_eap_radius_attr_provider::deleteAttribute(const gss_buffer_t attr) { - uint32_t attrid = getAttributeId(attr); + gss_eap_attrid attrid; - if (!attrid) + if (!getAttributeId(attr, &attrid)) return false; return deleteAttribute(attrid); @@ -324,25 +376,25 @@ gss_eap_radius_attr_provider::getAttribute(const gss_buffer_t attr, gss_buffer_t display_value, int *more) const { - uint32_t attrid; + gss_eap_attrid attrid; - attrid = getAttributeId(attr); - if (!attrid) + if (!getAttributeId(attr, &attrid)) return false; - return getAttribute(attrid, authenticated, complete, + return getAttribute(attrid, + authenticated, complete, value, display_value, more); } bool -gss_eap_radius_attr_provider::getAttribute(uint32_t attrid, +gss_eap_radius_attr_provider::getAttribute(const gss_eap_attrid &attrid, int *authenticated, int *complete, gss_buffer_t value, gss_buffer_t display_value, int *more) const { - VALUE_PAIR *vp; + rs_const_avp *vp; int i = *more, count = 0; *more = 0; @@ -350,11 +402,21 @@ gss_eap_radius_attr_provider::getAttribute(uint32_t attrid, if (i == -1) i = 0; - for (vp = pairfind(m_vps, attrid); + if (isSecretAttributeP(attrid) || + isInternalAttributeP(attrid)) { + return false; + } else if (isFragmentedAttributeP(attrid)) { + return getFragmentedAttribute(attrid, + authenticated, + complete, + value); + } + + for (vp = rs_avp_find_const(m_vps, attrid.second, attrid.first); vp != NULL; - vp = pairfind(vp->next, attrid)) { + vp = rs_avp_find_const(rs_avp_next_const(vp), attrid.second, attrid.first)) { if (count++ == i) { - if (pairfind(vp->next, attrid) != NULL) + if (rs_avp_find_const(rs_avp_next_const(vp), attrid.second, attrid.first) != NULL) *more = count; break; } @@ -366,18 +428,20 @@ gss_eap_radius_attr_provider::getAttribute(uint32_t attrid, if (value != GSS_C_NO_BUFFER) { gss_buffer_desc valueBuf; - valueBuf.value = (void *)vp->vp_octets; - valueBuf.length = vp->length; + rs_avp_octets_value_byref((rs_avp *)vp, + (unsigned char **)&valueBuf.value, + &valueBuf.length); duplicateBuffer(valueBuf, value); } - if (display_value != GSS_C_NO_BUFFER) { - char displayString[MAX_STRING_LEN]; + if (display_value != GSS_C_NO_BUFFER && + !rs_avp_is_octets(vp)) { + char displayString[RS_MAX_STRING_LEN]; gss_buffer_desc displayBuf; - displayBuf.length = vp_prints_value(displayString, - sizeof(displayString), vp, 0); + displayBuf.length = rs_avp_display_value(vp, displayString, + sizeof(displayString)); displayBuf.value = (void *)displayString; duplicateBuffer(displayBuf, display_value); @@ -392,15 +456,14 @@ gss_eap_radius_attr_provider::getAttribute(uint32_t attrid, } bool -gss_eap_radius_attr_provider::getFragmentedAttribute(uint16_t attribute, - uint16_t vendor, +gss_eap_radius_attr_provider::getFragmentedAttribute(const gss_eap_attrid &attrid, int *authenticated, int *complete, gss_buffer_t value) const { OM_uint32 major, minor; - major = gssEapRadiusGetAvp(&minor, m_vps, attribute, vendor, value, TRUE); + major = gssEapRadiusGetAvp(&minor, m_vps, attrid, value, TRUE); if (authenticated != NULL) *authenticated = m_authenticated; @@ -410,21 +473,6 @@ gss_eap_radius_attr_provider::getFragmentedAttribute(uint16_t attribute, return !GSS_ERROR(major); } -bool -gss_eap_radius_attr_provider::getAttribute(uint16_t attribute, - uint16_t vendor, - int *authenticated, - int *complete, - gss_buffer_t value, - gss_buffer_t display_value, - int *more) const -{ - - return getAttribute(VENDORATTR(attribute, vendor), - authenticated, complete, - value, display_value, more); -} - gss_any_t gss_eap_radius_attr_provider::mapToAny(int authenticated, gss_buffer_t type_id GSSEAP_UNUSED) const @@ -439,39 +487,15 @@ void gss_eap_radius_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED, gss_any_t input) const { - VALUE_PAIR *vp = (VALUE_PAIR *)input; - pairfree(&vp); + rs_avp *vp = (rs_avp *)input; + rs_avp_free(&vp); } 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; } @@ -487,38 +511,35 @@ gss_eap_radius_attr_provider::createAttrContext(void) return new gss_eap_radius_attr_provider; } -OM_uint32 +static OM_uint32 gssEapRadiusAddAvp(OM_uint32 *minor, - VALUE_PAIR **vps, - uint16_t attribute, - uint16_t vendor, + rs_avp **vps, + const gss_eap_attrid &attrid, const gss_buffer_t buffer) { - uint32_t attrid = VENDORATTR(vendor, attribute); unsigned char *p = (unsigned char *)buffer->value; size_t remain = buffer->length; do { - VALUE_PAIR *vp; + rs_avp *vp; size_t n = remain; /* * There's an extra byte of padding; RADIUS AVPs can only * be 253 octets. */ - if (n >= MAX_STRING_LEN) - n = MAX_STRING_LEN - 1; + if (n >= RS_MAX_STRING_LEN) + n = RS_MAX_STRING_LEN - 1; - vp = paircreate(attrid, PW_TYPE_OCTETS); + vp = rs_avp_alloc(attrid.second, attrid.first); if (vp == NULL) { *minor = ENOMEM; return GSS_S_FAILURE; } - memcpy(vp->vp_octets, p, n); - vp->length = n; + rs_avp_octets_set(vp, p, n); - pairadd(vps, vp); + rs_avp_append(vps, vp); p += n; remain -= n; @@ -528,15 +549,34 @@ gssEapRadiusAddAvp(OM_uint32 *minor, } OM_uint32 -gssEapRadiusGetRawAvp(OM_uint32 *minor, - VALUE_PAIR *vps, - uint16_t attribute, - uint16_t vendor, - VALUE_PAIR **vp) +gssEapRadiusAddAvp(OM_uint32 *minor, + struct rs_packet *pkt, + unsigned int attribute, + unsigned int vendor, + const gss_buffer_t buffer) { - uint32_t attr = VENDORATTR(vendor, attribute); + gss_eap_attrid attrid(vendor, attribute); + int code; + + code = rs_packet_append_avp(pkt, attrid.second, attrid.first, + buffer->value, buffer->length); + if (code != RSE_OK) { + *minor = RS_MAP_ERROR(code); + return GSS_S_FAILURE; + } - *vp = pairfind(vps, attr); + *minor = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +gssEapRadiusGetRawAvp(OM_uint32 *minor, + rs_const_avp *vps, + unsigned int attribute, + unsigned int vendor, + rs_const_avp **vp) +{ + *vp = rs_avp_find_const(vps, attribute, vendor); if (*vp == NULL) { *minor = GSSEAP_NO_SUCH_ATTR; return GSS_S_UNAVAILABLE; @@ -545,44 +585,48 @@ gssEapRadiusGetRawAvp(OM_uint32 *minor, return GSS_S_COMPLETE; } -OM_uint32 +static OM_uint32 gssEapRadiusGetAvp(OM_uint32 *minor, - VALUE_PAIR *vps, - uint16_t attribute, - uint16_t vendor, + rs_avp *vps, + const gss_eap_attrid &attrid, gss_buffer_t buffer, int concat) { - VALUE_PAIR *vp; - unsigned char *p; - uint32_t attr = VENDORATTR(vendor, attribute); + rs_const_avp *vp; + int err; - buffer->length = 0; - buffer->value = NULL; + if (buffer != GSS_C_NO_BUFFER) { + buffer->length = 0; + buffer->value = NULL; + } - vp = pairfind(vps, attr); + vp = rs_avp_find_const(vps, attrid.second, attrid.first); if (vp == NULL) { *minor = GSSEAP_NO_SUCH_ATTR; return GSS_S_UNAVAILABLE; } - do { - buffer->length += vp->length; - } while (concat && (vp = pairfind(vp->next, attr)) != NULL); + if (buffer != GSS_C_NO_BUFFER) { + if (concat) + rs_avp_fragmented_value(vp, NULL, &buffer->length); + else + buffer->length = rs_avp_length(vp); - 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; + if (concat) + err = rs_avp_fragmented_value(vp, (unsigned char *)buffer->value, &buffer->length); + else + err = rs_avp_octets_value(vp, (unsigned char *)buffer->value, &buffer->length); - for (vp = pairfind(vps, attr); - concat && vp != NULL; - vp = pairfind(vp->next, attr)) { - memcpy(p, vp->vp_octets, vp->length); - p += vp->length; + if (err != 0) { + *minor = RS_MAP_ERROR(err); + return GSS_S_FAILURE; + } } *minor = 0; @@ -590,10 +634,26 @@ gssEapRadiusGetAvp(OM_uint32 *minor, } OM_uint32 +gssEapRadiusGetAvp(OM_uint32 *minor, + struct rs_packet *pkt, + unsigned int attribute, + unsigned int vendor, + gss_buffer_t buffer, + int concat) +{ + rs_avp **vps; + gss_eap_attrid attrid(vendor, attribute); + + rs_packet_avps(pkt, &vps); + + return gssEapRadiusGetAvp(minor, *vps, attrid, buffer, concat); +} + +OM_uint32 gssEapRadiusFreeAvps(OM_uint32 *minor, - VALUE_PAIR **vps) + rs_avp **vps) { - pairfree(vps); + rs_avp_free(vps); *minor = 0; return GSS_S_COMPLETE; } @@ -619,25 +679,28 @@ gssEapRadiusAttrProviderFinalize(OM_uint32 *minor) } static JSONObject -avpToJson(const VALUE_PAIR *vp) +avpToJson(rs_const_avp *vp) { JSONObject obj; + gss_eap_attrid attrid; - assert(vp->length <= MAX_STRING_LEN); + GSSEAP_ASSERT(rs_avp_length(vp) <= RS_MAX_STRING_LEN); - switch (vp->type) { - case PW_TYPE_INTEGER: - case PW_TYPE_IPADDR: - case PW_TYPE_DATE: - obj.set("value", vp->lvalue); + switch (rs_avp_typeof(vp)) { + case RS_TYPE_INTEGER: + obj.set("value", rs_avp_integer_value(vp)); + break; + case RS_TYPE_DATE: + obj.set("value", rs_avp_date_value(vp)); break; - case PW_TYPE_STRING: - obj.set("value", vp->vp_strvalue); + case RS_TYPE_STRING: + obj.set("value", rs_avp_string_value(vp)); break; default: { char *b64; - if (base64Encode(vp->vp_octets, vp->length, &b64) < 0) + if (base64Encode(rs_avp_octets_value_const_ptr(vp), + rs_avp_length(vp), &b64) < 0) throw std::bad_alloc(); obj.set("value", b64); @@ -646,62 +709,65 @@ avpToJson(const VALUE_PAIR *vp) } } - obj.set("type", vp->attribute); + attrid = avpToAttrId(vp); + + obj.set("type", attrid.second); + if (attrid.first != 0) + obj.set("vendor", attrid.first); return obj; } static bool -jsonToAvp(VALUE_PAIR **pVp, JSONObject &obj) +jsonToAvp(rs_avp **pVp, JSONObject &obj) { - VALUE_PAIR *vp = NULL; - DICT_ATTR *da; - uint32_t attrid; + rs_avp *vp = NULL; + gss_eap_attrid attrid; JSONObject type = obj["type"]; + JSONObject vendor = obj["vendor"]; JSONObject value = obj["value"]; if (!type.isInteger()) goto fail; + attrid.second = type.integer(); - attrid = type.integer(); - da = dict_attrbyvalue(attrid); - if (da != NULL) { - vp = pairalloc(da); + if (!vendor.isNull()) { + if (!vendor.isInteger()) + goto fail; + attrid.first = vendor.integer(); } else { - int type = base64Valid(value.string()) ? - PW_TYPE_OCTETS : PW_TYPE_STRING; - vp = paircreate(attrid, type); + attrid.first = 0; } + + vp = rs_avp_alloc(attrid.second, attrid.first); if (vp == NULL) throw std::bad_alloc(); - switch (vp->type) { - case PW_TYPE_INTEGER: - case PW_TYPE_IPADDR: - case PW_TYPE_DATE: + switch (rs_avp_typeof(vp)) { + case RS_TYPE_INTEGER: + case RS_TYPE_IPADDR: + case RS_TYPE_DATE: if (!value.isInteger()) goto fail; - vp->length = 4; - vp->lvalue = value.integer(); + if (rs_avp_integer_set(vp, value.integer()) != RSE_OK) + goto fail; + break; - case PW_TYPE_STRING: { + case RS_TYPE_STRING: { if (!value.isString()) goto fail; - const char *str = value.string(); - size_t len = strlen(str); - - if (len >= MAX_STRING_LEN) + if (rs_avp_string_set(vp, value.string()) != RSE_OK) goto fail; - vp->length = len; - memcpy(vp->vp_strvalue, str, len + 1); break; } - case PW_TYPE_OCTETS: + case RS_TYPE_OCTETS: default: { + unsigned char buf[RS_MAX_STRING_LEN]; + if (!value.isString()) goto fail; @@ -709,14 +775,16 @@ jsonToAvp(VALUE_PAIR **pVp, JSONObject &obj) ssize_t len = strlen(str); /* this optimization requires base64Decode only understand packed encoding */ - if (len >= BASE64_EXPAND(MAX_STRING_LEN)) + if (len >= BASE64_EXPAND(RS_MAX_STRING_LEN)) goto fail; - len = base64Decode(str, vp->vp_octets); + len = base64Decode(str, buf); if (len < 0) goto fail; - vp->length = len; + if (rs_avp_octets_set(vp, buf, len) != RSE_OK) + goto fail; + break; } } @@ -727,7 +795,7 @@ jsonToAvp(VALUE_PAIR **pVp, JSONObject &obj) fail: if (vp != NULL) - pairbasicfree(vp); + rs_avp_free(&vp); *pVp = NULL; return false; } @@ -742,8 +810,6 @@ bool gss_eap_radius_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx, JSONObject &obj) { - VALUE_PAIR **pNext = &m_vps; - if (!gss_eap_attr_provider::initWithJsonObject(ctx, obj)) return false; @@ -752,16 +818,15 @@ gss_eap_radius_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx, for (size_t i = 0; i < nelems; i++) { JSONObject attr = attrs[i]; - VALUE_PAIR *vp; + rs_avp *vp; if (!jsonToAvp(&vp, attr)) return false; - *pNext = vp; - pNext = &vp->next; + rs_avp_append(&m_vps, vp); } - m_authenticated = obj["authenticated"].integer(); + m_authenticated = obj["authenticated"].integer() ? true : false; return true; } @@ -769,7 +834,7 @@ gss_eap_radius_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx, const char * gss_eap_radius_attr_provider::prefix(void) const { - return "urn:ietf:params:gss-eap:radius-avp"; + return "urn:ietf:params:gss:radius-attribute"; } JSONObject @@ -777,7 +842,7 @@ gss_eap_radius_attr_provider::jsonRepresentation(void) const { JSONObject obj, attrs = JSONObject::array(); - for (VALUE_PAIR *vp = m_vps; vp != NULL; vp = vp->next) { + for (rs_avp *vp = m_vps; vp != NULL; vp = rs_avp_next(vp)) { JSONObject attr = avpToJson(vp); attrs.append(attr); } @@ -792,13 +857,18 @@ gss_eap_radius_attr_provider::jsonRepresentation(void) const time_t gss_eap_radius_attr_provider::getExpiryTime(void) const { - VALUE_PAIR *vp; + rs_const_avp *vp; + uint32_t value; + + vp = rs_avp_find(m_vps, PW_SESSION_TIMEOUT, 0); + if (vp == NULL) + return 0; - vp = pairfind(m_vps, PW_SESSION_TIMEOUT); - if (vp == NULL || vp->lvalue == 0) + value = rs_avp_integer_value(vp); + if (value == 0) return 0; - return time(NULL) + vp->lvalue; + return time(NULL) + value; } OM_uint32 @@ -807,7 +877,7 @@ gssEapRadiusMapError(OM_uint32 *minor, { int code; - assert(err != NULL); + GSSEAP_ASSERT(err != NULL); code = rs_err_code(err, 0); @@ -816,10 +886,69 @@ gssEapRadiusMapError(OM_uint32 *minor, return GSS_S_COMPLETE; } - *minor = ERROR_TABLE_BASE_rse + code; + *minor = RS_MAP_ERROR(code); gssEapSaveStatusInfo(*minor, "%s", rs_err_msg(err)); rs_err_free(err); 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; + } + + *pRadContext = radContext; + + *minor = 0; + return GSS_S_COMPLETE; + +fail: + major = gssEapRadiusMapError(minor, err); + rs_context_destroy(radContext); + + return major; +} + +#endif /* GSSEAP_ENABLE_ACCEPTOR */ + +OM_uint32 +gssEapRadiusAddAttr(OM_uint32 *minor, struct wpabuf **buf, uint16_t attr, + uint16_t vendor, gss_buffer_t buffer) +{ + if (radius_add_tlv(buf, attr, vendor, (u8 *)buffer->value, + buffer->length) < 0) { + *minor = ENOMEM; /* could be length too long, though */ + return GSS_S_FAILURE; + } + return GSS_S_COMPLETE; +}