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