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;
80 /* providers should fail in constructor */
81 assert(m_providers[i] != NULL);
86 gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix)
90 for (i = ATTR_TYPE_MIN; i < ATTR_TYPE_LOCAL; i++) {
91 if (bufferEqual(&gssEapAttrPrefixes[i], prefix))
95 return ATTR_TYPE_LOCAL;
99 gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type)
101 if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_LOCAL)
102 return GSS_C_NO_BUFFER;
104 return &gssEapAttrPrefixes[type];
108 * Initialize a context from an existing context. All non-NULL providers
109 * in the existing context are duplicated, otherwise FALSE is returned.
112 gss_eap_attr_ctx::initFromExistingContext(const gss_eap_attr_ctx *manager)
116 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
117 gss_eap_attr_provider *provider = m_providers[i];
119 ret = provider->initFromExistingContext(this, manager->m_providers[i]);
128 * Initialize a context from a GSS credential and context.
131 gss_eap_attr_ctx::initFromGssContext(const gss_cred_id_t cred,
132 const gss_ctx_id_t ctx)
136 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
137 gss_eap_attr_provider *provider = m_providers[i];
139 ret = provider->initFromGssContext(this, cred, ctx);
148 * Initialize a context from an exported context or name token
151 gss_eap_attr_ctx::initFromBuffer(const gss_buffer_t buffer)
154 gss_eap_attr_provider *primaryProvider = getPrimaryProvider();
156 ret = primaryProvider->initFromBuffer(this, buffer);
160 for (unsigned int i = ATTR_TYPE_MIN; i < ATTR_TYPE_MAX; i++) {
161 gss_eap_attr_provider *provider = m_providers[i];
163 if (provider == primaryProvider)
166 ret = provider->initFromGssContext(this,
176 gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
178 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++)
179 delete m_providers[i];
182 gss_eap_attr_provider *
183 gss_eap_attr_ctx::getProvider(unsigned int type) const
185 return m_providers[type];
188 gss_eap_attr_provider *
189 gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const
193 type = attributePrefixToType(prefix);
195 return m_providers[type];
199 gss_eap_attr_ctx::setAttribute(int complete,
200 const gss_buffer_t attr,
201 const gss_buffer_t value)
203 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
205 gss_eap_attr_provider *provider;
207 decomposeAttributeName(attr, &type, &suffix);
209 provider = m_providers[type];
210 if (provider != NULL) {
211 provider->setAttribute(complete,
212 (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
219 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
221 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
223 gss_eap_attr_provider *provider;
225 decomposeAttributeName(attr, &type, &suffix);
227 provider = m_providers[type];
228 if (provider != NULL) {
229 provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
234 gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
239 for (i = 0; i < ATTR_TYPE_MAX; i++) {
240 ret = m_providers[i]->getAttributeTypes(cb, data);
248 struct eap_gss_get_attr_types_args {
250 gss_buffer_set_t attrs;
254 addAttribute(const gss_eap_attr_provider *provider,
255 const gss_buffer_t attribute,
258 eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
259 gss_buffer_t prefix = GSS_C_NO_BUFFER;
260 gss_buffer_desc qualified;
261 OM_uint32 major, minor;
263 if (args->type != ATTR_TYPE_LOCAL) {
264 gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified);
265 major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
266 gss_release_buffer(&minor, &qualified);
268 major = gss_add_buffer_set_member(&minor, prefix, &args->attrs);
271 return GSS_ERROR(major) ? false : true;
275 gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
277 eap_gss_get_attr_types_args args;
278 OM_uint32 major, minor;
282 major = gss_create_empty_buffer_set(&minor, attrs);
283 if (GSS_ERROR(major)) {
284 throw new std::bad_alloc;
290 for (i = 0; i < ATTR_TYPE_MAX; i++) {
293 ret = m_providers[i]->getAttributeTypes(addAttribute, (void *)&args);
299 gss_release_buffer_set(&minor, attrs);
305 gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
309 gss_buffer_t display_value,
312 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
314 gss_eap_attr_provider *provider;
317 decomposeAttributeName(attr, &type, &suffix);
319 provider = m_providers[type];
321 ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
322 authenticated, complete,
323 value, display_value, more);
329 gss_eap_attr_ctx::mapToAny(int authenticated,
330 gss_buffer_t type_id) const
333 gss_eap_attr_provider *provider;
335 type = attributePrefixToType(type_id);
337 provider = m_providers[type];
339 return provider->mapToAny(authenticated, type_id);
343 gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
344 gss_any_t input) const
347 gss_eap_attr_provider *provider;
349 type = attributePrefixToType(type_id);
351 provider = m_providers[type];
353 provider->releaseAnyNameMapping(type_id, input);
356 gss_eap_attr_provider *
357 gss_eap_attr_ctx::getPrimaryProvider(void) const
359 return m_providers[ATTR_TYPE_RADIUS];
363 gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
365 getPrimaryProvider()->exportToBuffer(buffer);
369 gss_eap_attr_ctx::getExpiryTime(void) const
372 time_t expiryTime = 0;
374 for (i = ATTR_TYPE_MIN; i < ATTR_TYPE_MAX; i++) {
375 time_t providerExpiryTime = m_providers[i]->getExpiryTime();
377 if (providerExpiryTime == 0)
380 if (expiryTime == 0 || providerExpiryTime < expiryTime)
381 expiryTime = providerExpiryTime;
392 mapException(OM_uint32 *minor, std::exception &e)
395 return GSS_S_FAILURE;
399 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
406 for (i = 0; i < attribute->length; i++) {
407 if (((char *)attribute->value)[i] == ' ') {
408 p = (char *)attribute->value + i + 1;
413 prefix->value = attribute->value;
416 if (p != NULL && *p != '\0') {
417 suffix->length = attribute->length - 1 - prefix->length;
421 suffix->value = NULL;
426 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
427 const gss_buffer_t suffix)
431 if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
434 str.append((const char *)prefix->value, prefix->length);
436 if (suffix != GSS_C_NO_BUFFER) {
438 str.append((const char *)suffix->value, suffix->length);
445 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
446 const gss_buffer_t suffix)
448 const gss_buffer_t prefix = attributeTypeToPrefix(type);
450 return composeAttributeName(prefix, suffix);
454 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
455 const gss_buffer_t suffix,
456 gss_buffer_t attribute)
458 std::string str = composeAttributeName(prefix, suffix);
460 if (str.length() != 0) {
461 return duplicateBuffer(str, attribute);
463 attribute->length = 0;
464 attribute->value = NULL;
469 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
473 gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
475 decomposeAttributeName(attribute, &prefix, suffix);
476 *type = attributePrefixToType(&prefix);
480 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
481 const gss_buffer_t suffix,
482 gss_buffer_t attribute)
484 gss_buffer_t prefix = attributeTypeToPrefix(type);
486 return composeAttributeName(prefix, suffix, attribute);
490 gssEapInquireName(OM_uint32 *minor,
494 gss_buffer_set_t *attrs)
496 if (name->attrCtx == NULL)
497 return GSS_S_UNAVAILABLE;
500 if (!name->attrCtx->getAttributeTypes(attrs))
501 return GSS_S_UNAVAILABLE;
502 } catch (std::exception &e) {
503 return mapException(minor, e);
506 return GSS_S_COMPLETE;
510 gssEapGetNameAttribute(OM_uint32 *minor,
516 gss_buffer_t display_value,
527 if (display_value != NULL) {
528 display_value->length = 0;
529 display_value->value = NULL;
532 if (name->attrCtx == NULL)
533 return GSS_S_UNAVAILABLE;
536 if (!name->attrCtx->getAttribute(attr, authenticated, complete,
537 value, display_value, more))
538 return GSS_S_UNAVAILABLE;
539 } catch (std::exception &e) {
540 return mapException(minor, e);
543 return GSS_S_COMPLETE;
547 gssEapDeleteNameAttribute(OM_uint32 *minor,
551 if (name->attrCtx == NULL)
552 return GSS_S_UNAVAILABLE;
555 name->attrCtx->deleteAttribute(attr);
556 } catch (std::exception &ex) {
557 return mapException(minor, ex);
560 return GSS_S_COMPLETE;
564 gssEapSetNameAttribute(OM_uint32 *minor,
570 if (name->attrCtx == NULL)
571 return GSS_S_UNAVAILABLE;
574 name->attrCtx->setAttribute(complete, attr, value);
575 } catch (std::exception &ex) {
576 return mapException(minor, ex);
579 return GSS_S_COMPLETE;
583 gssEapExportAttrContext(OM_uint32 *minor,
587 if (name->attrCtx == NULL) {
589 buffer->value = NULL;
591 return GSS_S_COMPLETE;
595 name->attrCtx->exportToBuffer(buffer);
596 if (buffer->length == 0)
597 return GSS_S_FAILURE;
598 } catch (std::exception &e) {
599 return mapException(minor, e);
602 return GSS_S_COMPLETE;
606 gssEapImportAttrContext(OM_uint32 *minor,
610 gss_eap_attr_ctx *ctx = NULL;
612 assert(name->attrCtx == NULL);
614 if (buffer->length != 0) {
616 ctx = new gss_eap_attr_ctx();
618 if (!ctx->initFromBuffer(buffer)) {
620 return GSS_S_DEFECTIVE_TOKEN;
623 } catch (std::exception &e) {
625 return mapException(minor, e);
629 return GSS_S_COMPLETE;
633 gssEapDuplicateAttrContext(OM_uint32 *minor,
637 gss_eap_attr_ctx *ctx = NULL;
639 assert(out->attrCtx == NULL);
642 if (in->attrCtx != NULL) {
643 ctx = new gss_eap_attr_ctx();
644 if (!ctx->initFromExistingContext(in->attrCtx)) {
646 return GSS_S_FAILURE;
650 } catch (std::exception &e) {
652 return mapException(minor, e);
655 return GSS_S_COMPLETE;
659 gssEapMapNameToAny(OM_uint32 *minor,
662 gss_buffer_t type_id,
666 *output = name->attrCtx->mapToAny(authenticated, type_id);
667 } catch (std::exception &e) {
668 return mapException(minor, e);
671 return GSS_S_COMPLETE;
675 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
677 gss_buffer_t type_id,
680 if (name->attrCtx == NULL)
681 return GSS_S_UNAVAILABLE;
685 name->attrCtx->releaseAnyNameMapping(type_id, *input);
687 } catch (std::exception &e) {
688 return mapException(minor, e);
691 return GSS_S_COMPLETE;
695 gssEapReleaseAttrContext(OM_uint32 *minor,
698 if (name->attrCtx != NULL)
699 delete name->attrCtx;
701 return GSS_S_COMPLETE;
705 gssEapAttrProvidersInit(OM_uint32 *minor)
708 if (gss_eap_radius_attr_provider::init() &&
709 gss_eap_saml_assertion_provider::init() &&
710 gss_eap_saml_attr_provider::init() &&
711 gss_eap_shib_attr_provider::init())
712 return GSS_S_COMPLETE;
713 } catch (std::exception &e) {
714 return mapException(minor, e);
717 return GSS_S_FAILURE;
721 gssEapAttrProvidersFinalize(OM_uint32 *minor)
724 gss_eap_shib_attr_provider::finalize();
725 gss_eap_saml_attr_provider::finalize();
726 gss_eap_saml_assertion_provider::finalize();
727 gss_eap_radius_attr_provider::finalize();
728 } catch (std::exception &e) {
729 return mapException(minor, e);
732 return GSS_S_COMPLETE;
735 struct gss_eap_attr_ctx *
736 gssEapCreateAttrContext(gss_cred_id_t gssCred,
739 gss_eap_attr_ctx *ctx;
741 assert(gssCtx != GSS_C_NO_CONTEXT);
743 ctx = new gss_eap_attr_ctx();
744 if (!ctx->initFromGssContext(gssCred, gssCtx)) {
749 gssCtx->expiryTime = ctx->getExpiryTime();