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