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