Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 Sep 1999 16:53:11 +0700 (NSS)
From:      Max Khon <fjoe@iclub.nsu.ru>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   ports/13614: xdm and wdm do not set environment variables defined in login.conf
Message-ID:  <199909070953.QAA06275@iclub.nsu.ru>

next in thread | raw e-mail | index | archive | help

>Number:         13614
>Category:       ports
>Synopsis:       xdm and wdm do not set environment variables defined in login.conf
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-ports
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Sep  7 03:00:02 PDT 1999
>Closed-Date:
>Last-Modified:
>Originator:     Max Khon
>Release:        FreeBSD 3.2-STABLE i386
>Organization:
WebSci Technologies Inc.
>Environment:

	FreeBSD 3.3-RC, XFree86 3.3.2/3.3.5, wdm-1.0 (optional)

>Description:

	xdm (wdm) is compiled under FreeBSD with HAS_SETUSERCONTEXT
	defined so it uses `setusercontext'.

	But xdm (and also wdm as it uses xdm code almost unchanged)
	builds environment list by hand and uses `execve' to
	execute `DisplayManager*session' program so environment
	changes made in `setusercontext' do not affect X-sessions
	started from display manager.

>How-To-Repeat:

	Try to set something using `charset', `lang', `path', `setenv'
	in login.conf. Sessions started from xdm (wdm) will not be affected.

>Fix:
	
	The following patch adds missing functionality.

	The patch applies cleanly to xdm from XFree86-3.3.2
	(wdm-1.0 uses xdm from that release) and can also be applied
	seamlessly to xdm from 3.3.5.

--- session.c.orig	Tue Sep  7 14:22:02 1999
+++ session.c	Tue Sep  7 15:45:13 1999
@@ -487,6 +487,149 @@
     exit (status);
 }
 
+#ifdef HAS_SETUSERCONTEXT
+/*
+ * copied from
+ * $FreeBSD: src/lib/libutil/login_class.c,v 1.10.2.2 1999/08/29 14:57:53 peter Exp $
+ */
+
+#undef	UNKNOWN
+#define	UNKNOWN	"su"
+
+static struct login_vars {
+    const char *tag;
+    const char *var;
+    const char *def;
+} pathvars[] = {
+    { "path",		"PATH",	      NULL    },
+    { "cdpath",		"CDPATH",     NULL    },
+    { "manpath",	"MANPATH",    NULL    },
+    { NULL,		NULL,	      NULL    }
+}, envars[] = {
+    { "lang",		"LANG",	      NULL    },
+    { "charset",	"MM_CHARSET", NULL    },
+    { "timezone",	"TZ",	      NULL    },
+    { "term",		"TERM",       UNKNOWN },
+    { NULL,		NULL,	      NULL    }
+};
+
+static char *
+substvar(char * var, const struct passwd * pwd, int hlen, int pch, int nlen)
+{
+    char    *np = NULL;
+
+    if (var != NULL) {
+	int	tildes = 0;
+	int	dollas = 0;
+	char	*p;
+
+	if (pwd != NULL) {
+	    /* Count the number of ~'s in var to substitute */
+	    p = var;
+	    for (p = var; (p = strchr(p, '~')) != NULL; p++)
+		++tildes;
+	    /* Count the number of $'s in var to substitute */
+	    p = var;
+	    for (p = var; (p = strchr(p, '$')) != NULL; p++)
+		++dollas;
+	}
+
+	np = malloc(strlen(var) + (dollas * nlen)
+		    - dollas + (tildes * (pch+hlen))
+		    - tildes + 1);
+
+	if (np != NULL) {
+	    p = strcpy(np, var);
+
+	    if (pwd != NULL) {
+		/*
+		 * This loop does user username and homedir substitutions
+		 * for unescaped $ (username) and ~ (homedir)
+		 */
+		while (*(p += strcspn(p, "~$")) != '\0') {
+		    int	l = strlen(p);
+
+		    if (p > np && *(p-1) == '\\')  /* Escaped: */
+			memmove(p - 1, p, l + 1); /* Slide-out the backslash */
+		    else if (*p == '~') {
+			int	v = pch && *(p+1) != '/'; /* Avoid double // */
+			memmove(p + hlen + v, p + 1, l);  /* Subst homedir */
+			memmove(p, pwd->pw_dir, hlen);
+			if (v)
+			    p[hlen] = '/';
+			p += hlen + v;
+		    }
+		    else /* if (*p == '$') */ {
+			memmove(p + nlen, p + 1, l);	/* Subst username */
+			memmove(p, pwd->pw_name, nlen);
+			p += nlen;
+		    }
+		}
+	    }
+	}
+    }
+
+    return np;
+}
+
+
+void
+setclassEnvironment(login_cap_t *lc, const struct passwd * pwd, int paths,
+		    struct verify_info *verify)
+{
+    char *getEnv ();
+    struct login_vars	*vars = paths ? pathvars : envars;
+    int			hlen = pwd ? strlen(pwd->pw_dir) : 0;
+    int			nlen = pwd ? strlen(pwd->pw_name) : 0;
+    char pch = 0;
+
+    if (hlen && pwd->pw_dir[hlen-1] != '/')
+	++pch;
+
+    while (vars->tag != NULL) {
+	char * var = paths ? login_getpath(lc, vars->tag, NULL)
+	    		   : login_getcapstr(lc, vars->tag, NULL, NULL);
+
+	char * np  = substvar(var, pwd, hlen, pch, nlen);
+
+	if (np != NULL) {
+	    verify->userEnviron = setEnv(verify->userEnviron, vars->var, np);
+	    free(np);
+	} else if (vars->def != NULL) {
+	    if (getEnv(verify->userEnviron, vars->var) == NULL)
+		setEnv(verify->userEnviron, vars->var, vars->def);
+	}
+	++vars;
+    }
+
+    /*
+     * If we're not processing paths, then see if there is a setenv list by
+     * which the admin and/or user may set an arbitrary set of env vars.
+     */
+    if (!paths) {
+	char	**set_env = login_getcaplist(lc, "setenv", ",");
+
+	if (set_env != NULL) {
+	    while (*set_env != NULL) {
+		char	*p = strchr(*set_env, '=');
+
+		if (p != NULL) {  /* Discard invalid entries */
+		    char	*np;
+
+		    *p++ = '\0';
+		    if ((np = substvar(p, pwd, hlen, pch, nlen)) != NULL) {
+	    	        verify->userEnviron = setEnv(verify->userEnviron,
+						     *set_env, np);
+			free(np);
+		    }
+		}
+		++set_env;
+	    }
+	}
+    }
+}
+#endif
+
 static Bool
 StartClient (verify, d, pidp, name, passwd)
     struct verify_info	*verify;
@@ -559,12 +702,26 @@
 	pwd = getpwnam(name);
 	if (pwd)
 	{
-	    if (setusercontext(NULL, pwd, pwd->pw_uid, LOGIN_SETALL) < 0)
-	    {
-		LogError("setusercontext for \"%s\" failed, errno=%d\n", name,
-			 errno);
-		return(0);
+    	    login_cap_t *lc;
+	
+	    lc = login_getpwclass(pwd);
+	    if (setusercontext(lc, pwd, pwd->pw_uid,
+		LOGIN_SETALL & ~(LOGIN_SETPATH | LOGIN_SETENV)) < 0) {
+		    LogError("setusercontext for \"%s\" failed, errno=%d\n",
+			     name, errno);
+		    login_close(lc);
+		    return(0);
+	    }
+	    setclassEnvironment(lc, pwd, 1, verify);
+	    setclassEnvironment(lc, pwd, 0, verify);
+	    login_close(lc);
+
+	    if ((lc = login_getuserclass(pwd)) != NULL) {
+	        setclassEnvironment(lc, pwd, 1, verify);
+	        setclassEnvironment(lc, pwd, 0, verify);
+		login_close(lc);
 	    }
+
 	    endpwent();
 	}
 	else

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ports" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199909070953.QAA06275>