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)
107 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
108 gss_eap_attr_provider *provider;
110 provider = m_providers[i];
111 if (provider != NULL) {
112 if (!provider->initFromExistingContext(this, manager->m_providers[i]))
121 gss_eap_attr_ctx::initFromGssContext(const gss_cred_id_t cred,
122 const gss_ctx_id_t ctx)
124 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
125 gss_eap_attr_provider *provider;
127 provider = m_providers[i];
128 if (provider != NULL) {
129 if (!provider->initFromGssContext(this, cred, ctx))
137 gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
139 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++)
140 delete m_providers[i];
143 gss_eap_attr_provider *
144 gss_eap_attr_ctx::getProvider(unsigned int type) const
146 return m_providers[type];
149 gss_eap_attr_provider *
150 gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const
154 type = attributePrefixToType(prefix);
156 return m_providers[type];
160 gss_eap_attr_ctx::setAttribute(int complete,
161 const gss_buffer_t attr,
162 const gss_buffer_t value)
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->setAttribute(complete,
173 (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
180 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
182 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
184 gss_eap_attr_provider *provider;
186 decomposeAttributeName(attr, &type, &suffix);
188 provider = m_providers[type];
189 if (provider != NULL) {
190 provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
195 gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
200 for (i = 0; i < ATTR_TYPE_MAX; i++) {
201 gss_eap_attr_provider *provider;
203 provider = m_providers[i];
204 if (provider == NULL)
207 ret = provider->getAttributeTypes(cb, data);
215 struct eap_gss_get_attr_types_args {
217 gss_buffer_set_t attrs;
221 addAttribute(const gss_eap_attr_provider *provider,
222 const gss_buffer_t attribute,
225 eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
226 gss_buffer_t prefix = GSS_C_NO_BUFFER;
227 gss_buffer_desc qualified;
228 OM_uint32 major, minor;
230 if (args->type != ATTR_TYPE_LOCAL) {
231 gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified);
232 major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
233 gss_release_buffer(&minor, &qualified);
235 major = gss_add_buffer_set_member(&minor, prefix, &args->attrs);
238 return GSS_ERROR(major) ? false : true;
242 gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
244 eap_gss_get_attr_types_args args;
245 OM_uint32 major, minor;
249 major = gss_create_empty_buffer_set(&minor, attrs);
250 if (GSS_ERROR(major)) {
251 throw new std::bad_alloc;
257 for (i = 0; i < ATTR_TYPE_MAX; i++) {
258 gss_eap_attr_provider *provider;
262 provider = m_providers[i];
263 if (provider == NULL)
266 ret = provider->getAttributeTypes(addAttribute, (void *)&args);
272 gss_release_buffer_set(&minor, attrs);
279 gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
283 gss_buffer_t display_value,
286 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
288 gss_eap_attr_provider *provider;
291 decomposeAttributeName(attr, &type, &suffix);
293 provider = m_providers[type];
294 if (provider == NULL) {
299 ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
300 authenticated, complete,
301 value, display_value, more);
307 gss_eap_attr_ctx::mapToAny(int authenticated,
308 gss_buffer_t type_id) const
311 gss_eap_attr_provider *provider;
313 type = attributePrefixToType(type_id);
315 provider = m_providers[type];
317 return provider->mapToAny(authenticated, type_id);
321 gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
322 gss_any_t input) const
325 gss_eap_attr_provider *provider;
327 type = attributePrefixToType(type_id);
329 provider = m_providers[type];
331 provider->releaseAnyNameMapping(type_id, input);
335 gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
337 m_providers[ATTR_TYPE_RADIUS]->exportToBuffer(buffer);
341 gss_eap_attr_ctx::initFromBuffer(const gss_buffer_t buffer)
346 ret = m_providers[ATTR_TYPE_RADIUS]->initFromBuffer(this, buffer);
350 for (i = ATTR_TYPE_RADIUS + 1; i < ATTR_TYPE_MAX; i++) {
351 gss_eap_attr_provider *provider = m_providers[i];
353 ret = provider->initFromGssContext(this,
368 mapException(OM_uint32 *minor, std::exception &e)
371 return GSS_S_FAILURE;
375 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
382 for (i = 0; i < attribute->length; i++) {
383 if (((char *)attribute->value)[i] == ' ') {
384 p = (char *)attribute->value + i + 1;
389 prefix->value = attribute->value;
392 if (p != NULL && *p != '\0') {
393 suffix->length = attribute->length - 1 - prefix->length;
397 suffix->value = NULL;
402 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
403 const gss_buffer_t suffix)
407 if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
410 str.append((const char *)prefix->value, prefix->length);
412 if (suffix != GSS_C_NO_BUFFER) {
414 str.append((const char *)suffix->value, suffix->length);
421 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
422 const gss_buffer_t suffix)
424 const gss_buffer_t prefix = attributeTypeToPrefix(type);
426 return composeAttributeName(prefix, suffix);
430 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
431 const gss_buffer_t suffix,
432 gss_buffer_t attribute)
434 std::string str = composeAttributeName(prefix, suffix);
436 if (str.length() != 0) {
437 return duplicateBuffer(str, attribute);
439 attribute->length = 0;
440 attribute->value = NULL;
445 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
449 gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
451 decomposeAttributeName(attribute, &prefix, suffix);
452 *type = attributePrefixToType(&prefix);
456 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
457 const gss_buffer_t suffix,
458 gss_buffer_t attribute)
460 gss_buffer_t prefix = attributeTypeToPrefix(type);
462 return composeAttributeName(prefix, suffix, attribute);
466 gssEapInquireName(OM_uint32 *minor,
470 gss_buffer_set_t *attrs)
472 if (name->attrCtx == NULL)
473 return GSS_S_UNAVAILABLE;
476 if (!name->attrCtx->getAttributeTypes(attrs))
477 return GSS_S_UNAVAILABLE;
478 } catch (std::exception &e) {
479 return mapException(minor, e);
482 return GSS_S_COMPLETE;
486 gssEapGetNameAttribute(OM_uint32 *minor,
492 gss_buffer_t display_value,
503 if (display_value != NULL) {
504 display_value->length = 0;
505 display_value->value = NULL;
508 if (name->attrCtx == NULL)
509 return GSS_S_UNAVAILABLE;
512 if (!name->attrCtx->getAttribute(attr, authenticated, complete,
513 value, display_value, more))
514 return GSS_S_UNAVAILABLE;
515 } catch (std::exception &e) {
516 return mapException(minor, e);
519 return GSS_S_COMPLETE;
523 gssEapDeleteNameAttribute(OM_uint32 *minor,
527 if (name->attrCtx == NULL)
528 return GSS_S_UNAVAILABLE;
531 name->attrCtx->deleteAttribute(attr);
532 } catch (std::exception &ex) {
533 return mapException(minor, ex);
536 return GSS_S_COMPLETE;
540 gssEapSetNameAttribute(OM_uint32 *minor,
546 if (name->attrCtx == NULL)
547 return GSS_S_UNAVAILABLE;
550 name->attrCtx->setAttribute(complete, attr, value);
551 } catch (std::exception &ex) {
552 return mapException(minor, ex);
555 return GSS_S_COMPLETE;
559 gssEapExportAttrContext(OM_uint32 *minor,
563 if (name->attrCtx == NULL) {
565 buffer->value = NULL;
567 return GSS_S_COMPLETE;
571 name->attrCtx->exportToBuffer(buffer);
572 if (buffer->length == 0)
573 return GSS_S_FAILURE;
574 } catch (std::exception &e) {
575 return mapException(minor, e);
578 return GSS_S_COMPLETE;
582 gssEapImportAttrContext(OM_uint32 *minor,
586 gss_eap_attr_ctx *ctx = NULL;
588 assert(name->attrCtx == NULL);
590 if (buffer->length != 0) {
592 ctx = new gss_eap_attr_ctx();
594 if (!ctx->initFromBuffer(buffer)) {
596 return GSS_S_DEFECTIVE_TOKEN;
599 } catch (std::exception &e) {
601 return mapException(minor, e);
605 return GSS_S_COMPLETE;
609 gssEapDuplicateAttrContext(OM_uint32 *minor,
613 gss_eap_attr_ctx *ctx = NULL;
615 assert(out->attrCtx == NULL);
618 if (in->attrCtx != NULL) {
619 ctx = new gss_eap_attr_ctx();
620 if (!ctx->initFromExistingContext(in->attrCtx)) {
622 return GSS_S_FAILURE;
626 } catch (std::exception &e) {
628 return mapException(minor, e);
631 return GSS_S_COMPLETE;
635 gssEapMapNameToAny(OM_uint32 *minor,
638 gss_buffer_t type_id,
642 *output = name->attrCtx->mapToAny(authenticated, type_id);
643 } catch (std::exception &e) {
644 return mapException(minor, e);
647 return GSS_S_COMPLETE;
651 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
653 gss_buffer_t type_id,
656 if (name->attrCtx == NULL)
657 return GSS_S_UNAVAILABLE;
661 name->attrCtx->releaseAnyNameMapping(type_id, *input);
663 } catch (std::exception &e) {
664 return mapException(minor, e);
667 return GSS_S_COMPLETE;
671 gssEapReleaseAttrContext(OM_uint32 *minor,
674 if (name->attrCtx != NULL)
675 delete name->attrCtx;
677 return GSS_S_COMPLETE;
681 gssEapAttrProvidersInit(OM_uint32 *minor)
684 if (gss_eap_radius_attr_provider::init() &&
685 gss_eap_saml_assertion_provider::init() &&
686 gss_eap_saml_attr_provider::init() &&
687 gss_eap_shib_attr_provider::init())
688 return GSS_S_COMPLETE;
689 } catch (std::exception &e) {
690 return mapException(minor, e);
693 return GSS_S_FAILURE;
697 gssEapAttrProvidersFinalize(OM_uint32 *minor)
700 gss_eap_shib_attr_provider::finalize();
701 gss_eap_saml_attr_provider::finalize();
702 gss_eap_saml_assertion_provider::finalize();
703 gss_eap_radius_attr_provider::finalize();
704 } catch (std::exception &e) {
705 return mapException(minor, e);
708 return GSS_S_COMPLETE;
711 struct gss_eap_attr_ctx *
712 gssEapCreateAttrContext(gss_cred_id_t gssCred,
715 gss_eap_attr_ctx *ctx;
717 assert(gssCtx != GSS_C_NO_CONTEXT);
719 ctx = new gss_eap_attr_ctx();
720 if (!ctx->initFromGssContext(gssCred, gssCtx)) {