1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 8563 Kenjiro * Common Development and Distribution License (the "License"). 6 8563 Kenjiro * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 8563 Kenjiro * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel #include <pwd.h> 27 0 stevel #include <grp.h> 28 0 stevel #include <stdio.h> 29 0 stevel #include <stdlib.h> 30 0 stevel #include <unistd.h> 31 0 stevel #include <thread.h> 32 0 stevel #include <synch.h> 33 0 stevel #include <syslog.h> 34 0 stevel #include <deflt.h> 35 0 stevel #include <mechglueP.h> 36 0 stevel #include "../../cmd/gss/gsscred/gsscred.h" 37 0 stevel 38 0 stevel static mutex_t uid_map_lock = DEFAULTMUTEX; 39 0 stevel static int uid_map_opt = 0; 40 0 stevel 41 0 stevel extern int _getgroupsbymember(const char *, gid_t[], int, int); 42 0 stevel 43 0 stevel /* local function used to call a mechanisms pname_to_uid */ 44 0 stevel static OM_uint32 gss_pname_to_uid(OM_uint32*, const gss_name_t, 45 0 stevel const gss_OID, uid_t *); 46 0 stevel 47 0 stevel static OM_uint32 private_gsscred_expname_to_unix_cred(const gss_buffer_t, 48 0 stevel uid_t *, gid_t *, gid_t **, int *); 49 0 stevel 50 0 stevel /* 51 0 stevel * The gsscred functions will first attempt to call the 52 0 stevel * mechanism'm pname_to_uid function. In case this function 53 0 stevel * returns an error or if it is not provided by a mechanism 54 0 stevel * then the functions will attempt to look up the principal 55 0 stevel * in the gsscred table. 56 0 stevel * It is envisioned that the pname_to_uid function will be 57 0 stevel * provided by only a few mechanism, which may have the principal 58 0 stevel * name to unix credential mapping inherently present. 59 0 stevel */ 60 0 stevel 61 0 stevel /* 62 0 stevel * Fetch gsscred options from conf file. 63 0 stevel */ 64 0 stevel static void 65 0 stevel get_conf_options(int *uid_map) 66 0 stevel { 67 8563 Kenjiro int flags; 68 0 stevel char *ptr; 69 8563 Kenjiro void *defp; 70 0 stevel static char *conffile = "/etc/gss/gsscred.conf"; 71 0 stevel 72 0 stevel *uid_map = 0; 73 8563 Kenjiro if ((defp = defopen_r(conffile)) != NULL) { 74 8563 Kenjiro flags = defcntl_r(DC_GETFLAGS, 0, defp); 75 0 stevel /* ignore case */ 76 0 stevel TURNOFF(flags, DC_CASE); 77 8563 Kenjiro (void) defcntl_r(DC_SETFLAGS, flags, defp); 78 0 stevel 79 8563 Kenjiro if ((ptr = defread_r("SYSLOG_UID_MAPPING=", defp)) != NULL && 80 0 stevel strcasecmp("yes", ptr) == 0) { 81 0 stevel *uid_map = 1; 82 0 stevel } 83 8563 Kenjiro defclose_r(defp); 84 0 stevel } 85 0 stevel } 86 0 stevel 87 0 stevel void 88 0 stevel gsscred_set_options() 89 0 stevel { 90 0 stevel int u; 91 0 stevel 92 0 stevel get_conf_options(&u); 93 0 stevel (void) mutex_lock(&uid_map_lock); 94 0 stevel uid_map_opt = u; 95 0 stevel (void) mutex_unlock(&uid_map_lock); 96 0 stevel } 97 0 stevel 98 0 stevel static int 99 0 stevel get_uid_map_opt() 100 0 stevel { 101 0 stevel int u; 102 0 stevel 103 0 stevel (void) mutex_lock(&uid_map_lock); 104 0 stevel u = uid_map_opt; 105 0 stevel (void) mutex_unlock(&uid_map_lock); 106 0 stevel return (u); 107 0 stevel } 108 0 stevel 109 0 stevel /* 110 0 stevel * This routine accepts a name in export name format and retrieves 111 0 stevel * unix credentials associated with it. 112 0 stevel */ 113 0 stevel 114 0 stevel OM_uint32 115 0 stevel gsscred_expname_to_unix_cred_ext( 116 0 stevel const gss_buffer_t expName, 117 0 stevel uid_t *uidOut, 118 0 stevel gid_t *gidOut, 119 0 stevel gid_t *gids[], 120 0 stevel int *gidsLen, 121 0 stevel int try_mech) 122 0 stevel { 123 0 stevel gss_name_t intName; 124 0 stevel OM_uint32 minor, major; 125 0 stevel const char *mechStr = NULL; 126 0 stevel char *nameStr = NULL; 127 0 stevel char *whoami = "gsscred_expname_to_unix_cred"; 128 0 stevel gss_buffer_desc namebuf; 129 0 stevel int debug = get_uid_map_opt(); 130 0 stevel 131 0 stevel if (uidOut == NULL) 132 0 stevel return (GSS_S_CALL_INACCESSIBLE_WRITE); 133 0 stevel 134 0 stevel if (expName == NULL) 135 0 stevel return (GSS_S_CALL_INACCESSIBLE_READ); 136 0 stevel 137 0 stevel /* first check the mechanism for the mapping */ 138 0 stevel if (gss_import_name(&minor, expName, (gss_OID)GSS_C_NT_EXPORT_NAME, 139 8563 Kenjiro &intName) == GSS_S_COMPLETE) { 140 0 stevel 141 0 stevel if (debug) { 142 0 stevel gss_union_name_t uintName = (gss_union_name_t)intName; 143 0 stevel 144 0 stevel if (uintName->mech_type) 145 0 stevel mechStr = __gss_oid_to_mech( 146 8563 Kenjiro uintName->mech_type); 147 0 stevel 148 0 stevel major = gss_display_name(&minor, intName, 149 8563 Kenjiro &namebuf, NULL); 150 0 stevel if (major == GSS_S_COMPLETE) { 151 0 stevel nameStr = strdup(namebuf.value); 152 0 stevel (void) gss_release_buffer(&minor, &namebuf); 153 0 stevel } 154 0 stevel } 155 0 stevel 156 0 stevel if (try_mech) { 157 0 stevel major = gss_pname_to_uid(&minor, intName, 158 8563 Kenjiro NULL, uidOut); 159 0 stevel if (major == GSS_S_COMPLETE) { 160 0 stevel 161 0 stevel if (debug) { 162 0 stevel syslog(LOG_AUTH|LOG_DEBUG, 163 0 stevel "%s: mech provided local name" 164 0 stevel " mapping (%s, %s, %d)", whoami, 165 0 stevel mechStr ? mechStr : "<null>", 166 0 stevel nameStr ? nameStr : "<null>", 167 0 stevel *uidOut); 168 0 stevel free(nameStr); 169 0 stevel } 170 0 stevel 171 0 stevel (void) gss_release_name(&minor, &intName); 172 0 stevel if (gids && gidsLen && gidOut) 173 0 stevel return (gss_get_group_info(*uidOut, 174 8563 Kenjiro gidOut, gids, gidsLen)); 175 0 stevel return (GSS_S_COMPLETE); 176 0 stevel } 177 0 stevel } 178 0 stevel 179 0 stevel (void) gss_release_name(&minor, &intName); 180 0 stevel } 181 0 stevel 182 0 stevel /* 183 0 stevel * we fall back onto the gsscred table to provide the mapping 184 0 stevel * start by making sure that the expName is an export name buffer 185 0 stevel */ 186 0 stevel major = private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut, 187 8563 Kenjiro gids, gidsLen); 188 0 stevel 189 0 stevel if (debug && major == GSS_S_COMPLETE) { 190 0 stevel syslog(LOG_AUTH|LOG_DEBUG, 191 0 stevel "%s: gsscred tbl provided" 192 0 stevel " local name mapping (%s, %s, %d)", 193 0 stevel whoami, 194 0 stevel mechStr ? mechStr : "<unknown>", 195 0 stevel nameStr ? nameStr : "<unknown>", 196 0 stevel *uidOut); 197 0 stevel free(nameStr); 198 0 stevel } else if (debug) { 199 0 stevel syslog(LOG_AUTH|LOG_DEBUG, 200 0 stevel "%s: gsscred tbl could NOT" 201 0 stevel " provide local name mapping (%s, %s)", 202 0 stevel whoami, 203 0 stevel mechStr ? mechStr : "<unknown>", 204 0 stevel nameStr ? nameStr : "<unknown>"); 205 0 stevel free(nameStr); 206 0 stevel } 207 0 stevel 208 0 stevel return (major); 209 0 stevel 210 0 stevel } /* gsscred_expname_to_unix_cred */ 211 0 stevel 212 0 stevel OM_uint32 213 0 stevel gsscred_expname_to_unix_cred( 214 0 stevel const gss_buffer_t expName, 215 0 stevel uid_t *uidOut, 216 0 stevel gid_t *gidOut, 217 0 stevel gid_t *gids[], 218 0 stevel int *gidsLen) 219 0 stevel { 220 0 stevel return (gsscred_expname_to_unix_cred_ext(expName, uidOut, gidOut, gids, 221 8563 Kenjiro gidsLen, 1)); 222 0 stevel } 223 0 stevel 224 0 stevel 225 0 stevel static const char *expNameTokId = "\x04\x01"; 226 0 stevel static const int expNameTokIdLen = 2; 227 0 stevel /* 228 0 stevel * private routine added to be called from gsscred_name_to_unix_cred 229 0 stevel * and gsscred_expName_to_unix_cred. 230 0 stevel */ 231 0 stevel static OM_uint32 232 0 stevel private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen) 233 0 stevel const gss_buffer_t expName; 234 0 stevel uid_t *uidOut; 235 0 stevel gid_t *gidOut; 236 0 stevel gid_t *gids[]; 237 0 stevel int *gidsLen; 238 0 stevel { 239 0 stevel 240 0 stevel if (expName->length < expNameTokIdLen || 241 0 stevel (memcmp(expName->value, expNameTokId, expNameTokIdLen) != 0)) 242 0 stevel return (GSS_S_DEFECTIVE_TOKEN); 243 0 stevel 244 0 stevel if (!gss_getGssCredEntry(expName, uidOut)) 245 0 stevel return (GSS_S_FAILURE); 246 0 stevel 247 0 stevel /* did caller request group info also ? */ 248 0 stevel if (gids && gidsLen && gidOut) 249 0 stevel return (gss_get_group_info(*uidOut, gidOut, gids, gidsLen)); 250 0 stevel 251 0 stevel return (GSS_S_COMPLETE); 252 0 stevel } 253 0 stevel 254 0 stevel /* 255 0 stevel * Return a string of the authenticated name. 256 0 stevel * It's a bit of hack/workaround/longroad but the current intName 257 0 stevel * passed to gss_display_name insists on returning an empty string. 258 0 stevel * 259 0 stevel * Caller must free string memory. 260 0 stevel */ 261 0 stevel static 262 0 stevel char *make_name_str( 263 0 stevel const gss_name_t intName, 264 0 stevel const gss_OID mechType) 265 0 stevel 266 0 stevel { 267 0 stevel gss_buffer_desc expName = GSS_C_EMPTY_BUFFER; 268 0 stevel OM_uint32 major, minor; 269 0 stevel gss_name_t canonName; 270 0 stevel gss_name_t iName; 271 0 stevel gss_buffer_desc namebuf; 272 0 stevel 273 0 stevel if (major = gss_canonicalize_name(&minor, intName, 274 0 stevel mechType, &canonName)) 275 0 stevel return (NULL); 276 0 stevel 277 0 stevel major = gss_export_name(&minor, canonName, &expName); 278 0 stevel (void) gss_release_name(&minor, &canonName); 279 0 stevel if (major) 280 0 stevel return (NULL); 281 0 stevel 282 0 stevel if (gss_import_name(&minor, &expName, 283 0 stevel (gss_OID)GSS_C_NT_EXPORT_NAME, 284 0 stevel &iName) == GSS_S_COMPLETE) { 285 0 stevel 286 0 stevel major = gss_display_name(&minor, iName, &namebuf, NULL); 287 0 stevel if (major == GSS_S_COMPLETE) { 288 0 stevel char *s; 289 0 stevel 290 0 stevel if (namebuf.value) 291 0 stevel s = strdup(namebuf.value); 292 0 stevel 293 0 stevel (void) gss_release_buffer(&minor, &namebuf); 294 0 stevel (void) gss_release_buffer(&minor, &expName); 295 0 stevel (void) gss_release_buffer(&minor, (gss_buffer_t)iName); 296 0 stevel return (s); 297 0 stevel } 298 0 stevel (void) gss_release_buffer(&minor, (gss_buffer_t)iName); 299 0 stevel } 300 0 stevel 301 0 stevel (void) gss_release_buffer(&minor, &expName); 302 0 stevel return (NULL); 303 0 stevel } 304 0 stevel 305 0 stevel /* 306 0 stevel * This routine accepts a name in gss internal name format together with 307 0 stevel * a mechanim OID and retrieves a unix credentials for that entity. 308 0 stevel */ 309 0 stevel OM_uint32 310 0 stevel gsscred_name_to_unix_cred_ext( 311 0 stevel const gss_name_t intName, 312 0 stevel const gss_OID mechType, 313 0 stevel uid_t *uidOut, 314 0 stevel gid_t *gidOut, 315 0 stevel gid_t *gids[], 316 0 stevel int *gidsLen, 317 0 stevel int try_mech) 318 0 stevel { 319 0 stevel gss_name_t canonName; 320 0 stevel gss_buffer_desc expName = GSS_C_EMPTY_BUFFER; 321 0 stevel OM_uint32 major, minor; 322 0 stevel int debug = get_uid_map_opt(); 323 0 stevel 324 0 stevel const char *mechStr; 325 0 stevel char *whoami = "gsscred_name_to_unix_cred"; 326 0 stevel gss_buffer_desc namebuf; 327 0 stevel 328 0 stevel if (intName == NULL || mechType == NULL) 329 0 stevel return (GSS_S_CALL_INACCESSIBLE_READ); 330 0 stevel 331 0 stevel if (uidOut == NULL) 332 0 stevel return (GSS_S_CALL_INACCESSIBLE_WRITE); 333 0 stevel 334 0 stevel mechStr = __gss_oid_to_mech(mechType); 335 0 stevel 336 0 stevel /* first try the mechanism provided mapping */ 337 0 stevel if (try_mech && gss_pname_to_uid(&minor, intName, mechType, uidOut) 338 8563 Kenjiro == GSS_S_COMPLETE) { 339 0 stevel 340 0 stevel if (debug) { 341 0 stevel char *s = make_name_str(intName, mechType); 342 0 stevel syslog(LOG_AUTH|LOG_DEBUG, 343 0 stevel "%s: mech provided local name" 344 0 stevel " mapping (%s, %s, %d)", whoami, 345 0 stevel mechStr ? mechStr : "<null>", 346 0 stevel s ? s : "<null>", 347 0 stevel *uidOut); 348 0 stevel free(s); 349 0 stevel } 350 0 stevel 351 0 stevel if (gids && gidsLen && gidOut) 352 0 stevel return (gss_get_group_info(*uidOut, gidOut, gids, 353 8563 Kenjiro gidsLen)); 354 0 stevel return (GSS_S_COMPLETE); 355 0 stevel } 356 0 stevel /* 357 0 stevel * falling back onto the gsscred table to provide the mapping 358 0 stevel * start by canonicalizing the passed in name and then export it 359 0 stevel */ 360 0 stevel if (major = gss_canonicalize_name(&minor, intName, 361 8563 Kenjiro mechType, &canonName)) 362 0 stevel return (major); 363 0 stevel 364 0 stevel major = gss_export_name(&minor, canonName, &expName); 365 0 stevel (void) gss_release_name(&minor, &canonName); 366 0 stevel if (major) 367 0 stevel return (major); 368 0 stevel 369 0 stevel major = private_gsscred_expname_to_unix_cred(&expName, uidOut, gidOut, 370 8563 Kenjiro gids, gidsLen); 371 0 stevel 372 0 stevel 373 0 stevel if (debug) { 374 0 stevel gss_name_t iName; 375 0 stevel OM_uint32 maj; 376 0 stevel char *nameStr = NULL; 377 0 stevel 378 0 stevel if (gss_import_name(&minor, &expName, 379 8563 Kenjiro (gss_OID)GSS_C_NT_EXPORT_NAME, &iName) == GSS_S_COMPLETE) { 380 0 stevel 381 0 stevel maj = gss_display_name(&minor, iName, &namebuf, 382 8563 Kenjiro NULL); 383 0 stevel (void) gss_release_buffer(&minor, (gss_buffer_t)iName); 384 0 stevel if (maj == GSS_S_COMPLETE) { 385 0 stevel nameStr = strdup(namebuf.value); 386 0 stevel (void) gss_release_buffer(&minor, &namebuf); 387 0 stevel } 388 0 stevel } 389 0 stevel 390 0 stevel if (major == GSS_S_COMPLETE) 391 0 stevel syslog(LOG_AUTH|LOG_DEBUG, 392 0 stevel "%s: gsscred tbl provided" 393 0 stevel " local name mapping (%s, %s, %d)", 394 0 stevel whoami, 395 0 stevel mechStr ? mechStr : "<unknown>", 396 0 stevel nameStr ? nameStr : "<unknown>", 397 0 stevel *uidOut); 398 0 stevel else 399 0 stevel syslog(LOG_AUTH|LOG_DEBUG, 400 0 stevel "%s: gsscred tbl could NOT" 401 0 stevel " provide local name mapping (%s, %s)", 402 0 stevel whoami, 403 0 stevel mechStr ? mechStr : "<unknown>", 404 0 stevel nameStr ? nameStr : "<unknown>"); 405 0 stevel 406 0 stevel free(nameStr); 407 0 stevel } 408 0 stevel 409 0 stevel (void) gss_release_buffer(&minor, &expName); 410 0 stevel return (major); 411 0 stevel } /* gsscred_name_to_unix_cred */ 412 0 stevel 413 0 stevel 414 0 stevel OM_uint32 415 0 stevel gsscred_name_to_unix_cred( 416 0 stevel const gss_name_t intName, 417 0 stevel const gss_OID mechType, 418 0 stevel uid_t *uidOut, 419 0 stevel gid_t *gidOut, 420 0 stevel gid_t *gids[], 421 0 stevel int *gidsLen) 422 0 stevel { 423 0 stevel return (gsscred_name_to_unix_cred_ext(intName, mechType, 424 8563 Kenjiro uidOut, gidOut, gids, gidsLen, 1)); 425 0 stevel } 426 0 stevel 427 0 stevel 428 0 stevel 429 0 stevel /* 430 0 stevel * This routine accepts a unix uid, and retrieves the group id 431 0 stevel * and supplamentery group ids for that uid. 432 0 stevel * Callers should be aware that the supplamentary group ids 433 0 stevel * array may be empty even when this function returns success. 434 0 stevel */ 435 0 stevel OM_uint32 436 0 stevel gss_get_group_info(uid, gidOut, gids, gidsLen) 437 0 stevel const uid_t uid; 438 0 stevel gid_t *gidOut; 439 0 stevel gid_t *gids[]; 440 0 stevel int *gidsLen; 441 0 stevel { 442 0 stevel struct passwd *pw; 443 0 stevel int maxgroups; 444 0 stevel 445 0 stevel /* check for output parameters */ 446 0 stevel if (gidOut == NULL || gids == NULL || gidsLen == NULL) 447 0 stevel return (GSS_S_CALL_INACCESSIBLE_WRITE); 448 0 stevel 449 0 stevel *gids = NULL; 450 0 stevel *gidsLen = 0; 451 0 stevel 452 0 stevel /* determine maximum number of groups possible */ 453 0 stevel maxgroups = sysconf(_SC_NGROUPS_MAX); 454 0 stevel if (maxgroups < 1) 455 0 stevel maxgroups = 16; 456 0 stevel 457 0 stevel if ((pw = getpwuid(uid)) == NULL) 458 0 stevel return (GSS_S_FAILURE); 459 0 stevel 460 0 stevel /* 461 0 stevel * we allocate for the maximum number of groups 462 0 stevel * we do not reclaim the space when the actual number 463 0 stevel * is lower, just set the size approprately. 464 0 stevel */ 465 0 stevel *gids = (gid_t *)calloc(maxgroups, sizeof (gid_t)); 466 0 stevel if (*gids == NULL) 467 0 stevel return (GSS_S_FAILURE); 468 0 stevel 469 0 stevel *gidOut = pw->pw_gid; 470 0 stevel (*gids)[0] = pw->pw_gid; 471 0 stevel *gidsLen = _getgroupsbymember(pw->pw_name, *gids, maxgroups, 1); 472 0 stevel /* 473 0 stevel * we will try to remove the duplicate entry from the groups 474 0 stevel * array. This can cause the group array to be empty. 475 0 stevel */ 476 0 stevel if (*gidsLen < 1) 477 0 stevel { 478 0 stevel free(*gids); 479 0 stevel *gids = NULL; 480 0 stevel return (GSS_S_FAILURE); 481 0 stevel } else if (*gidsLen == 1) { 482 0 stevel free(*gids); 483 0 stevel *gids = NULL; 484 0 stevel *gidsLen = 0; 485 0 stevel } else { 486 0 stevel /* length is atleast 2 */ 487 0 stevel *gidsLen = *gidsLen -1; 488 0 stevel (*gids)[0] = (*gids)[*gidsLen]; 489 0 stevel } 490 0 stevel 491 0 stevel return (GSS_S_COMPLETE); 492 0 stevel } /* gss_get_group_info */ 493 0 stevel 494 0 stevel 495 0 stevel static OM_uint32 496 0 stevel gss_pname_to_uid(minor, name, mech_type, uidOut) 497 0 stevel OM_uint32 *minor; 498 0 stevel const gss_name_t name; 499 0 stevel const gss_OID mech_type; 500 0 stevel uid_t *uidOut; 501 0 stevel { 502 0 stevel gss_mechanism mech; 503 0 stevel gss_union_name_t intName; 504 0 stevel gss_name_t mechName = NULL; 505 0 stevel OM_uint32 major, tmpMinor; 506 0 stevel 507 0 stevel if (!minor) 508 0 stevel return (GSS_S_CALL_INACCESSIBLE_WRITE); 509 0 stevel 510 0 stevel *minor = 0; 511 0 stevel 512 0 stevel if (uidOut == NULL) 513 0 stevel return (GSS_S_CALL_INACCESSIBLE_WRITE); 514 0 stevel 515 0 stevel if (name == NULL) 516 0 stevel return (GSS_S_CALL_INACCESSIBLE_READ); 517 0 stevel 518 0 stevel intName = (gss_union_name_t)name; 519 0 stevel 520 0 stevel if (mech_type != NULL) 521 0 stevel mech = __gss_get_mechanism(mech_type); 522 0 stevel else { 523 0 stevel /* 524 0 stevel * if this is a MN, then try using the mech 525 0 stevel * from the name; otherwise ask for default 526 0 stevel */ 527 0 stevel mech = __gss_get_mechanism(intName->mech_type); 528 0 stevel } 529 0 stevel 530 0 stevel if (mech == NULL || mech->pname_to_uid == NULL) 531 0 stevel return (GSS_S_UNAVAILABLE); 532 0 stevel 533 0 stevel /* may need to import the name if this is not MN */ 534 0 stevel if (intName->mech_type == NULL) { 535 0 stevel major = __gss_import_internal_name(minor, 536 0 stevel mech_type, intName, 537 0 stevel &mechName); 538 0 stevel if (major != GSS_S_COMPLETE) 539 0 stevel return (major); 540 0 stevel } else 541 0 stevel mechName = intName->mech_name; 542 0 stevel 543 0 stevel 544 0 stevel /* now call the mechanism's pname function to do the work */ 545 0 stevel major = mech->pname_to_uid(mech->context, minor, mechName, uidOut); 546 0 stevel 547 0 stevel if (intName->mech_name != mechName) 548 0 stevel (void) __gss_release_internal_name(&tmpMinor, &mech->mech_type, 549 0 stevel &mechName); 550 0 stevel 551 0 stevel return (major); 552 0 stevel } /* gss_pname_to_uid */ 553