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