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] = {
41 gss_eap_radius_attr_source::createAttrContext,
42 gss_eap_saml_assertion_source::createAttrContext,
43 gss_eap_saml_attr_source::createAttrContext,
44 gss_eap_shib_attr_source::createAttrContext
47 gss_eap_attr_ctx::gss_eap_attr_ctx(void)
49 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
50 gss_eap_attr_source *source;
52 source = (gss_eap_attr_factories[i])();
54 m_sources[i] = source;
59 gss_eap_attr_ctx::initFromExistingContext(const gss_eap_attr_ctx *manager,
60 const gss_eap_attr_source *source)
62 if (!gss_eap_attr_source::initFromExistingContext(this, source))
65 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
66 gss_eap_attr_source *source;
68 source = m_sources[i];
70 if (!source->initFromExistingContext(this, source))
79 gss_eap_attr_ctx::initFromGssContext(const gss_eap_attr_ctx *manager,
80 const gss_cred_id_t cred,
81 const gss_ctx_id_t ctx)
83 if (!gss_eap_attr_source::initFromGssContext(this, cred, ctx))
86 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
87 gss_eap_attr_source *source;
89 source = m_sources[i];
91 if (!source->initFromGssContext(this, cred, ctx))
99 gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
101 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++)
106 gss_eap_attr_ctx::init(void)
108 return gss_eap_radius_attr_source::init() &&
109 gss_eap_saml_assertion_source::init() &&
110 gss_eap_saml_attr_source::init() &&
111 gss_eap_shib_attr_source::init();
115 gss_eap_attr_ctx::finalize(void)
117 gss_eap_shib_attr_source::finalize();
118 gss_eap_saml_attr_source::finalize();
119 gss_eap_saml_assertion_source::finalize();
120 gss_eap_radius_attr_source::finalize();
123 gss_eap_attr_source *
124 gss_eap_attr_ctx::getProvider(unsigned int type) const
126 return m_sources[type];
129 gss_eap_attr_source *
130 gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const
134 type = attributePrefixToType(prefix);
136 return m_sources[type];
140 gss_eap_attr_ctx::setAttribute(int complete,
141 const gss_buffer_t attr,
142 const gss_buffer_t value)
144 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
146 gss_eap_attr_source *source;
148 decomposeAttributeName(attr, &type, &suffix);
150 source = m_sources[type];
151 if (source != NULL) {
152 source->setAttribute(complete,
153 (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
160 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
162 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
164 gss_eap_attr_source *source;
166 decomposeAttributeName(attr, &type, &suffix);
168 source = m_sources[type];
169 if (source != NULL) {
170 source->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
175 gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
180 for (i = 0; i < ATTR_TYPE_MAX; i++) {
181 gss_eap_attr_source *source;
183 source = m_sources[i];
187 ret = source->getAttributeTypes(cb, data);
195 struct eap_gss_get_attr_types_args {
197 gss_buffer_set_t attrs;
201 addAttribute(const gss_eap_attr_source *source,
202 const gss_buffer_t attribute,
205 eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
206 gss_buffer_t prefix = GSS_C_NO_BUFFER;
207 gss_buffer_desc qualified;
208 OM_uint32 major, minor;
210 if (args->type != ATTR_TYPE_LOCAL) {
211 gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified);
212 major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
213 gss_release_buffer(&minor, &qualified);
215 major = gss_add_buffer_set_member(&minor, prefix, &args->attrs);
218 return GSS_ERROR(major) ? false : true;
222 gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
224 eap_gss_get_attr_types_args args;
225 OM_uint32 major, minor;
229 major = gss_create_empty_buffer_set(&minor, attrs);
230 if (GSS_ERROR(major)) {
231 throw new std::bad_alloc;
237 for (i = 0; i < ATTR_TYPE_MAX; i++) {
238 gss_eap_attr_source *source;
242 source = m_sources[i];
246 ret = source->getAttributeTypes(addAttribute, (void *)&args);
252 gss_release_buffer_set(&minor, attrs);
259 gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
263 gss_buffer_t display_value,
266 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
268 gss_eap_attr_source *source;
271 decomposeAttributeName(attr, &type, &suffix);
273 source = m_sources[type];
274 if (source == NULL) {
279 ret = source->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
280 authenticated, complete,
281 value, display_value, more);
287 gss_eap_attr_ctx::mapToAny(int authenticated,
288 gss_buffer_t type_id) const
294 gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
295 gss_any_t input) const
300 gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
302 m_sources[ATTR_TYPE_RADIUS]->exportToBuffer(buffer);
306 gss_eap_attr_ctx::initFromBuffer(const gss_eap_attr_ctx *manager,
307 const gss_buffer_t buffer)
312 ret = m_sources[ATTR_TYPE_RADIUS]->initFromBuffer(this, buffer);
316 for (i = ATTR_TYPE_RADIUS + 1; i < ATTR_TYPE_MAX; i++) {
317 gss_eap_attr_source *source = m_sources[i];
319 ret = source->initFromGssContext(this,
335 mapException(OM_uint32 *minor, std::exception &e)
338 return GSS_S_FAILURE;
341 static gss_buffer_desc attributePrefixes[] = {
343 /* ATTR_TYPE_RADIUS_AVP */
344 sizeof("urn:ietf:params:gss-eap:radius-avp"),
345 (void *)"urn:ietf:params:gss-eap:radius-avp",
348 /* ATTR_TYPE_SAML_AAA_ASSERTION */
349 sizeof("urn:ietf:params:gss-eap:saml-aaa-assertion"),
350 (void *)"urn:ietf:params:gss-eap:saml-aaa-assertion"
353 /* ATTR_TYPE_SAML_ATTR */
354 sizeof("urn:ietf:params:gss-eap:saml-attr"),
355 (void *)"urn:ietf:params:gss-eap:saml-attr"
360 gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix)
364 for (i = ATTR_TYPE_MIN;
365 i < sizeof(attributePrefixes) / sizeof(attributePrefixes[0]);
368 if (bufferEqual(&attributePrefixes[i], prefix))
372 return ATTR_TYPE_LOCAL;
376 gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type)
378 if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_LOCAL)
379 return GSS_C_NO_BUFFER;
381 return &attributePrefixes[type];
385 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
392 for (i = 0; i < attribute->length; i++) {
393 if (((char *)attribute->value)[i] == ' ') {
394 p = (char *)attribute->value + i + 1;
399 prefix->value = attribute->value;
402 if (p != NULL && *p != '\0') {
403 suffix->length = attribute->length - 1 - prefix->length;
407 suffix->value = NULL;
412 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
413 const gss_buffer_t suffix)
417 if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
420 str.append((const char *)prefix->value, prefix->length);
422 if (suffix != GSS_C_NO_BUFFER) {
424 str.append((const char *)suffix->value, suffix->length);
431 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
432 const gss_buffer_t suffix)
434 const gss_buffer_t prefix = attributeTypeToPrefix(type);
436 return composeAttributeName(prefix, suffix);
440 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
441 const gss_buffer_t suffix,
442 gss_buffer_t attribute)
444 std::string str = composeAttributeName(prefix, suffix);
446 if (str.length() != 0) {
447 return duplicateBuffer(str, attribute);
449 attribute->length = 0;
450 attribute->value = NULL;
455 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
459 gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
461 decomposeAttributeName(attribute, &prefix, suffix);
462 *type = attributePrefixToType(&prefix);
466 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
467 const gss_buffer_t suffix,
468 gss_buffer_t attribute)
470 gss_buffer_t prefix = attributeTypeToPrefix(type);
472 return composeAttributeName(prefix, suffix, attribute);
476 gssEapInquireName(OM_uint32 *minor,
480 gss_buffer_set_t *attrs)
482 if (name->attrCtx == NULL)
483 return GSS_S_UNAVAILABLE;
486 if (!name->attrCtx->getAttributeTypes(attrs))
487 return GSS_S_UNAVAILABLE;
488 } catch (std::exception &e) {
489 return mapException(minor, e);
492 return GSS_S_COMPLETE;
496 gssEapGetNameAttribute(OM_uint32 *minor,
502 gss_buffer_t display_value,
511 if (display_value != NULL) {
512 display_value->length = 0;
513 display_value->value = NULL;
518 if (name->attrCtx == NULL)
519 return GSS_S_UNAVAILABLE;
522 if (!name->attrCtx->getAttribute(attr, authenticated, complete,
523 value, display_value, more))
524 return GSS_S_UNAVAILABLE;
525 } catch (std::exception &e) {
526 return mapException(minor, e);
529 return GSS_S_COMPLETE;
533 gssEapDeleteNameAttribute(OM_uint32 *minor,
537 if (name->attrCtx == NULL)
538 return GSS_S_UNAVAILABLE;
541 name->attrCtx->deleteAttribute(attr);
542 } catch (std::exception &ex) {
543 return mapException(minor, ex);
546 return GSS_S_COMPLETE;
550 gssEapSetNameAttribute(OM_uint32 *minor,
556 if (name->attrCtx == NULL)
557 return GSS_S_UNAVAILABLE;
560 name->attrCtx->setAttribute(complete, attr, value);
561 } catch (std::exception &ex) {
562 return mapException(minor, ex);
565 return GSS_S_COMPLETE;
569 gssEapExportAttrContext(OM_uint32 *minor,
573 if (name->attrCtx == NULL) {
575 buffer->value = NULL;
577 return GSS_S_COMPLETE;
581 name->attrCtx->exportToBuffer(buffer);
582 } catch (std::exception &e) {
583 return mapException(minor, e);
586 return GSS_S_COMPLETE;
590 gssEapImportAttrContext(OM_uint32 *minor,
594 gss_eap_attr_ctx *ctx = NULL;
596 assert(name->attrCtx == NULL);
598 if (buffer->length != 0) {
600 ctx = new gss_eap_attr_ctx;
602 if (!ctx->initFromBuffer(NULL, buffer)) {
604 return GSS_S_DEFECTIVE_TOKEN;
607 } catch (std::exception &e) {
609 return mapException(minor, e);
613 return GSS_S_COMPLETE;
617 gssEapDuplicateAttrContext(OM_uint32 *minor,
621 gss_eap_attr_ctx *ctx = NULL;
623 assert(out->attrCtx == NULL);
626 if (in->attrCtx != NULL) {
627 if (!ctx->initFromExistingContext(NULL, in->attrCtx)) {
629 return GSS_S_FAILURE;
633 } catch (std::exception &e) {
635 return mapException(minor, e);
638 return GSS_S_COMPLETE;
642 gssEapMapNameToAny(OM_uint32 *minor,
645 gss_buffer_t type_id,
649 *output = name->attrCtx->mapToAny(authenticated, type_id);
650 } catch (std::exception &e) {
651 return mapException(minor, e);
654 return GSS_S_COMPLETE;
658 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
660 gss_buffer_t type_id,
663 if (name->attrCtx == NULL)
664 return GSS_S_UNAVAILABLE;
668 name->attrCtx->releaseAnyNameMapping(type_id, *input);
670 } catch (std::exception &e) {
671 return mapException(minor, e);
674 return GSS_S_COMPLETE;
678 gssEapReleaseAttrContext(OM_uint32 *minor,
681 if (name->attrCtx != NULL)
682 delete name->attrCtx;
684 return GSS_S_COMPLETE;
688 gssEapAttrProvidersInit(OM_uint32 *minor)
691 gss_eap_attr_ctx::init();
692 } catch (std::exception &e) {
693 return mapException(minor, e);
696 return GSS_S_COMPLETE;
700 gssEapAttrProvidersFinalize(OM_uint32 *minor)
703 gss_eap_attr_ctx::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 ctx = new gss_eap_attr_ctx;
718 if (!ctx->initFromGssContext(NULL, gssCred, gssCtx)) {