From 97599e8839ff2910f700ae23458e19e38de2fbe5 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Mon, 14 Nov 2011 11:54:07 +1100 Subject: [PATCH] port to new RADIUS client library --- mech_eap/accept_sec_context.c | 67 +++--- mech_eap/gssapiP_eap.h | 28 +-- mech_eap/util_radius.cpp | 493 +++++++++++++++++++++++------------------- mech_eap/util_radius.h | 62 ++---- mech_eap/util_saml.cpp | 5 +- 5 files changed, 337 insertions(+), 318 deletions(-) diff --git a/mech_eap/accept_sec_context.c b/mech_eap/accept_sec_context.c index b089bae..fde86ec 100644 --- a/mech_eap/accept_sec_context.c +++ b/mech_eap/accept_sec_context.c @@ -59,7 +59,7 @@ static OM_uint32 acceptReadyEap(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred) { OM_uint32 major, tmpMinor; - VALUE_PAIR *vp; + rs_const_avp *vp; gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER; /* Cache encryption type derived from selected mechanism OID */ @@ -72,9 +72,10 @@ acceptReadyEap(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred) major = gssEapRadiusGetRawAvp(minor, ctx->acceptorCtx.vps, PW_USER_NAME, 0, &vp); - if (major == GSS_S_COMPLETE && vp->length) { - nameBuf.length = vp->length; - nameBuf.value = vp->vp_strvalue; + if (major == GSS_S_COMPLETE && rs_avp_length(vp) != 0) { + rs_avp_octets_value_byref((rs_avp *)vp, + (unsigned char **)&nameBuf.value, + &nameBuf.length); } else { ctx->gssFlags |= GSS_C_ANON_FLAG; } @@ -88,15 +89,15 @@ acceptReadyEap(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred) return major; major = gssEapRadiusGetRawAvp(minor, ctx->acceptorCtx.vps, - PW_MS_MPPE_SEND_KEY, VENDORPEC_MS, &vp); + PW_MS_MPPE_SEND_KEY, VENDORPEC_MICROSOFT, &vp); if (GSS_ERROR(major)) { *minor = GSSEAP_KEY_UNAVAILABLE; return GSS_S_UNAVAILABLE; } major = gssEapDeriveRfc3961Key(minor, - vp->vp_octets, - vp->length, + rs_avp_octets_value_const_ptr(vp), + rs_avp_length(vp), ctx->encryptionType, &ctx->rfc3961Key); if (GSS_ERROR(major)) @@ -287,7 +288,7 @@ importInitiatorIdentity(OM_uint32 *minor, static OM_uint32 setInitiatorIdentity(OM_uint32 *minor, gss_ctx_id_t ctx, - VALUE_PAIR **vps) + struct rs_packet *req) { OM_uint32 major, tmpMinor; gss_buffer_desc nameBuf; @@ -303,7 +304,7 @@ setInitiatorIdentity(OM_uint32 *minor, if (GSS_ERROR(major)) return major; - major = gssEapRadiusAddAvp(minor, vps, PW_USER_NAME, 0, &nameBuf); + major = gssEapRadiusAddAvp(minor, req, PW_USER_NAME, 0, &nameBuf); if (GSS_ERROR(major)) return major; @@ -320,7 +321,7 @@ setInitiatorIdentity(OM_uint32 *minor, static OM_uint32 setAcceptorIdentity(OM_uint32 *minor, gss_ctx_id_t ctx, - VALUE_PAIR **vps) + struct rs_packet *req) { OM_uint32 major; gss_buffer_desc nameBuf; @@ -349,7 +350,7 @@ setAcceptorIdentity(OM_uint32 *minor, /* Acceptor-Service-Name */ krbPrincComponentToGssBuffer(krbPrinc, 0, &nameBuf); - major = gssEapRadiusAddAvp(minor, vps, + major = gssEapRadiusAddAvp(minor, req, PW_GSS_ACCEPTOR_SERVICE_NAME, VENDORPEC_UKERNA, &nameBuf); @@ -359,7 +360,7 @@ setAcceptorIdentity(OM_uint32 *minor, /* Acceptor-Host-Name */ krbPrincComponentToGssBuffer(krbPrinc, 1, &nameBuf); - major = gssEapRadiusAddAvp(minor, vps, + major = gssEapRadiusAddAvp(minor, req, PW_GSS_ACCEPTOR_HOST_NAME, VENDORPEC_UKERNA, &nameBuf); @@ -382,7 +383,7 @@ setAcceptorIdentity(OM_uint32 *minor, nameBuf.value = ssi; nameBuf.length = strlen(ssi); - major = gssEapRadiusAddAvp(minor, vps, + major = gssEapRadiusAddAvp(minor, req, PW_GSS_ACCEPTOR_SERVICE_SPECIFIC, VENDORPEC_UKERNA, &nameBuf); @@ -397,7 +398,7 @@ setAcceptorIdentity(OM_uint32 *minor, krbPrincRealmToGssBuffer(krbPrinc, &nameBuf); if (nameBuf.length != 0) { /* Acceptor-Realm-Name */ - major = gssEapRadiusAddAvp(minor, vps, + major = gssEapRadiusAddAvp(minor, req, PW_GSS_ACCEPTOR_REALM_NAME, VENDORPEC_UKERNA, &nameBuf); @@ -469,7 +470,7 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, struct rs_connection *rconn; struct rs_request *request = NULL; struct rs_packet *req = NULL, *resp = NULL; - struct radius_packet *frreq, *frresp; + int isAccessChallenge; if (ctx->acceptorCtx.radContext == NULL) { /* May be NULL from an imported partial context */ @@ -490,23 +491,22 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, major = gssEapRadiusMapError(minor, rs_err_conn_pop(rconn)); goto cleanup; } - frreq = rs_packet_frpkt(req); - major = setInitiatorIdentity(minor, ctx, &frreq->vps); + major = setInitiatorIdentity(minor, ctx, req); if (GSS_ERROR(major)) goto cleanup; - major = setAcceptorIdentity(minor, ctx, &frreq->vps); + major = setAcceptorIdentity(minor, ctx, req); if (GSS_ERROR(major)) goto cleanup; - major = gssEapRadiusAddAvp(minor, &frreq->vps, + major = gssEapRadiusAddAvp(minor, req, PW_EAP_MESSAGE, 0, inputToken); if (GSS_ERROR(major)) goto cleanup; if (ctx->acceptorCtx.state.length != 0) { - major = gssEapRadiusAddAvp(minor, &frreq->vps, PW_STATE, 0, + major = gssEapRadiusAddAvp(minor, req, PW_STATE, 0, &ctx->acceptorCtx.state); if (GSS_ERROR(major)) goto cleanup; @@ -529,12 +529,15 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, GSSEAP_ASSERT(resp != NULL); - frresp = rs_packet_frpkt(resp); - switch (frresp->code) { + isAccessChallenge = 0; + + switch (rs_packet_code(resp)) { case PW_ACCESS_CHALLENGE: - case PW_AUTHENTICATION_ACK: + isAccessChallenge = 1; + break; + case PW_ACCESS_ACCEPT: break; - case PW_AUTHENTICATION_REJECT: + case PW_ACCESS_REJECT: *minor = GSSEAP_RADIUS_AUTH_FAILURE; major = GSS_S_DEFECTIVE_CREDENTIAL; goto cleanup; @@ -546,23 +549,27 @@ eapGssSmAcceptAuthenticate(OM_uint32 *minor, break; } - major = gssEapRadiusGetAvp(minor, frresp->vps, PW_EAP_MESSAGE, 0, + major = gssEapRadiusGetAvp(minor, resp, PW_EAP_MESSAGE, 0, outputToken, TRUE); - if (major == GSS_S_UNAVAILABLE && frresp->code == PW_ACCESS_CHALLENGE) { + if (major == GSS_S_UNAVAILABLE && isAccessChallenge) { *minor = GSSEAP_MISSING_EAP_REQUEST; major = GSS_S_DEFECTIVE_TOKEN; goto cleanup; } else if (GSS_ERROR(major)) goto cleanup; - if (frresp->code == PW_ACCESS_CHALLENGE) { - major = gssEapRadiusGetAvp(minor, frresp->vps, PW_STATE, 0, + if (isAccessChallenge) { + major = gssEapRadiusGetAvp(minor, resp, PW_STATE, 0, &ctx->acceptorCtx.state, TRUE); if (GSS_ERROR(major) && *minor != GSSEAP_NO_SUCH_ATTR) goto cleanup; } else { - ctx->acceptorCtx.vps = frresp->vps; - frresp->vps = NULL; + rs_avp **vps; + + rs_packet_avps(resp, &vps); + + ctx->acceptorCtx.vps = *vps; + *vps = NULL; major = acceptReadyEap(minor, ctx, cred); if (GSS_ERROR(major)) diff --git a/mech_eap/gssapiP_eap.h b/mech_eap/gssapiP_eap.h index d1790a0..6a5dfd7 100644 --- a/mech_eap/gssapiP_eap.h +++ b/mech_eap/gssapiP_eap.h @@ -90,28 +90,11 @@ typedef const gss_OID_desc *gss_const_OID; #include #ifdef GSSEAP_ENABLE_ACCEPTOR -/* FreeRADIUS headers */ -#ifdef __cplusplus -extern "C" { -#ifndef WIN32 -#define operator fr_operator -#endif -#endif -#include -#include - -#undef pid_t - /* libradsec headers */ #include #include -#ifdef __cplusplus -#ifndef WIN32 -#undef operator -#endif -} +#include #endif -#endif /* GSSEAP_ENABLE_ACCEPTOR */ #include "gsseap_err.h" #include "radsec_err.h" @@ -208,7 +191,7 @@ struct gss_eap_acceptor_ctx { struct rs_connection *radConn; char *radServer; gss_buffer_desc state; - VALUE_PAIR *vps; + rs_avp *vps; }; #endif @@ -338,9 +321,12 @@ gssEapDisplayStatus(OM_uint32 *minor, #define IS_WIRE_ERROR(err) ((err) > GSSEAP_RESERVED && \ (err) <= GSSEAP_RADIUS_PROT_FAILURE) -/* upper bound of RADIUS error range must be kept in sync with radsec.h */ +#ifdef GSSEAP_ENABLE_ACCEPTOR #define IS_RADIUS_ERROR(err) ((err) >= ERROR_TABLE_BASE_rse && \ - (err) <= ERROR_TABLE_BASE_rse + 20) + (err) <= ERROR_TABLE_BASE_rse + RSE_MAX) +#else +#define IS_RADIUS_ERROR(err) (0) +#endif /* exchange_meta_data.c */ OM_uint32 GSSAPI_CALLCONV diff --git a/mech_eap/util_radius.cpp b/mech_eap/util_radius.cpp index 9111e20..782815f 100644 --- a/mech_eap/util_radius.cpp +++ b/mech_eap/util_radius.cpp @@ -36,19 +36,37 @@ #include "gssapiP_eap.h" -/* stuff that should be provided by libradsec/libfreeradius-radius */ -#define VENDORATTR(vendor, attr) (((vendor) << 16) | (attr)) - -#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 VALUE_PAIR *copyAvps(const VALUE_PAIR *src); +static rs_avp *copyAvps(rs_const_avp *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 +77,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 +92,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 +114,7 @@ gss_eap_radius_attr_provider::initWithGssContext(const gss_eap_attr_ctx *manager return false; /* We assume libradsec validated this for us */ - GSSEAP_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 +123,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 +138,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 +160,22 @@ 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 */ - GSSEAP_ASSERT(!isSecretAttributeP(attrid, vendor)); + GSSEAP_ASSERT(!isSecretAttributeP(attrid)); - switch (vendor) { + switch (attrid.first) { case VENDORPEC_UKERNA: - switch (attrid) { + switch (attrid.second) { case PW_GSS_ACCEPTOR_SERVICE_NAME: case PW_GSS_ACCEPTOR_HOST_NAME: case PW_GSS_ACCEPTOR_SERVICE_SPECIFIC: @@ -175,48 +195,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(uint16_t attrid, uint16_t vendor) +isFragmentedAttributeP(const gss_eap_attrid &attrid) { /* 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)); + 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; @@ -226,68 +240,90 @@ 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 (attrid.second != 0) { + snprintf(buf, sizeof(buf), "%s%u.%u", + (char *)radiusUrnPrefix.value, attrid.first, attrid.second); + } else { + snprintf(buf, sizeof(buf), "%s%u", + (char *)radiusUrnPrefix.value, attrid.second); + } - attribute.value = attrid; - attribute.length = strlen(attrid); + desc.value = buf; + desc.length = strlen(buf); - 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; + bool ret; - if (attr->length < radiusUrnPrefix.length || - memcmp(attr->value, radiusUrnPrefix.value, radiusUrnPrefix.length) != 0) - return 0; + if (desc->length < radiusUrnPrefix.length || + memcmp(desc->value, radiusUrnPrefix.value, radiusUrnPrefix.length) != 0) + return false; /* need to duplicate because attr may not be NUL terminated */ - duplicateBuffer(*attr, &strAttr); + duplicateBuffer(*desc, &strAttr); s = (char *)strAttr.value + radiusUrnPrefix.length; - if (isdigit(*s)) { - attrid = strtoul(s, NULL, 10); + if (!isdigit(*s)) { + /* No digits */ + ret = rs_attr_find(s, &attrid->second, &attrid->first); } else { - da = dict_attrbyname(s); - if (da != NULL) - attrid = da->attr; + char *s2; + unsigned int tmp = strtoul(s, &s2, 10); + + if (s2 == NULL) { + /* Non-vendor attrbiute */ + attrid->first = 0; + attrid->second = tmp; + ret = true; + } else if (*s2 == '.') { + /* Vendor attributes formatted as Vendor.Attribute */ + attrid->first = tmp; + attrid->second = strtoul(s2 + 1, NULL, 10); + ret = true; + } else { + ret = false; + } } gss_release_buffer(&tmpMinor, &strAttr); - return attrid; + return ret; } 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; @@ -296,9 +332,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); @@ -309,32 +343,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); @@ -348,25 +381,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; @@ -374,7 +407,8 @@ gss_eap_radius_attr_provider::getAttribute(uint32_t attrid, if (i == -1) i = 0; - if (isSecretAttributeP(attrid) || isInternalAttributeP(attrid)) { + if (isSecretAttributeP(attrid) || + isInternalAttributeP(attrid)) { return false; } else if (isFragmentedAttributeP(attrid)) { return getFragmentedAttribute(attrid, @@ -383,11 +417,11 @@ gss_eap_radius_attr_provider::getAttribute(uint32_t attrid, value); } - for (vp = pairfind(m_vps, attrid); + 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; } @@ -399,19 +433,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 && - vp->type != PW_TYPE_OCTETS) { - char displayString[MAX_STRING_LEN]; + !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); @@ -426,15 +461,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; @@ -444,31 +478,6 @@ gss_eap_radius_attr_provider::getFragmentedAttribute(uint16_t attribute, return !GSS_ERROR(major); } -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, - 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 @@ -483,8 +492,8 @@ 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 @@ -507,38 +516,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; @@ -548,15 +554,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; + } + + *minor = 0; + return GSS_S_COMPLETE; +} - *vp = pairfind(vps, attr); +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; @@ -565,33 +590,32 @@ 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; 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; } if (buffer != GSS_C_NO_BUFFER) { - do { - buffer->length += vp->length; - } while (concat && (vp = pairfind(vp->next, attr)) != NULL); + 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) { @@ -599,13 +623,14 @@ gssEapRadiusGetAvp(OM_uint32 *minor, 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; } } @@ -614,10 +639,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; } @@ -643,25 +684,28 @@ gssEapRadiusAttrProviderFinalize(OM_uint32 *minor) } static JSONObject -avpToJson(const VALUE_PAIR *vp) +avpToJson(rs_const_avp *vp) { JSONObject obj; + gss_eap_attrid attrid; - GSSEAP_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 PW_TYPE_STRING: - obj.set("value", vp->vp_strvalue); + case RS_TYPE_DATE: + obj.set("value", rs_avp_date_value(vp)); + break; + 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); @@ -670,62 +714,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; @@ -733,14 +780,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; } } @@ -751,7 +800,7 @@ jsonToAvp(VALUE_PAIR **pVp, JSONObject &obj) fail: if (vp != NULL) - pairbasicfree(vp); + rs_avp_free(&vp); *pVp = NULL; return false; } @@ -766,8 +815,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; @@ -776,13 +823,12 @@ 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() ? true : false; @@ -801,7 +847,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); } @@ -816,13 +862,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 @@ -840,7 +891,7 @@ 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); diff --git a/mech_eap/util_radius.h b/mech_eap/util_radius.h index 481876a..4d1463d 100644 --- a/mech_eap/util_radius.h +++ b/mech_eap/util_radius.h @@ -39,6 +39,8 @@ #ifdef __cplusplus +typedef std::pair gss_eap_attrid; + struct gss_eap_radius_attr_provider : gss_eap_attr_provider { public: gss_eap_radius_attr_provider(void); @@ -72,30 +74,18 @@ public: JSONObject &obj); JSONObject jsonRepresentation(void) const; - bool getAttribute(uint32_t attribute, - int *authenticated, - int *complete, - gss_buffer_t value, - gss_buffer_t display_value, - int *more) const; - bool getAttribute(uint16_t attribute, - uint16_t vendor, + bool getAttribute(const gss_eap_attrid &attrid, int *authenticated, int *complete, gss_buffer_t value, gss_buffer_t display_value, int *more) const; bool setAttribute(int complete, - uint32_t attribute, + const gss_eap_attrid &attrid, const gss_buffer_t value); - bool deleteAttribute(uint32_t attribute); + bool deleteAttribute(const gss_eap_attrid &attrid); - bool getFragmentedAttribute(uint16_t attribute, - uint16_t vendor, - int *authenticated, - int *complete, - gss_buffer_t value) const; - bool getFragmentedAttribute(uint32_t attrid, + bool getFragmentedAttribute(const gss_eap_attrid &attrid, int *authenticated, int *complete, gss_buffer_t value) const; @@ -110,11 +100,11 @@ public: static gss_eap_attr_provider *createAttrContext(void); private: - const VALUE_PAIR *getAvps(void) const { + rs_const_avp *getAvps(void) const { return m_vps; } - VALUE_PAIR *m_vps; + rs_avp *m_vps; bool m_authenticated; }; @@ -124,28 +114,28 @@ extern "C" { OM_uint32 gssEapRadiusAddAvp(OM_uint32 *minor, - VALUE_PAIR **vp, - uint16_t type, - uint16_t vendor, + struct rs_packet *pkt, + unsigned int type, + unsigned int vendor, const gss_buffer_t buffer); OM_uint32 gssEapRadiusGetAvp(OM_uint32 *minor, - VALUE_PAIR *vps, - uint16_t type, - uint16_t vendor, + struct rs_packet *pkt, + unsigned int type, + unsigned int vendor, gss_buffer_t buffer, int concat); OM_uint32 gssEapRadiusGetRawAvp(OM_uint32 *minor, - VALUE_PAIR *vps, - uint16_t type, - uint16_t vendor, - VALUE_PAIR **vp); + rs_const_avp *vps, + unsigned int type, + unsigned int vendor, + rs_const_avp **vp); OM_uint32 gssEapRadiusFreeAvps(OM_uint32 *minor, - VALUE_PAIR **vps); + rs_avp **vps); OM_uint32 gssEapRadiusAttrProviderInit(OM_uint32 *minor); OM_uint32 gssEapRadiusAttrProviderFinalize(OM_uint32 *minor); @@ -162,20 +152,6 @@ gssEapCreateRadiusContext(OM_uint32 *minor, /* This really needs to be a function call on Windows */ #define RS_CONFIG_FILE SYSCONFDIR "/radsec.conf" -#define VENDORPEC_MS 311 /* RFC 2548 */ - -#define PW_MS_MPPE_SEND_KEY 16 -#define PW_MS_MPPE_RECV_KEY 17 - -#define VENDORPEC_UKERNA 25622 - -#define PW_GSS_ACCEPTOR_SERVICE_NAME 128 -#define PW_GSS_ACCEPTOR_HOST_NAME 129 -#define PW_GSS_ACCEPTOR_SERVICE_SPECIFIC 130 -#define PW_GSS_ACCEPTOR_REALM_NAME 131 -#define PW_SAML_AAA_ASSERTION 132 -#define PW_MS_WINDOWS_AUTH_DATA 133 - #ifdef __cplusplus } #endif diff --git a/mech_eap/util_saml.cpp b/mech_eap/util_saml.cpp index ce7582e..72047cd 100644 --- a/mech_eap/util_saml.cpp +++ b/mech_eap/util_saml.cpp @@ -103,6 +103,7 @@ gss_eap_saml_assertion_provider::initWithGssContext(const gss_eap_attr_ctx *mana gss_buffer_desc value = GSS_C_EMPTY_BUFFER; int authenticated, complete; OM_uint32 minor; + gss_eap_attrid attrid(VENDORPEC_UKERNA, PW_SAML_AAA_ASSERTION); GSSEAP_ASSERT(m_assertion == NULL); @@ -115,9 +116,7 @@ gss_eap_saml_assertion_provider::initWithGssContext(const gss_eap_attr_ctx *mana radius = static_cast (m_manager->getProvider(ATTR_TYPE_RADIUS)); if (radius != NULL && - radius->getFragmentedAttribute(PW_SAML_AAA_ASSERTION, - VENDORPEC_UKERNA, - &authenticated, &complete, &value)) { + radius->getFragmentedAttribute(attrid, &authenticated, &complete, &value)) { setAssertion(&value, authenticated); gss_release_buffer(&minor, &value); } else { -- 2.1.4