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_cb
40 gss_eap_attr_factories[ATTR_TYPE_MAX] = {
41 gss_eap_radius_attr_provider::createAttrContext,
42 gss_eap_saml_assertion_provider::createAttrContext,
43 gss_eap_saml_attr_provider::createAttrContext,
44 gss_eap_shib_attr_provider::createAttrContext
48 gss_eap_attr_ctx::createAttrContext(gss_cred_id_t gssCred,
51 gss_eap_attr_ctx *ctx;
53 ctx = new gss_eap_attr_ctx(NULL, gssCred, gssCtx);
55 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
56 gss_eap_attr_provider *provider;
58 provider = (gss_eap_attr_factories[i])(ctx, gssCred, gssCtx);
60 ctx->m_providers[i] = provider;
66 gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
68 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++)
69 delete m_providers[i];
73 gss_eap_attr_ctx::init(void)
75 return gss_eap_radius_attr_provider::init() &&
76 gss_eap_saml_assertion_provider::init() &&
77 gss_eap_saml_attr_provider::init() &&
78 gss_eap_shib_attr_provider::init();
82 gss_eap_attr_ctx::finalize(void)
84 gss_eap_shib_attr_provider::finalize();
85 gss_eap_saml_attr_provider::finalize();
86 gss_eap_saml_assertion_provider::finalize();
87 gss_eap_radius_attr_provider::finalize();
90 gss_eap_attr_provider *
91 gss_eap_attr_ctx::getProvider(unsigned int type) const
93 return m_providers[type];
96 gss_eap_attr_provider *
97 gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const
101 type = attributePrefixToType(prefix);
103 return m_providers[type];
106 gss_eap_attr_ctx::gss_eap_attr_ctx(const gss_eap_attr_ctx &ctx)
107 : gss_eap_attr_provider(ctx)
109 for (unsigned int i = 0; i < ATTR_TYPE_MAX; i++) {
110 if (ctx.m_providers[i] != NULL) {
111 m_providers[i] = (gss_eap_attr_factories[i])(&ctx, GSS_C_NO_CREDENTIAL,
118 gss_eap_attr_ctx::setAttribute(int complete,
119 const gss_buffer_t attr,
120 const gss_buffer_t value)
122 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
124 gss_eap_attr_provider *provider;
126 decomposeAttributeName(attr, &type, &suffix);
128 provider = m_providers[type];
129 if (provider != NULL) {
130 provider->setAttribute(complete,
131 (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
138 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
140 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
142 gss_eap_attr_provider *provider;
144 decomposeAttributeName(attr, &type, &suffix);
146 provider = m_providers[type];
147 if (provider != NULL) {
148 provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
153 gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
158 for (i = 0; i < ATTR_TYPE_MAX; i++) {
159 gss_eap_attr_provider *provider;
161 provider = m_providers[i];
162 if (provider == NULL)
165 ret = provider->getAttributeTypes(cb, data);
173 struct eap_gss_get_attr_types_args {
175 gss_buffer_set_t attrs;
179 addAttribute(const gss_eap_attr_provider *provider,
180 const gss_buffer_t attribute,
183 eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
184 gss_buffer_t prefix = GSS_C_NO_BUFFER;
185 gss_buffer_desc qualified;
186 OM_uint32 major, minor;
188 if (args->type != ATTR_TYPE_LOCAL) {
189 gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified);
190 major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
191 gss_release_buffer(&minor, &qualified);
193 major = gss_add_buffer_set_member(&minor, prefix, &args->attrs);
196 return GSS_ERROR(major) ? false : true;
200 gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
202 eap_gss_get_attr_types_args args;
203 OM_uint32 major, minor;
207 major = gss_create_empty_buffer_set(&minor, attrs);
208 if (GSS_ERROR(major)) {
209 throw new std::bad_alloc;
215 for (i = 0; i < ATTR_TYPE_MAX; i++) {
216 gss_eap_attr_provider *provider;
220 provider = m_providers[i];
221 if (provider == NULL)
224 ret = provider->getAttributeTypes(addAttribute, (void *)&args);
230 gss_release_buffer_set(&minor, attrs);
237 gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
241 gss_buffer_t display_value,
244 gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
246 gss_eap_attr_provider *provider;
249 decomposeAttributeName(attr, &type, &suffix);
251 provider = m_providers[type];
252 if (provider == NULL) {
257 ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
258 authenticated, complete,
259 value, display_value, more);
265 gss_eap_attr_ctx::mapToAny(int authenticated,
266 gss_buffer_t type_id) const
272 gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
273 gss_any_t input) const
278 gss_eap_attr_ctx::marshall(gss_buffer_t buffer) const
287 mapException(OM_uint32 *minor, std::exception &e)
290 return GSS_S_FAILURE;
293 static gss_buffer_desc attributePrefixes[] = {
295 /* ATTR_TYPE_RADIUS_AVP */
296 sizeof("urn:ietf:params:gss-eap:radius-avp"),
297 (void *)"urn:ietf:params:gss-eap:radius-avp",
300 /* ATTR_TYPE_SAML_AAA_ASSERTION */
301 sizeof("urn:ietf:params:gss-eap:saml-aaa-assertion"),
302 (void *)"urn:ietf:params:gss-eap:saml-aaa-assertion"
305 /* ATTR_TYPE_SAML_ATTR */
306 sizeof("urn:ietf:params:gss-eap:saml-attr"),
307 (void *)"urn:ietf:params:gss-eap:saml-attr"
312 gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix)
316 for (i = ATTR_TYPE_MIN;
317 i < sizeof(attributePrefixes) / sizeof(attributePrefixes[0]);
320 if (bufferEqual(&attributePrefixes[i], prefix))
324 return ATTR_TYPE_LOCAL;
328 gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type)
330 if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_LOCAL)
331 return GSS_C_NO_BUFFER;
333 return &attributePrefixes[type];
337 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
344 for (i = 0; i < attribute->length; i++) {
345 if (((char *)attribute->value)[i] == ' ') {
346 p = (char *)attribute->value + i + 1;
351 prefix->value = attribute->value;
354 if (p != NULL && *p != '\0') {
355 suffix->length = attribute->length - 1 - prefix->length;
359 suffix->value = NULL;
364 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
365 const gss_buffer_t suffix,
366 gss_buffer_t attribute)
371 attribute->length = 0;
372 attribute->value = NULL;
374 if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
377 len = prefix->length;
378 if (suffix != GSS_C_NO_BUFFER) {
379 len += 1 + suffix->length;
382 attribute->value = GSSEAP_MALLOC(len + 1);
383 if (attribute->value == NULL) {
384 throw new std::bad_alloc;
386 attribute->length = len;
388 p = (char *)attribute->value;
389 memcpy(p, prefix->value, prefix->length);
390 if (suffix != NULL) {
391 p[prefix->length] = ' ';
392 memcpy(p + prefix->length + 1, suffix->value, suffix->length);
395 p[attribute->length] = '\0';
399 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
403 gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
405 decomposeAttributeName(attribute, &prefix, suffix);
406 *type = attributePrefixToType(&prefix);
410 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
411 const gss_buffer_t suffix,
412 gss_buffer_t attribute)
414 gss_buffer_t prefix = attributeTypeToPrefix(type);
416 composeAttributeName(prefix, suffix, attribute);
420 gssEapInquireName(OM_uint32 *minor,
424 gss_buffer_set_t *attrs)
428 *MN_mech = GSS_EAP_MECHANISM;
429 *attrs = GSS_C_NO_BUFFER_SET;
431 if (name->attrCtx == NULL)
432 return GSS_S_UNAVAILABLE;
435 if (!name->attrCtx->getAttributeTypes(attrs))
436 return GSS_S_UNAVAILABLE;
437 } catch (std::exception &e) {
438 return mapException(minor, e);
441 return GSS_S_COMPLETE;
445 gssEapGetNameAttribute(OM_uint32 *minor,
451 gss_buffer_t display_value,
460 if (display_value != NULL) {
461 display_value->length = 0;
462 display_value->value = NULL;
467 if (name->attrCtx == NULL)
468 return GSS_S_UNAVAILABLE;
471 if (!name->attrCtx->getAttribute(attr, authenticated, complete,
472 value, display_value, more))
473 return GSS_S_UNAVAILABLE;
474 } catch (std::exception &e) {
475 return mapException(minor, e);
478 return GSS_S_COMPLETE;
482 gssEapDeleteNameAttribute(OM_uint32 *minor,
486 if (name->attrCtx == NULL)
487 return GSS_S_UNAVAILABLE;
490 name->attrCtx->deleteAttribute(attr);
491 } catch (std::exception &ex) {
492 return mapException(minor, ex);
495 return GSS_S_COMPLETE;
499 gssEapSetNameAttribute(OM_uint32 *minor,
505 if (name->attrCtx == NULL)
506 return GSS_S_UNAVAILABLE;
509 name->attrCtx->setAttribute(complete, attr, value);
510 } catch (std::exception &ex) {
511 return mapException(minor, ex);
514 return GSS_S_COMPLETE;
518 gssEapExportAttrContext(OM_uint32 *minor,
522 if (name->attrCtx == NULL)
523 return GSS_S_UNAVAILABLE;
526 name->attrCtx->marshall(buffer);
527 } catch (std::exception &e) {
528 return mapException(minor, e);
531 return GSS_S_COMPLETE;
535 gssEapImportAttrContext(OM_uint32 *minor,
539 GSSEAP_NOT_IMPLEMENTED;
543 gssEapDuplicateAttrContext(OM_uint32 *minor,
548 if (in->attrCtx != NULL)
549 out->attrCtx = new gss_eap_attr_ctx(*(in->attrCtx));
552 } catch (std::exception &e) {
553 return mapException(minor, e);
556 return GSS_S_COMPLETE;
560 gssEapMapNameToAny(OM_uint32 *minor,
563 gss_buffer_t type_id,
567 *output = name->attrCtx->mapToAny(authenticated, type_id);
568 } catch (std::exception &e) {
569 return mapException(minor, e);
572 return GSS_S_COMPLETE;
576 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
578 gss_buffer_t type_id,
581 if (name->attrCtx == NULL)
582 return GSS_S_UNAVAILABLE;
586 name->attrCtx->releaseAnyNameMapping(type_id, *input);
588 } catch (std::exception &e) {
589 return mapException(minor, e);
592 return GSS_S_COMPLETE;
596 gssEapReleaseAttrContext(OM_uint32 *minor,
599 if (name->attrCtx != NULL)
600 delete name->attrCtx;
602 return GSS_S_COMPLETE;
606 gssEapAttrProvidersInit(OM_uint32 *minor)
609 gss_eap_attr_ctx::init();
610 } catch (std::exception &e) {
611 return mapException(minor, e);
614 return GSS_S_COMPLETE;
618 gssEapAttrProvidersFinalize(OM_uint32 *minor)
621 gss_eap_attr_ctx::finalize();
622 } catch (std::exception &e) {
623 return mapException(minor, e);
626 return GSS_S_COMPLETE;
629 struct gss_eap_attr_ctx *
630 gssEapCreateAttrContext(gss_cred_id_t cred,
633 assert(ctx != GSS_C_NO_CONTEXT);
634 return gss_eap_attr_ctx::createAttrContext(cred, ctx);