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 #include <string.h>
31 #include "dh_gssapi.h"
32 
33 /*
34  * These are private mech_dh oid support routines.
35  */
36 
37 /* See if two oids have the same value */
38 int
__OID_equal(const gss_OID_desc * const oid1,const gss_OID_desc * const oid2)39 __OID_equal(const gss_OID_desc * const oid1, const gss_OID_desc * const oid2)
40 {
41 	if (oid1->length != oid2->length)
42 		return (0);
43 	return (memcmp(oid1->elements, oid2->elements, oid1->length) == 0);
44 }
45 
46 
47 /* Count the number of elements in an oid. Return -1 on badly formed OID */
48 int
__OID_nel(const gss_OID_desc * const oid)49 __OID_nel(const gss_OID_desc * const oid)
50 {
51 	int i;
52 	unsigned char *p = (unsigned char *)oid->elements;
53 	unsigned char *e = p + oid->length;
54 
55 	/* For each byte */
56 	for (i = 0; p < e; i++) {
57 		/* If the upper bit is set it is part of this element */
58 		while (*p & 0x80) {
59 			p++;
60 			if (p == e)
61 				return (-1);
62 		}
63 		p++;
64 	}
65 
66 	return (i);
67 }
68 
69 /* Copy an oid to an allocated gss_OID_desc */
70 OM_uint32
__OID_copy_desc(gss_OID dest,const gss_OID_desc * const source)71 __OID_copy_desc(gss_OID dest, const gss_OID_desc * const source)
72 {
73 	dest->length = 0;
74 	/* Allocate the elements of the new OID */
75 	dest->elements = (void *)New(char, source->length);
76 	if (dest->elements == NULL)
77 		return (DH_NOMEM_FAILURE);
78 
79 	/* Set the length */
80 	dest->length = source->length;
81 
82 	/* And copy the elements */
83 	memcpy(dest->elements, source->elements, dest->length);
84 
85 	return (DH_SUCCESS);
86 }
87 
88 /* Copy an oid, allocating storage */
89 OM_uint32
__OID_copy(gss_OID * dest,const gss_OID_desc * const source)90 __OID_copy(gss_OID *dest, const gss_OID_desc * const source)
91 {
92 	/* Allocate a new OID */
93 	gss_OID oid = New(gss_OID_desc, 1);
94 
95 	/* Clear the destination */
96 	*dest = NULL;
97 
98 	/* return failure if no memory for oid */
99 	if (oid == NULL)
100 		return (DH_NOMEM_FAILURE);
101 
102 	/* Copy the soure oid in to the new OID */
103 	if (__OID_copy_desc(oid, source) != DH_SUCCESS) {
104 		Free(oid);
105 		return (DH_NOMEM_FAILURE);
106 	}
107 
108 	/* Set the destination oid */
109 	*dest = oid;
110 	return (DH_SUCCESS);
111 }
112 
113 /* Check if an oid is a member of an oid set */
114 int
__OID_is_member(gss_OID_set set,const gss_OID_desc * const element)115 __OID_is_member(gss_OID_set set, const gss_OID_desc * const element)
116 {
117 	int i;
118 
119 	/* For each member in the set ... */
120 	for (i = 0; i < set->count; i++)
121 		if (__OID_equal(element, &set->elements[i]))
122 			return (TRUE);
123 
124 	return (FALSE);
125 }
126 
127 /* Copy oid set to a newly allocated set */
128 OM_uint32
__OID_copy_set(gss_OID_set * dest,gss_OID_set source)129 __OID_copy_set(gss_OID_set *dest, gss_OID_set source)
130 {
131 	gss_OID_set set;
132 	int i;
133 
134 	/* Clear the destination */
135 	*dest = GSS_C_NO_OID_SET;
136 
137 	/* Allocate a new container for the set */
138 	set = New(gss_OID_set_desc, 1);
139 	if (set == NULL)
140 		return (DH_NOMEM_FAILURE);
141 
142 	/* Allocate storage for the elements of the set */
143 	set->elements = New(gss_OID_desc, source->count);
144 	if (set->elements == NULL) {
145 		Free(set);
146 		return (DH_NOMEM_FAILURE);
147 	}
148 	/* set the number of elements in the set */
149 	set->count = source->count;
150 
151 	/* Add each member of the source set to the new set */
152 	for (i = 0; i < source->count; i++)
153 		if (__OID_copy_desc(&set->elements[i], &source->elements[i])
154 		    != DH_SUCCESS)
155 			break;
156 
157 	/* Free partially allocated set on error */
158 	if (i != source->count) {
159 		for (; i >= 0; i--)
160 			Free(set->elements[i].elements);
161 		Free(set->elements);
162 		Free(set);
163 		return (DH_NOMEM_FAILURE);
164 	}
165 
166 	/* Set the destination to the set */
167 	*dest = set;
168 
169 	return (DH_SUCCESS);
170 }
171 
172 /*
173  * Form a gss_OID_set from an array of gss_OID_desc.
174  */
175 OM_uint32
__OID_copy_set_from_array(gss_OID_set * dest,const gss_OID_desc * array[],size_t nel)176 __OID_copy_set_from_array(gss_OID_set *dest,
177     const gss_OID_desc *array[], size_t nel)
178 {
179 	gss_OID_set set;
180 	int i;
181 
182 	/* Clear the output set */
183 	*dest = GSS_C_NO_OID_SET;
184 
185 	/* Allocate the set */
186 	set = New(gss_OID_set_desc, 1);
187 	if (set == NULL)
188 		return (DH_NOMEM_FAILURE);
189 
190 	/* And space for the members */
191 	set->elements = New(gss_OID_desc, nel);
192 	if (set->elements == NULL) {
193 		Free(set);
194 		return (DH_NOMEM_FAILURE);
195 	}
196 	/* Set the set count */
197 	set->count = nel;
198 
199 	/* For each element in the array, addit to the set */
200 	for (i = 0; i < set->count; i++)
201 		if (__OID_copy_desc(&set->elements[i], array[i])
202 		    != DH_SUCCESS)
203 			break;
204 
205 	/* if we failed recover memory */
206 	if (i != set->count) {
207 		for (; i >= 0; i--)
208 			Free(set->elements[i].elements);
209 		Free(set->elements);
210 		Free(set);
211 		return (DH_NOMEM_FAILURE);
212 	}
213 
214 	/* Set the destination */
215 	*dest = set;
216 
217 	return (DH_SUCCESS);
218 }
219 
220 /*
221  * Given an oid create a GSS_OID_set with a copy of that oid as its
222  * sole member.
223  */
224 OM_uint32
__OID_to_OID_set(gss_OID_set * set,const gss_OID_desc * const oid)225 __OID_to_OID_set(gss_OID_set *set, const gss_OID_desc * const oid)
226 {
227 	int rc;
228 	gss_OID_set s;
229 
230 	/* Nothing to do */
231 	if (set == NULL)
232 		return (DH_SUCCESS);
233 
234 	/* Allocate a set description */
235 	if ((s = New(gss_OID_set_desc, 1)) == NULL)
236 		return (DH_NOMEM_FAILURE);
237 
238 	/* Add the OID to the set */
239 	s->count = 1;
240 	if (rc = __OID_copy(&s->elements, oid)) {
241 		Free(s);
242 		return (rc);
243 	}
244 
245 	/* return the set */
246 	*set = s;
247 
248 	return (DH_SUCCESS);
249 }
250