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 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 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 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 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 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 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 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 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 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 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