pam_env: per-user environment file?
Kees Cook
kees at ubuntu.com
Mon Sep 10 19:23:26 UTC 2007
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
More information about the Pam-list
mailing list