summaryrefslogtreecommitdiff
path: root/modules/pam_env/pam_env.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_env/pam_env.c')
-rw-r--r--modules/pam_env/pam_env.c175
1 files changed, 102 insertions, 73 deletions
diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c
index 1a41833c..395ada21 100644
--- a/modules/pam_env/pam_env.c
+++ b/modules/pam_env/pam_env.c
@@ -1,8 +1,6 @@
/* pam_env module */
/*
- * $Id: pam_env.c,v 1.13 2005/12/12 14:45:00 ldv Exp $
- *
* Written by Dave Kinchlea <kinch@kinch.ark.com> 1997/01/31
* Inspired by Andrew Morgan <morgan@kernel.org>, who also supplied the
* template for this file (via pam_mail)
@@ -11,6 +9,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>
@@ -38,6 +39,7 @@
#define PAM_SM_ACCOUNT /* "" */
#include <security/pam_modules.h>
+#include <security/pam_modutil.h>
#include <security/_pam_macros.h>
#include <security/pam_ext.h>
@@ -75,16 +77,19 @@ 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)
+ const char **conffile, const char **envfile, int *readenv,
+ const char **user_envfile, int *user_readenv)
{
int ctrl=0;
+ *user_envfile = DEFAULT_USER_ENVFILE;
+ *envfile = DEFAULT_ETC_ENVFILE;
+ *readenv = DEFAULT_READ_ENVFILE;
+ *user_readenv = DEFAULT_USER_READ_ENVFILE;
+ *conffile = DEFAULT_CONF_FILE;
/* step through arguments */
for (; argc-- > 0; ++argv) {
@@ -94,49 +99,51 @@ _pam_parse (const pam_handle_t *pamh, int argc, const char **argv,
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 {
- pam_syslog(pamh, LOG_ERR,
- "conffile= specification missing argument - ignored");
- }
+ if (*argv+9 == '\0') {
+ pam_syslog(pamh, LOG_ERR,
+ "conffile= specification missing argument - ignored");
+ } else {
+ *conffile = 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 {
- pam_syslog (pamh, LOG_ERR,
- "envfile= specification missing argument - ignored");
- }
+ if (*argv+8 == '\0') {
+ pam_syslog (pamh, LOG_ERR,
+ "envfile= specification missing argument - ignored");
+ } else {
+ *envfile = 8+*argv;
+ D(("new Env File: %s", *envfile));
+ }
+ } else if (!strncmp(*argv,"user_envfile=",13)) {
+ if (*argv+13 == '\0') {
+ pam_syslog (pamh, LOG_ERR,
+ "user_envfile= specification missing argument - ignored");
+ } else {
+ *user_envfile = 13+*argv;
+ D(("new User Env File: %s", *user_env_file));
+ }
} else if (!strncmp(*argv,"readenv=",8))
- *readenv = atoi(8+*argv);
+ *readenv = atoi(8+*argv);
+ else if (!strncmp(*argv,"user_readenv=",13))
+ *user_readenv = atoi(13+*argv);
else
- pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
+ pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
}
return ctrl;
}
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;
- var->name=NULL; var->defval=NULL; var->override=NULL;
D(("Called."));
- if (ctrl & PAM_NEW_CONF_FILE) {
- file = conffile;
- } else {
- file = DEFAULT_CONF_FILE;
- }
+ var->name=NULL; var->defval=NULL; var->override=NULL;
D(("Config file name is: %s", file));
@@ -184,18 +191,12 @@ _parse_config_file(pam_handle_t *pamh, int ctrl, const char *conffile)
}
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) {
@@ -211,7 +212,7 @@ _parse_env_file(pam_handle_t *pamh, int ctrl, const char *env_file)
key += strspn(key, " \n\t");
/* skip blanks lines and comments */
- if (!key || key[0] == '#')
+ if (key[0] == '#')
continue;
/* skip over "export " if present so we can be compat with
@@ -232,9 +233,14 @@ _parse_env_file(pam_handle_t *pamh, int ctrl, const char *env_file)
for ( i = 0 ; key[i] != '=' && key[i] != '\0' ; i++ )
if (!isalnum(key[i]) && key[i] != '_') {
- D(("key is not alpha numeric - '%s', ignoring", key));
- continue;
+ pam_syslog(pamh, LOG_ERR,
+ "non-alphanumeric key '%s' in %s', ignoring",
+ key, file);
+ break;
}
+ /* non-alphanumeric key, ignore this line */
+ if (key[i] != '=' && key[i] != '\0')
+ continue;
/* now we try to be smart about quotes around the value,
but not too smart, we can't get all fancy with escaped
@@ -248,6 +254,14 @@ _parse_env_file(pam_handle_t *pamh, int ctrl, const char *env_file)
key[i] = '\0';
}
+ /* if this is a request to delete a variable, check that it's
+ actually set first, so we don't get a vague error back from
+ pam_putenv() */
+ for (i = 0; key[i] != '=' && key[i] != '\0'; i++);
+
+ if (key[i] == '\0' && !pam_getenv(pamh,key))
+ continue;
+
/* set the env var, if it fails, we break out of the loop */
retval = pam_putenv(pamh, key);
if (retval != PAM_SUCCESS) {
@@ -689,7 +703,7 @@ static int _define_var(pam_handle_t *pamh, VAR *var)
pam_syslog(pamh, LOG_ERR, "out of memory");
return PAM_BUF_ERR;
}
-
+
retval = pam_putenv(pamh, envvar);
_pam_drop(envvar);
D(("Exit."));
@@ -733,30 +747,57 @@ pam_sm_authenticate (pam_handle_t *pamh UNUSED, int flags UNUSED,
return PAM_IGNORE;
}
-PAM_EXTERN int
-pam_sm_setcred (pam_handle_t *pamh, int flags UNUSED,
- int argc, const char **argv)
+static int
+handle_env (pam_handle_t *pamh, int argc, const char **argv)
{
int retval, ctrl, readenv=DEFAULT_READ_ENVFILE;
- const char *conf_file = NULL, *env_file = NULL;
+ int user_readenv = DEFAULT_USER_READ_ENVFILE;
+ const 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, &user_env_file, &user_readenv);
- 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;
}
- /* indicate success or failure */
+ if(user_readenv && 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 = pam_modutil_getpwnam (pamh, username);
+ if (!user_entry) {
+ pam_syslog(pamh, LOG_ERR, "No such user!?");
+ }
+ else {
+ if (asprintf(&envpath, "%s/%s", user_entry->pw_dir, user_env_file) < 0)
+ {
+ pam_syslog(pamh, LOG_ERR, "Out of memory");
+ return PAM_BUF_ERR;
+ }
+ 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."));
return retval;
}
@@ -770,31 +811,19 @@ pam_sm_acct_mgmt (pam_handle_t *pamh UNUSED, int flags UNUSED,
}
PAM_EXTERN int
+pam_sm_setcred (pam_handle_t *pamh, int flags UNUSED,
+ int argc, const char **argv)
+{
+ D(("Called"));
+ return handle_env (pamh, argc, argv);
+}
+
+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;
+ D(("Called"));
+ return handle_env (pamh, argc, argv);
}
PAM_EXTERN int