Merge branch 'fastreauth'
[mech_eap.orig] / util_attr.cpp
1 /*
2  * Copyright (c) 2010, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
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.
15  *
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.
19  *
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
30  * SUCH DAMAGE.
31  */
32
33 #include "gssapiP_eap.h"
34
35 #include <typeinfo>
36 #include <string>
37 #include <exception>
38 #include <new>
39
40 static gss_eap_attr_create_provider gssEapAttrFactories[ATTR_TYPE_MAX + 1];
41 static gss_buffer_desc gssEapAttrPrefixes[ATTR_TYPE_MAX + 1];
42
43 /*
44  * Register a provider for a particular type and prefix
45  */
46 void
47 gss_eap_attr_ctx::registerProvider(unsigned int type,
48                                    const char *prefix,
49                                    gss_eap_attr_create_provider factory)
50 {
51     assert(type <= ATTR_TYPE_MAX);
52
53     assert(gssEapAttrFactories[type] == NULL);
54
55     gssEapAttrFactories[type] = factory;
56     if (prefix != NULL) {
57         gssEapAttrPrefixes[type].value = (void *)prefix;
58         gssEapAttrPrefixes[type].length = strlen(prefix);
59     } else {
60         gssEapAttrPrefixes[type].value = NULL;
61         gssEapAttrPrefixes[type].length = 0;
62     }
63 }
64
65 /*
66  * Unregister a provider
67  */
68 void
69 gss_eap_attr_ctx::unregisterProvider(unsigned int type)
70 {
71     assert(type <= ATTR_TYPE_MAX);
72
73     gssEapAttrFactories[type] = NULL;
74     gssEapAttrPrefixes[type].value = NULL;
75     gssEapAttrPrefixes[type].length = 0;
76 }
77
78 /*
79  * Create an attribute context, that manages instances of providers
80  */
81 gss_eap_attr_ctx::gss_eap_attr_ctx(void)
82 {
83     m_flags = 0;
84
85     for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
86         gss_eap_attr_provider *provider;
87
88         if (gssEapAttrFactories[i] != NULL) {
89             provider = (gssEapAttrFactories[i])();
90         } else {
91             provider = NULL;
92         }
93
94         m_providers[i] = provider;
95     }
96 }
97
98 /*
99  * Convert an attribute prefix to a type
100  */
101 unsigned int
102 gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix)
103 {
104     unsigned int i;
105
106     for (i = ATTR_TYPE_MIN; i < ATTR_TYPE_MAX; i++) {
107         if (bufferEqual(&gssEapAttrPrefixes[i], prefix))
108             return i;
109     }
110
111     return ATTR_TYPE_LOCAL;
112 }
113
114 /*
115  * Convert a type to an attribute prefix
116  */
117 const gss_buffer_t
118 gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type)
119 {
120     if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_MAX)
121         return GSS_C_NO_BUFFER;
122
123     return &gssEapAttrPrefixes[type];
124 }
125
126 bool
127 gss_eap_attr_ctx::providerEnabled(unsigned int type) const
128 {
129     if (type == ATTR_TYPE_LOCAL &&
130         (m_flags & ATTR_FLAG_DISABLE_LOCAL))
131         return false;
132
133     if (m_providers[type] == NULL)
134         return false;
135
136     return true;
137 }
138
139 void
140 gss_eap_attr_ctx::releaseProvider(unsigned int type)
141 {
142     delete m_providers[type];
143     m_providers[type] = NULL;
144 }
145
146 /*
147  * Initialize a context from an existing context.
148  */
149 bool
150 gss_eap_attr_ctx::initFromExistingContext(const gss_eap_attr_ctx *manager)
151 {
152     bool ret = true;
153
154     m_flags = manager->m_flags;
155
156     for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
157         gss_eap_attr_provider *provider;
158
159         if (!providerEnabled(i)) {
160             releaseProvider(i);
161             continue;
162         }
163
164         provider = m_providers[i];
165
166         ret = provider->initFromExistingContext(this,
167                                                 manager->m_providers[i]);
168         if (ret == false) {
169             releaseProvider(i);
170             break;
171         }
172     }
173
174     return ret;
175 }
176
177 /*
178  * Initialize a context from a GSS credential and context.
179  */
180 bool
181 gss_eap_attr_ctx::initFromGssContext(const gss_cred_id_t cred,
182                                      const gss_ctx_id_t ctx)
183 {
184     bool ret = true;
185
186     if (cred != GSS_C_NO_CREDENTIAL &&
187         (cred->flags & GSS_EAP_DISABLE_LOCAL_ATTRS_FLAG)) {
188         m_flags |= ATTR_FLAG_DISABLE_LOCAL;
189     }
190
191     for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
192         gss_eap_attr_provider *provider;
193
194         if (!providerEnabled(i)) {
195             releaseProvider(i);
196             continue;
197         }
198
199         provider = m_providers[i];
200
201         ret = provider->initFromGssContext(this, cred, ctx);
202         if (ret == false) {
203             releaseProvider(i);
204             break;
205         }
206     }
207
208     return ret;
209 }
210
211 /*
212  * Initialize a context from an exported context or name token
213  */
214 bool
215 gss_eap_attr_ctx::initFromBuffer(const gss_buffer_t buffer)
216 {
217     bool ret;
218     gss_eap_attr_provider *primaryProvider = getPrimaryProvider();
219     gss_buffer_desc primaryBuf;
220
221     if (buffer->length < 4)
222         return false;
223
224     m_flags = load_uint32_be(buffer->value);
225
226     primaryBuf.length = buffer->length - 4;
227     primaryBuf.value = (char *)buffer->value + 4;
228
229     ret = primaryProvider->initFromBuffer(this, &primaryBuf);
230     if (ret == false)
231         return ret;
232
233     for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
234         gss_eap_attr_provider *provider;
235
236         if (!providerEnabled(i)) {
237             releaseProvider(i);
238             continue;
239         }
240
241         provider = m_providers[i];
242         if (provider == primaryProvider)
243             continue;
244
245         ret = provider->initFromGssContext(this,
246                                            GSS_C_NO_CREDENTIAL,
247                                            GSS_C_NO_CONTEXT);
248         if (ret == false) {
249             releaseProvider(i);
250             break;
251         }
252     }
253
254     return ret;
255 }
256
257 gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
258 {
259     for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++)
260         delete m_providers[i];
261 }
262
263 /*
264  * Locate provider for a given type
265  */
266 gss_eap_attr_provider *
267 gss_eap_attr_ctx::getProvider(unsigned int type) const
268 {
269     assert(type >= ATTR_TYPE_MIN && type <= ATTR_TYPE_MAX);
270     return m_providers[type];
271 }
272
273 /*
274  * Locate provider for a given prefix
275  */
276 gss_eap_attr_provider *
277 gss_eap_attr_ctx::getProvider(const gss_buffer_t prefix) const
278 {
279     unsigned int type;
280
281     type = attributePrefixToType(prefix);
282
283     return m_providers[type];
284 }
285
286 /*
287  * Get primary provider. Only the primary provider is serialised when
288  * gss_export_sec_context() or gss_export_name_composite() is called.
289  */
290 gss_eap_attr_provider *
291 gss_eap_attr_ctx::getPrimaryProvider(void) const
292 {
293     return m_providers[ATTR_TYPE_MIN];
294 }
295
296 /*
297  * Set an attribute
298  */
299 void
300 gss_eap_attr_ctx::setAttribute(int complete,
301                                const gss_buffer_t attr,
302                                const gss_buffer_t value)
303 {
304     gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
305     unsigned int type;
306     gss_eap_attr_provider *provider;
307
308     decomposeAttributeName(attr, &type, &suffix);
309
310     provider = m_providers[type];
311     if (provider != NULL) {
312         provider->setAttribute(complete,
313                                (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
314                                value);
315     } else {
316         /* XXX TODO throw exception */
317     }
318 }
319
320 /*
321  * Delete an attrbiute
322  */
323 void
324 gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
325 {
326     gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
327     unsigned int type;
328     gss_eap_attr_provider *provider;
329
330     decomposeAttributeName(attr, &type, &suffix);
331
332     provider = m_providers[type];
333     if (provider != NULL)
334         provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
335 }
336
337 /*
338  * Enumerate attribute types with callback
339  */
340 bool
341 gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
342 {
343     bool ret = false;
344     size_t i;
345
346     for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
347         gss_eap_attr_provider *provider = m_providers[i];
348
349         if (provider == NULL)
350             continue;
351
352         ret = provider->getAttributeTypes(cb, data);
353         if (ret == false)
354             break;
355     }
356
357     return ret;
358 }
359
360 struct eap_gss_get_attr_types_args {
361     unsigned int type;
362     gss_buffer_set_t attrs;
363 };
364
365 static bool
366 addAttribute(const gss_eap_attr_provider *provider,
367              const gss_buffer_t attribute,
368              void *data)
369 {
370     eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
371     gss_buffer_desc qualified;
372     OM_uint32 major, minor;
373
374     if (args->type != ATTR_TYPE_LOCAL) {
375         gss_eap_attr_ctx::composeAttributeName(args->type, attribute, &qualified);
376         major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
377         gss_release_buffer(&minor, &qualified);
378     } else {
379         major = gss_add_buffer_set_member(&minor, attribute, &args->attrs);
380     }
381
382     return GSS_ERROR(major) == false;
383 }
384
385 /*
386  * Enumerate attribute types, output is buffer set
387  */
388 bool
389 gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
390 {
391     eap_gss_get_attr_types_args args;
392     OM_uint32 major, minor;
393     bool ret = false;
394     unsigned int i;
395
396     major = gss_create_empty_buffer_set(&minor, attrs);
397     if (GSS_ERROR(major)) {
398         throw new std::bad_alloc;
399         return false;
400     }
401
402     args.attrs = *attrs;
403
404     for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
405         gss_eap_attr_provider *provider = m_providers[i];
406
407         args.type = i;
408
409         if (provider == NULL)
410             continue;
411
412         ret = provider->getAttributeTypes(addAttribute, (void *)&args);
413         if (ret == false)
414             break;
415     }
416
417     if (ret == false)
418         gss_release_buffer_set(&minor, attrs);
419
420     return ret;
421 }
422
423 /*
424  * Get attribute with given name
425  */
426 bool
427 gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
428                                int *authenticated,
429                                int *complete,
430                                gss_buffer_t value,
431                                gss_buffer_t display_value,
432                                int *more) const
433 {
434     gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
435     unsigned int type;
436     gss_eap_attr_provider *provider;
437     bool ret;
438
439     decomposeAttributeName(attr, &type, &suffix);
440
441     provider = m_providers[type];
442     if (provider == NULL)
443         return false;
444
445     ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
446                                  authenticated, complete,
447                                  value, display_value, more);
448
449     return ret;
450 }
451
452 /*
453  * Map attribute context to C++ object
454  */
455 gss_any_t
456 gss_eap_attr_ctx::mapToAny(int authenticated,
457                            gss_buffer_t type_id) const
458 {
459     unsigned int type;
460     gss_eap_attr_provider *provider;
461     gss_buffer_desc suffix;
462
463     decomposeAttributeName(type_id, &type, &suffix);
464
465     provider = m_providers[type];
466     if (provider == NULL)
467         return (gss_any_t)NULL;
468
469     return provider->mapToAny(authenticated, &suffix);
470 }
471
472 /*
473  * Release mapped context
474  */
475 void
476 gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
477                                         gss_any_t input) const
478 {
479     unsigned int type;
480     gss_eap_attr_provider *provider;
481     gss_buffer_desc suffix;
482
483     decomposeAttributeName(type_id, &type, &suffix);
484
485     provider = m_providers[type];
486     if (provider != NULL)
487         provider->releaseAnyNameMapping(&suffix, input);
488 }
489
490 /*
491  * Export attribute context to buffer
492  */
493 void
494 gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
495 {
496     const gss_eap_attr_provider *primaryProvider = getPrimaryProvider();
497     gss_buffer_desc tmp;
498     unsigned char *p;
499     OM_uint32 tmpMinor;
500
501     primaryProvider->exportToBuffer(&tmp);
502
503     buffer->length = 4 + tmp.length;
504     buffer->value = GSSEAP_MALLOC(buffer->length);
505     if (buffer->value == NULL)
506         throw new std::bad_alloc;
507
508     p = (unsigned char *)buffer->value;
509     store_uint32_be(m_flags, p);
510     memcpy(p + 4, tmp.value, tmp.length);
511
512     gss_release_buffer(&tmpMinor, &tmp);
513 }
514
515 /*
516  * Return soonest expiry time of providers
517  */
518 time_t
519 gss_eap_attr_ctx::getExpiryTime(void) const
520 {
521     unsigned int i;
522     time_t expiryTime = 0;
523
524     for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
525         gss_eap_attr_provider *provider = m_providers[i];
526         time_t providerExpiryTime;
527
528         if (provider == NULL)
529             continue;
530
531         providerExpiryTime = provider->getExpiryTime();
532         if (providerExpiryTime == 0)
533             continue;
534
535         if (expiryTime == 0 || providerExpiryTime < expiryTime)
536             expiryTime = providerExpiryTime;
537     }
538
539     return expiryTime;
540 }
541
542 /*
543  * Map C++ exception to GSS status
544  */
545 static OM_uint32
546 mapException(OM_uint32 *minor, std::exception &e)
547 {
548     OM_uint32 major = GSS_S_FAILURE;
549
550     /* XXX TODO implement other mappings */
551     if (typeid(e) == typeid(std::bad_alloc))
552         *minor = ENOMEM;
553     else
554         *minor = 0;
555
556 #ifdef GSSEAP_DEBUG
557     /* rethrow for now for debugging */
558     throw e;
559 #endif
560
561     return major;
562 }
563
564 /*
565  * Decompose attribute name into prefix and suffix
566  */
567 void
568 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
569                                          gss_buffer_t prefix,
570                                          gss_buffer_t suffix)
571 {
572     char *p = NULL;
573     size_t i;
574
575     for (i = 0; i < attribute->length; i++) {
576         if (((char *)attribute->value)[i] == ' ') {
577             p = (char *)attribute->value + i + 1;
578             break;
579         }
580     }
581
582     prefix->value = attribute->value;
583     prefix->length = i;
584
585     if (p != NULL && *p != '\0')  {
586         suffix->length = attribute->length - 1 - prefix->length;
587         suffix->value = p;
588     } else {
589         suffix->length = 0;
590         suffix->value = NULL;
591     }
592 }
593
594 /*
595  * Decompose attribute name into type and suffix
596  */
597 void
598 gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
599                                          unsigned int *type,
600                                          gss_buffer_t suffix)
601 {
602     gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
603
604     decomposeAttributeName(attribute, &prefix, suffix);
605     *type = attributePrefixToType(&prefix);
606 }
607
608 /*
609  * Compose attribute name from prefix, suffix; returns C++ string
610  */
611 std::string
612 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
613                                        const gss_buffer_t suffix)
614 {
615     std::string str;
616
617     if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
618         return str;
619
620     str.append((const char *)prefix->value, prefix->length);
621
622     if (suffix != GSS_C_NO_BUFFER) {
623         str.append(" ");
624         str.append((const char *)suffix->value, suffix->length);
625     }
626
627     return str;
628 }
629
630 /*
631  * Compose attribute name from type, suffix; returns C++ string
632  */
633 std::string
634 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
635                                        const gss_buffer_t suffix)
636 {
637     const gss_buffer_t prefix = attributeTypeToPrefix(type);
638
639     return composeAttributeName(prefix, suffix);
640 }
641
642 /*
643  * Compose attribute name from prefix, suffix; returns GSS buffer
644  */
645 void
646 gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
647                                        const gss_buffer_t suffix,
648                                        gss_buffer_t attribute)
649 {
650     std::string str = composeAttributeName(prefix, suffix);
651
652     if (str.length() != 0) {
653         return duplicateBuffer(str, attribute);
654     } else {
655         attribute->length = 0;
656         attribute->value = NULL;
657     }
658 }
659
660 /*
661  * Compose attribute name from type, suffix; returns GSS buffer
662  */
663 void
664 gss_eap_attr_ctx::composeAttributeName(unsigned int type,
665                                        const gss_buffer_t suffix,
666                                        gss_buffer_t attribute)
667 {
668     gss_buffer_t prefix = attributeTypeToPrefix(type);
669
670     return composeAttributeName(prefix, suffix, attribute);
671 }
672
673 /*
674  * C wrappers
675  */
676 OM_uint32
677 gssEapInquireName(OM_uint32 *minor,
678                   gss_name_t name,
679                   int *name_is_MN,
680                   gss_OID *MN_mech,
681                   gss_buffer_set_t *attrs)
682 {
683     if (name->attrCtx == NULL)
684         return GSS_S_UNAVAILABLE;
685
686     try {
687         if (!name->attrCtx->getAttributeTypes(attrs))
688             return GSS_S_UNAVAILABLE;
689     } catch (std::exception &e) {
690         return mapException(minor, e);
691     }
692
693     return GSS_S_COMPLETE;
694 }
695
696 OM_uint32
697 gssEapGetNameAttribute(OM_uint32 *minor,
698                        gss_name_t name,
699                        gss_buffer_t attr,
700                        int *authenticated,
701                        int *complete,
702                        gss_buffer_t value,
703                        gss_buffer_t display_value,
704                        int *more)
705 {
706     *authenticated = 0;
707     *complete = 0;
708
709     if (value != NULL) {
710         value->length = 0;
711         value->value = NULL;
712     }
713
714     if (display_value != NULL) {
715         display_value->length = 0;
716         display_value->value = NULL;
717     }
718
719     if (name->attrCtx == NULL)
720         return GSS_S_UNAVAILABLE;
721
722     try {
723         if (!name->attrCtx->getAttribute(attr, authenticated, complete,
724                                          value, display_value, more))
725             return GSS_S_UNAVAILABLE;
726     } catch (std::exception &e) {
727         return mapException(minor, e);
728     }
729
730     return GSS_S_COMPLETE;
731 }
732
733 OM_uint32
734 gssEapDeleteNameAttribute(OM_uint32 *minor,
735                           gss_name_t name,
736                           gss_buffer_t attr)
737 {
738     if (name->attrCtx == NULL)
739         return GSS_S_UNAVAILABLE;
740
741     try {
742         name->attrCtx->deleteAttribute(attr);
743     } catch (std::exception &ex) {
744         return mapException(minor, ex);
745     }
746
747     return GSS_S_COMPLETE;
748 }
749
750 OM_uint32
751 gssEapSetNameAttribute(OM_uint32 *minor,
752                        gss_name_t name,
753                        int complete,
754                        gss_buffer_t attr,
755                        gss_buffer_t value)
756 {
757     if (name->attrCtx == NULL)
758         return GSS_S_UNAVAILABLE;
759
760     try {
761         name->attrCtx->setAttribute(complete, attr, value);
762     } catch (std::exception &ex) {
763         return mapException(minor, ex);
764     }
765
766     return GSS_S_COMPLETE;
767 }
768
769 OM_uint32
770 gssEapExportAttrContext(OM_uint32 *minor,
771                         gss_name_t name,
772                         gss_buffer_t buffer)
773 {
774     if (name->attrCtx == NULL) {
775         buffer->length = 0;
776         buffer->value = NULL;
777
778         return GSS_S_COMPLETE;
779     }
780
781     try {
782         name->attrCtx->exportToBuffer(buffer);
783     } catch (std::exception &e) {
784         return mapException(minor, e);
785     }
786
787     return GSS_S_COMPLETE;
788 }
789
790 OM_uint32
791 gssEapImportAttrContext(OM_uint32 *minor,
792                         gss_buffer_t buffer,
793                         gss_name_t name)
794 {
795     gss_eap_attr_ctx *ctx = NULL;
796
797     assert(name->attrCtx == NULL);
798
799     if (buffer->length != 0) {
800         try {
801             ctx = new gss_eap_attr_ctx();
802
803             if (!ctx->initFromBuffer(buffer)) {
804                 delete ctx;
805                 return GSS_S_DEFECTIVE_TOKEN;
806             }
807             name->attrCtx = ctx;
808         } catch (std::exception &e) {
809             delete ctx;
810             return mapException(minor, e);
811         }
812     }
813
814     return GSS_S_COMPLETE;
815 }
816
817 OM_uint32
818 gssEapDuplicateAttrContext(OM_uint32 *minor,
819                            gss_name_t in,
820                            gss_name_t out)
821 {
822     gss_eap_attr_ctx *ctx = NULL;
823
824     assert(out->attrCtx == NULL);
825
826     try {
827         if (in->attrCtx != NULL) {
828             ctx = new gss_eap_attr_ctx();
829             if (!ctx->initFromExistingContext(in->attrCtx)) {
830                 delete ctx;
831                 return GSS_S_FAILURE;
832             }
833             out->attrCtx = ctx;
834         }
835     } catch (std::exception &e) {
836         delete ctx;
837         return mapException(minor, e);
838     }
839
840     return GSS_S_COMPLETE;
841 }
842
843 OM_uint32
844 gssEapMapNameToAny(OM_uint32 *minor,
845                    gss_name_t name,
846                    int authenticated,
847                    gss_buffer_t type_id,
848                    gss_any_t *output)
849 {
850     if (name->attrCtx == NULL)
851         return GSS_S_UNAVAILABLE;
852
853     try {
854         *output = name->attrCtx->mapToAny(authenticated, type_id);
855     } catch (std::exception &e) {
856         return mapException(minor, e);
857     }
858
859     return GSS_S_COMPLETE;
860 }
861
862 OM_uint32
863 gssEapReleaseAnyNameMapping(OM_uint32 *minor,
864                             gss_name_t name,
865                             gss_buffer_t type_id,
866                             gss_any_t *input)
867 {
868     if (name->attrCtx == NULL)
869         return GSS_S_UNAVAILABLE;
870
871     try {
872         if (*input != NULL)
873             name->attrCtx->releaseAnyNameMapping(type_id, *input);
874         *input = NULL;
875     } catch (std::exception &e) {
876         return mapException(minor, e);
877     }
878
879     return GSS_S_COMPLETE;
880 }
881
882 OM_uint32
883 gssEapReleaseAttrContext(OM_uint32 *minor,
884                          gss_name_t name)
885 {
886     if (name->attrCtx != NULL)
887         delete name->attrCtx;
888
889     return GSS_S_COMPLETE;
890 }
891
892 /*
893  * Public accessor for initialisng a context from a GSS context. Also
894  * sets expiry time on GSS context as a side-effect.
895  */
896 struct gss_eap_attr_ctx *
897 gssEapCreateAttrContext(gss_cred_id_t gssCred,
898                         gss_ctx_id_t gssCtx)
899 {
900     gss_eap_attr_ctx *ctx;
901
902     assert(gssCtx != GSS_C_NO_CONTEXT);
903
904     ctx = new gss_eap_attr_ctx();
905     if (!ctx->initFromGssContext(gssCred, gssCtx)) {
906         delete ctx;
907         return NULL;
908     }
909
910     gssCtx->expiryTime = ctx->getExpiryTime();
911
912     return ctx;
913 }