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