xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/mech/oid_ops.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2 
3 /*
4  * lib/gssapi/generic/oid_ops.c
5  *
6  * Copyright 1995 by the Massachusetts Institute of Technology.
7  * All Rights Reserved.
8  *
9  * Export of this software from the United States of America may
10  *   require a specific license from the United States Government.
11  *   It is the responsibility of any person or organization contemplating
12  *   export to obtain such a license before exporting.
13  *
14  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
15  * distribute this software and its documentation for any purpose and
16  * without fee is hereby granted, provided that the above copyright
17  * notice appear in all copies and that both that copyright notice and
18  * this permission notice appear in supporting documentation, and that
19  * the name of M.I.T. not be used in advertising or publicity pertaining
20  * to distribution of the software without specific, written prior
21  * permission.  Furthermore if you modify this software you must label
22  * your software as modified software and not distribute it in such a
23  * fashion that it might be confused with the original M.I.T. software.
24  * M.I.T. makes no representations about the suitability of
25  * this software for any purpose.  It is provided "as is" without express
26  * or implied warranty.
27  *
28  */
29 
30 /*
31  * oid_ops.c - GSS-API V2 interfaces to manipulate OIDs
32  */
33 
34 #include "mglueP.h"
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 #include <stdlib.h>
39 #include <string.h>
40 #include <stdio.h>
41 #include <gssapi_generic.h>
42 #include <errno.h>
43 #include <ctype.h>
44 
45 OM_uint32
46 generic_gss_release_oid(minor_status, oid)
47     OM_uint32	*minor_status;
48     gss_OID	*oid;
49 {
50     if (minor_status)
51 	*minor_status = 0;
52 
53     if (oid == NULL || *oid == GSS_C_NO_OID)
54 	return(GSS_S_COMPLETE);
55 
56     /*
57      * The V2 API says the following!
58      *
59      * gss_release_oid[()] will recognize any of the GSSAPI's own OID values,
60      * and will silently ignore attempts to free these OIDs; for other OIDs
61      * it will call the C free() routine for both the OID data and the
62      * descriptor.  This allows applications to freely mix their own heap-
63      * allocated OID values with OIDs returned by GSS-API.
64      */
65 
66     /*
67      * We use the official OID definitions instead of the unofficial OID
68      * defintions. But we continue to support the unofficial OID
69      * gss_nt_service_name just in case if some gss applications use
70      * the old OID.
71      */
72 
73     if ((*oid != GSS_C_NT_USER_NAME) &&
74 	(*oid != GSS_C_NT_MACHINE_UID_NAME) &&
75 	(*oid != GSS_C_NT_STRING_UID_NAME) &&
76 	(*oid != GSS_C_NT_HOSTBASED_SERVICE) &&
77 	(*oid != GSS_C_NT_ANONYMOUS) &&
78 	(*oid != GSS_C_NT_EXPORT_NAME) &&
79 	(*oid != gss_nt_service_name)) {
80 	free((*oid)->elements);
81 	free(*oid);
82     }
83     *oid = GSS_C_NO_OID;
84     return(GSS_S_COMPLETE);
85 }
86 
87 OM_uint32
88 generic_gss_copy_oid(minor_status, oid, new_oid)
89 	OM_uint32	*minor_status;
90 	gss_OID_desc * const oid;
91 	gss_OID		*new_oid;
92 {
93 	gss_OID		p;
94 
95 	*minor_status = 0;
96 
97 	p = (gss_OID) malloc(sizeof(gss_OID_desc));
98 	if (!p) {
99 		*minor_status = ENOMEM;
100 		return GSS_S_FAILURE;
101 	}
102 	p->length = oid->length;
103 	p->elements = malloc(p->length);
104 	if (!p->elements) {
105 		free(p);
106 		return GSS_S_FAILURE;
107 	}
108 	memcpy(p->elements, oid->elements, p->length);
109 	*new_oid = p;
110 	return(GSS_S_COMPLETE);
111 }
112 
113 
114 OM_uint32
115 generic_gss_create_empty_oid_set(minor_status, oid_set)
116     OM_uint32	*minor_status;
117     gss_OID_set	*oid_set;
118 {
119     *minor_status = 0;
120 
121     if ((*oid_set = (gss_OID_set) malloc(sizeof(gss_OID_set_desc)))) {
122 	memset(*oid_set, 0, sizeof(gss_OID_set_desc));
123 	return(GSS_S_COMPLETE);
124     }
125     else {
126 	*minor_status = ENOMEM;
127 	return(GSS_S_FAILURE);
128     }
129 }
130 
131 OM_uint32
132 generic_gss_add_oid_set_member(minor_status, member_oid, oid_set)
133     OM_uint32	*minor_status;
134     gss_OID_desc * const member_oid;
135     gss_OID_set	*oid_set;
136 {
137     gss_OID	elist;
138     gss_OID	lastel;
139 
140     *minor_status = 0;
141 
142     if (member_oid == NULL || member_oid->length == 0 ||
143 	member_oid->elements == NULL)
144 	return (GSS_S_CALL_INACCESSIBLE_READ);
145 
146     elist = (*oid_set)->elements;
147     /* Get an enlarged copy of the array */
148     if (((*oid_set)->elements = (gss_OID) malloc(((*oid_set)->count+1) *
149 						  sizeof(gss_OID_desc)))) {
150 	/* Copy in the old junk */
151 	if (elist)
152 	    memcpy((*oid_set)->elements,
153 		   elist,
154 		   ((*oid_set)->count * sizeof(gss_OID_desc)));
155 
156 	/* Duplicate the input element */
157 	lastel = &(*oid_set)->elements[(*oid_set)->count];
158 	if ((lastel->elements =
159 	     (void *) malloc((size_t) member_oid->length))) {
160 	    /* Success - copy elements */
161 	    memcpy(lastel->elements, member_oid->elements,
162 		   (size_t) member_oid->length);
163 	    /* Set length */
164 	    lastel->length = member_oid->length;
165 
166 	    /* Update count */
167 	    (*oid_set)->count++;
168 	    if (elist)
169 		free(elist);
170 	    *minor_status = 0;
171 	    return(GSS_S_COMPLETE);
172 	}
173 	else
174 	    free((*oid_set)->elements);
175     }
176     /* Failure - restore old contents of list */
177     (*oid_set)->elements = elist;
178     *minor_status = ENOMEM;
179     return(GSS_S_FAILURE);
180 }
181 
182 OM_uint32
183 generic_gss_test_oid_set_member(minor_status, member, set, present)
184     OM_uint32	*minor_status;
185     gss_OID_desc * const member;
186     gss_OID_set	set;
187     int		*present;
188 {
189     OM_uint32	i;
190     int		result;
191 
192     *minor_status = 0;
193 
194     if (member == NULL || set == NULL)
195 	return (GSS_S_CALL_INACCESSIBLE_READ);
196 
197     if (present == NULL)
198 	return (GSS_S_CALL_INACCESSIBLE_WRITE);
199 
200     result = 0;
201     for (i=0; i<set->count; i++) {
202 	if ((set->elements[i].length == member->length) &&
203 	    !memcmp(set->elements[i].elements,
204 		    member->elements,
205 		    (size_t) member->length)) {
206 	    result = 1;
207 	    break;
208 	}
209     }
210     *present = result;
211     return(GSS_S_COMPLETE);
212 }
213 
214 /*
215  * OID<->string routines.  These are uuuuugly.
216  */
217 OM_uint32
218 generic_gss_oid_to_str(minor_status, oid, oid_str)
219     OM_uint32		*minor_status;
220     gss_OID_desc * const oid;
221     gss_buffer_t	oid_str;
222 {
223     char		numstr[128];
224     OM_uint32		number;
225     int			numshift;
226     OM_uint32 string_length;
227     OM_uint32 i;
228     unsigned char	*cp;
229     char		*bp;
230 
231     if (minor_status != NULL)
232 	*minor_status = 0;
233 
234     if (oid_str != GSS_C_NO_BUFFER) {
235 	oid_str->length = 0;
236 	oid_str->value = NULL;
237     }
238 
239     if (oid == NULL || oid->length == 0 || oid->elements == NULL)
240 	return (GSS_S_CALL_INACCESSIBLE_READ);
241 
242     if (oid_str == GSS_C_NO_BUFFER)
243 	return (GSS_S_CALL_INACCESSIBLE_WRITE);
244 
245     /* Decoded according to krb5/gssapi_krb5.c */
246 
247     /* First determine the size of the string */
248     string_length = 0;
249     number = 0;
250     numshift = 0;
251     cp = (unsigned char *) oid->elements;
252     number = (unsigned long) cp[0];
253     snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number/40);
254     string_length += strlen(numstr);
255     snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number%40);
256     string_length += strlen(numstr);
257     for (i=1; i<oid->length; i++) {
258 	if ((OM_uint32) (numshift+7) < (sizeof (OM_uint32)*8)) {/* XXX */
259 	    number = (number << 7) | (cp[i] & 0x7f);
260 	    numshift += 7;
261 	}
262 	else {
263 	    return(GSS_S_FAILURE);
264 	}
265 	if ((cp[i] & 0x80) == 0) {
266 	    snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number);
267 	    string_length += strlen(numstr);
268 	    number = 0;
269 	    numshift = 0;
270 	}
271     }
272     /*
273      * If we get here, we've calculated the length of "n n n ... n ".  Add 4
274      * here for "{ " and "}\0".
275      */
276     string_length += 4;
277     if ((bp = (char *) malloc(string_length))) {
278 	strcpy(bp, "{ ");
279 	number = (OM_uint32) cp[0];
280 	snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number/40);
281 	strcat(bp, numstr);
282 	snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number%40);
283 	strcat(bp, numstr);
284 	number = 0;
285 	cp = (unsigned char *) oid->elements;
286 	for (i=1; i<oid->length; i++) {
287 	    number = (number << 7) | (cp[i] & 0x7f);
288 	    if ((cp[i] & 0x80) == 0) {
289 	        snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number);
290 		strcat(bp, numstr);
291 		number = 0;
292 	    }
293 	}
294 	strcat(bp, "}");
295 	oid_str->length = strlen(bp)+1;
296 	oid_str->value = (void *) bp;
297 	return(GSS_S_COMPLETE);
298     }
299     *minor_status = ENOMEM;
300     return(GSS_S_FAILURE);
301 }
302 
303 OM_uint32
304 generic_gss_str_to_oid(minor_status, oid_str, oid)
305     OM_uint32		*minor_status;
306     gss_buffer_t	oid_str;
307     gss_OID		*oid;
308 {
309     unsigned char	*cp, *bp, *startp;
310     int		brace;
311     long	numbuf;
312     long	onumbuf;
313     OM_uint32	nbytes;
314     int		index;
315     unsigned char *op;
316 
317     if (minor_status != NULL)
318 	*minor_status = 0;
319 
320     if (oid != NULL)
321 	*oid = GSS_C_NO_OID;
322 
323     if (GSS_EMPTY_BUFFER(oid_str))
324 	return (GSS_S_CALL_INACCESSIBLE_READ);
325 
326     if (oid == NULL)
327 	return (GSS_S_CALL_INACCESSIBLE_WRITE);
328 
329     brace = 0;
330     bp = oid_str->value;
331     cp = bp;
332     /* Skip over leading space */
333     while ((bp < &cp[oid_str->length]) && isspace(*bp))
334 	bp++;
335     if (*bp == '{') {
336 	brace = 1;
337 	bp++;
338     }
339     while ((bp < &cp[oid_str->length]) && isspace(*bp))
340 	bp++;
341     startp = bp;
342     nbytes = 0;
343 
344     /*
345      * The first two numbers are chewed up by the first octet.
346      */
347     if (sscanf((char *)bp, "%ld", &numbuf) != 1) {
348 	*minor_status = EINVAL;
349 	return(GSS_S_FAILURE);
350     }
351     while ((bp < &cp[oid_str->length]) && isdigit(*bp))
352 	bp++;
353     while ((bp < &cp[oid_str->length]) && isspace(*bp))
354 	bp++;
355     if (sscanf((char *)bp, "%ld", &numbuf) != 1) {
356 	*minor_status = EINVAL;
357 	return(GSS_S_FAILURE);
358     }
359     while ((bp < &cp[oid_str->length]) && isdigit(*bp))
360 	bp++;
361     while ((bp < &cp[oid_str->length]) &&
362 	   (isspace(*bp) || *bp == '.'))
363 	bp++;
364     nbytes++;
365     while (isdigit(*bp)) {
366 	if (sscanf((char *)bp, "%ld", &numbuf) != 1) {
367 	    return(GSS_S_FAILURE);
368 	}
369 	while (numbuf) {
370 	    nbytes++;
371 	    numbuf >>= 7;
372 	}
373 	while ((bp < &cp[oid_str->length]) && isdigit(*bp))
374 	    bp++;
375 	while ((bp < &cp[oid_str->length]) &&
376 	       (isspace(*bp) || *bp == '.'))
377 	    bp++;
378     }
379     if (brace && (*bp != '}')) {
380 	return(GSS_S_FAILURE);
381     }
382 
383     /*
384      * Phew!  We've come this far, so the syntax is good.
385      */
386     if ((*oid = (gss_OID) malloc(sizeof(gss_OID_desc)))) {
387 	if (((*oid)->elements = (void *) malloc(nbytes))) {
388 	    (*oid)->length = nbytes;
389 	    op = (unsigned char *) (*oid)->elements;
390 	    bp = startp;
391 	    (void) sscanf((char *)bp, "%ld", &numbuf);
392 	    while (isdigit(*bp))
393 		bp++;
394 	    while (isspace(*bp) || *bp == '.')
395 		bp++;
396 	    onumbuf = 40*numbuf;
397 	    (void) sscanf((char *)bp, "%ld", &numbuf);
398 	    onumbuf += numbuf;
399 	    *op = (unsigned char) onumbuf;
400 	    op++;
401 	    while (isdigit(*bp))
402 		bp++;
403 	    while (isspace(*bp) || *bp == '.')
404 		bp++;
405 	    while (isdigit(*bp)) {
406 		(void) sscanf((char *)bp, "%ld", &numbuf);
407 		nbytes = 0;
408 		/* Have to fill in the bytes msb-first */
409 		onumbuf = numbuf;
410 		while (numbuf) {
411 		    nbytes++;
412 		    numbuf >>= 7;
413 		}
414 		numbuf = onumbuf;
415 		op += nbytes;
416 		index = -1;
417 		while (numbuf) {
418 		    op[index] = (unsigned char) numbuf & 0x7f;
419 		    if (index != -1)
420 			op[index] |= 0x80;
421 		    index--;
422 		    numbuf >>= 7;
423 		}
424 		while (isdigit(*bp))
425 		    bp++;
426 		while (isspace(*bp) || *bp == '.')
427 		    bp++;
428 	    }
429 	    return(GSS_S_COMPLETE);
430 	}
431 	else {
432 	    free(*oid);
433 	    *oid = GSS_C_NO_OID;
434 	}
435     }
436     return(GSS_S_FAILURE);
437 }
438 
439 /*
440  * Copyright 1993 by OpenVision Technologies, Inc.
441  *
442  * Permission to use, copy, modify, distribute, and sell this software
443  * and its documentation for any purpose is hereby granted without fee,
444  * provided that the above copyright notice appears in all copies and
445  * that both that copyright notice and this permission notice appear in
446  * supporting documentation, and that the name of OpenVision not be used
447  * in advertising or publicity pertaining to distribution of the software
448  * without specific, written prior permission. OpenVision makes no
449  * representations about the suitability of this software for any
450  * purpose.  It is provided "as is" without express or implied warranty.
451  *
452  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
453  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
454  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
455  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
456  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
457  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
458  * PERFORMANCE OF THIS SOFTWARE.
459  */
460 OM_uint32
461 gssint_copy_oid_set(
462     OM_uint32 *minor_status,
463     const gss_OID_set_desc * const oidset,
464     gss_OID_set *new_oidset
465     )
466 {
467     gss_OID_set_desc *copy;
468     OM_uint32 minor = 0;
469     OM_uint32 major = GSS_S_COMPLETE;
470     OM_uint32 index;
471 
472     if (minor_status != NULL)
473 	*minor_status = 0;
474 
475     if (new_oidset != NULL)
476 	*new_oidset = GSS_C_NO_OID_SET;
477 
478     if (oidset == GSS_C_NO_OID_SET)
479 	return (GSS_S_CALL_INACCESSIBLE_READ);
480 
481     if (new_oidset == NULL)
482 	return (GSS_S_CALL_INACCESSIBLE_WRITE);
483 
484     if ((copy = (gss_OID_set_desc *) calloc(1, sizeof (*copy))) == NULL) {
485 	major = GSS_S_FAILURE;
486 	goto done;
487     }
488 
489     if ((copy->elements = (gss_OID_desc *)
490 	 calloc(oidset->count, sizeof (*copy->elements))) == NULL) {
491 	major = GSS_S_FAILURE;
492 	goto done;
493     }
494     copy->count = oidset->count;
495 
496     for (index = 0; index < copy->count; index++) {
497 	gss_OID_desc *out = &copy->elements[index];
498 	gss_OID_desc *in = &oidset->elements[index];
499 
500 	if ((out->elements = (void *) malloc(in->length)) == NULL) {
501 	    major = GSS_S_FAILURE;
502 	    goto done;
503 	}
504 	(void) memcpy(out->elements, in->elements, in->length);
505 	out->length = in->length;
506     }
507 
508     *new_oidset = copy;
509 done:
510     if (major != GSS_S_COMPLETE) {
511 	(void) gss_release_oid_set(&minor, &copy);
512     }
513 
514     return (major);
515 }
516