17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*b9175c69SKenjiro Tsuji * Common Development and Distribution License (the "License"). 6*b9175c69SKenjiro Tsuji * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*b9175c69SKenjiro Tsuji * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <pwd.h> 277c478bd9Sstevel@tonic-gate #include <grp.h> 287c478bd9Sstevel@tonic-gate #include <stdio.h> 297c478bd9Sstevel@tonic-gate #include <stdlib.h> 307c478bd9Sstevel@tonic-gate #include <unistd.h> 317c478bd9Sstevel@tonic-gate #include <thread.h> 327c478bd9Sstevel@tonic-gate #include <synch.h> 337c478bd9Sstevel@tonic-gate #include <syslog.h> 347c478bd9Sstevel@tonic-gate #include <deflt.h> 357c478bd9Sstevel@tonic-gate #include <mechglueP.h> 367c478bd9Sstevel@tonic-gate #include "../../cmd/gss/gsscred/gsscred.h" 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate static mutex_t uid_map_lock = DEFAULTMUTEX; 397c478bd9Sstevel@tonic-gate static int uid_map_opt = 0; 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate extern int _getgroupsbymember(const char *, gid_t[], int, int); 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /* local function used to call a mechanisms pname_to_uid */ 447c478bd9Sstevel@tonic-gate static OM_uint32 gss_pname_to_uid(OM_uint32*, const gss_name_t, 457c478bd9Sstevel@tonic-gate const gss_OID, uid_t *); 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate static OM_uint32 private_gsscred_expname_to_unix_cred(const gss_buffer_t, 487c478bd9Sstevel@tonic-gate uid_t *, gid_t *, gid_t **, int *); 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 517c478bd9Sstevel@tonic-gate * The gsscred functions will first attempt to call the 527c478bd9Sstevel@tonic-gate * mechanism'm pname_to_uid function. In case this function 537c478bd9Sstevel@tonic-gate * returns an error or if it is not provided by a mechanism 547c478bd9Sstevel@tonic-gate * then the functions will attempt to look up the principal 557c478bd9Sstevel@tonic-gate * in the gsscred table. 567c478bd9Sstevel@tonic-gate * It is envisioned that the pname_to_uid function will be 577c478bd9Sstevel@tonic-gate * provided by only a few mechanism, which may have the principal 587c478bd9Sstevel@tonic-gate * name to unix credential mapping inherently present. 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate /* 627c478bd9Sstevel@tonic-gate * Fetch gsscred options from conf file. 637c478bd9Sstevel@tonic-gate */ 647c478bd9Sstevel@tonic-gate static void 657c478bd9Sstevel@tonic-gate get_conf_options(int *uid_map) 667c478bd9Sstevel@tonic-gate { 67*b9175c69SKenjiro Tsuji int flags; 687c478bd9Sstevel@tonic-gate char *ptr; 69*b9175c69SKenjiro Tsuji void *defp; 707c478bd9Sstevel@tonic-gate static char *conffile = "/etc/gss/gsscred.conf"; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate *uid_map = 0; 73*b9175c69SKenjiro Tsuji if ((defp = defopen_r(conffile)) != NULL) { 74*b9175c69SKenjiro Tsuji flags = defcntl_r(DC_GETFLAGS, 0, defp); 757c478bd9Sstevel@tonic-gate /* ignore case */ 767c478bd9Sstevel@tonic-gate TURNOFF(flags, DC_CASE); 77*b9175c69SKenjiro Tsuji (void) defcntl_r(DC_SETFLAGS, flags, defp); 787c478bd9Sstevel@tonic-gate 79*b9175c69SKenjiro Tsuji if ((ptr = defread_r("SYSLOG_UID_MAPPING=", defp)) != NULL && 807c478bd9Sstevel@tonic-gate strcasecmp("yes", ptr) == 0) { 817c478bd9Sstevel@tonic-gate *uid_map = 1; 827c478bd9Sstevel@tonic-gate } 83*b9175c69SKenjiro Tsuji defclose_r(defp); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate void 887c478bd9Sstevel@tonic-gate gsscred_set_options() 897c478bd9Sstevel@tonic-gate { 907c478bd9Sstevel@tonic-gate int u; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate get_conf_options(&u); 937c478bd9Sstevel@tonic-gate (void) mutex_lock(&uid_map_lock); 947c478bd9Sstevel@tonic-gate uid_map_opt = u; 957c478bd9Sstevel@tonic-gate (void) mutex_unlock(&uid_map_lock); 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate static int 997c478bd9Sstevel@tonic-gate get_uid_map_opt() 1007c478bd9Sstevel@tonic-gate { 1017c478bd9Sstevel@tonic-gate int u; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate (void) mutex_lock(&uid_map_lock); 1047c478bd9Sstevel@tonic-gate u = uid_map_opt; 1057c478bd9Sstevel@tonic-gate (void) mutex_unlock(&uid_map_lock); 1067c478bd9Sstevel@tonic-gate return (u); 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /* 1107c478bd9Sstevel@tonic-gate * This routine accepts a name in export name format and retrieves 1117c478bd9Sstevel@tonic-gate * unix credentials associated with it. 1127c478bd9Sstevel@tonic-gate */ 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate OM_uint32 1157c478bd9Sstevel@tonic-gate gsscred_expname_to_unix_cred_ext( 1167c478bd9Sstevel@tonic-gate const gss_buffer_t expName, 1177c478bd9Sstevel@tonic-gate uid_t *uidOut, 1187c478bd9Sstevel@tonic-gate gid_t *gidOut, 1197c478bd9Sstevel@tonic-gate gid_t *gids[], 1207c478bd9Sstevel@tonic-gate int *gidsLen, 1217c478bd9Sstevel@tonic-gate int try_mech) 1227c478bd9Sstevel@tonic-gate { 1237c478bd9Sstevel@tonic-gate gss_name_t intName; 1247c478bd9Sstevel@tonic-gate OM_uint32 minor, major; 1257c478bd9Sstevel@tonic-gate const char *mechStr = NULL; 1267c478bd9Sstevel@tonic-gate char *nameStr = NULL; 1277c478bd9Sstevel@tonic-gate char *whoami = "gsscred_expname_to_unix_cred"; 1287c478bd9Sstevel@tonic-gate gss_buffer_desc namebuf; 1297c478bd9Sstevel@tonic-gate int debug = get_uid_map_opt(); 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate if (uidOut == NULL) 1327c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate if (expName == NULL) 1357c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_READ); 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* first check the mechanism for the mapping */ 1387c478bd9Sstevel@tonic-gate if (gss_import_name(&minor, expName, (gss_OID)GSS_C_NT_EXPORT_NAME, 1397c478bd9Sstevel@tonic-gate &intName) == GSS_S_COMPLETE) { 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate if (debug) { 1427c478bd9Sstevel@tonic-gate gss_union_name_t uintName = (gss_union_name_t)intName; 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate if (uintName->mech_type) 1457c478bd9Sstevel@tonic-gate mechStr = __gss_oid_to_mech( 1467c478bd9Sstevel@tonic-gate uintName->mech_type); 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate major = gss_display_name(&minor, intName, 1497c478bd9Sstevel@tonic-gate &namebuf, NULL); 1507c478bd9Sstevel@tonic-gate if (major == GSS_S_COMPLETE) { 1517c478bd9Sstevel@tonic-gate nameStr = strdup(namebuf.value); 1527c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&minor, &namebuf); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate if (try_mech) { 1577c478bd9Sstevel@tonic-gate major = gss_pname_to_uid(&minor, intName, 1587c478bd9Sstevel@tonic-gate NULL, uidOut); 1597c478bd9Sstevel@tonic-gate if (major == GSS_S_COMPLETE) { 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate if (debug) { 1627c478bd9Sstevel@tonic-gate syslog(LOG_AUTH|LOG_DEBUG, 1637c478bd9Sstevel@tonic-gate "%s: mech provided local name" 1647c478bd9Sstevel@tonic-gate " mapping (%s, %s, %d)", whoami, 1657c478bd9Sstevel@tonic-gate mechStr ? mechStr : "<null>", 1667c478bd9Sstevel@tonic-gate nameStr ? nameStr : "<null>", 1677c478bd9Sstevel@tonic-gate *uidOut); 1687c478bd9Sstevel@tonic-gate free(nameStr); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate (void) gss_release_name(&minor, &intName); 1727c478bd9Sstevel@tonic-gate if (gids && gidsLen && gidOut) 1737c478bd9Sstevel@tonic-gate return (gss_get_group_info(*uidOut, 174*b9175c69SKenjiro Tsuji gidOut, gids, gidsLen)); 1757c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate (void) gss_release_name(&minor, &intName); 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * we fall back onto the gsscred table to provide the mapping 1847c478bd9Sstevel@tonic-gate * start by making sure that the expName is an export name buffer 1857c478bd9Sstevel@tonic-gate */ 1867c478bd9Sstevel@tonic-gate major = private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut, 1877c478bd9Sstevel@tonic-gate gids, gidsLen); 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate if (debug && major == GSS_S_COMPLETE) { 1907c478bd9Sstevel@tonic-gate syslog(LOG_AUTH|LOG_DEBUG, 1917c478bd9Sstevel@tonic-gate "%s: gsscred tbl provided" 1927c478bd9Sstevel@tonic-gate " local name mapping (%s, %s, %d)", 1937c478bd9Sstevel@tonic-gate whoami, 1947c478bd9Sstevel@tonic-gate mechStr ? mechStr : "<unknown>", 1957c478bd9Sstevel@tonic-gate nameStr ? nameStr : "<unknown>", 1967c478bd9Sstevel@tonic-gate *uidOut); 1977c478bd9Sstevel@tonic-gate free(nameStr); 1987c478bd9Sstevel@tonic-gate } else if (debug) { 1997c478bd9Sstevel@tonic-gate syslog(LOG_AUTH|LOG_DEBUG, 2007c478bd9Sstevel@tonic-gate "%s: gsscred tbl could NOT" 2017c478bd9Sstevel@tonic-gate " provide local name mapping (%s, %s)", 2027c478bd9Sstevel@tonic-gate whoami, 2037c478bd9Sstevel@tonic-gate mechStr ? mechStr : "<unknown>", 2047c478bd9Sstevel@tonic-gate nameStr ? nameStr : "<unknown>"); 2057c478bd9Sstevel@tonic-gate free(nameStr); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate return (major); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate } /* gsscred_expname_to_unix_cred */ 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate OM_uint32 2137c478bd9Sstevel@tonic-gate gsscred_expname_to_unix_cred( 2147c478bd9Sstevel@tonic-gate const gss_buffer_t expName, 2157c478bd9Sstevel@tonic-gate uid_t *uidOut, 2167c478bd9Sstevel@tonic-gate gid_t *gidOut, 2177c478bd9Sstevel@tonic-gate gid_t *gids[], 2187c478bd9Sstevel@tonic-gate int *gidsLen) 2197c478bd9Sstevel@tonic-gate { 2207c478bd9Sstevel@tonic-gate return (gsscred_expname_to_unix_cred_ext(expName, uidOut, gidOut, gids, 2217c478bd9Sstevel@tonic-gate gidsLen, 1)); 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate static const char *expNameTokId = "\x04\x01"; 2267c478bd9Sstevel@tonic-gate static const int expNameTokIdLen = 2; 2277c478bd9Sstevel@tonic-gate /* 2287c478bd9Sstevel@tonic-gate * private routine added to be called from gsscred_name_to_unix_cred 2297c478bd9Sstevel@tonic-gate * and gsscred_expName_to_unix_cred. 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate static OM_uint32 2327c478bd9Sstevel@tonic-gate private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen) 2337c478bd9Sstevel@tonic-gate const gss_buffer_t expName; 2347c478bd9Sstevel@tonic-gate uid_t *uidOut; 2357c478bd9Sstevel@tonic-gate gid_t *gidOut; 2367c478bd9Sstevel@tonic-gate gid_t *gids[]; 2377c478bd9Sstevel@tonic-gate int *gidsLen; 2387c478bd9Sstevel@tonic-gate { 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate if (expName->length < expNameTokIdLen || 2417c478bd9Sstevel@tonic-gate (memcmp(expName->value, expNameTokId, expNameTokIdLen) != 0)) 2427c478bd9Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN); 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate if (!gss_getGssCredEntry(expName, uidOut)) 2457c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* did caller request group info also ? */ 2487c478bd9Sstevel@tonic-gate if (gids && gidsLen && gidOut) 2497c478bd9Sstevel@tonic-gate return (gss_get_group_info(*uidOut, gidOut, gids, gidsLen)); 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate /* 2557c478bd9Sstevel@tonic-gate * Return a string of the authenticated name. 2567c478bd9Sstevel@tonic-gate * It's a bit of hack/workaround/longroad but the current intName 2577c478bd9Sstevel@tonic-gate * passed to gss_display_name insists on returning an empty string. 2587c478bd9Sstevel@tonic-gate * 2597c478bd9Sstevel@tonic-gate * Caller must free string memory. 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate static 2627c478bd9Sstevel@tonic-gate char *make_name_str( 2637c478bd9Sstevel@tonic-gate const gss_name_t intName, 2647c478bd9Sstevel@tonic-gate const gss_OID mechType) 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate { 2677c478bd9Sstevel@tonic-gate gss_buffer_desc expName = GSS_C_EMPTY_BUFFER; 2687c478bd9Sstevel@tonic-gate OM_uint32 major, minor; 2697c478bd9Sstevel@tonic-gate gss_name_t canonName; 2707c478bd9Sstevel@tonic-gate gss_name_t iName; 2717c478bd9Sstevel@tonic-gate gss_buffer_desc namebuf; 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate if (major = gss_canonicalize_name(&minor, intName, 2747c478bd9Sstevel@tonic-gate mechType, &canonName)) 2757c478bd9Sstevel@tonic-gate return (NULL); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate major = gss_export_name(&minor, canonName, &expName); 2787c478bd9Sstevel@tonic-gate (void) gss_release_name(&minor, &canonName); 2797c478bd9Sstevel@tonic-gate if (major) 2807c478bd9Sstevel@tonic-gate return (NULL); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate if (gss_import_name(&minor, &expName, 2837c478bd9Sstevel@tonic-gate (gss_OID)GSS_C_NT_EXPORT_NAME, 2847c478bd9Sstevel@tonic-gate &iName) == GSS_S_COMPLETE) { 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate major = gss_display_name(&minor, iName, &namebuf, NULL); 2877c478bd9Sstevel@tonic-gate if (major == GSS_S_COMPLETE) { 2887c478bd9Sstevel@tonic-gate char *s; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate if (namebuf.value) 2917c478bd9Sstevel@tonic-gate s = strdup(namebuf.value); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&minor, &namebuf); 2947c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&minor, &expName); 2957c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&minor, (gss_buffer_t)iName); 2967c478bd9Sstevel@tonic-gate return (s); 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&minor, (gss_buffer_t)iName); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&minor, &expName); 3027c478bd9Sstevel@tonic-gate return (NULL); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * This routine accepts a name in gss internal name format together with 3077c478bd9Sstevel@tonic-gate * a mechanim OID and retrieves a unix credentials for that entity. 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate OM_uint32 3107c478bd9Sstevel@tonic-gate gsscred_name_to_unix_cred_ext( 3117c478bd9Sstevel@tonic-gate const gss_name_t intName, 3127c478bd9Sstevel@tonic-gate const gss_OID mechType, 3137c478bd9Sstevel@tonic-gate uid_t *uidOut, 3147c478bd9Sstevel@tonic-gate gid_t *gidOut, 3157c478bd9Sstevel@tonic-gate gid_t *gids[], 3167c478bd9Sstevel@tonic-gate int *gidsLen, 3177c478bd9Sstevel@tonic-gate int try_mech) 3187c478bd9Sstevel@tonic-gate { 3197c478bd9Sstevel@tonic-gate gss_name_t canonName; 3207c478bd9Sstevel@tonic-gate gss_buffer_desc expName = GSS_C_EMPTY_BUFFER; 3217c478bd9Sstevel@tonic-gate OM_uint32 major, minor; 3227c478bd9Sstevel@tonic-gate int debug = get_uid_map_opt(); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate const char *mechStr; 3257c478bd9Sstevel@tonic-gate char *whoami = "gsscred_name_to_unix_cred"; 3267c478bd9Sstevel@tonic-gate gss_buffer_desc namebuf; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate if (intName == NULL || mechType == NULL) 3297c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_READ); 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate if (uidOut == NULL) 3327c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate mechStr = __gss_oid_to_mech(mechType); 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* first try the mechanism provided mapping */ 3377c478bd9Sstevel@tonic-gate if (try_mech && gss_pname_to_uid(&minor, intName, mechType, uidOut) 3387c478bd9Sstevel@tonic-gate == GSS_S_COMPLETE) { 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate if (debug) { 3417c478bd9Sstevel@tonic-gate char *s = make_name_str(intName, mechType); 3427c478bd9Sstevel@tonic-gate syslog(LOG_AUTH|LOG_DEBUG, 3437c478bd9Sstevel@tonic-gate "%s: mech provided local name" 3447c478bd9Sstevel@tonic-gate " mapping (%s, %s, %d)", whoami, 3457c478bd9Sstevel@tonic-gate mechStr ? mechStr : "<null>", 3467c478bd9Sstevel@tonic-gate s ? s : "<null>", 3477c478bd9Sstevel@tonic-gate *uidOut); 3487c478bd9Sstevel@tonic-gate free(s); 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate if (gids && gidsLen && gidOut) 3527c478bd9Sstevel@tonic-gate return (gss_get_group_info(*uidOut, gidOut, gids, 3537c478bd9Sstevel@tonic-gate gidsLen)); 3547c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate /* 3577c478bd9Sstevel@tonic-gate * falling back onto the gsscred table to provide the mapping 3587c478bd9Sstevel@tonic-gate * start by canonicalizing the passed in name and then export it 3597c478bd9Sstevel@tonic-gate */ 3607c478bd9Sstevel@tonic-gate if (major = gss_canonicalize_name(&minor, intName, 3617c478bd9Sstevel@tonic-gate mechType, &canonName)) 3627c478bd9Sstevel@tonic-gate return (major); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate major = gss_export_name(&minor, canonName, &expName); 3657c478bd9Sstevel@tonic-gate (void) gss_release_name(&minor, &canonName); 3667c478bd9Sstevel@tonic-gate if (major) 3677c478bd9Sstevel@tonic-gate return (major); 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate major = private_gsscred_expname_to_unix_cred(&expName, uidOut, gidOut, 3707c478bd9Sstevel@tonic-gate gids, gidsLen); 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate if (debug) { 3747c478bd9Sstevel@tonic-gate gss_name_t iName; 3757c478bd9Sstevel@tonic-gate OM_uint32 maj; 3767c478bd9Sstevel@tonic-gate char *nameStr = NULL; 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate if (gss_import_name(&minor, &expName, 379*b9175c69SKenjiro Tsuji (gss_OID)GSS_C_NT_EXPORT_NAME, &iName) == GSS_S_COMPLETE) { 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate maj = gss_display_name(&minor, iName, &namebuf, 3827c478bd9Sstevel@tonic-gate NULL); 3837c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&minor, (gss_buffer_t)iName); 3847c478bd9Sstevel@tonic-gate if (maj == GSS_S_COMPLETE) { 3857c478bd9Sstevel@tonic-gate nameStr = strdup(namebuf.value); 3867c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&minor, &namebuf); 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate if (major == GSS_S_COMPLETE) 3917c478bd9Sstevel@tonic-gate syslog(LOG_AUTH|LOG_DEBUG, 3927c478bd9Sstevel@tonic-gate "%s: gsscred tbl provided" 3937c478bd9Sstevel@tonic-gate " local name mapping (%s, %s, %d)", 3947c478bd9Sstevel@tonic-gate whoami, 3957c478bd9Sstevel@tonic-gate mechStr ? mechStr : "<unknown>", 3967c478bd9Sstevel@tonic-gate nameStr ? nameStr : "<unknown>", 3977c478bd9Sstevel@tonic-gate *uidOut); 3987c478bd9Sstevel@tonic-gate else 3997c478bd9Sstevel@tonic-gate syslog(LOG_AUTH|LOG_DEBUG, 4007c478bd9Sstevel@tonic-gate "%s: gsscred tbl could NOT" 4017c478bd9Sstevel@tonic-gate " provide local name mapping (%s, %s)", 4027c478bd9Sstevel@tonic-gate whoami, 4037c478bd9Sstevel@tonic-gate mechStr ? mechStr : "<unknown>", 4047c478bd9Sstevel@tonic-gate nameStr ? nameStr : "<unknown>"); 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate free(nameStr); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&minor, &expName); 4107c478bd9Sstevel@tonic-gate return (major); 4117c478bd9Sstevel@tonic-gate } /* gsscred_name_to_unix_cred */ 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate OM_uint32 4157c478bd9Sstevel@tonic-gate gsscred_name_to_unix_cred( 4167c478bd9Sstevel@tonic-gate const gss_name_t intName, 4177c478bd9Sstevel@tonic-gate const gss_OID mechType, 4187c478bd9Sstevel@tonic-gate uid_t *uidOut, 4197c478bd9Sstevel@tonic-gate gid_t *gidOut, 4207c478bd9Sstevel@tonic-gate gid_t *gids[], 4217c478bd9Sstevel@tonic-gate int *gidsLen) 4227c478bd9Sstevel@tonic-gate { 4237c478bd9Sstevel@tonic-gate return (gsscred_name_to_unix_cred_ext(intName, mechType, 424*b9175c69SKenjiro Tsuji uidOut, gidOut, gids, gidsLen, 1)); 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate /* 4307c478bd9Sstevel@tonic-gate * This routine accepts a unix uid, and retrieves the group id 4317c478bd9Sstevel@tonic-gate * and supplamentery group ids for that uid. 4327c478bd9Sstevel@tonic-gate * Callers should be aware that the supplamentary group ids 4337c478bd9Sstevel@tonic-gate * array may be empty even when this function returns success. 4347c478bd9Sstevel@tonic-gate */ 4357c478bd9Sstevel@tonic-gate OM_uint32 4367c478bd9Sstevel@tonic-gate gss_get_group_info(uid, gidOut, gids, gidsLen) 4377c478bd9Sstevel@tonic-gate const uid_t uid; 4387c478bd9Sstevel@tonic-gate gid_t *gidOut; 4397c478bd9Sstevel@tonic-gate gid_t *gids[]; 4407c478bd9Sstevel@tonic-gate int *gidsLen; 4417c478bd9Sstevel@tonic-gate { 4427c478bd9Sstevel@tonic-gate struct passwd *pw; 4437c478bd9Sstevel@tonic-gate int maxgroups; 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate /* check for output parameters */ 4467c478bd9Sstevel@tonic-gate if (gidOut == NULL || gids == NULL || gidsLen == NULL) 4477c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate *gids = NULL; 4507c478bd9Sstevel@tonic-gate *gidsLen = 0; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate /* determine maximum number of groups possible */ 4537c478bd9Sstevel@tonic-gate maxgroups = sysconf(_SC_NGROUPS_MAX); 4547c478bd9Sstevel@tonic-gate if (maxgroups < 1) 4557c478bd9Sstevel@tonic-gate maxgroups = 16; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate if ((pw = getpwuid(uid)) == NULL) 4587c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate /* 4617c478bd9Sstevel@tonic-gate * we allocate for the maximum number of groups 4627c478bd9Sstevel@tonic-gate * we do not reclaim the space when the actual number 4637c478bd9Sstevel@tonic-gate * is lower, just set the size approprately. 4647c478bd9Sstevel@tonic-gate */ 4657c478bd9Sstevel@tonic-gate *gids = (gid_t *)calloc(maxgroups, sizeof (gid_t)); 4667c478bd9Sstevel@tonic-gate if (*gids == NULL) 4677c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate *gidOut = pw->pw_gid; 4707c478bd9Sstevel@tonic-gate (*gids)[0] = pw->pw_gid; 4717c478bd9Sstevel@tonic-gate *gidsLen = _getgroupsbymember(pw->pw_name, *gids, maxgroups, 1); 4727c478bd9Sstevel@tonic-gate /* 4737c478bd9Sstevel@tonic-gate * we will try to remove the duplicate entry from the groups 4747c478bd9Sstevel@tonic-gate * array. This can cause the group array to be empty. 4757c478bd9Sstevel@tonic-gate */ 4767c478bd9Sstevel@tonic-gate if (*gidsLen < 1) 4777c478bd9Sstevel@tonic-gate { 4787c478bd9Sstevel@tonic-gate free(*gids); 4797c478bd9Sstevel@tonic-gate *gids = NULL; 4807c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 4817c478bd9Sstevel@tonic-gate } else if (*gidsLen == 1) { 4827c478bd9Sstevel@tonic-gate free(*gids); 4837c478bd9Sstevel@tonic-gate *gids = NULL; 4847c478bd9Sstevel@tonic-gate *gidsLen = 0; 4857c478bd9Sstevel@tonic-gate } else { 4867c478bd9Sstevel@tonic-gate /* length is atleast 2 */ 4877c478bd9Sstevel@tonic-gate *gidsLen = *gidsLen -1; 4887c478bd9Sstevel@tonic-gate (*gids)[0] = (*gids)[*gidsLen]; 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 4927c478bd9Sstevel@tonic-gate } /* gss_get_group_info */ 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate static OM_uint32 4967c478bd9Sstevel@tonic-gate gss_pname_to_uid(minor, name, mech_type, uidOut) 4977c478bd9Sstevel@tonic-gate OM_uint32 *minor; 4987c478bd9Sstevel@tonic-gate const gss_name_t name; 4997c478bd9Sstevel@tonic-gate const gss_OID mech_type; 5007c478bd9Sstevel@tonic-gate uid_t *uidOut; 5017c478bd9Sstevel@tonic-gate { 5027c478bd9Sstevel@tonic-gate gss_mechanism mech; 5037c478bd9Sstevel@tonic-gate gss_union_name_t intName; 5047c478bd9Sstevel@tonic-gate gss_name_t mechName = NULL; 5057c478bd9Sstevel@tonic-gate OM_uint32 major, tmpMinor; 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate if (!minor) 5087c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate *minor = 0; 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if (uidOut == NULL) 5137c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate if (name == NULL) 5167c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_READ); 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate intName = (gss_union_name_t)name; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if (mech_type != NULL) 5217c478bd9Sstevel@tonic-gate mech = __gss_get_mechanism(mech_type); 5227c478bd9Sstevel@tonic-gate else { 5237c478bd9Sstevel@tonic-gate /* 5247c478bd9Sstevel@tonic-gate * if this is a MN, then try using the mech 5257c478bd9Sstevel@tonic-gate * from the name; otherwise ask for default 5267c478bd9Sstevel@tonic-gate */ 5277c478bd9Sstevel@tonic-gate mech = __gss_get_mechanism(intName->mech_type); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate if (mech == NULL || mech->pname_to_uid == NULL) 5317c478bd9Sstevel@tonic-gate return (GSS_S_UNAVAILABLE); 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate /* may need to import the name if this is not MN */ 5347c478bd9Sstevel@tonic-gate if (intName->mech_type == NULL) { 5357c478bd9Sstevel@tonic-gate major = __gss_import_internal_name(minor, 5367c478bd9Sstevel@tonic-gate mech_type, intName, 5377c478bd9Sstevel@tonic-gate &mechName); 5387c478bd9Sstevel@tonic-gate if (major != GSS_S_COMPLETE) 5397c478bd9Sstevel@tonic-gate return (major); 5407c478bd9Sstevel@tonic-gate } else 5417c478bd9Sstevel@tonic-gate mechName = intName->mech_name; 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* now call the mechanism's pname function to do the work */ 5457c478bd9Sstevel@tonic-gate major = mech->pname_to_uid(mech->context, minor, mechName, uidOut); 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate if (intName->mech_name != mechName) 5487c478bd9Sstevel@tonic-gate (void) __gss_release_internal_name(&tmpMinor, &mech->mech_type, 5497c478bd9Sstevel@tonic-gate &mechName); 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate return (major); 5527c478bd9Sstevel@tonic-gate } /* gss_pname_to_uid */ 553