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(void)
50 gss_eap_attr_ctx *ctx;
52 ctx = new gss_eap_attr_ctx;
54 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
55 gss_eap_attr_provider *provider;
57 provider = (gss_eap_attr_factories[i])();
59 ctx->m_providers[i] = provider;
66 gss_eap_attr_ctx::initFromExistingContext(const gss_eap_attr_ctx *source,
67 const gss_eap_attr_provider *ctx)
69 if (!gss_eap_attr_provider::initFromExistingContext(this, ctx))
72 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
73 gss_eap_attr_provider *provider;
75 provider = m_providers[i];
76 if (provider != NULL) {
77 if (!provider->initFromExistingContext(this, provider))
86 gss_eap_attr_ctx::initFromGssContext(const gss_eap_attr_ctx *source,
87 const gss_cred_id_t cred,
88 const gss_ctx_id_t ctx)
90 if (!gss_eap_attr_provider::initFromGssContext(this, cred, ctx))
93 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
94 gss_eap_attr_provider *provider;
96 provider = m_providers[i];
97 if (provider != NULL) {
98 if (!provider->initFromGssContext(this, cred, ctx))
106 gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
108 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++)
109 delete m_providers[i];
113 gss_eap_attr_ctx::init(void)
115 return gss_eap_radius_attr_provider::init() &&
116 gss_eap_saml_assertion_provider::init() &&
117 gss_eap_saml_attr_provider::init() &&
118 gss_eap_shib_attr_provider::init();
122 gss_eap_attr_ctx::finalize(void)
124 gss_eap_shib_attr_provider::finalize();
125 gss_eap_saml_attr_provider::finalize();
126 gss_eap_saml_assertion_provider::finalize();
127 gss_eap_radius_attr_provider::finalize();
130 gss_eap_attr_provider *
131 gss_eap_attr_ctx::getProvider(unsigned int type) const
133 return m_providers[type];
136 gss_eap_attr_provider *
137 gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const
141 type = attributePrefixToType(prefix);
143 return m_providers[type];
147 gss_eap_attr_ctx::setAttribute(int complete,
148 const gss_buffer_t attr,
149 const gss_buffer_t value)
151 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
153 gss_eap_attr_provider *provider;
155 decomposeAttributeName(attr, &type, &suffix);
157 provider = m_providers[type];
158 if (provider != NULL) {
159 provider->setAttribute(complete,
160 (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
167 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
169 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
171 gss_eap_attr_provider *provider;
173 decomposeAttributeName(attr, &type, &suffix);
175 provider = m_providers[type];
176 if (provider != NULL) {
177 provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
182 gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
187 for (i = 0; i < ATTR_TYPE_MAX; i++) {
188 gss_eap_attr_provider *provider;
190 provider = m_providers[i];
191 if (provider == NULL)
194 ret = provider->getAttributeTypes(cb, data);
202 struct eap_gss_get_attr_types_args {
204 gss_buffer_set_t attrs;
208 addAttribute(const gss_eap_attr_provider *provider,
209 const gss_buffer_t attribute,
212 eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
213 gss_buffer_t prefix = GSS_C_NO_BUFFER;
214 gss_buffer_desc qualified;
215 OM_uint32 major, minor;
217 if (args->type != ATTR_TYPE_LOCAL) {
218 gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified);
219 major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
220 gss_release_buffer(&minor, &qualified);
222 major = gss_add_buffer_set_member(&minor, prefix, &args->attrs);
225 return GSS_ERROR(major) ? false : true;
229 gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
231 eap_gss_get_attr_types_args args;
232 OM_uint32 major, minor;
236 major = gss_create_empty_buffer_set(&minor, attrs);
237 if (GSS_ERROR(major)) {
238 throw new std::bad_alloc;
244 for (i = 0; i < ATTR_TYPE_MAX; i++) {
245 gss_eap_attr_provider *provider;
249 provider = m_providers[i];
250 if (provider == NULL)
253 ret = provider->getAttributeTypes(addAttribute, (void *)&args);
259 gss_release_buffer_set(&minor, attrs);
266 gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
270 gss_buffer_t display_value,
273 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
275 gss_eap_attr_provider *provider;
278 decomposeAttributeName(attr, &type, &suffix);
280 provider = m_providers[type];
281 if (provider == NULL) {
286 ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
287 authenticated, complete,
288 value, display_value, more);
294 gss_eap_attr_ctx::mapToAny(int authenticated,
295 gss_buffer_t type_id) const
301 gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
302 gss_any_t input) const
307 gss_eap_attr_ctx::marshall(gss_buffer_t buffer) const
309 /* For now, just marshall the RADIUS context. */
313 gss_eap_attr_ctx::unmarshall(const gss_eap_attr_ctx *ctx,
314 const gss_buffer_t buffer)
318 for (i = 0; i < ATTR_TYPE_MAX; i++) {
319 gss_eap_attr_provider *provider = m_providers[i];
329 mapException(OM_uint32 *minor, std::exception &e)
332 return GSS_S_FAILURE;
335 static gss_buffer_desc attributePrefixes[] = {
337 /* ATTR_TYPE_RADIUS_AVP */
338 sizeof("urn:ietf:params:gss-eap:radius-avp"),
339 (void *)"urn:ietf:params:gss-eap:radius-avp",
342 /* ATTR_TYPE_SAML_AAA_ASSERTION */
343 sizeof("urn:ietf:params:gss-eap:saml-aaa-assertion"),
344 (void *)"urn:ietf:params:gss-eap:saml-aaa-assertion"
347 /* ATTR_TYPE_SAML_ATTR */
348 sizeof("urn:ietf:params:gss-eap:saml-attr"),
349 (void *)"urn:ietf:params:gss-eap:saml-attr"
354 gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix)
358 for (i = ATTR_TYPE_MIN;
359 i < sizeof(attributePrefixes) / sizeof(attributePrefixes[0]);
362 if (bufferEqual(&attributePrefixes[i], prefix))
366 return ATTR_TYPE_LOCAL;
370 gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type)
372 if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_LOCAL)
373 return GSS_C_NO_BUFFER;
375 return &attributePrefixes[type];
379 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
386 for (i = 0; i < attribute->length; i++) {
387 if (((char *)attribute->value)[i] == ' ') {
388 p = (char *)attribute->value + i + 1;
393 prefix->value = attribute->value;
396 if (p != NULL && *p != '\0') {
397 suffix->length = attribute->length - 1 - prefix->length;
401 suffix->value = NULL;
406 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
407 const gss_buffer_t suffix,
408 gss_buffer_t attribute)
413 attribute->length = 0;
414 attribute->value = NULL;
416 if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
419 len = prefix->length;
420 if (suffix != GSS_C_NO_BUFFER) {
421 len += 1 + suffix->length;
424 attribute->value = GSSEAP_MALLOC(len + 1);
425 if (attribute->value == NULL) {
426 throw new std::bad_alloc;
428 attribute->length = len;
430 p = (char *)attribute->value;
431 memcpy(p, prefix->value, prefix->length);
432 if (suffix != NULL) {
433 p[prefix->length] = ' ';
434 memcpy(p + prefix->length + 1, suffix->value, suffix->length);
437 p[attribute->length] = '\0';
441 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
445 gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
447 decomposeAttributeName(attribute, &prefix, suffix);
448 *type = attributePrefixToType(&prefix);
452 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
453 const gss_buffer_t suffix,
454 gss_buffer_t attribute)
456 gss_buffer_t prefix = attributeTypeToPrefix(type);
458 composeAttributeName(prefix, suffix, attribute);
462 gssEapInquireName(OM_uint32 *minor,
466 gss_buffer_set_t *attrs)
468 if (name->attrCtx == NULL)
469 return GSS_S_UNAVAILABLE;
472 if (!name->attrCtx->getAttributeTypes(attrs))
473 return GSS_S_UNAVAILABLE;
474 } catch (std::exception &e) {
475 return mapException(minor, e);
478 return GSS_S_COMPLETE;
482 gssEapGetNameAttribute(OM_uint32 *minor,
488 gss_buffer_t display_value,
497 if (display_value != NULL) {
498 display_value->length = 0;
499 display_value->value = NULL;
504 if (name->attrCtx == NULL)
505 return GSS_S_UNAVAILABLE;
508 if (!name->attrCtx->getAttribute(attr, authenticated, complete,
509 value, display_value, more))
510 return GSS_S_UNAVAILABLE;
511 } catch (std::exception &e) {
512 return mapException(minor, e);
515 return GSS_S_COMPLETE;
519 gssEapDeleteNameAttribute(OM_uint32 *minor,
523 if (name->attrCtx == NULL)
524 return GSS_S_UNAVAILABLE;
527 name->attrCtx->deleteAttribute(attr);
528 } catch (std::exception &ex) {
529 return mapException(minor, ex);
532 return GSS_S_COMPLETE;
536 gssEapSetNameAttribute(OM_uint32 *minor,
542 if (name->attrCtx == NULL)
543 return GSS_S_UNAVAILABLE;
546 name->attrCtx->setAttribute(complete, attr, value);
547 } catch (std::exception &ex) {
548 return mapException(minor, ex);
551 return GSS_S_COMPLETE;
555 gssEapExportAttrContext(OM_uint32 *minor,
559 if (name->attrCtx == NULL) {
561 buffer->value = NULL;
563 return GSS_S_COMPLETE;
567 name->attrCtx->marshall(buffer);
568 } catch (std::exception &e) {
569 return mapException(minor, e);
572 return GSS_S_COMPLETE;
576 gssEapImportAttrContext(OM_uint32 *minor,
581 GSSEAP_NOT_IMPLEMENTED;
585 gssEapDuplicateAttrContext(OM_uint32 *minor,
590 if (in->attrCtx != NULL) {
591 gss_eap_attr_ctx *ctx = new gss_eap_attr_ctx;
593 out->attrCtx = new gss_eap_attr_ctx;
594 if (!ctx->initFromExistingContext(NULL, in->attrCtx)) {
596 return GSS_S_FAILURE;
601 } catch (std::exception &e) {
602 return mapException(minor, e);
605 return GSS_S_COMPLETE;
609 gssEapMapNameToAny(OM_uint32 *minor,
612 gss_buffer_t type_id,
616 *output = name->attrCtx->mapToAny(authenticated, type_id);
617 } catch (std::exception &e) {
618 return mapException(minor, e);
621 return GSS_S_COMPLETE;
625 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
627 gss_buffer_t type_id,
630 if (name->attrCtx == NULL)
631 return GSS_S_UNAVAILABLE;
635 name->attrCtx->releaseAnyNameMapping(type_id, *input);
637 } catch (std::exception &e) {
638 return mapException(minor, e);
641 return GSS_S_COMPLETE;
645 gssEapReleaseAttrContext(OM_uint32 *minor,
648 if (name->attrCtx != NULL)
649 delete name->attrCtx;
651 return GSS_S_COMPLETE;
655 gssEapAttrProvidersInit(OM_uint32 *minor)
658 gss_eap_attr_ctx::init();
659 } catch (std::exception &e) {
660 return mapException(minor, e);
663 return GSS_S_COMPLETE;
667 gssEapAttrProvidersFinalize(OM_uint32 *minor)
670 gss_eap_attr_ctx::finalize();
671 } catch (std::exception &e) {
672 return mapException(minor, e);
675 return GSS_S_COMPLETE;
678 struct gss_eap_attr_ctx *
679 gssEapCreateAttrContext(gss_cred_id_t gssCred,
682 gss_eap_attr_ctx *ctx;
684 ctx = gss_eap_attr_ctx::createAttrContext();
685 if (!ctx->initFromGssContext(NULL, gssCred, gssCtx)) {