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