1 /* 2 * Copyright 2004 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 p = (gss_OID) malloc(sizeof (gss_OID_desc)); 107 if (!p) { 108 return (GSS_S_FAILURE); 109 } 110 p->length = oid->length; 111 p->elements = malloc(p->length); 112 if (!p->elements) { 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)))) { 131 (void) memset(*oid_set, 0, sizeof (gss_OID_set_desc)); 132 return (GSS_S_COMPLETE); 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 */ 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 { 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 } 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]; 228 OM_uint32 number; 229 int numshift; 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++) { 257 if ((OM_uint32) (numshift+7) < (sizeof (OM_uint32)*8)) { 258 number = (number << 7) | (cp[i] & 0x7f); 259 numshift += 7; 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, "{ "); 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; 295 oid_str->value = (void *) bp; 296 return (GSS_S_COMPLETE); 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; 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 */ 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++; 358 if (sscanf(bp, "%d", &numbuf) != 1) { 359 return (GSS_S_FAILURE); 360 } 361 while ((bp < &cp[oid_str->length]) && isdigit(*bp)) 362 bp++; 363 while ((bp < &cp[oid_str->length]) && 364 (isspace(*bp) || *bp == '.')) 365 bp++; 366 nbytes++; 367 while (isdigit(*bp)) { 368 if (sscanf(bp, "%d", &numbuf) != 1) { 369 return (GSS_S_FAILURE); 370 } 371 while (numbuf) { 372 nbytes++; 373 numbuf >>= 7; 374 } 375 while ((bp < &cp[oid_str->length]) && isdigit(*bp)) 376 bp++; 377 while ((bp < &cp[oid_str->length]) && 378 (isspace(*bp) || *bp == '.')) 379 bp++; 380 } 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)))) { 389 if (((*oid)->elements = (void *) malloc(nbytes))) { 390 (*oid)->length = nbytes; 391 op = (unsigned char *) (*oid)->elements; 392 bp = startp; 393 (void) sscanf(bp, "%d", &numbuf); 394 while (isdigit(*bp)) 395 bp++; 396 while (isspace(*bp) || *bp == '.') 397 bp++; 398 onumbuf = 40*numbuf; 399 (void) sscanf(bp, "%d", &numbuf); 400 onumbuf += numbuf; 401 *op = (unsigned char) onumbuf; 402 op++; 403 while (isdigit(*bp)) 404 bp++; 405 while (isspace(*bp) || *bp == '.') 406 bp++; 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 } 427 while (isdigit(*bp)) 428 bp++; 429 while (isspace(*bp) || *bp == '.') 430 bp++; 431 } 432 return (GSS_S_COMPLETE); 433 } else { 434 free(*oid); 435 *oid = GSS_C_NO_OID; 436 } 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 } 517