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.