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_provider gssEapAttrFactories[ATTR_TYPE_MAX];
40 static gss_buffer_desc gssEapAttrPrefixes[ATTR_TYPE_MAX];
43 gss_eap_attr_ctx::registerProvider(unsigned int type,
45 gss_eap_attr_create_provider factory)
47 assert(type < ATTR_TYPE_MAX);
49 assert(gssEapAttrFactories[type] == NULL);
51 gssEapAttrFactories[type] = factory;
53 gssEapAttrPrefixes[type].value = (void *)prefix;
54 gssEapAttrPrefixes[type].length = strlen(prefix);
56 gssEapAttrPrefixes[type].value = NULL;
57 gssEapAttrPrefixes[type].length = 0;
62 gss_eap_attr_ctx::unregisterProvider(unsigned int type)
64 assert(type < ATTR_TYPE_MAX);
66 gssEapAttrFactories[type] = NULL;
67 gssEapAttrPrefixes[type].value = NULL;
68 gssEapAttrPrefixes[type].length = 0;
71 gss_eap_attr_ctx::gss_eap_attr_ctx(void)
73 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
74 gss_eap_attr_provider *provider;
76 provider = (gssEapAttrFactories[i])();
78 m_providers[i] = provider;
83 gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix)
87 for (i = ATTR_TYPE_MIN; i < ATTR_TYPE_LOCAL; i++) {
88 if (bufferEqual(&gssEapAttrPrefixes[i], prefix))
92 return ATTR_TYPE_LOCAL;
96 gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type)
98 if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_LOCAL)
99 return GSS_C_NO_BUFFER;
101 return &gssEapAttrPrefixes[type];
105 gss_eap_attr_ctx::initFromExistingContext(const gss_eap_attr_ctx *manager,
106 const gss_eap_attr_provider *provider)
108 if (!gss_eap_attr_provider::initFromExistingContext(this, provider))
111 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
112 gss_eap_attr_provider *provider;
114 provider = m_providers[i];
115 if (provider != NULL) {
116 if (!provider->initFromExistingContext(this, provider))
125 gss_eap_attr_ctx::initFromGssContext(const gss_eap_attr_ctx *manager,
126 const gss_cred_id_t cred,
127 const gss_ctx_id_t ctx)
129 if (!gss_eap_attr_provider::initFromGssContext(this, cred, ctx))
132 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
133 gss_eap_attr_provider *provider;
135 provider = m_providers[i];
136 if (provider != NULL) {
137 if (!provider->initFromGssContext(this, cred, ctx))
145 gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
147 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++)
148 delete m_providers[i];
151 gss_eap_attr_provider *
152 gss_eap_attr_ctx::getProvider(unsigned int type) const
154 return m_providers[type];
157 gss_eap_attr_provider *
158 gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const
162 type = attributePrefixToType(prefix);
164 return m_providers[type];
168 gss_eap_attr_ctx::setAttribute(int complete,
169 const gss_buffer_t attr,
170 const gss_buffer_t value)
172 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
174 gss_eap_attr_provider *provider;
176 decomposeAttributeName(attr, &type, &suffix);
178 provider = m_providers[type];
179 if (provider != NULL) {
180 provider->setAttribute(complete,
181 (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
188 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
190 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
192 gss_eap_attr_provider *provider;
194 decomposeAttributeName(attr, &type, &suffix);
196 provider = m_providers[type];
197 if (provider != NULL) {
198 provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
203 gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
208 for (i = 0; i < ATTR_TYPE_MAX; i++) {
209 gss_eap_attr_provider *provider;
211 provider = m_providers[i];
212 if (provider == NULL)
215 ret = provider->getAttributeTypes(cb, data);
223 struct eap_gss_get_attr_types_args {
225 gss_buffer_set_t attrs;
229 addAttribute(const gss_eap_attr_provider *provider,
230 const gss_buffer_t attribute,
233 eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
234 gss_buffer_t prefix = GSS_C_NO_BUFFER;
235 gss_buffer_desc qualified;
236 OM_uint32 major, minor;
238 if (args->type != ATTR_TYPE_LOCAL) {
239 gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified);
240 major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
241 gss_release_buffer(&minor, &qualified);
243 major = gss_add_buffer_set_member(&minor, prefix, &args->attrs);
246 return GSS_ERROR(major) ? false : true;
250 gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
252 eap_gss_get_attr_types_args args;
253 OM_uint32 major, minor;
257 major = gss_create_empty_buffer_set(&minor, attrs);
258 if (GSS_ERROR(major)) {
259 throw new std::bad_alloc;
265 for (i = 0; i < ATTR_TYPE_MAX; i++) {
266 gss_eap_attr_provider *provider;
270 provider = m_providers[i];
271 if (provider == NULL)
274 ret = provider->getAttributeTypes(addAttribute, (void *)&args);
280 gss_release_buffer_set(&minor, attrs);
287 gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
291 gss_buffer_t display_value,
294 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
296 gss_eap_attr_provider *provider;
299 decomposeAttributeName(attr, &type, &suffix);
301 provider = m_providers[type];
302 if (provider == NULL) {
307 ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
308 authenticated, complete,
309 value, display_value, more);
315 gss_eap_attr_ctx::mapToAny(int authenticated,
316 gss_buffer_t type_id) const
322 gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
323 gss_any_t input) const
328 gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
330 m_providers[ATTR_TYPE_RADIUS]->exportToBuffer(buffer);
334 gss_eap_attr_ctx::initFromBuffer(const gss_eap_attr_ctx *manager,
335 const gss_buffer_t buffer)
340 ret = m_providers[ATTR_TYPE_RADIUS]->initFromBuffer(this, buffer);
344 for (i = ATTR_TYPE_RADIUS + 1; i < ATTR_TYPE_MAX; i++) {
345 gss_eap_attr_provider *provider = m_providers[i];
347 ret = provider->initFromGssContext(this,
363 mapException(OM_uint32 *minor, std::exception &e)
366 return GSS_S_FAILURE;
370 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
377 for (i = 0; i < attribute->length; i++) {
378 if (((char *)attribute->value)[i] == ' ') {
379 p = (char *)attribute->value + i + 1;
384 prefix->value = attribute->value;
387 if (p != NULL && *p != '\0') {
388 suffix->length = attribute->length - 1 - prefix->length;
392 suffix->value = NULL;
397 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
398 const gss_buffer_t suffix)
402 if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
405 str.append((const char *)prefix->value, prefix->length);
407 if (suffix != GSS_C_NO_BUFFER) {
409 str.append((const char *)suffix->value, suffix->length);
416 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
417 const gss_buffer_t suffix)
419 const gss_buffer_t prefix = attributeTypeToPrefix(type);
421 return composeAttributeName(prefix, suffix);
425 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
426 const gss_buffer_t suffix,
427 gss_buffer_t attribute)
429 std::string str = composeAttributeName(prefix, suffix);
431 if (str.length() != 0) {
432 return duplicateBuffer(str, attribute);
434 attribute->length = 0;
435 attribute->value = NULL;
440 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
444 gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
446 decomposeAttributeName(attribute, &prefix, suffix);
447 *type = attributePrefixToType(&prefix);
451 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
452 const gss_buffer_t suffix,
453 gss_buffer_t attribute)
455 gss_buffer_t prefix = attributeTypeToPrefix(type);
457 return composeAttributeName(prefix, suffix, attribute);
461 gssEapInquireName(OM_uint32 *minor,
465 gss_buffer_set_t *attrs)
467 if (name->attrCtx == NULL)
468 return GSS_S_UNAVAILABLE;
471 if (!name->attrCtx->getAttributeTypes(attrs))
472 return GSS_S_UNAVAILABLE;
473 } catch (std::exception &e) {
474 return mapException(minor, e);
477 return GSS_S_COMPLETE;
481 gssEapGetNameAttribute(OM_uint32 *minor,
487 gss_buffer_t display_value,
496 if (display_value != NULL) {
497 display_value->length = 0;
498 display_value->value = NULL;
503 if (name->attrCtx == NULL)
504 return GSS_S_UNAVAILABLE;
507 if (!name->attrCtx->getAttribute(attr, authenticated, complete,
508 value, display_value, more))
509 return GSS_S_UNAVAILABLE;
510 } catch (std::exception &e) {
511 return mapException(minor, e);
514 return GSS_S_COMPLETE;
518 gssEapDeleteNameAttribute(OM_uint32 *minor,
522 if (name->attrCtx == NULL)
523 return GSS_S_UNAVAILABLE;
526 name->attrCtx->deleteAttribute(attr);
527 } catch (std::exception &ex) {
528 return mapException(minor, ex);
531 return GSS_S_COMPLETE;
535 gssEapSetNameAttribute(OM_uint32 *minor,
541 if (name->attrCtx == NULL)
542 return GSS_S_UNAVAILABLE;
545 name->attrCtx->setAttribute(complete, attr, value);
546 } catch (std::exception &ex) {
547 return mapException(minor, ex);
550 return GSS_S_COMPLETE;
554 gssEapExportAttrContext(OM_uint32 *minor,
558 if (name->attrCtx == NULL) {
560 buffer->value = NULL;
562 return GSS_S_COMPLETE;
566 name->attrCtx->exportToBuffer(buffer);
567 if (buffer->length == 0)
568 return GSS_S_FAILURE;
569 } catch (std::exception &e) {
570 return mapException(minor, e);
573 return GSS_S_COMPLETE;
577 gssEapImportAttrContext(OM_uint32 *minor,
581 gss_eap_attr_ctx *ctx = NULL;
583 assert(name->attrCtx == NULL);
585 if (buffer->length != 0) {
587 ctx = new gss_eap_attr_ctx();
589 if (!ctx->initFromBuffer(NULL, buffer)) {
591 return GSS_S_DEFECTIVE_TOKEN;
594 } catch (std::exception &e) {
596 return mapException(minor, e);
600 return GSS_S_COMPLETE;
604 gssEapDuplicateAttrContext(OM_uint32 *minor,
608 gss_eap_attr_ctx *ctx = NULL;
610 assert(out->attrCtx == NULL);
613 if (in->attrCtx != NULL) {
614 ctx = new gss_eap_attr_ctx();
615 if (!ctx->initFromExistingContext(NULL, in->attrCtx)) {
617 return GSS_S_FAILURE;
621 } catch (std::exception &e) {
623 return mapException(minor, e);
626 return GSS_S_COMPLETE;
630 gssEapMapNameToAny(OM_uint32 *minor,
633 gss_buffer_t type_id,
637 *output = name->attrCtx->mapToAny(authenticated, type_id);
638 } catch (std::exception &e) {
639 return mapException(minor, e);
642 return GSS_S_COMPLETE;
646 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
648 gss_buffer_t type_id,
651 if (name->attrCtx == NULL)
652 return GSS_S_UNAVAILABLE;
656 name->attrCtx->releaseAnyNameMapping(type_id, *input);
658 } catch (std::exception &e) {
659 return mapException(minor, e);
662 return GSS_S_COMPLETE;
666 gssEapReleaseAttrContext(OM_uint32 *minor,
669 if (name->attrCtx != NULL)
670 delete name->attrCtx;
672 return GSS_S_COMPLETE;
676 gssEapAttrProvidersInit(OM_uint32 *minor)
679 if (gss_eap_radius_attr_provider::init() &&
680 gss_eap_saml_assertion_provider::init() &&
681 gss_eap_saml_attr_provider::init() &&
682 gss_eap_shib_attr_provider::init())
683 return GSS_S_COMPLETE;
684 } catch (std::exception &e) {
685 return mapException(minor, e);
688 return GSS_S_FAILURE;
692 gssEapAttrProvidersFinalize(OM_uint32 *minor)
695 gss_eap_shib_attr_provider::finalize();
696 gss_eap_saml_attr_provider::finalize();
697 gss_eap_saml_assertion_provider::finalize();
698 gss_eap_radius_attr_provider::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)) {