Subject: login.conf and xdm
To: None <tech-x11@NetBSD.org>
From: Patrick Welche <prlw1@newn.cam.ac.uk>
List: tech-x11
Date: 12/20/2005 19:01:29
--T4sUOijqQbZv57TR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

The following patch seems to work for me - I haven't tested the src/x11
reachover build (as my setup is currently broken: I haven't finished the
src/x11 equivalent of HasFreetype2)

Basically, path and environment variables set in login.conf are thrown
away by xdm even if setusercontext is called. Another method might be
to call setusercontext, and then copy the newly set environment into
verify->userEnviron instead of duplicating code from login_cap.c, but
I prefer the idea of update/add rather than delete/add.

Anyone care to check/commit?

Cheers,

Patrick

--T4sUOijqQbZv57TR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=loginpat

Index: xdm/session.c
===================================================================
RCS file: /cvsnetbsd/xsrc/xfree/xc/programs/xdm/session.c,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 session.c
--- xdm/session.c	18 Mar 2005 13:09:18 -0000	1.1.1.7
+++ xdm/session.c	20 Dec 2005 18:42:55 -0000
@@ -123,6 +123,119 @@
 }
 #endif
 
+#ifdef HAS_SETUSERCONTEXT
+/* Copied wholesale from NetBSD libutil/login_cap.c v1.22,
+ * just modified to set userEnviron rather than real environment.
+ */
+static void
+setuserpath(struct verify_info *verify, login_cap_t *lc, const char *home)
+{
+    size_t hlen, plen;
+    int cnt = 0;
+    char *path, *cpath, *defpath;
+    char *p, *q; 
+
+    if (home == NULL) return;
+
+    hlen = strlen(home);
+
+    defpath = getEnv(verify->userEnviron, "PATH");
+
+    p = path = login_getcapstr(lc, "path", NULL, NULL);
+    if (p) {
+        while (*p)
+            if (*p++ == '~')
+                ++cnt;
+        plen = (p - path) + cnt * (hlen + 1) + 1; 
+        p = path; 
+        q = path = malloc(plen);
+        if (q) {
+            while (*p) {
+                p += strspn(p, " \t");
+                if (*p == '\0') 
+                    break;
+                plen = strcspn(p, " \t");
+                if (hlen == 0 && *p == '~') { 
+                    p += plen;
+                    continue;
+                }
+                if (q != path)  
+                    *q++ = ':';
+                if (*p == '~') {
+                    strcpy(q, home);    
+                    q += hlen;
+                    ++p;
+                    --plen;
+                }
+                memcpy(q, p, plen);
+                p += plen;      
+                q += plen;      
+            }
+            *q = '\0';  
+            cpath = path;
+        } else  
+            cpath = defpath;
+    } else
+        cpath = defpath;
+
+    verify->userEnviron = setEnv(verify->userEnviron, "PATH", cpath);
+}
+
+static int
+setuserenv(struct verify_info *verify, login_cap_t *lc)
+{
+    const char *stop = ", \t";
+    int i, count;
+    char *ptr;
+    char **res;
+    char *str = login_getcapstr(lc, "setenv", NULL, NULL);
+
+    if (str == NULL || *str == '\0')
+        return 0;
+   
+    /* count the sub-strings */
+    for (i = 1, ptr = str; *ptr; i++) {
+        ptr += strcspn(ptr, stop);
+        if (*ptr)
+            ptr++;
+    }
+        
+    /* allocate ptr array and string */
+    count = i;
+    res = malloc(count * sizeof(char *) + strlen(str) + 1);
+
+    if (!res)  
+        return -1;
+   
+    ptr = (char *)(void *)res + count * sizeof(char *);
+    strcpy(ptr, str);
+    
+    /* split string */
+    for (i = 0; *ptr && i < count; i++) {
+        res[i] = ptr;
+        ptr += strcspn(ptr, stop);
+        if (*ptr)
+            *ptr++ = '\0';
+    }
+    
+    res[i] = NULL;
+
+    for (i = 0; i < count && res[i]; i++) {
+        if (*res[i] != '\0') {
+            if ((ptr = strchr(res[i], '=')) != NULL)
+                *ptr++ = '\0';
+            else
+                ptr = NULL;
+            verify->userEnviron =
+		setEnv(verify->userEnviron, res[i], ptr ? ptr : "");
+        }
+    }
+    
+    free(res);
+    return 0;
+}
+#endif
+
 static	struct dlfuncs	dlfuncs = {
 	PingServer,
 	SessionPingFailed,
@@ -531,7 +644,8 @@
     char	*failsafeArgv[2];
     int	pid;
 #ifdef HAS_SETUSERCONTEXT
-    struct passwd* pwd;
+    struct passwd *pwd;
+    login_cap_t *lc;
 #endif
 #ifdef USE_PAM
     pam_handle_t *pamh = thepamh ();
@@ -615,11 +729,20 @@
 	 */
 	pwd = getpwnam(name);
 	if (pwd) {
-	    if (setusercontext(NULL, pwd, pwd->pw_uid, LOGIN_SETALL) < 0) {
+	    lc = login_getclass(pwd->pw_class);
+	    if (lc == NULL) {
+		LogError ("login_class for \"%s\" not found\n",
+		    pwd->pw_class?pwd->pw_class:"default");
+		return (0);
+	    }
+	    if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETALL) < 0) {
 		LogError ("setusercontext for \"%s\" failed, errno=%d\n", name,
 		    errno);
 		return (0);
 	    }
+            setuserpath(verify, lc, pwd ? pwd->pw_dir : "");
+	    setuserenv (verify, lc);
+	    login_close(lc);
 	    endpwent();
 	} else {
 	    LogError ("getpwnam for \"%s\" failed, errno=%d\n", name, errno);
Index: xterm/main.c
===================================================================
RCS file: /cvsnetbsd/xsrc/xfree/xc/programs/xterm/main.c,v
retrieving revision 1.10
diff -u -r1.10 main.c
--- xterm/main.c	18 Mar 2005 14:55:18 -0000	1.10
+++ xterm/main.c	20 Dec 2005 18:43:24 -0000
@@ -214,6 +214,9 @@
 #endif
 #endif
 
+/*
+ * now get system-specific includes
+ */
 #ifdef SYSV			/* { */
 
 #ifdef USE_USG_PTYS		/* AT&T SYSV has no ptyio.h */
@@ -228,9 +231,6 @@
 #define USE_SYSV_ENVVARS	/* COLUMNS/LINES vs. TERMCAP */
 #endif
 
-/*
- * now get system-specific includes
- */
 #ifdef CRAY
 #define HAS_BSD_GROUPS
 #endif
Index: config/cf/NetBSD.cf
===================================================================
RCS file: /cvsnetbsd/xsrc/xfree/xc/config/cf/NetBSD.cf,v
retrieving revision 1.82
diff -u -r1.82 NetBSD.cf
--- config/cf/NetBSD.cf	12 Nov 2005 22:47:53 -0000	1.82
+++ config/cf/NetBSD.cf	20 Dec 2005 18:47:50 -0000
@@ -1012,3 +1012,7 @@
 # endif
 #endif
 
+/* NetBSD >= 1.5 has setusercontext() */
+#if OSMajorVersion == 1 && OSMinorVersion >= 5 || OSMajorVersion > 1
+#define HasSetUserContext       YES
+#endif
Index: bin/xdm/Makefile.xdm
===================================================================
RCS file: /cvsroot/src/x11/bin/xdm/Makefile.xdm,v
retrieving revision 1.11
diff -u -r1.11 Makefile.xdm
--- bin/xdm/Makefile.xdm	9 May 2005 16:15:49 -0000	1.11
+++ bin/xdm/Makefile.xdm	20 Dec 2005 18:49:08 -0000
@@ -10,10 +10,12 @@
 CPPFLAGS+=	-DBINDIR=\"${X11BINDIR}\" -DXDMDIR=\"${XDMDIR}\" \
 		-DHASXDMAUTH ${X11FLAGS.CONNECTION} -DGREET_USER_STATIC \
 		-DFRAGILE_DEV_MEM -DARC4_RANDOM \
-		-DXPM -DUSE_XINERAMA -DHAS_SETPROCTITLE \
+		-DXPM -DUSE_XINERAMA -DHAS_SETPROCTITLE -DHAS_SETUSERCONTEXT \
 		-DHAS_GETIFADDRS -UIPv6 -DHAS_MKSTEMP \
 		-I${X11SRCDIR.xc}/programs/xdm \
 		${X11FLAGS.VERSION}
+LDADD+=		-lutil
+DPADD+=		${LIBUTIL}
 
 .if (${USE_PAM} != "no")
 CPPFLAGS+=	-DUSE_PAM

--T4sUOijqQbZv57TR--