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