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>