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
47 gss_eap_attr_ctx::gss_eap_attr_ctx(void)
49 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
50 gss_eap_attr_provider *provider;
52 provider = (gss_eap_attr_factories[i])();
54 m_providers[i] = provider;
59 gss_eap_attr_ctx::initFromExistingContext(const gss_eap_attr_ctx *source,
60 const gss_eap_attr_provider *ctx)
62 if (!gss_eap_attr_provider::initFromExistingContext(this, ctx))
65 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
66 gss_eap_attr_provider *provider;
68 provider = m_providers[i];
69 if (provider != NULL) {
70 if (!provider->initFromExistingContext(this, provider))
79 gss_eap_attr_ctx::initFromGssContext(const gss_eap_attr_ctx *source,
80 const gss_cred_id_t cred,
81 const gss_ctx_id_t ctx)
83 if (!gss_eap_attr_provider::initFromGssContext(this, cred, ctx))
86 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
87 gss_eap_attr_provider *provider;
89 provider = m_providers[i];
90 if (provider != NULL) {
91 if (!provider->initFromGssContext(this, cred, ctx))
99 gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
101 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++)
102 delete m_providers[i];
106 gss_eap_attr_ctx::init(void)
108 return gss_eap_radius_attr_provider::init() &&
109 gss_eap_saml_assertion_provider::init() &&
110 gss_eap_saml_attr_provider::init() &&
111 gss_eap_shib_attr_provider::init();
115 gss_eap_attr_ctx::finalize(void)
117 gss_eap_shib_attr_provider::finalize();
118 gss_eap_saml_attr_provider::finalize();
119 gss_eap_saml_assertion_provider::finalize();
120 gss_eap_radius_attr_provider::finalize();
123 gss_eap_attr_provider *
124 gss_eap_attr_ctx::getProvider(unsigned int type) const
126 return m_providers[type];
129 gss_eap_attr_provider *
130 gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const
134 type = attributePrefixToType(prefix);
136 return m_providers[type];
140 gss_eap_attr_ctx::setAttribute(int complete,
141 const gss_buffer_t attr,
142 const gss_buffer_t value)
144 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
146 gss_eap_attr_provider *provider;
148 decomposeAttributeName(attr, &type, &suffix);
150 provider = m_providers[type];
151 if (provider != NULL) {
152 provider->setAttribute(complete,
153 (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
160 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
162 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
164 gss_eap_attr_provider *provider;
166 decomposeAttributeName(attr, &type, &suffix);
168 provider = m_providers[type];
169 if (provider != NULL) {
170 provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
175 gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
180 for (i = 0; i < ATTR_TYPE_MAX; i++) {
181 gss_eap_attr_provider *provider;
183 provider = m_providers[i];
184 if (provider == NULL)
187 ret = provider->getAttributeTypes(cb, data);
195 struct eap_gss_get_attr_types_args {
197 gss_buffer_set_t attrs;
201 addAttribute(const gss_eap_attr_provider *provider,
202 const gss_buffer_t attribute,
205 eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
206 gss_buffer_t prefix = GSS_C_NO_BUFFER;
207 gss_buffer_desc qualified;
208 OM_uint32 major, minor;
210 if (args->type != ATTR_TYPE_LOCAL) {
211 gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified);
212 major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
213 gss_release_buffer(&minor, &qualified);
215 major = gss_add_buffer_set_member(&minor, prefix, &args->attrs);
218 return GSS_ERROR(major) ? false : true;
222 gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
224 eap_gss_get_attr_types_args args;
225 OM_uint32 major, minor;
229 major = gss_create_empty_buffer_set(&minor, attrs);
230 if (GSS_ERROR(major)) {
231 throw new std::bad_alloc;
237 for (i = 0; i < ATTR_TYPE_MAX; i++) {
238 gss_eap_attr_provider *provider;
242 provider = m_providers[i];
243 if (provider == NULL)
246 ret = provider->getAttributeTypes(addAttribute, (void *)&args);
252 gss_release_buffer_set(&minor, attrs);
259 gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
263 gss_buffer_t display_value,
266 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
268 gss_eap_attr_provider *provider;
271 decomposeAttributeName(attr, &type, &suffix);
273 provider = m_providers[type];
274 if (provider == NULL) {
279 ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
280 authenticated, complete,
281 value, display_value, more);
287 gss_eap_attr_ctx::mapToAny(int authenticated,
288 gss_buffer_t type_id) const
294 gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
295 gss_any_t input) const
300 gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
302 m_providers[ATTR_TYPE_RADIUS]->exportToBuffer(buffer);
306 gss_eap_attr_ctx::initFromBuffer(const gss_eap_attr_ctx *ctx,
307 const gss_buffer_t buffer)
312 ret = m_providers[ATTR_TYPE_RADIUS]->initFromBuffer(this, buffer);
316 for (i = ATTR_TYPE_RADIUS + 1; i < ATTR_TYPE_MAX; i++) {
317 gss_eap_attr_provider *provider = m_providers[i];
319 ret = provider->initFromGssContext(
320 this, GSS_C_NO_CREDENTIAL, GSS_C_NO_CONTEXT);
334 mapException(OM_uint32 *minor, std::exception &e)
337 return GSS_S_FAILURE;
340 static gss_buffer_desc attributePrefixes[] = {
342 /* ATTR_TYPE_RADIUS_AVP */
343 sizeof("urn:ietf:params:gss-eap:radius-avp"),
344 (void *)"urn:ietf:params:gss-eap:radius-avp",
347 /* ATTR_TYPE_SAML_AAA_ASSERTION */
348 sizeof("urn:ietf:params:gss-eap:saml-aaa-assertion"),
349 (void *)"urn:ietf:params:gss-eap:saml-aaa-assertion"
352 /* ATTR_TYPE_SAML_ATTR */
353 sizeof("urn:ietf:params:gss-eap:saml-attr"),
354 (void *)"urn:ietf:params:gss-eap:saml-attr"
359 gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix)
363 for (i = ATTR_TYPE_MIN;
364 i < sizeof(attributePrefixes) / sizeof(attributePrefixes[0]);
367 if (bufferEqual(&attributePrefixes[i], prefix))
371 return ATTR_TYPE_LOCAL;
375 gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type)
377 if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_LOCAL)
378 return GSS_C_NO_BUFFER;
380 return &attributePrefixes[type];
384 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
391 for (i = 0; i < attribute->length; i++) {
392 if (((char *)attribute->value)[i] == ' ') {
393 p = (char *)attribute->value + i + 1;
398 prefix->value = attribute->value;
401 if (p != NULL && *p != '\0') {
402 suffix->length = attribute->length - 1 - prefix->length;
406 suffix->value = NULL;
411 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
412 const gss_buffer_t suffix)
416 if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
419 str.append((const char *)prefix->value, prefix->length);
421 if (suffix != GSS_C_NO_BUFFER) {
423 str.append((const char *)suffix->value, suffix->length);
430 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
431 const gss_buffer_t suffix)
433 const gss_buffer_t prefix = attributeTypeToPrefix(type);
435 return composeAttributeName(prefix, suffix);
439 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
440 const gss_buffer_t suffix,
441 gss_buffer_t attribute)
443 std::string str = composeAttributeName(prefix, suffix);
445 if (str.length() != 0) {
446 return duplicateBuffer(str, attribute);
448 attribute->length = 0;
449 attribute->value = NULL;
454 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
458 gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
460 decomposeAttributeName(attribute, &prefix, suffix);
461 *type = attributePrefixToType(&prefix);
465 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
466 const gss_buffer_t suffix,
467 gss_buffer_t attribute)
469 gss_buffer_t prefix = attributeTypeToPrefix(type);
471 return composeAttributeName(prefix, suffix, attribute);
475 gssEapInquireName(OM_uint32 *minor,
479 gss_buffer_set_t *attrs)
481 if (name->attrCtx == NULL)
482 return GSS_S_UNAVAILABLE;
485 if (!name->attrCtx->getAttributeTypes(attrs))
486 return GSS_S_UNAVAILABLE;
487 } catch (std::exception &e) {
488 return mapException(minor, e);
491 return GSS_S_COMPLETE;
495 gssEapGetNameAttribute(OM_uint32 *minor,
501 gss_buffer_t display_value,
510 if (display_value != NULL) {
511 display_value->length = 0;
512 display_value->value = NULL;
517 if (name->attrCtx == NULL)
518 return GSS_S_UNAVAILABLE;
521 if (!name->attrCtx->getAttribute(attr, authenticated, complete,
522 value, display_value, more))
523 return GSS_S_UNAVAILABLE;
524 } catch (std::exception &e) {
525 return mapException(minor, e);
528 return GSS_S_COMPLETE;
532 gssEapDeleteNameAttribute(OM_uint32 *minor,
536 if (name->attrCtx == NULL)
537 return GSS_S_UNAVAILABLE;
540 name->attrCtx->deleteAttribute(attr);
541 } catch (std::exception &ex) {
542 return mapException(minor, ex);
545 return GSS_S_COMPLETE;
549 gssEapSetNameAttribute(OM_uint32 *minor,
555 if (name->attrCtx == NULL)
556 return GSS_S_UNAVAILABLE;
559 name->attrCtx->setAttribute(complete, attr, value);
560 } catch (std::exception &ex) {
561 return mapException(minor, ex);
564 return GSS_S_COMPLETE;
568 gssEapExportAttrContext(OM_uint32 *minor,
572 if (name->attrCtx == NULL) {
574 buffer->value = NULL;
576 return GSS_S_COMPLETE;
580 name->attrCtx->exportToBuffer(buffer);
581 } catch (std::exception &e) {
582 return mapException(minor, e);
585 return GSS_S_COMPLETE;
589 gssEapImportAttrContext(OM_uint32 *minor,
593 if (buffer->length != 0) {
594 gss_eap_attr_ctx *ctx = new gss_eap_attr_ctx;
597 if (!ctx->initFromBuffer(NULL, buffer)) {
599 return GSS_S_DEFECTIVE_TOKEN;
602 } catch (std::exception &e) {
604 return mapException(minor, e);
608 return GSS_S_COMPLETE;
612 gssEapDuplicateAttrContext(OM_uint32 *minor,
616 gss_eap_attr_ctx *ctx = NULL;
618 assert(out->attrCtx == NULL);
621 if (in->attrCtx != NULL) {
622 if (!ctx->initFromExistingContext(NULL, in->attrCtx)) {
624 return GSS_S_FAILURE;
628 } catch (std::exception &e) {
630 return mapException(minor, e);
633 return GSS_S_COMPLETE;
637 gssEapMapNameToAny(OM_uint32 *minor,
640 gss_buffer_t type_id,
644 *output = name->attrCtx->mapToAny(authenticated, type_id);
645 } catch (std::exception &e) {
646 return mapException(minor, e);
649 return GSS_S_COMPLETE;
653 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
655 gss_buffer_t type_id,
658 if (name->attrCtx == NULL)
659 return GSS_S_UNAVAILABLE;
663 name->attrCtx->releaseAnyNameMapping(type_id, *input);
665 } catch (std::exception &e) {
666 return mapException(minor, e);
669 return GSS_S_COMPLETE;
673 gssEapReleaseAttrContext(OM_uint32 *minor,
676 if (name->attrCtx != NULL)
677 delete name->attrCtx;
679 return GSS_S_COMPLETE;
683 gssEapAttrProvidersInit(OM_uint32 *minor)
686 gss_eap_attr_ctx::init();
687 } catch (std::exception &e) {
688 return mapException(minor, e);
691 return GSS_S_COMPLETE;
695 gssEapAttrProvidersFinalize(OM_uint32 *minor)
698 gss_eap_attr_ctx::finalize();
699 } catch (std::exception &e) {
700 return mapException(minor, e);
703 return GSS_S_COMPLETE;
706 struct gss_eap_attr_ctx *
707 gssEapCreateAttrContext(gss_cred_id_t gssCred,
710 gss_eap_attr_ctx *ctx;
712 ctx = new gss_eap_attr_ctx;
713 if (!ctx->initFromGssContext(NULL, gssCred, gssCtx)) {