2 * Copyright (c) 2010, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include "gssapiP_eap.h"
39 static gss_eap_attr_create_cb
40 gss_eap_attr_factories[ATTR_TYPE_MAX] = {
41 gss_eap_radius_attr_provider::createAttrContext,
42 gss_eap_saml_assertion_provider::createAttrContext,
43 gss_eap_saml_attr_provider::createAttrContext,
44 gss_eap_shib_attr_provider::createAttrContext
48 gss_eap_attr_ctx::createAttrContext(gss_cred_id_t gssCred,
51 gss_eap_attr_ctx *ctx;
53 ctx = new gss_eap_attr_ctx(NULL, gssCred, gssCtx);
55 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
56 gss_eap_attr_provider *provider;
58 provider = (gss_eap_attr_factories[i])(ctx, gssCred, gssCtx);
60 ctx->m_providers[i] = provider;
66 gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
68 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++)
69 delete m_providers[i];
73 gss_eap_attr_ctx::init(void)
75 return gss_eap_radius_attr_provider::init() &&
76 gss_eap_saml_assertion_provider::init() &&
77 gss_eap_saml_attr_provider::init() &&
78 gss_eap_shib_attr_provider::init();
82 gss_eap_attr_ctx::finalize(void)
84 gss_eap_shib_attr_provider::finalize();
85 gss_eap_saml_attr_provider::finalize();
86 gss_eap_saml_assertion_provider::finalize();
87 gss_eap_radius_attr_provider::finalize();
90 gss_eap_attr_provider *
91 gss_eap_attr_ctx::getProvider(unsigned int type) const
93 return m_providers[type];
96 gss_eap_attr_provider *
97 gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const
101 type = attributePrefixToType(prefix);
103 return m_providers[type];
106 gss_eap_attr_ctx::gss_eap_attr_ctx(const gss_eap_attr_ctx &ctx)
107 : gss_eap_attr_provider(ctx)
109 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
110 if (ctx.m_providers[i] != NULL) {
111 m_providers[i] = (gss_eap_attr_factories[i])(&ctx,
119 gss_eap_attr_ctx::setAttribute(int complete,
120 const gss_buffer_t attr,
121 const gss_buffer_t value)
123 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
125 gss_eap_attr_provider *provider;
127 decomposeAttributeName(attr, &type, &suffix);
129 provider = m_providers[type];
130 if (provider != NULL) {
131 provider->setAttribute(complete,
132 (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
139 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
141 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
143 gss_eap_attr_provider *provider;
145 decomposeAttributeName(attr, &type, &suffix);
147 provider = m_providers[type];
148 if (provider != NULL) {
149 provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
154 gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
159 for (i = 0; i < ATTR_TYPE_MAX; i++) {
160 gss_eap_attr_provider *provider;
162 provider = m_providers[i];
163 if (provider == NULL)
166 ret = provider->getAttributeTypes(cb, data);
174 struct eap_gss_get_attr_types_args {
176 gss_buffer_set_t attrs;
180 addAttribute(const gss_eap_attr_provider *provider,
181 const gss_buffer_t attribute,
184 eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
185 gss_buffer_t prefix = GSS_C_NO_BUFFER;
186 gss_buffer_desc qualified;
187 OM_uint32 major, minor;
189 if (args->type != ATTR_TYPE_LOCAL) {
190 gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified);
191 major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
192 gss_release_buffer(&minor, &qualified);
194 major = gss_add_buffer_set_member(&minor, prefix, &args->attrs);
197 return GSS_ERROR(major) ? false : true;
201 gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
203 eap_gss_get_attr_types_args args;
204 OM_uint32 major, minor;
208 major = gss_create_empty_buffer_set(&minor, attrs);
209 if (GSS_ERROR(major)) {
210 throw new std::bad_alloc;
216 for (i = 0; i < ATTR_TYPE_MAX; i++) {
217 gss_eap_attr_provider *provider;
221 provider = m_providers[i];
222 if (provider == NULL)
225 ret = provider->getAttributeTypes(addAttribute, (void *)&args);
231 gss_release_buffer_set(&minor, attrs);
238 gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
242 gss_buffer_t display_value,
245 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
247 gss_eap_attr_provider *provider;
250 decomposeAttributeName(attr, &type, &suffix);
252 provider = m_providers[type];
253 if (provider == NULL) {
258 ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
259 authenticated, complete,
260 value, display_value, more);
266 gss_eap_attr_ctx::mapToAny(int authenticated,
267 gss_buffer_t type_id) const
273 gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
274 gss_any_t input) const
279 gss_eap_attr_ctx::marshall(gss_buffer_t buffer) const
281 /* For now, just marshall the RADIUS context. */
285 gss_eap_attr_ctx::unmarshall(const gss_eap_attr_ctx *ctx,
286 const gss_buffer_t buffer)
290 for (i = 0; i < ATTR_TYPE_MAX; i++) {
291 gss_eap_attr_provider *provider = m_providers[i];
302 mapException(OM_uint32 *minor, std::exception &e)
305 return GSS_S_FAILURE;
308 static gss_buffer_desc attributePrefixes[] = {
310 /* ATTR_TYPE_RADIUS_AVP */
311 sizeof("urn:ietf:params:gss-eap:radius-avp"),
312 (void *)"urn:ietf:params:gss-eap:radius-avp",
315 /* ATTR_TYPE_SAML_AAA_ASSERTION */
316 sizeof("urn:ietf:params:gss-eap:saml-aaa-assertion"),
317 (void *)"urn:ietf:params:gss-eap:saml-aaa-assertion"
320 /* ATTR_TYPE_SAML_ATTR */
321 sizeof("urn:ietf:params:gss-eap:saml-attr"),
322 (void *)"urn:ietf:params:gss-eap:saml-attr"
327 gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix)
331 for (i = ATTR_TYPE_MIN;
332 i < sizeof(attributePrefixes) / sizeof(attributePrefixes[0]);
335 if (bufferEqual(&attributePrefixes[i], prefix))
339 return ATTR_TYPE_LOCAL;
343 gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type)
345 if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_LOCAL)
346 return GSS_C_NO_BUFFER;
348 return &attributePrefixes[type];
352 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
359 for (i = 0; i < attribute->length; i++) {
360 if (((char *)attribute->value)[i] == ' ') {
361 p = (char *)attribute->value + i + 1;
366 prefix->value = attribute->value;
369 if (p != NULL && *p != '\0') {
370 suffix->length = attribute->length - 1 - prefix->length;
374 suffix->value = NULL;
379 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
380 const gss_buffer_t suffix,
381 gss_buffer_t attribute)
386 attribute->length = 0;
387 attribute->value = NULL;
389 if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
392 len = prefix->length;
393 if (suffix != GSS_C_NO_BUFFER) {
394 len += 1 + suffix->length;
397 attribute->value = GSSEAP_MALLOC(len + 1);
398 if (attribute->value == NULL) {
399 throw new std::bad_alloc;
401 attribute->length = len;
403 p = (char *)attribute->value;
404 memcpy(p, prefix->value, prefix->length);
405 if (suffix != NULL) {
406 p[prefix->length] = ' ';
407 memcpy(p + prefix->length + 1, suffix->value, suffix->length);
410 p[attribute->length] = '\0';
414 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
418 gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
420 decomposeAttributeName(attribute, &prefix, suffix);
421 *type = attributePrefixToType(&prefix);
425 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
426 const gss_buffer_t suffix,
427 gss_buffer_t attribute)
429 gss_buffer_t prefix = attributeTypeToPrefix(type);
431 composeAttributeName(prefix, suffix, attribute);
435 gssEapInquireName(OM_uint32 *minor,
439 gss_buffer_set_t *attrs)
441 if (name->attrCtx == NULL)
442 return GSS_S_UNAVAILABLE;
445 if (!name->attrCtx->getAttributeTypes(attrs))
446 return GSS_S_UNAVAILABLE;
447 } catch (std::exception &e) {
448 return mapException(minor, e);
451 return GSS_S_COMPLETE;
455 gssEapGetNameAttribute(OM_uint32 *minor,
461 gss_buffer_t display_value,
470 if (display_value != NULL) {
471 display_value->length = 0;
472 display_value->value = NULL;
477 if (name->attrCtx == NULL)
478 return GSS_S_UNAVAILABLE;
481 if (!name->attrCtx->getAttribute(attr, authenticated, complete,
482 value, display_value, more))
483 return GSS_S_UNAVAILABLE;
484 } catch (std::exception &e) {
485 return mapException(minor, e);
488 return GSS_S_COMPLETE;
492 gssEapDeleteNameAttribute(OM_uint32 *minor,
496 if (name->attrCtx == NULL)
497 return GSS_S_UNAVAILABLE;
500 name->attrCtx->deleteAttribute(attr);
501 } catch (std::exception &ex) {
502 return mapException(minor, ex);
505 return GSS_S_COMPLETE;
509 gssEapSetNameAttribute(OM_uint32 *minor,
515 if (name->attrCtx == NULL)
516 return GSS_S_UNAVAILABLE;
519 name->attrCtx->setAttribute(complete, attr, value);
520 } catch (std::exception &ex) {
521 return mapException(minor, ex);
524 return GSS_S_COMPLETE;
528 gssEapExportAttrContext(OM_uint32 *minor,
532 if (name->attrCtx == NULL)
533 return GSS_S_UNAVAILABLE;
536 name->attrCtx->marshall(buffer);
537 } catch (std::exception &e) {
538 return mapException(minor, e);
541 return GSS_S_COMPLETE;
545 gssEapImportAttrContext(OM_uint32 *minor,
549 GSSEAP_NOT_IMPLEMENTED;
553 gssEapDuplicateAttrContext(OM_uint32 *minor,
558 if (in->attrCtx != NULL)
559 out->attrCtx = new gss_eap_attr_ctx(*(in->attrCtx));
562 } catch (std::exception &e) {
563 return mapException(minor, e);
566 return GSS_S_COMPLETE;
570 gssEapMapNameToAny(OM_uint32 *minor,
573 gss_buffer_t type_id,
577 *output = name->attrCtx->mapToAny(authenticated, type_id);
578 } catch (std::exception &e) {
579 return mapException(minor, e);
582 return GSS_S_COMPLETE;
586 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
588 gss_buffer_t type_id,
591 if (name->attrCtx == NULL)
592 return GSS_S_UNAVAILABLE;
596 name->attrCtx->releaseAnyNameMapping(type_id, *input);
598 } catch (std::exception &e) {
599 return mapException(minor, e);
602 return GSS_S_COMPLETE;
606 gssEapReleaseAttrContext(OM_uint32 *minor,
609 if (name->attrCtx != NULL)
610 delete name->attrCtx;
612 return GSS_S_COMPLETE;
616 gssEapAttrProvidersInit(OM_uint32 *minor)
619 gss_eap_attr_ctx::init();
620 } catch (std::exception &e) {
621 return mapException(minor, e);
624 return GSS_S_COMPLETE;
628 gssEapAttrProvidersFinalize(OM_uint32 *minor)
631 gss_eap_attr_ctx::finalize();
632 } catch (std::exception &e) {
633 return mapException(minor, e);
636 return GSS_S_COMPLETE;
639 struct gss_eap_attr_ctx *
640 gssEapCreateAttrContext(gss_cred_id_t cred,
643 assert(ctx != GSS_C_NO_CONTEXT);
644 return gss_eap_attr_ctx::createAttrContext(cred, ctx);