import less(1)
[unleashed/tickless.git] / usr / src / lib / gss_mechs / mech_krb5 / mech / oid_ops.c
blob7e925ea16d1f1879e1f335e2876aca5e5c8ac8eb
1 /*
2 * lib/gssapi/generic/oid_ops.c
4 * Copyright 1995 by the Massachusetts Institute of Technology.
5 * All Rights Reserved.
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.
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.
29 * oid_ops.c - GSS-API V2 interfaces to manipulate OIDs
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>
43 OM_uint32
44 generic_gss_release_oid(minor_status, oid)
45 OM_uint32 *minor_status;
46 gss_OID *oid;
48 if (minor_status)
49 *minor_status = 0;
51 if (oid == NULL || *oid == GSS_C_NO_OID)
52 return(GSS_S_COMPLETE);
55 * The V2 API says the following!
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.
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.
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);
81 *oid = GSS_C_NO_OID;
82 return(GSS_S_COMPLETE);
85 OM_uint32
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;
91 gss_OID p;
93 *minor_status = 0;
95 p = (gss_OID) malloc(sizeof(gss_OID_desc));
96 if (!p) {
97 *minor_status = ENOMEM;
98 return GSS_S_FAILURE;
100 p->length = oid->length;
101 p->elements = malloc(p->length);
102 if (!p->elements) {
103 free(p);
104 return GSS_S_FAILURE;
106 memcpy(p->elements, oid->elements, p->length);
107 *new_oid = p;
108 return(GSS_S_COMPLETE);
112 OM_uint32
113 generic_gss_create_empty_oid_set(minor_status, oid_set)
114 OM_uint32 *minor_status;
115 gss_OID_set *oid_set;
117 *minor_status = 0;
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);
123 else {
124 *minor_status = ENOMEM;
125 return(GSS_S_FAILURE);
129 OM_uint32
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;
135 gss_OID elist;
136 gss_OID lastel;
138 *minor_status = 0;
140 if (member_oid == NULL || member_oid->length == 0 ||
141 member_oid->elements == NULL)
142 return (GSS_S_CALL_INACCESSIBLE_READ);
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)));
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;
164 /* Update count */
165 (*oid_set)->count++;
166 free(elist);
167 *minor_status = 0;
168 return(GSS_S_COMPLETE);
170 else
171 free((*oid_set)->elements);
173 /* Failure - restore old contents of list */
174 (*oid_set)->elements = elist;
175 *minor_status = ENOMEM;
176 return(GSS_S_FAILURE);
179 OM_uint32
180 generic_gss_test_oid_set_member(minor_status, member, set, present)
181 OM_uint32 *minor_status;
182 gss_OID_desc * const member;
183 gss_OID_set set;
184 int *present;
186 OM_uint32 i;
187 int result;
189 *minor_status = 0;
191 if (member == NULL || set == NULL)
192 return (GSS_S_CALL_INACCESSIBLE_READ);
194 if (present == NULL)
195 return (GSS_S_CALL_INACCESSIBLE_WRITE);
197 result = 0;
198 for (i=0; i<set->count; i++) {
199 if ((set->elements[i].length == member->length) &&
200 !memcmp(set->elements[i].elements,
201 member->elements,
202 (size_t) member->length)) {
203 result = 1;
204 break;
207 *present = result;
208 return(GSS_S_COMPLETE);
212 * OID<->string routines. These are uuuuugly.
214 OM_uint32
215 generic_gss_oid_to_str(minor_status, oid, oid_str)
216 OM_uint32 *minor_status;
217 gss_OID_desc * const oid;
218 gss_buffer_t oid_str;
220 char numstr[128];
221 OM_uint32 number;
222 int numshift;
223 OM_uint32 string_length;
224 OM_uint32 i;
225 unsigned char *cp;
226 char *bp;
228 if (minor_status != NULL)
229 *minor_status = 0;
231 if (oid_str != GSS_C_NO_BUFFER) {
232 oid_str->length = 0;
233 oid_str->value = NULL;
236 if (oid == NULL || oid->length == 0 || oid->elements == NULL)
237 return (GSS_S_CALL_INACCESSIBLE_READ);
239 if (oid_str == GSS_C_NO_BUFFER)
240 return (GSS_S_CALL_INACCESSIBLE_WRITE);
242 /* Decoded according to krb5/gssapi_krb5.c */
244 /* First determine the size of the string */
245 string_length = 0;
246 number = 0;
247 numshift = 0;
248 cp = (unsigned char *) oid->elements;
249 number = (unsigned long) cp[0];
250 snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number/40);
251 string_length += strlen(numstr);
252 snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number%40);
253 string_length += strlen(numstr);
254 for (i=1; i<oid->length; i++) {
255 if ((OM_uint32) (numshift+7) < (sizeof (OM_uint32)*8)) {/* XXX */
256 number = (number << 7) | (cp[i] & 0x7f);
257 numshift += 7;
259 else {
260 return(GSS_S_FAILURE);
262 if ((cp[i] & 0x80) == 0) {
263 snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number);
264 string_length += strlen(numstr);
265 number = 0;
266 numshift = 0;
270 * If we get here, we've calculated the length of "n n n ... n ". Add 4
271 * here for "{ " and "}\0".
273 string_length += 4;
274 if ((bp = (char *) malloc(string_length))) {
275 strcpy(bp, "{ ");
276 number = (OM_uint32) cp[0];
277 snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number/40);
278 strcat(bp, numstr);
279 snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number%40);
280 strcat(bp, numstr);
281 number = 0;
282 cp = (unsigned char *) oid->elements;
283 for (i=1; i<oid->length; i++) {
284 number = (number << 7) | (cp[i] & 0x7f);
285 if ((cp[i] & 0x80) == 0) {
286 snprintf(numstr, sizeof(numstr), "%lu ", (unsigned long)number);
287 strcat(bp, numstr);
288 number = 0;
291 strcat(bp, "}");
292 oid_str->length = strlen(bp)+1;
293 oid_str->value = (void *) bp;
294 return(GSS_S_COMPLETE);
296 *minor_status = ENOMEM;
297 return(GSS_S_FAILURE);
300 OM_uint32
301 generic_gss_str_to_oid(minor_status, oid_str, oid)
302 OM_uint32 *minor_status;
303 gss_buffer_t oid_str;
304 gss_OID *oid;
306 unsigned char *cp, *bp, *startp;
307 int brace;
308 long numbuf;
309 long onumbuf;
310 OM_uint32 nbytes;
311 int index;
312 unsigned char *op;
314 if (minor_status != NULL)
315 *minor_status = 0;
317 if (oid != NULL)
318 *oid = GSS_C_NO_OID;
320 if (GSS_EMPTY_BUFFER(oid_str))
321 return (GSS_S_CALL_INACCESSIBLE_READ);
323 if (oid == NULL)
324 return (GSS_S_CALL_INACCESSIBLE_WRITE);
326 brace = 0;
327 bp = oid_str->value;
328 cp = bp;
329 /* Skip over leading space */
330 while ((bp < &cp[oid_str->length]) && isspace(*bp))
331 bp++;
332 if (*bp == '{') {
333 brace = 1;
334 bp++;
336 while ((bp < &cp[oid_str->length]) && isspace(*bp))
337 bp++;
338 startp = bp;
339 nbytes = 0;
342 * The first two numbers are chewed up by the first octet.
344 if (sscanf((char *)bp, "%ld", &numbuf) != 1) {
345 *minor_status = EINVAL;
346 return(GSS_S_FAILURE);
348 while ((bp < &cp[oid_str->length]) && isdigit(*bp))
349 bp++;
350 while ((bp < &cp[oid_str->length]) && isspace(*bp))
351 bp++;
352 if (sscanf((char *)bp, "%ld", &numbuf) != 1) {
353 *minor_status = EINVAL;
354 return(GSS_S_FAILURE);
356 while ((bp < &cp[oid_str->length]) && isdigit(*bp))
357 bp++;
358 while ((bp < &cp[oid_str->length]) &&
359 (isspace(*bp) || *bp == '.'))
360 bp++;
361 nbytes++;
362 while (isdigit(*bp)) {
363 if (sscanf((char *)bp, "%ld", &numbuf) != 1) {
364 return(GSS_S_FAILURE);
366 while (numbuf) {
367 nbytes++;
368 numbuf >>= 7;
370 while ((bp < &cp[oid_str->length]) && isdigit(*bp))
371 bp++;
372 while ((bp < &cp[oid_str->length]) &&
373 (isspace(*bp) || *bp == '.'))
374 bp++;
376 if (brace && (*bp != '}')) {
377 return(GSS_S_FAILURE);
381 * Phew! We've come this far, so the syntax is good.
383 if ((*oid = (gss_OID) malloc(sizeof(gss_OID_desc)))) {
384 if (((*oid)->elements = (void *) malloc(nbytes))) {
385 (*oid)->length = nbytes;
386 op = (unsigned char *) (*oid)->elements;
387 bp = startp;
388 (void) sscanf((char *)bp, "%ld", &numbuf);
389 while (isdigit(*bp))
390 bp++;
391 while (isspace(*bp) || *bp == '.')
392 bp++;
393 onumbuf = 40*numbuf;
394 (void) sscanf((char *)bp, "%ld", &numbuf);
395 onumbuf += numbuf;
396 *op = (unsigned char) onumbuf;
397 op++;
398 while (isdigit(*bp))
399 bp++;
400 while (isspace(*bp) || *bp == '.')
401 bp++;
402 while (isdigit(*bp)) {
403 (void) sscanf((char *)bp, "%ld", &numbuf);
404 nbytes = 0;
405 /* Have to fill in the bytes msb-first */
406 onumbuf = numbuf;
407 while (numbuf) {
408 nbytes++;
409 numbuf >>= 7;
411 numbuf = onumbuf;
412 op += nbytes;
413 index = -1;
414 while (numbuf) {
415 op[index] = (unsigned char) numbuf & 0x7f;
416 if (index != -1)
417 op[index] |= 0x80;
418 index--;
419 numbuf >>= 7;
421 while (isdigit(*bp))
422 bp++;
423 while (isspace(*bp) || *bp == '.')
424 bp++;
426 return(GSS_S_COMPLETE);
428 else {
429 free(*oid);
430 *oid = GSS_C_NO_OID;
433 return(GSS_S_FAILURE);
436 /* Compose an OID of a prefix and an integer suffix */
437 OM_uint32
438 generic_gss_oid_compose(
439 OM_uint32 *minor_status,
440 const char *prefix,
441 size_t prefix_len,
442 int suffix,
443 gss_OID_desc *oid)
445 int osuffix, i;
446 size_t nbytes;
447 unsigned char *op;
449 if (oid == GSS_C_NO_OID) {
450 *minor_status = EINVAL;
451 return GSS_S_FAILURE;
453 if (oid->length < prefix_len) {
454 *minor_status = ERANGE;
455 return GSS_S_FAILURE;
458 memcpy(oid->elements, prefix, prefix_len);
460 nbytes = 0;
461 osuffix = suffix;
462 while (suffix) {
463 nbytes++;
464 suffix >>= 7;
466 suffix = osuffix;
468 if (oid->length < prefix_len + nbytes) {
469 *minor_status = ERANGE;
470 return GSS_S_FAILURE;
473 op = (unsigned char *) oid->elements + prefix_len + nbytes;
474 i = -1;
475 while (suffix) {
476 op[i] = (unsigned char)suffix & 0x7f;
477 if (i != -1)
478 op[i] |= 0x80;
479 i--;
480 suffix >>= 7;
483 oid->length = prefix_len + nbytes;
485 *minor_status = 0;
486 return GSS_S_COMPLETE;
489 OM_uint32
490 generic_gss_oid_decompose(
491 OM_uint32 *minor_status,
492 const char *prefix,
493 size_t prefix_len,
494 gss_OID_desc *oid,
495 int *suffix)
497 size_t i, slen;
498 unsigned char *op;
500 if (oid->length < prefix_len ||
501 memcmp(oid->elements, prefix, prefix_len) != 0) {
502 return GSS_S_BAD_MECH;
505 op = (unsigned char *) oid->elements + prefix_len;
507 *suffix = 0;
509 slen = oid->length - prefix_len;
511 for (i = 0; i < slen; i++) {
512 *suffix = (*suffix << 7) | (op[i] & 0x7f);
513 if (i + 1 != slen && (op[i] & 0x80) == 0) {
514 *minor_status = EINVAL;
515 return GSS_S_FAILURE;
519 return GSS_S_COMPLETE;
523 * Copyright 1993 by OpenVision Technologies, Inc.
525 * Permission to use, copy, modify, distribute, and sell this software
526 * and its documentation for any purpose is hereby granted without fee,
527 * provided that the above copyright notice appears in all copies and
528 * that both that copyright notice and this permission notice appear in
529 * supporting documentation, and that the name of OpenVision not be used
530 * in advertising or publicity pertaining to distribution of the software
531 * without specific, written prior permission. OpenVision makes no
532 * representations about the suitability of this software for any
533 * purpose. It is provided "as is" without express or implied warranty.
535 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
536 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
537 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
538 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
539 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
540 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
541 * PERFORMANCE OF THIS SOFTWARE.
543 OM_uint32
544 gssint_copy_oid_set(
545 OM_uint32 *minor_status,
546 const gss_OID_set_desc * const oidset,
547 gss_OID_set *new_oidset
550 gss_OID_set_desc *copy;
551 OM_uint32 minor = 0;
552 OM_uint32 major = GSS_S_COMPLETE;
553 OM_uint32 index;
555 if (minor_status != NULL)
556 *minor_status = 0;
558 if (new_oidset != NULL)
559 *new_oidset = GSS_C_NO_OID_SET;
561 if (oidset == GSS_C_NO_OID_SET)
562 return (GSS_S_CALL_INACCESSIBLE_READ);
564 if (new_oidset == NULL)
565 return (GSS_S_CALL_INACCESSIBLE_WRITE);
567 if ((copy = (gss_OID_set_desc *) calloc(1, sizeof (*copy))) == NULL) {
568 major = GSS_S_FAILURE;
569 goto done;
572 if ((copy->elements = (gss_OID_desc *)
573 calloc(oidset->count, sizeof (*copy->elements))) == NULL) {
574 major = GSS_S_FAILURE;
575 goto done;
577 copy->count = oidset->count;
579 for (index = 0; index < copy->count; index++) {
580 gss_OID_desc *out = &copy->elements[index];
581 gss_OID_desc *in = &oidset->elements[index];
583 if ((out->elements = (void *) malloc(in->length)) == NULL) {
584 major = GSS_S_FAILURE;
585 goto done;
587 (void) memcpy(out->elements, in->elements, in->length);
588 out->length = in->length;
591 *new_oidset = copy;
592 done:
593 if (major != GSS_S_COMPLETE) {
594 (void) gss_release_oid_set(&minor, &copy);
597 return (major);