]> git.decadent.org.uk Git - nfs-utils.git/blob - support/gssapi/g_glue.c
release 1.0.7-pre2
[nfs-utils.git] / support / gssapi / g_glue.c
1 /* #ident       "@(#)g_glue.c 1.1     96/02/06 SMI" */
2
3 /*
4  * Copyright 1996 by Sun Microsystems, Inc.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software
7  * and its documentation for any purpose is hereby granted without fee,
8  * provided that the above copyright notice appears in all copies and
9  * that both that copyright notice and this permission notice appear in
10  * supporting documentation, and that the name of Sun Microsystems not be used
11  * in advertising or publicity pertaining to distribution of the software
12  * without specific, written prior permission. Sun Microsystems makes no
13  * representations about the suitability of this software for any
14  * purpose.  It is provided "as is" without express or implied warranty.
15  *
16  * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22  * PERFORMANCE OF THIS SOFTWARE.
23  */
24
25 #include "mglueP.h"
26 #include <stdio.h>
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30 #include <string.h>
31 #include <errno.h>
32
33 #define g_OID_equal(o1,o2) \
34    (((o1)->length == (o2)->length) && \
35     (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
36
37 extern gss_mechanism *__gss_mechs_array;
38
39 /*
40  * This file contains the support routines for the glue layer.
41  */
42
43 /*
44  *  given the mechs_array and a mechanism OID, return the
45  *  pointer to the mechanism, or NULL if that mechanism is
46  *  not supported.  If the requested OID is NULL, then return
47  *  the first mechanism.
48  */
49
50 gss_mechanism __gss_get_mechanism (type)
51      gss_OID type;
52 {
53     int i;
54
55     if (type == GSS_C_NULL_OID)
56         return (__gss_mechs_array[0]);
57
58     for (i=0; __gss_mechs_array[i]->mech_type.length != 0; i++) {
59         if ((__gss_mechs_array[i]->mech_type.length == type->length) &&
60             (memcmp (__gss_mechs_array[i]->mech_type.elements, type->elements,
61                      type->length) == 0)) {
62
63             return (__gss_mechs_array[i]);
64         }
65     }
66     return NULL;
67 }
68
69
70 /*
71  *  glue routine for get_mech_type
72  *
73  */
74
75 OM_uint32 __gss_get_mech_type(OID, token)
76     gss_OID             OID;
77     gss_buffer_t        token;
78 {
79     unsigned char * buffer_ptr;
80     int length;
81
82     /*
83      * This routine reads the prefix of "token" in order to determine
84      * its mechanism type. It assumes the encoding suggested in
85      * Appendix B of RFC 1508. This format starts out as follows :
86      *
87      * tag for APPLICATION 0, Sequence[constructed, definite length]
88      * length of remainder of token
89      * tag of OBJECT IDENTIFIER
90      * length of mechanism OID
91      * encoding of mechanism OID
92      * <the rest of the token>
93      *
94      * Numerically, this looks like :
95      *
96      * 0x60
97      * <length> - could be multiple bytes
98      * 0x06
99      * <length> - assume only one byte, hence OID length < 127
100      * <mech OID bytes>
101      *
102      * The routine fills in the OID value and returns an error as necessary.
103      */
104
105     if (token == NULL)
106         return (GSS_S_DEFECTIVE_TOKEN);
107
108     /* Skip past the APP/Sequnce byte and the token length */
109
110     buffer_ptr = (unsigned char *) token->value;
111
112     if (*(buffer_ptr++) != 0x60)
113         return (GSS_S_DEFECTIVE_TOKEN);
114     length = *buffer_ptr++;
115     if (length & 0x80) {
116         if ((length & 0x7f) > 4)
117             return (GSS_S_DEFECTIVE_TOKEN);
118         buffer_ptr += length & 0x7f;
119     }
120
121     if (*(buffer_ptr++) != 0x06)
122         return (GSS_S_DEFECTIVE_TOKEN);
123
124     OID->length = (OM_uint32) *(buffer_ptr++);
125     OID->elements = (void *) buffer_ptr;
126     return (GSS_S_COMPLETE);
127 }
128
129
130 /*
131  *  Internal routines to get and release an internal mechanism name
132  */
133
134 #include "mglueP.h"
135
136 OM_uint32 __gss_import_internal_name (minor_status, mech_type, union_name,
137                                 internal_name)
138 OM_uint32       *minor_status;
139 gss_OID         mech_type;
140 gss_union_name_t        union_name;
141 gss_name_t      *internal_name;
142 {
143     OM_uint32           status;
144     gss_mechanism       mech;
145
146     mech = __gss_get_mechanism (mech_type);
147     if (mech) {
148         if (mech->gss_import_name)
149             status = mech->gss_import_name (
150 #ifdef USE_MECH_CONTEXT
151                                             mech->context,
152 #endif
153                                             minor_status,
154                                             union_name->external_name,
155                                             union_name->name_type,
156                                             internal_name);
157         else
158             status = GSS_S_BAD_BINDINGS;
159
160         return (status);
161     }
162
163     return (GSS_S_BAD_MECH);
164 }
165
166 OM_uint32 __gss_display_internal_name (minor_status, mech_type, internal_name,
167                                  external_name, name_type)
168 OM_uint32       *minor_status;
169 gss_OID         mech_type;
170 gss_name_t      internal_name;
171 gss_buffer_t    external_name;
172 gss_OID         *name_type;
173 {
174     OM_uint32           status;
175     gss_mechanism       mech;
176
177     mech = __gss_get_mechanism (mech_type);
178     if (mech) {
179         if (mech->gss_display_name)
180             status = mech->gss_display_name (
181 #ifdef USE_MECH_CONTEXT
182                                              mech->context,
183 #endif
184                                              minor_status,
185                                              internal_name,
186                                              external_name,
187                                              name_type);
188         else
189             status = GSS_S_BAD_BINDINGS;
190
191         return (status);
192     }
193
194     return (GSS_S_BAD_MECH);
195 }
196
197 OM_uint32 __gss_release_internal_name (minor_status, mech_type, internal_name)
198 OM_uint32       *minor_status;
199 gss_OID         mech_type;
200 gss_name_t      *internal_name;
201 {
202     OM_uint32           status;
203     gss_mechanism       mech;
204
205     mech = __gss_get_mechanism (mech_type);
206     if (mech) {
207         if (mech->gss_release_name)
208             status = mech->gss_release_name (
209 #ifdef USE_MECH_CONTEXT
210                                              mech->context,
211 #endif
212                                              minor_status,
213                                              internal_name);
214         else
215             status = GSS_S_BAD_BINDINGS;
216
217         return (status);
218     }
219
220     return (GSS_S_BAD_MECH);
221 }
222
223
224 /*
225  * This function converts an internal gssapi name to a union gssapi
226  * name.  Note that internal_name should be considered "consumed" by
227  * this call, whether or not we return an error.
228  */
229 OM_uint32 __gss_convert_name_to_union_name(minor_status, mech,
230                                            internal_name, external_name)
231     OM_uint32 *minor_status;
232     gss_mechanism       mech;
233     gss_name_t  internal_name;
234     gss_name_t  *external_name;
235 {
236     OM_uint32 major_status,tmp;
237     gss_union_name_t union_name;
238
239     union_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc));
240     if (!union_name) {
241             *minor_status = ENOMEM;
242             goto allocation_failure;
243     }
244     union_name->mech_type = 0;
245     union_name->mech_name = internal_name;
246     union_name->name_type = 0;
247     union_name->external_name = 0;
248     union_name->gss_mech = mech;
249
250     major_status = generic_gss_copy_oid(minor_status, &mech->mech_type,
251                                         &union_name->mech_type);
252     if (major_status != GSS_S_COMPLETE)
253         goto allocation_failure;
254
255     union_name->external_name =
256         (gss_buffer_t) malloc(sizeof(gss_buffer_desc));
257     if (!union_name->external_name) {
258             *minor_status = ENOMEM;
259             goto allocation_failure;
260     }
261
262 #ifdef USE_MECH_CONTEXT
263     major_status = mech->gss_display_name(mech->context, minor_status,
264 #else
265     major_status = mech->gss_display_name(minor_status,
266 #endif
267                                           internal_name,
268                                           union_name->external_name,
269                                           &union_name->name_type);
270     if (major_status != GSS_S_COMPLETE)
271         goto allocation_failure;
272
273     *external_name =  union_name;
274     return (GSS_S_COMPLETE);
275
276 allocation_failure:
277     if (union_name) {
278         if (union_name->external_name) {
279             if (union_name->external_name->value)
280                 free(union_name->external_name->value);
281             free(union_name->external_name);
282         }
283         if (union_name->name_type)
284             generic_gss_release_oid(&tmp, &union_name->name_type);
285         if (union_name->mech_name)
286             __gss_release_internal_name(minor_status, union_name->mech_type,
287                                         &union_name->mech_name);
288         if (union_name->mech_type)
289             mech_gss_release_oid(&tmp, &union_name->mech_type, mech);
290         free(union_name);
291     }
292     return (major_status);
293 }
294
295 /*
296  * Glue routine for returning the mechanism-specific credential from a
297  * external union credential.
298  */
299 gss_cred_id_t
300 __gss_get_mechanism_cred(union_cred, mech_type)
301     gss_union_cred_t    union_cred;
302     gss_OID             mech_type;
303 {
304     int         i;
305
306     if (union_cred == GSS_C_NO_CREDENTIAL)
307         return GSS_C_NO_CREDENTIAL;
308
309     for (i=0; i < union_cred->count; i++) {
310         if (g_OID_equal(mech_type, &union_cred->mechs_array[i]))
311             return union_cred->cred_array[i];
312     }
313     return GSS_C_NO_CREDENTIAL;
314 }
315
316
317 /*
318  * Glue routine to copy an external name buffer (used by gss_duplicate_name)
319  */
320 OM_uint32 __gss_copy_namebuf(src, dest)
321     gss_buffer_t   src;
322     gss_buffer_t   *dest;
323 {
324     gss_buffer_t   temp = NULL;
325
326     if (dest == NULL)
327         return (GSS_S_BAD_NAME);
328
329     temp = (gss_buffer_t) malloc (sizeof(gss_buffer_t));
330     if (!temp) {
331         return(GSS_S_FAILURE);
332     }
333     temp->value = (void *) malloc (src->length + 1);
334     if (temp->value == NULL) {
335         free(temp);
336         return(GSS_S_FAILURE);
337     }
338
339     memcpy(temp->value, src->value, src->length);
340     temp->length = src->length;
341
342     *dest = temp;
343     return (GSS_S_COMPLETE);
344 }