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];
43 gss_eap_attr_ctx::registerProvider(unsigned int type,
44 gss_eap_attr_create_factory factory)
46 gss_eap_attr_factories[type] = factory;
49 gss_eap_attr_ctx::gss_eap_attr_ctx(void)
51 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
52 gss_eap_attr_provider *provider;
54 provider = (gss_eap_attr_factories[i])();
56 m_providers[i] = provider;
61 gss_eap_attr_ctx::initFromExistingContext(const gss_eap_attr_ctx *manager,
62 const gss_eap_attr_provider *provider)
64 if (!gss_eap_attr_provider::initFromExistingContext(this, provider))
67 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
68 gss_eap_attr_provider *provider;
70 provider = m_providers[i];
71 if (provider != NULL) {
72 if (!provider->initFromExistingContext(this, provider))
81 gss_eap_attr_ctx::initFromGssContext(const gss_eap_attr_ctx *manager,
82 const gss_cred_id_t cred,
83 const gss_ctx_id_t ctx)
85 if (!gss_eap_attr_provider::initFromGssContext(this, cred, ctx))
88 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
89 gss_eap_attr_provider *provider;
91 provider = m_providers[i];
92 if (provider != NULL) {
93 if (!provider->initFromGssContext(this, cred, ctx))
101 gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
103 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++)
104 delete m_providers[i];
108 gss_eap_attr_ctx::init(void)
110 return gss_eap_radius_attr_provider::init() &&
111 gss_eap_saml_assertion_provider::init() &&
112 gss_eap_saml_attr_provider::init() &&
113 gss_eap_shib_attr_provider::init();
117 gss_eap_attr_ctx::finalize(void)
119 gss_eap_shib_attr_provider::finalize();
120 gss_eap_saml_attr_provider::finalize();
121 gss_eap_saml_assertion_provider::finalize();
122 gss_eap_radius_attr_provider::finalize();
125 gss_eap_attr_provider *
126 gss_eap_attr_ctx::getProvider(unsigned int type) const
128 return m_providers[type];
131 gss_eap_attr_provider *
132 gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const
136 type = attributePrefixToType(prefix);
138 return m_providers[type];
142 gss_eap_attr_ctx::setAttribute(int complete,
143 const gss_buffer_t attr,
144 const gss_buffer_t value)
146 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
148 gss_eap_attr_provider *provider;
150 decomposeAttributeName(attr, &type, &suffix);
152 provider = m_providers[type];
153 if (provider != NULL) {
154 provider->setAttribute(complete,
155 (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
162 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
164 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
166 gss_eap_attr_provider *provider;
168 decomposeAttributeName(attr, &type, &suffix);
170 provider = m_providers[type];
171 if (provider != NULL) {
172 provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
177 gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
182 for (i = 0; i < ATTR_TYPE_MAX; i++) {
183 gss_eap_attr_provider *provider;
185 provider = m_providers[i];
186 if (provider == NULL)
189 ret = provider->getAttributeTypes(cb, data);
197 struct eap_gss_get_attr_types_args {
199 gss_buffer_set_t attrs;
203 addAttribute(const gss_eap_attr_provider *provider,
204 const gss_buffer_t attribute,
207 eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
208 gss_buffer_t prefix = GSS_C_NO_BUFFER;
209 gss_buffer_desc qualified;
210 OM_uint32 major, minor;
212 if (args->type != ATTR_TYPE_LOCAL) {
213 gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified);
214 major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
215 gss_release_buffer(&minor, &qualified);
217 major = gss_add_buffer_set_member(&minor, prefix, &args->attrs);
220 return GSS_ERROR(major) ? false : true;
224 gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
226 eap_gss_get_attr_types_args args;
227 OM_uint32 major, minor;
231 major = gss_create_empty_buffer_set(&minor, attrs);
232 if (GSS_ERROR(major)) {
233 throw new std::bad_alloc;
239 for (i = 0; i < ATTR_TYPE_MAX; i++) {
240 gss_eap_attr_provider *provider;
244 provider = m_providers[i];
245 if (provider == NULL)
248 ret = provider->getAttributeTypes(addAttribute, (void *)&args);
254 gss_release_buffer_set(&minor, attrs);
261 gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
265 gss_buffer_t display_value,
268 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
270 gss_eap_attr_provider *provider;
273 decomposeAttributeName(attr, &type, &suffix);
275 provider = m_providers[type];
276 if (provider == NULL) {
281 ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
282 authenticated, complete,
283 value, display_value, more);
289 gss_eap_attr_ctx::mapToAny(int authenticated,
290 gss_buffer_t type_id) const
296 gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
297 gss_any_t input) const
302 gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
304 m_providers[ATTR_TYPE_RADIUS]->exportToBuffer(buffer);
308 gss_eap_attr_ctx::initFromBuffer(const gss_eap_attr_ctx *manager,
309 const gss_buffer_t buffer)
314 ret = m_providers[ATTR_TYPE_RADIUS]->initFromBuffer(this, buffer);
318 for (i = ATTR_TYPE_RADIUS + 1; i < ATTR_TYPE_MAX; i++) {
319 gss_eap_attr_provider *provider = m_providers[i];
321 ret = provider->initFromGssContext(this,
337 mapException(OM_uint32 *minor, std::exception &e)
340 return GSS_S_FAILURE;
343 static gss_buffer_desc attributePrefixes[] = {
345 /* ATTR_TYPE_RADIUS_AVP */
346 sizeof("urn:ietf:params:gss-eap:radius-avp"),
347 (void *)"urn:ietf:params:gss-eap:radius-avp",
350 /* ATTR_TYPE_SAML_AAA_ASSERTION */
351 sizeof("urn:ietf:params:gss-eap:saml-aaa-assertion"),
352 (void *)"urn:ietf:params:gss-eap:saml-aaa-assertion"
355 /* ATTR_TYPE_SAML_ATTR */
356 sizeof("urn:ietf:params:gss-eap:saml-attr"),
357 (void *)"urn:ietf:params:gss-eap:saml-attr"
362 gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix)
366 for (i = ATTR_TYPE_MIN;
367 i < sizeof(attributePrefixes) / sizeof(attributePrefixes[0]);
370 if (bufferEqual(&attributePrefixes[i], prefix))
374 return ATTR_TYPE_LOCAL;
378 gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type)
380 if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_LOCAL)
381 return GSS_C_NO_BUFFER;
383 return &attributePrefixes[type];
387 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
394 for (i = 0; i < attribute->length; i++) {
395 if (((char *)attribute->value)[i] == ' ') {
396 p = (char *)attribute->value + i + 1;
401 prefix->value = attribute->value;
404 if (p != NULL && *p != '\0') {
405 suffix->length = attribute->length - 1 - prefix->length;
409 suffix->value = NULL;
414 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
415 const gss_buffer_t suffix)
419 if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
422 str.append((const char *)prefix->value, prefix->length);
424 if (suffix != GSS_C_NO_BUFFER) {
426 str.append((const char *)suffix->value, suffix->length);
433 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
434 const gss_buffer_t suffix)
436 const gss_buffer_t prefix = attributeTypeToPrefix(type);
438 return composeAttributeName(prefix, suffix);
442 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
443 const gss_buffer_t suffix,
444 gss_buffer_t attribute)
446 std::string str = composeAttributeName(prefix, suffix);
448 if (str.length() != 0) {
449 return duplicateBuffer(str, attribute);
451 attribute->length = 0;
452 attribute->value = NULL;
457 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
461 gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
463 decomposeAttributeName(attribute, &prefix, suffix);
464 *type = attributePrefixToType(&prefix);
468 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
469 const gss_buffer_t suffix,
470 gss_buffer_t attribute)
472 gss_buffer_t prefix = attributeTypeToPrefix(type);
474 return composeAttributeName(prefix, suffix, attribute);
478 gssEapInquireName(OM_uint32 *minor,
482 gss_buffer_set_t *attrs)
484 if (name->attrCtx == NULL)
485 return GSS_S_UNAVAILABLE;
488 if (!name->attrCtx->getAttributeTypes(attrs))
489 return GSS_S_UNAVAILABLE;
490 } catch (std::exception &e) {
491 return mapException(minor, e);
494 return GSS_S_COMPLETE;
498 gssEapGetNameAttribute(OM_uint32 *minor,
504 gss_buffer_t display_value,
513 if (display_value != NULL) {
514 display_value->length = 0;
515 display_value->value = NULL;
520 if (name->attrCtx == NULL)
521 return GSS_S_UNAVAILABLE;
524 if (!name->attrCtx->getAttribute(attr, authenticated, complete,
525 value, display_value, more))
526 return GSS_S_UNAVAILABLE;
527 } catch (std::exception &e) {
528 return mapException(minor, e);
531 return GSS_S_COMPLETE;
535 gssEapDeleteNameAttribute(OM_uint32 *minor,
539 if (name->attrCtx == NULL)
540 return GSS_S_UNAVAILABLE;
543 name->attrCtx->deleteAttribute(attr);
544 } catch (std::exception &ex) {
545 return mapException(minor, ex);
548 return GSS_S_COMPLETE;
552 gssEapSetNameAttribute(OM_uint32 *minor,
558 if (name->attrCtx == NULL)
559 return GSS_S_UNAVAILABLE;
562 name->attrCtx->setAttribute(complete, attr, value);
563 } catch (std::exception &ex) {
564 return mapException(minor, ex);
567 return GSS_S_COMPLETE;
571 gssEapExportAttrContext(OM_uint32 *minor,
575 if (name->attrCtx == NULL) {
577 buffer->value = NULL;
579 return GSS_S_COMPLETE;
583 name->attrCtx->exportToBuffer(buffer);
584 } catch (std::exception &e) {
585 return mapException(minor, e);
588 return GSS_S_COMPLETE;
592 gssEapImportAttrContext(OM_uint32 *minor,
596 gss_eap_attr_ctx *ctx = NULL;
598 assert(name->attrCtx == NULL);
600 if (buffer->length != 0) {
602 ctx = new gss_eap_attr_ctx;
604 if (!ctx->initFromBuffer(NULL, buffer)) {
606 return GSS_S_DEFECTIVE_TOKEN;
609 } catch (std::exception &e) {
611 return mapException(minor, e);
615 return GSS_S_COMPLETE;
619 gssEapDuplicateAttrContext(OM_uint32 *minor,
623 gss_eap_attr_ctx *ctx = NULL;
625 assert(out->attrCtx == NULL);
628 if (in->attrCtx != NULL) {
629 if (!ctx->initFromExistingContext(NULL, in->attrCtx)) {
631 return GSS_S_FAILURE;
635 } catch (std::exception &e) {
637 return mapException(minor, e);
640 return GSS_S_COMPLETE;
644 gssEapMapNameToAny(OM_uint32 *minor,
647 gss_buffer_t type_id,
651 *output = name->attrCtx->mapToAny(authenticated, type_id);
652 } catch (std::exception &e) {
653 return mapException(minor, e);
656 return GSS_S_COMPLETE;
660 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
662 gss_buffer_t type_id,
665 if (name->attrCtx == NULL)
666 return GSS_S_UNAVAILABLE;
670 name->attrCtx->releaseAnyNameMapping(type_id, *input);
672 } catch (std::exception &e) {
673 return mapException(minor, e);
676 return GSS_S_COMPLETE;
680 gssEapReleaseAttrContext(OM_uint32 *minor,
683 if (name->attrCtx != NULL)
684 delete name->attrCtx;
686 return GSS_S_COMPLETE;
690 gssEapAttrProvidersInit(OM_uint32 *minor)
693 gss_eap_attr_ctx::init();
694 } catch (std::exception &e) {
695 return mapException(minor, e);
698 return GSS_S_COMPLETE;
702 gssEapAttrProvidersFinalize(OM_uint32 *minor)
705 gss_eap_attr_ctx::finalize();
706 } catch (std::exception &e) {
707 return mapException(minor, e);
710 return GSS_S_COMPLETE;
713 struct gss_eap_attr_ctx *
714 gssEapCreateAttrContext(gss_cred_id_t gssCred,
717 gss_eap_attr_ctx *ctx;
719 ctx = new gss_eap_attr_ctx;
720 if (!ctx->initFromGssContext(NULL, gssCred, gssCtx)) {