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
get_conf_options(int * uid_map)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
gsscred_set_options()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
get_uid_map_opt()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
gsscred_expname_to_unix_cred_ext(const gss_buffer_t expName,uid_t * uidOut,gid_t * gidOut,gid_t * gids[],int * gidsLen,int try_mech)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,
139*b9175c69SKenjiro Tsuji &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(
146*b9175c69SKenjiro Tsuji uintName->mech_type);
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate major = gss_display_name(&minor, intName,
149*b9175c69SKenjiro Tsuji &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,
158*b9175c69SKenjiro Tsuji 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,
187*b9175c69SKenjiro Tsuji 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
gsscred_expname_to_unix_cred(const gss_buffer_t expName,uid_t * uidOut,gid_t * gidOut,gid_t * gids[],int * gidsLen)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,
221*b9175c69SKenjiro Tsuji 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
private_gsscred_expname_to_unix_cred(expName,uidOut,gidOut,gids,gidsLen)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
make_name_str(const gss_name_t intName,const gss_OID mechType)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
gsscred_name_to_unix_cred_ext(const gss_name_t intName,const gss_OID mechType,uid_t * uidOut,gid_t * gidOut,gid_t * gids[],int * gidsLen,int try_mech)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)
338*b9175c69SKenjiro Tsuji == 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,
353*b9175c69SKenjiro Tsuji 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,
361*b9175c69SKenjiro Tsuji 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,
370*b9175c69SKenjiro Tsuji 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,
382*b9175c69SKenjiro Tsuji 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
gsscred_name_to_unix_cred(const gss_name_t intName,const gss_OID mechType,uid_t * uidOut,gid_t * gidOut,gid_t * gids[],int * gidsLen)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
gss_get_group_info(uid,gidOut,gids,gidsLen)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
gss_pname_to_uid(minor,name,mech_type,uidOut)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