Hi! Ubuntu has been carrying a patch against PAM to have a ~/.pam_environment file that is parsed for each user (which allows a way to set environment variables without regard to how a user logs in (ssh, gdm, etc)). I've included the patch below. Is this something that would be accepted into mainline PAM? Thanks, -Kees --- diff -uNrp Linux-PAM-0.99.8.1~/modules/pam_env/pam_env.c Linux-PAM-0.99.8.1/modules/pam_env/pam_env.c --- Linux-PAM-0.99.8.1~/modules/pam_env/pam_env.c 2005-12-12 06:45:00.000000000 -0800 +++ Linux-PAM-0.99.8.1/modules/pam_env/pam_env.c 2007-09-10 12:21:14.657766129 -0700 @@ -11,6 +11,9 @@ #define DEFAULT_ETC_ENVFILE "/etc/environment" #define DEFAULT_READ_ENVFILE 1 +#define DEFAULT_USER_ENVFILE ".pam_environment" +#define DEFAULT_USER_READ_ENVFILE 1 + #include "config.h" #include <ctype.h> @@ -75,16 +78,20 @@ static char quote='Z'; /* argument parsing */ #define PAM_DEBUG_ARG 0x01 -#define PAM_NEW_CONF_FILE 0x02 -#define PAM_ENV_SILENT 0x04 -#define PAM_NEW_ENV_FILE 0x10 static int _pam_parse (const pam_handle_t *pamh, int argc, const char **argv, - const char **conffile, const char **envfile, int *readenv) + char **conffile, char **envfile, int *readenv, + int *user_read_env, char **user_env_file) { int ctrl=0; + /* handle out of memory ; fixme */ + *user_env_file = strdup(DEFAULT_USER_ENVFILE); + *envfile = strdup(DEFAULT_ETC_ENVFILE); + *readenv = DEFAULT_READ_ENVFILE; + *user_read_env = DEFAULT_USER_READ_ENVFILE; + *conffile = strdup(DEFAULT_CONF_FILE); /* step through arguments */ for (; argc-- > 0; ++argv) { @@ -94,25 +101,36 @@ _pam_parse (const pam_handle_t *pamh, in if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; else if (!strncmp(*argv,"conffile=",9)) { - *conffile = 9 + *argv; - if (**conffile != '\0') { - D(("new Configuration File: %s", *conffile)); - ctrl |= PAM_NEW_CONF_FILE; - } else { + if (*argv+9 == '\0') { pam_syslog(pamh, LOG_ERR, "conffile= specification missing argument - ignored"); + } else { + free(*conffile); + *conffile = x_strdup(9+*argv); + D(("new Configuration File: %s", *conffile)); } } else if (!strncmp(*argv,"envfile=",8)) { - *envfile = 8 + *argv; - if (**envfile != '\0') { - D(("new Env File: %s", *envfile)); - ctrl |= PAM_NEW_ENV_FILE; - } else { + if (*argv+8 == '\0') { pam_syslog (pamh, LOG_ERR, "envfile= specification missing argument - ignored"); + } else { + free(*envfile); + *envfile = x_strdup(8+*argv); + D(("new Env File: %s", *envfile)); + } + } else if (!strncmp(*argv,"user_env_file=",13)) { + if (*argv+13 == '\0') { + pam_syslog (pamh, LOG_ERR, + "user_env_file= specification missing argument - ignored"); + } else { + free(*user_env_file); + *user_env_file = x_strdup(13+*argv); + D(("new User Env File: %s", *user_env_file)); } } else if (!strncmp(*argv,"readenv=",8)) *readenv = atoi(8+*argv); + else if (!strncmp(*argv,"user_readenv=",13)) + *user_read_env = atoi(13+*argv); else pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); } @@ -121,10 +139,9 @@ _pam_parse (const pam_handle_t *pamh, in } static int -_parse_config_file(pam_handle_t *pamh, int ctrl, const char *conffile) +_parse_config_file(pam_handle_t *pamh, const char *file) { int retval; - const char *file; char buffer[BUF_SIZE]; FILE *conf; VAR Var, *var=&Var; @@ -132,12 +149,6 @@ _parse_config_file(pam_handle_t *pamh, i var->name=NULL; var->defval=NULL; var->override=NULL; D(("Called.")); - if (ctrl & PAM_NEW_CONF_FILE) { - file = conffile; - } else { - file = DEFAULT_CONF_FILE; - } - D(("Config file name is: %s", file)); /* @@ -184,18 +195,12 @@ _parse_config_file(pam_handle_t *pamh, i } static int -_parse_env_file(pam_handle_t *pamh, int ctrl, const char *env_file) +_parse_env_file(pam_handle_t *pamh, const char *file) { int retval=PAM_SUCCESS, i, t; - const char *file; char buffer[BUF_SIZE], *key, *mark; FILE *conf; - if (ctrl & PAM_NEW_ENV_FILE) - file = env_file; - else - file = DEFAULT_ETC_ENVFILE; - D(("Env file name is: %s", file)); if ((conf = fopen(file,"r")) == NULL) { @@ -738,23 +743,52 @@ pam_sm_setcred (pam_handle_t *pamh, int int argc, const char **argv) { int retval, ctrl, readenv=DEFAULT_READ_ENVFILE; - const char *conf_file = NULL, *env_file = NULL; + int read_user_env = DEFAULT_USER_READ_ENVFILE; + char *conf_file = NULL, *env_file = NULL, *user_env_file = NULL; /* * this module sets environment variables read in from a file */ D(("Called.")); - ctrl = _pam_parse(pamh, argc, argv, &conf_file, &env_file, &readenv); + ctrl = _pam_parse(pamh, argc, argv, &conf_file, &env_file, &readenv, + &read_user_env, &user_env_file); - retval = _parse_config_file(pamh, ctrl, conf_file); + retval = _parse_config_file(pamh, conf_file); if(readenv && retval == PAM_SUCCESS) { - retval = _parse_env_file(pamh, ctrl, env_file); + retval = _parse_env_file(pamh, env_file); if (retval == PAM_IGNORE) retval = PAM_SUCCESS; } + if(read_user_env && retval == PAM_SUCCESS) { + char *envpath = NULL; + struct passwd *user_entry; + const char *username; + struct stat statbuf; + + username = _pam_get_item_byname(pamh, "PAM_USER"); + + user_entry = getpwnam(username); + if (!user_entry) { + pam_syslog(pamh, LOG_ERR, "No such user!?"); + } + else { + if (!(envpath = malloc(strlen(user_entry->pw_dir) + 1 + strlen(user_env_file) + 1))) { + pam_syslog(pamh, LOG_ERR, "Malloc failed"); + return PAM_BUF_ERR; + } + sprintf(envpath, "%s/%s", user_entry->pw_dir, user_env_file); + if (stat(envpath, &statbuf) == 0) { + retval = _parse_config_file(pamh, envpath); + if (retval == PAM_IGNORE) + retval = PAM_SUCCESS; + } + free(envpath); + } + } + /* indicate success or failure */ D(("Exit.")); @@ -773,28 +807,9 @@ PAM_EXTERN int pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { - int retval, ctrl, readenv=DEFAULT_READ_ENVFILE; - const char *conf_file = NULL, *env_file = NULL; - - /* - * this module sets environment variables read in from a file - */ - - D(("Called.")); - ctrl = _pam_parse(pamh, argc, argv, &conf_file, &env_file, &readenv); - - retval = _parse_config_file(pamh, ctrl, conf_file); - - if(readenv && retval == PAM_SUCCESS) { - retval = _parse_env_file(pamh, ctrl, env_file); - if (retval == PAM_IGNORE) - retval = PAM_SUCCESS; - } - - /* indicate success or failure */ - - D(("Exit.")); - return retval; + /* Function was identical to pam_sm_setcred, so call it instead */ + D(("Called -- calling pam_sm_setcred instead...")); + return pam_sm_setcred(pamh, flags, argc, argv); } PAM_EXTERN int -- Kees Cook _______________________________________________ Pam-list mailing list Pam-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/pam-list