1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *	oid.c
24  *
25  *	Copyright (c) 1997, by Sun Microsystems, Inc.
26  *	All rights reserved.
27  *
28  */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <string.h>
33 #include "dh_gssapi.h"
34 
35 /*
36  * These are private mech_dh oid support routines.
37  */
38 
39 /* See if two oids have the same value */
40 int
41 __OID_equal(const gss_OID_desc * const oid1, const gss_OID_desc * const oid2)
42 {
43 	if (oid1->length != oid2->length)
44 		return (0);
45 	return (memcmp(oid1->elements, oid2->elements, oid1->length) == 0);
46 }
47 
48 
49 /* Count the number of elements in an oid. Return -1 on badly formed OID */
50 int
51 __OID_nel(const gss_OID_desc * const oid)
52 {
53 	int i;
54 	unsigned char *p = (unsigned char *)oid->elements;
55 	unsigned char *e = p + oid->length;
56 
57 	/* For each byte */
58 	for (i = 0; p < e; i++) {
59 		/* If the upper bit is set it is part of this element */
60 		while (*p & 0x80) {
61 			p++;
62 			if (p == e)
63 				return (-1);
64 		}
65 		p++;
66 	}
67 
68 	return (i);
69 }
70 
71 /* Copy an oid to an allocated gss_OID_desc */
72 OM_uint32
73 __OID_copy_desc(gss_OID dest, const gss_OID_desc * const source)
74 {
75 	dest->length = 0;
76 	/* Allocate the elements of the new OID */
77 	dest->elements = (void *)New(char, source->length);
78 	if (dest->elements == NULL)
79 		return (DH_NOMEM_FAILURE);
80 
81 	/* Set the length */
82 	dest->length = source->length;
83 
84 	/* And copy the elements */
85 	memcpy(dest->elements, source->elements, dest->length);
86 
87 	return (DH_SUCCESS);
88 }
89 
90 /* Copy an oid, allocating storage */
91 OM_uint32
92 __OID_copy(gss_OID *dest, const gss_OID_desc * const source)
93 {
94 	/* Allocate a new OID */
95 	gss_OID oid = New(gss_OID_desc, 1);
96 
97 	/* Clear the destination */
98 	*dest = NULL;
99 
100 	/* return failure if no memory for oid */
101 	if (oid == NULL)
102 		return (DH_NOMEM_FAILURE);
103 
104 	/* Copy the soure oid in to the new OID */
105 	if (__OID_copy_desc(oid, source) != DH_SUCCESS) {
106 		Free(oid);
107 		return (DH_NOMEM_FAILURE);
108 	}
109 
110 	/* Set the destination oid */
111 	*dest = oid;
112 	return (DH_SUCCESS);
113 }
114 
115 /* Check if an oid is a member of an oid set */
116 int
117 __OID_is_member(gss_OID_set set, const gss_OID_desc * const element)
118 {
119 	int i;
120 
121 	/* For each member in the set ... */
122 	for (i = 0; i < set->count; i++)
123 		if (__OID_equal(element, &set->elements[i]))
124 			return (TRUE);
125 
126 	return (FALSE);
127 }
128 
129 /* Copy oid set to a newly allocated set */
130 OM_uint32
131 __OID_copy_set(gss_OID_set *dest, gss_OID_set source)
132 {
133 	gss_OID_set set;
134 	int i;
135 
136 	/* Clear the destination */
137 	*dest = GSS_C_NO_OID_SET;
138 
139 	/* Allocate a new container for the set */
140 	set = New(gss_OID_set_desc, 1);
141 	if (set == NULL)
142 		return (DH_NOMEM_FAILURE);
143 
144 	/* Allocate storage for the elements of the set */
145 	set->elements = New(gss_OID_desc, source->count);
146 	if (set->elements == NULL) {
147 		Free(set);
148 		return (DH_NOMEM_FAILURE);
149 	}
150 	/* set the number of elements in the set */
151 	set->count = source->count;
152 
153 	/* Add each member of the source set to the new set */
154 	for (i = 0; i < source->count; i++)
155 		if (__OID_copy_desc(&set->elements[i], &source->elements[i])
156 		    != DH_SUCCESS)
157 			break;
158 
159 	/* Free partially allocated set on error */
160 	if (i != source->count) {
161 		for (; i >= 0; i--)
162 			Free(set->elements[i].elements);
163 		Free(set->elements);
164 		Free(set);
165 		return (DH_NOMEM_FAILURE);
166 	}
167 
168 	/* Set the destination to the set */
169 	*dest = set;
170 
171 	return (DH_SUCCESS);
172 }
173 
174 /*
175  * Form a gss_OID_set from an array of gss_OID_desc.
176  */
177 OM_uint32
178 __OID_copy_set_from_array(gss_OID_set *dest,
179     const gss_OID_desc *array[], size_t nel)
180 {
181 	gss_OID_set set;
182 	int i;
183 
184 	/* Clear the output set */
185 	*dest = GSS_C_NO_OID_SET;
186 
187 	/* Allocate the set */
188 	set = New(gss_OID_set_desc, 1);
189 	if (set == NULL)
190 		return (DH_NOMEM_FAILURE);
191 
192 	/* And space for the members */
193 	set->elements = New(gss_OID_desc, nel);
194 	if (set->elements == NULL) {
195 		Free(set);
196 		return (DH_NOMEM_FAILURE);
197 	}
198 	/* Set the set count */
199 	set->count = nel;
200 
201 	/* For each element in the array, addit to the set */
202 	for (i = 0; i < set->count; i++)
203 		if (__OID_copy_desc(&set->elements[i], array[i])
204 		    != DH_SUCCESS)
205 			break;
206 
207 	/* if we failed recover memory */
208 	if (i != set->count) {
209 		for (; i >= 0; i--)
210 			Free(set->elements[i].elements);
211 		Free(set->elements);
212 		Free(set);
213 		return (DH_NOMEM_FAILURE);
214 	}
215 
216 	/* Set the destination */
217 	*dest = set;
218 
219 	return (DH_SUCCESS);
220 }
221 
222 /*
223  * Given an oid create a GSS_OID_set with a copy of that oid as its
224  * sole member.
225  */
226 OM_uint32
227 __OID_to_OID_set(gss_OID_set *set, const gss_OID_desc * const oid)
228 {
229 	int rc;
230 	gss_OID_set s;
231 
232 	/* Nothing to do */
233 	if (set == NULL)
234 		return (DH_SUCCESS);
235 
236 	/* Allocate a set description */
237 	if ((s = New(gss_OID_set_desc, 1)) == NULL)
238 		return (DH_NOMEM_FAILURE);
239 
240 	/* Add the OID to the set */
241 	s->count = 1;
242 	if (rc = __OID_copy(&s->elements, oid)) {
243 		Free(s);
244 		return (rc);
245 	}
246 
247 	/* return the set */
248 	*set = s;
249 
250 	return (DH_SUCCESS);
251 }
252