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_factory
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];
331 mapException(OM_uint32 *minor, std::exception &e)
334 return GSS_S_FAILURE;
337 static gss_buffer_desc attributePrefixes[] = {
339 /* ATTR_TYPE_RADIUS_AVP */
340 sizeof("urn:ietf:params:gss-eap:radius-avp"),
341 (void *)"urn:ietf:params:gss-eap:radius-avp",
344 /* ATTR_TYPE_SAML_AAA_ASSERTION */
345 sizeof("urn:ietf:params:gss-eap:saml-aaa-assertion"),
346 (void *)"urn:ietf:params:gss-eap:saml-aaa-assertion"
349 /* ATTR_TYPE_SAML_ATTR */
350 sizeof("urn:ietf:params:gss-eap:saml-attr"),
351 (void *)"urn:ietf:params:gss-eap:saml-attr"
356 gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix)
360 for (i = ATTR_TYPE_MIN;
361 i < sizeof(attributePrefixes) / sizeof(attributePrefixes[0]);
364 if (bufferEqual(&attributePrefixes[i], prefix))
368 return ATTR_TYPE_LOCAL;
372 gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type)
374 if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_LOCAL)
375 return GSS_C_NO_BUFFER;
377 return &attributePrefixes[type];
381 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
388 for (i = 0; i < attribute->length; i++) {
389 if (((char *)attribute->value)[i] == ' ') {
390 p = (char *)attribute->value + i + 1;
395 prefix->value = attribute->value;
398 if (p != NULL && *p != '\0') {
399 suffix->length = attribute->length - 1 - prefix->length;
403 suffix->value = NULL;
408 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
409 const gss_buffer_t suffix)
413 if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
416 str.append((const char *)prefix->value, prefix->length);
418 if (suffix != GSS_C_NO_BUFFER) {
420 str.append((const char *)suffix->value, suffix->length);
427 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
428 const gss_buffer_t suffix)
430 const gss_buffer_t prefix = attributeTypeToPrefix(type);
432 return composeAttributeName(prefix, suffix);
436 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
437 const gss_buffer_t suffix,
438 gss_buffer_t attribute)
440 std::string str = composeAttributeName(prefix, suffix);
442 if (str.length() != 0) {
443 return duplicateBuffer(str, attribute);
445 attribute->length = 0;
446 attribute->value = NULL;
451 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
455 gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
457 decomposeAttributeName(attribute, &prefix, suffix);
458 *type = attributePrefixToType(&prefix);
462 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
463 const gss_buffer_t suffix,
464 gss_buffer_t attribute)
466 gss_buffer_t prefix = attributeTypeToPrefix(type);
468 return composeAttributeName(prefix, suffix, attribute);
472 gssEapInquireName(OM_uint32 *minor,
476 gss_buffer_set_t *attrs)
478 if (name->attrCtx == NULL)
479 return GSS_S_UNAVAILABLE;
482 if (!name->attrCtx->getAttributeTypes(attrs))
483 return GSS_S_UNAVAILABLE;
484 } catch (std::exception &e) {
485 return mapException(minor, e);
488 return GSS_S_COMPLETE;
492 gssEapGetNameAttribute(OM_uint32 *minor,
498 gss_buffer_t display_value,
507 if (display_value != NULL) {
508 display_value->length = 0;
509 display_value->value = NULL;
514 if (name->attrCtx == NULL)
515 return GSS_S_UNAVAILABLE;
518 if (!name->attrCtx->getAttribute(attr, authenticated, complete,
519 value, display_value, more))
520 return GSS_S_UNAVAILABLE;
521 } catch (std::exception &e) {
522 return mapException(minor, e);
525 return GSS_S_COMPLETE;
529 gssEapDeleteNameAttribute(OM_uint32 *minor,
533 if (name->attrCtx == NULL)
534 return GSS_S_UNAVAILABLE;
537 name->attrCtx->deleteAttribute(attr);
538 } catch (std::exception &ex) {
539 return mapException(minor, ex);
542 return GSS_S_COMPLETE;
546 gssEapSetNameAttribute(OM_uint32 *minor,
552 if (name->attrCtx == NULL)
553 return GSS_S_UNAVAILABLE;
556 name->attrCtx->setAttribute(complete, attr, value);
557 } catch (std::exception &ex) {
558 return mapException(minor, ex);
561 return GSS_S_COMPLETE;
565 gssEapExportAttrContext(OM_uint32 *minor,
569 if (name->attrCtx == NULL) {
571 buffer->value = NULL;
573 return GSS_S_COMPLETE;
577 name->attrCtx->marshall(buffer);
578 } catch (std::exception &e) {
579 return mapException(minor, e);
582 return GSS_S_COMPLETE;
586 gssEapImportAttrContext(OM_uint32 *minor,
591 GSSEAP_NOT_IMPLEMENTED;
593 return GSS_S_COMPLETE;
597 gssEapDuplicateAttrContext(OM_uint32 *minor,
602 if (in->attrCtx != NULL) {
603 gss_eap_attr_ctx *ctx = new gss_eap_attr_ctx;
605 out->attrCtx = new gss_eap_attr_ctx;
606 if (!ctx->initFromExistingContext(NULL, in->attrCtx)) {
608 return GSS_S_FAILURE;
613 } catch (std::exception &e) {
614 return mapException(minor, e);
617 return GSS_S_COMPLETE;
621 gssEapMapNameToAny(OM_uint32 *minor,
624 gss_buffer_t type_id,
628 *output = name->attrCtx->mapToAny(authenticated, type_id);
629 } catch (std::exception &e) {
630 return mapException(minor, e);
633 return GSS_S_COMPLETE;
637 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
639 gss_buffer_t type_id,
642 if (name->attrCtx == NULL)
643 return GSS_S_UNAVAILABLE;
647 name->attrCtx->releaseAnyNameMapping(type_id, *input);
649 } catch (std::exception &e) {
650 return mapException(minor, e);
653 return GSS_S_COMPLETE;
657 gssEapReleaseAttrContext(OM_uint32 *minor,
660 if (name->attrCtx != NULL)
661 delete name->attrCtx;
663 return GSS_S_COMPLETE;
667 gssEapAttrProvidersInit(OM_uint32 *minor)
670 gss_eap_attr_ctx::init();
671 } catch (std::exception &e) {
672 return mapException(minor, e);
675 return GSS_S_COMPLETE;
679 gssEapAttrProvidersFinalize(OM_uint32 *minor)
682 gss_eap_attr_ctx::finalize();
683 } catch (std::exception &e) {
684 return mapException(minor, e);
687 return GSS_S_COMPLETE;
690 struct gss_eap_attr_ctx *
691 gssEapCreateAttrContext(gss_cred_id_t gssCred,
694 gss_eap_attr_ctx *ctx;
696 ctx = gss_eap_attr_ctx::createAttrContext();
697 if (!ctx->initFromGssContext(NULL, gssCred, gssCtx)) {