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