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 * Initialize a context from an existing context. All non-NULL providers
106 * in the existing context are duplicated, otherwise FALSE is returned.
109 gss_eap_attr_ctx::initFromExistingContext(const gss_eap_attr_ctx *manager)
111 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
112 gss_eap_attr_provider *provider;
114 if (manager->m_providers[i] == NULL)
117 provider = m_providers[i];
118 if (!provider->initFromExistingContext(this, manager->m_providers[i]))
126 * Initialize a context from a GSS credential and context.
129 gss_eap_attr_ctx::initFromGssContext(const gss_cred_id_t cred,
130 const gss_ctx_id_t ctx)
132 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
133 gss_eap_attr_provider *provider = m_providers[i];
135 if (!provider->initFromGssContext(this, cred, ctx))
143 * Initialize a context from an exported context or name token
146 gss_eap_attr_ctx::initFromBuffer(const gss_buffer_t buffer)
149 gss_eap_attr_provider *primaryProvider = getPrimaryProvider();
151 assert(primaryProvider != NULL);
153 if (!primaryProvider->initFromBuffer(this, buffer))
156 for (i = ATTR_TYPE_MIN; i < ATTR_TYPE_MAX; i++) {
157 gss_eap_attr_provider *provider = m_providers[i];
159 if (provider == primaryProvider)
162 if (!provider->initFromGssContext(this,
171 gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
173 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++)
174 delete m_providers[i];
177 gss_eap_attr_provider *
178 gss_eap_attr_ctx::getProvider(unsigned int type) const
180 return m_providers[type];
183 gss_eap_attr_provider *
184 gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const
188 type = attributePrefixToType(prefix);
190 return m_providers[type];
194 gss_eap_attr_ctx::setAttribute(int complete,
195 const gss_buffer_t attr,
196 const gss_buffer_t value)
198 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
200 gss_eap_attr_provider *provider;
202 decomposeAttributeName(attr, &type, &suffix);
204 provider = m_providers[type];
205 if (provider != NULL) {
206 provider->setAttribute(complete,
207 (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
214 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
216 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
218 gss_eap_attr_provider *provider;
220 decomposeAttributeName(attr, &type, &suffix);
222 provider = m_providers[type];
223 if (provider != NULL) {
224 provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
229 gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
234 for (i = 0; i < ATTR_TYPE_MAX; i++) {
235 gss_eap_attr_provider *provider;
237 provider = m_providers[i];
238 if (provider == NULL)
241 ret = provider->getAttributeTypes(cb, data);
249 struct eap_gss_get_attr_types_args {
251 gss_buffer_set_t attrs;
255 addAttribute(const gss_eap_attr_provider *provider,
256 const gss_buffer_t attribute,
259 eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
260 gss_buffer_t prefix = GSS_C_NO_BUFFER;
261 gss_buffer_desc qualified;
262 OM_uint32 major, minor;
264 if (args->type != ATTR_TYPE_LOCAL) {
265 gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified);
266 major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
267 gss_release_buffer(&minor, &qualified);
269 major = gss_add_buffer_set_member(&minor, prefix, &args->attrs);
272 return GSS_ERROR(major) ? false : true;
276 gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
278 eap_gss_get_attr_types_args args;
279 OM_uint32 major, minor;
283 major = gss_create_empty_buffer_set(&minor, attrs);
284 if (GSS_ERROR(major)) {
285 throw new std::bad_alloc;
291 for (i = 0; i < ATTR_TYPE_MAX; i++) {
292 gss_eap_attr_provider *provider;
296 provider = m_providers[i];
297 if (provider == NULL)
300 ret = provider->getAttributeTypes(addAttribute, (void *)&args);
306 gss_release_buffer_set(&minor, attrs);
313 gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
317 gss_buffer_t display_value,
320 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
322 gss_eap_attr_provider *provider;
325 decomposeAttributeName(attr, &type, &suffix);
327 provider = m_providers[type];
328 if (provider == NULL) {
333 ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
334 authenticated, complete,
335 value, display_value, more);
341 gss_eap_attr_ctx::mapToAny(int authenticated,
342 gss_buffer_t type_id) const
345 gss_eap_attr_provider *provider;
347 type = attributePrefixToType(type_id);
349 provider = m_providers[type];
351 return provider->mapToAny(authenticated, type_id);
355 gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
356 gss_any_t input) const
359 gss_eap_attr_provider *provider;
361 type = attributePrefixToType(type_id);
363 provider = m_providers[type];
365 provider->releaseAnyNameMapping(type_id, input);
368 gss_eap_attr_provider *
369 gss_eap_attr_ctx::getPrimaryProvider(void) const
371 return m_providers[ATTR_TYPE_RADIUS];
375 gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
377 getPrimaryProvider()->exportToBuffer(buffer);
381 gss_eap_attr_ctx::getExpiryTime(void) const
384 time_t expiryTime = 0;
386 for (i = ATTR_TYPE_MIN; i < ATTR_TYPE_MAX; i++) {
387 time_t providerExpiryTime = m_providers[i]->getExpiryTime();
389 if (providerExpiryTime == 0)
392 if (expiryTime == 0 || providerExpiryTime < expiryTime)
393 expiryTime = providerExpiryTime;
404 mapException(OM_uint32 *minor, std::exception &e)
407 return GSS_S_FAILURE;
411 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
418 for (i = 0; i < attribute->length; i++) {
419 if (((char *)attribute->value)[i] == ' ') {
420 p = (char *)attribute->value + i + 1;
425 prefix->value = attribute->value;
428 if (p != NULL && *p != '\0') {
429 suffix->length = attribute->length - 1 - prefix->length;
433 suffix->value = NULL;
438 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
439 const gss_buffer_t suffix)
443 if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
446 str.append((const char *)prefix->value, prefix->length);
448 if (suffix != GSS_C_NO_BUFFER) {
450 str.append((const char *)suffix->value, suffix->length);
457 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
458 const gss_buffer_t suffix)
460 const gss_buffer_t prefix = attributeTypeToPrefix(type);
462 return composeAttributeName(prefix, suffix);
466 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
467 const gss_buffer_t suffix,
468 gss_buffer_t attribute)
470 std::string str = composeAttributeName(prefix, suffix);
472 if (str.length() != 0) {
473 return duplicateBuffer(str, attribute);
475 attribute->length = 0;
476 attribute->value = NULL;
481 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
485 gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
487 decomposeAttributeName(attribute, &prefix, suffix);
488 *type = attributePrefixToType(&prefix);
492 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
493 const gss_buffer_t suffix,
494 gss_buffer_t attribute)
496 gss_buffer_t prefix = attributeTypeToPrefix(type);
498 return composeAttributeName(prefix, suffix, attribute);
502 gssEapInquireName(OM_uint32 *minor,
506 gss_buffer_set_t *attrs)
508 if (name->attrCtx == NULL)
509 return GSS_S_UNAVAILABLE;
512 if (!name->attrCtx->getAttributeTypes(attrs))
513 return GSS_S_UNAVAILABLE;
514 } catch (std::exception &e) {
515 return mapException(minor, e);
518 return GSS_S_COMPLETE;
522 gssEapGetNameAttribute(OM_uint32 *minor,
528 gss_buffer_t display_value,
539 if (display_value != NULL) {
540 display_value->length = 0;
541 display_value->value = NULL;
544 if (name->attrCtx == NULL)
545 return GSS_S_UNAVAILABLE;
548 if (!name->attrCtx->getAttribute(attr, authenticated, complete,
549 value, display_value, more))
550 return GSS_S_UNAVAILABLE;
551 } catch (std::exception &e) {
552 return mapException(minor, e);
555 return GSS_S_COMPLETE;
559 gssEapDeleteNameAttribute(OM_uint32 *minor,
563 if (name->attrCtx == NULL)
564 return GSS_S_UNAVAILABLE;
567 name->attrCtx->deleteAttribute(attr);
568 } catch (std::exception &ex) {
569 return mapException(minor, ex);
572 return GSS_S_COMPLETE;
576 gssEapSetNameAttribute(OM_uint32 *minor,
582 if (name->attrCtx == NULL)
583 return GSS_S_UNAVAILABLE;
586 name->attrCtx->setAttribute(complete, attr, value);
587 } catch (std::exception &ex) {
588 return mapException(minor, ex);
591 return GSS_S_COMPLETE;
595 gssEapExportAttrContext(OM_uint32 *minor,
599 if (name->attrCtx == NULL) {
601 buffer->value = NULL;
603 return GSS_S_COMPLETE;
607 name->attrCtx->exportToBuffer(buffer);
608 if (buffer->length == 0)
609 return GSS_S_FAILURE;
610 } catch (std::exception &e) {
611 return mapException(minor, e);
614 return GSS_S_COMPLETE;
618 gssEapImportAttrContext(OM_uint32 *minor,
622 gss_eap_attr_ctx *ctx = NULL;
624 assert(name->attrCtx == NULL);
626 if (buffer->length != 0) {
628 ctx = new gss_eap_attr_ctx();
630 if (!ctx->initFromBuffer(buffer)) {
632 return GSS_S_DEFECTIVE_TOKEN;
635 } catch (std::exception &e) {
637 return mapException(minor, e);
641 return GSS_S_COMPLETE;
645 gssEapDuplicateAttrContext(OM_uint32 *minor,
649 gss_eap_attr_ctx *ctx = NULL;
651 assert(out->attrCtx == NULL);
654 if (in->attrCtx != NULL) {
655 ctx = new gss_eap_attr_ctx();
656 if (!ctx->initFromExistingContext(in->attrCtx)) {
658 return GSS_S_FAILURE;
662 } catch (std::exception &e) {
664 return mapException(minor, e);
667 return GSS_S_COMPLETE;
671 gssEapMapNameToAny(OM_uint32 *minor,
674 gss_buffer_t type_id,
678 *output = name->attrCtx->mapToAny(authenticated, type_id);
679 } catch (std::exception &e) {
680 return mapException(minor, e);
683 return GSS_S_COMPLETE;
687 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
689 gss_buffer_t type_id,
692 if (name->attrCtx == NULL)
693 return GSS_S_UNAVAILABLE;
697 name->attrCtx->releaseAnyNameMapping(type_id, *input);
699 } catch (std::exception &e) {
700 return mapException(minor, e);
703 return GSS_S_COMPLETE;
707 gssEapReleaseAttrContext(OM_uint32 *minor,
710 if (name->attrCtx != NULL)
711 delete name->attrCtx;
713 return GSS_S_COMPLETE;
717 gssEapAttrProvidersInit(OM_uint32 *minor)
720 if (gss_eap_radius_attr_provider::init() &&
721 gss_eap_saml_assertion_provider::init() &&
722 gss_eap_saml_attr_provider::init() &&
723 gss_eap_shib_attr_provider::init())
724 return GSS_S_COMPLETE;
725 } catch (std::exception &e) {
726 return mapException(minor, e);
729 return GSS_S_FAILURE;
733 gssEapAttrProvidersFinalize(OM_uint32 *minor)
736 gss_eap_shib_attr_provider::finalize();
737 gss_eap_saml_attr_provider::finalize();
738 gss_eap_saml_assertion_provider::finalize();
739 gss_eap_radius_attr_provider::finalize();
740 } catch (std::exception &e) {
741 return mapException(minor, e);
744 return GSS_S_COMPLETE;
747 struct gss_eap_attr_ctx *
748 gssEapCreateAttrContext(gss_cred_id_t gssCred,
751 gss_eap_attr_ctx *ctx;
753 assert(gssCtx != GSS_C_NO_CONTEXT);
755 ctx = new gss_eap_attr_ctx();
756 if (!ctx->initFromGssContext(gssCred, gssCtx)) {
761 gssCtx->expiryTime = ctx->getExpiryTime();