1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% 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 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 if (new_oid == NULL) 107 return (GSS_S_CALL_INACCESSIBLE_WRITE); 108 109 if (oid == GSS_C_NO_OID) 110 return (GSS_S_CALL_INACCESSIBLE_READ); 111 112 p = (gss_OID) malloc(sizeof (gss_OID_desc)); 113 if (!p) { 114 return (GSS_S_FAILURE); 115 } 116 p->length = oid->length; 117 p->elements = malloc(p->length); 118 if (!p->elements) { 119 free(p); 120 return (GSS_S_FAILURE); 121 } 122 (void) memcpy(p->elements, oid->elements, p->length); 123 *new_oid = p; 124 return (GSS_S_COMPLETE); 125 } 126 127 128 OM_uint32 129 generic_gss_create_empty_oid_set(minor_status, oid_set) 130 OM_uint32 *minor_status; 131 gss_OID_set *oid_set; 132 { 133 if (minor_status) 134 *minor_status = 0; 135 136 if (oid_set == NULL) 137 return (GSS_S_CALL_INACCESSIBLE_WRITE); 138 139 if ((*oid_set = (gss_OID_set) malloc(sizeof (gss_OID_set_desc)))) { 140 (void) memset(*oid_set, 0, sizeof (gss_OID_set_desc)); 141 return (GSS_S_COMPLETE); 142 } else { 143 return (GSS_S_FAILURE); 144 } 145 } 146 147 OM_uint32 148 generic_gss_add_oid_set_member(minor_status, member_oid, oid_set) 149 OM_uint32 *minor_status; 150 const gss_OID member_oid; 151 gss_OID_set *oid_set; 152 { 153 gss_OID elist; 154 gss_OID lastel; 155 156 if (minor_status) 157 *minor_status = 0; 158 159 if (member_oid == GSS_C_NO_OID || member_oid->length == 0 || 160 member_oid->elements == NULL) 161 return (GSS_S_CALL_INACCESSIBLE_READ); 162 163 if (oid_set == NULL) 164 return (GSS_S_CALL_INACCESSIBLE_WRITE); 165 166 elist = (*oid_set)->elements; 167 /* Get an enlarged copy of the array */ 168 if (((*oid_set)->elements = (gss_OID) malloc(((*oid_set)->count+1) * 169 sizeof (gss_OID_desc)))) { 170 /* Copy in the old junk */ 171 if (elist) 172 (void) memcpy((*oid_set)->elements, elist, 173 ((*oid_set)->count * sizeof (gss_OID_desc))); 174 175 /* Duplicate the input element */ 176 lastel = &(*oid_set)->elements[(*oid_set)->count]; 177 if ((lastel->elements = 178 (void *) malloc(member_oid->length))) { 179 180 /* Success - copy elements */ 181 (void) memcpy(lastel->elements, member_oid->elements, 182 member_oid->length); 183 /* Set length */ 184 lastel->length = member_oid->length; 185 186 /* Update count */ 187 (*oid_set)->count++; 188 if (elist) 189 free(elist); 190 return (GSS_S_COMPLETE); 191 } else 192 free((*oid_set)->elements); 193 } 194 /* Failure - restore old contents of list */ 195 (*oid_set)->elements = elist; 196 return (GSS_S_FAILURE); 197 } 198 199 OM_uint32 200 generic_gss_test_oid_set_member(minor_status, member, set, present) 201 OM_uint32 *minor_status; 202 const gss_OID member; 203 const gss_OID_set set; 204 int *present; 205 { 206 OM_uint32 i; 207 int result; 208 209 if (minor_status) 210 *minor_status = 0; 211 212 if (member == GSS_C_NO_OID || set == NULL) 213 return (GSS_S_CALL_INACCESSIBLE_READ); 214 215 if (present == NULL) 216 return (GSS_S_CALL_INACCESSIBLE_WRITE); 217 218 result = 0; 219 for (i = 0; i < set->count; i++) { 220 if ((set->elements[i].length == member->length) && 221 !memcmp(set->elements[i].elements, 222 member->elements, member->length)) { 223 result = 1; 224 break; 225 } 226 } 227 *present = result; 228 return (GSS_S_COMPLETE); 229 } 230 231 /* 232 * OID<->string routines. These are uuuuugly. 233 */ 234 OM_uint32 235 generic_gss_oid_to_str(minor_status, oid, oid_str) 236 OM_uint32 *minor_status; 237 const gss_OID oid; 238 gss_buffer_t oid_str; 239 { 240 char numstr[128]; 241 OM_uint32 number; 242 int numshift; 243 OM_uint32 string_length; 244 OM_uint32 i; 245 unsigned char *cp; 246 char *bp; 247 248 if (minor_status) 249 *minor_status = 0; 250 251 if (oid == GSS_C_NO_OID || oid->length == 0 || oid->elements == NULL) 252 return (GSS_S_CALL_INACCESSIBLE_READ); 253 254 if (oid_str == NULL) 255 return (GSS_S_CALL_INACCESSIBLE_WRITE); 256 257 /* First determine the size of the string */ 258 string_length = 0; 259 number = 0; 260 numshift = 0; 261 cp = (unsigned char *) oid->elements; 262 number = (OM_uint32) cp[0]; 263 (void) sprintf(numstr, "%d ", number/40); 264 string_length += strlen(numstr); 265 (void) sprintf(numstr, "%d ", number%40); 266 string_length += strlen(numstr); 267 for (i = 1; i < oid->length; i++) { 268 if ((OM_uint32) (numshift+7) < (sizeof (OM_uint32)*8)) { 269 number = (number << 7) | (cp[i] & 0x7f); 270 numshift += 7; 271 } else { 272 return (GSS_S_FAILURE); 273 } 274 275 if ((cp[i] & 0x80) == 0) { 276 (void) sprintf(numstr, "%d ", number); 277 string_length += strlen(numstr); 278 number = 0; 279 numshift = 0; 280 } 281 } 282 /* 283 * If we get here, we've calculated the length of "n n n ... n ". Add 4 284 * here for "{ " and "}\0". 285 */ 286 string_length += 4; 287 if ((bp = (char *)malloc(string_length))) { 288 (void) strcpy(bp, "{ "); 289 number = (OM_uint32) cp[0]; 290 (void) sprintf(numstr, "%d ", number/40); 291 (void) strcat(bp, numstr); 292 (void) sprintf(numstr, "%d ", number%40); 293 (void) strcat(bp, numstr); 294 number = 0; 295 cp = (unsigned char *) oid->elements; 296 for (i = 1; i < oid->length; i++) { 297 number = (number << 7) | (cp[i] & 0x7f); 298 if ((cp[i] & 0x80) == 0) { 299 (void) sprintf(numstr, "%d ", number); 300 (void) strcat(bp, numstr); 301 number = 0; 302 } 303 } 304 (void) strcat(bp, "}"); 305 oid_str->length = strlen(bp)+1; 306 oid_str->value = (void *) bp; 307 return (GSS_S_COMPLETE); 308 } 309 return (GSS_S_FAILURE); 310 } 311 312 /* 313 * This routine will handle 2 types of oid string formats: 314 * 1 - { 1 2 3 4 } where the braces are optional 315 * 2 - 1.2.3.4 this is an alernative format 316 * The first format is mandated by the gss spec. The 317 * second format is popular outside of the gss community so 318 * has been added. 319 */ 320 OM_uint32 321 generic_gss_str_to_oid(minor_status, oid_str, oid) 322 OM_uint32 *minor_status; 323 const gss_buffer_t oid_str; 324 gss_OID *oid; 325 { 326 char *cp, *bp, *startp; 327 int brace; 328 int numbuf; 329 int onumbuf; 330 OM_uint32 nbytes; 331 int index; 332 unsigned char *op; 333 334 if (minor_status) 335 *minor_status = 0; 336 337 if (GSS_EMPTY_BUFFER(oid_str)) 338 return (GSS_S_CALL_INACCESSIBLE_READ); 339 340 if (oid == NULL) 341 return (GSS_S_CALL_INACCESSIBLE_WRITE); 342 343 brace = 0; 344 bp = (char *)oid_str->value; 345 cp = bp; 346 /* Skip over leading space */ 347 while ((bp < &cp[oid_str->length]) && isspace(*bp)) 348 bp++; 349 if (*bp == '{') { 350 brace = 1; 351 bp++; 352 } 353 while ((bp < &cp[oid_str->length]) && isspace(*bp)) 354 bp++; 355 startp = bp; 356 nbytes = 0; 357 358 /* 359 * The first two numbers are chewed up by the first octet. 360 */ 361 if (sscanf(bp, "%d", &numbuf) != 1) { 362 return (GSS_S_FAILURE); 363 } 364 while ((bp < &cp[oid_str->length]) && isdigit(*bp)) 365 bp++; 366 while ((bp < &cp[oid_str->length]) && 367 (isspace(*bp) || *bp == '.')) 368 bp++; 369 if (sscanf(bp, "%d", &numbuf) != 1) { 370 return (GSS_S_FAILURE); 371 } 372 while ((bp < &cp[oid_str->length]) && isdigit(*bp)) 373 bp++; 374 while ((bp < &cp[oid_str->length]) && 375 (isspace(*bp) || *bp == '.')) 376 bp++; 377 nbytes++; 378 while (isdigit(*bp)) { 379 if (sscanf(bp, "%d", &numbuf) != 1) { 380 return (GSS_S_FAILURE); 381 } 382 while (numbuf) { 383 nbytes++; 384 numbuf >>= 7; 385 } 386 while ((bp < &cp[oid_str->length]) && isdigit(*bp)) 387 bp++; 388 while ((bp < &cp[oid_str->length]) && 389 (isspace(*bp) || *bp == '.')) 390 bp++; 391 } 392 if (brace && (*bp != '}')) { 393 return (GSS_S_FAILURE); 394 } 395 396 /* 397 * Phew! We've come this far, so the syntax is good. 398 */ 399 if ((*oid = (gss_OID) malloc(sizeof (gss_OID_desc)))) { 400 if (((*oid)->elements = (void *) malloc(nbytes))) { 401 (*oid)->length = nbytes; 402 op = (unsigned char *) (*oid)->elements; 403 bp = startp; 404 (void) sscanf(bp, "%d", &numbuf); 405 while (isdigit(*bp)) 406 bp++; 407 while (isspace(*bp) || *bp == '.') 408 bp++; 409 onumbuf = 40*numbuf; 410 (void) sscanf(bp, "%d", &numbuf); 411 onumbuf += numbuf; 412 *op = (unsigned char) onumbuf; 413 op++; 414 while (isdigit(*bp)) 415 bp++; 416 while (isspace(*bp) || *bp == '.') 417 bp++; 418 while (isdigit(*bp)) { 419 (void) sscanf(bp, "%d", &numbuf); 420 nbytes = 0; 421 /* Have to fill in the bytes msb-first */ 422 onumbuf = numbuf; 423 while (numbuf) { 424 nbytes++; 425 numbuf >>= 7; 426 } 427 numbuf = onumbuf; 428 op += nbytes; 429 index = -1; 430 while (numbuf) { 431 op[index] = (unsigned char) 432 numbuf & 0x7f; 433 if (index != -1) 434 op[index] |= 0x80; 435 index--; 436 numbuf >>= 7; 437 } 438 while (isdigit(*bp)) 439 bp++; 440 while (isspace(*bp) || *bp == '.') 441 bp++; 442 } 443 return (GSS_S_COMPLETE); 444 } else { 445 free(*oid); 446 *oid = GSS_C_NO_OID; 447 } 448 } 449 return (GSS_S_FAILURE); 450 } 451 452 /* 453 * Copyright 1993 by OpenVision Technologies, Inc. 454 * 455 * Permission to use, copy, modify, distribute, and sell this software 456 * and its documentation for any purpose is hereby granted without fee, 457 * provided that the above copyright notice appears in all copies and 458 * that both that copyright notice and this permission notice appear in 459 * supporting documentation, and that the name of OpenVision not be used 460 * in advertising or publicity pertaining to distribution of the software 461 * without specific, written prior permission. OpenVision makes no 462 * representations about the suitability of this software for any 463 * purpose. It is provided "as is" without express or implied warranty. 464 * 465 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 466 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 467 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR 468 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 469 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 470 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 471 * PERFORMANCE OF THIS SOFTWARE. 472 */ 473 OM_uint32 474 gss_copy_oid_set( 475 OM_uint32 *minor_status, 476 const gss_OID_set_desc * const oidset, 477 gss_OID_set *new_oidset 478 ) 479 { 480 gss_OID_set_desc *copy; 481 OM_uint32 minor = 0; 482 OM_uint32 major = GSS_S_COMPLETE; 483 OM_uint32 index; 484 485 if (minor_status) 486 *minor_status = 0; 487 488 if (oidset == NULL) 489 return (GSS_S_CALL_INACCESSIBLE_READ); 490 491 if (new_oidset == NULL) 492 return (GSS_S_CALL_INACCESSIBLE_WRITE); 493 494 *new_oidset = NULL; 495 496 if ((copy = (gss_OID_set_desc *) calloc(1, sizeof (*copy))) == NULL) { 497 major = GSS_S_FAILURE; 498 goto done; 499 } 500 501 if ((copy->elements = (gss_OID_desc *) 502 calloc(oidset->count, sizeof (*copy->elements))) == NULL) { 503 major = GSS_S_FAILURE; 504 goto done; 505 } 506 copy->count = oidset->count; 507 508 for (index = 0; index < copy->count; index++) { 509 gss_OID_desc *out = ©->elements[index]; 510 gss_OID_desc *in = &oidset->elements[index]; 511 512 if ((out->elements = (void *) malloc(in->length)) == NULL) { 513 major = GSS_S_FAILURE; 514 goto done; 515 } 516 (void) memcpy(out->elements, in->elements, in->length); 517 out->length = in->length; 518 } 519 520 *new_oidset = copy; 521 done: 522 if (major != GSS_S_COMPLETE) { 523 (void) gss_release_oid_set(&minor, ©); 524 } 525 526 return (major); 527 } 528