Cdiff gssd_pname_to_uid.c
--- /net/etna.eng/build7/semery/mit2/webrev/usr/src/lib/libgss/gssd_pname_to_uid.c- Wed Sep 8 17:01:16 2004
+++ gssd_pname_to_uid.c Wed Sep 8 13:42:05 2004
@@ -1,20 +1,27 @@
/*
- * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
-#pragma ident "@(#)gssd_pname_to_uid.c 1.19 04/09/08 SMI"
+#pragma ident "@(#)gssd_pname_to_uid.c 1.18 04/02/23 SMI"
#include <pwd.h>
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <thread.h>
+#include <synch.h>
+#include <syslog.h>
+#include <deflt.h>
#include <mechglueP.h>
#include "../../cmd/gss/gsscred/gsscred.h"
+static mutex_t uid_map_lock = DEFAULTMUTEX;
+static int uid_map_opt = 0;
+
extern int _getgroupsbymember(const char *, gid_t[], int, int);
/* local function used to call a mechanisms pname_to_uid */
static OM_uint32 gss_pname_to_uid(OM_uint32*, const gss_name_t,
const gss_OID, uid_t *);
@@ -32,23 +39,88 @@
* provided by only a few mechanism, which may have the principal
* name to unix credential mapping inherently present.
*/
/*
+ * Fetch gsscred options from conf file.
+ */
+static void
+get_conf_options(int *uid_map)
+{
+ register int flags;
+ char *ptr;
+ static char *conffile = "/etc/gss/gsscred.conf";
+ static mutex_t deflt_lock = DEFAULTMUTEX;
+
+
+ *uid_map = 0;
+ /*
+ * hold the lock for the deflt file access as its
+ * interface does not appear to be mt-safe
+ */
+ (void) mutex_lock(&deflt_lock);
+ if (defopen(conffile) == 0) {
+ flags = defcntl(DC_GETFLAGS, 0);
+ /* ignore case */
+ TURNOFF(flags, DC_CASE);
+ (void) defcntl(DC_SETFLAGS, flags);
+
+ if ((ptr = defread("SYSLOG_UID_MAPPING=")) != NULL &&
+ strcasecmp("yes", ptr) == 0) {
+ (void) defopen((char *)NULL);
+ (void) mutex_unlock(&deflt_lock);
+ *uid_map = 1;
+ return;
+ }
+ (void) defopen((char *)NULL);
+ }
+ (void) mutex_unlock(&deflt_lock);
+}
+
+void
+gsscred_set_options()
+{
+ int u;
+
+ get_conf_options(&u);
+ (void) mutex_lock(&uid_map_lock);
+ uid_map_opt = u;
+ (void) mutex_unlock(&uid_map_lock);
+}
+
+static int
+get_uid_map_opt()
+{
+ int u;
+
+ (void) mutex_lock(&uid_map_lock);
+ u = uid_map_opt;
+ (void) mutex_unlock(&uid_map_lock);
+ return (u);
+}
+
+/*
* This routine accepts a name in export name format and retrieves
* unix credentials associated with it.
*/
+
OM_uint32
-gsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen)
-const gss_buffer_t expName;
-uid_t *uidOut;
-gid_t *gidOut;
-gid_t *gids[];
-int *gidsLen;
+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)
{
gss_name_t intName;
OM_uint32 minor, major;
+ const char *mechStr = NULL;
+ char *nameStr = NULL;
+ char *whoami = "gsscred_expname_to_unix_cred";
+ gss_buffer_desc namebuf;
+ int debug = get_uid_map_opt();
if (uidOut == NULL)
return (GSS_S_CALL_INACCESSIBLE_WRITE);
if (expName == NULL)
@@ -55,32 +127,97 @@
return (GSS_S_CALL_INACCESSIBLE_READ);
/* first check the mechanism for the mapping */
if (gss_import_name(&minor, expName, (gss_OID)GSS_C_NT_EXPORT_NAME,
&intName) == GSS_S_COMPLETE) {
- major = gss_pname_to_uid(&minor, intName, NULL, uidOut);
- gss_release_name(&minor, &intName);
+
+ if (debug) {
+ gss_union_name_t uintName = (gss_union_name_t)intName;
+
+ if (uintName->mech_type)
+ mechStr = __gss_oid_to_mech(
+ uintName->mech_type);
+
+ major = gss_display_name(&minor, intName,
+ &namebuf, NULL);
if (major == GSS_S_COMPLETE) {
+ nameStr = strdup(namebuf.value);
+ (void) gss_release_buffer(&minor, &namebuf);
+ }
+ }
+
+ if (try_mech) {
+ major = gss_pname_to_uid(&minor, intName,
+ NULL, uidOut);
+ if (major == GSS_S_COMPLETE) {
+
+ if (debug) {
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: mech provided local name"
+ " mapping (%s, %s, %d)", whoami,
+ mechStr ? mechStr : "<null>",
+ nameStr ? nameStr : "<null>",
+ *uidOut);
+ free(nameStr);
+ }
+
+ (void) gss_release_name(&minor, &intName);
if (gids && gidsLen && gidOut)
- return (gss_get_group_info(*uidOut, gidOut,
- gids, gidsLen));
+ return (gss_get_group_info(*uidOut,
+ gidOut,
+ gids,
+ gidsLen));
return (GSS_S_COMPLETE);
- (void) gss_release_buffer(&minor, &namebuf);
}
+ }
+
(void) gss_release_name(&minor, &intName);
- (void) gss_release_name(&minor, &intName);
}
/*
* we fall back onto the gsscred table to provide the mapping
* start by making sure that the expName is an export name buffer
*/
- return (private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut,
- gids, gidsLen));
+ major = private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut,
+ gids, gidsLen);
+
+ if (debug && major == GSS_S_COMPLETE) {
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: gsscred tbl provided"
+ " local name mapping (%s, %s, %d)",
+ whoami,
+ mechStr ? mechStr : "<unknown>",
+ nameStr ? nameStr : "<unknown>",
+ *uidOut);
+ free(nameStr);
+ } else if (debug) {
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: gsscred tbl could NOT"
+ " provide local name mapping (%s, %s)",
+ whoami,
+ mechStr ? mechStr : "<unknown>",
+ nameStr ? nameStr : "<unknown>");
+ free(nameStr);
+ }
+
+ return (major);
+
} /* gsscred_expname_to_unix_cred */
+OM_uint32
+gsscred_expname_to_unix_cred(
+ const gss_buffer_t expName,
+ uid_t *uidOut,
+ gid_t *gidOut,
+ gid_t *gids[],
+ int *gidsLen)
+{
+ return (gsscred_expname_to_unix_cred_ext(expName, uidOut, gidOut, gids,
+ gidsLen, 1));
+}
+
static const char *expNameTokId = "\x04\x01";
static const int expNameTokIdLen = 2;
/*
* private routine added to be called from gsscred_name_to_unix_cred
* and gsscred_expName_to_unix_cred.
@@ -107,48 +244,111 @@
return (GSS_S_COMPLETE);
}
/*
+ * Return a string of the authenticated name.
+ * It's a bit of hack/workaround/longroad but the current intName
+ * passed to gss_display_name insists on returning an empty string.
+ *
+ * Caller must free string memory.
+ */
+static
+char *make_name_str(
+ const gss_name_t intName,
+ const gss_OID mechType)
+
+{
+ gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
+ OM_uint32 major, minor;
+ gss_name_t canonName;
+ gss_name_t iName;
+ gss_buffer_desc namebuf;
+
+ if (major = gss_canonicalize_name(&minor, intName,
+ mechType, &canonName))
+ return (NULL);
+
+ major = gss_export_name(&minor, canonName, &expName);
(void) gss_release_name(&minor, &canonName);
+ if (major)
+ return (NULL);
+
+ if (gss_import_name(&minor, &expName,
+ (gss_OID)GSS_C_NT_EXPORT_NAME,
+ &iName) == GSS_S_COMPLETE) {
+
+ major = gss_display_name(&minor, iName, &namebuf, NULL);
+ if (major == GSS_S_COMPLETE) {
+ char *s;
+
+ if (namebuf.value)
+ s = strdup(namebuf.value);
+
(void) gss_release_buffer(&minor, &namebuf);
(void) gss_release_buffer(&minor, &expName);
(void) gss_release_buffer(&minor, (gss_buffer_t)iName);
+ return (s);
+ }
(void) gss_release_buffer(&minor, (gss_buffer_t)iName);
+ }
+
(void) gss_release_buffer(&minor, &expName);
+ return (NULL);
+}
+
+/*
* This routine accepts a name in gss internal name format together with
* a mechanim OID and retrieves a unix credentials for that entity.
*/
OM_uint32
-gsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids, gidsLen)
-const gss_name_t intName;
-const gss_OID mechType;
-uid_t *uidOut;
-gid_t *gidOut;
-gid_t *gids[];
-int *gidsLen;
+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)
{
gss_name_t canonName;
gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
OM_uint32 major, minor;
+ int debug = get_uid_map_opt();
+ const char *mechStr;
+ char *whoami = "gsscred_name_to_unix_cred";
+ gss_buffer_desc namebuf;
+
if (intName == NULL || mechType == NULL)
return (GSS_S_CALL_INACCESSIBLE_READ);
if (uidOut == NULL)
return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ mechStr = __gss_oid_to_mech(mechType);
+
/* first try the mechanism provided mapping */
- if (gss_pname_to_uid(&minor, intName, mechType, uidOut)
+ if (try_mech && gss_pname_to_uid(&minor, intName, mechType, uidOut)
== GSS_S_COMPLETE) {
+
+ if (debug) {
+ char *s = make_name_str(intName, mechType);
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: mech provided local name"
+ " mapping (%s, %s, %d)", whoami,
+ mechStr ? mechStr : "<null>",
+ s ? s : "<null>",
+ *uidOut);
+ free(s);
+ }
+
if (gids && gidsLen && gidOut)
return (gss_get_group_info(*uidOut, gidOut, gids,
gidsLen));
return (GSS_S_COMPLETE);
}
-
-
/*
* falling back onto the gsscred table to provide the mapping
* start by canonicalizing the passed in name and then export it
*/
if (major = gss_canonicalize_name(&minor, intName,
@@ -160,17 +360,70 @@
if (major)
return (major);
major = private_gsscred_expname_to_unix_cred(&expName, uidOut, gidOut,
gids, gidsLen);
+
+
+ if (debug) {
+ gss_name_t iName;
+ OM_uint32 maj;
+ char *nameStr = NULL;
+
+ if (gss_import_name(&minor, &expName,
+ (gss_OID)GSS_C_NT_EXPORT_NAME,
+ &iName) == GSS_S_COMPLETE) {
+
+ maj = gss_display_name(&minor, iName, &namebuf,
+ NULL);
(void) gss_release_buffer(&minor, (gss_buffer_t)iName);
+ if (maj == GSS_S_COMPLETE) {
+ nameStr = strdup(namebuf.value);
(void) gss_release_buffer(&minor, &namebuf);
+ }
+ }
+
+ if (major == GSS_S_COMPLETE)
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: gsscred tbl provided"
+ " local name mapping (%s, %s, %d)",
+ whoami,
+ mechStr ? mechStr : "<unknown>",
+ nameStr ? nameStr : "<unknown>",
+ *uidOut);
+ else
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: gsscred tbl could NOT"
+ " provide local name mapping (%s, %s)",
+ whoami,
+ mechStr ? mechStr : "<unknown>",
+ nameStr ? nameStr : "<unknown>");
+
+ free(nameStr);
+ }
+
(void) gss_release_buffer(&minor, &expName);
return (major);
} /* gsscred_name_to_unix_cred */
+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)
+{
+ return (gsscred_name_to_unix_cred_ext(intName, mechType,
+ uidOut, gidOut,
+ gids, gidsLen, 1));
+}
+
+
+
/*
* This routine accepts a unix uid, and retrieves the group id
* and supplamentery group ids for that uid.
* Callers should be aware that the supplamentary group ids
* array may be empty even when this function returns success.