From e359d4ad55858b6440f5077d632f14249137add4 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 8 Apr 2008 07:01:41 +0000 Subject: Relevant BUGIDs: Purpose of commit: cleanup Commit summary: --------------- 2008-04-08 Tomas Mraz * modules/pam_xauth/pam_xauth.c(run_coprocess): Avoid multiple calls to sysconf() (based on patch by Sami Farin). --- modules/pam_xauth/pam_xauth.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_xauth/pam_xauth.c b/modules/pam_xauth/pam_xauth.c index 1135d4b7..36f30708 100644 --- a/modules/pam_xauth/pam_xauth.c +++ b/modules/pam_xauth/pam_xauth.c @@ -118,6 +118,7 @@ run_coprocess(const char *input, char **output, size_t j; char *args[10]; const char *tmp; + int maxopened; /* Drop privileges. */ setgid(gid); setgroups(0, NULL); @@ -129,7 +130,8 @@ run_coprocess(const char *input, char **output, * descriptors. */ dup2(ipipe[0], STDIN_FILENO); dup2(opipe[1], STDOUT_FILENO); - for (i = 0; i < sysconf(_SC_OPEN_MAX); i++) { + maxopened = (int)sysconf(_SC_OPEN_MAX); + for (i = 0; i < maxopened; i++) { if ((i != STDIN_FILENO) && (i != STDOUT_FILENO)) { close(i); } -- cgit v1.2.3 From 71ef5e4a1c83fed2bb6f9753afc6a8a7c81ee0ba Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Wed, 16 Apr 2008 07:50:09 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-04-16 Tomas Mraz * modules/pam_unix/Makefile.am: Link unix_chkpwd with libaudit. * modules/pam_unix/unix_chkpwd.c(_audit_log): New function for audit. (main): Call _audit_log() when appropriate. --- modules/pam_unix/Makefile.am | 2 +- modules/pam_unix/unix_chkpwd.c | 48 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 4 deletions(-) (limited to 'modules') diff --git a/modules/pam_unix/Makefile.am b/modules/pam_unix/Makefile.am index 61a3b0ce..c4f746c9 100644 --- a/modules/pam_unix/Makefile.am +++ b/modules/pam_unix/Makefile.am @@ -50,7 +50,7 @@ unix_chkpwd_SOURCES = unix_chkpwd.c md5_good.c md5_broken.c bigcrypt.c \ passverify.c unix_chkpwd_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ -DHELPER_COMPILE=\"unix_chkpwd\" unix_chkpwd_LDFLAGS = @PIE_LDFLAGS@ -unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@ +unix_chkpwd_LDADD = @LIBCRYPT@ @LIBSELINUX@ @LIBAUDIT@ unix_update_SOURCES = unix_update.c md5_good.c md5_broken.c bigcrypt.c \ passverify.c diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c index 5f872d27..b4f9b3df 100644 --- a/modules/pam_unix/unix_chkpwd.c +++ b/modules/pam_unix/unix_chkpwd.c @@ -24,6 +24,10 @@ #include #include #include +#include +#ifdef HAVE_LIBAUDIT +#include +#endif #include #include @@ -54,6 +58,37 @@ static int _check_expiry(const char *uname) return retval; } +static int _audit_log(int type, const char *uname, int rc) +{ +#ifdef HAVE_LIBAUDIT + int audit_fd; + + audit_fd = audit_open(); + if (audit_fd < 0) { + /* You get these error codes only when the kernel doesn't have + * audit compiled in. */ + if (errno == EINVAL || errno == EPROTONOSUPPORT || + errno == EAFNOSUPPORT) + return PAM_SUCCESS; + + helper_log_err(LOG_CRIT, "audit_open() failed: %m"); + return PAM_AUTH_ERR; + } + + rc = audit_log_acct_message(audit_fd, type, NULL, "PAM:unix_chkpwd", + uname, -1, NULL, NULL, NULL, rc == PAM_SUCCESS); + if (rc == -EPERM && geteuid() != 0) { + rc = 0; + } + + audit_close(audit_fd); + + return rc < 0 ? PAM_AUTH_ERR : PAM_SUCCESS; +#else + return PAM_SUCCESS; +#endif +} + int main(int argc, char *argv[]) { char pass[MAXPASS + 1]; @@ -82,6 +117,7 @@ int main(int argc, char *argv[]) helper_log_err(LOG_NOTICE ,"inappropriate use of Unix helper binary [UID=%d]" ,getuid()); + _audit_log(AUDIT_ANOM_EXEC, getuidname(getuid()), PAM_SYSTEM_ERR); fprintf(stderr ,"This binary is not designed for running in this way\n" "-- the system administrator has been informed\n"); @@ -118,9 +154,10 @@ int main(int argc, char *argv[]) nullok = 1; else if (strcmp(option, "nonull") == 0) nullok = 0; - else + else { + _audit_log(AUDIT_ANOM_EXEC, getuidname(getuid()), PAM_SYSTEM_ERR); return PAM_SYSTEM_ERR; - + } /* read the password from stdin (a pipe from the pam_unix module) */ npass = read_passwords(STDIN_FILENO, 1, passwords); @@ -141,11 +178,16 @@ int main(int argc, char *argv[]) /* return pass or fail */ if (retval != PAM_SUCCESS) { - if (!nullok || !blankpass) + if (!nullok || !blankpass) { /* no need to log blank pass test */ + if (getuid() != 0) + _audit_log(AUDIT_USER_AUTH, user, PAM_AUTH_ERR); helper_log_err(LOG_NOTICE, "password check failed for user (%s)", user); + } return PAM_AUTH_ERR; } else { + if (getuid() != 0) + return _audit_log(AUDIT_USER_AUTH, user, PAM_SUCCESS); return PAM_SUCCESS; } } -- cgit v1.2.3 From 3165b29623e3498f8e75dba5413c4a662bdcec15 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Wed, 16 Apr 2008 08:21:05 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-04-16 Tomas Mraz * modules/pam_cracklib/pam_cracklib.c(_pam_parse): Recognize also try_first_pass and use_first_pass options. (pam_sm_chauthtok): Implement the new options. --- modules/pam_cracklib/pam_cracklib.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'modules') diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c index 0c39f89d..12cbcf3c 100644 --- a/modules/pam_cracklib/pam_cracklib.c +++ b/modules/pam_cracklib/pam_cracklib.c @@ -98,6 +98,7 @@ struct cracklib_options { int oth_credit; int min_class; int use_authtok; + int try_first_pass; char prompt_type[BUFSIZ]; const char *cracklib_dictpath; }; @@ -169,6 +170,10 @@ _pam_parse (pam_handle_t *pamh, struct cracklib_options *opt, opt->min_class = 4 ; } else if (!strncmp(*argv,"use_authtok",11)) { opt->use_authtok = 1; + } else if (!strncmp(*argv,"use_first_pass",14)) { + opt->use_authtok = 1; + } else if (!strncmp(*argv,"try_first_pass",14)) { + opt->try_first_pass = 1; } else if (!strncmp(*argv,"dictpath=",9)) { opt->cracklib_dictpath = *argv+9; if (!*(opt->cracklib_dictpath)) { @@ -619,7 +624,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, * set PAM_AUTHTOK and return */ - if (options.use_authtok == 1) { + if (options.use_authtok == 1 || options.try_first_pass == 1) { const void *item = NULL; retval = pam_get_item(pamh, PAM_AUTHTOK, &item); @@ -630,11 +635,13 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } else if (item != NULL) { /* we have a password! */ token1 = x_strdup(item); item = NULL; + options.use_authtok = 1; /* don't ask for the password again */ } else { retval = PAM_AUTHTOK_RECOVERY_ERR; /* didn't work */ } - - } else { + } + + if (options.use_authtok != 1) { /* Prepare to ask the user for the first time */ resp = NULL; retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp, -- cgit v1.2.3 From 083ef66c15e2ce9f90bdf6353488a01e1d3d813c Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 17 Apr 2008 12:52:25 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-04-17 Tomas Mraz * modules/pam_access/pam_access.c(myhostname): Removed function. (user_match): Supply hostname of the machine to the netgroup_match(). Use hostname from the loginfo instead of calling myhostname(). (pam_sm_authenticate): Call gethostname() to fill hostname in the loginfo. --- modules/pam_access/pam_access.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'modules') diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c index edb8fb0a..778b68cd 100644 --- a/modules/pam_access/pam_access.c +++ b/modules/pam_access/pam_access.c @@ -98,6 +98,7 @@ struct login_info { const struct passwd *user; const char *from; const char *config_file; + const char *hostname; int debug; /* Print debugging messages. */ int only_new_group_syntax; /* Only allow group entries of the form "(xyz)" */ int noaudit; /* Do not audit denials */ @@ -457,19 +458,6 @@ list_match(pam_handle_t *pamh, char *list, char *sptr, return (NO); } -/* myhostname - figure out local machine name */ - -static char *myhostname(void) -{ - static char name[MAXHOSTNAMELEN + 1]; - - if (gethostname(name, MAXHOSTNAMELEN) == 0) { - name[MAXHOSTNAMELEN] = 0; - return (name); - } - return NULL; -} - /* netgroup_match - match group against machine or user */ static int @@ -515,15 +503,17 @@ user_match (pam_handle_t *pamh, char *tok, struct login_info *item) */ if ((at = strchr(tok + 1, '@')) != 0) { /* split user@host pattern */ + if (item->hostname == NULL) + return NO; + fake_item.from = item->hostname; *at = 0; - fake_item.from = myhostname(); - if (fake_item.from == NULL) - return NO; return (user_match (pamh, tok, item) && from_match (pamh, at + 1, &fake_item)); - } else if (tok[0] == '@') /* netgroup */ - return (netgroup_match (pamh, tok + 1, (char *) 0, string, item->debug)); - else if (tok[0] == '(' && tok[strlen(tok) - 1] == ')') + } else if (tok[0] == '@') { /* netgroup */ + if (item->hostname == NULL) + return NO; + return (netgroup_match (pamh, tok + 1, item->hostname, string, item->debug)); + } else if (tok[0] == '(' && tok[strlen(tok) - 1] == ')') return (group_match (pamh, tok, string, item->debug)); else if ((rv=string_match (pamh, tok, string, item->debug)) != NO) /* ALL or exact match */ return rv; @@ -787,6 +777,8 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, const void *void_from=NULL; const char *from; struct passwd *user_pw; + char hostname[MAXHOSTNAMELEN + 1]; + /* set username */ @@ -860,6 +852,14 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, loginfo.from = from; + hostname[sizeof(hostname)-1] = '\0'; + if (gethostname(hostname, sizeof(hostname)-1) == 0) + loginfo.hostname = hostname; + else { + pam_syslog (pamh, LOG_ERR, "gethostname failed: %m"); + loginfo.hostname = NULL; + } + if (login_access(pamh, &loginfo)) { return (PAM_SUCCESS); } else { -- cgit v1.2.3 From 31a8f873dac892b15d374d8eb33037515678d6af Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 17 Apr 2008 14:29:02 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-04-17 Tomas Mraz * modules/pam_sepermit/pam_sepermit.c(sepermit_match): Do not try to lock if euid != 0. --- modules/pam_sepermit/pam_sepermit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_sepermit/pam_sepermit.c b/modules/pam_sepermit/pam_sepermit.c index 0d5ab21a..15cdc3e1 100644 --- a/modules/pam_sepermit/pam_sepermit.c +++ b/modules/pam_sepermit/pam_sepermit.c @@ -305,7 +305,7 @@ sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user, free(line); fclose(f); if (matched) - return exclusive ? sepermit_lock(pamh, user, debug) : 0; + return (geteuid() == 0 && exclusive) ? sepermit_lock(pamh, user, debug) : 0; else return -1; } -- cgit v1.2.3 From 902026536a826400014a7508b008e41269d081e6 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 18 Apr 2008 12:53:38 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-04-18 Tomas Mraz * modules/pam_namespace/pam_namespace.c: New functions unprotect_dirs(), cleanup_protect_data(), protect_mount(), protect_dir() to protect directory by bind mount. (cleanup_data): Renamed to cleanup_polydir_data(). (parse_create_params): Allow missing specification of mode or owner. (check_inst_parent): Call protect_dir() on the instance parent directory. The directory is created when it doesn't exist. (create_polydir): Protect and make the polydir by protect_dir(), remove potential races. (create_dirs): Renamed to create_instance(), remove call to inst_init(). (ns_setup): Call protect_dir() on the polydir if it already exists. Call inst_init() after the polydir is mounted. (setup_namespace): Set the namespace protect data to be cleaned up on pam_close_session()/pam_end(). (pam_sm_open_session): Initialize the protect_dirs. (pam_sm_close_session): Cleanup namespace protect data. * modules/pam_namespace/pam_namespace.h: Define struct for the stack of protected dirs. * modules/pam_namespace/pam_namespace.8.xml: Document when the instance init script is called. * modules/pam_namespace/namespace.conf.5.xml: Likewise. --- modules/pam_namespace/namespace.conf.5.xml | 4 +- modules/pam_namespace/pam_namespace.8.xml | 10 +- modules/pam_namespace/pam_namespace.c | 398 +++++++++++++++++++++-------- modules/pam_namespace/pam_namespace.h | 8 + 4 files changed, 310 insertions(+), 110 deletions(-) (limited to 'modules') diff --git a/modules/pam_namespace/namespace.conf.5.xml b/modules/pam_namespace/namespace.conf.5.xml index a1769600..61c8673b 100644 --- a/modules/pam_namespace/namespace.conf.5.xml +++ b/modules/pam_namespace/namespace.conf.5.xml @@ -25,8 +25,8 @@ Directories can be polyinstantiated based on user name or, in the case of SELinux, user name, sensitivity level or complete security context. If an executable script /etc/security/namespace.init - exists, it is used to initialize the namespace every time a new instance - directory is setup. The script receives the polyinstantiated + exists, it is used to initialize the namespace every time an instance + directory is set up and mounted. The script receives the polyinstantiated directory path and the instance directory path as its arguments. diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml index 32c5359d..787aba4a 100644 --- a/modules/pam_namespace/pam_namespace.8.xml +++ b/modules/pam_namespace/pam_namespace.8.xml @@ -64,11 +64,11 @@ provides a different instance of itself based on user name, or when using SELinux, user name, security context or both. If an executable script /etc/security/namespace.init exists, it - is used to initialize the namespace every time a new instance - directory is setup. The script receives the polyinstantiated - directory path, the instance directory path, flag whether the instance - directory was newly created (0 for no, 1 for yes), and the user name - as its arguments. + is used to initialize the instance directory after it is set up + and mounted on the polyinstantiated direcory. The script receives the + polyinstantiated directory path, the instance directory path, flag + whether the instance directory was newly created (0 for no, 1 for yes), + and the user name as its arguments. diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c index 80c51443..89bc3686 100644 --- a/modules/pam_namespace/pam_namespace.c +++ b/modules/pam_namespace/pam_namespace.c @@ -32,6 +32,8 @@ * DEALINGS IN THE SOFTWARE. */ +#define _ATFILE_SOURCE + #include "pam_namespace.h" #include "argv_parse.h" @@ -78,11 +80,29 @@ static void del_polydir_list(struct polydir_s *polydirs_ptr) } } -static void cleanup_data(pam_handle_t *pamh UNUSED , void *data, int err UNUSED) +static void unprotect_dirs(struct protect_dir_s *dir) +{ + struct protect_dir_s *next; + + while (dir != NULL) { + umount(dir->dir); + free(dir->dir); + next = dir->next; + free(dir); + dir = next; + } +} + +static void cleanup_polydir_data(pam_handle_t *pamh UNUSED , void *data, int err UNUSED) { del_polydir_list(data); } +static void cleanup_protect_data(pam_handle_t *pamh UNUSED , void *data, int err UNUSED) +{ + unprotect_dirs(data); +} + static char *expand_variables(const char *orig, const char *var_names[], const char *var_values[]) { const char *src = orig; @@ -132,8 +152,8 @@ static char *expand_variables(const char *orig, const char *var_names[], const c static int parse_create_params(char *params, struct polydir_s *poly) { - char *sptr; - struct passwd *pwd; + char *next; + struct passwd *pwd = NULL; struct group *grp; poly->mode = (mode_t)ULONG_MAX; @@ -144,28 +164,40 @@ static int parse_create_params(char *params, struct polydir_s *poly) return 0; params++; - params = strtok_r(params, ",", &sptr); - if (params == NULL) - return 0; + next = strchr(params, ','); + if (next != NULL) { + *next = '\0'; + next++; + } - errno = 0; - poly->mode = (mode_t)strtoul(params, NULL, 0); - if (errno != 0) { - poly->mode = (mode_t)ULONG_MAX; + if (*params != '\0') { + errno = 0; + poly->mode = (mode_t)strtoul(params, NULL, 0); + if (errno != 0) { + poly->mode = (mode_t)ULONG_MAX; + } } - params = strtok_r(NULL, ",", &sptr); + params = next; if (params == NULL) return 0; + next = strchr(params, ','); + if (next != NULL) { + *next = '\0'; + next++; + } - pwd = getpwnam(params); /* session modules are not reentrant */ - if (pwd == NULL) - return -1; - poly->owner = pwd->pw_uid; - - params = strtok_r(NULL, ",", &sptr); - if (params == NULL) { - poly->group = pwd->pw_gid; + if (*params != '\0') { + pwd = getpwnam(params); /* session modules are not reentrant */ + if (pwd == NULL) + return -1; + poly->owner = pwd->pw_uid; + } + + params = next; + if (params == NULL || *params == '\0') { + if (pwd != NULL) + poly->group = pwd->pw_gid; return 0; } grp = getgrnam(params); @@ -199,7 +231,7 @@ static int parse_method(char *method, struct polydir_s *poly, struct instance_data *idata) { enum polymethod pm; - char *sptr; + char *sptr = NULL; static const char *method_names[] = { "user", "context", "level", "tmpdir", "tmpfs", NULL }; static const char *flag_names[] = { "create", "noinit", "iscript", @@ -921,10 +953,158 @@ fail: return rc; } +static int protect_mount(int dfd, const char *path, struct instance_data *idata) +{ + struct protect_dir_s *dir = idata->protect_dirs; + char tmpbuf[64]; + + while (dir != NULL) { + if (strcmp(path, dir->dir) == 0) { + return 0; + } + dir = dir->next; + } + + dir = calloc(1, sizeof(*dir)); + + if (dir == NULL) { + return -1; + } + + dir->dir = strdup(path); + + if (dir->dir == NULL) { + free(dir); + return -1; + } + + snprintf(tmpbuf, sizeof(tmpbuf), "/proc/self/fd/%d", dfd); + + if (idata->flags & PAMNS_DEBUG) { + pam_syslog(idata->pamh, LOG_INFO, + "Protect mount of %s over itself", path); + } + + if (mount(tmpbuf, tmpbuf, NULL, MS_BIND, NULL) != 0) { + int save_errno = errno; + pam_syslog(idata->pamh, LOG_ERR, + "Protect mount of %s failed: %m", tmpbuf); + free(dir->dir); + free(dir); + errno = save_errno; + return -1; + } + + dir->next = idata->protect_dirs; + idata->protect_dirs = dir; + + return 0; +} + +static int protect_dir(const char *path, mode_t mode, int do_mkdir, + struct instance_data *idata) +{ + char *p = strdup(path); + char *d; + char *dir = p; + int dfd = AT_FDCWD; + int dfd_next; + int save_errno; + int flags = O_RDONLY; + int rv = -1; + struct stat st; + + if (p == NULL) { + goto error; + } + + if (*dir == '/') { + dfd = open("/", flags); + if (dfd == -1) { + goto error; + } + dir++; /* assume / is safe */ + } + + while ((d=strchr(dir, '/')) != NULL) { + *d = '\0'; + dfd_next = openat(dfd, dir, flags); + if (dfd_next == -1) { + goto error; + } + + if (dfd != AT_FDCWD) + close(dfd); + dfd = dfd_next; + + if (fstat(dfd, &st) != 0) { + goto error; + } + + if (flags & O_NOFOLLOW) { + /* we are inside user-owned dir - protect */ + if (protect_mount(dfd, p, idata) == -1) + goto error; + } else if (st.st_uid != 0 || st.st_gid != 0 || + (st.st_mode & S_IWOTH)) { + /* do not follow symlinks on subdirectories */ + flags |= O_NOFOLLOW; + } + + *d = '/'; + dir = d + 1; + } + + rv = openat(dfd, dir, flags); + + if (rv == -1) { + if (!do_mkdir || mkdirat(dfd, dir, mode) != 0) { + goto error; + } + rv = openat(dfd, dir, flags); + } + + if (rv != -1) { + if (fstat(rv, &st) != 0) { + save_errno = errno; + close(rv); + rv = -1; + errno = save_errno; + goto error; + } + if (!S_ISDIR(st.st_mode)) { + close(rv); + errno = ENOTDIR; + rv = -1; + goto error; + } + } + + if (flags & O_NOFOLLOW) { + /* we are inside user-owned dir - protect */ + if (protect_mount(rv, p, idata) == -1) { + save_errno = errno; + close(rv); + rv = -1; + errno = save_errno; + } + } + +error: + save_errno = errno; + free(p); + if (dfd != AT_FDCWD) + close(dfd); + errno = save_errno; + + return rv; +} + static int check_inst_parent(char *ipath, struct instance_data *idata) { struct stat instpbuf; char *inst_parent, *trailing_slash; + int dfd; /* * stat the instance parent path to make sure it exists * and is a directory. Check that its mode is 000 (unless the @@ -942,30 +1122,27 @@ static int check_inst_parent(char *ipath, struct instance_data *idata) if (trailing_slash) *trailing_slash = '\0'; - if (stat(inst_parent, &instpbuf) < 0) { - pam_syslog(idata->pamh, LOG_ERR, "Error stating %s, %m", inst_parent); - free(inst_parent); - return PAM_SESSION_ERR; - } + dfd = protect_dir(inst_parent, 0, 1, idata); - /* - * Make sure we are dealing with a directory - */ - if (!S_ISDIR(instpbuf.st_mode)) { - pam_syslog(idata->pamh, LOG_ERR, "Instance parent %s is not a dir", - inst_parent); + if (dfd == -1 || fstat(dfd, &instpbuf) < 0) { + pam_syslog(idata->pamh, LOG_ERR, + "Error creating or accessing instance parent %s, %m", inst_parent); + if (dfd != -1) + close(dfd); free(inst_parent); return PAM_SESSION_ERR; } if ((idata->flags & PAMNS_IGN_INST_PARENT_MODE) == 0) { - if (instpbuf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) { - pam_syslog(idata->pamh, LOG_ERR, "Mode of inst parent %s not 000", + if ((instpbuf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) || instpbuf.st_uid != 0) { + pam_syslog(idata->pamh, LOG_ERR, "Mode of inst parent %s not 000 or owner not root", inst_parent); + close(dfd); free(inst_parent); return PAM_SESSION_ERR; } } + close(dfd); free(inst_parent); return PAM_SUCCESS; } @@ -1051,6 +1228,8 @@ static int create_polydir(struct polydir_s *polyptr, security_context_t dircon, oldcon = NULL; #endif const char *dir = polyptr->dir; + uid_t uid; + gid_t gid; if (polyptr->mode != (mode_t)ULONG_MAX) mode = polyptr->mode; @@ -1077,8 +1256,8 @@ static int create_polydir(struct polydir_s *polyptr, } #endif - rc = mkdir(dir, mode); - if (rc != 0) { + rc = protect_dir(dir, mode, 1, idata); + if (rc == -1) { pam_syslog(idata->pamh, LOG_ERR, "Error creating directory %s: %m", dir); return PAM_SESSION_ERR; @@ -1098,36 +1277,41 @@ static int create_polydir(struct polydir_s *polyptr, if (polyptr->mode != (mode_t)ULONG_MAX) { /* explicit mode requested */ - if (chmod(dir, mode) != 0) { + if (fchmod(rc, mode) != 0) { pam_syslog(idata->pamh, LOG_ERR, "Error changing mode of directory %s: %m", dir); + close(rc); + umount(dir); /* undo the eventual protection bind mount */ rmdir(dir); return PAM_SESSION_ERR; } } - if (polyptr->owner != (uid_t)ULONG_MAX) { - if (chown(dir, polyptr->owner, polyptr->group) != 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Unable to change owner on directory %s: %m", dir); - rmdir(dir); - return PAM_SESSION_ERR; - } - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Polydir owner %u group %u from configuration", polyptr->owner, polyptr->group); - } else { - if (chown(dir, idata->uid, idata->gid) != 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Unable to change owner on directory %s: %m", dir); - rmdir(dir); - return PAM_SESSION_ERR; - } - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Polydir owner %u group %u", idata->uid, idata->gid); + if (polyptr->owner != (uid_t)ULONG_MAX) + uid = polyptr->owner; + else + uid = idata->uid; + + if (polyptr->group != (gid_t)ULONG_MAX) + gid = polyptr->group; + else + gid = idata->gid; + + if (fchown(rc, uid, gid) != 0) { + pam_syslog(idata->pamh, LOG_ERR, + "Unable to change owner on directory %s: %m", dir); + close(rc); + umount(dir); /* undo the eventual protection bind mount */ + rmdir(dir); + return PAM_SESSION_ERR; } + close(rc); + + if (idata->flags & PAMNS_DEBUG) + pam_syslog(idata->pamh, LOG_DEBUG, + "Polydir owner %u group %u", uid, gid); + return PAM_SUCCESS; } @@ -1135,17 +1319,16 @@ static int create_polydir(struct polydir_s *polyptr, * Create polyinstantiated instance directory (ipath). */ #ifdef WITH_SELINUX -static int create_dirs(struct polydir_s *polyptr, char *ipath, struct stat *statbuf, +static int create_instance(struct polydir_s *polyptr, char *ipath, struct stat *statbuf, security_context_t icontext, security_context_t ocontext, struct instance_data *idata) #else -static int create_dirs(struct polydir_s *polyptr, char *ipath, struct stat *statbuf, +static int create_instance(struct polydir_s *polyptr, char *ipath, struct stat *statbuf, struct instance_data *idata) #endif { struct stat newstatbuf; int fd; - int newdir = 0; /* * Check to make sure instance parent is valid. @@ -1171,7 +1354,7 @@ static int create_dirs(struct polydir_s *polyptr, char *ipath, struct stat *stat strcpy(ipath, polyptr->instance_prefix); } else if (mkdir(ipath, S_IRUSR) < 0) { if (errno == EEXIST) - goto inst_init; + return PAM_IGNORE; else { pam_syslog(idata->pamh, LOG_ERR, "Error creating %s, %m", ipath); @@ -1179,7 +1362,6 @@ static int create_dirs(struct polydir_s *polyptr, char *ipath, struct stat *stat } } - newdir = 1; /* Open a descriptor to it to prevent races */ fd = open(ipath, O_DIRECTORY | O_RDONLY); if (fd < 0) { @@ -1235,33 +1417,22 @@ static int create_dirs(struct polydir_s *polyptr, char *ipath, struct stat *stat return PAM_SESSION_ERR; } close(fd); - - /* - * Check to see if there is a namespace initialization script in - * the /etc/security directory. If such a script exists - * execute it and pass directory to polyinstantiate and instance - * directory as arguments. - */ - -inst_init: - if (polyptr->flags & POLYDIR_NOINIT) - return PAM_SUCCESS; - - return inst_init(polyptr, ipath, idata, newdir); + return PAM_SUCCESS; } /* * This function performs the namespace setup for a particular directory - * that is being polyinstantiated. It creates an MD5 hash of instance - * directory, calls create_dirs to create it with appropriate + * that is being polyinstantiated. It calls poly_name to create name of instance + * directory, calls create_instance to mkdir it with appropriate * security attributes, and performs bind mount to setup the process * namespace. */ static int ns_setup(struct polydir_s *polyptr, struct instance_data *idata) { - int retval = 0; + int retval; + int newdir = 1; char *inst_dir = NULL; char *instname = NULL; struct stat statbuf; @@ -1273,37 +1444,40 @@ static int ns_setup(struct polydir_s *polyptr, pam_syslog(idata->pamh, LOG_DEBUG, "Set namespace for directory %s", polyptr->dir); - while (stat(polyptr->dir, &statbuf) < 0) { - if (retval || !(polyptr->flags & POLYDIR_CREATE)) { - pam_syslog(idata->pamh, LOG_ERR, "Error stating %s, %m", - polyptr->dir); - return PAM_SESSION_ERR; - } else { - if (create_polydir(polyptr, idata) != PAM_SUCCESS) - return PAM_SESSION_ERR; - retval = PAM_SESSION_ERR; /* bail out on next failed stat */ - } - } + retval = protect_dir(polyptr->dir, 0, 0, idata); - /* - * Make sure we are dealing with a directory - */ - if (!S_ISDIR(statbuf.st_mode)) { - pam_syslog(idata->pamh, LOG_ERR, "Polydir %s is not a dir", + if (retval < 0 && errno != ENOENT) { + pam_syslog(idata->pamh, LOG_ERR, "Polydir %s access error: %m", polyptr->dir); - return PAM_SESSION_ERR; + return PAM_SESSION_ERR; } + if (retval < 0 && (polyptr->flags & POLYDIR_CREATE)) { + if (create_polydir(polyptr, idata) != PAM_SUCCESS) + return PAM_SESSION_ERR; + } else { + close(retval); + } + if (polyptr->method == TMPFS) { if (mount("tmpfs", polyptr->dir, "tmpfs", 0, NULL) < 0) { pam_syslog(idata->pamh, LOG_ERR, "Error mounting tmpfs on %s, %m", polyptr->dir); return PAM_SESSION_ERR; } - /* we must call inst_init after the mount in this case */ + + if (polyptr->flags & POLYDIR_NOINIT) + return PAM_SUCCESS; + return inst_init(polyptr, "tmpfs", idata, 1); } + if (stat(polyptr->dir, &statbuf) < 0) { + pam_syslog(idata->pamh, LOG_ERR, "Error stating %s: %m", + polyptr->dir); + return PAM_SESSION_ERR; + } + /* * Obtain the name of instance pathname based on the * polyinstantiation method and instance context returned by @@ -1341,14 +1515,18 @@ static int ns_setup(struct polydir_s *polyptr, * contexts, owner, group and mode bits. */ #ifdef WITH_SELINUX - retval = create_dirs(polyptr, inst_dir, &statbuf, instcontext, + retval = create_instance(polyptr, inst_dir, &statbuf, instcontext, origcontext, idata); #else - retval = create_dirs(polyptr, inst_dir, &statbuf, idata); + retval = create_instance(polyptr, inst_dir, &statbuf, idata); #endif - if (retval < 0) { - pam_syslog(idata->pamh, LOG_ERR, "Error creating instance dir"); + if (retval == PAM_IGNORE) { + newdir = 0; + retval = PAM_SUCCESS; + } + + if (retval != PAM_SUCCESS) { goto error_out; } @@ -1363,6 +1541,9 @@ static int ns_setup(struct polydir_s *polyptr, goto error_out; } + if (!(polyptr->flags & POLYDIR_NOINIT)) + retval = inst_init(polyptr, inst_dir, idata, newdir); + goto cleanup; /* @@ -1600,12 +1781,21 @@ static int setup_namespace(struct instance_data *idata, enum unmnt_op unmnt) } } out: - if (retval != PAM_SUCCESS) + if (retval != PAM_SUCCESS) { + cleanup_tmpdirs(idata); + unprotect_dirs(idata->protect_dirs); + } else if (pam_set_data(idata->pamh, NAMESPACE_PROTECT_DATA, idata->protect_dirs, + cleanup_protect_data) != PAM_SUCCESS) { + pam_syslog(idata->pamh, LOG_ERR, "Unable to set namespace protect data"); cleanup_tmpdirs(idata); - else if (pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, idata->polydirs_ptr, - cleanup_data) != PAM_SUCCESS) { - pam_syslog(idata->pamh, LOG_ERR, "Unable to set namespace data"); + unprotect_dirs(idata->protect_dirs); + return PAM_SYSTEM_ERR; + } else if (pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, idata->polydirs_ptr, + cleanup_polydir_data) != PAM_SUCCESS) { + pam_syslog(idata->pamh, LOG_ERR, "Unable to set namespace polydir data"); cleanup_tmpdirs(idata); + pam_set_data(idata->pamh, NAMESPACE_PROTECT_DATA, NULL, NULL); + idata->protect_dirs = NULL; return PAM_SYSTEM_ERR; } return retval; @@ -1742,6 +1932,7 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, /* init instance data */ idata.flags = 0; idata.polydirs_ptr = NULL; + idata.protect_dirs = NULL; idata.pamh = pamh; #ifdef WITH_SELINUX if (is_selinux_enabled()) @@ -1893,6 +2084,7 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED, } pam_set_data(idata.pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL); + pam_set_data(idata.pamh, NAMESPACE_PROTECT_DATA, NULL, NULL); return PAM_SUCCESS; } diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_namespace.h index bfc0da17..da21bd70 100644 --- a/modules/pam_namespace/pam_namespace.h +++ b/modules/pam_namespace/pam_namespace.h @@ -107,6 +107,7 @@ #define NAMESPACE_MAX_DIR_LEN 80 #define NAMESPACE_POLYDIR_DATA "pam_namespace:polydir_data" +#define NAMESPACE_PROTECT_DATA "pam_namespace:protect_data" /* * Polyinstantiation method options, based on user, security context @@ -156,9 +157,15 @@ struct polydir_s { struct polydir_s *next; /* pointer to the next polydir entry */ }; +struct protect_dir_s { + char *dir; /* protected directory */ + struct protect_dir_s *next; /* next entry */ +}; + struct instance_data { pam_handle_t *pamh; /* The pam handle for this instance */ struct polydir_s *polydirs_ptr; /* The linked list pointer */ + struct protect_dir_s *protect_dirs; /* The pointer to stack of mount-protected dirs */ char user[LOGIN_NAME_MAX]; /* User name */ char ruser[LOGIN_NAME_MAX]; /* Requesting user name */ uid_t uid; /* The uid of the user */ @@ -166,3 +173,4 @@ struct instance_data { uid_t ruid; /* The uid of the requesting user */ unsigned long flags; /* Flags for debug, selinux etc */ }; + -- cgit v1.2.3 From aeccee4585ab2ea6deab9cbebc7afc67b7196a80 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Mon, 21 Apr 2008 11:21:12 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-04-21 Thorsten Kukuk * modules/pam_access/access.conf.5.xml: Document changed behavior of LOCAL keyword. * modules/pam_access/pam_access.c: Add from_remote_host to struct login_info to change behavior of LOCAL keyword: if PAM_RHOST is not set, LOCAL will be true. --- modules/pam_access/access.conf.5.xml | 7 +++++-- modules/pam_access/pam_access.c | 17 +++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'modules') diff --git a/modules/pam_access/access.conf.5.xml b/modules/pam_access/access.conf.5.xml index f8eb7a4e..17185172 100644 --- a/modules/pam_access/access.conf.5.xml +++ b/modules/pam_access/access.conf.5.xml @@ -69,8 +69,11 @@ internet network numbers (end with "."), internet network addresses with network mask (where network mask can be a decimal number or an internet address also), ALL (which always matches) - or LOCAL (which matches any string that does not - contain a "." character). If supported by the system you can use + or LOCAL. LOCAL + keyword matches if and only if the PAM_RHOST is + not set and <origin> field is thus set from + PAM_TTY or PAM_SERVICE". + If supported by the system you can use @netgroupname in host or user patterns. diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c index 778b68cd..a5c6c6a5 100644 --- a/modules/pam_access/pam_access.c +++ b/modules/pam_access/pam_access.c @@ -48,7 +48,7 @@ #ifdef HAVE_LIBAUDIT #include -#endif +#endif /* * here, we make definitions for the externally accessible functions @@ -104,6 +104,7 @@ struct login_info { int noaudit; /* Do not audit denials */ const char *fs; /* field separator */ const char *sep; /* list-element separator */ + int from_remote_host; /* If PAM_RHOST was used for from */ }; /* Parse module config arguments */ @@ -113,7 +114,7 @@ parse_args(pam_handle_t *pamh, struct login_info *loginfo, int argc, const char **argv) { int i; - + loginfo->noaudit = NO; loginfo->debug = NO; loginfo->only_new_group_syntax = NO; @@ -571,8 +572,8 @@ from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item) * If a token has the magic value "ALL" the match always succeeds. Return * YES if the token fully matches the string. If the token is a domain * name, return YES if it matches the last fields of the string. If the - * token has the magic value "LOCAL", return YES if the string does not - * contain a "." character. If the token is a network number, return YES + * token has the magic value "LOCAL", return YES if the from field was + * not taken by PAM_RHOST. If the token is a network number, return YES * if it matches the head of the string. */ @@ -587,8 +588,8 @@ from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item) if ((str_len = strlen(string)) > (tok_len = strlen(tok)) && strcasecmp(tok, string + str_len - tok_len) == 0) return (YES); - } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */ - if (strchr(string, '.') == 0) + } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no PAM_RHOSTS */ + if (item->from_remote_host == 0) return (YES); } else if (tok[(tok_len = strlen(tok)) - 1] == '.') { struct addrinfo *res; @@ -817,6 +818,8 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, /* local login, set tty name */ + loginfo.from_remote_host = 0; + if (pam_get_item(pamh, PAM_TTY, &void_from) != PAM_SUCCESS || void_from == NULL) { D(("PAM_TTY not set, probing stdin")); @@ -849,6 +852,8 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, } } } + else + loginfo.from_remote_host = 1; loginfo.from = from; -- cgit v1.2.3 From 52f517dd540bdd12c5fa239bd7f60b51aaea9326 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 22 Apr 2008 19:21:37 +0000 Subject: Relevant BUGIDs: rhbz#443667 Purpose of commit: bugfix Commit summary: --------------- 2008-04-22 Tomas Mraz * modules/pam_selinux/pam_selinux.c(pam_sm_close_sesion): Fix regression from the change from 2008-03-20. setexeccon() must be called also with NULL prev_context. --- modules/pam_selinux/pam_selinux.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'modules') diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c index f679e33d..da49f3f9 100644 --- a/modules/pam_selinux/pam_selinux.c +++ b/modules/pam_selinux/pam_selinux.c @@ -702,21 +702,21 @@ pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED, free(ttyn); ttyn=NULL; } - if (prev_user_context) { - if (setexeccon(prev_user_context)) { + + if (setexeccon(prev_user_context)) { pam_syslog(pamh, LOG_ERR, "Unable to restore executable context %s.", - prev_user_context); + prev_user_context ? prev_user_context : ""); if (security_getenforce() == 1) status = PAM_AUTH_ERR; else status = PAM_SUCCESS; - } + } else if (debug) + pam_syslog(pamh, LOG_NOTICE, "Executable context back to original"); + + if (prev_user_context) { freecon(prev_user_context); prev_user_context = NULL; } - if (debug) - pam_syslog(pamh, LOG_NOTICE, "setcontext back to orginal"); - return status; } -- cgit v1.2.3 From 8aab1ab0b2564be02ac942fc39c043cd7b32008e Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 2 May 2008 12:41:32 +0000 Subject: Relevant BUGIDs: Purpose of commit: cleanup Commit summary: --------------- 2008-05-02 Tomas Mraz * modules/pam_selinux/pam_selinux.c(query_response): Add handling for NULL response. (manual_context): Handle failed query_response() properly. Rename variable responses to response which is more correct name. (config_context): Likewise. (pam_sm_open_session): Do not base decision on whether there is a tty. --- modules/pam_selinux/pam_selinux.c | 120 ++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 57 deletions(-) (limited to 'modules') diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c index da49f3f9..da1290f0 100644 --- a/modules/pam_selinux/pam_selinux.c +++ b/modules/pam_selinux/pam_selinux.c @@ -138,15 +138,22 @@ send_text (pam_handle_t *pamh, const char *text, int debug) */ static int query_response (pam_handle_t *pamh, const char *text, const char *def, - char **responses, int debug) + char **response, int debug) { int rc; if (def) - rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, responses, "%s [%s] ", text, def); + rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, response, "%s [%s] ", text, def); else - rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, responses, "%s ", text); - if (debug) - pam_syslog(pamh, LOG_NOTICE, "%s %s", text, responses[0]); + rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, response, "%s ", text); + + if (*response == NULL) { + rc = PAM_CONV_ERR; + } + + if (rc != PAM_SUCCESS) { + pam_syslog(pamh, LOG_WARNING, "No response to query: %s", text); + } else if (debug) + pam_syslog(pamh, LOG_NOTICE, "%s %s", text, *response); return rc; } @@ -157,13 +164,15 @@ manual_context (pam_handle_t *pamh, const char *user, int debug) context_t new_context; int mls_enabled = is_selinux_mls_enabled(); char *type=NULL; - char *responses=NULL; + char *response=NULL; while (1) { - query_response(pamh, - _("Would you like to enter a security context? [N] "), NULL, - &responses,debug); - if ((responses[0] == 'y') || (responses[0] == 'Y')) + if (query_response(pamh, + _("Would you like to enter a security context? [N] "), NULL, + &response, debug) != PAM_SUCCESS) + return NULL; + + if ((response[0] == 'y') || (response[0] == 'Y')) { if (mls_enabled) new_context = context_new ("user:role:type:level"); @@ -176,26 +185,29 @@ manual_context (pam_handle_t *pamh, const char *user, int debug) if (context_user_set (new_context, user)) goto fail_set; - _pam_drop(responses); + _pam_drop(response); /* Allow the user to enter each field of the context individually */ - query_response(pamh,_("role:"), NULL, &responses,debug); - if (responses[0] != '\0') { - if (context_role_set (new_context, responses)) + if (query_response(pamh, _("role:"), NULL, &response, debug) == PAM_SUCCESS && + response[0] != '\0') { + if (context_role_set (new_context, response)) goto fail_set; - if (get_default_type(responses, &type)) + if (get_default_type(response, &type)) goto fail_set; if (context_type_set (new_context, type)) goto fail_set; } - _pam_drop(responses); + _pam_drop(response); + if (mls_enabled) { - query_response(pamh,_("level:"), NULL, &responses,debug); - if (responses[0] != '\0') { - if (context_range_set (new_context, responses)) + if (query_response(pamh, _("level:"), NULL, &response, debug) == PAM_SUCCESS && + response[0] != '\0') { + if (context_range_set (new_context, response)) goto fail_set; } + _pam_drop(response); } + /* Get the string value of the context and see if it is valid. */ if (!security_check_context(context_str(new_context))) { newcon = strdup(context_str(new_context)); @@ -204,16 +216,17 @@ manual_context (pam_handle_t *pamh, const char *user, int debug) } else send_text(pamh,_("Not a valid security context"),debug); - context_free (new_context); + + context_free (new_context); } else { - _pam_drop(responses); + _pam_drop(response); return NULL; } } /* end while */ fail_set: free(type); - _pam_drop(responses); + _pam_drop(response); context_free (new_context); return NULL; } @@ -244,49 +257,52 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) security_context_t newcon=NULL; context_t new_context; int mls_enabled = is_selinux_mls_enabled(); - char *responses=NULL; + char *response=NULL; char *type=NULL; char resp_val = 0; pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), puser_context); while (1) { - query_response(pamh, + if (query_response(pamh, _("Would you like to enter a different role or level?"), "n", - &responses,debug); - - resp_val = responses[0]; - _pam_drop(responses); + &response, debug) == PAM_SUCCESS) { + resp_val = response[0]; + _pam_drop(response); + } else { + resp_val = 'N'; + } if ((resp_val == 'y') || (resp_val == 'Y')) { - new_context = context_new(puser_context); - + if ((new_context = context_new(puser_context)) == NULL) + goto fail_set; + /* Allow the user to enter role and level individually */ - query_response(pamh,_("role:"), context_role_get(new_context), - &responses, debug); - if (responses[0]) { - if (get_default_type(responses, &type)) { - pam_prompt (pamh, PAM_ERROR_MSG, NULL, _("No default type for role %s\n"), responses); - _pam_drop(responses); + if (query_response(pamh, _("role:"), context_role_get(new_context), + &response, debug) == PAM_SUCCESS && response[0]) { + if (get_default_type(response, &type)) { + pam_prompt (pamh, PAM_ERROR_MSG, NULL, _("No default type for role %s\n"), response); + _pam_drop(response); continue; } else { - if (context_role_set(new_context, responses)) + if (context_role_set(new_context, response)) goto fail_set; if (context_type_set (new_context, type)) goto fail_set; } } - _pam_drop(responses); + _pam_drop(response); + if (mls_enabled) { - query_response(pamh,_("level:"), context_range_get(new_context), - &responses, debug); - if (responses[0]) { - if (context_range_set(new_context, responses)) + if (query_response(pamh, _("level:"), context_range_get(new_context), + &response, debug) == PAM_SUCCESS && response[0]) { + if (context_range_set(new_context, response)) goto fail_set; } - _pam_drop(responses); + _pam_drop(response); } + if (debug) pam_syslog(pamh, LOG_NOTICE, "Selected Security Context %s", context_str(new_context)); @@ -322,7 +338,7 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) fail_set: free(type); - _pam_drop(responses); + _pam_drop(response); context_free (new_context); send_audit_message(pamh, 0, puser_context, NULL); fail_range: @@ -439,7 +455,7 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { - int i, debug = 0, ttys=1, has_tty=isatty(0); + int i, debug = 0, ttys=1; int verbose=0, close_session=0; int select_context = 0; int use_current_range = 0; @@ -513,7 +529,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, return PAM_AUTH_ERR; } user_context = default_user_context; - if (select_context && has_tty) { + if (select_context) { user_context = config_context(pamh, default_user_context, debug); if (user_context == NULL) { freecon(default_user_context); @@ -528,7 +544,6 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, } } else { - if (has_tty) { user_context = manual_context(pamh,seuser,debug); if (user_context == NULL) { pam_syslog (pamh, LOG_ERR, "Unable to get valid context for %s", @@ -538,15 +553,6 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, else return PAM_SUCCESS; } - } else { - pam_syslog (pamh, LOG_ERR, - "Unable to get valid context for %s, No valid tty", - username); - if (security_getenforce() == 1) - return PAM_AUTH_ERR; - else - return PAM_SUCCESS; - } } if (use_current_range && is_selinux_mls_enabled()) { @@ -613,7 +619,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, } } } - if(ttys && tty ) { + if (ttys && tty) { ttyn=strdup(tty); ttyn_context=security_label_tty(pamh,ttyn,user_context); } -- cgit v1.2.3 From cf90454cdde0b0a905877dd0b02042347184729c Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Wed, 14 May 2008 13:03:39 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-05-14 Tomas Mraz * modules/pam_unix/pam_unix_passwd.c(pam_sm_chauthtok): Unset authtok item when password is not approved. * modules/pam_unix/support.c(_unix_read_password): UNIX_USE_FIRST_PASS is always set when UNIX_AUTHTOK is set, change order of conditions. --- modules/pam_unix/pam_unix_passwd.c | 4 ++++ modules/pam_unix/support.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index d221220f..0a429756 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -699,6 +699,10 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, pass_new = NULL; } retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new); + + if (retval != PAM_SUCCESS && off(UNIX_NOT_SET_PASS, ctrl)) { + pam_set_item(pamh, PAM_AUTHTOK, NULL); + } } if (retval != PAM_SUCCESS) { diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index b82cad26..781d0006 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -743,11 +743,11 @@ int _unix_read_password(pam_handle_t * pamh return retval; } else if (*pass != NULL) { /* we have a password! */ return PAM_SUCCESS; - } else if (on(UNIX_USE_FIRST_PASS, ctrl)) { - return PAM_AUTHTOK_RECOVERY_ERR; /* didn't work */ } else if (on(UNIX_USE_AUTHTOK, ctrl) && off(UNIX__OLD_PASSWD, ctrl)) { return PAM_AUTHTOK_ERR; + } else if (on(UNIX_USE_FIRST_PASS, ctrl)) { + return PAM_AUTHTOK_RECOVERY_ERR; /* didn't work */ } } /* -- cgit v1.2.3 From e80ad6cce5f605b400e24fb3b29f64a0998541a6 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 19 Jun 2008 12:15:57 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-06-19 Tomas Mraz * modules/pam_succeed_if/pam_succeed_if.c (pam_sm_authenticate): Detect configuration errors. Fail on incomplete condition. --- modules/pam_succeed_if/pam_succeed_if.8.xml | 2 +- modules/pam_succeed_if/pam_succeed_if.c | 79 +++++++++++++++-------------- 2 files changed, 42 insertions(+), 39 deletions(-) (limited to 'modules') diff --git a/modules/pam_succeed_if/pam_succeed_if.8.xml b/modules/pam_succeed_if/pam_succeed_if.8.xml index d064e03b..e377ae86 100644 --- a/modules/pam_succeed_if/pam_succeed_if.8.xml +++ b/modules/pam_succeed_if/pam_succeed_if.8.xml @@ -249,7 +249,7 @@ A service error occured or the arguments can't be - parsed as numbers. + parsed correctly. diff --git a/modules/pam_succeed_if/pam_succeed_if.c b/modules/pam_succeed_if/pam_succeed_if.c index 06cb5d6a..cf95d38e 100644 --- a/modules/pam_succeed_if/pam_succeed_if.c +++ b/modules/pam_succeed_if/pam_succeed_if.c @@ -443,10 +443,38 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, } /* Walk the argument list. */ - i = count = 0; + count = 0; left = qual = right = NULL; - while (i <= argc) { - if ((left != NULL) && (qual != NULL) && (right != NULL)) { + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "debug") == 0) { + continue; + } + if (strcmp(argv[i], "use_uid") == 0) { + continue; + } + if (strcmp(argv[i], "quiet") == 0) { + continue; + } + if (strcmp(argv[i], "quiet_fail") == 0) { + continue; + } + if (strcmp(argv[i], "quiet_success") == 0) { + continue; + } + if (left == NULL) { + left = argv[i]; + continue; + } + if (qual == NULL) { + qual = argv[i]; + continue; + } + if (right == NULL) { + right = argv[i]; + if (right == NULL) + continue; + + count++; ret = evaluate(pamh, debug, left, qual, right, pwd); @@ -456,6 +484,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, "requirement \"%s %s %s\" " "not met by user \"%s\"", left, qual, right, user); + left = qual = right = NULL; break; } else @@ -465,43 +494,17 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, "was met by user \"%s\"", left, qual, right, user); left = qual = right = NULL; - } - if ((i < argc) && (strcmp(argv[i], "debug") == 0)) { - i++; - continue; - } - if ((i < argc) && (strcmp(argv[i], "use_uid") == 0)) { - i++; continue; } - if ((i < argc) && (strcmp(argv[i], "quiet") == 0)) { - i++; - continue; - } - if ((i < argc) && (strcmp(argv[i], "quiet_fail") == 0)) { - i++; - continue; - } - if ((i < argc) && (strcmp(argv[i], "quiet_success") == 0)) { - i++; - continue; - } - if ((i < argc) && (left == NULL)) { - left = argv[i++]; - count++; - continue; - } - if ((i < argc) && (qual == NULL)) { - qual = argv[i++]; - count++; - continue; - } - if ((i < argc) && (right == NULL)) { - right = argv[i++]; - count++; - continue; - } - i++; + } + + if (left || qual || right) { + ret = PAM_SERVICE_ERR; + pam_syslog(pamh, LOG_CRIT, + "incomplete condition detected"); + } else if (count == 0) { + pam_syslog(pamh, LOG_INFO, + "no condition detected; module succeeded"); } return ret; -- cgit v1.2.3 From 8f0abb6a4553664074d27bd6c6ddea09598c7e72 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Sun, 22 Jun 2008 09:13:39 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-06-22 Thorsten Kukuk * modules/pam_unix/unix_chkpwd.c (main): Fix compiling without audit support. * modules/pam_cracklib/pam_cracklib.8.xml: Fix typo in ucredit description (reported by Wayne Pollock ) --- modules/pam_cracklib/pam_cracklib.8.xml | 2 +- modules/pam_unix/unix_chkpwd.c | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'modules') diff --git a/modules/pam_cracklib/pam_cracklib.8.xml b/modules/pam_cracklib/pam_cracklib.8.xml index 589e7b44..823a0bce 100644 --- a/modules/pam_cracklib/pam_cracklib.8.xml +++ b/modules/pam_cracklib/pam_cracklib.8.xml @@ -281,7 +281,7 @@ than 10. - (N > 0) This is the minimum number of upper + (N < 0) This is the minimum number of upper case letters that must be met for a new password. diff --git a/modules/pam_unix/unix_chkpwd.c b/modules/pam_unix/unix_chkpwd.c index b4f9b3df..61675ed2 100644 --- a/modules/pam_unix/unix_chkpwd.c +++ b/modules/pam_unix/unix_chkpwd.c @@ -47,7 +47,7 @@ static int _check_expiry(const char *uname) printf("-1\n"); return retval; } - + if (spent == NULL) { printf("-1\n"); return retval; @@ -58,9 +58,9 @@ static int _check_expiry(const char *uname) return retval; } +#ifdef HAVE_LIBAUDIT static int _audit_log(int type, const char *uname, int rc) { -#ifdef HAVE_LIBAUDIT int audit_fd; audit_fd = audit_open(); @@ -84,10 +84,8 @@ static int _audit_log(int type, const char *uname, int rc) audit_close(audit_fd); return rc < 0 ? PAM_AUTH_ERR : PAM_SUCCESS; -#else - return PAM_SUCCESS; -#endif } +#endif int main(int argc, char *argv[]) { @@ -117,7 +115,9 @@ int main(int argc, char *argv[]) helper_log_err(LOG_NOTICE ,"inappropriate use of Unix helper binary [UID=%d]" ,getuid()); +#ifdef HAVE_LIBAUDIT _audit_log(AUDIT_ANOM_EXEC, getuidname(getuid()), PAM_SYSTEM_ERR); +#endif fprintf(stderr ,"This binary is not designed for running in this way\n" "-- the system administrator has been informed\n"); @@ -148,14 +148,16 @@ int main(int argc, char *argv[]) if (strcmp(option, "chkexpiry") == 0) /* Check account information from the shadow file */ - return _check_expiry(argv[1]); + return _check_expiry(argv[1]); /* read the nullok/nonull option */ else if (strcmp(option, "nullok") == 0) nullok = 1; else if (strcmp(option, "nonull") == 0) nullok = 0; else { +#ifdef HAVE_LIBAUDIT _audit_log(AUDIT_ANOM_EXEC, getuidname(getuid()), PAM_SYSTEM_ERR); +#endif return PAM_SYSTEM_ERR; } /* read the password from stdin (a pipe from the pam_unix module) */ @@ -180,14 +182,21 @@ int main(int argc, char *argv[]) if (retval != PAM_SUCCESS) { if (!nullok || !blankpass) { /* no need to log blank pass test */ +#ifdef HAVE_LIBAUDIT if (getuid() != 0) _audit_log(AUDIT_USER_AUTH, user, PAM_AUTH_ERR); +#endif helper_log_err(LOG_NOTICE, "password check failed for user (%s)", user); } return PAM_AUTH_ERR; } else { - if (getuid() != 0) + if (getuid() != 0) { +#ifdef HAVE_LIBAUDIT return _audit_log(AUDIT_USER_AUTH, user, PAM_SUCCESS); +#else + return PAM_SUCCESS; +#endif + } return PAM_SUCCESS; } } -- cgit v1.2.3 From a56a27d91b53f6029760d6a0e38b44b46f086f87 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Tue, 8 Jul 2008 11:20:25 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-07-08 Thorsten Kukuk * modules/pam_unix/passverify.c (verify_pwd_hash): Adjust debug statement. --- modules/pam_unix/passverify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 6d588e63..ce5bc450 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -117,7 +117,7 @@ verify_pwd_hash(const char *p, char *hash, unsigned int nullok) p = NULL; /* no longer needed here */ /* the moment of truth -- do we agree with the password? */ - D(("comparing state of pp[%s] and salt[%s]", pp, salt)); + D(("comparing state of pp[%s] and hash[%s]", pp, hash)); if (pp && strcmp(pp, hash) == 0) { retval = PAM_SUCCESS; -- cgit v1.2.3 From 72fae03ec85016c4c443eb1c0195ed54b4423544 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 9 Jul 2008 12:23:23 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-07-09 Thorsten Kukuk * modules/pam_tally/pam_tally.c: Add support for silent and no_log_info options. * modules/pam_tally/pam_tally.8.xml: Document silent and no_log_info options. --- modules/pam_tally/pam_tally.8.xml | 26 ++++++++++++++++++++ modules/pam_tally/pam_tally.c | 51 ++++++++++++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 12 deletions(-) (limited to 'modules') diff --git a/modules/pam_tally/pam_tally.8.xml b/modules/pam_tally/pam_tally.8.xml index 4f89269e..68b69a30 100644 --- a/modules/pam_tally/pam_tally.8.xml +++ b/modules/pam_tally/pam_tally.8.xml @@ -51,6 +51,12 @@ audit + + silent + + + no_log_info + pam_tally @@ -150,6 +156,26 @@ + + + + + + + Don't print informative messages. + + + + + + + + + + Don't log informative messages via syslog3. + + + diff --git a/modules/pam_tally/pam_tally.c b/modules/pam_tally/pam_tally.c index 8814659a..a01e1938 100644 --- a/modules/pam_tally/pam_tally.c +++ b/modules/pam_tally/pam_tally.c @@ -97,6 +97,8 @@ struct tally_options { #define OPT_NO_LOCK_TIME 020 #define OPT_NO_RESET 040 #define OPT_AUDIT 0100 +#define OPT_SILENT 0200 +#define OPT_NOLOGNOTICE 0400 /*---------------------------------------------------------------------*/ @@ -205,6 +207,12 @@ tally_parse_args(pam_handle_t *pamh, struct tally_options *opts, else if ( ! strcmp ( *argv, "audit") ) { opts->ctrl |= OPT_AUDIT; } + else if ( ! strcmp ( *argv, "silent") ) { + opts->ctrl |= OPT_SILENT; + } + else if ( ! strcmp ( *argv, "no_log_info") ) { + opts->ctrl |= OPT_NOLOGNOTICE; + } else { pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); } @@ -524,12 +532,17 @@ tally_check (time_t oldtime, pam_handle_t *pamh, uid_t uid, { if ( lock_time + oldtime > time(NULL) ) { - pam_syslog(pamh, LOG_NOTICE, - "user %s (%lu) has time limit [%lds left]" - " since last failure.", - user, (unsigned long int) uid, - oldtime+lock_time - -time(NULL)); + if (!(opts->ctrl & OPT_SILENT)) + pam_info (pamh, + _("Account temporary locked (%lds seconds left)"), + oldtime+lock_time-time(NULL)); + + if (!(opts->ctrl & OPT_NOLOGNOTICE)) + pam_syslog (pamh, LOG_NOTICE, + "user %s (%lu) has time limit [%lds left]" + " since last failure.", + user, (unsigned long int) uid, + oldtime+lock_time-time(NULL)); return PAM_AUTH_ERR; } } @@ -545,9 +558,14 @@ tally_check (time_t oldtime, pam_handle_t *pamh, uid_t uid, ( tally > deny ) && /* tally>deny means exceeded */ ( ((opts->ctrl & OPT_DENY_ROOT) || uid) ) /* even_deny stops uid check */ ) { - pam_syslog(pamh, LOG_NOTICE, - "user %s (%lu) tally "TALLY_FMT", deny "TALLY_FMT, - user, (unsigned long int) uid, tally, deny); + if (!(opts->ctrl & OPT_SILENT)) + pam_info (pamh, _("Accounted locked due to "TALLY_FMT" failed login"), + tally); + + if (!(opts->ctrl & OPT_NOLOGNOTICE)) + pam_syslog(pamh, LOG_NOTICE, + "user %s (%lu) tally "TALLY_FMT", deny "TALLY_FMT, + user, (unsigned long int) uid, tally, deny); return PAM_AUTH_ERR; /* Only unconditional failure */ } } @@ -594,7 +612,7 @@ tally_reset (pam_handle_t *pamh, uid_t uid, struct tally_options *opts) #ifdef PAM_SM_AUTH PAM_EXTERN int -pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { int @@ -612,6 +630,9 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, if ( rvcheck != PAM_SUCCESS ) RETURN_ERROR( rvcheck ); + if (flags & PAM_SILENT) + opts->ctrl |= OPT_SILENT; + rvcheck = pam_get_uid(pamh, &uid, &user, opts); if ( rvcheck != PAM_SUCCESS ) RETURN_ERROR( rvcheck ); @@ -625,7 +646,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, } PAM_EXTERN int -pam_sm_setcred(pam_handle_t *pamh, int flags UNUSED, +pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { int @@ -643,6 +664,9 @@ pam_sm_setcred(pam_handle_t *pamh, int flags UNUSED, if ( rv != PAM_SUCCESS ) RETURN_ERROR( rv ); + if (flags & PAM_SILENT) + opts->ctrl |= OPT_SILENT; + rv = pam_get_uid(pamh, &uid, &user, opts); if ( rv != PAM_SUCCESS ) RETURN_ERROR( rv ); @@ -667,7 +691,7 @@ pam_sm_setcred(pam_handle_t *pamh, int flags UNUSED, /* To reset failcount of user on successfull login */ PAM_EXTERN int -pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED, +pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { int @@ -685,6 +709,9 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED, if ( rv != PAM_SUCCESS ) RETURN_ERROR( rv ); + if (flags & PAM_SILENT) + opts->ctrl |= OPT_SILENT; + rv = pam_get_uid(pamh, &uid, &user, opts); if ( rv != PAM_SUCCESS ) RETURN_ERROR( rv ); -- cgit v1.2.3 From 42f4dc06c31fc1e8eb3d11ce896bad65ca0489af Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 9 Jul 2008 13:09:10 +0000 Subject: Relevant BUGIDs: 1994330 Purpose of commit: bugfix Commit summary: --------------- 2008-07-09 Thorsten Kukuk * modules/pam_securetty/pam_securetty.8.xml: Replace PAM_IGNORE with PAM_USER_UNKNOWN (#1994330) --- modules/pam_securetty/pam_securetty.8.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_securetty/pam_securetty.8.xml b/modules/pam_securetty/pam_securetty.8.xml index 56348d78..ef8562ea 100644 --- a/modules/pam_securetty/pam_securetty.8.xml +++ b/modules/pam_securetty/pam_securetty.8.xml @@ -116,7 +116,7 @@ - PAM_IGNORE + PAM_USER_UNKNOWN The module could not find the user name in the -- cgit v1.2.3 From 6377bdbbfc0af3c88572f5108f55344af745a010 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 9 Jul 2008 14:37:51 +0000 Subject: Relevant BUGIDs: 1976310 Purpose of commit: feature Commit summary: --------------- 2008-07-09 Thorsten Kukuk * modules/pam_exec/pam_exec.c (call_exec): Move all variable declaration to begin of a block (#1976310). * xtests/tst-pam_group1.c (run_test): Move no_grps declaration to begin of function (#1976310). --- modules/pam_exec/pam_exec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'modules') diff --git a/modules/pam_exec/pam_exec.c b/modules/pam_exec/pam_exec.c index 14dddd54..dce65730 100644 --- a/modules/pam_exec/pam_exec.c +++ b/modules/pam_exec/pam_exec.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Thorsten Kukuk + * Copyright (c) 2006, 2008 Thorsten Kukuk * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -117,6 +117,7 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) { int status = 0; pid_t retval; + while ((retval = waitpid (pid, &status, 0)) == -1 && errno == EINTR); if (retval == (pid_t)-1) @@ -160,6 +161,8 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) { char **arggv; int i; + char **envlist, **tmp; + int envlen, nitems; for (i = 0; i < sysconf (_SC_OPEN_MAX); i++) close (i); @@ -229,9 +232,6 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) arggv[i] = strdup(argv[i+optargc]); arggv[i] = NULL; - char **envlist, **tmp; - int envlen, nitems; - /* * Set up the child's environment list. It consists of the PAM * environment, plus a few hand-picked PAM items. -- cgit v1.2.3 From 0323cbc3d94badc4d5e941a8fb679444dcb72bbb Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 11 Jul 2008 15:29:00 +0000 Subject: Relevant BUGIDs: #2009766 Purpose of commit: bugfix Commit summary: --------------- 2008-07-11 Tomas Mraz * modules/pam_unix/pam_unix_acct.c (_unix_run_verify_binary): Do not close the pipe descriptor in borderline case (#2009766) * modules/pam_unix/pam_unix_passwd.c (_unix_run_update_binary): Likewise. * modules/pam_unix/support.c (_unix_run_helper_binary): Likewise. * modules/pam_unix/support.h: Define upper limit of fds we will attempt to close. --- modules/pam_unix/pam_unix_acct.c | 13 ++++++------- modules/pam_unix/pam_unix_passwd.c | 10 +++++----- modules/pam_unix/support.c | 8 ++++---- modules/pam_unix/support.h | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) (limited to 'modules') diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index c09bc175..3a40d8d3 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -91,21 +91,21 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, /* fork */ child = fork(); if (child == 0) { - size_t i=0; + int i=0; struct rlimit rlim; static char *envp[] = { NULL }; char *args[] = { NULL, NULL, NULL, NULL }; - close(0); close(1); - /* reopen stdin as pipe */ - close(fds[0]); + /* reopen stdout as pipe */ dup2(fds[1], STDOUT_FILENO); /* XXX - should really tidy up PAM here too */ if (getrlimit(RLIMIT_NOFILE,&rlim)==0) { - for (i=2; i < rlim.rlim_max; i++) { - if ((unsigned int)fds[1] != i) { + if (rlim.rlim_max >= MAX_FD_NO) + rlim.rlim_max = MAX_FD_NO; + for (i=0; i < (int)rlim.rlim_max; i++) { + if (i != STDOUT_FILENO) { close(i); } } @@ -126,7 +126,6 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, pam_syslog(pamh, LOG_ERR, "helper binary execve failed: %m"); /* should not get here: exit with error */ - close (fds[1]); D(("helper binary is not available")); printf("-1\n"); exit(PAM_AUTHINFO_UNAVAIL); diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 0a429756..abb04c53 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -163,7 +163,7 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const /* fork */ child = fork(); if (child == 0) { - size_t i=0; + int i=0; struct rlimit rlim; static char *envp[] = { NULL }; char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL }; @@ -171,14 +171,14 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const /* XXX - should really tidy up PAM here too */ - close(0); close(1); /* reopen stdin as pipe */ - close(fds[1]); dup2(fds[0], STDIN_FILENO); if (getrlimit(RLIMIT_NOFILE,&rlim)==0) { - for (i=2; i < rlim.rlim_max; i++) { - if ((unsigned int)fds[0] != i) + if (rlim.rlim_max >= MAX_FD_NO) + rlim.rlim_max = MAX_FD_NO; + for (i=0; i < (int)rlim.rlim_max; i++) { + if (i != STDIN_FILENO) close(i); } } diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 781d0006..db630f51 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -427,14 +427,14 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, /* XXX - should really tidy up PAM here too */ - close(0); close(1); /* reopen stdin as pipe */ - close(fds[1]); dup2(fds[0], STDIN_FILENO); if (getrlimit(RLIMIT_NOFILE,&rlim)==0) { - for (i=2; i < (int)rlim.rlim_max; i++) { - if (fds[0] != i) + if (rlim.rlim_max >= MAX_FD_NO) + rlim.rlim_max = MAX_FD_NO; + for (i=0; i < (int)rlim.rlim_max; i++) { + if (i != STDIN_FILENO) close(i); } } diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h index 9d4f8b85..a33dadaa 100644 --- a/modules/pam_unix/support.h +++ b/modules/pam_unix/support.h @@ -91,7 +91,6 @@ typedef struct { /* -------------- */ #define UNIX_CTRLS_ 26 /* number of ctrl arguments defined */ - static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = { /* symbol token name ctrl mask ctrl * @@ -127,6 +126,7 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) +#define MAX_FD_NO 2000000 /* use this to free strings. ESPECIALLY password strings */ -- cgit v1.2.3 From 3c3bb4c3659615ffba1b23f537120ea996e8a774 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 11 Jul 2008 15:37:28 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-07-11 Tomas Mraz * modules/pam_selinux/pam_selinux.c (config_context): Do not ask for the level if use_current_range is set. (context_from_env): New function to obtain the context from PAM environment variables. (pam_sm_open_session): Call context_from_env() if env_params option is present. use_current_range now modifies behavior of the context_from_env and config_context options. * modules/pam_selinux/pam_selinux.8.xml: Describe the env_params option. Adjust description of use_current_range option. --- modules/pam_selinux/pam_selinux.8.xml | 25 +++- modules/pam_selinux/pam_selinux.c | 208 +++++++++++++++++++++++----------- 2 files changed, 166 insertions(+), 67 deletions(-) (limited to 'modules') diff --git a/modules/pam_selinux/pam_selinux.8.xml b/modules/pam_selinux/pam_selinux.8.xml index 3acd1322..ab368a87 100644 --- a/modules/pam_selinux/pam_selinux.8.xml +++ b/modules/pam_selinux/pam_selinux.8.xml @@ -36,6 +36,9 @@ select_context + + env_params + use_current_range @@ -135,14 +138,32 @@ + + + + + + + Attempt to obtain a custom security context role from PAM environment. + If MLS is on obtain also sensitivity level. This option and the + select_context option are mutually exclusive. The respective PAM + environment variables are SELINUX_ROLE_REQUESTED, + SELINUX_LEVEL_REQUESTED, and + SELINUX_USE_CURRENT_RANGE. The first two variables + are self describing and the last one if set to 1 makes the PAM module behave as + if the use_current_range was specified on the command line of the module. + + + - Use the sensitivity range of the process for the user context. - This option and the select_context option are mutually exclusive. + Use the sensitivity level of the current process for the user context + instead of the default level. Also supresses asking of the + sensitivity level from the user or obtaining it from PAM environment. diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c index da1290f0..e45d6f99 100644 --- a/modules/pam_selinux/pam_selinux.c +++ b/modules/pam_selinux/pam_selinux.c @@ -2,8 +2,9 @@ * A module for Linux-PAM that will set the default security context after login * via PAM. * - * Copyright (c) 2003 Red Hat, Inc. + * Copyright (c) 2003-2008 Red Hat, Inc. * Written by Dan Walsh + * Additional improvements by Tomas Mraz * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -252,7 +253,7 @@ static int mls_range_allowed(pam_handle_t *pamh, security_context_t src, securit } static security_context_t -config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) +config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_current_range, int debug) { security_context_t newcon=NULL; context_t new_context; @@ -261,7 +262,7 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) char *type=NULL; char resp_val = 0; - pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), puser_context); + pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), defaultcon); while (1) { if (query_response(pamh, @@ -274,7 +275,7 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) } if ((resp_val == 'y') || (resp_val == 'Y')) { - if ((new_context = context_new(puser_context)) == NULL) + if ((new_context = context_new(defaultcon)) == NULL) goto fail_set; /* Allow the user to enter role and level individually */ @@ -295,10 +296,27 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) if (mls_enabled) { - if (query_response(pamh, _("level:"), context_range_get(new_context), + if (use_current_range) { + security_context_t mycon = NULL; + context_t my_context; + + if (getcon(&mycon) != 0) + goto fail_set; + my_context = context_new(mycon); + if (my_context == NULL) { + freecon(mycon); + goto fail_set; + } + freecon(mycon); + if (context_range_set(new_context, context_range_get(my_context))) { + context_free(my_context); + goto fail_set; + } + context_free(my_context); + } else if (query_response(pamh, _("level:"), context_range_get(new_context), &response, debug) == PAM_SUCCESS && response[0]) { - if (context_range_set(new_context, response)) - goto fail_set; + if (context_range_set(new_context, response)) + goto fail_set; } _pam_drop(response); } @@ -309,15 +327,17 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) /* Get the string value of the context and see if it is valid. */ if (!security_check_context(context_str(new_context))) { newcon = strdup(context_str(new_context)); - context_free (new_context); + if (newcon == NULL) + goto fail_set; + context_free(new_context); /* we have to check that this user is allowed to go into the range they have specified ... role is tied to an seuser, so that'll be checked at setexeccon time */ - if (mls_enabled && !mls_range_allowed(pamh, puser_context, newcon, debug)) { - pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", puser_context, newcon); + if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) { + pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon); - send_audit_message(pamh, 0, puser_context, newcon); + send_audit_message(pamh, 0, defaultcon, newcon); free(newcon); goto fail_range; @@ -325,13 +345,13 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) return newcon; } else { - send_audit_message(pamh, 0, puser_context, context_str(new_context)); + send_audit_message(pamh, 0, defaultcon, context_str(new_context)); send_text(pamh,_("Not a valid security context"),debug); } context_free(new_context); /* next time around allocates another */ } else - return strdup(puser_context); + return strdup(defaultcon); } /* end while */ return NULL; @@ -340,11 +360,105 @@ config_context (pam_handle_t *pamh, security_context_t puser_context, int debug) free(type); _pam_drop(response); context_free (new_context); - send_audit_message(pamh, 0, puser_context, NULL); + send_audit_message(pamh, 0, defaultcon, NULL); fail_range: return NULL; } +static security_context_t +context_from_env (pam_handle_t *pamh, security_context_t defaultcon, int env_params, int use_current_range, int debug) +{ + security_context_t newcon = NULL; + context_t new_context; + context_t my_context = NULL; + int mls_enabled = is_selinux_mls_enabled(); + const char *env = NULL; + char *type = NULL; + + if ((new_context = context_new(defaultcon)) == NULL) + goto fail_set; + + if (env_params && (env = pam_getenv(pamh, "SELINUX_ROLE_REQUESTED")) != NULL && env[0] != '\0') { + if (debug) + pam_syslog(pamh, LOG_NOTICE, "Requested role: %s", env); + + if (get_default_type(env, &type)) { + pam_syslog(pamh, LOG_NOTICE, "No default type for role %s", env); + goto fail_set; + } else { + if (context_role_set(new_context, env)) + goto fail_set; + if (context_type_set(new_context, type)) + goto fail_set; + } + } + + if (mls_enabled) { + if ((env = pam_getenv(pamh, "SELINUX_USE_CURRENT_RANGE")) != NULL && env[0] == '1') { + if (debug) + pam_syslog(pamh, LOG_NOTICE, "SELINUX_USE_CURRENT_RANGE is set"); + use_current_range = 1; + } + + if (use_current_range) { + security_context_t mycon = NULL; + + if (getcon(&mycon) != 0) + goto fail_set; + my_context = context_new(mycon); + if (my_context == NULL) { + freecon(mycon); + goto fail_set; + } + freecon(mycon); + env = context_range_get(my_context); + } else { + env = pam_getenv(pamh, "SELINUX_LEVEL_REQUESTED"); + } + + if (env != NULL && env[0] != '\0') { + if (debug) + pam_syslog(pamh, LOG_NOTICE, "Requested level: %s", env); + if (context_range_set(new_context, env)) + goto fail_set; + } + } + + newcon = strdup(context_str(new_context)); + if (newcon == NULL) + goto fail_set; + + if (debug) + pam_syslog(pamh, LOG_NOTICE, "Selected Security Context %s", newcon); + + /* Get the string value of the context and see if it is valid. */ + if (security_check_context(newcon)) { + pam_syslog(pamh, LOG_NOTICE, "Not a valid security context %s", newcon); + send_audit_message(pamh, 0, defaultcon, newcon); + freecon(newcon); + newcon = NULL; + + goto fail_set; + } + + /* we have to check that this user is allowed to go into the + range they have specified ... role is tied to an seuser, so that'll + be checked at setexeccon time */ + if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) { + pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon); + send_audit_message(pamh, 0, defaultcon, newcon); + freecon(newcon); + newcon = NULL; + } + + fail_set: + free(type); + context_free(my_context); + context_free(new_context); + send_audit_message(pamh, 0, defaultcon, NULL); + return newcon; +} + static void security_restorelabel_tty(const pam_handle_t *pamh, const char *tty, security_context_t context) @@ -462,6 +576,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int ret = 0; security_context_t* contextlist = NULL; int num_contexts = 0; + int env_params = 0; const char *username = NULL; const void *tty = NULL; char *seuser=NULL; @@ -488,13 +603,16 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, if (strcmp(argv[i], "use_current_range") == 0) { use_current_range = 1; } + if (strcmp(argv[i], "env_params") == 0) { + env_params = 1; + } } if (debug) pam_syslog(pamh, LOG_NOTICE, "Open Session"); - if (select_context && use_current_range) { - pam_syslog(pamh, LOG_ERR, "select_context cannot be used with use_current_range"); + if (select_context && env_params) { + pam_syslog(pamh, LOG_ERR, "select_context cannot be used with env_params"); select_context = 0; } @@ -526,12 +644,17 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, freeconary(contextlist); if (default_user_context == NULL) { pam_syslog(pamh, LOG_ERR, "Out of memory"); - return PAM_AUTH_ERR; + return PAM_BUF_ERR; } + user_context = default_user_context; if (select_context) { - user_context = config_context(pamh, default_user_context, debug); - if (user_context == NULL) { + user_context = config_context(pamh, default_user_context, use_current_range, debug); + } else if (env_params || use_current_range) { + user_context = context_from_env(pamh, default_user_context, env_params, use_current_range, debug); + } + + if (user_context == NULL) { freecon(default_user_context); pam_syslog(pamh, LOG_ERR, "Unable to get valid context for %s", username); @@ -540,8 +663,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, return PAM_AUTH_ERR; else return PAM_SUCCESS; - } - } + } } else { user_context = manual_context(pamh,seuser,debug); @@ -555,50 +677,6 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, } } - if (use_current_range && is_selinux_mls_enabled()) { - security_context_t process_context=NULL; - if (getcon(&process_context) == 0) { - context_t pcon, ucon; - char *process_level=NULL; - security_context_t orig_context; - - if (user_context) - orig_context = user_context; - else - orig_context = default_user_context; - - pcon = context_new(process_context); - freecon(process_context); - process_level = strdup(context_range_get(pcon)); - context_free(pcon); - - if (debug) - pam_syslog (pamh, LOG_DEBUG, "process level=%s", process_level); - - ucon = context_new(orig_context); - - context_range_set(ucon, process_level); - free(process_level); - - if (!mls_range_allowed(pamh, orig_context, context_str(ucon), debug)) { - send_text(pamh, _("Requested MLS level not in permitted range"), debug); - /* even if default_user_context is NULL audit that anyway */ - send_audit_message(pamh, 0, default_user_context, context_str(ucon)); - context_free(ucon); - return PAM_AUTH_ERR; - } - - if (debug) - pam_syslog (pamh, LOG_DEBUG, "adjusted context=%s", context_str(ucon)); - - /* replace the user context with the level adjusted one */ - freecon(user_context); - user_context = strdup(context_str(ucon)); - - context_free(ucon); - } - } - if (getexeccon(&prev_user_context)<0) { prev_user_context=NULL; } -- cgit v1.2.3 From 43c4ee3643350ead3ba4ef9d16a959f6934e310e Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Sun, 13 Jul 2008 17:14:13 +0000 Subject: Relevant BUGIDs: #1980773 Purpose of commit: bugfix Commit summary: --------------- 2008-07-13 Tomas Mraz * modules/pam_mail/pam_mail.8.xml: Module supports session and not account service (#1980773). --- modules/pam_mail/pam_mail.8.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/pam_mail/pam_mail.8.xml b/modules/pam_mail/pam_mail.8.xml index d3c481a5..2e97d999 100644 --- a/modules/pam_mail/pam_mail.8.xml +++ b/modules/pam_mail/pam_mail.8.xml @@ -196,8 +196,9 @@ MODULE SERVICES PROVIDED - The auth and - account services are supported. + The session and + auth (on establishment and + deletion of credentials) services are supported. -- cgit v1.2.3 From c5d4bcfc192189b1d79c9b2e397bd8eade5b16db Mon Sep 17 00:00:00 2001 From: Steve Langasek Date: Sun, 27 Jul 2008 04:47:54 +0000 Subject: Relevant BUGIDs: Debian bug #439984 Purpose of commit: bugfix Commit summary: --------------- 2008-07-26 Steve Langasek * modules/pam_env/pam_env.c: Fix module to skip over non-alphanumeric variable names, and to handle the case when asked to delete a non-existent variable. --- modules/pam_env/pam_env.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c index bcbb1881..80a20cd6 100644 --- a/modules/pam_env/pam_env.c +++ b/modules/pam_env/pam_env.c @@ -232,9 +232,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 +253,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) { -- cgit v1.2.3 From 498944b7863f188fa1d8e3c4c620bb1681294fee Mon Sep 17 00:00:00 2001 From: Steve Langasek Date: Sun, 27 Jul 2008 09:11:48 +0000 Subject: Relevant BUGIDs: Debian bug #470137 Purpose of commit: bugfix Commit summary: --------------- 2008-07-27 Steve Langasek * modules/pam_*/pam_*.8.xml: fix up the references to pam.d, which is in manpage section 5, not 8. --- modules/pam_access/pam_access.8.xml | 2 +- modules/pam_cracklib/pam_cracklib.8.xml | 2 +- modules/pam_debug/pam_debug.8.xml | 2 +- modules/pam_deny/pam_deny.8.xml | 2 +- modules/pam_echo/pam_echo.8.xml | 2 +- modules/pam_env/pam_env.8.xml | 2 +- modules/pam_exec/pam_exec.8.xml | 2 +- modules/pam_faildelay/pam_faildelay.8.xml | 2 +- modules/pam_filter/pam_filter.8.xml | 2 +- modules/pam_ftp/pam_ftp.8.xml | 2 +- modules/pam_group/pam_group.8.xml | 2 +- modules/pam_issue/pam_issue.8.xml | 2 +- modules/pam_keyinit/pam_keyinit.8.xml | 2 +- modules/pam_lastlog/pam_lastlog.8.xml | 2 +- modules/pam_limits/pam_limits.8.xml | 2 +- modules/pam_listfile/pam_listfile.8.xml | 2 +- modules/pam_localuser/pam_localuser.8.xml | 2 +- modules/pam_loginuid/pam_loginuid.8.xml | 2 +- modules/pam_mail/pam_mail.8.xml | 2 +- modules/pam_mkhomedir/pam_mkhomedir.8.xml | 2 +- modules/pam_motd/pam_motd.8.xml | 2 +- modules/pam_namespace/pam_namespace.8.xml | 2 +- modules/pam_nologin/pam_nologin.8.xml | 2 +- modules/pam_permit/pam_permit.8.xml | 2 +- modules/pam_rhosts/pam_rhosts.8.xml | 2 +- modules/pam_rootok/pam_rootok.8.xml | 2 +- modules/pam_securetty/pam_securetty.8.xml | 2 +- modules/pam_selinux/pam_selinux.8.xml | 2 +- modules/pam_shells/pam_shells.8.xml | 2 +- modules/pam_tally/pam_tally.8.xml | 2 +- modules/pam_time/pam_time.8.xml | 2 +- modules/pam_umask/pam_umask.8.xml | 2 +- modules/pam_unix/pam_unix.8.xml | 2 +- modules/pam_userdb/pam_userdb.8.xml | 2 +- modules/pam_warn/pam_warn.8.xml | 2 +- modules/pam_wheel/pam_wheel.8.xml | 2 +- modules/pam_xauth/pam_xauth.8.xml | 2 +- 37 files changed, 37 insertions(+), 37 deletions(-) (limited to 'modules') diff --git a/modules/pam_access/pam_access.8.xml b/modules/pam_access/pam_access.8.xml index 21970d49..68f21bab 100644 --- a/modules/pam_access/pam_access.8.xml +++ b/modules/pam_access/pam_access.8.xml @@ -231,7 +231,7 @@ access.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_cracklib/pam_cracklib.8.xml b/modules/pam_cracklib/pam_cracklib.8.xml index 823a0bce..c1731d29 100644 --- a/modules/pam_cracklib/pam_cracklib.8.xml +++ b/modules/pam_cracklib/pam_cracklib.8.xml @@ -495,7 +495,7 @@ password required pam_unix.so use_authtok nullok md5 pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_debug/pam_debug.8.xml b/modules/pam_debug/pam_debug.8.xml index 65519852..db775067 100644 --- a/modules/pam_debug/pam_debug.8.xml +++ b/modules/pam_debug/pam_debug.8.xml @@ -213,7 +213,7 @@ auth sufficient pam_debug.so auth=success cred=success pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_deny/pam_deny.8.xml b/modules/pam_deny/pam_deny.8.xml index e50beb2d..4f45fa9a 100644 --- a/modules/pam_deny/pam_deny.8.xml +++ b/modules/pam_deny/pam_deny.8.xml @@ -117,7 +117,7 @@ other session required pam_deny.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_echo/pam_echo.8.xml b/modules/pam_echo/pam_echo.8.xml index 4a495195..4f4c2428 100644 --- a/modules/pam_echo/pam_echo.8.xml +++ b/modules/pam_echo/pam_echo.8.xml @@ -154,7 +154,7 @@ password required pam_unix.so pam.conf8 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_env/pam_env.8.xml b/modules/pam_env/pam_env.8.xml index 731c20b2..1187d507 100644 --- a/modules/pam_env/pam_env.8.xml +++ b/modules/pam_env/pam_env.8.xml @@ -189,7 +189,7 @@ pam_env.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_exec/pam_exec.8.xml b/modules/pam_exec/pam_exec.8.xml index f4dc1e15..3ee5315e 100644 --- a/modules/pam_exec/pam_exec.8.xml +++ b/modules/pam_exec/pam_exec.8.xml @@ -199,7 +199,7 @@ pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_faildelay/pam_faildelay.8.xml b/modules/pam_faildelay/pam_faildelay.8.xml index d2dfd266..57b3305a 100644 --- a/modules/pam_faildelay/pam_faildelay.8.xml +++ b/modules/pam_faildelay/pam_faildelay.8.xml @@ -118,7 +118,7 @@ auth optional pam_faildelay.so delay=10000000 pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_filter/pam_filter.8.xml b/modules/pam_filter/pam_filter.8.xml index d15d7e97..faf97911 100644 --- a/modules/pam_filter/pam_filter.8.xml +++ b/modules/pam_filter/pam_filter.8.xml @@ -243,7 +243,7 @@ pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_ftp/pam_ftp.8.xml b/modules/pam_ftp/pam_ftp.8.xml index aca21694..f99256c0 100644 --- a/modules/pam_ftp/pam_ftp.8.xml +++ b/modules/pam_ftp/pam_ftp.8.xml @@ -165,7 +165,7 @@ auth required pam_listfile.so \ pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_group/pam_group.8.xml b/modules/pam_group/pam_group.8.xml index f7488fb3..114d0c51 100644 --- a/modules/pam_group/pam_group.8.xml +++ b/modules/pam_group/pam_group.8.xml @@ -145,7 +145,7 @@ group.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_issue/pam_issue.8.xml b/modules/pam_issue/pam_issue.8.xml index fd0d06ae..916dd5e7 100644 --- a/modules/pam_issue/pam_issue.8.xml +++ b/modules/pam_issue/pam_issue.8.xml @@ -216,7 +216,7 @@ pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_keyinit/pam_keyinit.8.xml b/modules/pam_keyinit/pam_keyinit.8.xml index c7dddf54..f3e64b3d 100644 --- a/modules/pam_keyinit/pam_keyinit.8.xml +++ b/modules/pam_keyinit/pam_keyinit.8.xml @@ -220,7 +220,7 @@ session required pam_keyinit.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml index 066eff58..a738402c 100644 --- a/modules/pam_lastlog/pam_lastlog.8.xml +++ b/modules/pam_lastlog/pam_lastlog.8.xml @@ -213,7 +213,7 @@ pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_limits/pam_limits.8.xml b/modules/pam_limits/pam_limits.8.xml index 98afdcd4..05c4d160 100644 --- a/modules/pam_limits/pam_limits.8.xml +++ b/modules/pam_limits/pam_limits.8.xml @@ -239,7 +239,7 @@ session required pam_limits.so limits.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_listfile/pam_listfile.8.xml b/modules/pam_listfile/pam_listfile.8.xml index e54e80a4..d33cdb1e 100644 --- a/modules/pam_listfile/pam_listfile.8.xml +++ b/modules/pam_listfile/pam_listfile.8.xml @@ -278,7 +278,7 @@ auth required pam_listfile.so \ pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_localuser/pam_localuser.8.xml b/modules/pam_localuser/pam_localuser.8.xml index ac00ce99..cae98ca1 100644 --- a/modules/pam_localuser/pam_localuser.8.xml +++ b/modules/pam_localuser/pam_localuser.8.xml @@ -155,7 +155,7 @@ account required pam_wheel.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_loginuid/pam_loginuid.8.xml b/modules/pam_loginuid/pam_loginuid.8.xml index f50336d0..801c88f9 100644 --- a/modules/pam_loginuid/pam_loginuid.8.xml +++ b/modules/pam_loginuid/pam_loginuid.8.xml @@ -101,7 +101,7 @@ session required pam_loginuid.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_mail/pam_mail.8.xml b/modules/pam_mail/pam_mail.8.xml index 2e97d999..17677c73 100644 --- a/modules/pam_mail/pam_mail.8.xml +++ b/modules/pam_mail/pam_mail.8.xml @@ -262,7 +262,7 @@ session optional pam_mail.so standard pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_mkhomedir/pam_mkhomedir.8.xml b/modules/pam_mkhomedir/pam_mkhomedir.8.xml index 3c40de15..aeb619f0 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.8.xml +++ b/modules/pam_mkhomedir/pam_mkhomedir.8.xml @@ -186,7 +186,7 @@ SEE ALSO - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_motd/pam_motd.8.xml b/modules/pam_motd/pam_motd.8.xml index 7bd6798c..69e9efd8 100644 --- a/modules/pam_motd/pam_motd.8.xml +++ b/modules/pam_motd/pam_motd.8.xml @@ -96,7 +96,7 @@ session optional pam_motd.so motd=/etc/motd pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml index 787aba4a..bb9b3e34 100644 --- a/modules/pam_namespace/pam_namespace.8.xml +++ b/modules/pam_namespace/pam_namespace.8.xml @@ -365,7 +365,7 @@ namespace.conf5 , - pam.d8 + pam.d5 , mount8 diff --git a/modules/pam_nologin/pam_nologin.8.xml b/modules/pam_nologin/pam_nologin.8.xml index 9710df9d..c9a81792 100644 --- a/modules/pam_nologin/pam_nologin.8.xml +++ b/modules/pam_nologin/pam_nologin.8.xml @@ -156,7 +156,7 @@ auth required pam_nologin.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_permit/pam_permit.8.xml b/modules/pam_permit/pam_permit.8.xml index 4db7a963..6ecc34ac 100644 --- a/modules/pam_permit/pam_permit.8.xml +++ b/modules/pam_permit/pam_permit.8.xml @@ -87,7 +87,7 @@ account required pam_permit.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_rhosts/pam_rhosts.8.xml b/modules/pam_rhosts/pam_rhosts.8.xml index e559f315..194f956e 100644 --- a/modules/pam_rhosts/pam_rhosts.8.xml +++ b/modules/pam_rhosts/pam_rhosts.8.xml @@ -153,7 +153,7 @@ auth required pam_unix.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_rootok/pam_rootok.8.xml b/modules/pam_rootok/pam_rootok.8.xml index ec8dee43..ed26d357 100644 --- a/modules/pam_rootok/pam_rootok.8.xml +++ b/modules/pam_rootok/pam_rootok.8.xml @@ -112,7 +112,7 @@ auth required pam_unix.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_securetty/pam_securetty.8.xml b/modules/pam_securetty/pam_securetty.8.xml index ef8562ea..0ba44413 100644 --- a/modules/pam_securetty/pam_securetty.8.xml +++ b/modules/pam_securetty/pam_securetty.8.xml @@ -149,7 +149,7 @@ auth required pam_unix.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_selinux/pam_selinux.8.xml b/modules/pam_selinux/pam_selinux.8.xml index ab368a87..d9ff1770 100644 --- a/modules/pam_selinux/pam_selinux.8.xml +++ b/modules/pam_selinux/pam_selinux.8.xml @@ -223,7 +223,7 @@ session optional pam_selinux.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_shells/pam_shells.8.xml b/modules/pam_shells/pam_shells.8.xml index abbd5cbd..72191da8 100644 --- a/modules/pam_shells/pam_shells.8.xml +++ b/modules/pam_shells/pam_shells.8.xml @@ -99,7 +99,7 @@ auth required pam_shells.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_tally/pam_tally.8.xml b/modules/pam_tally/pam_tally.8.xml index 68b69a30..bd86e80f 100644 --- a/modules/pam_tally/pam_tally.8.xml +++ b/modules/pam_tally/pam_tally.8.xml @@ -435,7 +435,7 @@ session optional pam_mail.so standard pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_time/pam_time.8.xml b/modules/pam_time/pam_time.8.xml index e0b149a7..490a793c 100644 --- a/modules/pam_time/pam_time.8.xml +++ b/modules/pam_time/pam_time.8.xml @@ -166,7 +166,7 @@ login account required pam_time.so time.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_umask/pam_umask.8.xml b/modules/pam_umask/pam_umask.8.xml index d65e6660..43eba83b 100644 --- a/modules/pam_umask/pam_umask.8.xml +++ b/modules/pam_umask/pam_umask.8.xml @@ -202,7 +202,7 @@ pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml index 290cb2b9..e6a5e7fc 100644 --- a/modules/pam_unix/pam_unix.8.xml +++ b/modules/pam_unix/pam_unix.8.xml @@ -361,7 +361,7 @@ session required pam_unix.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_userdb/pam_userdb.8.xml b/modules/pam_userdb/pam_userdb.8.xml index 70b416b3..ea2ebfe6 100644 --- a/modules/pam_userdb/pam_userdb.8.xml +++ b/modules/pam_userdb/pam_userdb.8.xml @@ -274,7 +274,7 @@ auth sufficient pam_userdb.so icase db=/etc/dbtest.db pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_warn/pam_warn.8.xml b/modules/pam_warn/pam_warn.8.xml index b3261b86..04f29283 100644 --- a/modules/pam_warn/pam_warn.8.xml +++ b/modules/pam_warn/pam_warn.8.xml @@ -86,7 +86,7 @@ other session required pam_deny.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_wheel/pam_wheel.8.xml b/modules/pam_wheel/pam_wheel.8.xml index bf8b7349..1a344d08 100644 --- a/modules/pam_wheel/pam_wheel.8.xml +++ b/modules/pam_wheel/pam_wheel.8.xml @@ -224,7 +224,7 @@ su auth required pam_unix.so pam.conf5 , - pam.d8 + pam.d5 , pam8 diff --git a/modules/pam_xauth/pam_xauth.8.xml b/modules/pam_xauth/pam_xauth.8.xml index f6323f26..78184fdb 100644 --- a/modules/pam_xauth/pam_xauth.8.xml +++ b/modules/pam_xauth/pam_xauth.8.xml @@ -273,7 +273,7 @@ session optional pam_xauth.so pam.conf5 , - pam.d8 + pam.d5 , pam8 -- cgit v1.2.3 From cd72839ac8265051051e5d70efa840dfd6bdd34f Mon Sep 17 00:00:00 2001 From: Steve Langasek Date: Sun, 27 Jul 2008 21:59:42 +0000 Subject: Relevant BUGIDs: Debian bug #488690 Purpose of commit: bugfix Commit summary: --------------- 2008-07-27 Steve Langasek * modules/pam_env/environment, modules/pam_env/pam_env.8.xml: spelling fix, seperate -> separate --- modules/pam_env/environment | 2 +- modules/pam_env/pam_env.8.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/pam_env/environment b/modules/pam_env/environment index f46b8d94..3e704a6b 100644 --- a/modules/pam_env/environment +++ b/modules/pam_env/environment @@ -1,5 +1,5 @@ # # This file is parsed by pam_env module # -# Syntax: simple "KEY=VAL" pairs on seperate lines +# Syntax: simple "KEY=VAL" pairs on separate lines # diff --git a/modules/pam_env/pam_env.8.xml b/modules/pam_env/pam_env.8.xml index 1187d507..ecf0355a 100644 --- a/modules/pam_env/pam_env.8.xml +++ b/modules/pam_env/pam_env.8.xml @@ -53,7 +53,7 @@ This module can also parse a file with simple - KEY=VAL pairs on seperate lines + KEY=VAL pairs on separate lines (/etc/environment by default). You can change the default file to parse, with the envfile flag and turn it on or off by setting the readenv -- cgit v1.2.3 From b4a78564bec722ef5b17dbba4b2830b2c8d2085b Mon Sep 17 00:00:00 2001 From: Steve Langasek Date: Mon, 28 Jul 2008 20:51:56 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix (thread safety) Commit summary: --------------- 2008-07-28 Steve Langasek * modules/pam_unix/passverify.c: make save_old_password() thread-safe by using pam_modutil_getpwnam() instead of getpwnam() * modules/pam_unix/passverify.c, modules/pam_unix/passverify.h, modules/pam_unix/pam_unix_passwd.c: add pamh argument to save_old_password() --- modules/pam_unix/pam_unix_passwd.c | 2 +- modules/pam_unix/passverify.c | 8 +++++++- modules/pam_unix/passverify.h | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index abb04c53..240caddb 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -378,7 +378,7 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho, return _unix_run_update_binary(pamh, ctrl, forwho, fromwhat, towhat, remember); #endif /* first, save old password */ - if (save_old_password(forwho, fromwhat, remember)) { + if (save_old_password(pamh, forwho, fromwhat, remember)) { retval = PAM_AUTHTOK_ERR; goto done; } diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index ce5bc450..0f58b019 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -535,9 +535,15 @@ unlock_pwdf(void) } #endif +#ifdef HELPER_COMPILE int save_old_password(const char *forwho, const char *oldpass, int howmany) +#else +int +save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, + int howmany) +#endif { static char buf[16384]; static char nbuf[16384]; @@ -653,7 +659,7 @@ save_old_password(const char *forwho, const char *oldpass, fclose(opwfile); if (!found) { - pwd = getpwnam(forwho); + pwd = pam_modutil_getpwnam(pamh, forwho); if (pwd == NULL) { err = 1; } else { diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h index e8e112d0..21bb9232 100644 --- a/modules/pam_unix/passverify.h +++ b/modules/pam_unix/passverify.h @@ -33,9 +33,15 @@ lock_pwdf(void); void unlock_pwdf(void); +#ifdef HELPER_COMPILE int save_old_password(const char *forwho, const char *oldpass, int howmany); +#else +int +save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, + int howmany); +#endif #ifdef HELPER_COMPILE void -- cgit v1.2.3 From 68eb48b63d297db91cf371373e4187fda4830280 Mon Sep 17 00:00:00 2001 From: Steve Langasek Date: Tue, 29 Jul 2008 22:33:37 +0000 Subject: Relevant BUGIDs: Ubuntu bug #175686 Purpose of commit: grammar fix Commit summary: --------------- 2008-07-29 Steve Langasek * modules/pam_cracklib/pam_cracklib.8.xml: correct a typo, "Only he" -> "Only the" --- modules/pam_cracklib/pam_cracklib.8.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_cracklib/pam_cracklib.8.xml b/modules/pam_cracklib/pam_cracklib.8.xml index c1731d29..ee9a5917 100644 --- a/modules/pam_cracklib/pam_cracklib.8.xml +++ b/modules/pam_cracklib/pam_cracklib.8.xml @@ -379,7 +379,7 @@ MODULE SERVICES PROVIDED - Only he service is supported. + Only the service is supported. -- cgit v1.2.3 From 374a7652e6ebeb9b731c41cf48aa83b603faae3e Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Mon, 18 Aug 2008 13:29:21 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-08-18 Thorsten Kukuk * Makefile.am (M4_FILES): Adjust list. * modules/pam_access/pam_access.8.xml: Fix module service vs. module type. * modules/pam_cracklib/pam_cracklib.8.xml: Likewise. * modules/pam_debug/pam_debug.8.xml: Likewise. * modules/pam_deny/pam_deny.8.xml: Likewise. * modules/pam_echo/pam_echo.8.xml: Likewise. * modules/pam_env/pam_env.8.xml: Likewise. * modules/pam_exec/pam_exec.8.xml: Likewise. * modules/pam_faildelay/pam_faildelay.8.xml: Likewise. * modules/pam_filter/pam_filter.8.xml: Likewise. * modules/pam_ftp/pam_ftp.8.xml: Likewise. * modules/pam_group/pam_group.8.xml: Likewise. * modules/pam_issue/pam_issue.8.xml: Likewise. * modules/pam_keyinit/pam_keyinit.8.xml: Likewise. * modules/pam_lastlog/pam_lastlog.8.xml: Likewise. * modules/pam_limits/pam_limits.8.xml: Likewise. * modules/pam_listfile/pam_listfile.8.xml: Likewise. * modules/pam_localuser/pam_localuser.8.xml: Likewise. * modules/pam_loginuid/pam_loginuid.8.xml: Likewise. * modules/pam_mail/pam_mail.8.xml: Likewise. * modules/pam_mkhomedir/pam_mkhomedir.8.xml: Likewise. * modules/pam_motd/pam_motd.8.xml: Likewise. * modules/pam_namespace/pam_namespace.8.xml: Likewise. * modules/pam_nologin/pam_nologin.8.xml: Likewise. * modules/pam_permit/pam_permit.8.xml: Likewise. * modules/pam_rhosts/pam_rhosts.8.xml: Likewise. * modules/pam_rootok/pam_rootok.8.xml: Likewise. * modules/pam_securetty/pam_securetty.8.xml: Likewise. * modules/pam_selinux/pam_selinux.8.xml: Likewise. * modules/pam_sepermit/pam_sepermit.8.xml: Likewise. * modules/pam_shells/pam_shells.8.xml: Likewise. * modules/pam_succeed_if/pam_succeed_if.8.xml: Likewise. * modules/pam_tally/pam_tally.8.xml: Likewise. * modules/pam_time/pam_time.8.xml: Likewise. * modules/pam_tty_audit/pam_tty_audit.8.xml: Likewise. * modules/pam_umask/pam_umask.8.xml: Likewise. * modules/pam_unix/pam_unix.8.xml: Likewise. * modules/pam_userdb/pam_userdb.8.xml: Likewise. * modules/pam_warn/pam_warn.8.xml: Likewise. * modules/pam_wheel/pam_wheel.8.xml: Likewise. * modules/pam_xauth/pam_xauth.8.xml: Likewise. --- modules/pam_access/pam_access.8.xml | 9 +++++---- modules/pam_cracklib/pam_cracklib.8.xml | 6 +++--- modules/pam_debug/pam_debug.8.xml | 8 ++++---- modules/pam_deny/pam_deny.8.xml | 8 ++++---- modules/pam_echo/pam_echo.8.xml | 8 +++++--- modules/pam_env/pam_env.8.xml | 8 ++++---- modules/pam_exec/pam_exec.8.xml | 8 ++++---- modules/pam_faildelay/pam_faildelay.8.xml | 6 +++--- modules/pam_filter/pam_filter.8.xml | 8 ++++---- modules/pam_ftp/pam_ftp.8.xml | 6 +++--- modules/pam_group/pam_group.8.xml | 6 +++--- modules/pam_issue/pam_issue.8.xml | 6 +++--- modules/pam_keyinit/pam_keyinit.8.xml | 6 +++--- modules/pam_lastlog/pam_lastlog.8.xml | 6 +++--- modules/pam_limits/pam_limits.8.xml | 6 +++--- modules/pam_listfile/pam_listfile.8.xml | 8 ++++---- modules/pam_localuser/pam_localuser.8.xml | 8 ++++---- modules/pam_loginuid/pam_loginuid.8.xml | 6 +++--- modules/pam_mail/pam_mail.8.xml | 10 +++++----- modules/pam_mkhomedir/pam_mkhomedir.8.xml | 6 +++--- modules/pam_motd/pam_motd.8.xml | 6 +++--- modules/pam_namespace/pam_namespace.8.xml | 8 ++++---- modules/pam_nologin/pam_nologin.8.xml | 8 ++++---- modules/pam_permit/pam_permit.8.xml | 9 +++++---- modules/pam_rhosts/pam_rhosts.8.xml | 6 +++--- modules/pam_rootok/pam_rootok.8.xml | 6 +++--- modules/pam_securetty/pam_securetty.8.xml | 6 +++--- modules/pam_selinux/pam_selinux.8.xml | 8 ++++---- modules/pam_sepermit/pam_sepermit.8.xml | 8 ++++---- modules/pam_shells/pam_shells.8.xml | 8 ++++---- modules/pam_succeed_if/pam_succeed_if.8.xml | 7 ++++--- modules/pam_tally/pam_tally.8.xml | 8 ++++---- modules/pam_time/pam_time.8.xml | 8 ++++---- modules/pam_tty_audit/pam_tty_audit.8.xml | 6 +++--- modules/pam_umask/pam_umask.8.xml | 6 +++--- modules/pam_unix/pam_unix.8.xml | 9 +++++---- modules/pam_userdb/pam_userdb.8.xml | 8 ++++---- modules/pam_warn/pam_warn.8.xml | 9 +++++---- modules/pam_wheel/pam_wheel.8.xml | 6 +++--- modules/pam_xauth/pam_xauth.8.xml | 6 +++--- 40 files changed, 148 insertions(+), 141 deletions(-) (limited to 'modules') diff --git a/modules/pam_access/pam_access.8.xml b/modules/pam_access/pam_access.8.xml index 68f21bab..ff048593 100644 --- a/modules/pam_access/pam_access.8.xml +++ b/modules/pam_access/pam_access.8.xml @@ -59,7 +59,7 @@ If Linux PAM is compiled with audit support the module will report - when it denies access based on origin (host or tty). + when it denies access based on origin (host or tty). @@ -159,10 +159,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - All services are supported. + All module types (, , + and ) are provided. diff --git a/modules/pam_cracklib/pam_cracklib.8.xml b/modules/pam_cracklib/pam_cracklib.8.xml index ee9a5917..2f1eecbc 100644 --- a/modules/pam_cracklib/pam_cracklib.8.xml +++ b/modules/pam_cracklib/pam_cracklib.8.xml @@ -376,10 +376,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. diff --git a/modules/pam_debug/pam_debug.8.xml b/modules/pam_debug/pam_debug.8.xml index db775067..3d85f4d8 100644 --- a/modules/pam_debug/pam_debug.8.xml +++ b/modules/pam_debug/pam_debug.8.xml @@ -171,11 +171,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The services , , - and are supported. + All module types (, , + and ) are provided. diff --git a/modules/pam_deny/pam_deny.8.xml b/modules/pam_deny/pam_deny.8.xml index 4f45fa9a..a9283582 100644 --- a/modules/pam_deny/pam_deny.8.xml +++ b/modules/pam_deny/pam_deny.8.xml @@ -38,11 +38,11 @@ This module does not recognise any options. - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - All services (, , - and ) are supported. + All module types (, , + and ) are provided. diff --git a/modules/pam_echo/pam_echo.8.xml b/modules/pam_echo/pam_echo.8.xml index 4f4c2428..d2873cc1 100644 --- a/modules/pam_echo/pam_echo.8.xml +++ b/modules/pam_echo/pam_echo.8.xml @@ -96,10 +96,12 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - All services are supported. + All module types (, , + and ) are provided. + diff --git a/modules/pam_env/pam_env.8.xml b/modules/pam_env/pam_env.8.xml index ecf0355a..9e9a96a5 100644 --- a/modules/pam_env/pam_env.8.xml +++ b/modules/pam_env/pam_env.8.xml @@ -118,11 +118,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The and services - are supported. + The and module + types are provided. diff --git a/modules/pam_exec/pam_exec.8.xml b/modules/pam_exec/pam_exec.8.xml index 3ee5315e..1ee25cab 100644 --- a/modules/pam_exec/pam_exec.8.xml +++ b/modules/pam_exec/pam_exec.8.xml @@ -123,11 +123,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The services , , - and are supported. + All module types (, , + and ) are provided. diff --git a/modules/pam_faildelay/pam_faildelay.8.xml b/modules/pam_faildelay/pam_faildelay.8.xml index 57b3305a..57107203 100644 --- a/modules/pam_faildelay/pam_faildelay.8.xml +++ b/modules/pam_faildelay/pam_faildelay.8.xml @@ -68,10 +68,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. diff --git a/modules/pam_filter/pam_filter.8.xml b/modules/pam_filter/pam_filter.8.xml index faf97911..9a9d69b9 100644 --- a/modules/pam_filter/pam_filter.8.xml +++ b/modules/pam_filter/pam_filter.8.xml @@ -188,11 +188,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The services , , - and are supported. + All module types (, , + and ) are provided. diff --git a/modules/pam_ftp/pam_ftp.8.xml b/modules/pam_ftp/pam_ftp.8.xml index f99256c0..ea985c0d 100644 --- a/modules/pam_ftp/pam_ftp.8.xml +++ b/modules/pam_ftp/pam_ftp.8.xml @@ -105,10 +105,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. diff --git a/modules/pam_group/pam_group.8.xml b/modules/pam_group/pam_group.8.xml index 114d0c51..8c0770b8 100644 --- a/modules/pam_group/pam_group.8.xml +++ b/modules/pam_group/pam_group.8.xml @@ -65,10 +65,10 @@ This module does not recognise any options. - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. diff --git a/modules/pam_issue/pam_issue.8.xml b/modules/pam_issue/pam_issue.8.xml index 916dd5e7..4254ea61 100644 --- a/modules/pam_issue/pam_issue.8.xml +++ b/modules/pam_issue/pam_issue.8.xml @@ -146,10 +146,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. diff --git a/modules/pam_keyinit/pam_keyinit.8.xml b/modules/pam_keyinit/pam_keyinit.8.xml index f3e64b3d..bcc50964 100644 --- a/modules/pam_keyinit/pam_keyinit.8.xml +++ b/modules/pam_keyinit/pam_keyinit.8.xml @@ -121,10 +121,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the session service is supported. + Only the module type is provided. diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml index a738402c..f066ac6a 100644 --- a/modules/pam_lastlog/pam_lastlog.8.xml +++ b/modules/pam_lastlog/pam_lastlog.8.xml @@ -140,10 +140,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. diff --git a/modules/pam_limits/pam_limits.8.xml b/modules/pam_limits/pam_limits.8.xml index 05c4d160..a4375e22 100644 --- a/modules/pam_limits/pam_limits.8.xml +++ b/modules/pam_limits/pam_limits.8.xml @@ -132,10 +132,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. diff --git a/modules/pam_listfile/pam_listfile.8.xml b/modules/pam_listfile/pam_listfile.8.xml index d33cdb1e..4c1fb1fd 100644 --- a/modules/pam_listfile/pam_listfile.8.xml +++ b/modules/pam_listfile/pam_listfile.8.xml @@ -175,11 +175,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The services , , - and are supported. + All module types (, , + and ) are provided. diff --git a/modules/pam_localuser/pam_localuser.8.xml b/modules/pam_localuser/pam_localuser.8.xml index cae98ca1..861fc35a 100644 --- a/modules/pam_localuser/pam_localuser.8.xml +++ b/modules/pam_localuser/pam_localuser.8.xml @@ -80,11 +80,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - All services (, , - and ) are supported. + All module types (, , + and ) are provided. diff --git a/modules/pam_loginuid/pam_loginuid.8.xml b/modules/pam_loginuid/pam_loginuid.8.xml index 801c88f9..2a146b2c 100644 --- a/modules/pam_loginuid/pam_loginuid.8.xml +++ b/modules/pam_loginuid/pam_loginuid.8.xml @@ -57,10 +57,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The service is supported. + Only the module type is provided. diff --git a/modules/pam_mail/pam_mail.8.xml b/modules/pam_mail/pam_mail.8.xml index 17677c73..a6dff870 100644 --- a/modules/pam_mail/pam_mail.8.xml +++ b/modules/pam_mail/pam_mail.8.xml @@ -193,12 +193,12 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The session and - auth (on establishment and - deletion of credentials) services are supported. + The and + (on establishment and + deletion of credentials) module types are provided. diff --git a/modules/pam_mkhomedir/pam_mkhomedir.8.xml b/modules/pam_mkhomedir/pam_mkhomedir.8.xml index aeb619f0..5d66ee23 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.8.xml +++ b/modules/pam_mkhomedir/pam_mkhomedir.8.xml @@ -95,10 +95,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. diff --git a/modules/pam_motd/pam_motd.8.xml b/modules/pam_motd/pam_motd.8.xml index 69e9efd8..7b9b2437 100644 --- a/modules/pam_motd/pam_motd.8.xml +++ b/modules/pam_motd/pam_motd.8.xml @@ -55,10 +55,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml index bb9b3e34..81328476 100644 --- a/modules/pam_namespace/pam_namespace.8.xml +++ b/modules/pam_namespace/pam_namespace.8.xml @@ -237,11 +237,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The service is supported. The module must not - be called from multithreaded processes. + Only the module type is provided. + The module must not be called from multithreaded processes. diff --git a/modules/pam_nologin/pam_nologin.8.xml b/modules/pam_nologin/pam_nologin.8.xml index c9a81792..b30b6bed 100644 --- a/modules/pam_nologin/pam_nologin.8.xml +++ b/modules/pam_nologin/pam_nologin.8.xml @@ -68,11 +68,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The and services are - supported. + The and module + types are provided. diff --git a/modules/pam_permit/pam_permit.8.xml b/modules/pam_permit/pam_permit.8.xml index 6ecc34ac..6bb49658 100644 --- a/modules/pam_permit/pam_permit.8.xml +++ b/modules/pam_permit/pam_permit.8.xml @@ -47,11 +47,12 @@ This module does not recognise any options. - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The services , , - and are supported. + The , , + and + module types are provided. diff --git a/modules/pam_rhosts/pam_rhosts.8.xml b/modules/pam_rhosts/pam_rhosts.8.xml index 194f956e..eb96371d 100644 --- a/modules/pam_rhosts/pam_rhosts.8.xml +++ b/modules/pam_rhosts/pam_rhosts.8.xml @@ -89,10 +89,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. diff --git a/modules/pam_rootok/pam_rootok.8.xml b/modules/pam_rootok/pam_rootok.8.xml index ed26d357..e2d2441f 100644 --- a/modules/pam_rootok/pam_rootok.8.xml +++ b/modules/pam_rootok/pam_rootok.8.xml @@ -54,10 +54,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the type is provided. diff --git a/modules/pam_securetty/pam_securetty.8.xml b/modules/pam_securetty/pam_securetty.8.xml index 0ba44413..dd57705b 100644 --- a/modules/pam_securetty/pam_securetty.8.xml +++ b/modules/pam_securetty/pam_securetty.8.xml @@ -64,10 +64,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. diff --git a/modules/pam_selinux/pam_selinux.8.xml b/modules/pam_selinux/pam_selinux.8.xml index d9ff1770..3db26d04 100644 --- a/modules/pam_selinux/pam_selinux.8.xml +++ b/modules/pam_selinux/pam_selinux.8.xml @@ -170,10 +170,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the module type is provided. @@ -211,7 +211,7 @@ EXAMPLES auth required pam_unix.so -session required pam_permit.so +session required pam_permit.so session optional pam_selinux.so diff --git a/modules/pam_sepermit/pam_sepermit.8.xml b/modules/pam_sepermit/pam_sepermit.8.xml index c2546b62..da4153bf 100644 --- a/modules/pam_sepermit/pam_sepermit.8.xml +++ b/modules/pam_sepermit/pam_sepermit.8.xml @@ -87,11 +87,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the and - services are supported. + The and + module types are provided. diff --git a/modules/pam_shells/pam_shells.8.xml b/modules/pam_shells/pam_shells.8.xml index 72191da8..c197a989 100644 --- a/modules/pam_shells/pam_shells.8.xml +++ b/modules/pam_shells/pam_shells.8.xml @@ -41,11 +41,11 @@ This module does not recognise any options. - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The services and - are supported. + The and + module types are provided. diff --git a/modules/pam_succeed_if/pam_succeed_if.8.xml b/modules/pam_succeed_if/pam_succeed_if.8.xml index e377ae86..c99f6be5 100644 --- a/modules/pam_succeed_if/pam_succeed_if.8.xml +++ b/modules/pam_succeed_if/pam_succeed_if.8.xml @@ -215,10 +215,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - All services are supported. + All module types (, , + and ) are provided. diff --git a/modules/pam_tally/pam_tally.8.xml b/modules/pam_tally/pam_tally.8.xml index bd86e80f..831ee1a5 100644 --- a/modules/pam_tally/pam_tally.8.xml +++ b/modules/pam_tally/pam_tally.8.xml @@ -119,7 +119,7 @@ This can be used for auth and - account services. + account module types. @@ -348,11 +348,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED The and - services are supported. + module types are provided. diff --git a/modules/pam_time/pam_time.8.xml b/modules/pam_time/pam_time.8.xml index 490a793c..8e7f222c 100644 --- a/modules/pam_time/pam_time.8.xml +++ b/modules/pam_time/pam_time.8.xml @@ -49,7 +49,7 @@ If Linux PAM is compiled with audit support the module will report - when it denies access. + when it denies access. @@ -83,10 +83,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the type is provided. diff --git a/modules/pam_tty_audit/pam_tty_audit.8.xml b/modules/pam_tty_audit/pam_tty_audit.8.xml index f6f0602f..005d2e85 100644 --- a/modules/pam_tty_audit/pam_tty_audit.8.xml +++ b/modules/pam_tty_audit/pam_tty_audit.8.xml @@ -80,10 +80,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the session service is supported. + Only the session type is supported. diff --git a/modules/pam_umask/pam_umask.8.xml b/modules/pam_umask/pam_umask.8.xml index 43eba83b..b2858b57 100644 --- a/modules/pam_umask/pam_umask.8.xml +++ b/modules/pam_umask/pam_umask.8.xml @@ -141,10 +141,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the service is supported. + Only the type is provided. diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml index e6a5e7fc..32565b1f 100644 --- a/modules/pam_unix/pam_unix.8.xml +++ b/modules/pam_unix/pam_unix.8.xml @@ -85,7 +85,7 @@ - The session component of this module logs when a user logins + The session component of this module logs when a user logins or leave the system. @@ -314,10 +314,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - All service are supported. + All module types (, , + and ) are provided. diff --git a/modules/pam_userdb/pam_userdb.8.xml b/modules/pam_userdb/pam_userdb.8.xml index ea2ebfe6..ba971526 100644 --- a/modules/pam_userdb/pam_userdb.8.xml +++ b/modules/pam_userdb/pam_userdb.8.xml @@ -189,11 +189,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The services and - are supported. + The and module + types are provided. diff --git a/modules/pam_warn/pam_warn.8.xml b/modules/pam_warn/pam_warn.8.xml index 04f29283..1764ec92 100644 --- a/modules/pam_warn/pam_warn.8.xml +++ b/modules/pam_warn/pam_warn.8.xml @@ -38,11 +38,12 @@ This module does not recognise any options. - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - The services , , - and are supported. + The , , + and module + types are provided. diff --git a/modules/pam_wheel/pam_wheel.8.xml b/modules/pam_wheel/pam_wheel.8.xml index 1a344d08..c0ae68c6 100644 --- a/modules/pam_wheel/pam_wheel.8.xml +++ b/modules/pam_wheel/pam_wheel.8.xml @@ -130,11 +130,11 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED The auth and - account services are supported. + account module types are provided. diff --git a/modules/pam_xauth/pam_xauth.8.xml b/modules/pam_xauth/pam_xauth.8.xml index 78184fdb..353f1b6e 100644 --- a/modules/pam_xauth/pam_xauth.8.xml +++ b/modules/pam_xauth/pam_xauth.8.xml @@ -147,10 +147,10 @@ - - MODULE SERVICES PROVIDED + + MODULE TYPES PROVIDED - Only the session service is supported. + Only the session type is provided. -- cgit v1.2.3 From d524b169597996b61f10ce7cdb4aa39d27867eb9 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 29 Aug 2008 07:33:20 +0000 Subject: Relevant BUGIDs: rhbz#460241 Purpose of commit: bugfix Commit summary: --------------- 2008-08-29 Tomas Mraz * modules/pam_loginuid/pam_loginuid.c(set_loginuid): Uids are unsigned. --- modules/pam_loginuid/pam_loginuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_loginuid/pam_loginuid.c b/modules/pam_loginuid/pam_loginuid.c index 13509e7e..4fa486c7 100644 --- a/modules/pam_loginuid/pam_loginuid.c +++ b/modules/pam_loginuid/pam_loginuid.c @@ -53,7 +53,7 @@ static int set_loginuid(pam_handle_t *pamh, uid_t uid) int fd, count, rc = 0; char loginuid[24]; - count = snprintf(loginuid, sizeof(loginuid), "%d", uid); + count = snprintf(loginuid, sizeof(loginuid), "%lu", (unsigned long)uid); fd = open("/proc/self/loginuid", O_NOFOLLOW|O_WRONLY|O_TRUNC); if (fd < 0) { if (errno != ENOENT) { -- cgit v1.2.3 From 53a20abf8666d4af2522bd51bf64e9e3c2deb0cf Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 3 Sep 2008 13:06:22 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-09-03 Thorsten Kukuk * modules/pam_exec/pam_exec.c: Expose authtok if requested, provide environment variable containing service type. * modules/pam_exec/pam_exec.8.xml: Document new option. --- modules/pam_exec/pam_exec.8.xml | 23 +++++- modules/pam_exec/pam_exec.c | 162 ++++++++++++++++++++++++++++++++++------ 2 files changed, 160 insertions(+), 25 deletions(-) (limited to 'modules') diff --git a/modules/pam_exec/pam_exec.8.xml b/modules/pam_exec/pam_exec.8.xml index 1ee25cab..3cbd6af3 100644 --- a/modules/pam_exec/pam_exec.8.xml +++ b/modules/pam_exec/pam_exec.8.xml @@ -21,6 +21,9 @@ debug + + expose_authtok + seteuid @@ -57,7 +60,11 @@ In addition, the following PAM items are exported as environment variables: PAM_RHOST, PAM_RUSER, PAM_SERVICE, - PAM_TTY, and PAM_USER. + PAM_TTY, PAM_USER and + PAM_TYPE, which contains one of the module + types: , , + , and + . @@ -79,6 +86,20 @@ + + + + + + + During authentication the calling command can read + the password from + stdin3 + . + + + + diff --git a/modules/pam_exec/pam_exec.c b/modules/pam_exec/pam_exec.c index dce65730..47e1d5bb 100644 --- a/modules/pam_exec/pam_exec.c +++ b/modules/pam_exec/pam_exec.c @@ -58,6 +58,7 @@ #include #include #include +#include #define ENV_ITEM(n) { (n), #n } static struct { @@ -71,15 +72,20 @@ static struct { ENV_ITEM(PAM_RUSER), }; + static int -call_exec (pam_handle_t *pamh, int argc, const char **argv) +call_exec (const char *pam_type, pam_handle_t *pamh, + int argc, const char **argv) { int debug = 0; int call_setuid = 0; int quiet = 0; + int expose_authtok = 0; int optargc; const char *logfile = NULL; + const char *authtok = NULL; pid_t pid; + int fds[2]; if (argc < 1) { pam_syslog (pamh, LOG_ERR, @@ -100,10 +106,63 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) call_setuid = 1; else if (strcasecmp (argv[optargc], "quiet") == 0) quiet = 1; + else if (strcasecmp (argv[optargc], "expose_authtok") == 0) + expose_authtok = 1; else break; /* Unknown option, assume program to execute. */ } + if (expose_authtok == 1) + { + if (strcmp (pam_type, "auth") != 0) + { + pam_syslog (pamh, LOG_ERR, + "expose_authtok not supported for type %s", pam_type); + expose_authtok = 0; + } + else + { + const void *void_pass; + int retval; + + retval = pam_get_item (pamh, PAM_AUTHTOK, &void_pass); + if (retval != PAM_SUCCESS) + { + if (debug) + pam_syslog (pamh, LOG_DEBUG, + "pam_get_item (PAM_AUTHTOK) failed, return %d", + retval); + return retval; + } + else if (void_pass == NULL) + { + char *resp = NULL; + + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, + &resp, _("Password: ")); + + if (retval != PAM_SUCCESS) + { + _pam_drop (resp); + if (retval == PAM_CONV_AGAIN) + retval = PAM_INCOMPLETE; + return retval; + } + + pam_set_item (pamh, PAM_AUTHTOK, resp); + authtok = strdupa (resp); + _pam_drop (resp); + } + else + authtok = void_pass; + + if (pipe(fds) != 0) + { + pam_syslog (pamh, LOG_ERR, "Could not create pipe: %m"); + return PAM_SYSTEM_ERR; + } + } + } if (optargc >= argc) { pam_syslog (pamh, LOG_ERR, "No path given as argument"); @@ -118,6 +177,27 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) int status = 0; pid_t retval; + if (expose_authtok) /* send the password to the child */ + { + if (authtok != NULL) + { /* send the password to the child */ + if (debug) + pam_syslog (pamh, LOG_DEBUG, "send password to child"); + if (write(fds[1], authtok, strlen(authtok)+1) == -1) + pam_syslog (pamh, LOG_ERR, + "sending password to child failed: %m"); + authtok = NULL; + } + else + { + if (write(fds[1], "", 1) == -1) /* blank password */ + pam_syslog (pamh, LOG_ERR, + "sending password to child failed: %m"); + } + close(fds[0]); /* close here to avoid possible SIGPIPE above */ + close(fds[1]); + } + while ((retval = waitpid (pid, &status, 0)) == -1 && errno == EINTR); if (retval == (pid_t)-1) @@ -163,17 +243,38 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) int i; char **envlist, **tmp; int envlen, nitems; + char *envstr; - for (i = 0; i < sysconf (_SC_OPEN_MAX); i++) - close (i); + if (expose_authtok) + { + /* reopen stdin as pipe */ + if (dup2(fds[0], STDIN_FILENO) == -1) + { + int err = errno; + pam_syslog (pamh, LOG_ERR, "dup2 of STDIN failed: %m"); + exit (err); + } - /* New stdin. */ - if ((i = open ("/dev/null", O_RDWR)) < 0) + for (i = 0; i < sysconf (_SC_OPEN_MAX); i++) + { + if (i != STDIN_FILENO) + close (i); + } + } + else { - int err = errno; - pam_syslog (pamh, LOG_ERR, "open of /dev/null failed: %m"); - exit (err); + for (i = 0; i < sysconf (_SC_OPEN_MAX); i++) + close (i); + + /* New stdin. */ + if ((i = open ("/dev/null", O_RDWR)) < 0) + { + int err = errno; + pam_syslog (pamh, LOG_ERR, "open of /dev/null failed: %m"); + exit (err); + } } + /* New stdout and stderr. */ if (logfile) { @@ -195,18 +296,22 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) } } else - if (dup (i) == -1) - { - int err = errno; - pam_syslog (pamh, LOG_ERR, "dup failed: %m"); - exit (err); - } + { + /* New stdout/stderr. */ + if ((i = open ("/dev/null", O_RDWR)) < 0) + { + int err = errno; + pam_syslog (pamh, LOG_ERR, "open of /dev/null failed: %m"); + exit (err); + } + } + if (dup (i) == -1) - { + { int err = errno; pam_syslog (pamh, LOG_ERR, "dup failed: %m"); - exit (err); - } + exit (err); + } if (call_setuid) if (setuid (geteuid ()) == -1) @@ -240,7 +345,8 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) for (envlen = 0; envlist[envlen] != NULL; ++envlen) /* nothing */ ; nitems = sizeof(env_items) / sizeof(*env_items); - tmp = realloc(envlist, (envlen + nitems + 1) * sizeof(*envlist)); + /* + 2 because of PAM_TYPE and NULL entry */ + tmp = realloc(envlist, (envlen + nitems + 2) * sizeof(*envlist)); if (tmp == NULL) { free(envlist); @@ -251,7 +357,6 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) for (i = 0; i < nitems; ++i) { const void *item; - char *envstr; if (pam_get_item(pamh, env_items[i].item, &item) != PAM_SUCCESS || item == NULL) continue; @@ -265,6 +370,15 @@ call_exec (pam_handle_t *pamh, int argc, const char **argv) envlist[envlen] = NULL; } + if (asprintf(&envstr, "PAM_TYPE=%s", pam_type) < 0) + { + free(envlist); + pam_syslog (pamh, LOG_ERR, "prepare environment failed: %m"); + exit (ENOMEM); + } + envlist[envlen++] = envstr; + envlist[envlen] = NULL; + if (debug) pam_syslog (pamh, LOG_DEBUG, "Calling %s ...", arggv[0]); @@ -286,7 +400,7 @@ PAM_EXTERN int pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { - return call_exec (pamh, argc, argv); + return call_exec ("auth", pamh, argc, argv); } PAM_EXTERN int @@ -304,28 +418,28 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, { if (flags & PAM_PRELIM_CHECK) return PAM_SUCCESS; - return call_exec (pamh, argc, argv); + return call_exec ("password", pamh, argc, argv); } PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { - return call_exec (pamh, argc, argv); + return call_exec ("account", pamh, argc, argv); } PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { - return call_exec (pamh, argc, argv); + return call_exec ("open_session", pamh, argc, argv); } PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { - return call_exec (pamh, argc, argv); + return call_exec ("close_session", pamh, argc, argv); } #ifdef PAM_STATIC -- cgit v1.2.3 From 152576cd900a64319c74b569cd606d888b9cd235 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Tue, 16 Sep 2008 14:44:02 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-09-16 Thorsten Kukuk * modules/pam_unix/pam_unix.8.xml: Fix typo. --- modules/pam_unix/pam_unix.8.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml index 32565b1f..e08edfcc 100644 --- a/modules/pam_unix/pam_unix.8.xml +++ b/modules/pam_unix/pam_unix.8.xml @@ -187,7 +187,7 @@ password to the one provided by a previously stacked module (this is used in the example of the stacking of the pam_cracklib - module documented above). + module documented below). -- cgit v1.2.3 From 742a6386465fb4290c3a5f86505f9a3e5e48fad3 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Tue, 16 Sep 2008 14:47:45 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-09-16 Thorsten Kukuk * modules/pam_cracklib/pam_cracklib.8.xml: Fix typo. --- modules/pam_cracklib/pam_cracklib.8.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_cracklib/pam_cracklib.8.xml b/modules/pam_cracklib/pam_cracklib.8.xml index 2f1eecbc..19b74d27 100644 --- a/modules/pam_cracklib/pam_cracklib.8.xml +++ b/modules/pam_cracklib/pam_cracklib.8.xml @@ -184,7 +184,7 @@ Prompt user at most N times before returning with error. The default is - 1 + 1. -- cgit v1.2.3 From e15dee8abc38058cae9259a3aa3b625ea8febbfd Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 19 Sep 2008 13:38:32 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-09-19 Tomas Mraz * modules/pam_cracklib/pam_cracklib.8.xml: Fix description of the palindrome test. Document new options maxrepeat and reject_username. * modules/pam_cracklib/pam_cracklib.c(_pam_parse): Parse the maxrepeat and reject_username options. (password_check): Call the new tests usercheck() and consecutive(). (_pam_unix_approve_pass): Pass user name to the password_check(). --- modules/pam_cracklib/pam_cracklib.8.xml | 45 ++++++++++++++++- modules/pam_cracklib/pam_cracklib.c | 90 +++++++++++++++++++++++++++++---- 2 files changed, 124 insertions(+), 11 deletions(-) (limited to 'modules') diff --git a/modules/pam_cracklib/pam_cracklib.8.xml b/modules/pam_cracklib/pam_cracklib.8.xml index 19b74d27..3d061c43 100644 --- a/modules/pam_cracklib/pam_cracklib.8.xml +++ b/modules/pam_cracklib/pam_cracklib.8.xml @@ -59,7 +59,7 @@ Palindrome - Is the new password a palindrome of the old one? + Is the new password a palindrome? @@ -120,6 +120,23 @@ + + Same consecutive characters + + + Optional check for same consecutive characters. + + + + + Contains user name + + + Optional check whether the password contains the user's name + in some form. + + + This module with no arguments will work well for standard unix @@ -347,6 +364,32 @@ + + + + + + + Reject passwords which contain more than N same consecutive + characters. The default is 0 which means that this check + is disabled. + + + + + + + + + + + Check whether the name of the user in straight or reversed + form is contained in the new password. If it is found the + new password is rejected. + + + + diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c index 12cbcf3c..3dcc4729 100644 --- a/modules/pam_cracklib/pam_cracklib.c +++ b/modules/pam_cracklib/pam_cracklib.c @@ -99,6 +99,8 @@ struct cracklib_options { int min_class; int use_authtok; int try_first_pass; + int max_repeat; + int reject_user; char prompt_type[BUFSIZ]; const char *cracklib_dictpath; }; @@ -166,8 +168,14 @@ _pam_parse (pam_handle_t *pamh, struct cracklib_options *opt, opt->min_class = strtol(*argv+9,&ep,10); if (!ep) opt->min_class = 0; - if (opt->min_class > 4) - opt->min_class = 4 ; + if (opt->min_class > 4) + opt->min_class = 4; + } else if (!strncmp(*argv,"maxrepeat=",10)) { + opt->max_repeat = strtol(*argv+10,&ep,10); + if (!ep) + opt->max_repeat = 0; + } else if (!strncmp(*argv,"reject_username",15)) { + opt->reject_user = 1; } else if (!strncmp(*argv,"use_authtok",11)) { opt->use_authtok = 1; } else if (!strncmp(*argv,"use_first_pass",14)) { @@ -418,6 +426,58 @@ static int simple(struct cracklib_options *opt, const char *new) return 1; } +static int consecutive(struct cracklib_options *opt, const char *new) +{ + char c; + int i; + int same; + + if (opt->max_repeat == 0) + return 0; + + for (i = 0; new[i]; i++) { + if (i > 0 && new[i] == c) { + ++same; + if (same > opt->max_repeat) + return 1; + } else { + c = new[i]; + same = 1; + } + } + return 0; +} + +static int usercheck(struct cracklib_options *opt, const char *new, + char *user) +{ + char *f, *b; + + if (!opt->reject_user) + return 0; + + if (strstr(new, user) != NULL) + return 1; + + /* now reverse the username, we can do that in place + as it is strdup-ed */ + f = user; + b = user+strlen(user)-1; + while (f < b) { + char c; + + c = *f; + *f = *b; + *b = c; + --b; + ++f; + } + + if (strstr(new, user) != NULL) + return 1; + return 0; +} + static char * str_lower(char *string) { char *cp; @@ -428,10 +488,12 @@ static char * str_lower(char *string) } static const char *password_check(struct cracklib_options *opt, - const char *old, const char *new) + const char *old, const char *new, + const char *user) { const char *msg = NULL; char *oldmono = NULL, *newmono, *wrapped = NULL; + char *usermono = NULL; if (old && strcmp(new, old) == 0) { msg = _("is the same as the old one"); @@ -439,6 +501,7 @@ static const char *password_check(struct cracklib_options *opt, } newmono = str_lower(x_strdup(new)); + usermono = str_lower(x_strdup(user)); if (old) { oldmono = str_lower(x_strdup(old)); wrapped = malloc(strlen(oldmono) * 2 + 1); @@ -464,8 +527,15 @@ static const char *password_check(struct cracklib_options *opt, if (!msg && minclass (opt, new)) msg = _("not enough character classes"); + if (!msg && consecutive(opt, new)) + msg = _("contains too many same characters consecutively"); + + if (!msg && usercheck(opt, newmono, usermono)) + msg = _("contains the user name in some form"); + memset(newmono, 0, strlen(newmono)); free(newmono); + free(usermono); if (old) { memset(oldmono, 0, strlen(oldmono)); memset(wrapped, 0, strlen(wrapped)); @@ -532,18 +602,18 @@ static int _pam_unix_approve_pass(pam_handle_t *pamh, return PAM_AUTHTOK_ERR; } + retval = pam_get_item(pamh, PAM_USER, &user); + if (retval != PAM_SUCCESS || user == NULL) { + if (ctrl & PAM_DEBUG_ARG) + pam_syslog(pamh,LOG_ERR,"Can not get username"); + return PAM_AUTHTOK_ERR; + } /* * if one wanted to hardwire authentication token strength * checking this would be the place */ - msg = password_check(opt, pass_old, pass_new); + msg = password_check(opt, pass_old, pass_new, user); if (!msg) { - retval = pam_get_item(pamh, PAM_USER, &user); - if (retval != PAM_SUCCESS || user == NULL) { - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh,LOG_ERR,"Can not get username"); - return PAM_AUTHTOK_ERR; - } msg = check_old_password(user, pass_new); } -- cgit v1.2.3 From 075f2898e48a008cf36092b83b9621bc077d9f5a Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 23 Sep 2008 13:27:50 +0000 Subject: Relevant BUGIDs: Purpose of commit: cleanup Commit summary: --------------- 2008-09-23 Tomas Mraz * modules/pam_limits/limits.conf.5.xml: Comment that rss limit is ignored. --- modules/pam_limits/limits.conf.5.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_limits/limits.conf.5.xml b/modules/pam_limits/limits.conf.5.xml index fb1fad27..f831a909 100644 --- a/modules/pam_limits/limits.conf.5.xml +++ b/modules/pam_limits/limits.conf.5.xml @@ -145,7 +145,7 @@ - maximum resident set size (KB) + maximum resident set size (KB) (Ignored in Linux 2.4.30 and higher) -- cgit v1.2.3 From 3022b9383b52422482fcf5104b6d56b8e598cbeb Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Thu, 25 Sep 2008 11:53:02 +0000 Subject: Relevant BUGIDs: http://bugs.debian.org/439268 Purpose of commit: bugfix Commit summary: --------------- 2008-09-25 Thorsten Kukuk * modules/pam_mail/pam_mail.c (report_mail): Fix logic of "quiet" option (Patch from Andreas Henriksson ) * modules/pam_mail/pam_mail.8.xml: Fix typo. --- modules/pam_mail/pam_mail.8.xml | 2 +- modules/pam_mail/pam_mail.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'modules') diff --git a/modules/pam_mail/pam_mail.8.xml b/modules/pam_mail/pam_mail.8.xml index a6dff870..3015145d 100644 --- a/modules/pam_mail/pam_mail.8.xml +++ b/modules/pam_mail/pam_mail.8.xml @@ -40,7 +40,7 @@ nopen - quit + quiet standard diff --git a/modules/pam_mail/pam_mail.c b/modules/pam_mail/pam_mail.c index 46395b53..a5473605 100644 --- a/modules/pam_mail/pam_mail.c +++ b/modules/pam_mail/pam_mail.c @@ -303,8 +303,13 @@ report_mail(pam_handle_t *pamh, int ctrl, int type, const char *folder) { int retval; - if (!(ctrl & PAM_MAIL_SILENT) || - ((ctrl & PAM_QUIET_MAIL) && type == HAVE_NEW_MAIL)) + if ((ctrl & PAM_MAIL_SILENT) || + ((ctrl & PAM_QUIET_MAIL) && type != HAVE_NEW_MAIL)) + { + D(("keeping quiet")); + retval = PAM_SUCCESS; + } + else { if (ctrl & PAM_STANDARD_MAIL) switch (type) @@ -345,11 +350,6 @@ report_mail(pam_handle_t *pamh, int ctrl, int type, const char *folder) break; } } - else - { - D(("keeping quiet")); - retval = PAM_SUCCESS; - } D(("returning %s", pam_strerror(pamh, retval))); return retval; -- cgit v1.2.3 From df687b4a249bdc941a5aee078749960356e2e259 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 25 Sep 2008 18:58:10 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-09-25 Tomas Mraz * modules/pam_tally/pam_tally.c(get_tally): Fix syslog message. (tally_check): Open faillog read only. Close file descriptor. Fix typos in messages. --- modules/pam_tally/pam_tally.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'modules') diff --git a/modules/pam_tally/pam_tally.c b/modules/pam_tally/pam_tally.c index a01e1938..dffbc895 100644 --- a/modules/pam_tally/pam_tally.c +++ b/modules/pam_tally/pam_tally.c @@ -350,7 +350,7 @@ get_tally(pam_handle_t *pamh, tally_t *tally, uid_t uid, } if ( ! ( *TALLY = fopen(filename,(*tally!=TALLY_HI)?"r+":"r") ) ) { - pam_syslog(pamh, LOG_ALERT, "Error opening %s for update", filename); + pam_syslog(pamh, LOG_ALERT, "Error opening %s for %s", filename, *tally!=TALLY_HI?"update":"read"); /* Discovering why account service fails: e/uid are target user. * @@ -504,7 +504,7 @@ tally_check (time_t oldtime, pam_handle_t *pamh, uid_t uid, tally_t deny = opts->deny; tally_t - tally = 0; /* !TALLY_HI --> Log opened for update */ + tally = TALLY_HI; long lock_time = opts->lock_time; @@ -515,6 +515,10 @@ tally_check (time_t oldtime, pam_handle_t *pamh, uid_t uid, i=get_tally(pamh, &tally, uid, opts->filename, &TALLY, fsp); if ( i != PAM_SUCCESS ) { RETURN_ERROR( i ); } + if ( TALLY != NULL ) { + fclose(TALLY); + } + if ( !(opts->ctrl & OPT_MAGIC_ROOT) || getuid() ) { /* magic_root skips tally check */ /* To deny or not to deny; that is the question */ @@ -534,7 +538,7 @@ tally_check (time_t oldtime, pam_handle_t *pamh, uid_t uid, { if (!(opts->ctrl & OPT_SILENT)) pam_info (pamh, - _("Account temporary locked (%lds seconds left)"), + _("Account temporary locked (%ld seconds left)"), oldtime+lock_time-time(NULL)); if (!(opts->ctrl & OPT_NOLOGNOTICE)) @@ -559,8 +563,8 @@ tally_check (time_t oldtime, pam_handle_t *pamh, uid_t uid, ( ((opts->ctrl & OPT_DENY_ROOT) || uid) ) /* even_deny stops uid check */ ) { if (!(opts->ctrl & OPT_SILENT)) - pam_info (pamh, _("Accounted locked due to "TALLY_FMT" failed login"), - tally); + pam_info (pamh, _("Account locked due to %u failed logins"), + (unsigned int)tally); if (!(opts->ctrl & OPT_NOLOGNOTICE)) pam_syslog(pamh, LOG_NOTICE, -- cgit v1.2.3 From 85dcbd2d2b9d1cd57e628599703dd28326478720 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Mon, 29 Sep 2008 12:11:50 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-09-29 Thorsten Kukuk * modules/pam_echo/pam_echo.8.xml: Fix format error. --- modules/pam_echo/pam_echo.8.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_echo/pam_echo.8.xml b/modules/pam_echo/pam_echo.8.xml index d2873cc1..07ac9af2 100644 --- a/modules/pam_echo/pam_echo.8.xml +++ b/modules/pam_echo/pam_echo.8.xml @@ -41,7 +41,7 @@ - %h + %h The name of the local host. -- cgit v1.2.3 From c6e6da3915c87e210c24d3c24b7303c59004e98c Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 30 Sep 2008 14:40:39 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-09-30 Tomas Mraz * modules/pam_lastlog/pam_lastlog.8.xml: Document new options noupdate and showfailed. * modules/pam_lastlog/pam_lastlog.c(pam_parse): Recognize the new options. (last_login_read): New output parameter lltime. Do not display the last login message if it would be empty. (last_login_date): New output parameter lltime. Do not write the last login info when LASTLOG_UPDATE is not set. (last_login_failed): New function to display the last bad login attempt from btmp. (pam_sm_open_session): Obtain lltime from last_login_date() and call last_login_failed() when appropriate. --- modules/pam_lastlog/pam_lastlog.8.xml | 28 +++++++ modules/pam_lastlog/pam_lastlog.c | 152 ++++++++++++++++++++++++++++++++-- 2 files changed, 171 insertions(+), 9 deletions(-) (limited to 'modules') diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml index f066ac6a..f1fffa89 100644 --- a/modules/pam_lastlog/pam_lastlog.8.xml +++ b/modules/pam_lastlog/pam_lastlog.8.xml @@ -39,6 +39,12 @@ nowtmp + + noupdate + + + showfailed + @@ -137,6 +143,28 @@ + + + + + + + Don't update any file. + + + + + + + + + + Display number of failed login attempts and the date of the + last failed attempt from btmp. The date is not displayed + when is specified. + + + diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c index a75e1ce7..8af6b9eb 100644 --- a/modules/pam_lastlog/pam_lastlog.c +++ b/modules/pam_lastlog/pam_lastlog.c @@ -46,6 +46,10 @@ struct lastlog { }; #endif /* hpux */ +#ifndef _PATH_BTMP +# define _PATH_BTMP "/var/log/btmp" +#endif + /* XXX - time before ignoring lock. Is 1 sec enough? */ #define LASTLOG_IGNORE_LOCK_TIME 1 @@ -75,11 +79,13 @@ struct lastlog { #define LASTLOG_DEBUG 020 /* send info to syslog(3) */ #define LASTLOG_QUIET 040 /* keep quiet about things */ #define LASTLOG_WTMP 0100 /* log to wtmp as well as lastlog */ +#define LASTLOG_BTMP 0200 /* display failed login info from btmp */ +#define LASTLOG_UPDATE 0400 /* update the lastlog and wtmp files (default) */ static int _pam_parse(pam_handle_t *pamh, int flags, int argc, const char **argv) { - int ctrl=(LASTLOG_DATE|LASTLOG_HOST|LASTLOG_LINE|LASTLOG_WTMP); + int ctrl=(LASTLOG_DATE|LASTLOG_HOST|LASTLOG_LINE|LASTLOG_WTMP|LASTLOG_UPDATE); /* does the appliction require quiet? */ if (flags & PAM_SILENT) { @@ -105,6 +111,10 @@ _pam_parse(pam_handle_t *pamh, int flags, int argc, const char **argv) ctrl |= LASTLOG_NEVER; } else if (!strcmp(*argv,"nowtmp")) { ctrl &= ~LASTLOG_WTMP; + } else if (!strcmp(*argv,"noupdate")) { + ctrl &= ~(LASTLOG_WTMP|LASTLOG_UPDATE); + } else if (!strcmp(*argv,"showfailed")) { + ctrl |= LASTLOG_BTMP; } else { pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); } @@ -135,7 +145,7 @@ get_tty(pam_handle_t *pamh) } static int -last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid) +last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid, time_t *lltime) { struct flock last_lock; struct lastlog last_login; @@ -166,6 +176,7 @@ last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid) last_lock.l_type = F_UNLCK; (void) fcntl(last_fd, F_SETLK, &last_lock); /* unlock */ + *lltime = last_login.ll_time; if (!last_login.ll_time) { if (announce & LASTLOG_DEBUG) { pam_syslog(pamh, LOG_DEBUG, @@ -216,8 +227,9 @@ last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid) } } - /* TRANSLATORS: "Last login: from on " */ - retval = pam_info(pamh, _("Last login:%s%s%s"), + if (date != NULL || host != NULL || line != NULL) + /* TRANSLATORS: "Last login: from on " */ + retval = pam_info(pamh, _("Last login:%s%s%s"), date ? date : "", host ? host : "", line ? line : ""); @@ -320,13 +332,13 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd, } static int -last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user) +last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user, time_t *lltime) { int retval; int last_fd; /* obtain the last login date and all the relevant info */ - last_fd = open(_PATH_LASTLOG, O_RDWR); + last_fd = open(_PATH_LASTLOG, announce&LASTLOG_UPDATE ? O_RDWR : O_RDONLY); if (last_fd < 0) { if (errno == ENOENT) { last_fd = open(_PATH_LASTLOG, O_RDWR|O_CREAT, @@ -353,7 +365,7 @@ last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user) return PAM_SERVICE_ERR; } - retval = last_login_read(pamh, announce, last_fd, uid); + retval = last_login_read(pamh, announce, last_fd, uid, lltime); if (retval != PAM_SUCCESS) { close(last_fd); @@ -361,7 +373,9 @@ last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user) return retval; } - retval = last_login_write(pamh, announce, last_fd, uid, user); + if (announce & LASTLOG_UPDATE) { + retval = last_login_write(pamh, announce, last_fd, uid, user); + } close(last_fd); D(("all done with last login")); @@ -369,6 +383,121 @@ last_login_date(pam_handle_t *pamh, int announce, uid_t uid, const char *user) return retval; } +static int +last_login_failed(pam_handle_t *pamh, int announce, const char *user, time_t lltime) +{ + int retval; + int fd; + struct utmp ut; + struct utmp utuser; + int failed = 0; + char the_time[256]; + char *date = NULL; + char *host = NULL; + char *line = NULL; + + if (strlen(user) > UT_NAMESIZE) { + pam_syslog(pamh, LOG_WARNING, "username too long, output might be inaccurate"); + } + + /* obtain the failed login attempt records from btmp */ + fd = open(_PATH_BTMP, O_RDONLY); + if (fd < 0) { + pam_syslog(pamh, LOG_ERR, "unable to open %s: %m", _PATH_BTMP); + D(("unable to open %s file", _PATH_BTMP)); + return PAM_SERVICE_ERR; + } + + while ((retval=pam_modutil_read(fd, (void *)&ut, + sizeof(ut))) == sizeof(ut)) { + if (ut.ut_tv.tv_sec >= lltime && strncmp(ut.ut_user, user, UT_NAMESIZE) == 0) { + memcpy(&utuser, &ut, sizeof(utuser)); + failed++; + } + } + + if (failed) { + /* we want the date? */ + if (announce & LASTLOG_DATE) { + struct tm *tm, tm_buf; + time_t lf_time; + + lf_time = utuser.ut_tv.tv_sec; + tm = localtime_r (&lf_time, &tm_buf); + strftime (the_time, sizeof (the_time), + /* TRANSLATORS: "strftime options for date of last login" */ + _(" %a %b %e %H:%M:%S %Z %Y"), tm); + + date = the_time; + } + + /* we want & have the host? */ + if ((announce & LASTLOG_HOST) + && (utuser.ut_host[0] != '\0')) { + /* TRANSLATORS: " from " */ + if (asprintf(&host, _(" from %.*s"), UT_HOSTSIZE, + utuser.ut_host) < 0) { + pam_syslog(pamh, LOG_ERR, "out of memory"); + retval = PAM_BUF_ERR; + goto cleanup; + } + } + + /* we want and have the terminal? */ + if ((announce & LASTLOG_LINE) + && (utuser.ut_line[0] != '\0')) { + /* TRANSLATORS: " on " */ + if (asprintf(&line, _(" on %.*s"), UT_LINESIZE, + utuser.ut_line) < 0) { + pam_syslog(pamh, LOG_ERR, "out of memory"); + retval = PAM_BUF_ERR; + goto cleanup; + } + } + + if (line != NULL || date != NULL || host != NULL) { + /* TRANSLATORS: "Last failed login: from on " */ + pam_info(pamh, _("Last failed login:%s%s%s"), + date ? date : "", + host ? host : "", + line ? line : ""); + } + + _pam_drop(line); +#if defined HAVE_DNGETTEXT && defined ENABLE_NLS + retval = asprintf (&line, dngettext(PACKAGE, + "There was %d failed login attempt since the last successful login.", + "There were %d failed login attempts since the last successful login.", + failed), + failed); +#else + if (daysleft == 1) + retval = asprintf(&line, + _("There was %d failed login attempt since the last successful login."), + failed); + else + retval = asprintf(&line, + /* TRANSLATORS: only used if dngettext is not supported */ + _("There were %d failed login attempts since the last successful login."), + failed); +#endif + if (retval >= 0) + retval = pam_info(pamh, "%s", line); + else { + retval = PAM_BUF_ERR; + line = NULL; + } + } + +cleanup: + free(host); + free(line); + close(fd); + D(("all done with btmp")); + + return retval; +} + /* --- authentication management functions (only) --- */ PAM_EXTERN int @@ -379,6 +508,7 @@ pam_sm_open_session(pam_handle_t *pamh, int flags, const void *user; const struct passwd *pwd; uid_t uid; + time_t lltime = 0; /* * this module gets the uid of the PAM_USER. Uses it to display @@ -407,7 +537,11 @@ pam_sm_open_session(pam_handle_t *pamh, int flags, /* process the current login attempt (indicate last) */ - retval = last_login_date(pamh, ctrl, uid, user); + retval = last_login_date(pamh, ctrl, uid, user, &lltime); + + if ((ctrl & LASTLOG_BTMP) && retval == PAM_SUCCESS) { + retval = last_login_failed(pamh, ctrl, user, lltime); + } /* indicate success or failure */ -- cgit v1.2.3 From dad5bd7c146a842e11da19c5715db117d62f5677 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Fri, 10 Oct 2008 06:53:45 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-10-10 Thorsten Kukuk * configure.in: add modules/pam_pwhistory/Makefile. * doc/sag/Linux-PAM_SAG.xml: Include pam_pwhistory.xml. * doc/sag/pam_pwhistory.xml: New. * libpam/pam_static_modules.h: Add pam_pwhistory data. * modules/Makefile.am: Add pam_pwhistory directory. * modules/pam_pwhistory/Makefile.am: New. * modules/pam_pwhistory/README.xml: New. * modules/pam_pwhistory/opasswd.c: New. * modules/pam_pwhistory/opasswd.h: New. * modules/pam_pwhistory/pam_pwhistory.8.xml: New. * modules/pam_pwhistory/pam_pwhistory.c: New. * modules/pam_pwhistory/tst-pam_pwhistory: New. * xtests/Makefile.am: New. * xtests/run-xtests.sh: New. * xtests/tst-pam_pwhistory1.c: New. * xtests/tst-pam_pwhistory1.pamd: New. * xtests/tst-pam_pwhistory1.sh: New. * po/POTFILES.in: Add modules/pam_pwhistory/. * po/de.po: Update translations. --- modules/Makefile.am | 15 +- modules/pam_pwhistory/.cvsignore | 8 + modules/pam_pwhistory/Makefile.am | 35 +++ modules/pam_pwhistory/README.xml | 41 +++ modules/pam_pwhistory/opasswd.c | 473 ++++++++++++++++++++++++++++++ modules/pam_pwhistory/opasswd.h | 45 +++ modules/pam_pwhistory/pam_pwhistory.8.xml | 226 ++++++++++++++ modules/pam_pwhistory/pam_pwhistory.c | 319 ++++++++++++++++++++ modules/pam_pwhistory/tst-pam_pwhistory | 2 + 9 files changed, 1157 insertions(+), 7 deletions(-) create mode 100644 modules/pam_pwhistory/.cvsignore create mode 100644 modules/pam_pwhistory/Makefile.am create mode 100644 modules/pam_pwhistory/README.xml create mode 100644 modules/pam_pwhistory/opasswd.c create mode 100644 modules/pam_pwhistory/opasswd.h create mode 100644 modules/pam_pwhistory/pam_pwhistory.8.xml create mode 100644 modules/pam_pwhistory/pam_pwhistory.c create mode 100755 modules/pam_pwhistory/tst-pam_pwhistory (limited to 'modules') diff --git a/modules/Makefile.am b/modules/Makefile.am index c79f5957..f21d52e8 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -1,15 +1,16 @@ # -# Copyright (c) 2005, 2006 Thorsten Kukuk +# Copyright (c) 2005, 2006, 2008 Thorsten Kukuk # SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \ - pam_env pam_filter pam_ftp pam_group pam_issue pam_keyinit \ - pam_lastlog pam_limits pam_listfile pam_localuser pam_mail \ - pam_mkhomedir pam_motd pam_nologin pam_permit pam_rhosts pam_rootok \ - pam_securetty pam_selinux pam_sepermit pam_shells pam_stress \ + pam_env pam_exec pam_faildelay pam_filter pam_ftp \ + pam_group pam_issue pam_keyinit pam_lastlog pam_limits \ + pam_listfile pam_localuser pam_loginuid pam_mail \ + pam_mkhomedir pam_motd pam_namespace pam_nologin \ + pam_permit pam_pwhistory pam_rhosts pam_rootok pam_securetty \ + pam_selinux pam_sepermit pam_shells pam_stress \ pam_succeed_if pam_tally pam_time pam_tty_audit pam_umask \ - pam_unix pam_userdb pam_warn pam_wheel pam_xauth pam_exec \ - pam_namespace pam_loginuid pam_faildelay + pam_unix pam_userdb pam_warn pam_wheel pam_xauth CLEANFILES = *~ diff --git a/modules/pam_pwhistory/.cvsignore b/modules/pam_pwhistory/.cvsignore new file mode 100644 index 00000000..c0d3c72c --- /dev/null +++ b/modules/pam_pwhistory/.cvsignore @@ -0,0 +1,8 @@ +*.la +*.lo +.deps +.libs +Makefile +Makefile.in +README +pam_pwhistory.8 diff --git a/modules/pam_pwhistory/Makefile.am b/modules/pam_pwhistory/Makefile.am new file mode 100644 index 00000000..018d0b52 --- /dev/null +++ b/modules/pam_pwhistory/Makefile.am @@ -0,0 +1,35 @@ +# +# Copyright (c) 2008 Thorsten Kukuk +# + +CLEANFILES = *~ + +EXTRA_DIST = README $(MANS) $(XMLS) tst-pam_pwhistory + +TESTS = tst-pam_pwhistory + +man_MANS = pam_pwhistory.8 + +XMLS = README.xml pam_pwhistory.8.xml + +securelibdir = $(SECUREDIR) +secureconfdir = $(SCONFIGDIR) + +AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include +AM_LDFLAGS = -no-undefined -avoid-version -module +if HAVE_VERSIONING + AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map +endif + +noinst_HEADERS = opasswd.h + +securelib_LTLIBRARIES = pam_pwhistory.la +pam_pwhistory_la_LIBADD = -L$(top_builddir)/libpam -lpam @LIBCRYPT@ +pam_pwhistory_la_SOURCES = pam_pwhistory.c opasswd.c + +if ENABLE_REGENERATE_MAN +noinst_DATA = README +README: pam_pwhistory.8.xml +-include $(top_srcdir)/Make.xml.rules +endif + diff --git a/modules/pam_pwhistory/README.xml b/modules/pam_pwhistory/README.xml new file mode 100644 index 00000000..f048e321 --- /dev/null +++ b/modules/pam_pwhistory/README.xml @@ -0,0 +1,41 @@ + + +--> +]> + +
+ + + + + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" + href="pam_pwhistory.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_pwhistory-name"]/*)'/> + + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c new file mode 100644 index 00000000..89452d3f --- /dev/null +++ b/modules/pam_pwhistory/opasswd.c @@ -0,0 +1,473 @@ +/* + * Copyright (c) 2008 Thorsten Kukuk + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (HAVE_XCRYPT_H) +#include +#elif defined (HAVE_CRYPT_H) +#include +#endif + +#include +#include + +#include "opasswd.h" + +#ifndef RANDOM_DEVICE +#define RANDOM_DEVICE "/dev/urandom" +#endif + +#define OLD_PASSWORDS_FILE "/etc/security/opasswd" +#define TMP_PASSWORDS_FILE OLD_PASSWORDS_FILE".tmpXXXXXX" + +#define DEFAULT_BUFLEN 4096 + +typedef struct { + char *user; + char *uid; + int count; + char *old_passwords; +} opwd; + + +static int +parse_entry (char *line, opwd *data) +{ + const char delimiters[] = ":"; + char *endptr; + + data->user = strsep (&line, delimiters); + data->uid = strsep (&line, delimiters); + data->count = strtol (strsep (&line, delimiters), &endptr, 10); + if (endptr != NULL && *endptr != '\0') + return 1; + + data->old_passwords = strsep (&line, delimiters); + + return 0; +} + +/* Check, if the new password is already in the opasswd file. */ +int +check_old_password (pam_handle_t *pamh, const char *user, + const char *newpass, int debug) +{ + int retval = PAM_SUCCESS; + FILE *oldpf; + char *buf = NULL; + size_t buflen = 0; + opwd entry; + int found = 0; + + if ((oldpf = fopen (OLD_PASSWORDS_FILE, "r")) == NULL) + { + if (errno != ENOENT) + pam_syslog (pamh, LOG_ERR, "Cannot open %s: %m", OLD_PASSWORDS_FILE); + return PAM_SUCCESS; + } + + while (!feof (oldpf)) + { + char *cp, *tmp; +#if defined(HAVE_GETLINE) + ssize_t n = getline (&buf, &buflen, oldpf); +#elif defined (HAVE_GETDELIM) + ssize_t n = getdelim (&buf, &buflen, '\n', oldpf); +#else + ssize_t n; + + if (buf == NULL) + { + buflen = DEFAULT_BUFLEN; + buf = malloc (buflen); + if (buf == NULL) + return PAM_BUF_ERR; + } + buf[0] = '\0'; + fgets (buf, buflen - 1, oldpf); + n = strlen (buf); +#endif /* HAVE_GETLINE / HAVE_GETDELIM */ + cp = buf; + + if (n < 1) + break; + + tmp = strchr (cp, '#'); /* remove comments */ + if (tmp) + *tmp = '\0'; + while (isspace ((int)*cp)) /* remove spaces and tabs */ + ++cp; + if (*cp == '\0') /* ignore empty lines */ + continue; + + if (cp[strlen (cp) - 1] == '\n') + cp[strlen (cp) - 1] = '\0'; + + if (strncmp (cp, user, strlen (user)) == 0 && + cp[strlen (user)] == ':') + { + /* We found the line we needed */ + if (parse_entry (cp, &entry) == 0) + { + found = 1; + break; + } + } + } + + fclose (oldpf); + + if (found) + { + const char delimiters[] = ","; + struct crypt_data output; + char *running; + char *oldpass; + + memset (&output, 0, sizeof (output)); + + running = strdupa (entry.old_passwords); + if (running == NULL) + return PAM_BUF_ERR; + + do { + oldpass = strsep (&running, delimiters); + if (oldpass && strlen (oldpass) > 0 && + strcmp (crypt_r (newpass, oldpass, &output), oldpass) == 0) + { + if (debug) + pam_syslog (pamh, LOG_DEBUG, "New password already used"); + retval = PAM_AUTHTOK_ERR; + break; + } + } while (oldpass != NULL); + } + + if (buf) + free (buf); + + return retval; +} + +int +save_old_password (pam_handle_t *pamh, const char *user, uid_t uid, + const char *oldpass, int howmany, int debug UNUSED) +{ + char opasswd_tmp[] = TMP_PASSWORDS_FILE; + struct stat opasswd_stat; + FILE *oldpf, *newpf; + int newpf_fd; + int do_create = 0; + int retval = PAM_SUCCESS; + char *buf = NULL; + size_t buflen = 0; + int found = 0; + + if (howmany <= 0) + return PAM_SUCCESS; + + if (oldpass == NULL || *oldpass == '\0') + return PAM_SUCCESS; + + if ((oldpf = fopen (OLD_PASSWORDS_FILE, "r")) == NULL) + { + if (errno == ENOENT) + { + pam_syslog (pamh, LOG_NOTICE, "Creating %s", + OLD_PASSWORDS_FILE); + do_create = 1; + } + else + { + pam_syslog (pamh, LOG_ERR, "Cannot open %s: %m", + OLD_PASSWORDS_FILE); + return PAM_AUTHTOK_ERR; + } + } + else if (fstat (fileno (oldpf), &opasswd_stat) < 0) + { + pam_syslog (pamh, LOG_ERR, "Cannot stat %s: %m", OLD_PASSWORDS_FILE); + fclose (oldpf); + return PAM_AUTHTOK_ERR; + } + + /* Open a temp passwd file */ + newpf_fd = mkstemp (opasswd_tmp); + if (newpf_fd == -1) + { + pam_syslog (pamh, LOG_ERR, "Cannot create %s temp file: %m", + OLD_PASSWORDS_FILE); + fclose (oldpf); + return PAM_AUTHTOK_ERR; + } + if (do_create) + { + if (fchmod (newpf_fd, S_IRUSR|S_IWUSR) != 0) + pam_syslog (pamh, LOG_ERR, + "Cannot set permissions of %s temp file: %m", + OLD_PASSWORDS_FILE); + if (fchown (newpf_fd, 0, 0) != 0) + pam_syslog (pamh, LOG_ERR, + "Cannot set owner/group of %s temp file: %m", + OLD_PASSWORDS_FILE); + } + else + { + if (fchmod (newpf_fd, opasswd_stat.st_mode) != 0) + pam_syslog (pamh, LOG_ERR, + "Cannot set permissions of %s temp file: %m", + OLD_PASSWORDS_FILE); + if (fchown (newpf_fd, opasswd_stat.st_uid, opasswd_stat.st_gid) != 0) + pam_syslog (pamh, LOG_ERR, + "Cannot set owner/group of %s temp file: %m", + OLD_PASSWORDS_FILE); + } + newpf = fdopen (newpf_fd, "w+"); + if (newpf == NULL) + { + pam_syslog (pamh, LOG_ERR, "Cannot fdopen %s: %m", opasswd_tmp); + fclose (oldpf); + close (newpf_fd); + retval = PAM_AUTHTOK_ERR; + goto error_opasswd; + } + + if (!do_create) + while (!feof (oldpf)) + { + char *cp, *tmp, *save; +#if defined(HAVE_GETLINE) + ssize_t n = getline (&buf, &buflen, oldpf); +#elif defined (HAVE_GETDELIM) + ssize_t n = getdelim (&buf, &buflen, '\n', oldpf); +#else + ssize_t n; + + if (buf == NULL) + { + buflen = DEFAULT_BUFLEN; + buf = malloc (buflen); + if (buf == NULL) + return PAM_BUF_ERR; + + } + buf[0] = '\0'; + fgets (buf, buflen - 1, oldpf); + n = strlen (buf); +#endif /* HAVE_GETLINE / HAVE_GETDELIM */ + + cp = buf; + save = strdup (buf); /* Copy to write the original data back. */ + if (save == NULL) + return PAM_BUF_ERR; + + if (n < 1) + break; + + tmp = strchr (cp, '#'); /* remove comments */ + if (tmp) + *tmp = '\0'; + while (isspace ((int)*cp)) /* remove spaces and tabs */ + ++cp; + if (*cp == '\0') /* ignore empty lines */ + goto write_old_data; + + if (cp[strlen (cp) - 1] == '\n') + cp[strlen (cp) - 1] = '\0'; + + if (strncmp (cp, user, strlen (user)) == 0 && + cp[strlen (user)] == ':') + { + /* We found the line we needed */ + opwd entry; + + if (parse_entry (cp, &entry) == 0) + { + char *out = NULL; + + found = 1; + + /* Don't save the current password twice */ + if (entry.old_passwords) + { + /* there is only one password */ + if (strcmp (entry.old_passwords, oldpass) == 0) + goto write_old_data; + else + { + /* check last entry */ + cp = strstr (entry.old_passwords, oldpass); + + if (cp && strcmp (cp, oldpass) == 0) + { /* the end is the same, check that there + is a "," before. */ + --cp; + if (*cp == ',') + goto write_old_data; + } + } + } + + /* increase count. */ + entry.count++; + + /* check that we don't remember to many passwords. */ + while (entry.count > howmany) + { + char *p = strpbrk (entry.old_passwords, ","); + if (p != NULL) + entry.old_passwords = ++p; + entry.count--; + } + + if (entry.old_passwords == NULL) + { + if (asprintf (&out, "%s:%s:%d:%s\n", + entry.user, entry.uid, entry.count, + oldpass) < 0) + { + retval = PAM_AUTHTOK_ERR; + fclose (oldpf); + fclose (newpf); + goto error_opasswd; + } + } + else + { + if (asprintf (&out, "%s:%si%d:%s,%s\n", + entry.user, entry.uid, entry.count, + entry.old_passwords, oldpass) < 0) + { + retval = PAM_AUTHTOK_ERR; + fclose (oldpf); + fclose (newpf); + goto error_opasswd; + } + } + + if (fputs (out, newpf) < 0) + { + free (out); + free (save); + retval = PAM_AUTHTOK_ERR; + fclose (oldpf); + fclose (newpf); + goto error_opasswd; + } + free (out); + } + } + else + { + write_old_data: + if (fputs (save, newpf) < 0) + { + free (save); + retval = PAM_AUTHTOK_ERR; + fclose (oldpf); + fclose (newpf); + goto error_opasswd; + } + } + free (save); + } + + if (!found) + { + char *out; + + if (asprintf (&out, "%s:%d:1:%s\n", user, uid, oldpass) < 0) + { + retval = PAM_AUTHTOK_ERR; + if (oldpf) + fclose (oldpf); + fclose (newpf); + goto error_opasswd; + } + if (fputs (out, newpf) < 0) + { + free (out); + retval = PAM_AUTHTOK_ERR; + if (oldpf) + fclose (oldpf); + fclose (newpf); + goto error_opasswd; + } + free (out); + } + + if (oldpf) + if (fclose (oldpf) != 0) + { + pam_syslog (pamh, LOG_ERR, "Error while closing old opasswd file: %m"); + retval = PAM_AUTHTOK_ERR; + fclose (newpf); + goto error_opasswd; + } + + if (fclose (newpf) != 0) + { + pam_syslog (pamh, LOG_ERR, + "Error while closing temporary opasswd file: %m"); + retval = PAM_AUTHTOK_ERR; + goto error_opasswd; + } + + unlink (OLD_PASSWORDS_FILE".old"); + if (link (OLD_PASSWORDS_FILE, OLD_PASSWORDS_FILE".old") != 0 && + errno != ENOENT) + pam_syslog (pamh, LOG_ERR, "Cannot create backup file of %s: %m", + OLD_PASSWORDS_FILE); + rename (opasswd_tmp, OLD_PASSWORDS_FILE); + error_opasswd: + unlink (opasswd_tmp); + + return retval; +} diff --git a/modules/pam_pwhistory/opasswd.h b/modules/pam_pwhistory/opasswd.h new file mode 100644 index 00000000..e8a20139 --- /dev/null +++ b/modules/pam_pwhistory/opasswd.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008 Thorsten Kukuk + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __OPASSWD_H__ +#define __OPASSWD_H__ + +extern int check_old_password (pam_handle_t *pamh, const char *user, + const char *newpass, int debug); +extern int save_old_password (pam_handle_t *pamh, const char *user, + uid_t uid, const char *oldpass, + int howmany, int debug); + +#endif /* __OPASSWD_H__ */ diff --git a/modules/pam_pwhistory/pam_pwhistory.8.xml b/modules/pam_pwhistory/pam_pwhistory.8.xml new file mode 100644 index 00000000..26d6bd15 --- /dev/null +++ b/modules/pam_pwhistory/pam_pwhistory.8.xml @@ -0,0 +1,226 @@ + + + + + + + pam_pwhistory + 8 + Linux-PAM Manual + + + + pam_pwhistory + PAM module to remember last passwords + + + + + pam_pwhistory.so + + debug + + + use_authtok + + + enforce_for_root + + + remember=N + + + retry=N + + + + + + + + DESCRIPTION + + + This module saves the last passwords for each user in order + to force password change history and keep the user from + alternating between the same password too frequently. + + + This module does not work togehter with kerberos. In general, + it does not make much sense to use this module in conjuction + with NIS or LDAP, since the old passwords are stored on the + local machine and are not available on another machine for + password history checking. + + + + + OPTIONS + + + + + + + + Turns on debugging via + + syslog3 + . + + + + + + + + + + When password changing enforce the module to use the new password + provided by a previously stacked + module (this is used in the example of the stacking of the + pam_cracklib module documented below). + + + + + + + + + + If this option is set, the check is enforced for root, too. + + + + + + + + + + The last N passwords for each + user are saved in /etc/security/opasswd. + The default is 10. + + + + + + + + + + Prompt user at most N times + before returning with error. The default is + 1. + + + + + + + + + MODULE TYPES PROVIDED + + Only the module type is provided. + + + + + RETURN VALUES + + + PAM_AUTHTOK_ERR + + + No new password was entered, the user aborted password + change or new password couldn't be set. + + + + + PAM_IGNORE + + + Password history was disabled. + + + + + PAM_MAXTRIES + + + Password was rejected too often. + + + + + PAM_USER_UNKNOWN + + + User is not known to system. + + + + + + + + EXAMPLES + + An example password section would be: + +#%PAM-1.0 +password required pam_pwhistory.so +password required pam_unix.so use_authtok + + + + In combination with pam_cracklib: + +#%PAM-1.0 +password required pam_cracklib.so retry=3 +password required pam_pwhistory.so use_authtok +password required pam_unix.so use_authtok + + + + + + FILES + + + /etc/security/opasswd + + File with password history + + + + + + + SEE ALSO + + + pam.conf5 + , + + pam.d5 + , + + pam8 + + + + + + AUTHOR + + pam_pwhistory was written by Thorsten Kukuk <kukuk@thkukuk.de> + + + + diff --git a/modules/pam_pwhistory/pam_pwhistory.c b/modules/pam_pwhistory/pam_pwhistory.c new file mode 100644 index 00000000..d3cce728 --- /dev/null +++ b/modules/pam_pwhistory/pam_pwhistory.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2008 Thorsten Kukuk + * Author: Thorsten Kukuk + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#define PAM_SM_PASSWORD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "opasswd.h" + +#define NEW_PASSWORD_PROMPT _("New %s%spassword: ") +#define AGAIN_PASSWORD_PROMPT _("Retype new %s%spassword: ") +#define MISTYPED_PASSWORD _("Sorry, passwords do not match.") + +#define DEFAULT_BUFLEN 2048 + +struct options_t { + int debug; + int use_authtok; + int enforce_for_root; + int remember; + int tries; +}; +typedef struct options_t options_t; + + +static void +parse_option (pam_handle_t *pamh, const char *argv, options_t *options) +{ + if (strcasecmp (argv, "use_first_pass") == 0) + /* ignore */; + else if (strcasecmp (argv, "use_first_pass") == 0) + /* ignore */; + else if (strcasecmp (argv, "use_authtok") == 0) + options->use_authtok = 1; + else if (strcasecmp (argv, "debug") == 0) + options->debug = 1; + else if (strncasecmp (argv, "remember=", 9) == 0) + { + options->remember = strtol(&argv[9], NULL, 10); + if (options->remember < 0) + options->remember = 0; + if (options->remember > 400) + options->remember = 400; + } + else if (strncasecmp (argv, "retry=", 6) == 0) + { + options->tries = strtol(&argv[6], NULL, 10); + if (options->tries < 0) + options->tries = 1; + } + else if (strcasecmp (argv, "enforce_for_root") == 0) + options->enforce_for_root = 1; + else + pam_syslog (pamh, LOG_ERR, "pam_pwhistory: unknown option: %s", argv); +} + + +PAM_EXTERN int +pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + struct passwd *pwd; + char *newpass; + const char *user; + void *newpass_void; + int retval, tries; + options_t options; + + memset (&options, 0, sizeof (options)); + + /* Set some default values, which could be overwritten later. */ + options.remember = 10; + options.tries = 1; + + /* Parse parameters for module */ + for ( ; argc-- > 0; argv++) + parse_option (pamh, *argv, &options); + + if (options.debug) + pam_syslog (pamh, LOG_DEBUG, "pam_sm_chauthtok entered"); + + + if (options.remember == 0) + return PAM_IGNORE; + + retval = pam_get_user (pamh, &user, NULL); + if (retval != PAM_SUCCESS) + return retval; + + if (user == NULL || strlen (user) == 0) + { + if (options.debug) + pam_syslog (pamh, LOG_DEBUG, + "User is not known to system"); + + return PAM_USER_UNKNOWN; + } + + if (flags & PAM_PRELIM_CHECK) + { + if (options.debug) + pam_syslog (pamh, LOG_DEBUG, + "pam_sm_chauthtok(PAM_PRELIM_CHECK)"); + + return PAM_SUCCESS; + } + + pwd = pam_modutil_getpwnam (pamh, user); + if (pwd == NULL) + return PAM_USER_UNKNOWN; + + /* Ignore root if not enforced */ + if (pwd->pw_uid == 0 && !options.enforce_for_root) + return PAM_SUCCESS; + + if ((strcmp(pwd->pw_passwd, "x") == 0) || + ((pwd->pw_passwd[0] == '#') && + (pwd->pw_passwd[1] == '#') && + (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0))) + { + struct spwd *spw = pam_modutil_getspnam (pamh, user); + if (spw == NULL) + return PAM_USER_UNKNOWN; + + retval = save_old_password (pamh, user, pwd->pw_uid, spw->sp_pwdp, + options.remember, options.debug); + if (retval != PAM_SUCCESS) + return retval; + } + else + { + retval = save_old_password (pamh, user, pwd->pw_uid, pwd->pw_passwd, + options.remember, options.debug); + if (retval != PAM_SUCCESS) + return retval; + } + + retval = pam_get_item (pamh, PAM_AUTHTOK, (const void **) &newpass_void); + newpass = (char *) newpass_void; + if (retval != PAM_SUCCESS) + return retval; + if (options.debug) + { + if (newpass) + pam_syslog (pamh, LOG_DEBUG, "got new auth token"); + else + pam_syslog (pamh, LOG_DEBUG, "new auth token not set"); + } + + /* If we haven't been given a password yet, prompt for one... */ + if (newpass == NULL) + { + if (options.use_authtok) + /* We are not allowed to ask for a new password */ + return PAM_AUTHTOK_ERR; + + tries = 0; + + while ((newpass == NULL) && (tries++ < options.tries)) + { + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &newpass, + NEW_PASSWORD_PROMPT, "UNIX", " "); + if (retval != PAM_SUCCESS) + { + _pam_drop (newpass); + if (retval == PAM_CONV_AGAIN) + retval = PAM_INCOMPLETE; + return retval; + } + + if (newpass == NULL) + { + /* We want to abort the password change */ + pam_error (pamh, _("Password change aborted.")); + return PAM_AUTHTOK_ERR; + } + + if (options.debug) + pam_syslog (pamh, LOG_DEBUG, "check against old password file"); + + if (check_old_password (pamh, user, newpass, + options.debug) != PAM_SUCCESS) + { + pam_error (pamh, + _("Password has been already used. Choose another.")); + _pam_overwrite (newpass); + _pam_drop (newpass); + if (tries >= options.tries) + { + if (options.debug) + pam_syslog (pamh, LOG_DEBUG, + "Aborted, too many tries"); + return PAM_MAXTRIES; + } + } + else + { + int failed; + char *new2; + + retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &new2, + AGAIN_PASSWORD_PROMPT, "UNIX", " "); + if (retval != PAM_SUCCESS) + return retval; + + if (new2 == NULL) + { /* Aborting password change... */ + pam_error (pamh, _("Password change aborted.")); + return PAM_AUTHTOK_ERR; + } + + failed = (strcmp (newpass, new2) != 0); + + _pam_overwrite (new2); + _pam_drop (new2); + + if (failed) + { + pam_error (pamh, MISTYPED_PASSWORD); + _pam_overwrite (newpass); + _pam_drop (newpass); + if (tries >= options.tries) + { + if (options.debug) + pam_syslog (pamh, LOG_DEBUG, + "Aborted, too many tries"); + return PAM_MAXTRIES; + } + } + } + } + + /* Remember new password */ + pam_set_item (pamh, PAM_AUTHTOK, (void *) newpass); + } + else /* newpass != NULL, we found an old password */ + { + if (options.debug) + pam_syslog (pamh, LOG_DEBUG, "look in old password file"); + + if (check_old_password (pamh, user, newpass, + options.debug) != PAM_SUCCESS) + { + pam_error (pamh, + _("Password has been already used. Choose another.")); + /* We are only here, because old password was set. + So overwrite it, else it will be stored! */ + pam_set_item (pamh, PAM_AUTHTOK, (void *) NULL); + + return PAM_AUTHTOK_ERR; + } + } + + return PAM_SUCCESS; +} + + +#ifdef PAM_STATIC +/* static module data */ +struct pam_module _pam_pwhistory_modstruct = { + "pam_pwhistory", + NULL, + NULL, + NULL, + NULL, + NULL, + pam_sm_chauthtok +}; +#endif diff --git a/modules/pam_pwhistory/tst-pam_pwhistory b/modules/pam_pwhistory/tst-pam_pwhistory new file mode 100755 index 00000000..3531a88a --- /dev/null +++ b/modules/pam_pwhistory/tst-pam_pwhistory @@ -0,0 +1,2 @@ +#!/bin/sh +../../tests/tst-dlopen .libs/pam_pwhistory.so -- cgit v1.2.3 From 8283ef44f01931108c5f29bd4e0bda8c86bc5478 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Sun, 12 Oct 2008 17:06:04 +0000 Subject: Relevant BUGIDs: Purpose of commit: Commit summary: --------------- 2008-10-10 Thorsten Kukuk * modules/pam_cracklib/pam_cracklib.c (_pam_unix_approve_pass): Remove check for re-used passwords. * modules/pam_cracklib/pam_cracklib.8.xml: Remove documentation of re-used password check. --- modules/pam_cracklib/pam_cracklib.8.xml | 9 ------- modules/pam_cracklib/pam_cracklib.c | 44 ++------------------------------- 2 files changed, 2 insertions(+), 51 deletions(-) (limited to 'modules') diff --git a/modules/pam_cracklib/pam_cracklib.8.xml b/modules/pam_cracklib/pam_cracklib.8.xml index 3d061c43..336da5dd 100644 --- a/modules/pam_cracklib/pam_cracklib.8.xml +++ b/modules/pam_cracklib/pam_cracklib.8.xml @@ -111,15 +111,6 @@ - - Already used - - - Was the password used in the past? Previously used passwords - are to be found in /etc/security/opasswd. - - - Same consecutive characters diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c index 3dcc4729..2c4cd4a0 100644 --- a/modules/pam_cracklib/pam_cracklib.c +++ b/modules/pam_cracklib/pam_cracklib.c @@ -462,7 +462,7 @@ static int usercheck(struct cracklib_options *opt, const char *new, /* now reverse the username, we can do that in place as it is strdup-ed */ f = user; - b = user+strlen(user)-1; + b = user+strlen(user)-1; while (f < b) { char c; @@ -547,43 +547,6 @@ static const char *password_check(struct cracklib_options *opt, } -#define OLD_PASSWORDS_FILE "/etc/security/opasswd" - -static const char * check_old_password(const char *forwho, const char *newpass) -{ - static char buf[16384]; - char *s_luser, *s_uid, *s_npas, *s_pas; - const char *msg = NULL; - FILE *opwfile; - - opwfile = fopen(OLD_PASSWORDS_FILE, "r"); - if (opwfile == NULL) - return NULL; - - while (fgets(buf, 16380, opwfile)) { - if (!strncmp(buf, forwho, strlen(forwho))) { - char *sptr; - buf[strlen(buf)-1] = '\0'; - s_luser = strtok_r(buf, ":,", &sptr); - s_uid = strtok_r(NULL, ":,", &sptr); - s_npas = strtok_r(NULL, ":,", &sptr); - s_pas = strtok_r(NULL, ":,", &sptr); - while (s_pas != NULL) { - if (!strcmp(crypt(newpass, s_pas), s_pas)) { - msg = _("has been already used"); - break; - } - s_pas = strtok_r(NULL, ":,", &sptr); - } - break; - } - } - fclose(opwfile); - - return msg; -} - - static int _pam_unix_approve_pass(pam_handle_t *pamh, unsigned int ctrl, struct cracklib_options *opt, @@ -613,9 +576,6 @@ static int _pam_unix_approve_pass(pam_handle_t *pamh, * checking this would be the place */ msg = password_check(opt, pass_old, pass_new, user); - if (!msg) { - msg = check_old_password(user, pass_new); - } if (msg) { if (ctrl & PAM_DEBUG_ARG) @@ -710,7 +670,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, retval = PAM_AUTHTOK_RECOVERY_ERR; /* didn't work */ } } - + if (options.use_authtok != 1) { /* Prepare to ask the user for the first time */ resp = NULL; -- cgit v1.2.3 From 955caa5f8c4840931ce49bcd8f59c8803c8f0266 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 17 Oct 2008 11:09:25 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-10-15 Tomas Mraz * modules/pam_keyinit/pam_keyinit.c (kill_keyrings): Save the old euid to suid to be able to restore it. --- modules/pam_keyinit/pam_keyinit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_keyinit/pam_keyinit.c b/modules/pam_keyinit/pam_keyinit.c index 378a7723..4732f93b 100644 --- a/modules/pam_keyinit/pam_keyinit.c +++ b/modules/pam_keyinit/pam_keyinit.c @@ -143,7 +143,7 @@ static void kill_keyrings(pam_handle_t *pamh) error(pamh, "Unable to change GID to %d temporarily\n", revoke_as_gid); - if (revoke_as_uid != old_uid && setreuid(-1, revoke_as_uid) < 0) + if (revoke_as_uid != old_uid && setresuid(-1, revoke_as_uid, old_uid) < 0) error(pamh, "Unable to change UID to %d temporarily\n", revoke_as_uid); -- cgit v1.2.3 From 114ed318bea9b5859ab89144261946716776e2ed Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 17 Oct 2008 11:29:55 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-10-17 Tomas Mraz * configure.in: Add modules/pam_tally2/Makefile. * doc/sag/Linux-PAM_SAG.xml: Include pam_tally2.xml. * doc/sag/pam_tally2.xml: New. * libpam/pam_static_modules.h: Add pam_tally2 static struct. * modules/Makefile.am: Add pam_tally2 directory. * modules/pam_tally2/Makefile.am: New. * modules/pam_tally2/README.xml: New. * modules/pam_tally2/tallylog.h: New. * modules/pam_tally2/pam_tally2.8.xml: New. * modules/pam_tally2/pam_tally2.c: New. * modules/pam_tally2/pam_tally2_app.c: New. * modules/pam_tally2/tst-pam_tally2: New. * po/POTFILES.in: Add pam_tally2 sources. --- modules/Makefile.am | 2 +- modules/pam_tally2/.cvsignore | 9 + modules/pam_tally2/Makefile.am | 40 ++ modules/pam_tally2/README.xml | 46 ++ modules/pam_tally2/pam_tally2.8.xml | 439 ++++++++++++++++ modules/pam_tally2/pam_tally2.c | 985 ++++++++++++++++++++++++++++++++++++ modules/pam_tally2/pam_tally2_app.c | 7 + modules/pam_tally2/tallylog.h | 52 ++ modules/pam_tally2/tst-pam_tally2 | 2 + 9 files changed, 1581 insertions(+), 1 deletion(-) create mode 100644 modules/pam_tally2/.cvsignore create mode 100644 modules/pam_tally2/Makefile.am create mode 100644 modules/pam_tally2/README.xml create mode 100644 modules/pam_tally2/pam_tally2.8.xml create mode 100644 modules/pam_tally2/pam_tally2.c create mode 100644 modules/pam_tally2/pam_tally2_app.c create mode 100644 modules/pam_tally2/tallylog.h create mode 100755 modules/pam_tally2/tst-pam_tally2 (limited to 'modules') diff --git a/modules/Makefile.am b/modules/Makefile.am index f21d52e8..37d5a739 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -9,7 +9,7 @@ SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \ pam_mkhomedir pam_motd pam_namespace pam_nologin \ pam_permit pam_pwhistory pam_rhosts pam_rootok pam_securetty \ pam_selinux pam_sepermit pam_shells pam_stress \ - pam_succeed_if pam_tally pam_time pam_tty_audit pam_umask \ + pam_succeed_if pam_tally pam_tally2 pam_time pam_tty_audit pam_umask \ pam_unix pam_userdb pam_warn pam_wheel pam_xauth CLEANFILES = *~ diff --git a/modules/pam_tally2/.cvsignore b/modules/pam_tally2/.cvsignore new file mode 100644 index 00000000..c20ebb92 --- /dev/null +++ b/modules/pam_tally2/.cvsignore @@ -0,0 +1,9 @@ +*.la +*.lo +.deps +.libs +Makefile +Makefile.in +pam_tally2 +README +pam_tally2.8 diff --git a/modules/pam_tally2/Makefile.am b/modules/pam_tally2/Makefile.am new file mode 100644 index 00000000..6f843e1f --- /dev/null +++ b/modules/pam_tally2/Makefile.am @@ -0,0 +1,40 @@ +# +# Copyright (c) 2005, 2006, 2007 Thorsten Kukuk +# Copyright (c) 2008 Red Hat, Inc. +# + +CLEANFILES = *~ + +EXTRA_DIST = README $(MANS) $(XMLS) tst-pam_tally2 + +man_MANS = pam_tally2.8 +XMLS = README.xml pam_tally2.8.xml + +TESTS = tst-pam_tally2 + +securelibdir = $(SECUREDIR) +secureconfdir = $(SCONFIGDIR) + +noinst_HEADERS = tallylog.h + +AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include + +pam_tally2_la_LDFLAGS = -no-undefined -avoid-version -module +pam_tally2_la_LIBADD = -L$(top_builddir)/libpam -lpam $(LIBAUDIT) +if HAVE_VERSIONING + pam_tally2_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map +endif + +pam_tally2_LDADD = $(LIBAUDIT) + +securelib_LTLIBRARIES = pam_tally2.la +sbin_PROGRAMS = pam_tally2 + +pam_tally2_la_SOURCES = pam_tally2.c +pam_tally2_SOURCES = pam_tally2_app.c + +if ENABLE_REGENERATE_MAN +noinst_DATA = README +README: pam_tally2.8.xml +-include $(top_srcdir)/Make.xml.rules +endif diff --git a/modules/pam_tally2/README.xml b/modules/pam_tally2/README.xml new file mode 100644 index 00000000..aa470570 --- /dev/null +++ b/modules/pam_tally2/README.xml @@ -0,0 +1,46 @@ + + +--> +]> + +
+ + + + + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" + href="pam_tally2.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_tally2-name"]/*)'/> + + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
diff --git a/modules/pam_tally2/pam_tally2.8.xml b/modules/pam_tally2/pam_tally2.8.xml new file mode 100644 index 00000000..dc284a1d --- /dev/null +++ b/modules/pam_tally2/pam_tally2.8.xml @@ -0,0 +1,439 @@ + + + + + + + pam_tally2 + 8 + Linux-PAM Manual + + + + pam_tally2 + The login counter (tallying) module + + + + + pam_tally2.so + + file=/path/to/counter + + + onerr=[fail|succeed] + + + magic_root + + + even_deny_root + + + deny=n + + + lock_time=n + + + unlock_time=n + + + root_unlock_time=n + + + audit + + + silent + + + no_log_info + + + + pam_tally2 + + --file /path/to/counter + + + --user username + + + --reset[=n] + + + --quiet + + + + + + + DESCRIPTION + + + This module maintains a count of attempted accesses, can + reset count on success, can deny access if too many attempts fail. + + + pam_tally2 comes in two parts: + pam_tally2.so and + pam_tally2. The former is the PAM module and + the latter, a stand-alone program. pam_tally2 + is an (optional) application which can be used to interrogate and + manipulate the counter file. It can display users' counts, set + individual counts, or clear all counts. Setting artificially high + counts may be useful for blocking users without changing their + passwords. For example, one might find it useful to clear all counts + every midnight from a cron job. + + + Normally, failed attempts to access root will + not cause the root account to become + blocked, to prevent denial-of-service: if your users aren't given + shell accounts and root may only login via su or + at the machine console (not telnet/rsh, etc), this is safe. + + + + + + OPTIONS + + + + GLOBAL OPTIONS + + + + This can be used for auth and + account module types. + + + + + + + + + If something weird happens (like unable to open the file), + return with PAM_SUCESS if + + is given, else with the corresponding PAM error code. + + + + + + + + + + File where to keep counts. Default is + /var/log/tallylog. + + + + + + + + + + Will log the user name into the system log if the user is not found. + + + + + + + + + + Don't print informative messages. + + + + + + + + + + Don't log informative messages via syslog3. + + + + + + + + + + AUTH OPTIONS + + + + Authentication phase first increments attempted login counter and + checks if user should be denied access. If the user is authenticated + and the login process continues on call to + pam_setcred3 + it resets the attempts counter. + + + + + + + + + Deny access if tally for this user exceeds + n. + + + + + + + + + + Always deny for n seconds + after failed attempt. + + + + + + + + + + Allow access after n seconds + after failed attempt. If this option is used the user will + be locked out for the specified amount of time after he + exceeded his maximum allowed attempts. Otherwise the + account is locked until the lock is removed by a manual + intervention of the system administrator. + + + + + + + + + + If the module is invoked by a user with uid=0 the + counter is not incremented. The sys-admin should use this + for user launched services, like su, + otherwise this argument should be omitted. + + + + + + + + + + Do not use the .fail_locktime field in + /var/log/faillog for this user. + + + + + + + + + + Don't reset count on successful entry, only decrement. + + + + + + + + + + Root account can become unavailable. + + + + + + + + + + This option implies option. + Allow access after n seconds + to root acccount after failed attempt. If this option is used + the root user will be locked out for the specified amount of + time after he exceeded his maximum allowed attempts. + + + + + + + + + + + ACCOUNT OPTIONS + + + + Account phase resets attempts counter if the user is + not magic root. + This phase can be used optionaly for services which don't call + + pam_setcred3 + correctly or if the reset should be done regardless + of the failure of the account phase of other modules. + + + + + + + + + If the module is invoked by a user with uid=0 the + counter is not changed. The sys-admin should use this + for user launched services, like su, + otherwise this argument should be omitted. + + + + + + + + + + + MODULE TYPES PROVIDED + + The and + module types are provided. + + + + + RETURN VALUES + + + PAM_AUTH_ERR + + + A invalid option was given, the module was not able + to retrive the user name, no valid counter file + was found, or too many failed logins. + + + + + PAM_SUCCESS + + + Everything was successfull. + + + + + PAM_USER_UNKNOWN + + + User not known. + + + + + + + + NOTES + + pam_tally2 is not compatible with the old pam_tally faillog file format. + This is caused by requirement of compatibility of the tallylog file + format between 32bit and 64bit architectures on multiarch systems. + + + There is no setuid wrapper for access to the data file such as when the + pam_tally2.so module is called from + xscreensaver. As this would make it impossible to share PAM configuration + with such services the following workaround is used: If the data file + cannot be opened because of insufficient permissions + (EPERM) the module returns + PAM_IGNORE. + + + + + EXAMPLES + + Add the following line to /etc/pam.d/login to + lock the account after 4 failed logins. Root account will be locked + as well. The accounts will be automatically unlocked after 20 minutes. + The module does not have to be called in the account phase because the + login calls + pam_setcred3 + correctly. + + +auth required pam_securetty.so +auth required pam_tally2.so deny=4 even_deny_root unlock_time=1200 +auth required pam_env.so +auth required pam_unix.so +auth required pam_nologin.so +account required pam_unix.so +password required pam_unix.so +session required pam_limits.so +session required pam_unix.so +session required pam_lastlog.so nowtmp +session optional pam_mail.so standard + + + + + FILES + + + /var/log/tallylog + + failure count logging file + + + + + + + SEE ALSO + + + pam.conf5 + , + + pam.d5 + , + + pam8 + + + + + + AUTHOR + + pam_tally was written by Tim Baverstock and Tomas Mraz. + + + + + diff --git a/modules/pam_tally2/pam_tally2.c b/modules/pam_tally2/pam_tally2.c new file mode 100644 index 00000000..9ae3180d --- /dev/null +++ b/modules/pam_tally2/pam_tally2.c @@ -0,0 +1,985 @@ +/* + * pam_tally2.c + * + */ + + +/* By Tim Baverstock , Multi Media Machine Ltd. + * 5 March 1997 + * + * Stuff stolen from pam_rootok and pam_listfile + * + * Changes by Tomas Mraz 5 January 2005, 26 January 2006 + * Audit option added for Tomas patch by Sebastien Tricaud 13 January 2005 + * Portions Copyright 2006, Red Hat, Inc. + * Portions Copyright 1989 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#if defined(MAIN) && defined(MEMORY_DEBUG) +# undef exit +#endif /* defined(MAIN) && defined(MEMORY_DEBUG) */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LIBAUDIT +#include +#endif + +#include +#include +#include +#include "tallylog.h" + +#ifndef TRUE +#define TRUE 1L +#define FALSE 0L +#endif + +#ifndef HAVE_FSEEKO +#define fseeko fseek +#endif + +/* + * here, we make a definition for the externally accessible function + * in this file (this definition is required for static a module + * but strongly encouraged generally) it is used to instruct the + * modules include file to define the function prototypes. + */ + +#ifndef MAIN +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT +/* #define PAM_SM_SESSION */ +/* #define PAM_SM_PASSWORD */ + +#include +#include +#endif +#include + +/*---------------------------------------------------------------------*/ + +#define DEFAULT_LOGFILE "/var/log/tallylog" +#define MODULE_NAME "pam_tally2" + +#define tally_t uint16_t +#define TALLY_HI ((tally_t)~0L) + +struct tally_options { + const char *filename; + tally_t deny; + long lock_time; + long unlock_time; + long root_unlock_time; + unsigned int ctrl; +}; + +#define PHASE_UNKNOWN 0 +#define PHASE_AUTH 1 +#define PHASE_ACCOUNT 2 +#define PHASE_SESSION 3 + +#define OPT_MAGIC_ROOT 01 +#define OPT_FAIL_ON_ERROR 02 +#define OPT_DENY_ROOT 04 +#define OPT_QUIET 040 +#define OPT_AUDIT 0100 +#define OPT_NOLOGNOTICE 0400 + + +/*---------------------------------------------------------------------*/ + +/* some syslogging */ + +#ifdef MAIN +#define pam_syslog tally_log +static void +tally_log (const pam_handle_t *pamh UNUSED, int priority UNUSED, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + fprintf(stderr, "%s: ", MODULE_NAME); + vfprintf(stderr, fmt, args); + fprintf(stderr,"\n"); + va_end(args); +} + +#define pam_modutil_getpwnam(pamh, user) getpwnam(user) +#endif + +/*---------------------------------------------------------------------*/ + +/* --- Support function: parse arguments --- */ + +#ifndef MAIN + +static void +log_phase_no_auth(pam_handle_t *pamh, int phase, const char *argv) +{ + if ( phase != PHASE_AUTH ) { + pam_syslog(pamh, LOG_ERR, + "option %s allowed in auth phase only", argv); + } +} + +static int +tally_parse_args(pam_handle_t *pamh, struct tally_options *opts, + int phase, int argc, const char **argv) +{ + memset(opts, 0, sizeof(*opts)); + opts->filename = DEFAULT_LOGFILE; + opts->ctrl = OPT_FAIL_ON_ERROR; + opts->root_unlock_time = -1; + + for ( ; argc-- > 0; ++argv ) { + + if ( ! strncmp( *argv, "file=", 5 ) ) { + const char *from = *argv + 5; + if ( *from!='/' ) { + pam_syslog(pamh, LOG_ERR, + "filename not /rooted; %s", *argv); + return PAM_AUTH_ERR; + } + opts->filename = from; + } + else if ( ! strcmp( *argv, "onerr=fail" ) ) { + opts->ctrl |= OPT_FAIL_ON_ERROR; + } + else if ( ! strcmp( *argv, "onerr=succeed" ) ) { + opts->ctrl &= ~OPT_FAIL_ON_ERROR; + } + else if ( ! strcmp( *argv, "magic_root" ) ) { + opts->ctrl |= OPT_MAGIC_ROOT; + } + else if ( ! strcmp( *argv, "even_deny_root_account" ) || + ! strcmp( *argv, "even_deny_root" ) ) { + log_phase_no_auth(pamh, phase, *argv); + opts->ctrl |= OPT_DENY_ROOT; + } + else if ( ! strncmp( *argv, "deny=", 5 ) ) { + log_phase_no_auth(pamh, phase, *argv); + if ( sscanf((*argv)+5,"%hu",&opts->deny) != 1 ) { + pam_syslog(pamh, LOG_ERR, "bad number supplied: %s", *argv); + return PAM_AUTH_ERR; + } + } + else if ( ! strncmp( *argv, "lock_time=", 10 ) ) { + log_phase_no_auth(pamh, phase, *argv); + if ( sscanf((*argv)+10,"%ld",&opts->lock_time) != 1 ) { + pam_syslog(pamh, LOG_ERR, "bad number supplied: %s", *argv); + return PAM_AUTH_ERR; + } + } + else if ( ! strncmp( *argv, "unlock_time=", 12 ) ) { + log_phase_no_auth(pamh, phase, *argv); + if ( sscanf((*argv)+12,"%ld",&opts->unlock_time) != 1 ) { + pam_syslog(pamh, LOG_ERR, "bad number supplied: %s", *argv); + return PAM_AUTH_ERR; + } + } + else if ( ! strncmp( *argv, "root_unlock_time=", 17 ) ) { + log_phase_no_auth(pamh, phase, *argv); + if ( sscanf((*argv)+17,"%ld",&opts->root_unlock_time) != 1 ) { + pam_syslog(pamh, LOG_ERR, "bad number supplied: %s", *argv); + return PAM_AUTH_ERR; + } + opts->ctrl |= OPT_DENY_ROOT; /* even_deny_root implied */ + } + else if ( ! strcmp( *argv, "quiet" ) || + ! strcmp ( *argv, "silent")) { + opts->ctrl |= OPT_QUIET; + } + else if ( ! strcmp ( *argv, "no_log_info") ) { + opts->ctrl |= OPT_NOLOGNOTICE; + } + else if ( ! strcmp ( *argv, "audit") ) { + opts->ctrl |= OPT_AUDIT; + } + else { + pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); + } + } + + if (opts->root_unlock_time == -1) + opts->root_unlock_time = opts->unlock_time; + + return PAM_SUCCESS; +} + +#endif /* #ifndef MAIN */ + +/*---------------------------------------------------------------------*/ + +/* --- Support function: get uid (and optionally username) from PAM or + cline_user --- */ + +#ifdef MAIN +static char *cline_user=0; /* cline_user is used in the administration prog */ +#endif + +static int +pam_get_uid(pam_handle_t *pamh, uid_t *uid, const char **userp, struct tally_options *opts) +{ + const char *user = NULL; + struct passwd *pw; + +#ifdef MAIN + user = cline_user; +#else + if ((pam_get_user( pamh, &user, NULL )) != PAM_SUCCESS) { + user = NULL; + } +#endif + + if ( !user || !*user ) { + pam_syslog(pamh, LOG_ERR, "pam_get_uid; user?"); + return PAM_AUTH_ERR; + } + + if ( ! ( pw = pam_modutil_getpwnam( pamh, user ) ) ) { + opts->ctrl & OPT_AUDIT ? + pam_syslog(pamh, LOG_ERR, "pam_get_uid; no such user %s", user) : + pam_syslog(pamh, LOG_ERR, "pam_get_uid; no such user"); + return PAM_USER_UNKNOWN; + } + + if ( uid ) *uid = pw->pw_uid; + if ( userp ) *userp = user; + return PAM_SUCCESS; +} + +/*---------------------------------------------------------------------*/ + +/* --- Support functions: set/get tally data --- */ + +#ifndef MAIN + +static void +_cleanup(pam_handle_t *pamh UNUSED, void *data, int error_status UNUSED) +{ + free(data); +} + + +static void +tally_set_data( pam_handle_t *pamh, time_t oldtime ) +{ + time_t *data; + + if ( (data=malloc(sizeof(time_t))) != NULL ) { + *data = oldtime; + pam_set_data(pamh, MODULE_NAME, (void *)data, _cleanup); + } +} + +static int +tally_get_data( pam_handle_t *pamh, time_t *oldtime ) +{ + int rv; + const void *data; + + rv = pam_get_data(pamh, MODULE_NAME, &data); + if ( rv == PAM_SUCCESS && data != NULL && oldtime != NULL ) { + *oldtime = *(const time_t *)data; + pam_set_data(pamh, MODULE_NAME, NULL, NULL); + } + else { + rv = -1; + *oldtime = 0; + } + return rv; +} +#endif /* #ifndef MAIN */ + +/*---------------------------------------------------------------------*/ + +/* --- Support function: open/create tallyfile and return tally for uid --- */ + +/* If on entry tallyfile doesn't exist, creation is attempted. */ + +static int +get_tally(pam_handle_t *pamh, uid_t uid, const char *filename, + FILE **tfile, struct tallylog *tally) +{ + struct stat fileinfo; + int lstat_ret; + + lstat_ret = lstat(filename, &fileinfo); + if (lstat_ret) { + int save_errno; + int oldmask = umask(077); + *tfile=fopen(filename, "a"); + save_errno = errno; + /* Create file, or append-open in pathological case. */ + umask(oldmask); + if ( !*tfile ) { +#ifndef MAIN + if (save_errno == EPERM) { + return PAM_IGNORE; /* called with insufficient access rights */ + } +#endif + errno = save_errno; + pam_syslog(pamh, LOG_ALERT, "Couldn't create %s: %m", filename); + return PAM_AUTH_ERR; + } + lstat_ret = fstat(fileno(*tfile),&fileinfo); + fclose(*tfile); + *tfile = NULL; + } + + if ( lstat_ret ) { + pam_syslog(pamh, LOG_ALERT, "Couldn't stat %s", filename); + return PAM_AUTH_ERR; + } + + if ((fileinfo.st_mode & S_IWOTH) || !S_ISREG(fileinfo.st_mode)) { + /* If the file is world writable or is not a + normal file, return error */ + pam_syslog(pamh, LOG_ALERT, + "%s is either world writable or not a normal file", + filename); + return PAM_AUTH_ERR; + } + + if (!(*tfile = fopen(filename, "r+"))) { +#ifndef MAIN + if (errno == EPERM) /* called with insufficient access rights */ + return PAM_IGNORE; +#endif + pam_syslog(pamh, LOG_ALERT, "Error opening %s for update: %m", filename); + + return PAM_AUTH_ERR; + } + + if (fseeko(*tfile, (off_t)uid*(off_t)sizeof(*tally), SEEK_SET)) { + pam_syslog(pamh, LOG_ALERT, "fseek failed for %s: %m", filename); + fclose(*tfile); + *tfile = NULL; + return PAM_AUTH_ERR; + } + + if (fileinfo.st_size < (off_t)(uid+1)*(off_t)sizeof(*tally)) { + memset(tally, 0, sizeof(*tally)); + } else if (fread(tally, sizeof(*tally), 1, *tfile) == 0) { + memset(tally, 0, sizeof(*tally)); + /* Shouldn't happen */ + } + + tally->fail_line[sizeof(tally->fail_line)-1] = '\0'; + + return PAM_SUCCESS; +} + +/*---------------------------------------------------------------------*/ + +/* --- Support function: update and close tallyfile with tally!=TALLY_HI --- */ + +static int +set_tally(pam_handle_t *pamh, uid_t uid, + const char *filename, FILE **tfile, struct tallylog *tally) +{ + if (tally->fail_cnt != TALLY_HI) { + if (fseeko(*tfile, (off_t)uid * sizeof(*tally), SEEK_SET)) { + pam_syslog(pamh, LOG_ALERT, "fseek failed for %s: %m", filename); + return PAM_AUTH_ERR; + } + if (fwrite(tally, sizeof(*tally), 1, *tfile) == 0) { + pam_syslog(pamh, LOG_ALERT, "update (fwrite) failed for %s: %m", filename); + return PAM_AUTH_ERR; + } + } + + if (fclose(*tfile)) { + *tfile = NULL; + pam_syslog(pamh, LOG_ALERT, "update (fclose) failed for %s: %m", filename); + return PAM_AUTH_ERR; + } + *tfile=NULL; + return PAM_SUCCESS; +} + +/*---------------------------------------------------------------------*/ + +/* --- PAM bits --- */ + +#ifndef MAIN + +#define RETURN_ERROR(i) return ((opts->ctrl & OPT_FAIL_ON_ERROR)?(i):(PAM_SUCCESS)) + +/*---------------------------------------------------------------------*/ + +static int +tally_check (tally_t oldcnt, time_t oldtime, pam_handle_t *pamh, uid_t uid, + const char *user, struct tally_options *opts, + struct tallylog *tally) +{ + int rv = PAM_SUCCESS; +#ifdef HAVE_LIBAUDIT + char buf[64]; + int audit_fd = -1; +#endif + + if ((opts->ctrl & OPT_MAGIC_ROOT) && getuid() == 0) { + return PAM_SUCCESS; + } + /* magic_root skips tally check */ +#ifdef HAVE_LIBAUDIT + audit_fd = audit_open(); + /* If there is an error & audit support is in the kernel report error */ + if ((audit_fd < 0) && !(errno == EINVAL || errno == EPROTONOSUPPORT || + errno == EAFNOSUPPORT)) + return PAM_SYSTEM_ERR; +#endif + if (opts->deny != 0 && /* deny==0 means no deny */ + tally->fail_cnt > opts->deny && /* tally>deny means exceeded */ + ((opts->ctrl & OPT_DENY_ROOT) || uid)) { /* even_deny stops uid check */ +#ifdef HAVE_LIBAUDIT + if (tally->fail_cnt == opts->deny+1) { + /* First say that max number was hit. */ + snprintf(buf, sizeof(buf), "pam_tally2 uid=%u ", uid); + audit_log_user_message(audit_fd, AUDIT_ANOM_LOGIN_FAILURES, buf, + NULL, NULL, NULL, 1); + } +#endif + if (uid) { + /* Unlock time check */ + if (opts->unlock_time && oldtime) { + if (opts->unlock_time + oldtime <= time(NULL)) { + /* ignore deny check after unlock_time elapsed */ +#ifdef HAVE_LIBAUDIT + snprintf(buf, sizeof(buf), "pam_tally2 uid=%u ", uid); + audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_UNLOCK_TIMED, buf, + NULL, NULL, NULL, 1); +#endif + rv = PAM_SUCCESS; + goto cleanup; + } + } + } else { + /* Root unlock time check */ + if (opts->root_unlock_time && oldtime) { + if (opts->root_unlock_time + oldtime <= time(NULL)) { + /* ignore deny check after unlock_time elapsed */ +#ifdef HAVE_LIBAUDIT + snprintf(buf, sizeof(buf), "pam_tally2 uid=%u ", uid); + audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_UNLOCK_TIMED, buf, + NULL, NULL, NULL, 1); +#endif + rv = PAM_SUCCESS; + goto cleanup; + } + } + } + +#ifdef HAVE_LIBAUDIT + if (tally->fail_cnt == opts->deny+1) { + /* First say that max number was hit. */ + audit_log_user_message(audit_fd, AUDIT_RESP_ACCT_LOCK, buf, + NULL, NULL, NULL, 1); + } +#endif + + if (!(opts->ctrl & OPT_QUIET)) { + pam_info(pamh, _("Account locked due to %hu failed logins"), + tally->fail_cnt); + } + if (!(opts->ctrl & OPT_NOLOGNOTICE)) { + pam_syslog(pamh, LOG_NOTICE, + "user %s (%lu) tally %hu, deny %hu", + user, (unsigned long)uid, tally->fail_cnt, opts->deny); + } + rv = PAM_AUTH_ERR; /* Only unconditional failure */ + goto cleanup; + } + + /* Lock time check */ + if (opts->lock_time && oldtime) { + if (opts->lock_time + oldtime > time(NULL)) { + /* don't increase fail_cnt or update fail_time when + lock_time applies */ + tally->fail_cnt = oldcnt; + tally->fail_time = oldtime; + + if (!(opts->ctrl & OPT_QUIET)) { + pam_info(pamh, _("Account temporary locked (%ld seconds left)"), + oldtime+opts->lock_time-time(NULL)); + } + if (!(opts->ctrl & OPT_NOLOGNOTICE)) { + pam_syslog(pamh, LOG_NOTICE, + "user %s (%lu) has time limit [%lds left]" + " since last failure.", + user, (unsigned long)uid, + oldtime+opts->lock_time-time(NULL)); + } + rv = PAM_AUTH_ERR; + goto cleanup; + } + } + +cleanup: +#ifdef HAVE_LIBAUDIT + if (audit_fd != -1) { + close(audit_fd); + } +#endif + return rv; +} + +/* --- tally bump function: bump tally for uid by (signed) inc --- */ + +static int +tally_bump (int inc, time_t *oldtime, pam_handle_t *pamh, + uid_t uid, const char *user, struct tally_options *opts) +{ + struct tallylog tally; + tally_t oldcnt; + FILE *tfile = NULL; + const void *remote_host = NULL; + int i, rv; + + tally.fail_cnt = 0; /* !TALLY_HI --> Log opened for update */ + + i = get_tally(pamh, uid, opts->filename, &tfile, &tally); + if (i != PAM_SUCCESS) { + if (tfile) + fclose(tfile); + RETURN_ERROR(i); + } + + /* to remember old fail time (for locktime) */ + if (oldtime) { + *oldtime = (time_t)tally.fail_time; + } + + tally.fail_time = time(NULL); + + (void) pam_get_item(pamh, PAM_RHOST, &remote_host); + if (!remote_host) { + (void) pam_get_item(pamh, PAM_TTY, &remote_host); + if (!remote_host) { + remote_host = "unknown"; + } + } + + strncpy(tally.fail_line, remote_host, + sizeof(tally.fail_line)-1); + tally.fail_line[sizeof(tally.fail_line)-1] = 0; + + oldcnt = tally.fail_cnt; + + if (!(opts->ctrl & OPT_MAGIC_ROOT) || getuid()) { + /* magic_root doesn't change tally */ + tally.fail_cnt += inc; + + if (tally.fail_cnt == TALLY_HI) { /* Overflow *and* underflow. :) */ + tally.fail_cnt -= inc; + pam_syslog(pamh, LOG_ALERT, "Tally %sflowed for user %s", + (inc<0)?"under":"over",user); + } + } + + rv = tally_check(oldcnt, *oldtime, pamh, uid, user, opts, &tally); + + i = set_tally(pamh, uid, opts->filename, &tfile, &tally); + if (i != PAM_SUCCESS) { + if (tfile) + fclose(tfile); + if (rv == PAM_SUCCESS) + RETURN_ERROR( i ); + /* fallthrough */ + } + + return rv; +} + +static int +tally_reset (pam_handle_t *pamh, uid_t uid, struct tally_options *opts) +{ + struct tallylog tally; + FILE *tfile = NULL; + int i; + + /* resets only if not magic root */ + + if ((opts->ctrl & OPT_MAGIC_ROOT) && getuid() == 0) { + return PAM_SUCCESS; + } + + tally.fail_cnt = 0; /* !TALLY_HI --> Log opened for update */ + + i=get_tally(pamh, uid, opts->filename, &tfile, &tally); + if (i != PAM_SUCCESS) { + if (tfile) + fclose(tfile); + RETURN_ERROR(i); + } + + memset(&tally, 0, sizeof(tally)); + + i=set_tally(pamh, uid, opts->filename, &tfile, &tally); + if (i != PAM_SUCCESS) { + if (tfile) + fclose(tfile); + RETURN_ERROR(i); + } + + return PAM_SUCCESS; +} + +/*---------------------------------------------------------------------*/ + +/* --- authentication management functions (only) --- */ + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, + int argc, const char **argv) +{ + int + rv; + time_t + oldtime = 0; + struct tally_options + options, *opts = &options; + uid_t + uid; + const char + *user; + + rv = tally_parse_args(pamh, opts, PHASE_AUTH, argc, argv); + if (rv != PAM_SUCCESS) + RETURN_ERROR(rv); + + if (flags & PAM_SILENT) + opts->ctrl |= OPT_QUIET; + + rv = pam_get_uid(pamh, &uid, &user, opts); + if (rv != PAM_SUCCESS) + RETURN_ERROR(rv); + + rv = tally_bump(1, &oldtime, pamh, uid, user, opts); + + tally_set_data(pamh, oldtime); + + return rv; +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, int flags UNUSED, + int argc, const char **argv) +{ + int + rv; + time_t + oldtime = 0; + struct tally_options + options, *opts = &options; + uid_t + uid; + const char + *user; + + rv = tally_parse_args(pamh, opts, PHASE_AUTH, argc, argv); + if ( rv != PAM_SUCCESS ) + RETURN_ERROR( rv ); + + rv = pam_get_uid(pamh, &uid, &user, opts); + if ( rv != PAM_SUCCESS ) + RETURN_ERROR( rv ); + + if ( tally_get_data(pamh, &oldtime) != 0 ) + /* no data found */ + return PAM_SUCCESS; + + return tally_reset(pamh, uid, opts); +} + +/*---------------------------------------------------------------------*/ + +/* --- authentication management functions (only) --- */ + +/* To reset failcount of user on successfull login */ + +PAM_EXTERN int +pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED, + int argc, const char **argv) +{ + int + rv; + time_t + oldtime = 0; + struct tally_options + options, *opts = &options; + uid_t + uid; + const char + *user; + + rv = tally_parse_args(pamh, opts, PHASE_ACCOUNT, argc, argv); + if ( rv != PAM_SUCCESS ) + RETURN_ERROR( rv ); + + rv = pam_get_uid(pamh, &uid, &user, opts); + if ( rv != PAM_SUCCESS ) + RETURN_ERROR( rv ); + + if ( tally_get_data(pamh, &oldtime) != 0 ) + /* no data found */ + return PAM_SUCCESS; + + return tally_reset(pamh, uid, opts); +} + +/*-----------------------------------------------------------------------*/ + +#ifdef PAM_STATIC + +/* static module data */ + +struct pam_module _pam_tally_modstruct = { + MODULE_NAME, +#ifdef PAM_SM_AUTH + pam_sm_authenticate, + pam_sm_setcred, +#else + NULL, + NULL, +#endif +#ifdef PAM_SM_ACCOUNT + pam_sm_acct_mgmt, +#else + NULL, +#endif + NULL, + NULL, + NULL, +}; + +#endif /* #ifdef PAM_STATIC */ + +/*-----------------------------------------------------------------------*/ + +#else /* #ifndef MAIN */ + +static const char *cline_filename = DEFAULT_LOGFILE; +static tally_t cline_reset = TALLY_HI; /* Default is `interrogate only' */ +static int cline_quiet = 0; + +/* + * Not going to link with pamlib just for these.. :) + */ + +static const char * +pam_errors( int i ) +{ + switch (i) { + case PAM_AUTH_ERR: return _("Authentication error"); + case PAM_SERVICE_ERR: return _("Service error"); + case PAM_USER_UNKNOWN: return _("Unknown user"); + default: return _("Unknown error"); + } +} + +static int +getopts( char **argv ) +{ + const char *pname = *argv; + for ( ; *argv ; (void)(*argv && ++argv) ) { + if ( !strcmp (*argv,"--file") ) cline_filename=*++argv; + else if ( !strcmp(*argv,"-f") ) cline_filename=*++argv; + else if ( !strncmp(*argv,"--file=",7) ) cline_filename=*argv+7; + else if ( !strcmp (*argv,"--user") ) cline_user=*++argv; + else if ( !strcmp (*argv,"-u") ) cline_user=*++argv; + else if ( !strncmp(*argv,"--user=",7) ) cline_user=*argv+7; + else if ( !strcmp (*argv,"--reset") ) cline_reset=0; + else if ( !strcmp (*argv,"-r") ) cline_reset=0; + else if ( !strncmp(*argv,"--reset=",8)) { + if ( sscanf(*argv+8,"%hu",&cline_reset) != 1 ) + fprintf(stderr,_("%s: Bad number given to --reset=\n"),pname), exit(0); + } + else if ( !strcmp (*argv,"--quiet") ) cline_quiet=1; + else { + fprintf(stderr,_("%s: Unrecognised option %s\n"),pname,*argv); + return FALSE; + } + } + return TRUE; +} + +static void +print_one(const struct tallylog *tally, uid_t uid) +{ + static int once; + char *cp; + time_t fail_time; + struct tm *tm; + struct passwd *pwent; + const char *username = "[NONAME]"; + char ptime[80]; + + pwent = getpwuid(uid); + fail_time = tally->fail_time; + tm = localtime(&fail_time); + strftime (ptime, sizeof (ptime), "%D %H:%M:%S", tm); + cp = ptime; + if (pwent) { + username = pwent->pw_name; + } + if (!once) { + printf (_("Login Failures Latest failure From\n")); + once++; + } + printf ("%-15.15s %5hu ", username, tally->fail_cnt); + if (tally->fail_time) { + printf ("%-17.17s %s", cp, tally->fail_line); + } + putchar ('\n'); +} + +int +main( int argc UNUSED, char **argv ) +{ + struct tallylog tally; + + if ( ! getopts( argv+1 ) ) { + printf(_("%s: [-f rooted-filename] [--file rooted-filename]\n" + " [-u username] [--user username]\n" + " [-r] [--reset[=n]] [--quiet]\n"), + *argv); + exit(2); + } + + umask(077); + + /* + * Major difference between individual user and all users: + * --user just handles one user, just like PAM. + * without --user it handles all users, sniffing cline_filename for nonzeros + */ + + if ( cline_user ) { + uid_t uid; + FILE *tfile=0; + struct tally_options opts; + int i; + + memset(&opts, 0, sizeof(opts)); + opts.ctrl = OPT_AUDIT; + i=pam_get_uid(NULL, &uid, NULL, &opts); + if ( i != PAM_SUCCESS ) { + fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); + exit(1); + } + + i=get_tally(NULL, uid, cline_filename, &tfile, &tally); + if ( i != PAM_SUCCESS ) { + if (tfile) + fclose(tfile); + fprintf(stderr, "%s: %s\n", *argv, pam_errors(i)); + exit(1); + } + + if ( !cline_quiet ) + print_one(&tally, uid); + + if (cline_reset != TALLY_HI) { +#ifdef HAVE_LIBAUDIT + char buf[64]; + int audit_fd = audit_open(); + snprintf(buf, sizeof(buf), "pam_tally2 uid=%u reset=%hu", uid, cline_reset); + audit_log_user_message(audit_fd, AUDIT_USER_ACCT, + buf, NULL, NULL, NULL, 1); + if (audit_fd >=0) + close(audit_fd); +#endif + if (cline_reset == 0) { + memset(&tally, 0, sizeof(tally)); + } else { + tally.fail_cnt = cline_reset; + } + i=set_tally(NULL, uid, cline_filename, &tfile, &tally); + if (i != PAM_SUCCESS) { + if (tfile) fclose(tfile); + fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); + exit(1); + } + } else { + fclose(tfile); + } + } + else /* !cline_user (ie, operate on all users) */ { + FILE *tfile=fopen(cline_filename, "r"); + uid_t uid=0; + if (!tfile && cline_reset != 0) { + perror(*argv); + exit(1); + } + + for ( ; tfile && !feof(tfile); uid++ ) { + if ( !fread(&tally, sizeof(tally), 1, tfile) + || !tally.fail_cnt ) { + continue; + } + print_one(&tally, uid); + } + if (tfile) + fclose(tfile); + if ( cline_reset!=0 && cline_reset!=TALLY_HI ) { + fprintf(stderr,_("%s: Can't reset all users to non-zero\n"),*argv); + } + else if ( !cline_reset ) { +#ifdef HAVE_LIBAUDIT + char buf[64]; + int audit_fd = audit_open(); + snprintf(buf, sizeof(buf), "pam_tally2 uid=all reset=0"); + audit_log_user_message(audit_fd, AUDIT_USER_ACCT, + buf, NULL, NULL, NULL, 1); + if (audit_fd >=0) + close(audit_fd); +#endif + tfile=fopen(cline_filename, "w"); + if ( !tfile ) perror(*argv), exit(0); + fclose(tfile); + } + } + return 0; +} + + +#endif /* #ifndef MAIN */ diff --git a/modules/pam_tally2/pam_tally2_app.c b/modules/pam_tally2/pam_tally2_app.c new file mode 100644 index 00000000..681ed690 --- /dev/null +++ b/modules/pam_tally2/pam_tally2_app.c @@ -0,0 +1,7 @@ +/* + # This seemed like such a good idea at the time. :) + */ + +#define MAIN +#include "pam_tally2.c" + diff --git a/modules/pam_tally2/tallylog.h b/modules/pam_tally2/tallylog.h new file mode 100644 index 00000000..596b1dac --- /dev/null +++ b/modules/pam_tally2/tallylog.h @@ -0,0 +1,52 @@ +/* + * Copyright 2006, Red Hat, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Red Hat, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT, INC. AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * tallylog.h - login failure data file format + * + * The new login failure file is not compatible with the old faillog(8) format + * Each record in the file represents a separate UID and the file + * is indexed in that fashion. + */ + + +#ifndef _TALLYLOG_H +#define _TALLYLOG_H + +#include + +struct tallylog { + char fail_line[52]; /* rhost or tty of last failure */ + uint16_t reserved; /* reserved for future use */ + uint16_t fail_cnt; /* failures since last success */ + uint64_t fail_time; /* time of last failure */ +}; +/* 64 bytes / entry */ + +#endif diff --git a/modules/pam_tally2/tst-pam_tally2 b/modules/pam_tally2/tst-pam_tally2 new file mode 100755 index 00000000..83c71f41 --- /dev/null +++ b/modules/pam_tally2/tst-pam_tally2 @@ -0,0 +1,2 @@ +#!/bin/sh +../../tests/tst-dlopen .libs/pam_tally2.so -- cgit v1.2.3 From dade683fe1334eccfae157517fa4f8b9a77d36cb Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 19 Nov 2008 14:24:47 +0000 Subject: Relevant BUGIDs: Purpose of commit: missing part of new feature Commit summary: --------------- 2008-11-19 Thorsten Kukuk * modules/pam_pwhistory/pam_pwhistory.c (pam_sm_chauthtok): Finish implementation of type=STRING option. * modules/pam_pwhistory/pam_pwhistory.8.xml: Document "type=STRING" option. --- modules/pam_env/pam_env.c | 150 +++++++++++++++++------------- modules/pam_pwhistory/pam_pwhistory.8.xml | 18 ++++ modules/pam_pwhistory/pam_pwhistory.c | 13 ++- modules/pam_xauth/pam_xauth.c | 25 ++++- 4 files changed, 136 insertions(+), 70 deletions(-) (limited to 'modules') diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c index 80a20cd6..4d81f1c4 100644 --- a/modules/pam_env/pam_env.c +++ b/modules/pam_env/pam_env.c @@ -11,6 +11,9 @@ #define DEFAULT_ETC_ENVFILE "/etc/environment" #define DEFAULT_READ_ENVFILE 1 +#define DEFAULT_USER_ENVFILE ".environment" +#define DEFAULT_USER_READ_ENVFILE 1 + #include "config.h" #include @@ -75,16 +78,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) + char **conffile, char **envfile, int *readenv, + char **user_envfile, int *user_readenv) { int ctrl=0; + *user_envfile = strdup (DEFAULT_USER_ENVFILE); + *envfile = strdup (DEFAULT_ETC_ENVFILE); + *readenv = DEFAULT_READ_ENVFILE; + *user_readenv = DEFAULT_USER_READ_ENVFILE; + *conffile = strdup (DEFAULT_CONF_FILE); /* step through arguments */ for (; argc-- > 0; ++argv) { @@ -94,49 +100,54 @@ _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 { + 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 { - 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 { + free(*envfile); + *envfile = x_strdup(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 { + free(*user_envfile); + *user_envfile = x_strdup(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, 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 +195,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, 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) { @@ -702,7 +707,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.")); @@ -751,24 +756,60 @@ pam_sm_setcred (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; + int user_readenv = 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, &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; } + 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 = getpwnam(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"); + free (conf_file); + free (env_file); + free (user_env_file); + 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 */ + free (conf_file); + free (env_file); + free (user_env_file); D(("Exit.")); return retval; @@ -786,28 +827,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 diff --git a/modules/pam_pwhistory/pam_pwhistory.8.xml b/modules/pam_pwhistory/pam_pwhistory.8.xml index 26d6bd15..f8c152ad 100644 --- a/modules/pam_pwhistory/pam_pwhistory.8.xml +++ b/modules/pam_pwhistory/pam_pwhistory.8.xml @@ -33,6 +33,9 @@ retry=N + + type=STRING + @@ -119,6 +122,21 @@
+ + + + + + + The default action is for the module to use the + following prompts when requesting passwords: + "New UNIX password: " and "Retype UNIX password: ". + The default word UNIX can + be replaced with this option. + + + + diff --git a/modules/pam_pwhistory/pam_pwhistory.c b/modules/pam_pwhistory/pam_pwhistory.c index d3cce728..424be38e 100644 --- a/modules/pam_pwhistory/pam_pwhistory.c +++ b/modules/pam_pwhistory/pam_pwhistory.c @@ -58,7 +58,9 @@ #include "opasswd.h" +/* For Translators: "%s%s" could be replaced with " " or "". */ #define NEW_PASSWORD_PROMPT _("New %s%spassword: ") +/* For Translators: "%s%s" could be replaced with " " or "". */ #define AGAIN_PASSWORD_PROMPT _("Retype new %s%spassword: ") #define MISTYPED_PASSWORD _("Sorry, passwords do not match.") @@ -70,6 +72,7 @@ struct options_t { int enforce_for_root; int remember; int tries; + const char *prompt_type; }; typedef struct options_t options_t; @@ -101,6 +104,8 @@ parse_option (pam_handle_t *pamh, const char *argv, options_t *options) } else if (strcasecmp (argv, "enforce_for_root") == 0) options->enforce_for_root = 1; + else if (strncasecmp (argv, "type=", 5) == 0) + options->prompt_type = &argv[5]; else pam_syslog (pamh, LOG_ERR, "pam_pwhistory: unknown option: %s", argv); } @@ -121,6 +126,7 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) /* Set some default values, which could be overwritten later. */ options.remember = 10; options.tries = 1; + options.prompt_type = "UNIX"; /* Parse parameters for module */ for ( ; argc-- > 0; argv++) @@ -209,7 +215,8 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) while ((newpass == NULL) && (tries++ < options.tries)) { retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &newpass, - NEW_PASSWORD_PROMPT, "UNIX", " "); + NEW_PASSWORD_PROMPT, options.prompt_type, + strlen (options.prompt_type) > 0?" ":""); if (retval != PAM_SUCCESS) { _pam_drop (newpass); @@ -249,7 +256,9 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) char *new2; retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &new2, - AGAIN_PASSWORD_PROMPT, "UNIX", " "); + AGAIN_PASSWORD_PROMPT, + options.prompt_type, + strlen (options.prompt_type) > 0?" ":""); if (retval != PAM_SUCCESS) return retval; diff --git a/modules/pam_xauth/pam_xauth.c b/modules/pam_xauth/pam_xauth.c index 36f30708..518c015a 100644 --- a/modules/pam_xauth/pam_xauth.c +++ b/modules/pam_xauth/pam_xauth.c @@ -280,7 +280,7 @@ check_acl(pam_handle_t *pamh, return noent_code; default: if (debug) { - pam_syslog(pamh, LOG_ERR, + pam_syslog(pamh, LOG_DEBUG, "error opening %s: %m", path); } return PAM_PERM_DENIED; @@ -293,7 +293,8 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { char *cookiefile = NULL, *xauthority = NULL, - *cookie = NULL, *display = NULL, *tmp = NULL; + *cookie = NULL, *display = NULL, *tmp = NULL, + *xauthlocalhostname = NULL; const char *user, *xauth = NULL; struct passwd *tpwd, *rpwd; int fd, i, debug = 0; @@ -588,14 +589,30 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, if (asprintf(&d, "DISPLAY=%s", display) < 0) { - pam_syslog(pamh, LOG_DEBUG, "out of memory"); + pam_syslog(pamh, LOG_ERR, "out of memory"); cookiefile = NULL; retval = PAM_SESSION_ERR; goto cleanup; } if (pam_putenv (pamh, d) != PAM_SUCCESS) - pam_syslog (pamh, LOG_DEBUG, + pam_syslog (pamh, LOG_ERR, + "can't set environment variable '%s'", d); + free (d); + } + + /* set XAUTHLOCALHOSTNAME to make sure that su - work under gnome */ + if ((xauthlocalhostname = getenv("XAUTHLOCALHOSTNAME")) != NULL) { + char *d; + + if (asprintf(&d, "XAUTHLOCALHOSTNAME=%s", xauthlocalhostname) < 0) { + pam_syslog(pamh, LOG_ERR, "out of memory"); + retval = PAM_SESSION_ERR; + goto cleanup; + } + + if (pam_putenv (pamh, d) != PAM_SUCCESS) + pam_syslog (pamh, LOG_ERR, "can't set environment variable '%s'", d); free (d); } -- cgit v1.2.3 From d356c2696c3044d4b81690830558a3ecd0f3427c Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 19 Nov 2008 15:03:53 +0000 Subject: Relevant BUGIDs: Purpose of commit: fix Commit summary: --------------- Revert wrong commitment --- modules/pam_env/pam_env.c | 150 ++++++++++++++++++++-------------------------- 1 file changed, 64 insertions(+), 86 deletions(-) (limited to 'modules') diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c index 4d81f1c4..80a20cd6 100644 --- a/modules/pam_env/pam_env.c +++ b/modules/pam_env/pam_env.c @@ -11,9 +11,6 @@ #define DEFAULT_ETC_ENVFILE "/etc/environment" #define DEFAULT_READ_ENVFILE 1 -#define DEFAULT_USER_ENVFILE ".environment" -#define DEFAULT_USER_READ_ENVFILE 1 - #include "config.h" #include @@ -78,19 +75,16 @@ 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, - char **conffile, char **envfile, int *readenv, - char **user_envfile, int *user_readenv) + const char **conffile, const char **envfile, int *readenv) { int ctrl=0; - *user_envfile = strdup (DEFAULT_USER_ENVFILE); - *envfile = strdup (DEFAULT_ETC_ENVFILE); - *readenv = DEFAULT_READ_ENVFILE; - *user_readenv = DEFAULT_USER_READ_ENVFILE; - *conffile = strdup (DEFAULT_CONF_FILE); /* step through arguments */ for (; argc-- > 0; ++argv) { @@ -100,54 +94,49 @@ _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)) { - 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)); - } + *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"); + } } else if (!strncmp(*argv,"envfile=",8)) { - 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_envfile=",13)) { - if (*argv+13 == '\0') { - pam_syslog (pamh, LOG_ERR, - "user_envfile= specification missing argument - ignored"); - } else { - free(*user_envfile); - *user_envfile = x_strdup(13+*argv); - D(("new User Env File: %s", *user_env_file)); - } + *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"); + } } else if (!strncmp(*argv,"readenv=",8)) - *readenv = atoi(8+*argv); - else if (!strncmp(*argv,"user_readenv=",13)) - *user_readenv = atoi(13+*argv); + *readenv = atoi(8+*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, char *file) +_parse_config_file(pam_handle_t *pamh, int ctrl, const char *conffile) { 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.")); - var->name=NULL; var->defval=NULL; var->override=NULL; + if (ctrl & PAM_NEW_CONF_FILE) { + file = conffile; + } else { + file = DEFAULT_CONF_FILE; + } D(("Config file name is: %s", file)); @@ -195,12 +184,18 @@ _parse_config_file(pam_handle_t *pamh, char *file) } static int -_parse_env_file(pam_handle_t *pamh, char *file) +_parse_env_file(pam_handle_t *pamh, int ctrl, const char *env_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) { @@ -707,7 +702,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.")); @@ -756,60 +751,24 @@ pam_sm_setcred (pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { int retval, ctrl, readenv=DEFAULT_READ_ENVFILE; - int user_readenv = DEFAULT_USER_READ_ENVFILE; - char *conf_file = NULL, *env_file = NULL, *user_env_file = NULL; - + 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, &user_env_file, &user_readenv); + ctrl = _pam_parse(pamh, argc, argv, &conf_file, &env_file, &readenv); - retval = _parse_config_file(pamh, conf_file); + retval = _parse_config_file(pamh, ctrl, conf_file); if(readenv && retval == PAM_SUCCESS) { - retval = _parse_env_file(pamh, env_file); + retval = _parse_env_file(pamh, ctrl, env_file); if (retval == PAM_IGNORE) retval = PAM_SUCCESS; } - 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 = getpwnam(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"); - free (conf_file); - free (env_file); - free (user_env_file); - 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 */ - free (conf_file); - free (env_file); - free (user_env_file); D(("Exit.")); return retval; @@ -827,9 +786,28 @@ PAM_EXTERN int pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { - /* 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); + 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; } PAM_EXTERN int -- cgit v1.2.3 From bc32e648b76cb6eef5a3dd4720a7384d918ca6fb Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 20 Nov 2008 14:10:17 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-11-20 Tomas Mraz * modules/pam_sepermit/pam_sepermit.c (sepermit_match): Do not call sepermit_lock() if sense is deny. Do not crash on NULL seuser match. (pam_sm_authenticate): Try to call getseuserbyname() even if SELinux is disabled. --- modules/pam_sepermit/pam_sepermit.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'modules') diff --git a/modules/pam_sepermit/pam_sepermit.c b/modules/pam_sepermit/pam_sepermit.c index 15cdc3e1..0fd95619 100644 --- a/modules/pam_sepermit/pam_sepermit.c +++ b/modules/pam_sepermit/pam_sepermit.c @@ -231,7 +231,7 @@ sepermit_lock(pam_handle_t *pamh, const char *user, int debug) /* return 0 when matched, -1 when unmatched, pam error otherwise */ static int sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user, - const char *seuser, int debug) + const char *seuser, int debug, int sense) { FILE *f; char *line = NULL; @@ -278,6 +278,8 @@ sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user, } break; case '%': + if (seuser == NULL) + break; ++start; if (debug) pam_syslog(pamh, LOG_NOTICE, "Matching seuser %s against seuser %s", seuser, start); @@ -304,8 +306,12 @@ sepermit_match(pam_handle_t *pamh, const char *cfgfile, const char *user, free(line); fclose(f); - if (matched) - return (geteuid() == 0 && exclusive) ? sepermit_lock(pamh, user, debug) : 0; + if (matched) { + if (sense == PAM_SUCCESS && geteuid() == 0 && exclusive) + return sepermit_lock(pamh, user, debug); + else + return 0; + } else return -1; } @@ -348,18 +354,18 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, pam_syslog(pamh, LOG_NOTICE, "Enforcing mode, access will be allowed on match"); sense = PAM_SUCCESS; } + } - if (getseuserbyname(user, &seuser, &level) != 0) { - seuser = NULL; - level = NULL; - pam_syslog(pamh, LOG_ERR, "getseuserbyname failed: %m"); - } + if (getseuserbyname(user, &seuser, &level) != 0) { + seuser = NULL; + level = NULL; + pam_syslog(pamh, LOG_ERR, "getseuserbyname failed: %m"); } if (debug && sense != PAM_SUCCESS) pam_syslog(pamh, LOG_NOTICE, "Access will not be allowed on match"); - rv = sepermit_match(pamh, cfgfile, user, seuser, debug); + rv = sepermit_match(pamh, cfgfile, user, seuser, debug, sense); if (debug) pam_syslog(pamh, LOG_NOTICE, "sepermit_match returned: %d", rv); -- cgit v1.2.3 From b66f2f941f5dd41710b0e3f3251d5d664602911f Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 24 Nov 2008 14:06:15 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-11-24 Tomas Mraz * modules/pam_cracklib/pam_cracklib.c(pam_sm_chauthtok): Fix leaks in error path. * modules/pam_env/pam_env.c(_parse_env_file): Remove superfluous condition. * modules/pam_group/pam_group.c(check_account): Fix leak in error path. * modules/pam_listfile/pam_listfile.c(pam_sm_authenticate): Fix leak in error path. * modules/pam_securetty/pam_securetty.c(securetty_perform_check): Remove superfluous condition. * modules/pam_stress/pam_stress.c(stress_get_password,pam_sm_authenticate): Remove superfluous conditions. (pam_sm_chauthtok): Fix mistaken && for &. * modules/pam_unix/pam_unix_auth.c(pam_sm_authenticate): Remove superfluous condition. All the problems fixed in this commit were found by Steve Grubb. --- modules/pam_cracklib/pam_cracklib.c | 2 ++ modules/pam_env/pam_env.c | 2 +- modules/pam_group/pam_group.c | 2 +- modules/pam_listfile/pam_listfile.c | 1 + modules/pam_securetty/pam_securetty.c | 2 +- modules/pam_stress/pam_stress.c | 7 +++---- modules/pam_unix/pam_unix_auth.c | 2 +- 7 files changed, 10 insertions(+), 8 deletions(-) (limited to 'modules') diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c index 2c4cd4a0..b94f8596 100644 --- a/modules/pam_cracklib/pam_cracklib.c +++ b/modules/pam_cracklib/pam_cracklib.c @@ -692,6 +692,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } if (retval != PAM_SUCCESS) { + token1 = _pam_delete(token1); if (ctrl & PAM_DEBUG_ARG) pam_syslog(pamh,LOG_DEBUG,"unable to obtain a password"); continue; @@ -756,6 +757,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, if (retval != PAM_SUCCESS) { if (ctrl & PAM_DEBUG_ARG) pam_syslog(pamh,LOG_DEBUG,"unable to obtain retyped password"); + token1 = _pam_delete(token1); continue; } diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c index 80a20cd6..a8cd2c8f 100644 --- a/modules/pam_env/pam_env.c +++ b/modules/pam_env/pam_env.c @@ -211,7 +211,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 diff --git a/modules/pam_group/pam_group.c b/modules/pam_group/pam_group.c index 4a54da14..bddcf1cb 100644 --- a/modules/pam_group/pam_group.c +++ b/modules/pam_group/pam_group.c @@ -603,7 +603,7 @@ static int check_account(pam_handle_t *pamh, const char *service, if (getgroups(no_grps, grps) < 0) { D(("getgroups call failed")); no_grps = 0; - grps = NULL; + _pam_drop(grps); } #ifdef DEBUG { diff --git a/modules/pam_listfile/pam_listfile.c b/modules/pam_listfile/pam_listfile.c index f276e5b8..dbd92058 100644 --- a/modules/pam_listfile/pam_listfile.c +++ b/modules/pam_listfile/pam_listfile.c @@ -239,6 +239,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, retval = pam_get_item(pamh,citem,&void_citemp); citemp = void_citemp; if(retval != PAM_SUCCESS) { + free(ifname); return onerr; } if((citem == PAM_USER) && !citemp) { diff --git a/modules/pam_securetty/pam_securetty.c b/modules/pam_securetty/pam_securetty.c index 9dbe9bc4..ec796d9e 100644 --- a/modules/pam_securetty/pam_securetty.c +++ b/modules/pam_securetty/pam_securetty.c @@ -152,7 +152,7 @@ securetty_perform_check (pam_handle_t *pamh, int ctrl, retval = PAM_AUTH_ERR; } else { - if ((retval == PAM_SUCCESS) && (ctrl & PAM_DEBUG_ARG)) { + if (ctrl & PAM_DEBUG_ARG) { pam_syslog(pamh, LOG_DEBUG, "access allowed for '%s' on '%s'", username, uttyname); } diff --git a/modules/pam_stress/pam_stress.c b/modules/pam_stress/pam_stress.c index c254868f..01587fea 100644 --- a/modules/pam_stress/pam_stress.c +++ b/modules/pam_stress/pam_stress.c @@ -197,8 +197,7 @@ static int stress_get_password(pam_handle_t *pamh, int flags } return PAM_CONV_ERR; } - if (resp) - free(resp); + free(resp); } *password = pass; /* this *MUST* be free()'d by this module */ @@ -238,7 +237,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, retval = PAM_USER_UNKNOWN; /* username was null */ return retval; } - else if ((ctrl & PAM_ST_DEBUG) && (retval == PAM_SUCCESS)) { + else if (ctrl & PAM_ST_DEBUG) { pam_syslog(pamh, LOG_DEBUG, "pam_sm_authenticate: username = %s", username); } @@ -426,7 +425,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, if (ctrl & PAM_ST_FAIL_1) return PAM_AUTHTOK_LOCK_BUSY; - if ( !(ctrl && PAM_ST_EXPIRED) + if ( !(ctrl & PAM_ST_EXPIRED) && (flags & PAM_CHANGE_EXPIRED_AUTHTOK) && (pam_get_data(pamh,"stress_new_pwd", &text) != PAM_SUCCESS || strcmp(text,"yes"))) { diff --git a/modules/pam_unix/pam_unix_auth.c b/modules/pam_unix/pam_unix_auth.c index dfedd608..05b5ec6c 100644 --- a/modules/pam_unix/pam_unix_auth.c +++ b/modules/pam_unix/pam_unix_auth.c @@ -132,7 +132,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags retval = PAM_USER_UNKNOWN; AUTH_RETURN; } - if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) + if (on(UNIX_DEBUG, ctrl)) D(("username [%s] obtained", name)); } else { D(("trouble reading username")); -- cgit v1.2.3 From c7d0b27a8b9647e8c4f981541dab352761bb91d5 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Tue, 25 Nov 2008 14:04:55 +0000 Subject: Relevant BUGIDs: debian #326407 Purpose of commit: bugfix Commit summary: --------------- 2008-11-25 Thorsten Kukuk * modules/pam_time/pam_time.c (is_same): Fix check of correct string length (debian bug #326407). --- modules/pam_time/pam_time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/pam_time/pam_time.c b/modules/pam_time/pam_time.c index 8e3b2486..7e418808 100644 --- a/modules/pam_time/pam_time.c +++ b/modules/pam_time/pam_time.c @@ -358,8 +358,8 @@ is_same(pam_handle_t *pamh UNUSED, const void *A, const char *b, /* Ok, we know that b is a substring from A and does not contain wildcards, but now the length of both strings must be the same, - too. */ - if (strlen (a) != strlen(b)) + too. In this case it means, a[i] has to be the end of the string. */ + if (a[i] != '\0') return FALSE; return ( !len ); -- cgit v1.2.3 From cf4f02cdbdd015b8360cc3fdf905afc2602b4d37 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Tue, 25 Nov 2008 14:29:41 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-11-25 Thorsten Kukuk * modules/pam_pwhistory/opasswd.c (save_old_password): Fix typo. --- modules/pam_pwhistory/opasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c index 89452d3f..fd4cd251 100644 --- a/modules/pam_pwhistory/opasswd.c +++ b/modules/pam_pwhistory/opasswd.c @@ -381,7 +381,7 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid, } else { - if (asprintf (&out, "%s:%si%d:%s,%s\n", + if (asprintf (&out, "%s:%s:%d:%s,%s\n", entry.user, entry.uid, entry.count, entry.old_passwords, oldpass) < 0) { -- cgit v1.2.3 From 51a9be048c75f86e2d2493a47b1f6fd25f5e549d Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 28 Nov 2008 12:48:43 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-11-28 Tomas Mraz * modules/pam_unix/unix_update.c (set_password): Allow root to change passwords without verification of the old ones. --- modules/pam_unix/unix_update.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'modules') diff --git a/modules/pam_unix/unix_update.c b/modules/pam_unix/unix_update.c index f54a59ce..702912d0 100644 --- a/modules/pam_unix/unix_update.c +++ b/modules/pam_unix/unix_update.c @@ -71,11 +71,14 @@ set_password(const char *forwho, const char *shadow, const char *remember) goto done; } - /* does pass agree with the official one? - we always allow change from null pass */ - retval = helper_verify_password(forwho, pass, 1); - if (retval != PAM_SUCCESS) { - goto done; + /* If real caller uid is not root we must verify that + received old pass agrees with the current one. + We always allow change from null pass. */ + if (getuid()) { + retval = helper_verify_password(forwho, pass, 1); + if (retval != PAM_SUCCESS) { + goto done; + } } /* first, save old password */ -- cgit v1.2.3 From 4a67d64dd0cb01c40e675f48f0c6ea3d08e53664 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 28 Nov 2008 14:29:12 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-11-28 Tomas Mraz * modules/pam_tally2/pam_tally2.c (tally_check): Fix info format to be the same as in pam_tally. * configure.in: Add modules/pam_timestamp/Makefile. * doc/sag/Linux-PAM_SAG.xml: Include pam_timestamp.xml. * doc/sag/pam_timestamp.xml: New. * libpam/pam_static_modules.h: Add pam_timestamp static struct. * modules/Makefile.am: Add pam_timestamp directory. * modules/pam_timestamp/Makefile.am: New. * modules/pam_timestamp/README.xml: New. * modules/pam_timestamp/hmacsha1.h: New. * modules/pam_timestamp/sha1.h: New. * modules/pam_timestamp/pam_timestamp.8.xml: New. * modules/pam_timestamp/pam_timestamp_check.8.xml: New. * modules/pam_timestamp/pam_timestamp.c: New. * modules/pam_timestamp/pam_timestamp_check.c: New. * modules/pam_timestamp/hmacfile.c: New. * modules/pam_timestamp/hmacsha1.c: New. * modules/pam_timestamp/sha1.c: New. * modules/pam_timestamp/tst-pam_timestamp: New. * po/POTFILES.in: Add pam_timestamp sources. * po/*.po: Regenerate. * po/cs.po: Updated translations. --- modules/Makefile.am | 3 +- modules/pam_tally2/pam_tally2.c | 4 +- modules/pam_timestamp/Makefile.am | 47 ++ modules/pam_timestamp/README.xml | 46 ++ modules/pam_timestamp/hmacfile.c | 157 +++++ modules/pam_timestamp/hmacsha1.c | 293 +++++++++ modules/pam_timestamp/hmacsha1.h | 15 + modules/pam_timestamp/pam_timestamp.8.xml | 189 ++++++ modules/pam_timestamp/pam_timestamp.c | 816 ++++++++++++++++++++++++ modules/pam_timestamp/pam_timestamp_check.8.xml | 208 ++++++ modules/pam_timestamp/pam_timestamp_check.c | 42 ++ modules/pam_timestamp/sha1.c | 254 ++++++++ modules/pam_timestamp/sha1.h | 60 ++ modules/pam_timestamp/tst-pam_timestamp | 2 + 14 files changed, 2133 insertions(+), 3 deletions(-) create mode 100644 modules/pam_timestamp/Makefile.am create mode 100644 modules/pam_timestamp/README.xml create mode 100644 modules/pam_timestamp/hmacfile.c create mode 100644 modules/pam_timestamp/hmacsha1.c create mode 100644 modules/pam_timestamp/hmacsha1.h create mode 100644 modules/pam_timestamp/pam_timestamp.8.xml create mode 100644 modules/pam_timestamp/pam_timestamp.c create mode 100644 modules/pam_timestamp/pam_timestamp_check.8.xml create mode 100644 modules/pam_timestamp/pam_timestamp_check.c create mode 100644 modules/pam_timestamp/sha1.c create mode 100644 modules/pam_timestamp/sha1.h create mode 100755 modules/pam_timestamp/tst-pam_timestamp (limited to 'modules') diff --git a/modules/Makefile.am b/modules/Makefile.am index 37d5a739..0c80cea9 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -9,7 +9,8 @@ SUBDIRS = pam_access pam_cracklib pam_debug pam_deny pam_echo \ pam_mkhomedir pam_motd pam_namespace pam_nologin \ pam_permit pam_pwhistory pam_rhosts pam_rootok pam_securetty \ pam_selinux pam_sepermit pam_shells pam_stress \ - pam_succeed_if pam_tally pam_tally2 pam_time pam_tty_audit pam_umask \ + pam_succeed_if pam_tally pam_tally2 pam_time pam_timestamp \ + pam_tty_audit pam_umask \ pam_unix pam_userdb pam_warn pam_wheel pam_xauth CLEANFILES = *~ diff --git a/modules/pam_tally2/pam_tally2.c b/modules/pam_tally2/pam_tally2.c index 9ae3180d..5924edf9 100644 --- a/modules/pam_tally2/pam_tally2.c +++ b/modules/pam_tally2/pam_tally2.c @@ -517,8 +517,8 @@ tally_check (tally_t oldcnt, time_t oldtime, pam_handle_t *pamh, uid_t uid, #endif if (!(opts->ctrl & OPT_QUIET)) { - pam_info(pamh, _("Account locked due to %hu failed logins"), - tally->fail_cnt); + pam_info(pamh, _("Account locked due to %u failed logins"), + (unsigned int)tally->fail_cnt); } if (!(opts->ctrl & OPT_NOLOGNOTICE)) { pam_syslog(pamh, LOG_NOTICE, diff --git a/modules/pam_timestamp/Makefile.am b/modules/pam_timestamp/Makefile.am new file mode 100644 index 00000000..51a3c215 --- /dev/null +++ b/modules/pam_timestamp/Makefile.am @@ -0,0 +1,47 @@ +# +# Copyright (c) 2005 Thorsten Kukuk +# Copyright (c) 2005 Red Hat, Inc. +# + +CLEANFILES = *~ + +XMLS = README.xml pam_timestamp.8.xml pam_timestamp_check.8.xml +man_MANS = pam_timestamp.8 pam_timestamp_check.8 +TESTS = tst-pam_timestamp + +EXTRA_DIST = $(man_MANS) hmactest.c $(XMLS) $(TESTS) + +securelibdir = $(SECUREDIR) +secureconfdir = $(SCONFIGDIR) + +noinst_HEADERS = hmacsha1.h sha1.h + +AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include + +pam_timestamp_la_LDFLAGS = -no-undefined -avoid-version -module $(AM_LDFLAGS) +pam_timestamp_la_LIBADD = -L$(top_builddir)/libpam -lpam +if HAVE_VERSIONING + pam_timestamp_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map +endif + +securelib_LTLIBRARIES = pam_timestamp.la +sbin_PROGRAMS = pam_timestamp_check + +pam_timestamp_la_SOURCES = pam_timestamp.c hmacsha1.c sha1.c +pam_timestamp_la_CFLAGS = $(AM_CFLAGS) + +pam_timestamp_check_SOURCES = pam_timestamp_check.c +pam_timestamp_check_CFLAGS = $(AM_CFLAGS) @PIE_CFLAGS@ +pam_timestamp_check_LDADD = -L$(top_builddir)/libpam -lpam +pam_timestamp_check_LDFLAGS = @PIE_LDFLAGS@ + +hmacfile_SOURCES = hmacfile.c hmacsha1.c sha1.c +hmacfile_LDADD = -L$(top_builddir)/libpam -lpam + +if ENABLE_REGENERATE_MAN +noinst_DATA = README +README: pam_timestamp.8.xml +-include $(top_srcdir)/Make.xml.rules +endif + +noinst_PROGRAMS = hmacfile diff --git a/modules/pam_timestamp/README.xml b/modules/pam_timestamp/README.xml new file mode 100644 index 00000000..5b72deb1 --- /dev/null +++ b/modules/pam_timestamp/README.xml @@ -0,0 +1,46 @@ + + +--> +]> + +
+ + + + + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" + href="pam_timestamp.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_timestamp-name"]/*)'/> + + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
diff --git a/modules/pam_timestamp/hmacfile.c b/modules/pam_timestamp/hmacfile.c new file mode 100644 index 00000000..963f6f54 --- /dev/null +++ b/modules/pam_timestamp/hmacfile.c @@ -0,0 +1,157 @@ +/* + * Copyright 2003,2004 Red Hat, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "hmacsha1.h" + +static void +testvectors(void) +{ + void *hmac; + size_t hmac_len; + size_t i, j; + char hex[3]; + struct vector { + const char *key; + int key_len; + const char *data; + int data_len; + const char *hmac; + } vectors[] = { + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20, + "Hi There", 8, + "b617318655057264e28bc0b6fb378c8ef146be00", + }, + + { + "Jefe", 4, + "what do ya want for nothing?", 28, + "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", + }, + + { + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 20, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", 50, + "125d7342b9ac11cd91a39af48aa17b4f63f175d3", + }, + + { + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + 50, + "4c9007f4026250c6bc8414f9bf50c86c2d7235da", + }, + + { + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 20, + "Test With Truncation", 20, + "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04", + }, + + { + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + 80, + "Test Using Larger Than Block-Size Key - Hash Key First", 54, + "aa4ae5e15272d00e95705637ce8a3b55ed402112", + }, + + { + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + 80, + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73, + "e8e99d0f45237d786d6bbaa7965c7808bbff1a91", + }, + }; + for (i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { + hmac = NULL; + hmac_len = 0; + hmac_sha1_generate(&hmac, &hmac_len, + vectors[i].key, vectors[i].key_len, + vectors[i].data, vectors[i].data_len); + if (hmac != NULL) { + unsigned char *hmacc = hmac; + for (j = 0; j < hmac_len; j++) { + snprintf(hex, sizeof(hex), "%02x", + hmacc[j] & 0xff); + if (strncasecmp(hex, + vectors[i].hmac + 2 * j, + 2) != 0) { + printf("Incorrect result for vector %lu\n", i + 1); + exit(1); + + } + } + free(hmac); + } else { + printf("Error in vector %lu.\n", i + 1); + exit(1); + } + } +} + +int +main(int argc, char **argv) +{ + void *hmac; + size_t maclen; + const char *keyfile; + int i; + size_t j; + + testvectors(); + + keyfile = argv[1]; + for (i = 2; i < argc; i++) { + hmac_sha1_generate_file(NULL, &hmac, &maclen, keyfile, -1, -1, + argv[i], strlen(argv[i])); + if (hmac != NULL) { + unsigned char *hmacc = hmac; + for (j = 0; j < maclen; j++) { + printf("%02x", hmacc[j] & 0xff); + } + printf(" %s\n", argv[i]); + free(hmac); + } + } + return 0; +} diff --git a/modules/pam_timestamp/hmacsha1.c b/modules/pam_timestamp/hmacsha1.c new file mode 100644 index 00000000..5b3774ff --- /dev/null +++ b/modules/pam_timestamp/hmacsha1.c @@ -0,0 +1,293 @@ +/* An implementation of HMAC using SHA-1. + * + * Copyright (c) 2003 Red Hat, Inc. + * Written by Nalin Dahyabhai + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* See RFC 2104 for descriptions. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hmacsha1.h" +#include "sha1.h" + +#define MINIMUM_KEY_SIZE SHA1_OUTPUT_SIZE +#define MAXIMUM_KEY_SIZE SHA1_BLOCK_SIZE + +static void +hmac_key_create(pam_handle_t *pamh, const char *filename, size_t key_size, + uid_t owner, gid_t group) +{ + int randfd, keyfd, i; + size_t count; + char *key; + + /* Open the destination file. */ + keyfd = open(filename, + O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, + S_IRUSR | S_IWUSR); + if (keyfd == -1) { + pam_syslog(pamh, LOG_ERR, "Cannot create %s: %m", filename); + return; + } + + + if (fchown(keyfd, owner, group) == -1) { + pam_syslog(pamh, LOG_ERR, "Cannot chown %s: %m", filename); + return; + } + + /* Open the random device to get key data. */ + randfd = open("/dev/urandom", O_RDONLY); + if (randfd == -1) { + pam_syslog(pamh, LOG_ERR, "Cannot open /dev/urandom: %m"); + close(keyfd); + return; + } + + /* Read random data for use as the key. */ + key = malloc(key_size); + count = 0; + if (!key) { + close(keyfd); + close(randfd); + return; + } + while (count < key_size) { + i = read(randfd, key + count, key_size - count); + if ((i == 0) || (i == -1)) { + break; + } + count += i; + } + + close(randfd); + + /* If we didn't get enough, stop here. */ + if (count < key_size) { + pam_syslog(pamh, LOG_ERR, "Short read on random device"); + memset(key, 0, key_size); + free(key); + close(keyfd); + return; + } + + /* Now write the key. */ + count = 0; + while (count < key_size) { + i = write(keyfd, key + count, key_size - count); + if ((i == 0) || (i == -1)) { + break; + } + count += i; + } + memset(key, 0, key_size); + free(key); + close(keyfd); +} + +static void +hmac_key_read(pam_handle_t *pamh, const char *filename, size_t default_key_size, + uid_t owner, gid_t group, + void **key, size_t *key_size) +{ + char *tmp; + int keyfd, i, count; + struct stat st; + + tmp = NULL; + *key = NULL; + *key_size = 0; + + /* Try to open the key file. */ + keyfd = open(filename, O_RDONLY); + if (keyfd == -1) { + /* No such thing? Create it. */ + if (errno == ENOENT) { + hmac_key_create(pamh, filename, default_key_size, + owner, group); + keyfd = open(filename, O_RDONLY); + } else { + pam_syslog(pamh, LOG_ERR, "Cannot open %s: %m", filename); + } + if (keyfd == -1) + return; + } + + /* If we failed to open the file, we're done. */ + if (fstat(keyfd, &st) == -1) { + close(keyfd); + return; + } + + /* Read the contents of the file. */ + tmp = malloc(st.st_size); + if (!tmp) { + close(keyfd); + return; + } + + count = 0; + while (count < st.st_size) { + i = read(keyfd, tmp + count, st.st_size - count); + if ((i == 0) || (i == -1)) { + break; + } + count += i; + } + close(keyfd); + + /* Require that we got the expected amount of data. */ + if (count < st.st_size) { + memset(tmp, 0, st.st_size); + free(tmp); + return; + } + + /* Pass the key back. */ + *key = tmp; + *key_size = st.st_size; +} + +static void +xor_block(unsigned char *p, unsigned char byte, size_t length) +{ + size_t i; + for (i = 0; i < length; i++) { + p[i] = p[i] ^ byte; + } +} + +void +hmac_sha1_generate(void **mac, size_t *mac_length, + const void *raw_key, size_t raw_key_size, + const void *text, size_t text_length) +{ + unsigned char key[MAXIMUM_KEY_SIZE], tmp_key[MAXIMUM_KEY_SIZE]; + size_t maximum_key_size = SHA1_BLOCK_SIZE, + minimum_key_size = SHA1_OUTPUT_SIZE; + const unsigned char ipad = 0x36, opad = 0x5c; + struct sha1_context sha1; + unsigned char inner[SHA1_OUTPUT_SIZE], outer[SHA1_OUTPUT_SIZE]; + + *mac = NULL; + *mac_length = 0; + +#ifndef HMAC_ALLOW_SHORT_KEYS + /* If the key is too short, don't bother. */ + if (raw_key_size < minimum_key_size) { + return; + } +#endif + + /* If the key is too long, "compress" it, else copy it and pad it + * out with zero bytes. */ + memset(key, 0, sizeof(key)); + if (raw_key_size > maximum_key_size) { + sha1_init(&sha1); + sha1_update(&sha1, raw_key, raw_key_size); + sha1_output(&sha1, key); + } else { + memmove(key, raw_key, raw_key_size); + } + + /* Generate the inner sum. */ + memcpy(tmp_key, key, sizeof(tmp_key)); + xor_block(tmp_key, ipad, sizeof(tmp_key)); + + sha1_init(&sha1); + sha1_update(&sha1, tmp_key, sizeof(tmp_key)); + sha1_update(&sha1, text, text_length); + sha1_output(&sha1, inner); + + /* Generate the outer sum. */ + memcpy(tmp_key, key, sizeof(tmp_key)); + xor_block(tmp_key, opad, sizeof(tmp_key)); + + sha1_init(&sha1); + sha1_update(&sha1, tmp_key, sizeof(tmp_key)); + sha1_update(&sha1, inner, sizeof(inner)); + sha1_output(&sha1, outer); + + /* We don't need any of the keys any more. */ + memset(key, 0, sizeof(key)); + memset(tmp_key, 0, sizeof(tmp_key)); + + /* Allocate space to store the output. */ + *mac_length = sizeof(outer); + *mac = malloc(*mac_length); + if (*mac == NULL) { + *mac_length = 0; + return; + } + + memcpy(*mac, outer, *mac_length); +} + +void +hmac_sha1_generate_file(pam_handle_t *pamh, void **mac, size_t *mac_length, + const char *keyfile, uid_t owner, gid_t group, + const void *text, size_t text_length) +{ + void *key; + size_t key_length; + + hmac_key_read(pamh, keyfile, + MAXIMUM_KEY_SIZE, owner, group, + &key, &key_length); + if (key == NULL) { + *mac = NULL; + *mac_length = 0; + return; + } + hmac_sha1_generate(mac, mac_length, + key, key_length, + text, text_length); + memset(key, 0, key_length); + free(key); +} + +size_t +hmac_sha1_size(void) +{ + return SHA1_OUTPUT_SIZE; +} diff --git a/modules/pam_timestamp/hmacsha1.h b/modules/pam_timestamp/hmacsha1.h new file mode 100644 index 00000000..200d1d06 --- /dev/null +++ b/modules/pam_timestamp/hmacsha1.h @@ -0,0 +1,15 @@ +#ifndef pam_timestamp_hmacfile_h +#define pam_timestamp_hmacfile_h + +#include +#include + +size_t hmac_sha1_size(void); +void hmac_sha1_generate(void **mac, size_t *mac_length, + const void *key, size_t key_length, + const void *text, size_t text_length); +void hmac_sha1_generate_file(pam_handle_t *pamh, void **mac, size_t *mac_length, + const char *keyfile, uid_t owner, gid_t group, + const void *text, size_t text_length); + +#endif diff --git a/modules/pam_timestamp/pam_timestamp.8.xml b/modules/pam_timestamp/pam_timestamp.8.xml new file mode 100644 index 00000000..c96424ab --- /dev/null +++ b/modules/pam_timestamp/pam_timestamp.8.xml @@ -0,0 +1,189 @@ + + + + + + + pam_timestamp + 8 + Linux-PAM Manual + + + + pam_timestamp + Authenticate using cached successful authentication attempts + + + + + pam_timestamp.so + + timestamp_timeout=number + + + verbose + + + debug + + + + + + + DESCRIPTION + + + In a nutshell, pam_timestamp caches successful +authentication attempts, and allows you to use a recent successful attempt as +the basis for authentication. This is similar mechanism which is used in +sudo. + + + When an application opens a session using pam_timestamp, +a timestamp file is created in the timestampdir directory +for the user. When an application attempts to authenticate the user, a +pam_timestamp will treat a sufficiently recent timestamp +file as grounds for succeeding. + + + + + + OPTIONS + + + + + + + + How long should pam_timestamp treat timestamp as valid after their + last modification date (in seconds). Default is 300 seconds. + + + + + + + + + + Attempt to inform the user when access is granted. + + + + + + + + + + Turns on debugging messages sent to + syslog3 + . + + + + + + + + MODULE TYPES PROVIDED + + The and + module types are provided. + + + + + RETURN VALUES + + + PAM_AUTH_ERR + + + The module was not able to retrive the user name or + no valid timestamp file was found. + + + + + PAM_SUCCESS + + + Everything was successfull. + + + + + PAM_SESSION_ERR + + + Timestamp file could not be created or updated. + + + + + + + + NOTES + + Users can get confused when they are not always asked for passwords when +running a given program. Some users reflexively begin typing information before +noticing that it is not being asked for. + + + + + EXAMPLES + +auth sufficient pam_timestamp.so verbose +auth required pam_unix.so + +session required pam_unix.so +session optional pam_timestamp.so + + + + + FILES + + + /var/run/sudo/... + + timestamp files and directories + + + + + + + SEE ALSO + + + pam_timestamp_check8 + , + + pam.conf5 + , + + pam.d5 + , + + pam8 + + + + + + AUTHOR + + pam_tally was written by Nalin Dahyabhai. + + + + + diff --git a/modules/pam_timestamp/pam_timestamp.c b/modules/pam_timestamp/pam_timestamp.c new file mode 100644 index 00000000..8a01c6f3 --- /dev/null +++ b/modules/pam_timestamp/pam_timestamp.c @@ -0,0 +1,816 @@ +/****************************************************************************** + * A module for Linux-PAM that will cache authentication results, inspired by + * (and implemented with an eye toward being mixable with) sudo. + * + * Copyright (c) 2002 Red Hat, Inc. + * Written by Nalin Dahyabhai + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define PAM_SM_AUTH +#define PAM_SM_SESSION + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hmacsha1.h" + +#include +#include +#include +#include + +/* The default timeout we use is 5 minutes, which matches the sudo default + * for the timestamp_timeout parameter. */ +#define DEFAULT_TIMESTAMP_TIMEOUT (5 * 60) +#define MODULE "pam_timestamp" +#define TIMESTAMPDIR "/var/run/sudo" +#define TIMESTAMPKEY TIMESTAMPDIR "/_pam_timestamp_key" + +/* Various buffers we use need to be at least as large as either PATH_MAX or + * LINE_MAX, so choose the larger of the two. */ +#if (LINE_MAX > PATH_MAX) +#define BUFLEN LINE_MAX +#else +#define BUFLEN PATH_MAX +#endif + +/* Return PAM_SUCCESS if the given directory looks "safe". */ +static int +check_dir_perms(pam_handle_t *pamh, const char *tdir) +{ + char scratch[BUFLEN]; + struct stat st; + int i; + /* Check that the directory is "safe". */ + if ((tdir == NULL) || (strlen(tdir) == 0)) { + return PAM_AUTH_ERR; + } + /* Iterate over the path, checking intermediate directories. */ + memset(scratch, 0, sizeof(scratch)); + for (i = 0; (tdir[i] != '\0') && (i < (int)sizeof(scratch)); i++) { + scratch[i] = tdir[i]; + if ((scratch[i] == '/') || (tdir[i + 1] == '\0')) { + /* We now have the name of a directory in the path, so + * we need to check it. */ + if ((lstat(scratch, &st) == -1) && (errno != ENOENT)) { + pam_syslog(pamh, LOG_ERR, + "unable to read `%s': %m", + scratch); + return PAM_AUTH_ERR; + } + if (!S_ISDIR(st.st_mode)) { + pam_syslog(pamh, LOG_ERR, + "`%s' is not a directory", + scratch); + return PAM_AUTH_ERR; + } + if (S_ISLNK(st.st_mode)) { + pam_syslog(pamh, LOG_ERR, + "`%s' is a symbolic link", + scratch); + return PAM_AUTH_ERR; + } + if (st.st_uid != 0) { + pam_syslog(pamh, LOG_ERR, + "`%s' owner UID != 0", + scratch); + return PAM_AUTH_ERR; + } + if (st.st_gid != 0) { + pam_syslog(pamh, LOG_ERR, + "`%s' owner GID != 0", + scratch); + return PAM_AUTH_ERR; + } + if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) { + pam_syslog(pamh, LOG_ERR, + "`%s' permissions are lax", + scratch); + return PAM_AUTH_ERR; + } + } + } + return PAM_SUCCESS; +} + +/* Validate a tty pathname as actually belonging to a tty, and return its base + * name if it's valid. */ +static const char * +check_tty(const char *tty) +{ + /* Check that we're not being set up to take a fall. */ + if ((tty == NULL) || (strlen(tty) == 0)) { + return NULL; + } + /* Pull out the meaningful part of the tty's name. */ + if (strchr(tty, '/') != NULL) { + if (strncmp(tty, "/dev/", 5) != 0) { + /* Make sure the device node is actually in /dev/, + * noted by Michal Zalewski. */ + return NULL; + } + tty = strrchr(tty, '/') + 1; + } + /* Make sure the tty wasn't actually a directory (no basename). */ + if (strlen(tty) == 0) { + return NULL; + } + return tty; +} + +/* Determine the right path name for a given user's timestamp. */ +static int +format_timestamp_name(char *path, size_t len, + const char *timestamp_dir, + const char *tty, + const char *ruser, + const char *user) +{ + if (strcmp(ruser, user) == 0) { + return snprintf(path, len, "%s/%s/%s", timestamp_dir, + ruser, tty); + } else { + return snprintf(path, len, "%s/%s/%s:%s", timestamp_dir, + ruser, tty, user); + } +} + +/* Check if a given timestamp date, when compared to a current time, fits + * within the given interval. */ +static int +timestamp_good(time_t then, time_t now, time_t interval) +{ + if (((now >= then) && ((now - then) < interval)) || + ((now < then) && ((then - now) < (2 * interval)))) { + return PAM_SUCCESS; + } + return PAM_AUTH_ERR; +} + +static int +check_login_time(const char *ruser, time_t timestamp) +{ + struct utmp utbuf, *ut; + time_t oldest_login = 0; + + setutent(); + while(!getutent_r(&utbuf, &ut)) { + if (ut->ut_type != USER_PROCESS) { + continue; + } + if (strncmp(ruser, ut->ut_user, sizeof(ut->ut_user) != 0)) { + continue; + } + if (oldest_login == 0 || oldest_login > ut->ut_tv.tv_sec) { + oldest_login = ut->ut_tv.tv_sec; + } + } + endutent(); + if(oldest_login == 0 || timestamp < oldest_login) { + return PAM_AUTH_ERR; + } + return PAM_SUCCESS; +} + +#ifndef PAM_TIMESTAMP_MAIN +static int +get_ruser(pam_handle_t *pamh, char *ruserbuf, size_t ruserbuflen) +{ + const void *ruser; + struct passwd *pwd; + + if (ruserbuf == NULL || ruserbuflen < 1) + return -2; + /* Get the name of the source user. */ + if (pam_get_item(pamh, PAM_RUSER, &ruser) != PAM_SUCCESS) { + ruser = NULL; + } + if ((ruser == NULL) || (strlen(ruser) == 0)) { + /* Barring that, use the current RUID. */ + pwd = pam_modutil_getpwuid(pamh, getuid()); + if (pwd != NULL) { + ruser = pwd->pw_name; + } + } + if (ruser == NULL || strlen(ruser) >= ruserbuflen) { + *ruserbuf = '\0'; + return -1; + } + strcpy(ruserbuf, ruser); + return 0; +} + +/* Get the path to the timestamp to use. */ +static int +get_timestamp_name(pam_handle_t *pamh, int argc, const char **argv, + char *path, size_t len) +{ + const char *user, *tty; + const void *void_tty; + const char *tdir = TIMESTAMPDIR; + char ruser[BUFLEN]; + int i, debug = 0; + + /* Parse arguments. */ + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "debug") == 0) { + debug = 1; + } + } + for (i = 0; i < argc; i++) { + if (strncmp(argv[i], "timestampdir=", 13) == 0) { + tdir = argv[i] + 13; + if (debug) { + pam_syslog(pamh, LOG_DEBUG, + "storing timestamps in `%s'", + tdir); + } + } + } + i = check_dir_perms(pamh, tdir); + if (i != PAM_SUCCESS) { + return i; + } + /* Get the name of the target user. */ + if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS) { + user = NULL; + } + if ((user == NULL) || (strlen(user) == 0)) { + return PAM_AUTH_ERR; + } + if (debug) { + pam_syslog(pamh, LOG_DEBUG, "becoming user `%s'", user); + } + /* Get the name of the source user. */ + if (get_ruser(pamh, ruser, sizeof(ruser)) || strlen(ruser) == 0) { + return PAM_AUTH_ERR; + } + if (debug) { + pam_syslog(pamh, LOG_DEBUG, "currently user `%s'", ruser); + } + /* Get the name of the terminal. */ + if (pam_get_item(pamh, PAM_TTY, &void_tty) != PAM_SUCCESS) { + tty = NULL; + } else { + tty = void_tty; + } + if ((tty == NULL) || (strlen(tty) == 0)) { + tty = ttyname(STDIN_FILENO); + if ((tty == NULL) || (strlen(tty) == 0)) { + tty = ttyname(STDOUT_FILENO); + } + if ((tty == NULL) || (strlen(tty) == 0)) { + tty = ttyname(STDERR_FILENO); + } + if ((tty == NULL) || (strlen(tty) == 0)) { + /* Match sudo's behavior for this case. */ + tty = "unknown"; + } + } + if (debug) { + pam_syslog(pamh, LOG_DEBUG, "tty is `%s'", tty); + } + /* Snip off all but the last part of the tty name. */ + tty = check_tty(tty); + if (tty == NULL) { + return PAM_AUTH_ERR; + } + /* Generate the name of the file used to cache auth results. These + * paths should jive with sudo's per-tty naming scheme. */ + if (format_timestamp_name(path, len, tdir, tty, ruser, user) >= (int)len) { + return PAM_AUTH_ERR; + } + if (debug) { + pam_syslog(pamh, LOG_DEBUG, "using timestamp file `%s'", path); + } + return PAM_SUCCESS; +} + +/* Tell the user that access has been granted. */ +static void +verbose_success(pam_handle_t *pamh, long diff) +{ + pam_info(pamh, _("Access granted (last access was %ld seconds ago)."), diff); +} + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + struct stat st; + time_t interval = DEFAULT_TIMESTAMP_TIMEOUT; + int i, fd, debug = 0, verbose = 0; + char path[BUFLEN], *p, *message, *message_end; + long tmp; + const void *void_service; + const char *service; + time_t now, then; + + /* Parse arguments. */ + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "debug") == 0) { + debug = 1; + } + } + for (i = 0; i < argc; i++) { + if (strncmp(argv[i], "timestamp_timeout=", 18) == 0) { + tmp = strtol(argv[i] + 18, &p, 0); + if ((p != NULL) && (*p == '\0')) { + interval = tmp; + if (debug) { + pam_syslog(pamh, LOG_DEBUG, + "setting timeout to %ld" + " seconds", (long)interval); + } + } + } else + if (strcmp(argv[i], "verbose") == 0) { + verbose = 1; + if (debug) { + pam_syslog(pamh, LOG_DEBUG, + "becoming more verbose"); + } + } + } + + if (flags & PAM_SILENT) { + verbose = 0; + } + + /* Get the name of the timestamp file. */ + if (get_timestamp_name(pamh, argc, argv, + path, sizeof(path)) != PAM_SUCCESS) { + return PAM_AUTH_ERR; + } + + /* Get the name of the service. */ + if (pam_get_item(pamh, PAM_SERVICE, &void_service) != PAM_SUCCESS) { + service = NULL; + } else { + service = void_service; + } + if ((service == NULL) || (strlen(service) == 0)) { + service = "(unknown)"; + } + + /* Open the timestamp file. */ + fd = open(path, O_RDONLY | O_NOFOLLOW); + if (fd == -1) { + if (debug) { + pam_syslog(pamh, LOG_DEBUG, + "cannot open timestamp `%s': %m", + path); + } + return PAM_AUTH_ERR; + } + + if (fstat(fd, &st) == 0) { + int count; + void *mac; + size_t maclen; + char ruser[BUFLEN]; + + /* Check that the file is owned by the superuser. */ + if ((st.st_uid != 0) || (st.st_gid != 0)) { + pam_syslog(pamh, LOG_ERR, "timestamp file `%s' is " + "not owned by root", path); + close(fd); + return PAM_AUTH_ERR; + } + + /* Check that the file is a normal file. */ + if (!(S_ISREG(st.st_mode))) { + pam_syslog(pamh, LOG_ERR, "timestamp file `%s' is " + "not a regular file", path); + close(fd); + return PAM_AUTH_ERR; + } + + /* Check that the file is the expected size. */ + if (st.st_size == 0) { + /* Invalid, but may have been created by sudo. */ + close(fd); + return PAM_AUTH_ERR; + } + if (st.st_size != + (off_t)(strlen(path) + 1 + sizeof(then) + hmac_sha1_size())) { + pam_syslog(pamh, LOG_NOTICE, "timestamp file `%s' " + "appears to be corrupted", path); + close(fd); + return PAM_AUTH_ERR; + } + + /* Read the file contents. */ + message = malloc(st.st_size); + count = 0; + if (!message) { + close(fd); + return PAM_BUF_ERR; + } + while (count < st.st_size) { + i = read(fd, message + count, st.st_size - count); + if ((i == 0) || (i == -1)) { + break; + } + count += i; + } + if (count < st.st_size) { + pam_syslog(pamh, LOG_NOTICE, "error reading timestamp " + "file `%s': %m", path); + close(fd); + free(message); + return PAM_AUTH_ERR; + } + message_end = message + strlen(path) + 1 + sizeof(then); + + /* Regenerate the MAC. */ + hmac_sha1_generate_file(pamh, &mac, &maclen, TIMESTAMPKEY, 0, 0, + message, message_end - message); + if ((mac == NULL) || + (memcmp(path, message, strlen(path)) != 0) || + (memcmp(mac, message_end, maclen) != 0)) { + pam_syslog(pamh, LOG_NOTICE, "timestamp file `%s' is " + "corrupted", path); + close(fd); + free(message); + return PAM_AUTH_ERR; + } + free(mac); + memmove(&then, message + strlen(path) + 1, sizeof(then)); + free(message); + + /* Check oldest login against timestamp */ + if (get_ruser(pamh, ruser, sizeof(ruser))) + { + close(fd); + return PAM_AUTH_ERR; + } + if (check_login_time(ruser, then) != PAM_SUCCESS) + { + pam_syslog(pamh, LOG_NOTICE, "timestamp file `%s' is " + "older than oldest login, disallowing " + "access to %s for user %s", + path, service, ruser); + close(fd); + return PAM_AUTH_ERR; + } + + /* Compare the dates. */ + now = time(NULL); + if (timestamp_good(then, now, interval) == PAM_SUCCESS) { + close(fd); + pam_syslog(pamh, LOG_NOTICE, "timestamp file `%s' is " + "only %ld seconds old, allowing access to %s " + "for user %s", path, (long) (now - st.st_mtime), + service, ruser); + if (verbose) { + verbose_success(pamh, now - st.st_mtime); + } + return PAM_SUCCESS; + } else { + close(fd); + pam_syslog(pamh, LOG_NOTICE, "timestamp file `%s' has " + "unacceptable age (%ld seconds), disallowing " + "access to %s for user %s", + path, (long) (now - st.st_mtime), + service, ruser); + return PAM_AUTH_ERR; + } + } + close(fd); + + /* Fail by default. */ + return PAM_AUTH_ERR; +} + +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh UNUSED, int flags UNUSED, int argc UNUSED, const char **argv UNUSED) +{ + return PAM_SUCCESS; +} + +PAM_EXTERN int +pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) +{ + char path[BUFLEN], subdir[BUFLEN], *text, *p; + void *mac; + size_t maclen; + time_t now; + int fd, i, debug = 0; + + /* Parse arguments. */ + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "debug") == 0) { + debug = 1; + } + } + + /* Get the name of the timestamp file. */ + if (get_timestamp_name(pamh, argc, argv, + path, sizeof(path)) != PAM_SUCCESS) { + return PAM_SESSION_ERR; + } + + /* Create the directory for the timestamp file if it doesn't already + * exist. */ + for (i = 1; path[i] != '\0'; i++) { + if (path[i] == '/') { + /* Attempt to create the directory. */ + strncpy(subdir, path, i); + subdir[i] = '\0'; + if (mkdir(subdir, 0700) == 0) { + /* Attempt to set the owner to the superuser. */ + lchown(subdir, 0, 0); + } else { + if (errno != EEXIST) { + if (debug) { + pam_syslog(pamh, LOG_DEBUG, + "error creating directory `%s': %m", + subdir); + } + return PAM_SESSION_ERR; + } + } + } + } + + /* Generate the message. */ + text = malloc(strlen(path) + 1 + sizeof(now) + hmac_sha1_size()); + if (text == NULL) { + pam_syslog(pamh, LOG_ERR, "unable to allocate memory: %m"); + return PAM_SESSION_ERR; + } + p = text; + + strcpy(text, path); + p += strlen(path) + 1; + + now = time(NULL); + memmove(p, &now, sizeof(now)); + p += sizeof(now); + + /* Generate the MAC and append it to the plaintext. */ + hmac_sha1_generate_file(pamh, &mac, &maclen, + TIMESTAMPKEY, + 0, 0, + text, p - text); + if (mac == NULL) { + pam_syslog(pamh, LOG_ERR, "failure generating MAC: %m"); + free(text); + return PAM_SESSION_ERR; + } + memmove(p, mac, maclen); + p += maclen; + free(mac); + + /* Open the file. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + if (fd == -1) { + pam_syslog(pamh, LOG_ERR, "unable to open `%s': %m", path); + free(text); + return PAM_SESSION_ERR; + } + + /* Attempt to set the owner to the superuser. */ + fchown(fd, 0, 0); + + /* Write the timestamp to the file. */ + if (write(fd, text, p - text) != p - text) { + pam_syslog(pamh, LOG_ERR, "unable to write to `%s': %m", path); + close(fd); + free(text); + return PAM_SESSION_ERR; + } + + /* Close the file and return successfully. */ + close(fd); + free(text); + pam_syslog(pamh, LOG_DEBUG, "updated timestamp file `%s'", path); + return PAM_SUCCESS; +} + +PAM_EXTERN int +pam_sm_close_session(pam_handle_t *pamh UNUSED, int flags UNUSED, int argc UNUSED, const char **argv UNUSED) +{ + return PAM_SUCCESS; +} + +#ifdef PAM_STATIC +/* static module data */ + +struct pam_module _pam_timestamp_modstruct = { + "pam_timestamp", + pam_sm_authenticate, + pam_sm_setcred, + NULL, + pam_sm_open_session, + pam_sm_close_session, + NULL +}; +#endif + + +#else /* PAM_TIMESTAMP_MAIN */ + +#define USAGE "Usage: %s [[-k] | [-d]] [target user]\n" +#define CHECK_INTERVAL 7 + +int +main(int argc, char **argv) +{ + int i, pretval = -1, retval = 0, dflag = 0, kflag = 0; + const char *target_user = NULL, *user = NULL, *tty = NULL; + struct passwd *pwd; + struct timeval tv; + fd_set write_fds; + char path[BUFLEN]; + struct stat st; + + /* Check that there's nothing funny going on with stdio. */ + if ((fstat(STDIN_FILENO, &st) == -1) || + (fstat(STDOUT_FILENO, &st) == -1) || + (fstat(STDERR_FILENO, &st) == -1)) { + /* Appropriate the "no controlling tty" error code. */ + return 3; + } + + /* Parse arguments. */ + while ((i = getopt(argc, argv, "dk")) != -1) { + switch (i) { + case 'd': + dflag++; + break; + case 'k': + kflag++; + break; + default: + fprintf(stderr, USAGE, argv[0]); + return 1; + break; + } + } + + /* Bail if both -k and -d are given together. */ + if ((kflag + dflag) > 1) { + fprintf(stderr, USAGE, argv[0]); + return 1; + } + + /* Check that we're setuid. */ + if (geteuid() != 0) { + fprintf(stderr, "%s must be setuid root\n", + argv[0]); + retval = 2; + } + + /* Check that we have a controlling tty. */ + tty = ttyname(STDIN_FILENO); + if ((tty == NULL) || (strlen(tty) == 0)) { + tty = ttyname(STDOUT_FILENO); + } + if ((tty == NULL) || (strlen(tty) == 0)) { + tty = ttyname(STDERR_FILENO); + } + if ((tty == NULL) || (strlen(tty) == 0)) { + tty = "unknown"; + } + + /* Get the name of the invoking (requesting) user. */ + pwd = getpwuid(getuid()); + if (pwd == NULL) { + retval = 4; + } + + /* Get the name of the target user. */ + user = strdup(pwd->pw_name); + if (user == NULL) { + retval = 4; + } else { + target_user = (optind < argc) ? argv[optind] : user; + if ((strchr(target_user, '.') != NULL) || + (strchr(target_user, '/') != NULL) || + (strchr(target_user, '%') != NULL)) { + fprintf(stderr, "unknown user: %s\n", + target_user); + retval = 4; + } + } + + /* Sanity check the tty to make sure we should be checking + * for timestamps which pertain to it. */ + if (retval == 0) { + tty = check_tty(tty); + if (tty == NULL) { + fprintf(stderr, "invalid tty\n"); + retval = 6; + } + } + + do { + /* Sanity check the timestamp directory itself. */ + if (retval == 0) { + if (check_dir_perms(NULL, TIMESTAMPDIR) != PAM_SUCCESS) { + retval = 5; + } + } + + if (retval == 0) { + /* Generate the name of the timestamp file. */ + format_timestamp_name(path, sizeof(path), TIMESTAMPDIR, + tty, user, target_user); + } + + if (retval == 0) { + if (kflag) { + /* Remove the timestamp. */ + if (lstat(path, &st) != -1) { + retval = unlink(path); + } + } else { + /* Check the timestamp. */ + if (lstat(path, &st) != -1) { + /* Check oldest login against timestamp */ + if (check_login_time(user, st.st_mtime) != PAM_SUCCESS) { + retval = 7; + } else if (!timestamp_good(st.st_mtime, time(NULL), + DEFAULT_TIMESTAMP_TIMEOUT) == PAM_SUCCESS) { + retval = 7; + } + } else { + retval = 7; + } + } + } + + if (dflag > 0) { + struct timeval now; + /* Send the would-be-returned value to our parent. */ + signal(SIGPIPE, SIG_DFL); + fprintf(stdout, "%d\n", retval); + fflush(stdout); + /* Wait. */ + gettimeofday(&now, NULL); + tv.tv_sec = CHECK_INTERVAL; + /* round the sleep time to get woken up on a whole second */ + tv.tv_usec = 1000000 - now.tv_usec; + if (now.tv_usec < 500000) + tv.tv_sec--; + FD_ZERO(&write_fds); + FD_SET(STDOUT_FILENO, &write_fds); + select(STDOUT_FILENO + 1, + NULL, NULL, &write_fds, + &tv); + pretval = retval; + retval = 0; + } + } while (dflag > 0); + + return retval; +} + +#endif diff --git a/modules/pam_timestamp/pam_timestamp_check.8.xml b/modules/pam_timestamp/pam_timestamp_check.8.xml new file mode 100644 index 00000000..85484a06 --- /dev/null +++ b/modules/pam_timestamp/pam_timestamp_check.8.xml @@ -0,0 +1,208 @@ + + + + + + + pam_timestamp_check + 8 + Linux-PAM Manual + + + + pam_timestamp_check + Check to see if the default timestamp is valid + + + + + pam_timestamp_check + + -k + + + -d + + + target_user + + + + + + + DESCRIPTION + + + With no arguments pam_timestamp_check will check to +see if the default timestamp is valid, or optionally remove it. + + + + + + OPTIONS + + + + + + + + Instead of checking the validity of a timestamp, remove it. + This is analogous to sudo's -k option. + + + + + + + + + + Instead of returning validity using an exit status, + loop indefinitely, polling regularly and printing the status on + standard output. + + + + + + + + + + By default pam_timestamp_check checks or removes + timestamps generated by pam_timestamp when + the user authenticates as herself. When the user authenticates as a + different user, the name of the timestamp file changes to + accomodate this. target_user allows + to specify this user name. + + + + + + + + RETURN VALUES + + + 0 + + + The timestamp is valid. + + + + + 2 + + + The binary is not setuid root. + + + + + 3 + + + Invalid invocation. + + + + + 4 + + + User is unknown. + + + + + 5 + + + Permissions error. + + + + + 6 + + + Invalid controlling tty. + + + + + 7 + + + Timestamp is not valid. + + + + + + + + NOTES + + Users can get confused when they are not always asked for passwords when +running a given program. Some users reflexively begin typing information before +noticing that it is not being asked for. + + + + + EXAMPLES + +auth sufficient pam_timestamp.so verbose +auth required pam_unix.so + +session required pam_unix.so +session optional pam_timestamp.so + + + + + FILES + + + /var/run/sudo/... + + timestamp files and directories + + + + + + + SEE ALSO + + + pam_timestamp_check8 + , + + pam.conf5 + , + + pam.d5 + , + + pam8 + + + + + + AUTHOR + + pam_tally was written by Nalin Dahyabhai. + + + + + diff --git a/modules/pam_timestamp/pam_timestamp_check.c b/modules/pam_timestamp/pam_timestamp_check.c new file mode 100644 index 00000000..52b5a95a --- /dev/null +++ b/modules/pam_timestamp/pam_timestamp_check.c @@ -0,0 +1,42 @@ +/****************************************************************************** + * A module for Linux-PAM that will cache authentication results, inspired by + * (and implemented with an eye toward being mixable with) sudo. + * + * Copyright (c) 2002 Red Hat, Inc. + * Written by Nalin Dahyabhai + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define PAM_TIMESTAMP_MAIN 1 +#include "pam_timestamp.c" diff --git a/modules/pam_timestamp/sha1.c b/modules/pam_timestamp/sha1.c new file mode 100644 index 00000000..e6705eb5 --- /dev/null +++ b/modules/pam_timestamp/sha1.c @@ -0,0 +1,254 @@ +/* Yet another SHA-1 implementation. + * + * Copyright (c) 2003 Red Hat, Inc. + * Written by Nalin Dahyabhai + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* See http://www.itl.nist.gov/fipspubs/fip180-1.htm for descriptions. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sha1.h" + +static unsigned char +padding[SHA1_BLOCK_SIZE] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static u_int32_t +F(u_int32_t b, u_int32_t c, u_int32_t d) +{ + return (b & c) | ((~b) & d); +} + +static u_int32_t +G(u_int32_t b, u_int32_t c, u_int32_t d) +{ + return b ^ c ^ d; +} + +static u_int32_t +H(u_int32_t b, u_int32_t c, u_int32_t d) +{ + return (b & c) | (b & d) | (c & d); +} + +static u_int32_t +RL(u_int32_t n, u_int32_t s) +{ + return (n << s) | (n >> (32 - s)); +} + +static u_int32_t +sha1_round(u_int32_t (*FUNC)(u_int32_t, u_int32_t, u_int32_t), + u_int32_t a, u_int32_t b, u_int32_t c, u_int32_t d, u_int32_t e, + u_int32_t i, u_int32_t n) +{ + return RL(a, 5) + FUNC(b, c, d) + e + i + n; +} + +void +sha1_init(struct sha1_context *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + ctx->e = 0xc3d2e1f0; +} + +static void +sha1_process(struct sha1_context *ctx, u_int32_t buffer[SHA1_BLOCK_SIZE / 4]) +{ + u_int32_t a, b, c, d, e, temp; + u_int32_t data[80]; + int i; + + for (i = 0; i < 16; i++) { + data[i] = htonl(buffer[i]); + } + for (i = 16; i < 80; i++) { + data[i] = RL(data[i - 3] ^ data[i - 8] ^ data[i - 14] ^ data[i - 16], 1); + } + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + e = ctx->e; + + for (i = 0; i < 20; i++) { + temp = sha1_round(F, a, b, c, d, e, data[i], 0x5a827999); + e = d; d = c; c = RL(b, 30); b = a; a = temp; + } + for (i = 20; i < 40; i++) { + temp = sha1_round(G, a, b, c, d, e, data[i], 0x6ed9eba1); + e = d; d = c; c = RL(b, 30); b = a; a = temp; + } + for (i = 40; i < 60; i++) { + temp = sha1_round(H, a, b, c, d, e, data[i], 0x8f1bbcdc); + e = d; d = c; c = RL(b, 30); b = a; a = temp; + } + for (i = 60; i < 80; i++) { + temp = sha1_round(G, a, b, c, d, e, data[i], 0xca62c1d6); + e = d; d = c; c = RL(b, 30); b = a; a = temp; + } + + ctx->a += a; + ctx->b += b; + ctx->c += c; + ctx->d += d; + ctx->e += e; + + memset(buffer, 0, sizeof(buffer[0]) * SHA1_BLOCK_SIZE / 4); + memset(data, 0, sizeof(data)); +} + +void +sha1_update(struct sha1_context *ctx, const unsigned char *data, size_t length) +{ + size_t i = 0, l = length, c, t; + u_int32_t count = 0; + + /* Process any pending + data blocks. */ + while (l + ctx->pending_count >= SHA1_BLOCK_SIZE) { + c = ctx->pending_count; + t = SHA1_BLOCK_SIZE - c; + memcpy(ctx->pending + c, &data[i], t); + sha1_process(ctx, (u_int32_t*) ctx->pending); + i += t; + l -= t; + ctx->pending_count = 0; + } + + /* Save what's left of the data block as a pending data block. */ + c = ctx->pending_count; + memcpy(ctx->pending + c, &data[i], l); + ctx->pending_count += l; + + /* Update the message length. */ + ctx->count += length; + + /* Update our internal counts. */ + if (length != 0) { + count = ctx->counts[0]; + ctx->counts[0] += length; + if (count >= ctx->counts[0]) { + ctx->counts[1]++; + } + } +} + +size_t +sha1_output(struct sha1_context *ctx, unsigned char *out) +{ + struct sha1_context ctx2; + + /* Output the sum. */ + if (out != NULL) { + u_int32_t c; + memcpy(&ctx2, ctx, sizeof(ctx2)); + + /* Pad this block. */ + c = ctx2.pending_count; + memcpy(ctx2.pending + c, + padding, SHA1_BLOCK_SIZE - c); + + /* Do we need to process two blocks now? */ + if (c >= (SHA1_BLOCK_SIZE - (sizeof(u_int32_t) * 2))) { + /* Process this block. */ + sha1_process(&ctx2, + (u_int32_t*) ctx2.pending); + /* Set up another block. */ + ctx2.pending_count = 0; + memset(ctx2.pending, 0, SHA1_BLOCK_SIZE); + ctx2.pending[0] = + (c == SHA1_BLOCK_SIZE) ? 0x80 : 0; + } + + /* Process the final block. */ + ctx2.counts[1] <<= 3; + if (ctx2.counts[0] >> 29) { + ctx2.counts[1] |= + (ctx2.counts[0] >> 29); + } + ctx2.counts[0] <<= 3; + ctx2.counts[0] = htonl(ctx2.counts[0]); + ctx2.counts[1] = htonl(ctx2.counts[1]); + memcpy(ctx2.pending + 56, + &ctx2.counts[1], sizeof(u_int32_t)); + memcpy(ctx2.pending + 60, + &ctx2.counts[0], sizeof(u_int32_t)); + sha1_process(&ctx2, (u_int32_t*) ctx2.pending); + + /* Output the data. */ + out[ 3] = (ctx2.a >> 0) & 0xff; + out[ 2] = (ctx2.a >> 8) & 0xff; + out[ 1] = (ctx2.a >> 16) & 0xff; + out[ 0] = (ctx2.a >> 24) & 0xff; + + out[ 7] = (ctx2.b >> 0) & 0xff; + out[ 6] = (ctx2.b >> 8) & 0xff; + out[ 5] = (ctx2.b >> 16) & 0xff; + out[ 4] = (ctx2.b >> 24) & 0xff; + + out[11] = (ctx2.c >> 0) & 0xff; + out[10] = (ctx2.c >> 8) & 0xff; + out[ 9] = (ctx2.c >> 16) & 0xff; + out[ 8] = (ctx2.c >> 24) & 0xff; + + out[15] = (ctx2.d >> 0) & 0xff; + out[14] = (ctx2.d >> 8) & 0xff; + out[13] = (ctx2.d >> 16) & 0xff; + out[12] = (ctx2.d >> 24) & 0xff; + + out[19] = (ctx2.e >> 0) & 0xff; + out[18] = (ctx2.e >> 8) & 0xff; + out[17] = (ctx2.e >> 16) & 0xff; + out[16] = (ctx2.e >> 24) & 0xff; + } + + return SHA1_OUTPUT_SIZE; +} diff --git a/modules/pam_timestamp/sha1.h b/modules/pam_timestamp/sha1.h new file mode 100644 index 00000000..667b87ca --- /dev/null +++ b/modules/pam_timestamp/sha1.h @@ -0,0 +1,60 @@ +/* Yet another SHA-1 implementation. + * + * Copyright (c) 2003 Red Hat, Inc. + * Written by Nalin Dahyabhai + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef pam_timestamp_sha1_h +#define pam_timestamp_sha1_h + +#include + +#define SHA1_BLOCK_SIZE 64 + +struct sha1_context { + size_t count; + unsigned char pending[SHA1_BLOCK_SIZE]; + u_int32_t counts[2]; + size_t pending_count; + u_int32_t a, b, c, d, e; +}; + +#define SHA1_OUTPUT_SIZE 20 + +void sha1_init(struct sha1_context *ctx); +void sha1_update(struct sha1_context *ctx, + const unsigned char *data, size_t length); +size_t sha1_output(struct sha1_context *ctx, unsigned char *out); + +#endif diff --git a/modules/pam_timestamp/tst-pam_timestamp b/modules/pam_timestamp/tst-pam_timestamp new file mode 100755 index 00000000..1d425b83 --- /dev/null +++ b/modules/pam_timestamp/tst-pam_timestamp @@ -0,0 +1,2 @@ +#!/bin/sh +../../tests/tst-dlopen .libs/pam_timestamp.so -- cgit v1.2.3 From ca0f93a7e6a1b3e0d2d94b658d84e9b34b17577b Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Sun, 30 Nov 2008 17:13:58 +0000 Subject: Relevant BUGIDs: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purpose of commit: bugfix Commit summary: --------------- 2008-11-29 Thorsten Kukuk * configure.in: Check for xcrypt.h, fix typo in libaudit check. * modules/pam_cracklib/pam_cracklib.c: Include xcrypt.h if available. * modules/pam_unix/bigcrypt.c: Likewise. * modules/pam_unix/passverify.c: Likewise. * modules/pam_userdb/pam_userdb.c: Likewise. Patch from Diego Flameeyes Pettenò --- modules/pam_cracklib/pam_cracklib.c | 4 +++- modules/pam_unix/bigcrypt.c | 4 +++- modules/pam_unix/passverify.c | 4 +++- modules/pam_userdb/pam_userdb.c | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) (limited to 'modules') diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c index b94f8596..4b2052fc 100644 --- a/modules/pam_cracklib/pam_cracklib.c +++ b/modules/pam_cracklib/pam_cracklib.c @@ -37,7 +37,9 @@ #include "config.h" #include -#ifdef HAVE_CRYPT_H +#ifdef HAVE_LIBXCRYPT +# include +#elif defined(HAVE_CRYPT_H) # include #endif #include diff --git a/modules/pam_unix/bigcrypt.c b/modules/pam_unix/bigcrypt.c index 9cd55384..9922d177 100644 --- a/modules/pam_unix/bigcrypt.c +++ b/modules/pam_unix/bigcrypt.c @@ -29,7 +29,9 @@ #include #include #include -#ifdef HAVE_CRYPT_H +#ifdef HAVE_LIBXCRYPT +#include +#elif defined(HAVE_CRYPT_H) #include #endif diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 0f58b019..eae1e24c 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -19,7 +19,9 @@ #include #include #include -#ifdef HAVE_CRYPT_H +#ifdef HAVE_LIBXCRYPT +#include +#elif defined(HAVE_CRYPT_H) #include #endif diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c index a796b15e..2d39123b 100644 --- a/modules/pam_userdb/pam_userdb.c +++ b/modules/pam_userdb/pam_userdb.c @@ -17,7 +17,9 @@ #include #include #include -#ifdef HAVE_CRYPT_H +#ifdef HAVE_LIBXCRYPT +#include +#elif defined(HAVE_CRYPT_H) #include #endif -- cgit v1.2.3 From e7ce957e4efd094cdfaac8908cc95042b47260a3 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Mon, 1 Dec 2008 10:13:03 +0000 Subject: Relevant BUGIDs: Purpose of commit: cleanup Commit summary: --------------- Add .cvsignore file --- modules/pam_timestamp/.cvsignore | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 modules/pam_timestamp/.cvsignore (limited to 'modules') diff --git a/modules/pam_timestamp/.cvsignore b/modules/pam_timestamp/.cvsignore new file mode 100644 index 00000000..d9a7b0d9 --- /dev/null +++ b/modules/pam_timestamp/.cvsignore @@ -0,0 +1,12 @@ +*.la +*.lo +*.so +*~ +.deps +.libs +Makefile +Makefile.in +README +pam_timestamp.8 +pam_timestamp_check.8 + -- cgit v1.2.3 From 1395ff30321ce605ab2ca79b1301cd93f51a5ca1 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 1 Dec 2008 11:26:59 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-12-01 Tomas Mraz * modules/pam_access/pam_access.8.xml: Fix description of nodefgroup option. * modules/pam_group/pam_group.c (is_same): Fix check for correct string length. --- modules/pam_access/pam_access.8.xml | 6 ++++-- modules/pam_group/pam_group.c | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'modules') diff --git a/modules/pam_access/pam_access.8.xml b/modules/pam_access/pam_access.8.xml index ff048593..6b031d2e 100644 --- a/modules/pam_access/pam_access.8.xml +++ b/modules/pam_access/pam_access.8.xml @@ -150,8 +150,10 @@ - The group database will not be used for tokens not - identified as account name. + User tokens which are not enclosed in parentheses will not be + matched against the group database. The backwards compatible default is + to try the group database match even for tokens not enclosed + in parentheses. diff --git a/modules/pam_group/pam_group.c b/modules/pam_group/pam_group.c index bddcf1cb..4a931c4f 100644 --- a/modules/pam_group/pam_group.c +++ b/modules/pam_group/pam_group.c @@ -331,10 +331,10 @@ is_same (const pam_handle_t *pamh UNUSED, } /* Ok, we know that b is a substring from A and does not contain - wildcards, but now the length of both strings must be the same, - too. */ - if (strlen (a) != strlen(b)) - return FALSE; + wildcards, but now the length of both strings must be the same, + too. In this case it means, a[i] has to be the end of the string. */ + if (a[i] != '\0') + return FALSE; return ( !len ); } -- cgit v1.2.3 From 090693e116fc6ea0dfb649e11a01af08e19b33d9 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Mon, 1 Dec 2008 12:40:40 +0000 Subject: Relevant BUGIDs: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purpose of commit: new feature Commit summary: --------------- 2008-12-01 Thorsten Kukuk * modules/pam_unix/pam_unix.8.xml: Document blowfish option. * configure.in: Check for crypt_gensalt_rn. * modules/pam_unix/pam_unix_passwd.c: Pass pamh to create_password_hash function. * modules/pam_unix/passverify.c (create_password_hash): Add blowfish support. * modules/pam_unix/passverify.h: Adjust create_password_hash prototype. * modules/pam_unix/support.c: Add support for blowfish option. * modules/pam_unix/support.h: Add defines for blowfish option. Patch from Diego Flameeyes Pettenò --- modules/pam_unix/pam_unix.8.xml | 28 ++++++++-- modules/pam_unix/pam_unix_passwd.c | 2 +- modules/pam_unix/passverify.c | 107 +++++++++++++++---------------------- modules/pam_unix/passverify.h | 51 +++++++----------- modules/pam_unix/support.c | 32 +++++++---- modules/pam_unix/support.h | 4 +- 6 files changed, 113 insertions(+), 111 deletions(-) (limited to 'modules') diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml index e08edfcc..cc3affd9 100644 --- a/modules/pam_unix/pam_unix.8.xml +++ b/modules/pam_unix/pam_unix.8.xml @@ -266,7 +266,9 @@ When a user changes their password next, encrypt it with the SHA256 algorithm. If the - SHA256 algorithm is not known to the libcrypt, + SHA256 algorithm is not known to the + crypt3 + function, fall back to MD5. @@ -279,7 +281,24 @@ When a user changes their password next, encrypt it with the SHA512 algorithm. If the - SHA512 algorithm is not known to the libcrypt, + SHA512 algorithm is not known to the + crypt3 + function, + fall back to MD5. + + + + + + + + + + When a user changes their password next, + encrypt it with the blowfish algorithm. If the + SHA512 algorithm is not known to the + crypt3 + function, fall back to MD5. @@ -290,8 +309,9 @@ - Set the optional number of rounds of the SHA256 and SHA512 - password hashing algorithms to n. + Set the optional number of rounds of the SHA256, SHA512 + and blowfish password hashing algorithms to + n. diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 240caddb..b8da9913 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -749,7 +749,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * First we encrypt the new password. */ - tpass = create_password_hash(pass_new, ctrl, rounds); + tpass = create_password_hash(pamh, pass_new, ctrl, rounds); if (tpass == NULL) { pam_syslog(pamh, LOG_CRIT, "out of memory for password"); diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index eae1e24c..281716e0 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -151,15 +151,8 @@ is_pwd_shadowed(const struct passwd *pwd) return 0; } -#ifdef HELPER_COMPILE -int -get_account_info(const char *name, - struct passwd **pwd, struct spwd **spwdent) -#else -int -get_account_info(pam_handle_t *pamh, const char *name, - struct passwd **pwd, struct spwd **spwdent) -#endif +PAMH_ARG_DECL(int get_account_info, + const char *name, struct passwd **pwd, struct spwd **spwdent) { /* UNIX passwords area */ *pwd = pam_modutil_getpwnam(pamh, name); /* Get password file entry... */ @@ -219,24 +212,13 @@ get_account_info(pam_handle_t *pamh, const char *name, return PAM_SUCCESS; } -#ifdef HELPER_COMPILE -int -get_pwd_hash(const char *name, - struct passwd **pwd, char **hash) -#else -int -get_pwd_hash(pam_handle_t *pamh, const char *name, - struct passwd **pwd, char **hash) -#endif +PAMH_ARG_DECL(int get_pwd_hash, + const char *name, struct passwd **pwd, char **hash) { int retval; struct spwd *spwdent = NULL; -#ifdef HELPER_COMPILE - retval = get_account_info(name, pwd, &spwdent); -#else - retval = get_account_info(pamh, name, pwd, &spwdent); -#endif + retval = get_account_info(PAMH_ARG(name, pwd, &spwdent)); if (retval != PAM_SUCCESS) { return retval; } @@ -251,13 +233,8 @@ get_pwd_hash(pam_handle_t *pamh, const char *name, return PAM_SUCCESS; } -#ifdef HELPER_COMPILE -int -check_shadow_expiry(struct spwd *spent, int *daysleft) -#else -int -check_shadow_expiry(pam_handle_t *pamh, struct spwd *spent, int *daysleft) -#endif +PAMH_ARG_DECL(int check_shadow_expiry, + struct spwd *spent, int *daysleft) { long int curdays; *daysleft = -1; @@ -386,17 +363,19 @@ crypt_md5_wrapper(const char *pass_new) return cp; } -char * -create_password_hash(const char *password, unsigned int ctrl, int rounds) +PAMH_ARG_DECL(char * create_password_hash, + const char *password, unsigned int ctrl, int rounds) { const char *algoid; char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */ char *sp; if (on(UNIX_MD5_PASS, ctrl)) { + /* algoid = "$1" */ return crypt_md5_wrapper(password); - } - if (on(UNIX_SHA256_PASS, ctrl)) { + } else if (on(UNIX_BLOWFISH_PASS, ctrl)) { + algoid = "$2a$"; + } else if (on(UNIX_SHA256_PASS, ctrl)) { algoid = "$5$"; } else if (on(UNIX_SHA512_PASS, ctrl)) { algoid = "$6$"; @@ -416,17 +395,35 @@ create_password_hash(const char *password, unsigned int ctrl, int rounds) return crypted; } - sp = stpcpy(salt, algoid); - if (on(UNIX_ALGO_ROUNDS, ctrl)) { - sp += snprintf(sp, sizeof(salt) - 3, "rounds=%u$", rounds); +#ifdef HAVE_CRYPT_GENSALT_RN + if (on(UNIX_BLOWFISH_PASS, ctrl)) { + char entropy[17]; + crypt_make_salt(entropy, sizeof(entropy) - 1); + sp = crypt_gensalt_rn(algoid, rounds, + entropy, sizeof(entropy), + salt, sizeof(salt)); + } else { +#endif + sp = stpcpy(salt, algoid); + if (on(UNIX_ALGO_ROUNDS, ctrl)) { + sp += snprintf(sp, sizeof(salt) - 3, "rounds=%u$", rounds); + } + crypt_make_salt(sp, 8); + /* For now be conservative so the resulting hashes + * are not too long. 8 bytes of salt prevents dictionary + * attacks well enough. */ +#ifdef HAVE_CRYPT_GENSALT_RN } - crypt_make_salt(sp, 8); - /* For now be conservative so the resulting hashes - * are not too long. 8 bytes of salt prevents dictionary - * attacks well enough. */ +#endif sp = crypt(password, salt); if (strncmp(algoid, sp, strlen(algoid)) != 0) { - /* libc doesn't know the algorithm, use MD5 */ + /* libxcrypt/libc doesn't know the algorithm, use MD5 */ + pam_syslog(pamh, LOG_ERR, + "Algo %s not supported by the crypto backend, " + "falling back to MD5\n", + on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" : + on(UNIX_SHA256_PASS, ctrl) ? "sha256" : + on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid); memset(sp, '\0', strlen(sp)); return crypt_md5_wrapper(password); } @@ -703,13 +700,8 @@ done: } } -#ifdef HELPER_COMPILE -int -unix_update_passwd(const char *forwho, const char *towhat) -#else -int -unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat) -#endif +PAMH_ARG_DECL(int unix_update_passwd, + const char *forwho, const char *towhat) { struct passwd *tmpent = NULL; struct stat st; @@ -803,11 +795,7 @@ unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat) done: if (!err) { if (!rename(PW_TMPFILE, "/etc/passwd")) -#ifdef HELPER_COMPILE - helper_log_err( -#else pam_syslog(pamh, -#endif LOG_NOTICE, "password changed for %s", forwho); else err = 1; @@ -830,13 +818,8 @@ done: } } -#ifdef HELPER_COMPILE -int -unix_update_shadow(const char *forwho, char *towhat) -#else -int -unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat) -#endif +PAMH_ARG_DECL(int unix_update_shadow, + const char *forwho, char *towhat) { struct spwd *spwdent = NULL, *stmpent = NULL; struct stat st; @@ -933,11 +916,7 @@ unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat) done: if (!err) { if (!rename(SH_TMPFILE, "/etc/shadow")) -#ifdef HELPER_COMPILE - helper_log_err( -#else pam_syslog(pamh, -#endif LOG_NOTICE, "password changed for %s", forwho); else err = 1; diff --git a/modules/pam_unix/passverify.h b/modules/pam_unix/passverify.h index 21bb9232..3de67593 100644 --- a/modules/pam_unix/passverify.h +++ b/modules/pam_unix/passverify.h @@ -21,9 +21,6 @@ is_pwd_shadowed(const struct passwd *pwd); char * crypt_md5_wrapper(const char *pass_new); -char * -create_password_hash(const char *password, unsigned int ctrl, int rounds); - int unix_selinux_confined(void); @@ -58,41 +55,33 @@ getuidname(uid_t uid); int read_passwords(int fd, int npass, char **passwords); +#endif -int -get_account_info(const char *name, - struct passwd **pwd, struct spwd **spwdent); - -int -get_pwd_hash(const char *name, - struct passwd **pwd, char **hash); - -int -check_shadow_expiry(struct spwd *spent, int *daysleft); +#ifdef HELPER_COMPILE +#define PAMH_ARG_DECL(fname, ...) fname(__VA_ARGS__) +#define PAMH_ARG(...) __VA_ARGS__ +#else +#define PAMH_ARG_DECL(fname, ...) fname(pam_handle_t *pamh, __VA_ARGS__) +#define PAMH_ARG(...) pamh, __VA_ARGS__ +#endif -int -unix_update_passwd(const char *forwho, const char *towhat); +PAMH_ARG_DECL(char * create_password_hash, + const char *password, unsigned int ctrl, int rounds); -int -unix_update_shadow(const char *forwho, char *towhat); -#else -int -get_account_info(pam_handle_t *pamh, const char *name, - struct passwd **pwd, struct spwd **spwdent); +PAMH_ARG_DECL(int get_account_info, + const char *name, struct passwd **pwd, struct spwd **spwdent); -int -get_pwd_hash(pam_handle_t *pamh, const char *name, - struct passwd **pwd, char **hash); +PAMH_ARG_DECL(int get_pwd_hash, + const char *name, struct passwd **pwd, char **hash); -int -check_shadow_expiry(pam_handle_t *pamh, struct spwd *spent, int *daysleft); +PAMH_ARG_DECL(int check_shadow_expiry, + struct spwd *spent, int *daysleft); -int -unix_update_passwd(pam_handle_t *pamh, const char *forwho, const char *towhat); +PAMH_ARG_DECL(int unix_update_passwd, + const char *forwho, const char *towhat); -int -unix_update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat); -#endif +PAMH_ARG_DECL(int unix_update_shadow, + const char *forwho, char *towhat); /* ****************************************************************** * * Copyright (c) Red Hat, Inc. 2007. diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index db630f51..faec20dc 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -109,16 +109,8 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds, *remember = 400; } } - if (rounds != NULL) { - if (j == UNIX_ALGO_ROUNDS) { - *rounds = strtol(*argv + 7, NULL, 10); - if ((*rounds < 1000) || (*rounds == INT_MAX)) - /* don't care about bogus values */ - unset(UNIX_ALGO_ROUNDS, ctrl); - if (*rounds >= 10000000) - *rounds = 9999999; - } - } + if (rounds != NULL && j == UNIX_ALGO_ROUNDS) + *rounds = strtol(*argv + 7, NULL, 10); } ++argv; /* step to next argument */ @@ -128,6 +120,26 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds, D(("DISALLOW_NULL_AUTHTOK")); set(UNIX__NONULL, ctrl); } + + /* Set default rounds for blowfish */ + if (on(UNIX_BLOWFISH_PASS, ctrl) && off(UNIX_ALGO_ROUNDS, ctrl)) { + *rounds = 5; + set(UNIX_ALGO_ROUNDS, ctrl); + } + + /* Enforce sane "rounds" values */ + if (on(UNIX_ALGO_ROUNDS, ctrl)) { + if (on(UNIX_BLOWFISH_PASS, ctrl)) { + if (*rounds < 4 || *rounds > 31) + *rounds = 5; + } else if (on(UNIX_SHA256_PASS, ctrl) || on(UNIX_SHA512_PASS, ctrl)) { + if ((*rounds < 1000) || (*rounds == INT_MAX)) + /* don't care about bogus values */ + unset(UNIX_ALGO_ROUNDS, ctrl); + if (*rounds >= 10000000) + *rounds = 9999999; + } + } /* auditing is a more sensitive version of debug */ diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h index a33dadaa..86575ff0 100644 --- a/modules/pam_unix/support.h +++ b/modules/pam_unix/support.h @@ -88,8 +88,9 @@ typedef struct { #define UNIX_SHA512_PASS 24 /* new password hashes will use SHA512 */ #define UNIX_ALGO_ROUNDS 25 /* optional number of rounds for new password hash algorithms */ +#define UNIX_BLOWFISH_PASS 26 /* new password hashes will use blowfish */ /* -------------- */ -#define UNIX_CTRLS_ 26 /* number of ctrl arguments defined */ +#define UNIX_CTRLS_ 27 /* number of ctrl arguments defined */ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = { @@ -122,6 +123,7 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = /* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(040420000), 020000000}, /* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(020420000), 040000000}, /* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000}, +/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(060420000),0200000000}, }; #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) -- cgit v1.2.3 From 703c640d3722f93b4e7fe14688efc15c9fb92e5f Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 1 Dec 2008 15:10:22 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-12-01 Tomas Mraz * modules/pam_unix/support.h: Fix masks for cipher algorithm flags. --- modules/pam_unix/support.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'modules') diff --git a/modules/pam_unix/support.h b/modules/pam_unix/support.h index 86575ff0..dfee2dae 100644 --- a/modules/pam_unix/support.h +++ b/modules/pam_unix/support.h @@ -110,20 +110,20 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = /* UNIX__QUIET */ {NULL, _ALL_ON_, 02000}, /* UNIX_USE_AUTHTOK */ {"use_authtok", _ALL_ON_, 04000}, /* UNIX_SHADOW */ {"shadow", _ALL_ON_, 010000}, -/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0400000), 020000}, +/* UNIX_MD5_PASS */ {"md5", _ALL_ON_^(0260420000), 020000}, /* UNIX__NULLOK */ {"nullok", _ALL_ON_^(01000), 0}, /* UNIX_DEBUG */ {"debug", _ALL_ON_, 040000}, /* UNIX_NODELAY */ {"nodelay", _ALL_ON_, 0100000}, /* UNIX_NIS */ {"nis", _ALL_ON_, 0200000}, -/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(020000), 0400000}, +/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(0260420000), 0400000}, /* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000}, /* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000}, /* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000}, /* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000}, -/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(040420000), 020000000}, -/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(020420000), 040000000}, +/* UNIX_SHA256_PASS */ {"sha256", _ALL_ON_^(0260420000), 020000000}, +/* UNIX_SHA512_PASS */ {"sha512", _ALL_ON_^(0260420000), 040000000}, /* UNIX_ALGO_ROUNDS */ {"rounds=", _ALL_ON_, 0100000000}, -/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(060420000),0200000000}, +/* UNIX_BLOWFISH_PASS */ {"blowfish", _ALL_ON_^(0260420000), 0200000000}, }; #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) -- cgit v1.2.3 From f9cde35ec82267c2fa3012276a35a6f1b2cf131f Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 2 Dec 2008 10:57:19 +0000 Subject: Relevant BUGIDs: Purpose of commit: cleanup Commit summary: --------------- 2008-12-02 Tomas Mraz * modules/pam_timestamp/Makefile.am: Add hmacfile to tests. * modules/pam_timestamp/hmacfile.c: Do not try the short key testvector. --- modules/pam_timestamp/.cvsignore | 3 ++- modules/pam_timestamp/Makefile.am | 4 ++-- modules/pam_timestamp/hmacfile.c | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'modules') diff --git a/modules/pam_timestamp/.cvsignore b/modules/pam_timestamp/.cvsignore index d9a7b0d9..c084c915 100644 --- a/modules/pam_timestamp/.cvsignore +++ b/modules/pam_timestamp/.cvsignore @@ -9,4 +9,5 @@ Makefile.in README pam_timestamp.8 pam_timestamp_check.8 - +hmacfile +pam_timestamp_check diff --git a/modules/pam_timestamp/Makefile.am b/modules/pam_timestamp/Makefile.am index 51a3c215..373f483c 100644 --- a/modules/pam_timestamp/Makefile.am +++ b/modules/pam_timestamp/Makefile.am @@ -1,13 +1,13 @@ # # Copyright (c) 2005 Thorsten Kukuk -# Copyright (c) 2005 Red Hat, Inc. +# Copyright (c) 2005, 2008 Red Hat, Inc. # CLEANFILES = *~ XMLS = README.xml pam_timestamp.8.xml pam_timestamp_check.8.xml man_MANS = pam_timestamp.8 pam_timestamp_check.8 -TESTS = tst-pam_timestamp +TESTS = tst-pam_timestamp hmacfile EXTRA_DIST = $(man_MANS) hmactest.c $(XMLS) $(TESTS) diff --git a/modules/pam_timestamp/hmacfile.c b/modules/pam_timestamp/hmacfile.c index 963f6f54..d2da5ff1 100644 --- a/modules/pam_timestamp/hmacfile.c +++ b/modules/pam_timestamp/hmacfile.c @@ -63,11 +63,13 @@ testvectors(void) "b617318655057264e28bc0b6fb378c8ef146be00", }, +#ifdef HMAC_ALLOW_SHORT_KEYS { "Jefe", 4, "what do ya want for nothing?", 28, "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", }, +#endif { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 20, -- cgit v1.2.3 From 7630ed2ce08055607206d25ba078cc081f1b12b7 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 2 Dec 2008 11:15:13 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-12-02 Olivier Fourdan * modules/pam_filter/pam_filter.c (master): Use /dev/ptmx instead of the old BSD pseudoterminal API. (set_filter): Call grantpt(), unlockpt() and ptsname(). Do not close pseudoterminal handle in filter child. * modules/pam_filter/upperLOWER/upperLOWER.c (main): Use regular read() instead of pam_modutil_read() to allow for short reads. --- modules/pam_filter/pam_filter.c | 74 +++++++++++++----------------- modules/pam_filter/upperLOWER/upperLOWER.c | 6 +-- 2 files changed, 34 insertions(+), 46 deletions(-) (limited to 'modules') diff --git a/modules/pam_filter/pam_filter.c b/modules/pam_filter/pam_filter.c index 86bc172b..6b821efc 100644 --- a/modules/pam_filter/pam_filter.c +++ b/modules/pam_filter/pam_filter.c @@ -48,41 +48,18 @@ #include -#define TERMINAL_LEN 12 +#define DEV_PTMX "/dev/ptmx" static int -master (const pam_handle_t *pamh, char *terminal) -/* - * try to open all of the terminals in sequence return first free one, - * or -1 - */ +master (void) { - const char ptys[] = "pqrs", *pty = ptys; - const char hexs[] = "0123456789abcdef", *hex; - struct stat tstat; - int fd; - - strcpy(terminal, "/dev/pty??"); - - while (*pty) { /* step through four types */ - terminal[8] = *pty++; - terminal[9] = '0'; - if (stat(terminal,&tstat) < 0) { - pam_syslog(pamh, LOG_WARNING, - "unknown pseudo terminal: %s", terminal); - break; - } - for (hex = hexs; *hex; ) { /* step through 16 of these */ - terminal[9] = *hex++; - if ((fd = open(terminal, O_RDWR)) >= 0) { - return fd; - } - } - } - - /* no terminal found */ - - return -1; + int fd; + + if ((fd = open(DEV_PTMX, O_RDWR)) >= 0) { + return fd; + } + + return -1; } static int process_args(pam_handle_t *pamh @@ -279,7 +256,7 @@ set_filter (pam_handle_t *pamh, int flags UNUSED, int ctrl, const char **evp, const char *filtername) { int status=-1; - char terminal[TERMINAL_LEN]; + char* terminal = NULL; struct termios stored_mode; /* initial terminal mode settings */ int fd[2], child=0, child2=0, aterminal; @@ -299,7 +276,7 @@ set_filter (pam_handle_t *pamh, int flags UNUSED, int ctrl, /* open the master pseudo terminal */ - fd[0] = master(pamh,terminal); + fd[0] = master(); if (fd[0] < 0) { pam_syslog(pamh, LOG_CRIT, "no master terminal"); return PAM_AUTH_ERR; @@ -392,8 +369,27 @@ set_filter (pam_handle_t *pamh, int flags UNUSED, int ctrl, return PAM_ABORT; } + /* grant slave terminal */ + if (grantpt (fd[0]) < 0) { + pam_syslog(pamh, LOG_WARNING, "Cannot grant acccess to slave terminal"); + return PAM_ABORT; + } + + /* unlock slave terminal */ + if (unlockpt (fd[0]) < 0) { + pam_syslog(pamh, LOG_WARNING, "Cannot unlock slave terminal"); + return PAM_ABORT; + } + /* find slave's name */ - terminal[5] = 't'; /* want to open slave terminal */ + terminal = ptsname(fd[0]); /* returned value should not be freed */ + + if (terminal == NULL) { + pam_syslog(pamh, LOG_WARNING, + "Cannot get the name of the slave terminal: %m"); + return PAM_ABORT; + } + fd[1] = open(terminal, O_RDWR); close(fd[0]); /* process is the child -- uses line fd[1] */ @@ -412,7 +408,6 @@ set_filter (pam_handle_t *pamh, int flags UNUSED, int ctrl, close(fd[1]); return PAM_ABORT; } - } else { /* nothing to do for a simple stream socket */ @@ -450,13 +445,6 @@ set_filter (pam_handle_t *pamh, int flags UNUSED, int ctrl, return PAM_SUCCESS; } - /* - * process is the parent here. So we can close the application's - * input/output - */ - - close(fd[1]); - /* Clear out passwords... there is a security problem here in * that this process never executes pam_end. Consequently, any * other sensitive data in this process is *not* explicitly diff --git a/modules/pam_filter/upperLOWER/upperLOWER.c b/modules/pam_filter/upperLOWER/upperLOWER.c index 0ede4a0d..25e70a5a 100644 --- a/modules/pam_filter/upperLOWER/upperLOWER.c +++ b/modules/pam_filter/upperLOWER/upperLOWER.c @@ -89,7 +89,7 @@ int main(int argc, char **argv UNUSED) /* application errors */ if ( FD_ISSET(APPERR_FILENO,&readers) ) { - int got = pam_modutil_read(APPERR_FILENO, buffer, BUFSIZ); + int got = read(APPERR_FILENO, buffer, BUFSIZ); if (got <= 0) { break; } else { @@ -102,7 +102,7 @@ int main(int argc, char **argv UNUSED) } } } else if ( FD_ISSET(APPOUT_FILENO,&readers) ) { /* app output */ - int got = pam_modutil_read(APPOUT_FILENO, buffer, BUFSIZ); + int got = read(APPOUT_FILENO, buffer, BUFSIZ); if (got <= 0) { break; } else { @@ -117,7 +117,7 @@ int main(int argc, char **argv UNUSED) } if ( FD_ISSET(STDIN_FILENO, &readers) ) { /* user input */ - int got = pam_modutil_read(STDIN_FILENO, buffer, BUFSIZ); + int got = read(STDIN_FILENO, buffer, BUFSIZ); if (got < 0) { syslog(LOG_WARNING,"user input junked"); break; -- cgit v1.2.3 From d9719b48ab49957f5b983bfcfadf25d23e6674ed Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Tue, 2 Dec 2008 15:13:43 +0000 Subject: Relevant BUGIDs: Purpose of commit: new features Commit summary: --------------- 2008-12-02 Thorsten Kukuk * modules/pam_env/pam_env.c: Add support for user specific environment file. Based on a patch from Ubuntu. * modules/pam_env/pam_env.8.xml: Document new options. --- modules/pam_env/pam_env.8.xml | 39 +++++++++++ modules/pam_env/pam_env.c | 156 +++++++++++++++++++++++------------------- 2 files changed, 125 insertions(+), 70 deletions(-) (limited to 'modules') diff --git a/modules/pam_env/pam_env.8.xml b/modules/pam_env/pam_env.8.xml index 9e9a96a5..e8cd561b 100644 --- a/modules/pam_env/pam_env.8.xml +++ b/modules/pam_env/pam_env.8.xml @@ -34,6 +34,12 @@ readenv=0|1 + + user_envfile=env-file + + + user_readenv=0|1 + @@ -115,6 +121,33 @@ + + + + + + + + Indicate an alternative .pam_environment + file to override the default. This can be useful when different + services need different environments. The filename is relativ to + the user home directory. + + + + + + + + + + + Turns on or off the reading of the user specific environment + file. 0 is off, 1 is on. By default this option is on. + + + + @@ -179,6 +212,12 @@ Default environment file + + $HOME/.pam_environment + + User specific environment file + + diff --git a/modules/pam_env/pam_env.c b/modules/pam_env/pam_env.c index a8cd2c8f..395ada21 100644 --- a/modules/pam_env/pam_env.c +++ b/modules/pam_env/pam_env.c @@ -1,8 +1,6 @@ /* pam_env module */ /* - * $Id$ - * * Written by Dave Kinchlea 1997/01/31 * Inspired by Andrew Morgan , 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 @@ -38,6 +39,7 @@ #define PAM_SM_ACCOUNT /* "" */ #include +#include #include #include @@ -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) { @@ -702,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.")); @@ -746,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; } @@ -782,32 +810,20 @@ pam_sm_acct_mgmt (pam_handle_t *pamh UNUSED, int flags UNUSED, return PAM_SERVICE_ERR; } +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 -- cgit v1.2.3 From de63f0160c57494553e400aca215ffe316e946b7 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Tue, 2 Dec 2008 22:11:07 +0000 Subject: Relevant BUGIDs: bnc#448314 Purpose of commit: enhancement Commit summary: --------------- 2008-12-02 Michael Calmer * modules/pam_limits/limits.conf.5.xml: Document valid values for limits (bnc#448314). --- modules/pam_limits/limits.conf.5.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_limits/limits.conf.5.xml b/modules/pam_limits/limits.conf.5.xml index f831a909..aabcf2cc 100644 --- a/modules/pam_limits/limits.conf.5.xml +++ b/modules/pam_limits/limits.conf.5.xml @@ -229,6 +229,11 @@ + + All items support the values -1, + unlimited or infinity indicating no limit, + except for priority and nice. + In general, individual limits have priority over group limits, so if you impose no limits for admin group, but one of @@ -274,7 +279,8 @@ ftp hard nproc 0 pam_limits8, pam.d5, - pam8 + pam8, + getrlimit2 -- cgit v1.2.3 From f326d04ccd16631d57134487e56bb73074f0dd0e Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 3 Dec 2008 14:16:33 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-12-03 Thorsten Kukuk * doc/man/Makefile.am: Add pam_get_authtok.3.xml. * doc/man/pam_get_authtok.3.xml: New. * libpam/Makefile.am: Add pam_get_authtok.c. * libpam/libpam.map: Export pam_get_authtok. * libpam/pam_get_authtok.c: New. * libpam/pam_private.h: Add mod_argc and mod_argv to pam_handle. * libpam_include/security/pam_ext.h: Add pam_get_authtok prototype. * modules/pam_cracklib/pam_cracklib.c: Use pam_get_authtok. * modules/pam_pwhistory/pam_pwhistory.c: Likewise. * po/POTFILES.in: Add libpam/pam_get_authtok.c. * xtests/tst-pam_cracklib1.c: Adjust error codes. * modules/pam_timestamp/Makefile.am: Remove hmactest.c from EXTRA_DIST. * po/*.po: Regenerated. --- modules/pam_cracklib/pam_cracklib.c | 236 +++++++++------------------------- modules/pam_pwhistory/pam_pwhistory.c | 151 ++++++---------------- modules/pam_timestamp/Makefile.am | 2 +- 3 files changed, 102 insertions(+), 287 deletions(-) (limited to 'modules') diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c index 4b2052fc..398727e1 100644 --- a/modules/pam_cracklib/pam_cracklib.c +++ b/modules/pam_cracklib/pam_cracklib.c @@ -200,14 +200,6 @@ _pam_parse (pam_handle_t *pamh, struct cracklib_options *opt, /* Helper functions */ -/* use this to free strings. ESPECIALLY password strings */ -static char *_pam_delete(register char *xx) -{ - _pam_overwrite(xx); - free(xx); - return NULL; -} - /* * can't be a palindrome - like `R A D A R' or `M A D A M' */ @@ -624,183 +616,83 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, return PAM_SUCCESS; } else if (flags & PAM_UPDATE_AUTHTOK) { int retval; - char *token1, *token2, *resp; const void *oldtoken; + int tries; D(("do update")); - retval = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldtoken); - if (retval != PAM_SUCCESS) { - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh,LOG_ERR,"Can not get old passwd"); - oldtoken=NULL; - retval = PAM_SUCCESS; - } - - do { - /* - * make sure nothing inappropriate gets returned - */ - token1 = token2 = NULL; - - if (!options.retry_times) { - D(("returning %s because maxtries reached", - pam_strerror(pamh, retval))); - return retval; - } - /* Planned modus operandi: - * Get a passwd. - * Verify it against cracklib. - * If okay get it a second time. - * Check to be the same with the first one. - * set PAM_AUTHTOK and return - */ - - if (options.use_authtok == 1 || options.try_first_pass == 1) { - const void *item = NULL; - - retval = pam_get_item(pamh, PAM_AUTHTOK, &item); - if (retval != PAM_SUCCESS) { - /* very strange. */ - pam_syslog(pamh, LOG_ALERT, - "pam_get_item returned error to pam_cracklib"); - } else if (item != NULL) { /* we have a password! */ - token1 = x_strdup(item); - item = NULL; - options.use_authtok = 1; /* don't ask for the password again */ - } else { - retval = PAM_AUTHTOK_RECOVERY_ERR; /* didn't work */ - } - } - - if (options.use_authtok != 1) { - /* Prepare to ask the user for the first time */ - resp = NULL; - retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp, - PROMPT1, options.prompt_type, - options.prompt_type[0]?" ":""); - - if (retval == PAM_SUCCESS) { /* a good conversation */ - token1 = resp; - if (token1 == NULL) { - pam_syslog(pamh, LOG_NOTICE, - "could not recover authentication token 1"); - retval = PAM_AUTHTOK_RECOVERY_ERR; - } - } else { - retval = (retval == PAM_SUCCESS) ? - PAM_AUTHTOK_RECOVERY_ERR:retval ; - } - } + retval = pam_get_item (pamh, PAM_OLDAUTHTOK, &oldtoken); if (retval != PAM_SUCCESS) { - token1 = _pam_delete(token1); if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh,LOG_DEBUG,"unable to obtain a password"); - continue; + pam_syslog(pamh,LOG_ERR,"Can not get old passwd"); + oldtoken = NULL; } - D(("testing password, retval = %s", pam_strerror(pamh, retval))); - /* now test this passwd against cracklib */ - { - const char *crack_msg; - - D(("against cracklib")); - if ((crack_msg = FascistCheck(token1,options.cracklib_dictpath))) { - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh,LOG_DEBUG,"bad password: %s",crack_msg); - pam_error(pamh, _("BAD PASSWORD: %s"), crack_msg); - if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) - retval = PAM_AUTHTOK_ERR; - else - retval = PAM_SUCCESS; - } else { - /* check it for strength too... */ - D(("for strength")); - retval = _pam_unix_approve_pass (pamh, ctrl, &options, - oldtoken, token1); - if (retval != PAM_SUCCESS) { - if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) - retval = PAM_AUTHTOK_ERR; - else - retval = PAM_SUCCESS; - } - } + tries = 0; + while (tries < options.retry_times) { + const char *crack_msg; + const char *newtoken = NULL; + + + tries++; + + /* Planned modus operandi: + * Get a passwd. + * Verify it against cracklib. + * If okay get it a second time. + * Check to be the same with the first one. + * set PAM_AUTHTOK and return + */ + + retval = pam_get_authtok (pamh, PAM_AUTHTOK, &newtoken, NULL); + if (retval != PAM_SUCCESS) { + pam_syslog(pamh, LOG_ERR, "pam_get_authtok returned error: %s", + pam_strerror (pamh, retval)); + continue; + } else if (newtoken == NULL) { /* user aborted password change, quit */ + return PAM_AUTHTOK_ERR; + } + + D(("testing password")); + /* now test this passwd against cracklib */ + + D(("against cracklib")); + if ((crack_msg = FascistCheck (newtoken, options.cracklib_dictpath))) { + if (ctrl & PAM_DEBUG_ARG) + pam_syslog(pamh,LOG_DEBUG,"bad password: %s",crack_msg); + pam_error (pamh, _("BAD PASSWORD: %s"), crack_msg); + if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) + { + retval = PAM_AUTHTOK_ERR; + continue; + } + } + + /* check it for strength too... */ + D(("for strength")); + retval = _pam_unix_approve_pass (pamh, ctrl, &options, + oldtoken, newtoken); + if (retval != PAM_SUCCESS) { + if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK)) + { + retval = PAM_AUTHTOK_ERR; + continue; + } + } + return PAM_SUCCESS; } - D(("after testing: retval = %s", pam_strerror(pamh, retval))); - /* if cracklib/strength check said it is a bad passwd... */ - if ((retval != PAM_SUCCESS) && (retval != PAM_IGNORE)) { - int temp_unused; + D(("returning because maxtries reached")); - temp_unused = pam_set_item(pamh, PAM_AUTHTOK, NULL); - token1 = _pam_delete(token1); - continue; - } - - /* Now we have a good passwd. Ask for it once again */ - - if (options.use_authtok == 0) { - resp = NULL; - retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp, - PROMPT2, options.prompt_type, - options.prompt_type[0]?" ":""); - if (retval == PAM_SUCCESS) { /* a good conversation */ - token2 = resp; - if (token2 == NULL) { - pam_syslog(pamh,LOG_NOTICE, - "could not recover authentication token 2"); - retval = PAM_AUTHTOK_RECOVERY_ERR; - } - } - - /* No else, the a retval == PAM_SUCCESS path can change retval - to a failure code. */ - if (retval != PAM_SUCCESS) { - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh,LOG_DEBUG,"unable to obtain retyped password"); - token1 = _pam_delete(token1); - continue; - } - - /* Hopefully now token1 and token2 the same password ... */ - if (strcmp(token1,token2) != 0) { - /* tell the user */ - pam_error(pamh, "%s", MISTYPED_PASS); - token1 = _pam_delete(token1); - token2 = _pam_delete(token2); - pam_set_item(pamh, PAM_AUTHTOK, NULL); - if (ctrl & PAM_DEBUG_ARG) - pam_syslog(pamh,LOG_NOTICE,"Password mistyped"); - retval = PAM_AUTHTOK_RECOVERY_ERR; - continue; - } - - /* Yes, the password was typed correct twice - * we store this password as an item - */ - - { - const void *item = NULL; - - retval = pam_set_item(pamh, PAM_AUTHTOK, token1); - - /* clean up */ - token1 = _pam_delete(token1); - token2 = _pam_delete(token2); - - if ( (retval != PAM_SUCCESS) || - ((retval = pam_get_item(pamh, PAM_AUTHTOK, &item) - ) != PAM_SUCCESS) ) { - pam_syslog(pamh, LOG_CRIT, "error manipulating password"); - continue; - } - item = NULL; /* break link to password */ - return PAM_SUCCESS; - } - } + pam_set_item (pamh, PAM_AUTHTOK, NULL); - } while (options.retry_times--); + /* if we have only one try, we can use the real reason, + else say that there were too many tries. */ + if (options.retry_times > 1) + return PAM_MAXTRIES; + else + return retval; } else { if (ctrl & PAM_DEBUG_ARG) diff --git a/modules/pam_pwhistory/pam_pwhistory.c b/modules/pam_pwhistory/pam_pwhistory.c index 424be38e..c555ac39 100644 --- a/modules/pam_pwhistory/pam_pwhistory.c +++ b/modules/pam_pwhistory/pam_pwhistory.c @@ -58,17 +58,10 @@ #include "opasswd.h" -/* For Translators: "%s%s" could be replaced with " " or "". */ -#define NEW_PASSWORD_PROMPT _("New %s%spassword: ") -/* For Translators: "%s%s" could be replaced with " " or "". */ -#define AGAIN_PASSWORD_PROMPT _("Retype new %s%spassword: ") -#define MISTYPED_PASSWORD _("Sorry, passwords do not match.") - #define DEFAULT_BUFLEN 2048 struct options_t { int debug; - int use_authtok; int enforce_for_root; int remember; int tries; @@ -80,12 +73,12 @@ typedef struct options_t options_t; static void parse_option (pam_handle_t *pamh, const char *argv, options_t *options) { - if (strcasecmp (argv, "use_first_pass") == 0) + if (strcasecmp (argv, "try_first_pass") == 0) /* ignore */; else if (strcasecmp (argv, "use_first_pass") == 0) /* ignore */; else if (strcasecmp (argv, "use_authtok") == 0) - options->use_authtok = 1; + /* ignore, handled by pam_get_authtok */; else if (strcasecmp (argv, "debug") == 0) options->debug = 1; else if (strncasecmp (argv, "remember=", 9) == 0) @@ -115,10 +108,9 @@ PAM_EXTERN int pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) { struct passwd *pwd; - char *newpass; + const char *newpass; const char *user; - void *newpass_void; - int retval, tries; + int retval, tries; options_t options; memset (&options, 0, sizeof (options)); @@ -191,126 +183,57 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) return retval; } - retval = pam_get_item (pamh, PAM_AUTHTOK, (const void **) &newpass_void); - newpass = (char *) newpass_void; - if (retval != PAM_SUCCESS) - return retval; - if (options.debug) - { - if (newpass) - pam_syslog (pamh, LOG_DEBUG, "got new auth token"); - else - pam_syslog (pamh, LOG_DEBUG, "new auth token not set"); - } - - /* If we haven't been given a password yet, prompt for one... */ - if (newpass == NULL) + newpass = NULL; + tries = 0; + while ((newpass == NULL) && (tries < options.tries)) { - if (options.use_authtok) - /* We are not allowed to ask for a new password */ - return PAM_AUTHTOK_ERR; + retval = pam_get_authtok (pamh, PAM_AUTHTOK, &newpass, NULL); + if (retval != PAM_SUCCESS && retval != PAM_TRY_AGAIN) + return retval; + tries++; - tries = 0; + if (newpass == NULL || retval == PAM_TRY_AGAIN) + continue; - while ((newpass == NULL) && (tries++ < options.tries)) + if (options.debug) { - retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &newpass, - NEW_PASSWORD_PROMPT, options.prompt_type, - strlen (options.prompt_type) > 0?" ":""); - if (retval != PAM_SUCCESS) - { - _pam_drop (newpass); - if (retval == PAM_CONV_AGAIN) - retval = PAM_INCOMPLETE; - return retval; - } - - if (newpass == NULL) - { - /* We want to abort the password change */ - pam_error (pamh, _("Password change aborted.")); - return PAM_AUTHTOK_ERR; - } - - if (options.debug) - pam_syslog (pamh, LOG_DEBUG, "check against old password file"); - - if (check_old_password (pamh, user, newpass, - options.debug) != PAM_SUCCESS) - { - pam_error (pamh, - _("Password has been already used. Choose another.")); - _pam_overwrite (newpass); - _pam_drop (newpass); - if (tries >= options.tries) - { - if (options.debug) - pam_syslog (pamh, LOG_DEBUG, - "Aborted, too many tries"); - return PAM_MAXTRIES; - } - } + if (newpass) + pam_syslog (pamh, LOG_DEBUG, "got new auth token"); else - { - int failed; - char *new2; - - retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &new2, - AGAIN_PASSWORD_PROMPT, - options.prompt_type, - strlen (options.prompt_type) > 0?" ":""); - if (retval != PAM_SUCCESS) - return retval; - - if (new2 == NULL) - { /* Aborting password change... */ - pam_error (pamh, _("Password change aborted.")); - return PAM_AUTHTOK_ERR; - } - - failed = (strcmp (newpass, new2) != 0); - - _pam_overwrite (new2); - _pam_drop (new2); - - if (failed) - { - pam_error (pamh, MISTYPED_PASSWORD); - _pam_overwrite (newpass); - _pam_drop (newpass); - if (tries >= options.tries) - { - if (options.debug) - pam_syslog (pamh, LOG_DEBUG, - "Aborted, too many tries"); - return PAM_MAXTRIES; - } - } - } + pam_syslog (pamh, LOG_DEBUG, "got no auth token"); + } + + if (retval != PAM_SUCCESS || newpass == NULL) + { + if (retval == PAM_CONV_AGAIN) + retval = PAM_INCOMPLETE; + return retval; } - /* Remember new password */ - pam_set_item (pamh, PAM_AUTHTOK, (void *) newpass); - } - else /* newpass != NULL, we found an old password */ - { if (options.debug) - pam_syslog (pamh, LOG_DEBUG, "look in old password file"); + pam_syslog (pamh, LOG_DEBUG, "check against old password file"); if (check_old_password (pamh, user, newpass, options.debug) != PAM_SUCCESS) { pam_error (pamh, _("Password has been already used. Choose another.")); - /* We are only here, because old password was set. - So overwrite it, else it will be stored! */ + newpass = NULL; + /* Remove password item, else following module will use it */ pam_set_item (pamh, PAM_AUTHTOK, (void *) NULL); - - return PAM_AUTHTOK_ERR; + continue; } } - return PAM_SUCCESS; + if (newpass == NULL && tries >= options.tries) + { + if (options.debug) + pam_syslog (pamh, LOG_DEBUG, "Aborted, too many tries"); + return PAM_MAXTRIES; + } + + /* Remember new password */ + return pam_set_item (pamh, PAM_AUTHTOK, newpass); } diff --git a/modules/pam_timestamp/Makefile.am b/modules/pam_timestamp/Makefile.am index 373f483c..37cbabf9 100644 --- a/modules/pam_timestamp/Makefile.am +++ b/modules/pam_timestamp/Makefile.am @@ -9,7 +9,7 @@ XMLS = README.xml pam_timestamp.8.xml pam_timestamp_check.8.xml man_MANS = pam_timestamp.8 pam_timestamp_check.8 TESTS = tst-pam_timestamp hmacfile -EXTRA_DIST = $(man_MANS) hmactest.c $(XMLS) $(TESTS) +EXTRA_DIST = $(man_MANS) $(XMLS) $(TESTS) securelibdir = $(SECUREDIR) secureconfdir = $(SCONFIGDIR) -- cgit v1.2.3 From 300b741a23d95cd44fa391905d6edce8340c8fee Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 3 Dec 2008 14:19:47 +0000 Subject: Relevant BUGIDs: 2356400 Purpose of commit: bugfix Commit summary: --------------- 2008-12-03 Thorsten Kukuk * modules/pam_access/access.conf.5.xml: Replace 2001:4ca0 with 2001:db8:: [bug#2356400]. --- modules/pam_access/access.conf.5.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/pam_access/access.conf.5.xml b/modules/pam_access/access.conf.5.xml index 17185172..1b629afc 100644 --- a/modules/pam_access/access.conf.5.xml +++ b/modules/pam_access/access.conf.5.xml @@ -161,12 +161,12 @@ User john and foo should get access from IPv6 host address. - + : john foo : 2001:4ca0:0:101::1 + + : john foo : 2001:db8:0:101::1 User john should get access from IPv6 net/mask. - + : john : 2001:4ca0:0:101::/64 + + : john : 2001:db8:0:101::/64 Disallow console logins to all but the shutdown, sync and all -- cgit v1.2.3 From a1131337d71a61da5b3b5e129545d3257a709480 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Thu, 11 Dec 2008 19:41:49 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-12-10 Thorsten Kukuk * doc/man/pam_item_types_ext.inc.xml: Document PAM_AUTHTOK_TYPE. * libpam/pam_end.c (pam_end): Free authtok_type. * tests/tst-pam_get_item.c: Add PAM_AUTHTOK_TYPE as test case. * tests/tst-pam_set_item.c: Likewise. * libpam/pam_start.c (pam_start): Initialize xdisplay, xauth and authtok_type. * libpam/pam_get_authtok.c (pam_get_authtok): Rename "type" to "authtok_type". * modules/pam_cracklib/pam_cracklib.8.xml: Replace "type=" with "authtok_type=". * doc/man/pam_get_authtok.3.xml: Document authtok_type argument. * modules/pam_cracklib/pam_cracklib.c (pam_sm_chauthtok): Set type= argument as PAM_AUTHTOK_TYPE item. * libpam/pam_get_authtok.c (pam_get_authtok): If no type argument given, use PAM_AUTHTOK_TYPE item. * libpam/pam_item.c (pam_get_item): Fetch PAM_AUTHTOK_TYPE item. (pam_set_item): Store PAM_AUTHTOK_TYPE item. * libpam/pam_private.h: Add authtok_type to pam_handle. * libpam/include/security/_pam_types.h (PAM_AUTHTOK_TYPE): New. --- modules/pam_cracklib/pam_cracklib.8.xml | 6 +++--- modules/pam_cracklib/pam_cracklib.c | 18 ++++++------------ 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'modules') diff --git a/modules/pam_cracklib/pam_cracklib.8.xml b/modules/pam_cracklib/pam_cracklib.8.xml index 336da5dd..1c31e077 100644 --- a/modules/pam_cracklib/pam_cracklib.8.xml +++ b/modules/pam_cracklib/pam_cracklib.8.xml @@ -171,15 +171,15 @@ - + The default action is for the module to use the following prompts when requesting passwords: "New UNIX password: " and "Retype UNIX password: ". - The default word UNIX can - be replaced with this option. + The example word UNIX can + be replaced with this option, by default it is empty. diff --git a/modules/pam_cracklib/pam_cracklib.c b/modules/pam_cracklib/pam_cracklib.c index 398727e1..ba64aae2 100644 --- a/modules/pam_cracklib/pam_cracklib.c +++ b/modules/pam_cracklib/pam_cracklib.c @@ -99,11 +99,8 @@ struct cracklib_options { int low_credit; int oth_credit; int min_class; - int use_authtok; - int try_first_pass; int max_repeat; int reject_user; - char prompt_type[BUFSIZ]; const char *cracklib_dictpath; }; @@ -116,7 +113,6 @@ struct cracklib_options { #define CO_UP_CREDIT 1 #define CO_LOW_CREDIT 1 #define CO_OTH_CREDIT 1 -#define CO_USE_AUTHTOK 0 static int _pam_parse (pam_handle_t *pamh, struct cracklib_options *opt, @@ -133,7 +129,7 @@ _pam_parse (pam_handle_t *pamh, struct cracklib_options *opt, if (!strcmp(*argv,"debug")) ctrl |= PAM_DEBUG_ARG; else if (!strncmp(*argv,"type=",5)) - strncpy(opt->prompt_type, *argv+5, sizeof(opt->prompt_type) - 1); + pam_set_item (pamh, PAM_AUTHTOK_TYPE, *argv+5); else if (!strncmp(*argv,"retry=",6)) { opt->retry_times = strtol(*argv+6,&ep,10); if (!ep || (opt->retry_times < 1)) @@ -178,12 +174,14 @@ _pam_parse (pam_handle_t *pamh, struct cracklib_options *opt, opt->max_repeat = 0; } else if (!strncmp(*argv,"reject_username",15)) { opt->reject_user = 1; + } else if (!strncmp(*argv,"authtok_type",12)) { + /* for pam_get_authtok, ignore */; } else if (!strncmp(*argv,"use_authtok",11)) { - opt->use_authtok = 1; + /* for pam_get_authtok, ignore */; } else if (!strncmp(*argv,"use_first_pass",14)) { - opt->use_authtok = 1; + /* for pam_get_authtok, ignore */; } else if (!strncmp(*argv,"try_first_pass",14)) { - opt->try_first_pass = 1; + /* for pam_get_authtok, ignore */; } else if (!strncmp(*argv,"dictpath=",9)) { opt->cracklib_dictpath = *argv+9; if (!*(opt->cracklib_dictpath)) { @@ -193,7 +191,6 @@ _pam_parse (pam_handle_t *pamh, struct cracklib_options *opt, pam_syslog(pamh,LOG_ERR,"pam_parse: unknown option; %s",*argv); } } - opt->prompt_type[sizeof(opt->prompt_type) - 1] = '\0'; return ctrl; } @@ -602,9 +599,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, options.up_credit = CO_UP_CREDIT; options.low_credit = CO_LOW_CREDIT; options.oth_credit = CO_OTH_CREDIT; - options.use_authtok = CO_USE_AUTHTOK; - memset(options.prompt_type, 0, BUFSIZ); - strcpy(options.prompt_type,"UNIX"); options.cracklib_dictpath = CRACKLIB_DICTS; ctrl = _pam_parse(pamh, &options, argc, argv); -- cgit v1.2.3 From 54febaaeb968aa3d9aa85583cd49ff058c6e1368 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 12 Dec 2008 14:05:41 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-12-12 Tomas Mraz * modules/pam_tally2/pam_tally2.c (get_tally): Test for EACCES instead of EPERM. * modules/pam_tally2/pam_tally2.8.xml: Fix documentation. --- modules/pam_tally2/pam_tally2.8.xml | 2 +- modules/pam_tally2/pam_tally2.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'modules') diff --git a/modules/pam_tally2/pam_tally2.8.xml b/modules/pam_tally2/pam_tally2.8.xml index dc284a1d..a7a3fc47 100644 --- a/modules/pam_tally2/pam_tally2.8.xml +++ b/modules/pam_tally2/pam_tally2.8.xml @@ -370,7 +370,7 @@ xscreensaver. As this would make it impossible to share PAM configuration with such services the following workaround is used: If the data file cannot be opened because of insufficient permissions - (EPERM) the module returns + (EACCES) the module returns PAM_IGNORE. diff --git a/modules/pam_tally2/pam_tally2.c b/modules/pam_tally2/pam_tally2.c index 5924edf9..faa6942e 100644 --- a/modules/pam_tally2/pam_tally2.c +++ b/modules/pam_tally2/pam_tally2.c @@ -351,7 +351,7 @@ get_tally(pam_handle_t *pamh, uid_t uid, const char *filename, umask(oldmask); if ( !*tfile ) { #ifndef MAIN - if (save_errno == EPERM) { + if (save_errno == EACCES) { return PAM_IGNORE; /* called with insufficient access rights */ } #endif @@ -380,7 +380,7 @@ get_tally(pam_handle_t *pamh, uid_t uid, const char *filename, if (!(*tfile = fopen(filename, "r+"))) { #ifndef MAIN - if (errno == EPERM) /* called with insufficient access rights */ + if (errno == EACCES) /* called with insufficient access rights */ return PAM_IGNORE; #endif pam_syslog(pamh, LOG_ALERT, "Error opening %s for update: %m", filename); -- cgit v1.2.3 From 96377420e795eaa52f3d8017dfec557f8c5948a0 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Wed, 17 Dec 2008 13:49:42 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-12-17 Tomas Mraz * modules/pam_tty_audit/pam_tty_audit.c (pam_sm_open_session): Do not abort on unknown option. Avoid double free of old_status. (pam_sm_close_session): Use LOG_DEBUG for restored status message. --- modules/pam_tty_audit/pam_tty_audit.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'modules') diff --git a/modules/pam_tty_audit/pam_tty_audit.c b/modules/pam_tty_audit/pam_tty_audit.c index d57dbbe3..080f4950 100644 --- a/modules/pam_tty_audit/pam_tty_audit.c +++ b/modules/pam_tty_audit/pam_tty_audit.c @@ -240,7 +240,6 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv) else { pam_syslog (pamh, LOG_ERR, "unknown option `%s'", argv[i]); - return PAM_SESSION_ERR; } } if (command == CMD_NONE) @@ -265,7 +264,7 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv) new_status.enabled = (command == CMD_ENABLE ? 1 : 0); if (old_status->enabled == new_status.enabled) { - free (old_status); + open_only = 1; /* to clean up old_status */ goto ok_fd; } @@ -327,7 +326,7 @@ pam_sm_close_session (pam_handle_t *pamh, int flags, int argc, return PAM_SESSION_ERR; } close (fd); - pam_syslog (pamh, LOG_ERR, "restored status to %d", status->enabled); + pam_syslog (pamh, LOG_DEBUG, "restored status to %d", status->enabled); } return PAM_SUCCESS; } -- cgit v1.2.3 From 2fe275aed5c0c285781e6487242a9e4a13071e4f Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Wed, 17 Dec 2008 14:27:24 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2008-12-17 Tomas Mraz * modules/pam_tty_audit/pam_tty_audit.c (pam_sm_open_session): Do not abort on unknown option. Avoid double free of old_status. (pam_sm_close_session): Use LOG_DEBUG for restored status message. * configure.in: Test for getseuser(). * modules/pam_selinux/pam_selinux.c (pam_sm_open_session): Call getseuser() instead of getseuserbyname() if the function is available. --- modules/pam_selinux/pam_selinux.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'modules') diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c index e45d6f99..c6f887a6 100644 --- a/modules/pam_selinux/pam_selinux.c +++ b/modules/pam_selinux/pam_selinux.c @@ -577,11 +577,16 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, security_context_t* contextlist = NULL; int num_contexts = 0; int env_params = 0; - const char *username = NULL; + const char *username; + const void *void_username; const void *tty = NULL; char *seuser=NULL; char *level=NULL; security_context_t default_user_context=NULL; +#ifdef HAVE_GETSEUSER + const void *void_service; + const char *service; +#endif /* Parse arguments. */ for (i = 0; i < argc; i++) { @@ -623,12 +628,23 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, if (!(selinux_enabled = is_selinux_enabled()>0) ) return PAM_SUCCESS; - if (pam_get_item(pamh, PAM_USER, (void *) &username) != PAM_SUCCESS || - username == NULL) { + if (pam_get_item(pamh, PAM_USER, &void_username) != PAM_SUCCESS || + void_username == NULL) { return PAM_USER_UNKNOWN; } + username = void_username; + +#ifdef HAVE_GETSEUSER + if (pam_get_item(pamh, PAM_SERVICE, (void *) &void_service) != PAM_SUCCESS || + void_service == NULL) { + return PAM_SESSION_ERR; + } + service = void_service; - if (getseuserbyname(username, &seuser, &level)==0) { + if (getseuser(username, service, &seuser, &level) == 0) { +#else + if (getseuserbyname(username, &seuser, &level) == 0) { +#endif num_contexts = get_ordered_context_list_with_level(seuser, level, NULL, -- cgit v1.2.3 From b6935e26379d61916e59b0d66009b2352e8ce2e5 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Thu, 18 Dec 2008 13:09:36 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2008-12-18 Thorsten Kukuk * modules/pam_pwhistory/pam_pwhistory.c (parse_option): Rename type= option to authtok_type= (because of pam_get_authtok). * modules/pam_pwhistory/pam_pwhistory.8.xml: Likewise. --- modules/pam_pwhistory/pam_pwhistory.8.xml | 15 ++++++++------- modules/pam_pwhistory/pam_pwhistory.c | 6 ++---- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'modules') diff --git a/modules/pam_pwhistory/pam_pwhistory.8.xml b/modules/pam_pwhistory/pam_pwhistory.8.xml index f8c152ad..cc216707 100644 --- a/modules/pam_pwhistory/pam_pwhistory.8.xml +++ b/modules/pam_pwhistory/pam_pwhistory.8.xml @@ -34,7 +34,7 @@ retry=N - type=STRING + authtok_type=STRING @@ -124,15 +124,13 @@ - + - The default action is for the module to use the - following prompts when requesting passwords: - "New UNIX password: " and "Retype UNIX password: ". - The default word UNIX can - be replaced with this option. + See + pam_get_authtok3 + for more details. @@ -231,6 +229,9 @@ password required pam_unix.so use_authtok pam8 + + pam_get_authtok3 + diff --git a/modules/pam_pwhistory/pam_pwhistory.c b/modules/pam_pwhistory/pam_pwhistory.c index c555ac39..0f6ffca3 100644 --- a/modules/pam_pwhistory/pam_pwhistory.c +++ b/modules/pam_pwhistory/pam_pwhistory.c @@ -65,7 +65,6 @@ struct options_t { int enforce_for_root; int remember; int tries; - const char *prompt_type; }; typedef struct options_t options_t; @@ -97,8 +96,8 @@ parse_option (pam_handle_t *pamh, const char *argv, options_t *options) } else if (strcasecmp (argv, "enforce_for_root") == 0) options->enforce_for_root = 1; - else if (strncasecmp (argv, "type=", 5) == 0) - options->prompt_type = &argv[5]; + else if (strncasecmp (argv, "authtok_type=", 13) == 0) + { /* ignore, for pam_get_authtok */; } else pam_syslog (pamh, LOG_ERR, "pam_pwhistory: unknown option: %s", argv); } @@ -118,7 +117,6 @@ pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc, const char **argv) /* Set some default values, which could be overwritten later. */ options.remember = 10; options.tries = 1; - options.prompt_type = "UNIX"; /* Parse parameters for module */ for ( ; argc-- > 0; argv++) -- cgit v1.2.3 From 7b14630ef39e71f603aeca0c47edf2f384717176 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 19 Jan 2009 09:09:15 +0000 Subject: Relevant BUGIDs: rhbz#476784 Purpose of commit: new feature Commit summary: --------------- 2009-01-19 Tomas Mraz * modules/pam_mkhomedir/Makefile.am: Add mkhomedir_helper. * modules/pam_mkhomedir/mkhomedir_helper.8.xml: New file. Manual page for mkhomedir_helper. * modules/pam_mkhomedir/mkhomedir_helper.c: New file. Source for mkhomedir_helper. Most of the code moved from pam_mkhomedir.c. * modules/pam_mkhomedir/pam_mkhomedir.c (_pam_parse): Do not convert umask to integer. (rec_mkdir): Moved to mkhomedir_helper.c. (create_homedir): Just exec the helper. (pam_sm_open_session): Improve logging. --- modules/pam_mkhomedir/Makefile.am | 12 +- modules/pam_mkhomedir/mkhomedir_helper.8.xml | 78 +++++ modules/pam_mkhomedir/mkhomedir_helper.c | 422 +++++++++++++++++++++++++++ modules/pam_mkhomedir/pam_mkhomedir.c | 421 +++++--------------------- 4 files changed, 590 insertions(+), 343 deletions(-) create mode 100644 modules/pam_mkhomedir/mkhomedir_helper.8.xml create mode 100644 modules/pam_mkhomedir/mkhomedir_helper.c (limited to 'modules') diff --git a/modules/pam_mkhomedir/Makefile.am b/modules/pam_mkhomedir/Makefile.am index 7ed3a9f0..42031472 100644 --- a/modules/pam_mkhomedir/Makefile.am +++ b/modules/pam_mkhomedir/Makefile.am @@ -1,21 +1,23 @@ # # Copyright (c) 2005, 2006 Thorsten Kukuk +# Copyright (c) 2008 Red Hat, Inc. # CLEANFILES = *~ EXTRA_DIST = README $(MANS) $(XMLS) tst-pam_mkhomedir -man_MANS = pam_mkhomedir.8 +man_MANS = pam_mkhomedir.8 mkhomedir_helper.8 -XMLS = README.xml pam_mkhomedir.8.xml +XMLS = README.xml pam_mkhomedir.8.xml mkhomedir_helper.8.xml TESTS = tst-pam_mkhomedir securelibdir = $(SECUREDIR) secureconfdir = $(SCONFIGDIR) -AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include +AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ + -DMKHOMEDIR_HELPER=\"$(sbindir)/mkhomedir_helper\" AM_LDFLAGS = -no-undefined -avoid-version -module if HAVE_VERSIONING AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map @@ -25,6 +27,10 @@ securelib_LTLIBRARIES = pam_mkhomedir.la pam_mkhomedir_la_SOURCES = pam_mkhomedir.c pam_mkhomedir_la_LIBADD = -L$(top_builddir)/libpam -lpam +sbin_PROGRAMS = mkhomedir_helper +mkhomedir_helper_SOURCES = mkhomedir_helper.c +mkhomedir_helper_LDADD = -L$(top_builddir)/libpam -lpam + if ENABLE_REGENERATE_MAN noinst_DATA = README README: pam_mkhomedir.8.xml diff --git a/modules/pam_mkhomedir/mkhomedir_helper.8.xml b/modules/pam_mkhomedir/mkhomedir_helper.8.xml new file mode 100644 index 00000000..c834eddd --- /dev/null +++ b/modules/pam_mkhomedir/mkhomedir_helper.8.xml @@ -0,0 +1,78 @@ + + + + + + + mkhomedir_helper + 8 + Linux-PAM Manual + + + + mkhomedir_helper + Helper binary that creates home directories + + + + + mkhomedir_helper + + user + + + umask + + path-to-skel + + + + + + + + DESCRIPTION + + + mkhomedir_helper is a helper program for the + pam_mkhomedir module that creates home directories + and populates them with contents of the specified skel directory. + + + + The default value of umask is 0022 and the + default value of path-to-skel is + /etc/skel. + + + + The helper is separated from the module to not require direct access from + login SELinux domains to the contents of user home directories. The + SELinux domain transition happens when the module is executing the + mkhomedir_helper. + + + + The helper never touches home directories if they already exist. + + + + + SEE ALSO + + + pam_mkhomedir8 + + + + + + AUTHOR + + Written by Tomas Mraz based on the code originally in + pam_mkhomedir module. + + + + diff --git a/modules/pam_mkhomedir/mkhomedir_helper.c b/modules/pam_mkhomedir/mkhomedir_helper.c new file mode 100644 index 00000000..550a1354 --- /dev/null +++ b/modules/pam_mkhomedir/mkhomedir_helper.c @@ -0,0 +1,422 @@ +/* mkhomedir_helper - helper for pam_mkhomedir module + + Released under the GNU LGPL version 2 or later + + Copyright (c) Red Hat, Inc., 2009 + Originally written by Jason Gunthorpe Feb 1999 + Structure taken from pam_lastlogin by Andrew Morgan + 1996 + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static unsigned long u_mask = 0022; +static char skeldir[BUFSIZ] = "/etc/skel"; + +static int +rec_mkdir(const char *dir, mode_t mode) +{ + char *cp; + char *parent = strdup(dir); + + if (parent == NULL) + return 1; + + cp = strrchr(parent, '/'); + + if (cp != NULL && cp != parent) + { + struct stat st; + + *cp++ = '\0'; + if (stat(parent, &st) == -1 && errno == ENOENT) + if (rec_mkdir(parent, mode) != 0) + { + free(parent); + return 1; + } + } + + free(parent); + + if (mkdir(dir, mode) != 0 && errno != EEXIST) + return 1; + + return 0; +} + +/* Do the actual work of creating a home dir */ +static int +create_homedir(const struct passwd *pwd, + const char *source, const char *dest) +{ + char remark[BUFSIZ]; + DIR *d; + struct dirent *dent; + int retval = PAM_SESSION_ERR; + + /* Create the new directory */ + if (rec_mkdir(dest, 0755) != 0) + { + pam_syslog(NULL, LOG_ERR, "unable to create directory %s: %m", dest); + return PAM_PERM_DENIED; + } + + /* See if we need to copy the skel dir over. */ + if ((source == NULL) || (strlen(source) == 0)) + { + retval = PAM_SUCCESS; + goto go_out; + } + + /* Scan the directory */ + d = opendir(source); + if (d == NULL) + { + pam_syslog(NULL, LOG_DEBUG, "unable to read directory %s: %m", source); + retval = PAM_PERM_DENIED; + goto go_out; + } + + for (dent = readdir(d); dent != NULL; dent = readdir(d)) + { + int srcfd; + int destfd; + int res; + struct stat st; +#ifndef PATH_MAX + char *newsource = NULL, *newdest = NULL; + /* track length of buffers */ + int nslen = 0, ndlen = 0; + int slen = strlen(source), dlen = strlen(dest); +#else + char newsource[PATH_MAX], newdest[PATH_MAX]; +#endif + + /* Skip some files.. */ + if (strcmp(dent->d_name,".") == 0 || + strcmp(dent->d_name,"..") == 0) + continue; + + /* Determine what kind of file it is. */ +#ifndef PATH_MAX + nslen = slen + strlen(dent->d_name) + 2; + + if (nslen <= 0) + { + retval = PAM_BUF_ERR; + goto go_out; + } + + if ((newsource = malloc(nslen)) == NULL) + { + retval = PAM_BUF_ERR; + goto go_out; + } + + sprintf(newsource, "%s/%s", source, dent->d_name); +#else + snprintf(newsource, sizeof(newsource), "%s/%s", source, dent->d_name); +#endif + + if (lstat(newsource, &st) != 0) +#ifndef PATH_MAX + { + free(newsource); + newsource = NULL; + continue; + } +#else + continue; +#endif + + + /* We'll need the new file's name. */ +#ifndef PATH_MAX + ndlen = dlen + strlen(dent->d_name)+2; + + if (ndlen <= 0) + { + retval = PAM_BUF_ERR; + goto go_out; + } + + if ((newdest = malloc(ndlen)) == NULL) + { + free (newsource); + retval = PAM_BUF_ERR; + goto go_out; + } + + sprintf (newdest, "%s/%s", dest, dent->d_name); +#else + snprintf (newdest, sizeof (newdest), "%s/%s", dest, dent->d_name); +#endif + + /* If it's a directory, recurse. */ + if (S_ISDIR(st.st_mode)) + { + retval = create_homedir(pwd, newsource, newdest); + +#ifndef PATH_MAX + free(newsource); newsource = NULL; + free(newdest); newdest = NULL; +#endif + + if (retval != PAM_SUCCESS) + { + closedir(d); + goto go_out; + } + continue; + } + + /* If it's a symlink, create a new link. */ + if (S_ISLNK(st.st_mode)) + { + int pointedlen = 0; +#ifndef PATH_MAX + char *pointed = NULL; + { + int size = 100; + + while (1) { + pointed = malloc(size); + if (pointed == NULL) { + free(newsource); + free(newdest); + return PAM_BUF_ERR; + } + pointedlen = readlink(newsource, pointed, size); + if (pointedlen < 0) break; + if (pointedlen < size) break; + free(pointed); + size *= 2; + } + } + if (pointedlen < 0) + free(pointed); + else + pointed[pointedlen] = 0; +#else + char pointed[PATH_MAX]; + memset(pointed, 0, sizeof(pointed)); + + pointedlen = readlink(newsource, pointed, sizeof(pointed) - 1); +#endif + + if (pointedlen >= 0) { + if(symlink(pointed, newdest) == 0) + { + if (lchown(newdest, pwd->pw_uid, pwd->pw_gid) != 0) + { + pam_syslog(NULL, LOG_DEBUG, + "unable to change perms on link %s: %m", newdest); + closedir(d); +#ifndef PATH_MAX + free(pointed); + free(newsource); + free(newdest); +#endif + return PAM_PERM_DENIED; + } + } +#ifndef PATH_MAX + free(pointed); +#endif + } +#ifndef PATH_MAX + free(newsource); newsource = NULL; + free(newdest); newdest = NULL; +#endif + continue; + } + + /* If it's not a regular file, it's probably not a good idea to create + * the new device node, FIFO, or whatever it is. */ + if (!S_ISREG(st.st_mode)) + { +#ifndef PATH_MAX + free(newsource); newsource = NULL; + free(newdest); newdest = NULL; +#endif + continue; + } + + /* Open the source file */ + if ((srcfd = open(newsource, O_RDONLY)) < 0 || fstat(srcfd, &st) != 0) + { + pam_syslog(NULL, LOG_DEBUG, + "unable to open src file %s: %m", newsource); + closedir(d); + +#ifndef PATH_MAX + free(newsource); newsource = NULL; + free(newdest); newdest = NULL; +#endif + + return PAM_PERM_DENIED; + } + if (stat(newsource, &st) != 0) + { + pam_syslog(NULL, LOG_DEBUG, "unable to stat src file %s: %m", + newsource); + close(srcfd); + closedir(d); + +#ifndef PATH_MAX + free(newsource); newsource = NULL; + free(newdest); newdest = NULL; +#endif + + return PAM_PERM_DENIED; + } + + /* Open the dest file */ + if ((destfd = open(newdest, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) + { + pam_syslog(NULL, LOG_DEBUG, + "unable to open dest file %s: %m", newdest); + close(srcfd); + closedir(d); + +#ifndef PATH_MAX + free(newsource); newsource = NULL; + free(newdest); newdest = NULL; +#endif + return PAM_PERM_DENIED; + } + + /* Set the proper ownership and permissions for the module. We make + the file a+w and then mask it with the set mask. This preseves + execute bits */ + if (fchmod(destfd, (st.st_mode | 0222) & (~u_mask)) != 0 || + fchown(destfd, pwd->pw_uid, pwd->pw_gid) != 0) + { + pam_syslog(NULL, LOG_DEBUG, + "unable to change perms on copy %s: %m", newdest); + close(srcfd); + close(destfd); + closedir(d); + +#ifndef PATH_MAX + free(newsource); newsource = NULL; + free(newdest); newdest = NULL; +#endif + + return PAM_PERM_DENIED; + } + + /* Copy the file */ + do + { + res = pam_modutil_read(srcfd, remark, sizeof(remark)); + + if (res == 0) + continue; + + if (res > 0) { + if (pam_modutil_write(destfd, remark, res) == res) + continue; + } + + /* If we get here, pam_modutil_read returned a -1 or + pam_modutil_write returned something unexpected. */ + pam_syslog(NULL, LOG_DEBUG, "unable to perform IO: %m"); + close(srcfd); + close(destfd); + closedir(d); + +#ifndef PATH_MAX + free(newsource); newsource = NULL; + free(newdest); newdest = NULL; +#endif + + return PAM_PERM_DENIED; + } + while (res != 0); + close(srcfd); + close(destfd); + +#ifndef PATH_MAX + free(newsource); newsource = NULL; + free(newdest); newdest = NULL; +#endif + + } + closedir(d); + + retval = PAM_SUCCESS; + + go_out: + + if (chmod(dest, 0777 & (~u_mask)) != 0 || + chown(dest, pwd->pw_uid, pwd->pw_gid) != 0) + { + pam_syslog(NULL, LOG_DEBUG, + "unable to change perms on directory %s: %m", dest); + return PAM_PERM_DENIED; + } + + return retval; +} + +int +main(int argc, char *argv[]) +{ + const struct passwd *pwd; + struct stat st; + + if (argc < 2) { + fprintf(stderr, "Usage: %s [ []]\n", argv[0]); + return PAM_SESSION_ERR; + } + + pwd = getpwnam(argv[1]); + if (pwd == NULL) { + pam_syslog(NULL, LOG_ERR, "User unknown."); + return PAM_CRED_INSUFFICIENT; + } + + if (argc >= 3) { + char *eptr; + errno = 0; + u_mask = strtoul(argv[2], &eptr, 0); + if (errno != 0 || *eptr != '\0') { + pam_syslog(NULL, LOG_ERR, "Bogus umask value %s", argv[2]); + return PAM_SESSION_ERR; + } + } + + if (argc >= 4) { + if (strlen(argv[3]) >= sizeof(skeldir)) { + pam_syslog(NULL, LOG_ERR, "Too long skeldir path."); + return PAM_SESSION_ERR; + } + strcpy(skeldir, argv[3]); + } + + /* Stat the home directory, if something exists then we assume it is + correct and return a success */ + if (stat(pwd->pw_dir, &st) == 0) + return PAM_SUCCESS; + + return create_homedir(pwd, skeldir, pwd->pw_dir); +} + diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c index 44b092c1..a0c389c5 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.c +++ b/modules/pam_mkhomedir/pam_mkhomedir.c @@ -22,6 +22,7 @@ password required pam_unix.so Released under the GNU LGPL version 2 or later + Copyright (c) Red Hat, Inc. 2009 Originally written by Jason Gunthorpe Feb 1999 Structure taken from pam_lastlogin by Andrew Morgan 1996 @@ -29,18 +30,19 @@ #include "config.h" -#include #include #include -#include +#include +#include +#include #include #include #include #include #include #include -#include #include +#include /* * here, we make a definition for the externally accessible function @@ -56,12 +58,13 @@ #include #include +#define MAX_FD_NO 10000 /* argument parsing */ #define MKHOMEDIR_DEBUG 020 /* be verbose about things */ #define MKHOMEDIR_QUIET 040 /* keep quiet about things */ -static unsigned int UMask = 0022; +static char UMask[16] = "0022"; static char SkelDir[BUFSIZ] = "/etc/skel"; /* THIS MODULE IS NOT THREAD SAFE */ static int @@ -81,7 +84,8 @@ _pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv) } else if (!strcmp(*argv, "debug")) { ctrl |= MKHOMEDIR_DEBUG; } else if (!strncmp(*argv,"umask=",6)) { - UMask = strtol(*argv+6,0,0); + strncpy(SkelDir,*argv+6,sizeof(UMask)); + UMask[sizeof(UMask)-1] = '\0'; } else if (!strncmp(*argv,"skel=",5)) { strncpy(SkelDir,*argv+5,sizeof(SkelDir)); SkelDir[sizeof(SkelDir)-1] = '\0'; @@ -94,357 +98,88 @@ _pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv) return ctrl; } -static int -rec_mkdir (const char *dir, mode_t mode) -{ - char *cp; - char *parent = strdup (dir); - - if (parent == NULL) - return 1; - - cp = strrchr (parent, '/'); - - if (cp != NULL && cp != parent) - { - struct stat st; - - *cp++ = '\0'; - if (stat (parent, &st) == -1 && errno == ENOENT) - if (rec_mkdir (parent, mode) != 0) - { - free (parent); - return 1; - } - } - - free (parent); - - if (mkdir (dir, mode) != 0 && errno != EEXIST) - return 1; - - return 0; -} - /* Do the actual work of creating a home dir */ static int -create_homedir (pam_handle_t * pamh, int ctrl, - const struct passwd *pwd, - const char *source, const char *dest) +create_homedir (pam_handle_t *pamh, int ctrl, + const struct passwd *pwd) { - char remark[BUFSIZ]; - DIR *D; - struct dirent *Dir; - int retval = PAM_AUTH_ERR; + int retval, child; + void (*sighandler)(int) = NULL; /* Mention what is happening, if the notification fails that is OK */ - if ((ctrl & MKHOMEDIR_QUIET) != MKHOMEDIR_QUIET) - pam_info(pamh, _("Creating directory '%s'."), dest); - - /* Create the new directory */ - if (rec_mkdir (dest,0755) != 0) - { - pam_error(pamh, _("Unable to create directory %s: %m"), dest); - pam_syslog(pamh, LOG_ERR, "unable to create directory %s: %m", dest); - return PAM_PERM_DENIED; - } - - /* See if we need to copy the skel dir over. */ - if ((source == NULL) || (strlen(source) == 0)) - { - retval = PAM_SUCCESS; - goto go_out; - } - - /* Scan the directory */ - D = opendir (source); - if (D == 0) - { - pam_syslog(pamh, LOG_DEBUG, "unable to read directory %s: %m", source); - retval = PAM_PERM_DENIED; - goto go_out; - } - - for (Dir = readdir(D); Dir != 0; Dir = readdir(D)) - { - int SrcFd; - int DestFd; - int Res; - struct stat St; -#ifndef PATH_MAX - char *newsource = NULL, *newdest = NULL; - /* track length of buffers */ - int nslen = 0, ndlen = 0; - int slen = strlen(source), dlen = strlen(dest); -#else - char newsource[PATH_MAX], newdest[PATH_MAX]; -#endif - - /* Skip some files.. */ - if (strcmp(Dir->d_name,".") == 0 || - strcmp(Dir->d_name,"..") == 0) - continue; - - /* Determine what kind of file it is. */ -#ifndef PATH_MAX - nslen = slen + strlen(Dir->d_name) + 2; - - if (nslen <= 0) - { - retval = PAM_BUF_ERR; - goto go_out; - } - - if ((newsource = malloc (nslen)) == NULL) - { - retval = PAM_BUF_ERR; - goto go_out; - } + if (!(ctrl & MKHOMEDIR_QUIET)) + pam_info(pamh, _("Creating directory '%s'."), pwd->pw_dir); - sprintf(newsource, "%s/%s", source, Dir->d_name); -#else - snprintf(newsource,sizeof(newsource),"%s/%s",source,Dir->d_name); -#endif - if (lstat(newsource,&St) != 0) -#ifndef PATH_MAX - { - free(newsource); - newsource = NULL; - continue; - } -#else - continue; -#endif + D(("called.")); + /* + * This code arranges that the demise of the child does not cause + * the application to receive a signal it is not expecting - which + * may kill the application or worse. + */ + sighandler = signal(SIGCHLD, SIG_DFL); - /* We'll need the new file's name. */ -#ifndef PATH_MAX - ndlen = dlen + strlen(Dir->d_name)+2; + if (ctrl & MKHOMEDIR_DEBUG) { + pam_syslog(pamh, LOG_DEBUG, "Executing mkhomedir_helper."); + } - if (ndlen <= 0) - { - retval = PAM_BUF_ERR; - goto go_out; + /* fork */ + child = fork(); + if (child == 0) { + int i; + struct rlimit rlim; + static char *envp[] = { NULL }; + char *args[] = { NULL, NULL, NULL, NULL, NULL }; + + if (getrlimit(RLIMIT_NOFILE, &rlim)==0) { + if (rlim.rlim_max >= MAX_FD_NO) + rlim.rlim_max = MAX_FD_NO; + for (i=0; i < (int)rlim.rlim_max; i++) { + close(i); + } } - if ((newdest = malloc(ndlen)) == NULL) - { - free (newsource); - retval = PAM_BUF_ERR; - goto go_out; + /* exec the mkhomedir helper */ + args[0] = x_strdup(MKHOMEDIR_HELPER); + args[1] = pwd->pw_name; + args[2] = UMask; + args[3] = SkelDir; + + execve(MKHOMEDIR_HELPER, args, envp); + + /* should not get here: exit with error */ + D(("helper binary is not available")); + exit(PAM_SYSTEM_ERR); + } else if (child > 0) { + int rc; + while ((rc=waitpid(child, &retval, 0)) < 0 && errno == EINTR); + if (rc < 0) { + pam_syslog(pamh, LOG_ERR, "waitpid failed: %m"); + retval = PAM_SYSTEM_ERR; + } else { + retval = WEXITSTATUS(retval); } - - sprintf (newdest, "%s/%s", dest, Dir->d_name); -#else - snprintf (newdest,sizeof (newdest),"%s/%s",dest,Dir->d_name); -#endif - - /* If it's a directory, recurse. */ - if (S_ISDIR(St.st_mode)) - { - retval = create_homedir (pamh, ctrl, pwd, newsource, newdest); - -#ifndef PATH_MAX - free(newsource); newsource = NULL; - free(newdest); newdest = NULL; -#endif - - if (retval != PAM_SUCCESS) - { - closedir(D); - goto go_out; - } - continue; - } - - /* If it's a symlink, create a new link. */ - if (S_ISLNK(St.st_mode)) - { - int pointedlen = 0; -#ifndef PATH_MAX - char *pointed = NULL; - { - int size = 100; - - while (1) { - pointed = (char *) malloc(size); - if ( ! pointed ) { - free(newsource); - free(newdest); - return PAM_BUF_ERR; - } - pointedlen = readlink (newsource, pointed, size); - if ( pointedlen < 0 ) break; - if ( pointedlen < size ) break; - free (pointed); - size *= 2; - } - } - if ( pointedlen < 0 ) - free(pointed); - else - pointed[pointedlen] = 0; -#else - char pointed[PATH_MAX]; - memset(pointed, 0, sizeof(pointed)); - - pointedlen = readlink(newsource, pointed, sizeof(pointed) - 1); -#endif - - if ( pointedlen >= 0 ) { - if(symlink(pointed, newdest) == 0) - { - if (lchown(newdest,pwd->pw_uid,pwd->pw_gid) != 0) - { - pam_syslog(pamh, LOG_DEBUG, - "unable to change perms on link %s: %m", newdest); - closedir(D); -#ifndef PATH_MAX - free(pointed); - free(newsource); - free(newdest); -#endif - return PAM_PERM_DENIED; - } - } -#ifndef PATH_MAX - free(pointed); -#endif - } -#ifndef PATH_MAX - free(newsource); newsource = NULL; - free(newdest); newdest = NULL; -#endif - continue; - } - - /* If it's not a regular file, it's probably not a good idea to create - * the new device node, FIFO, or whatever it is. */ - if (!S_ISREG(St.st_mode)) - { -#ifndef PATH_MAX - free(newsource); newsource = NULL; - free(newdest); newdest = NULL; -#endif - continue; - } - - /* Open the source file */ - if ((SrcFd = open(newsource,O_RDONLY)) < 0 || fstat(SrcFd,&St) != 0) - { - pam_syslog(pamh, LOG_DEBUG, - "unable to open src file %s: %m", newsource); - closedir(D); - -#ifndef PATH_MAX - free(newsource); newsource = NULL; - free(newdest); newdest = NULL; -#endif - - return PAM_PERM_DENIED; - } - if (stat(newsource,&St) != 0) - { - pam_syslog(pamh, LOG_DEBUG, "unable to stat src file %s: %m", - newsource); - close(SrcFd); - closedir(D); - -#ifndef PATH_MAX - free(newsource); newsource = NULL; - free(newdest); newdest = NULL; -#endif - - return PAM_PERM_DENIED; - } - - /* Open the dest file */ - if ((DestFd = open(newdest,O_WRONLY | O_TRUNC | O_CREAT,0600)) < 0) - { - pam_syslog(pamh, LOG_DEBUG, - "unable to open dest file %s: %m", newdest); - close(SrcFd); - closedir(D); - -#ifndef PATH_MAX - free(newsource); newsource = NULL; - free(newdest); newdest = NULL; -#endif - return PAM_PERM_DENIED; - } - - /* Set the proper ownership and permissions for the module. We make - the file a+w and then mask it with the set mask. This preseves - execute bits */ - if (fchmod(DestFd,(St.st_mode | 0222) & (~UMask)) != 0 || - fchown(DestFd,pwd->pw_uid,pwd->pw_gid) != 0) - { - pam_syslog(pamh, LOG_DEBUG, - "unable to change perms on copy %s: %m", newdest); - close(SrcFd); - close(DestFd); - closedir(D); - -#ifndef PATH_MAX - free(newsource); newsource = NULL; - free(newdest); newdest = NULL; -#endif - - return PAM_PERM_DENIED; - } - - /* Copy the file */ - do - { - Res = pam_modutil_read(SrcFd,remark,sizeof(remark)); - - if (Res == 0) - continue; - - if (Res > 0) { - if (pam_modutil_write(DestFd,remark,Res) == Res) - continue; - } - - /* If we get here, pam_modutil_read returned a -1 or - pam_modutil_write returned something unexpected. */ - pam_syslog(pamh, LOG_DEBUG, "unable to perform IO: %m"); - close(SrcFd); - close(DestFd); - closedir(D); - -#ifndef PATH_MAX - free(newsource); newsource = NULL; - free(newdest); newdest = NULL; -#endif - - return PAM_PERM_DENIED; - } - while (Res != 0); - close(SrcFd); - close(DestFd); - -#ifndef PATH_MAX - free(newsource); newsource = NULL; - free(newdest); newdest = NULL; -#endif - + } else { + D(("fork failed")); + pam_syslog(pamh, LOG_ERR, "fork failed: %m"); + retval = PAM_SYSTEM_ERR; } - closedir(D); - retval = PAM_SUCCESS; + if (sighandler != SIG_ERR) { + (void) signal(SIGCHLD, sighandler); /* restore old signal handler */ + } - go_out: + if (ctrl & MKHOMEDIR_DEBUG) { + pam_syslog(pamh, LOG_DEBUG, "mkhomedir_helper returned %d", retval); + } - if (chmod(dest,0777 & (~UMask)) != 0 || - chown(dest,pwd->pw_uid,pwd->pw_gid) != 0) - { - pam_syslog(pamh, LOG_DEBUG, - "unable to change perms on directory %s: %m", dest); - return PAM_PERM_DENIED; + if (retval != PAM_SUCCESS && !(ctrl & MKHOMEDIR_QUIET)) { + pam_error(pamh, _("Unable to create and initialize directory '%s'."), + pwd->pw_dir); } + D(("returning %d", retval)); return retval; } @@ -466,7 +201,7 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, retval = pam_get_item(pamh, PAM_USER, &user); if (retval != PAM_SUCCESS || user == NULL || *(const char *)user == '\0') { - pam_syslog(pamh, LOG_NOTICE, "user unknown"); + pam_syslog(pamh, LOG_NOTICE, "Cannot obtain the user name."); return PAM_USER_UNKNOWN; } @@ -474,16 +209,22 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, pwd = pam_modutil_getpwnam (pamh, user); if (pwd == NULL) { + pam_syslog(pamh, LOG_NOTICE, "User unknown."); D(("couldn't identify user %s", user)); return PAM_CRED_INSUFFICIENT; } /* Stat the home directory, if something exists then we assume it is correct and return a success*/ - if (stat(pwd->pw_dir,&St) == 0) + if (stat(pwd->pw_dir, &St) == 0) { + if (ctrl & MKHOMEDIR_DEBUG) { + pam_syslog(pamh, LOG_DEBUG, "Home directory %s already exists.", + pwd->pw_dir); + } return PAM_SUCCESS; + } - return create_homedir(pamh,ctrl,pwd,SkelDir,pwd->pw_dir); + return create_homedir(pamh, ctrl, pwd); } /* Ignore */ -- cgit v1.2.3 From 2eb9c8be027c7b30dde7e8eaf8466434a0de3aa0 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Fri, 20 Feb 2009 13:27:12 +0000 Subject: Relevant BUGIDs: Purpose of commit: enhancement Commit summary: --------------- 2009-02-20 Thorsten Kukuk * modules/pam_limits/limits.conf.5.xml: Document that the kernel can refuse values out of range for the local system. * modules/pam_limits/pam_limits.c (setup_limits): Log if setrlimit fails. --- modules/pam_limits/limits.conf.5.xml | 14 +++++-- modules/pam_limits/pam_limits.c | 80 ++++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 6 deletions(-) (limited to 'modules') diff --git a/modules/pam_limits/limits.conf.5.xml b/modules/pam_limits/limits.conf.5.xml index aabcf2cc..a9757a7f 100644 --- a/modules/pam_limits/limits.conf.5.xml +++ b/modules/pam_limits/limits.conf.5.xml @@ -230,10 +230,17 @@ - All items support the values -1, + All items support the values -1, unlimited or infinity indicating no limit, except for priority and nice. + + If a hard limit or soft limit of a resource is set to a valid value, + but outside of the supported range of the local system, the system + may reject the new limit or unexpected behavior may occur. If the + control value required is used, the module will + reject the login if a limit could not be set. + In general, individual limits have priority over group limits, so if you impose no limits for admin group, but one of @@ -251,8 +258,8 @@ - after which the rest of the line is ignored. - The pam_limits module does its best to report configuration problems - found in its configuration file via + The pam_limits module does report configuration problems + found in its configuration file and errors via syslog3. @@ -281,6 +288,7 @@ ftp hard nproc 0 pam.d5, pam8, getrlimit2 + getrlimit3p diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c index f1e29b85..f446f9e3 100644 --- a/modules/pam_limits/pam_limits.c +++ b/modules/pam_limits/pam_limits.c @@ -42,7 +42,7 @@ #include #ifdef HAVE_LIBAUDIT -#include +#include #endif /* Module defines */ @@ -141,6 +141,73 @@ _pam_parse (const pam_handle_t *pamh, int argc, const char **argv, return ctrl; } +static const char * +rlimit2str (int i) +{ + switch (i) { + case RLIMIT_CPU: + return "cpu"; + break; + case RLIMIT_FSIZE: + return "fsize"; + break; + case RLIMIT_DATA: + return "data"; + break; + case RLIMIT_STACK: + return "stack"; + break; + case RLIMIT_CORE: + return "core"; + break; + case RLIMIT_RSS: + return "rss"; + break; + case RLIMIT_NPROC: + return "nproc"; + break; + case RLIMIT_NOFILE: + return "nofile"; + break; + case RLIMIT_MEMLOCK: + return "memlock"; + break; +#ifdef RLIMIT_AS + case RLIMIT_AS: + return "as"; + break; +#endif +#ifdef RLIMIT_LOCKS + case RLIMIT_LOCKS: + return "locks"; + break; +#endif +#ifdef RLIMIT_SIGPENDING + case RLIMIT_SIGPENDING: + return "sigpending"; + break; +#endif +#ifdef RLIMIT_MSGQUEUE + case RLIMIT_MSGQUEUE: + return "msgqueue"; + break; +#endif +#ifdef RLIMIT_NICE + case RLIMIT_NICE: + return "nice"; + break; +#endif +#ifdef RLIMIT_RTPRIO + case RLIMIT_RTPRIO: + return "rtprio"; + break; +#endif + default: + return "UNKNOWN"; + break; + } +} + #define LIMITED_OK 0 /* limit setting appeared to work */ #define LIMIT_ERR 1 /* error setting a limit */ @@ -416,8 +483,8 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type, if (int_value < -20) int_value = -20; rlimit_value = 20 - int_value; -#endif break; +#endif } if ( (limit_item != LIMIT_LOGIN) @@ -575,6 +642,8 @@ static int setup_limits(pam_handle_t *pamh, int retval = LIMITED_OK; for (i=0, status=LIMITED_OK; ilimits[i].supported) { /* skip it if its not known to the system */ continue; @@ -586,7 +655,11 @@ static int setup_limits(pam_handle_t *pamh, } if (pl->limits[i].limit.rlim_cur > pl->limits[i].limit.rlim_max) pl->limits[i].limit.rlim_cur = pl->limits[i].limit.rlim_max; - status |= setrlimit(i, &pl->limits[i].limit); + res = setrlimit(i, &pl->limits[i].limit); + if (res != 0) + pam_syslog(pamh, LOG_ERR, "Could not set limit for '%s': %m", + rlimit2str(i)); + status |= res; } if (status) { @@ -595,6 +668,7 @@ static int setup_limits(pam_handle_t *pamh, status = setpriority(PRIO_PROCESS, 0, pl->priority); if (status != 0) { + pam_syslog(pamh, LOG_ERR, "Could not set limit for PRIO_PROCESS: %m"); retval = LIMIT_ERR; } -- cgit v1.2.3 From 1376c1565abb318a5b4d086edd7f295ee3da6b13 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Wed, 25 Feb 2009 15:50:21 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2009-02-25 Tomas Mraz * xtests/access.conf: Add a line for name resolution test case. * xtests/tst-pam_access4.c (main): Set PAM_RHOST for testing the LOCAL keyword. Add a test case for name resolution. * modules/pam_access/pam_access.c (from_match): Move name resolution to network_netmask_match(). (network_netmask_match): Do a name resolution of the origin only if matching against a real network/netmask. --- modules/pam_access/pam_access.c | 154 +++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 79 deletions(-) (limited to 'modules') diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c index a5c6c6a5..ba8effe3 100644 --- a/modules/pam_access/pam_access.c +++ b/modules/pam_access/pam_access.c @@ -627,44 +627,10 @@ from_match (pam_handle_t *pamh UNUSED, char *tok, struct login_info *item) } freeaddrinfo (res); } - } else if (isipaddr(string, NULL, NULL) == YES) { + } else { /* Assume network/netmask with a IP of a host. */ if (network_netmask_match(pamh, tok, string, item->debug)) return YES; - } else { - /* Assume network/netmask with a name of a host. */ - struct addrinfo *res; - struct addrinfo hint; - - memset (&hint, '\0', sizeof (hint)); - hint.ai_flags = AI_CANONNAME; - hint.ai_family = AF_UNSPEC; - - if (getaddrinfo (string, NULL, &hint, &res) != 0) - return NO; - else - { - struct addrinfo *runp = res; - - while (runp != NULL) - { - char buf[INET6_ADDRSTRLEN]; - - inet_ntop (runp->ai_family, - runp->ai_family == AF_INET - ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr - : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr, - buf, sizeof (buf)); - - if (network_netmask_match(pamh, tok, buf, item->debug)) - { - freeaddrinfo (res); - return YES; - } - runp = runp->ai_next; - } - freeaddrinfo (res); - } } return NO; @@ -701,69 +667,99 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string, /* network_netmask_match - match a string against one token - * where string is an ip (v4,v6) address and tok represents - * whether a single ip (v4,v6) address or a network/netmask + * where string is a hostname or ip (v4,v6) address and tok + * represents either a single ip (v4,v6) address or a network/netmask */ static int network_netmask_match (pam_handle_t *pamh, const char *tok, const char *string, int debug) { - if (debug) + char *netmask_ptr; + char netmask_string[MAXHOSTNAMELEN + 1]; + int addr_type; + + if (debug) pam_syslog (pamh, LOG_DEBUG, "network_netmask_match: tok=%s, item=%s", tok, string); + /* OK, check if tok is of type addr/mask */ + if ((netmask_ptr = strchr(tok, '/')) != NULL) + { + long netmask = 0; - if (isipaddr(string, NULL, NULL) == YES) - { - char *netmask_ptr = NULL; - static char netmask_string[MAXHOSTNAMELEN + 1] = ""; - int addr_type; - - /* OK, check if tok is of type addr/mask */ - if ((netmask_ptr = strchr(tok, '/')) != NULL) - { - long netmask = 0; - - /* YES */ - *netmask_ptr = 0; - netmask_ptr++; + /* YES */ + *netmask_ptr = 0; + netmask_ptr++; - if (isipaddr(tok, &addr_type, NULL) == NO) - { /* no netaddr */ - return(NO); - } + if (isipaddr(tok, &addr_type, NULL) == NO) + { /* no netaddr */ + return NO; + } - /* check netmask */ - if (isipaddr(netmask_ptr, NULL, NULL) == NO) - { /* netmask as integre value */ - char *endptr = NULL; - netmask = strtol(netmask_ptr, &endptr, 0); - if ((endptr == NULL) || (*endptr != '\0')) + /* check netmask */ + if (isipaddr(netmask_ptr, NULL, NULL) == NO) + { /* netmask as integre value */ + char *endptr = NULL; + netmask = strtol(netmask_ptr, &endptr, 0); + if ((endptr == NULL) || (*endptr != '\0')) { /* invalid netmask value */ - return(NO); + return NO; } - if ((netmask < 0) || (netmask >= 128)) + if ((netmask < 0) || (netmask >= 128)) { /* netmask value out of range */ - return(NO); + return NO; } - netmask_ptr = number_to_netmask(netmask, addr_type, - netmask_string, MAXHOSTNAMELEN); - } - - /* Netmask is now an ipv4/ipv6 address. - * This works also if netmask_ptr is NULL. - */ - return (are_addresses_equal(string, tok, netmask_ptr)); + netmask_ptr = number_to_netmask(netmask, addr_type, + netmask_string, MAXHOSTNAMELEN); + } } - else + else /* NO, then check if it is only an addr */ - if (isipaddr(tok, NULL, NULL) == YES) - { /* check if they are the same, no netmask */ - return(are_addresses_equal(string, tok, NULL)); + if (isipaddr(tok, NULL, NULL) != YES) + { + return NO; } - } - return (NO); + if (isipaddr(string, NULL, NULL) != YES) + { + /* Assume network/netmask with a name of a host. */ + struct addrinfo *res; + struct addrinfo hint; + + memset (&hint, '\0', sizeof (hint)); + hint.ai_flags = AI_CANONNAME; + hint.ai_family = AF_UNSPEC; + + if (getaddrinfo (string, NULL, &hint, &res) != 0) + return NO; + else + { + struct addrinfo *runp = res; + + while (runp != NULL) + { + char buf[INET6_ADDRSTRLEN]; + + inet_ntop (runp->ai_family, + runp->ai_family == AF_INET + ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr + : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr, + buf, sizeof (buf)); + + if (are_addresses_equal(buf, tok, netmask_ptr)) + { + freeaddrinfo (res); + return YES; + } + runp = runp->ai_next; + } + freeaddrinfo (res); + } + } + else + return (are_addresses_equal(string, tok, netmask_ptr)); + + return NO; } -- cgit v1.2.3 From 48a26b6141fb6bf276208bc1a06f5105880e843e Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 25 Feb 2009 17:05:22 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2009-02-25 Thorsten Kukuk * libpam/pam_misc.c (_pam_StrTok): Use unsigned char instead of int. Reported by Marcus Granado. * tests/Makefile.am (TESTS): Add tst-pam_mkargv. * tests/tst-pam_mkargv.c (main): Test case for _pam_mkargv. * po/de.po: Update fuzzy translations. --- modules/pam_mkhomedir/.cvsignore | 2 ++ 1 file changed, 2 insertions(+) (limited to 'modules') diff --git a/modules/pam_mkhomedir/.cvsignore b/modules/pam_mkhomedir/.cvsignore index bd6faa7e..a0ad1aad 100644 --- a/modules/pam_mkhomedir/.cvsignore +++ b/modules/pam_mkhomedir/.cvsignore @@ -6,3 +6,5 @@ Makefile Makefile.in README pam_mkhomedir.8 +mkhomedir_helper +mkhomedir_helper.8 -- cgit v1.2.3 From 5891c5508e3b9ba699a6a6ba3dae9221a45528e5 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 26 Feb 2009 18:56:12 +0000 Subject: Relevant BUGIDs: debian#514437 rhbz#487216 Purpose of commit: bugfix Commit summary: --------------- 2009-02-26 Tomas Mraz * xtests/Makefile.am: Add tst-pam_unix4. * xtests/tst-pam_unix4.c: New test for password change and shadow min days limit. * xtests/tst-pam_unix4.pamd: Likewise. * xtests/tst-pam_unix4.sh: Likewise. * modules/pam_unix/pam_unix_acct.c (pam_sm_acct_mgmt): Ignore PAM_AUTHTOK_ERR on shadow verification. * modules/pam_unix/passverify.c (check_shadow_expiry): Return PAM_AUTHTOK_ERR if sp_min limit for password change is defied. --- modules/pam_unix/pam_unix_acct.c | 3 +++ modules/pam_unix/passverify.c | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index 3a40d8d3..40ff3c06 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -249,6 +249,9 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags, _make_remark(pamh, ctrl, PAM_ERROR_MSG, _("Your account has expired; please contact your system administrator")); break; + case PAM_AUTHTOK_ERR: + retval = PAM_SUCCESS; + /* fallthrough */ case PAM_SUCCESS: if (daysleft >= 0) { pam_syslog(pamh, LOG_DEBUG, diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 281716e0..360bd90b 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -272,8 +272,16 @@ PAMH_ARG_DECL(int check_shadow_expiry, *daysleft = (int)((spent->sp_lstchg + spent->sp_max) - curdays); D(("warn before expiry")); } + if ((curdays - spent->sp_lstchg < spent->sp_min) + && (spent->sp_min != -1)) { + /* + * The last password change was too recent. This error will be ignored + * if no password change is attempted. + */ + D(("password change too recent")); + return PAM_AUTHTOK_ERR; + } return PAM_SUCCESS; - } /* passwd/salt conversion macros */ -- cgit v1.2.3 From 42f4743cc3ca046833afcaeec01f9793d74bbfb4 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 27 Feb 2009 14:29:39 +0000 Subject: Relevant BUGIDs: Purpose of commit: new feature Commit summary: --------------- 2009-02-27 Tomas Mraz * modules/pam_mkhomedir/pam_mkhomedir.c(create_homedir): Replace signal() with sigaction(). * modules/pam_namespace/pam_namespace.c(inst_init, cleanup_tmpdirs): Likewise. * modules/pam_unix/pam_unix_acct.c(_unix_run_verify_binary): Likewise. * modules/pam_unix/pam_unix_passwd.c(_unix_run_update_binary): Likewise. * modules/pam_unix/passverify.c(su_sighandler): Likewise. * modules/pam_unix/support.c(_unix_run_helper_binary): Likewise. * modules/pam_tally2/Makefile.am: Link the pam_tally2 app to libpam for auxiliary functions. * modules/pam_tally2/pam_tally2.8.xml: Drop non-existing no_reset option. Document new serialize option. * modules/pam_tally2/pam_tally2.c: Add support for the new serialize option. (_cleanup, tally_set_data, tally_get_data): Add tally file handle to tally PAM data. Needed for fcntl() locking. (get_tally): Use low level file access instead of stdio buffered FILE. If serialize option is used lock the tally file access. (set_tally, tally_bump, tally_reset): Use low level file access instead of stdio buffered FILE. Close the file handle only when it is not owned by PAM data. (pam_sm_authenticate, pam_sm_setcred, pam_sm_acct_mgmt): Pass the tally file handle to tally_set_data(). Get it from tally_get_data(). (main): Use low level file access instead of stdio buffered FILE. --- modules/pam_mkhomedir/pam_mkhomedir.c | 12 +- modules/pam_namespace/pam_namespace.c | 24 ++-- modules/pam_tally2/Makefile.am | 2 +- modules/pam_tally2/pam_tally2.8.xml | 32 +++-- modules/pam_tally2/pam_tally2.c | 216 ++++++++++++++++++++++------------ modules/pam_unix/pam_unix_acct.c | 12 +- modules/pam_unix/pam_unix_passwd.c | 10 +- modules/pam_unix/passverify.c | 8 +- modules/pam_unix/support.c | 10 +- 9 files changed, 210 insertions(+), 116 deletions(-) (limited to 'modules') diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c index a0c389c5..1beb2d9f 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.c +++ b/modules/pam_mkhomedir/pam_mkhomedir.c @@ -104,7 +104,7 @@ create_homedir (pam_handle_t *pamh, int ctrl, const struct passwd *pwd) { int retval, child; - void (*sighandler)(int) = NULL; + struct sigaction newsa, oldsa; /* Mention what is happening, if the notification fails that is OK */ if (!(ctrl & MKHOMEDIR_QUIET)) @@ -118,8 +118,10 @@ create_homedir (pam_handle_t *pamh, int ctrl, * the application to receive a signal it is not expecting - which * may kill the application or worse. */ - sighandler = signal(SIGCHLD, SIG_DFL); - + memset(&newsa, '\0', sizeof(newsa)); + newsa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &newsa, &oldsa); + if (ctrl & MKHOMEDIR_DEBUG) { pam_syslog(pamh, LOG_DEBUG, "Executing mkhomedir_helper."); } @@ -166,9 +168,7 @@ create_homedir (pam_handle_t *pamh, int ctrl, retval = PAM_SYSTEM_ERR; } - if (sighandler != SIG_ERR) { - (void) signal(SIGCHLD, sighandler); /* restore old signal handler */ - } + sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */ if (ctrl & MKHOMEDIR_DEBUG) { pam_syslog(pamh, LOG_DEBUG, "mkhomedir_helper returned %d", retval); diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c index 89bc3686..7d668d9e 100644 --- a/modules/pam_namespace/pam_namespace.c +++ b/modules/pam_namespace/pam_namespace.c @@ -1157,15 +1157,15 @@ static int inst_init(const struct polydir_s *polyptr, const char *ipath, struct instance_data *idata, int newdir) { pid_t rc, pid; - sighandler_t osighand = NULL; + struct sigaction newsa, oldsa; int status; const char *init_script = NAMESPACE_INIT_SCRIPT; - osighand = signal(SIGCHLD, SIG_DFL); - if (osighand == SIG_ERR) { + memset(&newsa, '\0', sizeof(newsa)); + newsa.sa_handler = SIG_DFL; + if (sigaction(SIGCHLD, &newsa, &oldsa) == -1) { pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value"); - rc = PAM_SESSION_ERR; - goto out; + return PAM_SESSION_ERR; } if ((polyptr->flags & POLYDIR_ISCRIPT) && polyptr->init_script) @@ -1214,7 +1214,7 @@ static int inst_init(const struct polydir_s *polyptr, const char *ipath, } rc = PAM_SUCCESS; out: - (void) signal(SIGCHLD, osighand); + (void) sigaction(SIGCHLD, &oldsa, NULL); return rc; } @@ -1594,14 +1594,14 @@ static int cleanup_tmpdirs(struct instance_data *idata) { struct polydir_s *pptr; pid_t rc, pid; - sighandler_t osighand = NULL; + struct sigaction newsa, oldsa; int status; - osighand = signal(SIGCHLD, SIG_DFL); - if (osighand == SIG_ERR) { + memset(&newsa, '\0', sizeof(newsa)); + newsa.sa_handler = SIG_DFL; + if (sigaction(SIGCHLD, &newsa, &oldsa) == -1) { pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value"); - rc = PAM_SESSION_ERR; - goto out; + return PAM_SESSION_ERR; } for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) { @@ -1639,7 +1639,7 @@ static int cleanup_tmpdirs(struct instance_data *idata) rc = PAM_SUCCESS; out: - signal(SIGCHLD, osighand); + sigaction(SIGCHLD, &oldsa, NULL); return rc; } diff --git a/modules/pam_tally2/Makefile.am b/modules/pam_tally2/Makefile.am index 6f843e1f..06cdf554 100644 --- a/modules/pam_tally2/Makefile.am +++ b/modules/pam_tally2/Makefile.am @@ -25,7 +25,7 @@ if HAVE_VERSIONING pam_tally2_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map endif -pam_tally2_LDADD = $(LIBAUDIT) +pam_tally2_LDADD = -L$(top_builddir)/libpam -lpam $(LIBAUDIT) securelib_LTLIBRARIES = pam_tally2.la sbin_PROGRAMS = pam_tally2 diff --git a/modules/pam_tally2/pam_tally2.8.xml b/modules/pam_tally2/pam_tally2.8.xml index a7a3fc47..255fcea4 100644 --- a/modules/pam_tally2/pam_tally2.8.xml +++ b/modules/pam_tally2/pam_tally2.8.xml @@ -42,6 +42,9 @@ root_unlock_time=n + + serialize + audit @@ -244,16 +247,6 @@ - - - - - - - Don't reset count on successful entry, only decrement. - - - @@ -278,6 +271,23 @@ + + + + + + + Serialize access to the tally file using locks. This option might + be used only for non-multithreaded services because it depends on + the fcntl locking of the tally file. Also it is a good idea to use + this option only in such configurations where the time between auth + phase and account or setcred phase is not dependent on the + authenticating client. Otherwise the authenticating client will be + able to prevent simultaneous authentications by the same user by + simply artificially prolonging the time the file record lock is held. + + + @@ -431,7 +441,7 @@ session optional pam_mail.so standard AUTHOR - pam_tally was written by Tim Baverstock and Tomas Mraz. + pam_tally2 was written by Tim Baverstock and Tomas Mraz. diff --git a/modules/pam_tally2/pam_tally2.c b/modules/pam_tally2/pam_tally2.c index faa6942e..3490aa15 100644 --- a/modules/pam_tally2/pam_tally2.c +++ b/modules/pam_tally2/pam_tally2.c @@ -63,6 +63,9 @@ #include #include #include +#include +#include +#include #include "tallylog.h" #ifndef TRUE @@ -87,9 +90,9 @@ /* #define PAM_SM_SESSION */ /* #define PAM_SM_PASSWORD */ -#include #include #endif +#include #include /*---------------------------------------------------------------------*/ @@ -120,7 +123,9 @@ struct tally_options { #define OPT_QUIET 040 #define OPT_AUDIT 0100 #define OPT_NOLOGNOTICE 0400 +#define OPT_SERIALIZE 01000 +#define MAX_LOCK_WAITING_TIME 10 /*---------------------------------------------------------------------*/ @@ -188,6 +193,9 @@ tally_parse_args(pam_handle_t *pamh, struct tally_options *opts, else if ( ! strcmp( *argv, "magic_root" ) ) { opts->ctrl |= OPT_MAGIC_ROOT; } + else if ( ! strcmp( *argv, "serialize" ) ) { + opts->ctrl |= OPT_SERIALIZE; + } else if ( ! strcmp( *argv, "even_deny_root_account" ) || ! strcmp( *argv, "even_deny_root" ) ) { log_phase_no_auth(pamh, phase, *argv); @@ -291,34 +299,44 @@ pam_get_uid(pam_handle_t *pamh, uid_t *uid, const char **userp, struct tally_opt #ifndef MAIN +struct tally_data { + time_t time; + int tfile; +}; + static void -_cleanup(pam_handle_t *pamh UNUSED, void *data, int error_status UNUSED) +_cleanup(pam_handle_t *pamh UNUSED, void *void_data, int error_status UNUSED) { + struct tally_data *data = void_data; + if (data->tfile != -1) + close(data->tfile); free(data); } - static void -tally_set_data( pam_handle_t *pamh, time_t oldtime ) +tally_set_data( pam_handle_t *pamh, time_t oldtime, int tfile ) { - time_t *data; + struct tally_data *data; - if ( (data=malloc(sizeof(time_t))) != NULL ) { - *data = oldtime; + if ( (data=malloc(sizeof(*data))) != NULL ) { + data->time = oldtime; + data->tfile = tfile; pam_set_data(pamh, MODULE_NAME, (void *)data, _cleanup); } } static int -tally_get_data( pam_handle_t *pamh, time_t *oldtime ) +tally_get_data( pam_handle_t *pamh, time_t *oldtime, int *tfile ) { int rv; - const void *data; - - rv = pam_get_data(pamh, MODULE_NAME, &data); - if ( rv == PAM_SUCCESS && data != NULL && oldtime != NULL ) { - *oldtime = *(const time_t *)data; - pam_set_data(pamh, MODULE_NAME, NULL, NULL); + const void *void_data; + const struct tally_data *data; + + rv = pam_get_data(pamh, MODULE_NAME, &void_data); + if ( rv == PAM_SUCCESS && void_data != NULL && oldtime != NULL ) { + data = void_data; + *oldtime = data->time; + *tfile = data->tfile; } else { rv = -1; @@ -334,36 +352,44 @@ tally_get_data( pam_handle_t *pamh, time_t *oldtime ) /* If on entry tallyfile doesn't exist, creation is attempted. */ +static void +alarm_handler(int sig UNUSED) +{ /* we just need to ignore it */ +} + static int get_tally(pam_handle_t *pamh, uid_t uid, const char *filename, - FILE **tfile, struct tallylog *tally) + int *tfile, struct tallylog *tally, unsigned int ctrl) { struct stat fileinfo; int lstat_ret; + void *void_tally = tally; + int preopened = 0; + + if (*tfile != -1) { + preopened = 1; + goto skip_open; + } lstat_ret = lstat(filename, &fileinfo); if (lstat_ret) { - int save_errno; - int oldmask = umask(077); - *tfile=fopen(filename, "a"); - save_errno = errno; + *tfile=open(filename, O_APPEND|O_CREAT, 0700); /* Create file, or append-open in pathological case. */ - umask(oldmask); - if ( !*tfile ) { + if (*tfile == -1) { #ifndef MAIN - if (save_errno == EACCES) { + if (errno == EACCES) { return PAM_IGNORE; /* called with insufficient access rights */ } #endif - errno = save_errno; pam_syslog(pamh, LOG_ALERT, "Couldn't create %s: %m", filename); return PAM_AUTH_ERR; } - lstat_ret = fstat(fileno(*tfile),&fileinfo); - fclose(*tfile); - *tfile = NULL; + lstat_ret = fstat(*tfile, &fileinfo); + close(*tfile); } + *tfile = -1; + if ( lstat_ret ) { pam_syslog(pamh, LOG_ALERT, "Couldn't stat %s", filename); return PAM_AUTH_ERR; @@ -378,7 +404,7 @@ get_tally(pam_handle_t *pamh, uid_t uid, const char *filename, return PAM_AUTH_ERR; } - if (!(*tfile = fopen(filename, "r+"))) { + if ((*tfile = open(filename, O_RDWR)) == -1) { #ifndef MAIN if (errno == EACCES) /* called with insufficient access rights */ return PAM_IGNORE; @@ -388,16 +414,46 @@ get_tally(pam_handle_t *pamh, uid_t uid, const char *filename, return PAM_AUTH_ERR; } - if (fseeko(*tfile, (off_t)uid*(off_t)sizeof(*tally), SEEK_SET)) { - pam_syslog(pamh, LOG_ALERT, "fseek failed for %s: %m", filename); - fclose(*tfile); - *tfile = NULL; +skip_open: + if (lseek(*tfile, (off_t)uid*(off_t)sizeof(*tally), SEEK_SET) == (off_t)-1) { + pam_syslog(pamh, LOG_ALERT, "lseek failed for %s: %m", filename); + if (!preopened) { + close(*tfile); + *tfile = -1; + } return PAM_AUTH_ERR; } + if (!preopened && (ctrl & OPT_SERIALIZE)) { + /* this code is not thread safe as it uses fcntl locks and alarm() + so never use serialize with multithreaded services */ + struct sigaction newsa, oldsa; + unsigned int oldalarm; + int rv; + + memset(&newsa, '\0', sizeof(newsa)); + newsa.sa_handler = alarm_handler; + sigaction(SIGALRM, &newsa, &oldsa); + oldalarm = alarm(MAX_LOCK_WAITING_TIME); + + rv = lockf(*tfile, F_LOCK, sizeof(*tally)); + /* lock failure is not fatal, we attempt to read the tally anyway */ + + /* reinstate the eventual old alarm handler */ + if (rv == -1 && errno == EINTR) { + if (oldalarm > MAX_LOCK_WAITING_TIME) { + oldalarm -= MAX_LOCK_WAITING_TIME; + } else if (oldalarm > 0) { + oldalarm = 1; + } + } + sigaction(SIGALRM, &oldsa, NULL); + alarm(oldalarm); + } + if (fileinfo.st_size < (off_t)(uid+1)*(off_t)sizeof(*tally)) { memset(tally, 0, sizeof(*tally)); - } else if (fread(tally, sizeof(*tally), 1, *tfile) == 0) { + } else if (pam_modutil_read(*tfile, void_tally, sizeof(*tally)) != sizeof(*tally)) { memset(tally, 0, sizeof(*tally)); /* Shouldn't happen */ } @@ -409,29 +465,28 @@ get_tally(pam_handle_t *pamh, uid_t uid, const char *filename, /*---------------------------------------------------------------------*/ -/* --- Support function: update and close tallyfile with tally!=TALLY_HI --- */ +/* --- Support function: update tallyfile with tally!=TALLY_HI --- */ static int set_tally(pam_handle_t *pamh, uid_t uid, - const char *filename, FILE **tfile, struct tallylog *tally) + const char *filename, int *tfile, struct tallylog *tally) { + void *void_tally = tally; if (tally->fail_cnt != TALLY_HI) { - if (fseeko(*tfile, (off_t)uid * sizeof(*tally), SEEK_SET)) { - pam_syslog(pamh, LOG_ALERT, "fseek failed for %s: %m", filename); + if (lseek(*tfile, (off_t)uid * sizeof(*tally), SEEK_SET) == (off_t)-1) { + pam_syslog(pamh, LOG_ALERT, "lseek failed for %s: %m", filename); return PAM_AUTH_ERR; } - if (fwrite(tally, sizeof(*tally), 1, *tfile) == 0) { - pam_syslog(pamh, LOG_ALERT, "update (fwrite) failed for %s: %m", filename); + if (pam_modutil_write(*tfile, void_tally, sizeof(*tally)) != sizeof(*tally)) { + pam_syslog(pamh, LOG_ALERT, "update (write) failed for %s: %m", filename); return PAM_AUTH_ERR; } } - if (fclose(*tfile)) { - *tfile = NULL; - pam_syslog(pamh, LOG_ALERT, "update (fclose) failed for %s: %m", filename); + if (fsync(*tfile)) { + pam_syslog(pamh, LOG_ALERT, "update (fsync) failed for %s: %m", filename); return PAM_AUTH_ERR; } - *tfile=NULL; return PAM_SUCCESS; } @@ -566,20 +621,21 @@ cleanup: static int tally_bump (int inc, time_t *oldtime, pam_handle_t *pamh, - uid_t uid, const char *user, struct tally_options *opts) + uid_t uid, const char *user, struct tally_options *opts, int *tfile) { struct tallylog tally; tally_t oldcnt; - FILE *tfile = NULL; const void *remote_host = NULL; int i, rv; tally.fail_cnt = 0; /* !TALLY_HI --> Log opened for update */ - i = get_tally(pamh, uid, opts->filename, &tfile, &tally); + i = get_tally(pamh, uid, opts->filename, tfile, &tally, opts->ctrl); if (i != PAM_SUCCESS) { - if (tfile) - fclose(tfile); + if (*tfile != -1) { + close(*tfile); + *tfile = -1; + } RETURN_ERROR(i); } @@ -617,23 +673,28 @@ tally_bump (int inc, time_t *oldtime, pam_handle_t *pamh, rv = tally_check(oldcnt, *oldtime, pamh, uid, user, opts, &tally); - i = set_tally(pamh, uid, opts->filename, &tfile, &tally); + i = set_tally(pamh, uid, opts->filename, tfile, &tally); if (i != PAM_SUCCESS) { - if (tfile) - fclose(tfile); + if (*tfile != -1) { + close(*tfile); + *tfile = -1; + } if (rv == PAM_SUCCESS) RETURN_ERROR( i ); /* fallthrough */ + } else if (!(opts->ctrl & OPT_SERIALIZE)) { + close(*tfile); + *tfile = -1; } return rv; } static int -tally_reset (pam_handle_t *pamh, uid_t uid, struct tally_options *opts) +tally_reset (pam_handle_t *pamh, uid_t uid, struct tally_options *opts, int old_tfile) { struct tallylog tally; - FILE *tfile = NULL; + int tfile = old_tfile; int i; /* resets only if not magic root */ @@ -644,10 +705,10 @@ tally_reset (pam_handle_t *pamh, uid_t uid, struct tally_options *opts) tally.fail_cnt = 0; /* !TALLY_HI --> Log opened for update */ - i=get_tally(pamh, uid, opts->filename, &tfile, &tally); + i=get_tally(pamh, uid, opts->filename, &tfile, &tally, opts->ctrl); if (i != PAM_SUCCESS) { - if (tfile) - fclose(tfile); + if (tfile != old_tfile) /* the descriptor is not owned by pam data */ + close(tfile); RETURN_ERROR(i); } @@ -655,11 +716,14 @@ tally_reset (pam_handle_t *pamh, uid_t uid, struct tally_options *opts) i=set_tally(pamh, uid, opts->filename, &tfile, &tally); if (i != PAM_SUCCESS) { - if (tfile) - fclose(tfile); + if (tfile != old_tfile) /* the descriptor is not owned by pam data */ + close(tfile); RETURN_ERROR(i); } + if (tfile != old_tfile) + close(tfile); + return PAM_SUCCESS; } @@ -672,7 +736,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { int - rv; + rv, tfile = -1; time_t oldtime = 0; struct tally_options @@ -693,9 +757,9 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags UNUSED, if (rv != PAM_SUCCESS) RETURN_ERROR(rv); - rv = tally_bump(1, &oldtime, pamh, uid, user, opts); + rv = tally_bump(1, &oldtime, pamh, uid, user, opts, &tfile); - tally_set_data(pamh, oldtime); + tally_set_data(pamh, oldtime, tfile); return rv; } @@ -705,7 +769,7 @@ pam_sm_setcred(pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { int - rv; + rv, tfile = -1; time_t oldtime = 0; struct tally_options @@ -723,11 +787,15 @@ pam_sm_setcred(pam_handle_t *pamh, int flags UNUSED, if ( rv != PAM_SUCCESS ) RETURN_ERROR( rv ); - if ( tally_get_data(pamh, &oldtime) != 0 ) + if ( tally_get_data(pamh, &oldtime, &tfile) != 0 ) /* no data found */ return PAM_SUCCESS; - return tally_reset(pamh, uid, opts); + rv = tally_reset(pamh, uid, opts, tfile); + + pam_set_data(pamh, MODULE_NAME, NULL, NULL); + + return rv; } /*---------------------------------------------------------------------*/ @@ -741,7 +809,7 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { int - rv; + rv, tfile = -1; time_t oldtime = 0; struct tally_options @@ -759,11 +827,15 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags UNUSED, if ( rv != PAM_SUCCESS ) RETURN_ERROR( rv ); - if ( tally_get_data(pamh, &oldtime) != 0 ) + if ( tally_get_data(pamh, &oldtime, &tfile) != 0 ) /* no data found */ return PAM_SUCCESS; - return tally_reset(pamh, uid, opts); + rv = tally_reset(pamh, uid, opts, tfile); + + pam_set_data(pamh, MODULE_NAME, NULL, NULL); + + return rv; } /*-----------------------------------------------------------------------*/ @@ -895,7 +967,7 @@ main( int argc UNUSED, char **argv ) if ( cline_user ) { uid_t uid; - FILE *tfile=0; + int tfile = -1; struct tally_options opts; int i; @@ -907,10 +979,10 @@ main( int argc UNUSED, char **argv ) exit(1); } - i=get_tally(NULL, uid, cline_filename, &tfile, &tally); + i=get_tally(NULL, uid, cline_filename, &tfile, &tally, 0); if ( i != PAM_SUCCESS ) { - if (tfile) - fclose(tfile); + if (tfile != -1) + close(tfile); fprintf(stderr, "%s: %s\n", *argv, pam_errors(i)); exit(1); } @@ -934,13 +1006,13 @@ main( int argc UNUSED, char **argv ) tally.fail_cnt = cline_reset; } i=set_tally(NULL, uid, cline_filename, &tfile, &tally); + close(tfile); if (i != PAM_SUCCESS) { - if (tfile) fclose(tfile); fprintf(stderr,"%s: %s\n",*argv,pam_errors(i)); exit(1); } } else { - fclose(tfile); + close(tfile); } } else /* !cline_user (ie, operate on all users) */ { diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index 40ff3c06..f8698337 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -65,7 +65,7 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, const char *user, int *daysleft) { int retval=0, child, fds[2]; - void (*sighandler)(int) = NULL; + struct sigaction newsa, oldsa; D(("running verify_binary")); /* create a pipe for the messages */ @@ -85,7 +85,9 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, * The "noreap" module argument is provided so that the admin can * override this behavior. */ - sighandler = signal(SIGCHLD, SIG_DFL); + memset(&newsa, '\0', sizeof(newsa)); + newsa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &newsa, &oldsa); } /* fork */ @@ -158,9 +160,11 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, } close(fds[0]); } - if (sighandler != SIG_ERR) { - (void) signal(SIGCHLD, sighandler); /* restore old signal handler */ + + if (off(UNIX_NOREAP, ctrl)) { + sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */ } + D(("Returning %d",retval)); return retval; } diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index b8da9913..9386d87f 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -139,7 +139,7 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const const char *fromwhat, const char *towhat, int remember) { int retval, child, fds[2]; - void (*sighandler)(int) = NULL; + struct sigaction newsa, oldsa; D(("called.")); /* create a pipe for the password */ @@ -157,7 +157,9 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const * The "noreap" module argument is provided so that the admin can * override this behavior. */ - sighandler = signal(SIGCHLD, SIG_DFL); + memset(&newsa, '\0', sizeof(newsa)); + newsa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &newsa, &oldsa); } /* fork */ @@ -236,8 +238,8 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const retval = PAM_AUTH_ERR; } - if (sighandler != SIG_ERR) { - (void) signal(SIGCHLD, sighandler); /* restore old signal handler */ + if (off(UNIX_NOREAP, ctrl)) { + sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */ } return retval; diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 360bd90b..234e86dd 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -994,8 +994,12 @@ su_sighandler(int sig) { #ifndef SA_RESETHAND /* emulate the behaviour of the SA_RESETHAND flag */ - if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) - signal(sig, SIG_DFL); + if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) { + struct sigaction sa; + memset(&sa, '\0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + sigaction(sig, &sa, NULL); + } #endif if (sig > 0) { _exit(sig); diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index faec20dc..6e1bd454 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -408,7 +408,7 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, unsigned int ctrl, const char *user) { int retval, child, fds[2]; - void (*sighandler)(int) = NULL; + struct sigaction newsa, oldsa; D(("called.")); /* create a pipe for the password */ @@ -426,7 +426,9 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, * The "noreap" module argument is provided so that the admin can * override this behavior. */ - sighandler = signal(SIGCHLD, SIG_DFL); + memset(&newsa, '\0', sizeof(newsa)); + newsa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &newsa, &oldsa); } /* fork */ @@ -497,8 +499,8 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, retval = PAM_AUTH_ERR; } - if (sighandler != SIG_ERR) { - (void) signal(SIGCHLD, sighandler); /* restore old signal handler */ + if (off(UNIX_NOREAP, ctrl)) { + sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */ } D(("returning %d", retval)); -- cgit v1.2.3 From 5814c9064606215dca37b138a12822d66ca2b312 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 3 Mar 2009 08:10:53 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2009-03-03 Tomas Mraz * modules/pam_unix/pam_unix_acct.c(_unix_run_verify_binary): Test for abnormal exit of the helper binary. * modules/pam_unix/pam_unix_passwd.c(_unix_run_update_binary): Likewise. * modules/pam_unix/support.c(_unix_run_helper_binary): Likewise. * modules/pam_mkhomedir/pam_mkhomedir.c(create_homedir): Likewise. --- modules/pam_mkhomedir/pam_mkhomedir.c | 5 ++++- modules/pam_unix/pam_unix_acct.c | 3 +++ modules/pam_unix/pam_unix_passwd.c | 7 +++++-- modules/pam_unix/support.c | 3 +++ 4 files changed, 15 insertions(+), 3 deletions(-) (limited to 'modules') diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c index 1beb2d9f..419b525a 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.c +++ b/modules/pam_mkhomedir/pam_mkhomedir.c @@ -159,7 +159,10 @@ create_homedir (pam_handle_t *pamh, int ctrl, if (rc < 0) { pam_syslog(pamh, LOG_ERR, "waitpid failed: %m"); retval = PAM_SYSTEM_ERR; - } else { + } else if (!WIFEXITED(retval)) { + pam_syslog(pamh, LOG_ERR, "mkhomedir_helper abnormal exit: %d", retval); + retval = PAM_SYSTEM_ERR; + } else { retval = WEXITSTATUS(retval); } } else { diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index f8698337..4e119340 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -140,6 +140,9 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, if (rc<0) { pam_syslog(pamh, LOG_ERR, "unix_chkpwd waitpid returned %d: %m", rc); retval = PAM_AUTH_ERR; + } else if (!WIFEXITED(retval)) { + pam_syslog(pamh, LOG_ERR, "unix_chkpwd abnormal exit: %d", retval); + retval = PAM_AUTH_ERR; } else { retval = WEXITSTATUS(retval); rc = pam_modutil_read(fds[0], buf, sizeof(buf) - 1); diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index 9386d87f..ab1adda0 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -227,8 +227,11 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const rc=waitpid(child, &retval, 0); /* wait for helper to complete */ if (rc<0) { pam_syslog(pamh, LOG_ERR, "unix_update waitpid failed: %m"); - retval = PAM_AUTH_ERR; - } else { + retval = PAM_AUTHTOK_ERR; + } else if (!WIFEXITED(retval)) { + pam_syslog(pamh, LOG_ERR, "unix_update abnormal exit: %d", retval); + retval = PAM_AUTHTOK_ERR; + } else { retval = WEXITSTATUS(retval); } } else { diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 6e1bd454..dda617a0 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -489,6 +489,9 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, if (rc<0) { pam_syslog(pamh, LOG_ERR, "unix_chkpwd waitpid returned %d: %m", rc); retval = PAM_AUTH_ERR; + } else if (!WIFEXITED(retval)) { + pam_syslog(pamh, LOG_ERR, "unix_chkpwd abnormal exit: %d", retval); + retval = PAM_AUTH_ERR; } else { retval = WEXITSTATUS(retval); } -- cgit v1.2.3 From 1e56491f0e1cbd07fc0eb0fbfdf5982eced366a6 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 24 Mar 2009 16:33:21 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2009-03-24 Tomas Mraz * modules/pam_unix/passverify.c(save_old_password): Call fflush() and fsync(). (unix_update_passwd, unix_update_shadow): Likewise. * modules/pam_pwhistory/opasswd.c(save_old_password): Likewise. --- modules/pam_pwhistory/opasswd.c | 9 +++++++++ modules/pam_unix/passverify.c | 21 ++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) (limited to 'modules') diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c index fd4cd251..dbcd04e3 100644 --- a/modules/pam_pwhistory/opasswd.c +++ b/modules/pam_pwhistory/opasswd.c @@ -452,6 +452,15 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid, goto error_opasswd; } + if (fflush (newpf) != 0 || fsync (fileno (newpf)) != 0) + { + pam_syslog (pamh, LOG_ERR, + "Error while syncing temporary opasswd file: %m"); + retval = PAM_AUTHTOK_ERR; + fclose (newpf); + goto error_opasswd; + } + if (fclose (newpf) != 0) { pam_syslog (pamh, LOG_ERR, diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 234e86dd..0575f657 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -680,8 +680,13 @@ save_old_password(pam_handle_t *pamh, const char *forwho, const char *oldpass, } } + if (fflush(pwfile) || fsync(fileno(pwfile))) { + D(("fflush or fsync error writing entries to old passwords file: %m")); + err = 1; + } + if (fclose(pwfile)) { - D(("error writing entries to old passwords file: %m")); + D(("fclose error writing entries to old passwords file: %m")); err = 1; } @@ -795,8 +800,13 @@ PAMH_ARG_DECL(int unix_update_passwd, } fclose(opwfile); + if (fflush(pwfile) || fsync(fileno(pwfile))) { + D(("fflush or fsync error writing entries to password file: %m")); + err = 1; + } + if (fclose(pwfile)) { - D(("error writing entries to password file: %m")); + D(("fclose error writing entries to password file: %m")); err = 1; } @@ -916,8 +926,13 @@ PAMH_ARG_DECL(int unix_update_shadow, } fclose(opwfile); + if (fflush(pwfile) || fsync(fileno(pwfile))) { + D(("fflush or fsync error writing entries to shadow file: %m")); + err = 1; + } + if (fclose(pwfile)) { - D(("error writing entries to shadow file: %m")); + D(("fclose error writing entries to shadow file: %m")); err = 1; } -- cgit v1.2.3 From fd1b9361a937f8b565d0d55179da359122e1fc96 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 25 Mar 2009 10:54:23 +0000 Subject: Relevant BUGIDs: 2487654 Purpose of commit: bugfix Commit summary: --------------- 2009-03-25 Thorsten Kukuk * modules/pam_mkhomedir/pam_mkhomedir.c: Make option handling reentrant (#2487654) (_pam_parse): Fix umask option. * modules/pam_unix/passverify.c: Fix typo. * modules/pam_issue/pam_issue.c: Fix compiler warning. * modules/pam_ftp/pam_ftp.c: Likewise. --- modules/pam_ftp/pam_ftp.c | 2 +- modules/pam_issue/pam_issue.c | 2 +- modules/pam_mkhomedir/pam_mkhomedir.c | 57 ++++++++++++++++++----------------- modules/pam_unix/passverify.c | 2 +- 4 files changed, 33 insertions(+), 30 deletions(-) (limited to 'modules') diff --git a/modules/pam_ftp/pam_ftp.c b/modules/pam_ftp/pam_ftp.c index 7c546511..a124795b 100644 --- a/modules/pam_ftp/pam_ftp.c +++ b/modules/pam_ftp/pam_ftp.c @@ -172,7 +172,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, /* XXX: Some effort should be made to verify this email address! */ if (!(ctrl & PAM_IGNORE_EMAIL)) { - char *sptr; + char *sptr = NULL; token = strtok_r(resp, "@", &sptr); retval = pam_set_item(pamh, PAM_RUSER, token); diff --git a/modules/pam_issue/pam_issue.c b/modules/pam_issue/pam_issue.c index 7a8a24d5..060baada 100644 --- a/modules/pam_issue/pam_issue.c +++ b/modules/pam_issue/pam_issue.c @@ -145,7 +145,7 @@ read_issue_raw(pam_handle_t *pamh, FILE *fp, char **prompt) return PAM_BUF_ERR; } - if (fread(issue, 1, st.st_size, fp) != st.st_size) { + if ((off_t)fread(issue, 1, st.st_size, fp) != st.st_size) { pam_syslog(pamh, LOG_ERR, "read error: %m"); _pam_drop(issue); return PAM_SERVICE_ERR; diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c index 419b525a..b81708f2 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.c +++ b/modules/pam_mkhomedir/pam_mkhomedir.c @@ -64,50 +64,52 @@ #define MKHOMEDIR_DEBUG 020 /* be verbose about things */ #define MKHOMEDIR_QUIET 040 /* keep quiet about things */ -static char UMask[16] = "0022"; -static char SkelDir[BUFSIZ] = "/etc/skel"; /* THIS MODULE IS NOT THREAD SAFE */ +struct options_t { + int ctrl; + const char *umask; + const char *skeldir; +}; +typedef struct options_t options_t; -static int -_pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv) +static void +_pam_parse (const pam_handle_t *pamh, int flags, int argc, const char **argv, + options_t *opt) { - int ctrl = 0; + opt->ctrl = 0; + opt->umask = "0022"; + opt->skeldir = "/etc/skel"; /* does the appliction require quiet? */ if ((flags & PAM_SILENT) == PAM_SILENT) - ctrl |= MKHOMEDIR_QUIET; + opt->ctrl |= MKHOMEDIR_QUIET; /* step through arguments */ for (; argc-- > 0; ++argv) { if (!strcmp(*argv, "silent")) { - ctrl |= MKHOMEDIR_QUIET; + opt->ctrl |= MKHOMEDIR_QUIET; } else if (!strcmp(*argv, "debug")) { - ctrl |= MKHOMEDIR_DEBUG; + opt->ctrl |= MKHOMEDIR_DEBUG; } else if (!strncmp(*argv,"umask=",6)) { - strncpy(SkelDir,*argv+6,sizeof(UMask)); - UMask[sizeof(UMask)-1] = '\0'; + opt->umask = *argv+6; } else if (!strncmp(*argv,"skel=",5)) { - strncpy(SkelDir,*argv+5,sizeof(SkelDir)); - SkelDir[sizeof(SkelDir)-1] = '\0'; + opt->skeldir = *argv+5; } else { pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); } } - - D(("ctrl = %o", ctrl)); - return ctrl; } /* Do the actual work of creating a home dir */ static int -create_homedir (pam_handle_t *pamh, int ctrl, +create_homedir (pam_handle_t *pamh, options_t *opt, const struct passwd *pwd) { int retval, child; struct sigaction newsa, oldsa; /* Mention what is happening, if the notification fails that is OK */ - if (!(ctrl & MKHOMEDIR_QUIET)) + if (!(opt->ctrl & MKHOMEDIR_QUIET)) pam_info(pamh, _("Creating directory '%s'."), pwd->pw_dir); @@ -121,8 +123,8 @@ create_homedir (pam_handle_t *pamh, int ctrl, memset(&newsa, '\0', sizeof(newsa)); newsa.sa_handler = SIG_DFL; sigaction(SIGCHLD, &newsa, &oldsa); - - if (ctrl & MKHOMEDIR_DEBUG) { + + if (opt->ctrl & MKHOMEDIR_DEBUG) { pam_syslog(pamh, LOG_DEBUG, "Executing mkhomedir_helper."); } @@ -145,8 +147,8 @@ create_homedir (pam_handle_t *pamh, int ctrl, /* exec the mkhomedir helper */ args[0] = x_strdup(MKHOMEDIR_HELPER); args[1] = pwd->pw_name; - args[2] = UMask; - args[3] = SkelDir; + args[2] = x_strdup(opt->umask); + args[3] = x_strdup(opt->skeldir); execve(MKHOMEDIR_HELPER, args, envp); @@ -173,11 +175,11 @@ create_homedir (pam_handle_t *pamh, int ctrl, sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */ - if (ctrl & MKHOMEDIR_DEBUG) { + if (opt->ctrl & MKHOMEDIR_DEBUG) { pam_syslog(pamh, LOG_DEBUG, "mkhomedir_helper returned %d", retval); } - if (retval != PAM_SUCCESS && !(ctrl & MKHOMEDIR_QUIET)) { + if (retval != PAM_SUCCESS && !(opt->ctrl & MKHOMEDIR_QUIET)) { pam_error(pamh, _("Unable to create and initialize directory '%s'."), pwd->pw_dir); } @@ -192,13 +194,14 @@ PAM_EXTERN int pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv) { - int retval, ctrl; + int retval; + options_t opt; const void *user; const struct passwd *pwd; struct stat St; /* Parse the flag values */ - ctrl = _pam_parse(pamh, flags, argc, argv); + _pam_parse(pamh, flags, argc, argv, &opt); /* Determine the user name so we can get the home directory */ retval = pam_get_item(pamh, PAM_USER, &user); @@ -220,14 +223,14 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, /* Stat the home directory, if something exists then we assume it is correct and return a success*/ if (stat(pwd->pw_dir, &St) == 0) { - if (ctrl & MKHOMEDIR_DEBUG) { + if (opt.ctrl & MKHOMEDIR_DEBUG) { pam_syslog(pamh, LOG_DEBUG, "Home directory %s already exists.", pwd->pw_dir); } return PAM_SUCCESS; } - return create_homedir(pamh, ctrl, pwd); + return create_homedir(pamh, &opt, pwd); } /* Ignore */ diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c index 0575f657..8cf95c33 100644 --- a/modules/pam_unix/passverify.c +++ b/modules/pam_unix/passverify.c @@ -1011,7 +1011,7 @@ su_sighandler(int sig) /* emulate the behaviour of the SA_RESETHAND flag */ if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) { struct sigaction sa; - memset(&sa, '\0, sizeof(sa)); + memset(&sa, '\0', sizeof(sa)); sa.sa_handler = SIG_DFL; sigaction(sig, &sa, NULL); } -- cgit v1.2.3 From 5182ea70c8425d302c31386a325b869fcfef9671 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Fri, 27 Mar 2009 10:46:11 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2009-03-27 Thorsten Kukuk * modules/pam_unix/support.c (_unix_run_helper_binary): Don't ignore return value of write(). * libpamc/include/security/pam_client.h (PAM_BP_ASSERT): Honour NDEBUG. * modules/pam_timestamp/pam_timestamp.c: don't ignore return values of lchown and fchown. --- modules/pam_ftp/pam_ftp.c | 2 +- modules/pam_timestamp/pam_timestamp.c | 31 +++++++++++++++++++++++-------- modules/pam_unix/support.c | 20 ++++++++++++++------ 3 files changed, 38 insertions(+), 15 deletions(-) (limited to 'modules') diff --git a/modules/pam_ftp/pam_ftp.c b/modules/pam_ftp/pam_ftp.c index a124795b..896a1dda 100644 --- a/modules/pam_ftp/pam_ftp.c +++ b/modules/pam_ftp/pam_ftp.c @@ -79,7 +79,7 @@ static int lookup(const char *name, const char *list, const char **_user) if (list && *list) { const char *l; char *list_copy, *x; - char *sptr; + char *sptr = NULL; list_copy = x_strdup(list); x = list_copy; diff --git a/modules/pam_timestamp/pam_timestamp.c b/modules/pam_timestamp/pam_timestamp.c index 8a01c6f3..7e6c4b0b 100644 --- a/modules/pam_timestamp/pam_timestamp.c +++ b/modules/pam_timestamp/pam_timestamp.c @@ -194,7 +194,7 @@ timestamp_good(time_t then, time_t now, time_t interval) } static int -check_login_time(const char *ruser, time_t timestamp) +check_login_time(const char *ruser, time_t timestamp) { struct utmp utbuf, *ut; time_t oldest_login = 0; @@ -237,14 +237,14 @@ get_ruser(pam_handle_t *pamh, char *ruserbuf, size_t ruserbuflen) if (pwd != NULL) { ruser = pwd->pw_name; } - } + } if (ruser == NULL || strlen(ruser) >= ruserbuflen) { *ruserbuf = '\0'; return -1; } strcpy(ruserbuf, ruser); return 0; -} +} /* Get the path to the timestamp to use. */ static int @@ -299,7 +299,7 @@ get_timestamp_name(pam_handle_t *pamh, int argc, const char **argv, tty = NULL; } else { tty = void_tty; - } + } if ((tty == NULL) || (strlen(tty) == 0)) { tty = ttyname(STDIN_FILENO); if ((tty == NULL) || (strlen(tty) == 0)) { @@ -413,7 +413,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) int count; void *mac; size_t maclen; - char ruser[BUFLEN]; + char ruser[BUFLEN]; /* Check that the file is owned by the superuser. */ if ((st.st_uid != 0) || (st.st_gid != 0)) { @@ -483,7 +483,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) free(mac); memmove(&then, message + strlen(path) + 1, sizeof(then)); free(message); - + /* Check oldest login against timestamp */ if (get_ruser(pamh, ruser, sizeof(ruser))) { @@ -565,7 +565,14 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char * subdir[i] = '\0'; if (mkdir(subdir, 0700) == 0) { /* Attempt to set the owner to the superuser. */ - lchown(subdir, 0, 0); + if (lchown(subdir, 0, 0) != 0) { + if (debug) { + pam_syslog(pamh, LOG_DEBUG, + "error setting permissions on `%s': %m", + subdir); + } + return PAM_SESSION_ERR; + } } else { if (errno != EEXIST) { if (debug) { @@ -617,7 +624,15 @@ pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, int argc, const char * } /* Attempt to set the owner to the superuser. */ - fchown(fd, 0, 0); + if (fchown(fd, 0, 0) != 0) { + if (debug) { + pam_syslog(pamh, LOG_DEBUG, + "error setting ownership of `%s': %m", + path); + } + return PAM_SESSION_ERR; + } + /* Write the timestamp to the file. */ if (write(fd, text, p - text) != p - text) { diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index dda617a0..98283502 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -120,13 +120,13 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int *rounds, D(("DISALLOW_NULL_AUTHTOK")); set(UNIX__NONULL, ctrl); } - + /* Set default rounds for blowfish */ if (on(UNIX_BLOWFISH_PASS, ctrl) && off(UNIX_ALGO_ROUNDS, ctrl)) { *rounds = 5; set(UNIX_ALGO_ROUNDS, ctrl); } - + /* Enforce sane "rounds" values */ if (on(UNIX_ALGO_ROUNDS, ctrl)) { if (on(UNIX_BLOWFISH_PASS, ctrl)) { @@ -478,10 +478,18 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, /* if the stored password is NULL */ int rc=0; if (passwd != NULL) { /* send the password to the child */ - write(fds[1], passwd, strlen(passwd)+1); + if (write(fds[1], passwd, strlen(passwd)+1) == -1) { + pam_syslog (pamh, LOG_ERR, "Cannot send password to helper: %m"); + close(fds[1]); + retval = PAM_AUTH_ERR; + } passwd = NULL; - } else { - write(fds[1], "", 1); /* blank password */ + } else { /* blank password */ + if (write(fds[1], "", 1) == -1) { + pam_syslog (pamh, LOG_ERR, "Cannot send password to helper: %m"); + close(fds[1]); + retval = PAM_AUTH_ERR; + } } close(fds[0]); /* close here to avoid possible SIGPIPE above */ close(fds[1]); @@ -871,7 +879,7 @@ int _unix_read_password(pam_handle_t * pamh } /* ****************************************************************** * - * Copyright (c) Jan Rêkorajski 1999. + * Copyright (c) Jan Rêkorajski 1999. * Copyright (c) Andrew G. Morgan 1996-8. * Copyright (c) Alex O. Yuriev, 1996. * Copyright (c) Cristian Gafton 1996. -- cgit v1.2.3 From 8575828fae141d5f918fca7f123cc96f6793ac11 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Fri, 3 Apr 2009 00:36:22 +0000 Subject: Relevant BUGIDs: Purpose of commit: bugfix Commit summary: --------------- 2009-04-03 Dmitry V. Levin * libpamc/pamc_load.c (__pamc_exec_agent): Replace call to exit(3) in child process with call to _exit(2). * modules/pam_mkhomedir/pam_mkhomedir.c (create_homedir): Likewise. * modules/pam_unix/pam_unix_acct.c (_unix_run_verify_binary): Likewise. * modules/pam_unix/pam_unix_passwd.c (_unix_run_update_binary): Likewise. * modules/pam_unix/support.c (_unix_run_helper_binary): Likewise. * modules/pam_xauth/pam_xauth.c (run_coprocess): Likewise. * modules/pam_exec/pam_exec.c (call_exec): Replace all calls to exit(3) in child process with calls to _exit(2). * modules/pam_filter/pam_filter.c (set_filter): Likewise. * modules/pam_namespace/pam_namespace.c (inst_init, cleanup_tmpdirs): Likewise. --- modules/pam_exec/pam_exec.c | 35 +++++++++++++++-------------------- modules/pam_filter/pam_filter.c | 5 +++-- modules/pam_mkhomedir/pam_mkhomedir.c | 2 +- modules/pam_namespace/pam_namespace.c | 10 +++++----- modules/pam_unix/pam_unix_acct.c | 3 ++- modules/pam_unix/pam_unix_passwd.c | 2 +- modules/pam_unix/support.c | 2 +- modules/pam_xauth/pam_xauth.c | 2 +- 8 files changed, 29 insertions(+), 32 deletions(-) (limited to 'modules') diff --git a/modules/pam_exec/pam_exec.c b/modules/pam_exec/pam_exec.c index 47e1d5bb..7b2e402c 100644 --- a/modules/pam_exec/pam_exec.c +++ b/modules/pam_exec/pam_exec.c @@ -252,7 +252,7 @@ call_exec (const char *pam_type, pam_handle_t *pamh, { int err = errno; pam_syslog (pamh, LOG_ERR, "dup2 of STDIN failed: %m"); - exit (err); + _exit (err); } for (i = 0; i < sysconf (_SC_OPEN_MAX); i++) @@ -271,7 +271,7 @@ call_exec (const char *pam_type, pam_handle_t *pamh, { int err = errno; pam_syslog (pamh, LOG_ERR, "open of /dev/null failed: %m"); - exit (err); + _exit (err); } } @@ -287,7 +287,7 @@ call_exec (const char *pam_type, pam_handle_t *pamh, int err = errno; pam_syslog (pamh, LOG_ERR, "open of %s failed: %m", logfile); - exit (err); + _exit (err); } if (asprintf (&buffer, "*** %s", ctime (&tm)) > 0) { @@ -302,7 +302,7 @@ call_exec (const char *pam_type, pam_handle_t *pamh, { int err = errno; pam_syslog (pamh, LOG_ERR, "open of /dev/null failed: %m"); - exit (err); + _exit (err); } } @@ -310,7 +310,7 @@ call_exec (const char *pam_type, pam_handle_t *pamh, { int err = errno; pam_syslog (pamh, LOG_ERR, "dup failed: %m"); - exit (err); + _exit (err); } if (call_setuid) @@ -319,19 +319,19 @@ call_exec (const char *pam_type, pam_handle_t *pamh, int err = errno; pam_syslog (pamh, LOG_ERR, "setuid(%lu) failed: %m", (unsigned long) geteuid ()); - exit (err); + _exit (err); } if (setsid () == -1) { int err = errno; pam_syslog (pamh, LOG_ERR, "setsid failed: %m"); - exit (err); + _exit (err); } arggv = calloc (argc + 4, sizeof (char *)); if (arggv == NULL) - exit (ENOMEM); + _exit (ENOMEM); for (i = 0; i < (argc - optargc); i++) arggv[i] = strdup(argv[i+optargc]); @@ -351,7 +351,7 @@ call_exec (const char *pam_type, pam_handle_t *pamh, { free(envlist); pam_syslog (pamh, LOG_ERR, "realloc environment failed: %m"); - exit (ENOMEM); + _exit (ENOMEM); } envlist = tmp; for (i = 0; i < nitems; ++i) @@ -364,7 +364,7 @@ call_exec (const char *pam_type, pam_handle_t *pamh, { free(envlist); pam_syslog (pamh, LOG_ERR, "prepare environment failed: %m"); - exit (ENOMEM); + _exit (ENOMEM); } envlist[envlen++] = envstr; envlist[envlen] = NULL; @@ -374,7 +374,7 @@ call_exec (const char *pam_type, pam_handle_t *pamh, { free(envlist); pam_syslog (pamh, LOG_ERR, "prepare environment failed: %m"); - exit (ENOMEM); + _exit (ENOMEM); } envlist[envlen++] = envstr; envlist[envlen] = NULL; @@ -382,16 +382,11 @@ call_exec (const char *pam_type, pam_handle_t *pamh, if (debug) pam_syslog (pamh, LOG_DEBUG, "Calling %s ...", arggv[0]); - if (execve (arggv[0], arggv, envlist) == -1) - { - int err = errno; - pam_syslog (pamh, LOG_ERR, "execve(%s,...) failed: %m", - arggv[0]); - free(envlist); - exit (err); - } + execve (arggv[0], arggv, envlist); + i = errno; + pam_syslog (pamh, LOG_ERR, "execve(%s,...) failed: %m", arggv[0]); free(envlist); - exit (1); /* should never be reached. */ + _exit (i); } return PAM_SYSTEM_ERR; /* will never be reached. */ } diff --git a/modules/pam_filter/pam_filter.c b/modules/pam_filter/pam_filter.c index 6b821efc..2f290fd5 100644 --- a/modules/pam_filter/pam_filter.c +++ b/modules/pam_filter/pam_filter.c @@ -468,7 +468,7 @@ set_filter (pam_handle_t *pamh, int flags UNUSED, int ctrl, pam_syslog(pamh, LOG_WARNING, "unable to re-assign APPIN/OUT/ERR: %m"); close(fd[0]); - exit(1); + _exit(1); } /* make sure that file descriptors survive 'exec's */ @@ -481,7 +481,7 @@ set_filter (pam_handle_t *pamh, int flags UNUSED, int ctrl, close(APPIN_FILENO); close(APPOUT_FILENO); close(APPERR_FILENO); - exit(1); + _exit(1); } /* now the user input is read from the parent through filter */ @@ -491,6 +491,7 @@ set_filter (pam_handle_t *pamh, int flags UNUSED, int ctrl, /* getting to here is an error */ pam_syslog(pamh, LOG_ALERT, "filter: %s: %m", filtername); + _exit(1); } else { /* wait for either of the two children to exit */ diff --git a/modules/pam_mkhomedir/pam_mkhomedir.c b/modules/pam_mkhomedir/pam_mkhomedir.c index b81708f2..dfc4979e 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.c +++ b/modules/pam_mkhomedir/pam_mkhomedir.c @@ -154,7 +154,7 @@ create_homedir (pam_handle_t *pamh, options_t *opt, /* should not get here: exit with error */ D(("helper binary is not available")); - exit(PAM_SYSTEM_ERR); + _exit(PAM_SYSTEM_ERR); } else if (child > 0) { int rc; while ((rc=waitpid(child, &retval, 0)) < 0 && errno == EINTR); diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c index 7d668d9e..f6219271 100644 --- a/modules/pam_namespace/pam_namespace.c +++ b/modules/pam_namespace/pam_namespace.c @@ -1184,12 +1184,12 @@ static int inst_init(const struct polydir_s *polyptr, const char *ipath, #ifdef WITH_SELINUX if (idata->flags & PAMNS_SELINUX_ENABLED) { if (setexeccon(NULL) < 0) - exit(1); + _exit(1); } #endif if (execl(init_script, init_script, polyptr->dir, ipath, newdir?"1":"0", idata->user, (char *)NULL) < 0) - exit(1); + _exit(1); } else if (pid > 0) { while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) && (errno == EINTR)); @@ -1611,16 +1611,16 @@ static int cleanup_tmpdirs(struct instance_data *idata) #ifdef WITH_SELINUX if (idata->flags & PAMNS_SELINUX_ENABLED) { if (setexeccon(NULL) < 0) - exit(1); + _exit(1); } #endif if (execl("/bin/rm", "/bin/rm", "-rf", pptr->instance_prefix, (char *)NULL) < 0) - exit(1); + _exit(1); } else if (pid > 0) { while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) && (errno == EINTR)); if (rc == (pid_t)-1) { - pam_syslog(idata->pamh, LOG_ERR, "waitpid failed- %m"); + pam_syslog(idata->pamh, LOG_ERR, "waitpid failed: %m"); rc = PAM_SESSION_ERR; goto out; } diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c index 4e119340..08cc750f 100644 --- a/modules/pam_unix/pam_unix_acct.c +++ b/modules/pam_unix/pam_unix_acct.c @@ -130,7 +130,8 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned int ctrl, /* should not get here: exit with error */ D(("helper binary is not available")); printf("-1\n"); - exit(PAM_AUTHINFO_UNAVAIL); + fflush(stdout); + _exit(PAM_AUTHINFO_UNAVAIL); } else { close(fds[1]); if (child > 0) { diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index ab1adda0..d3ee6815 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -207,7 +207,7 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const /* should not get here: exit with error */ D(("helper binary is not available")); - exit(PAM_AUTHINFO_UNAVAIL); + _exit(PAM_AUTHINFO_UNAVAIL); } else if (child > 0) { /* wait for child */ /* if the stored password is NULL */ diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 98283502..050e0dc1 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -472,7 +472,7 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, /* should not get here: exit with error */ D(("helper binary is not available")); - exit(PAM_AUTHINFO_UNAVAIL); + _exit(PAM_AUTHINFO_UNAVAIL); } else if (child > 0) { /* wait for child */ /* if the stored password is NULL */ diff --git a/modules/pam_xauth/pam_xauth.c b/modules/pam_xauth/pam_xauth.c index 518c015a..bc72a8c1 100644 --- a/modules/pam_xauth/pam_xauth.c +++ b/modules/pam_xauth/pam_xauth.c @@ -149,7 +149,7 @@ run_coprocess(const char *input, char **output, /* Run the command. */ execv(command, args); /* Never reached. */ - exit(1); + _exit(1); } /* We're the parent, so close the other ends of the pipes. */ -- cgit v1.2.3 From 751447604965c690b0f5bc35d633488b20e7f24a Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Thu, 9 Apr 2009 08:09:11 +0000 Subject: Relevant BUGIDs: Purpose of commit: cleanup Commit summary: --------------- 2009-04-09 Thorsten Kukuk * modules/pam_unix/yppasswd.h: Update license to GPLv2 or later on request of Olaf Kirch (Author). * modules/pam_unix/yppasswd_xdr.c: Likewise. --- modules/pam_unix/yppasswd.h | 6 +++--- modules/pam_unix/yppasswd_xdr.c | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'modules') diff --git a/modules/pam_unix/yppasswd.h b/modules/pam_unix/yppasswd.h index 6b414be0..5f947071 100644 --- a/modules/pam_unix/yppasswd.h +++ b/modules/pam_unix/yppasswd.h @@ -1,9 +1,9 @@ /* * yppasswdd - * Copyright 1994, 1995, 1996 Olaf Kirch, + * Copyright 1994, 1995, 1996 Olaf Kirch, * - * This program is covered by the GNU General Public License, version 2. - * It is provided in the hope that it is useful. However, the author + * This program is covered by the GNU General Public License, version 2 + * or later. It is provided in the hope that it is useful. However, the author * disclaims ALL WARRANTIES, expressed or implied. See the GPL for details. * * This file was generated automatically by rpcgen from yppasswd.x, and diff --git a/modules/pam_unix/yppasswd_xdr.c b/modules/pam_unix/yppasswd_xdr.c index bf3f2fc6..0b7cfac6 100644 --- a/modules/pam_unix/yppasswd_xdr.c +++ b/modules/pam_unix/yppasswd_xdr.c @@ -1,11 +1,11 @@ -/* +/* * yppasswdd - * Copyright 1994, 1995, 1996 Olaf Kirch, + * Copyright 1994, 1995, 1996 Olaf Kirch, * - * This program is covered by the GNU General Public License, version 2. - * It is provided in the hope that it is useful. However, the author + * This program is covered by the GNU General Public License, version 2 + * or later. It is provided in the hope that it is useful. However, the author * disclaims ALL WARRANTIES, expressed or implied. See the GPL for details. - * + * * This file was generated automatically by rpcgen from yppasswd.x, and * editied manually. */ -- cgit v1.2.3 From 91defb2140f9141d74543f57598410daab8d43a0 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 16 Apr 2009 13:54:46 +0000 Subject: Relevant BUGIDs: rhbz#495941 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purpose of commit: bugfix Commit summary: --------------- 2009-04-16 Tomáš Mráz * modules/pam_succeed_if/pam_succeed_if.c (evaluate): Add user parameter. Use user instead of pwd->pw_name in comparsions. (pam_sm_authenticate): Pass the original user to evaluate(). --- modules/pam_succeed_if/pam_succeed_if.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'modules') diff --git a/modules/pam_succeed_if/pam_succeed_if.c b/modules/pam_succeed_if/pam_succeed_if.c index cf95d38e..e728d2e1 100644 --- a/modules/pam_succeed_if/pam_succeed_if.c +++ b/modules/pam_succeed_if/pam_succeed_if.c @@ -250,7 +250,7 @@ evaluate_notinnetgr(const char *host, const char *user, const char *group) static int evaluate(pam_handle_t *pamh, int debug, const char *left, const char *qual, const char *right, - struct passwd *pwd) + struct passwd *pwd, const char *user) { char buf[LINE_MAX] = ""; const char *attribute = left; @@ -258,7 +258,7 @@ evaluate(pam_handle_t *pamh, int debug, if ((strcasecmp(left, "login") == 0) || (strcasecmp(left, "name") == 0) || (strcasecmp(left, "user") == 0)) { - snprintf(buf, sizeof(buf), "%s", pwd->pw_name); + snprintf(buf, sizeof(buf), "%s", user); left = buf; } if (strcasecmp(left, "uid") == 0) { @@ -350,25 +350,25 @@ evaluate(pam_handle_t *pamh, int debug, } /* User is in this group. */ if (strcasecmp(qual, "ingroup") == 0) { - return evaluate_ingroup(pamh, pwd->pw_name, right); + return evaluate_ingroup(pamh, user, right); } /* User is not in this group. */ if (strcasecmp(qual, "notingroup") == 0) { - return evaluate_notingroup(pamh, pwd->pw_name, right); + return evaluate_notingroup(pamh, user, right); } /* (Rhost, user) is in this netgroup. */ if (strcasecmp(qual, "innetgr") == 0) { const void *rhost; if (pam_get_item(pamh, PAM_RHOST, &rhost) != PAM_SUCCESS) rhost = NULL; - return evaluate_innetgr(rhost, pwd->pw_name, right); + return evaluate_innetgr(rhost, user, right); } /* (Rhost, user) is not in this group. */ if (strcasecmp(qual, "notinnetgr") == 0) { const void *rhost; if (pam_get_item(pamh, PAM_RHOST, &rhost) != PAM_SUCCESS) rhost = NULL; - return evaluate_notinnetgr(rhost, pwd->pw_name, right); + return evaluate_notinnetgr(rhost, user, right); } /* Fail closed. */ return PAM_SERVICE_ERR; @@ -477,7 +477,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED, count++; ret = evaluate(pamh, debug, left, qual, right, - pwd); + pwd, user); if (ret != PAM_SUCCESS) { if(!quiet_fail) pam_syslog(pamh, LOG_INFO, -- cgit v1.2.3 From 538c9efe38bfc96a2cc5355b26a70a4e2957158a Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 11 May 2009 14:52:31 +0000 Subject: Relevant BUGIDs: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purpose of commit: bugfix Commit summary: --------------- 2009-05-11 Tomáš Mráz * modules/pam_unix/pam_unix_passwd.c (_unix_run_update_binary): Remove unnecessary setuid() call. --- modules/pam_unix/pam_unix_passwd.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'modules') diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c index d3ee6815..30ea6687 100644 --- a/modules/pam_unix/pam_unix_passwd.c +++ b/modules/pam_unix/pam_unix_passwd.c @@ -185,12 +185,6 @@ static int _unix_run_update_binary(pam_handle_t *pamh, unsigned int ctrl, const } } - if (SELINUX_ENABLED && geteuid() == 0) { - /* must set the real uid to 0 so the helper will not error - out if pam is called from setuid binary (su, sudo...) */ - setuid(0); - } - /* exec binary helper */ args[0] = x_strdup(UPDATE_HELPER); args[1] = x_strdup(user); -- cgit v1.2.3 From fbd40f8764ac17611e1e7f9464565a1b3e7792a2 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 1 Jun 2009 07:03:19 +0000 Subject: Relevant BUGIDs: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purpose of commit: cleanup Commit summary: --------------- 2009-06-01 Ville Skyttä * modules/pam_limits/pam_limits.8.xml: Only *.conf files are parsed. Spelling fixes. * modules/pam_access/pam_access.8.xml: Spelling fixes. * modules/pam_cracklib/pam_cracklib.8.xml: Likewise. * modules/pam_echo/pam_echo.8.xml: Likewise. * modules/pam_env/pam_env.8.xml: Likewise. * modules/pam_exec/pam_exec.8.xml: Likewise. * modules/pam_filter/pam_filter.8.xml: Likewise. * modules/pam_ftp/pam_ftp.8.xml: Likewise. * modules/pam_group/pam_group.8.xml: Likewise. * modules/pam_issue/pam_issue.8.xml: Likewise. * modules/pam_lastlog/pam_lastlog.8.xml: Likewise. * modules/pam_listfile/pam_listfile.8.xml: Likewise. * modules/pam_localuser/pam_localuser.8.xml: Likewise. * modules/pam_loginuid/pam_loginuid.8.xml: Likewise. * modules/pam_mkhomedir/pam_mkhomedir.8.xml: Likewise. * modules/pam_motd/pam_motd.8.xml: Likewise. * modules/pam_namespace/pam_namespace.8.xml: Likewise. * modules/pam_pwhistory/pam_pwhistory.8.xml: Likewise. * modules/pam_selinux/pam_selinux.8.xml: Likewise. * modules/pam_succeed_if/pam_succeed_if.8.xml: Likewise. * modules/pam_tally/pam_tally.8.xml: Likewise. * modules/pam_tally2/pam_tally2.8.xml: Likewise. * modules/pam_time/pam_time.8.xml: Likewise. * modules/pam_timestamp/pam_timestamp.8.xml: Likewise. * modules/pam_timestamp/pam_timestamp_check.8.xml: Likewise. * modules/pam_tty_audit/pam_tty_audit.8.xml: Likewise. * modules/pam_umask/pam_umask.8.xml: Likewise. * modules/pam_unix/pam_unix.8.xml: Likewise. * modules/pam_xauth/pam_xauth.8.xml: Likewise. --- modules/pam_access/pam_access.8.xml | 4 ++-- modules/pam_cracklib/pam_cracklib.8.xml | 2 +- modules/pam_echo/pam_echo.8.xml | 2 +- modules/pam_env/pam_env.8.xml | 4 ++-- modules/pam_exec/pam_exec.8.xml | 4 ++-- modules/pam_filter/pam_filter.8.xml | 2 +- modules/pam_ftp/pam_ftp.8.xml | 2 +- modules/pam_group/pam_group.8.xml | 2 +- modules/pam_issue/pam_issue.8.xml | 4 ++-- modules/pam_lastlog/pam_lastlog.8.xml | 4 ++-- modules/pam_limits/pam_limits.8.xml | 6 +++--- modules/pam_listfile/pam_listfile.8.xml | 2 +- modules/pam_localuser/pam_localuser.8.xml | 2 +- modules/pam_loginuid/pam_loginuid.8.xml | 2 +- modules/pam_mkhomedir/pam_mkhomedir.8.xml | 2 +- modules/pam_motd/pam_motd.8.xml | 2 +- modules/pam_namespace/pam_namespace.8.xml | 4 ++-- modules/pam_pwhistory/pam_pwhistory.8.xml | 4 ++-- modules/pam_selinux/pam_selinux.8.xml | 4 ++-- modules/pam_succeed_if/pam_succeed_if.8.xml | 2 +- modules/pam_tally/pam_tally.8.xml | 12 ++++++------ modules/pam_tally2/pam_tally2.8.xml | 14 +++++++------- modules/pam_time/pam_time.8.xml | 2 +- modules/pam_timestamp/pam_timestamp.8.xml | 4 ++-- modules/pam_timestamp/pam_timestamp_check.8.xml | 2 +- modules/pam_tty_audit/pam_tty_audit.8.xml | 2 +- modules/pam_umask/pam_umask.8.xml | 2 +- modules/pam_unix/pam_unix.8.xml | 2 +- modules/pam_xauth/pam_xauth.8.xml | 4 ++-- 29 files changed, 52 insertions(+), 52 deletions(-) (limited to 'modules') diff --git a/modules/pam_access/pam_access.8.xml b/modules/pam_access/pam_access.8.xml index 6b031d2e..710e2e7b 100644 --- a/modules/pam_access/pam_access.8.xml +++ b/modules/pam_access/pam_access.8.xml @@ -86,7 +86,7 @@ - A lot of debug informations are printed with + A lot of debug information is printed with syslog3. @@ -115,7 +115,7 @@ fieldsep=| will cause the default `:' character to be treated as part of a field value and `|' becomes the field separator. Doing this may be - useful in conjuction with a system that wants to use + useful in conjunction with a system that wants to use pam_access with X based applications, since the PAM_TTY item is likely to be of the form "hostname:0" which includes a `:' character in diff --git a/modules/pam_cracklib/pam_cracklib.8.xml b/modules/pam_cracklib/pam_cracklib.8.xml index 1c31e077..29e00c09 100644 --- a/modules/pam_cracklib/pam_cracklib.8.xml +++ b/modules/pam_cracklib/pam_cracklib.8.xml @@ -458,7 +458,7 @@ PAM_SERVICE_ERR - A internal error occured. + A internal error occurred. diff --git a/modules/pam_echo/pam_echo.8.xml b/modules/pam_echo/pam_echo.8.xml index 07ac9af2..ef76b022 100644 --- a/modules/pam_echo/pam_echo.8.xml +++ b/modules/pam_echo/pam_echo.8.xml @@ -141,7 +141,7 @@ EXAMPLES For an example of the use of this module, we show how it may be - used to print informations about good passwords: + used to print information about good passwords: password optional pam_echo.so file=/usr/share/doc/good-password.txt password required pam_unix.so diff --git a/modules/pam_env/pam_env.8.xml b/modules/pam_env/pam_env.8.xml index e8cd561b..536cb132 100644 --- a/modules/pam_env/pam_env.8.xml +++ b/modules/pam_env/pam_env.8.xml @@ -90,7 +90,7 @@ - A lot of debug informations are printed with + A lot of debug information is printed with syslog3. @@ -130,7 +130,7 @@ Indicate an alternative .pam_environment file to override the default. This can be useful when different - services need different environments. The filename is relativ to + services need different environments. The filename is relative to the user home directory. diff --git a/modules/pam_exec/pam_exec.8.xml b/modules/pam_exec/pam_exec.8.xml index 3cbd6af3..1ca50dd5 100644 --- a/modules/pam_exec/pam_exec.8.xml +++ b/modules/pam_exec/pam_exec.8.xml @@ -161,7 +161,7 @@ PAM_SUCCESS - The external command runs successfull. + The external command was run successfully. @@ -179,7 +179,7 @@ PAM_SYSTEM_ERR - A system error occured or the command to execute failed. + A system error occurred or the command to execute failed. diff --git a/modules/pam_filter/pam_filter.8.xml b/modules/pam_filter/pam_filter.8.xml index 9a9d69b9..7309c352 100644 --- a/modules/pam_filter/pam_filter.8.xml +++ b/modules/pam_filter/pam_filter.8.xml @@ -205,7 +205,7 @@ PAM_SUCCESS - The new filter was set successfull. + The new filter was set successfully. diff --git a/modules/pam_ftp/pam_ftp.8.xml b/modules/pam_ftp/pam_ftp.8.xml index ea985c0d..6f11f570 100644 --- a/modules/pam_ftp/pam_ftp.8.xml +++ b/modules/pam_ftp/pam_ftp.8.xml @@ -121,7 +121,7 @@ PAM_SUCCESS - The authentication was successfull. + The authentication was successful. diff --git a/modules/pam_group/pam_group.8.xml b/modules/pam_group/pam_group.8.xml index 8c0770b8..2c1c9058 100644 --- a/modules/pam_group/pam_group.8.xml +++ b/modules/pam_group/pam_group.8.xml @@ -52,7 +52,7 @@ access to should be mounted nosuid. - The pam_group module fuctions in parallel with the + The pam_group module functions in parallel with the /etc/group file. If the user is granted any groups based on the behavior of this module, they are granted in addition to those entries diff --git a/modules/pam_issue/pam_issue.8.xml b/modules/pam_issue/pam_issue.8.xml index 4254ea61..fb9b7377 100644 --- a/modules/pam_issue/pam_issue.8.xml +++ b/modules/pam_issue/pam_issue.8.xml @@ -180,7 +180,7 @@ PAM_SERVICE_ERR - A service module error occured. + A service module error occurred. @@ -189,7 +189,7 @@ PAM_SUCCESS - The new prompt was set successfull. + The new prompt was set successfully. diff --git a/modules/pam_lastlog/pam_lastlog.8.xml b/modules/pam_lastlog/pam_lastlog.8.xml index f1fffa89..2a6794ad 100644 --- a/modules/pam_lastlog/pam_lastlog.8.xml +++ b/modules/pam_lastlog/pam_lastlog.8.xml @@ -84,7 +84,7 @@ Don't inform the user about any previous login, - just upate the /var/log/lastlog file. + just update the /var/log/lastlog file. @@ -184,7 +184,7 @@ PAM_SUCCESS - Everything was successfull. + Everything was successful. diff --git a/modules/pam_limits/pam_limits.8.xml b/modules/pam_limits/pam_limits.8.xml index a4375e22..0be7ef4d 100644 --- a/modules/pam_limits/pam_limits.8.xml +++ b/modules/pam_limits/pam_limits.8.xml @@ -50,11 +50,11 @@ By default limits are taken from the /etc/security/limits.conf - config file. Then individual files from the /etc/security/limits.d/ + config file. Then individual *.conf files from the /etc/security/limits.d/ directory are read. The files are parsed one after another in the order of "C" locale. The effect of the individual files is the same as if all the files were concatenated together in the order of parsing. - If a config file is explicitely specified with a module option then the + If a config file is explicitly specified with a module option then the files in the above directory are not parsed. @@ -175,7 +175,7 @@ - PAM_SESSEION_ERR + PAM_SESSION_ERR Error recovering account name. diff --git a/modules/pam_listfile/pam_listfile.8.xml b/modules/pam_listfile/pam_listfile.8.xml index 4c1fb1fd..15f047c2 100644 --- a/modules/pam_listfile/pam_listfile.8.xml +++ b/modules/pam_listfile/pam_listfile.8.xml @@ -129,7 +129,7 @@ File containing one item per line. The file needs to be a plain - file and not world writeable. + file and not world writable. diff --git a/modules/pam_localuser/pam_localuser.8.xml b/modules/pam_localuser/pam_localuser.8.xml index 861fc35a..b06a0bf7 100644 --- a/modules/pam_localuser/pam_localuser.8.xml +++ b/modules/pam_localuser/pam_localuser.8.xml @@ -97,7 +97,7 @@ PAM_SUCCESS - The new localuser was set successfull. + The new localuser was set successfully. diff --git a/modules/pam_loginuid/pam_loginuid.8.xml b/modules/pam_loginuid/pam_loginuid.8.xml index 2a146b2c..d16e2b2d 100644 --- a/modules/pam_loginuid/pam_loginuid.8.xml +++ b/modules/pam_loginuid/pam_loginuid.8.xml @@ -72,7 +72,7 @@ PAM_SESSION_ERR - An error occured during session management. + An error occurred during session management. diff --git a/modules/pam_mkhomedir/pam_mkhomedir.8.xml b/modules/pam_mkhomedir/pam_mkhomedir.8.xml index 5d66ee23..c980ce1d 100644 --- a/modules/pam_mkhomedir/pam_mkhomedir.8.xml +++ b/modules/pam_mkhomedir/pam_mkhomedir.8.xml @@ -44,7 +44,7 @@ without using a distributed file system or pre-creating a large number of directories. The skeleton directory (usually /etc/skel/) is used to copy default files - and also set's a umask for the creation. + and also sets a umask for the creation. The new users home directory will not be removed after logout diff --git a/modules/pam_motd/pam_motd.8.xml b/modules/pam_motd/pam_motd.8.xml index 7b9b2437..ff92154e 100644 --- a/modules/pam_motd/pam_motd.8.xml +++ b/modules/pam_motd/pam_motd.8.xml @@ -30,7 +30,7 @@ pam_motd is a PAM module that can be used to display - arbitrary motd (message of the day) files after a succesful + arbitrary motd (message of the day) files after a successful login. By default the /etc/motd file is shown. The message size is limited to 64KB. diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml index 81328476..0433f0fd 100644 --- a/modules/pam_namespace/pam_namespace.8.xml +++ b/modules/pam_namespace/pam_namespace.8.xml @@ -65,7 +65,7 @@ using SELinux, user name, security context or both. If an executable script /etc/security/namespace.init exists, it is used to initialize the instance directory after it is set up - and mounted on the polyinstantiated direcory. The script receives the + and mounted on the polyinstantiated directory. The script receives the polyinstantiated directory path, the instance directory path, flag whether the instance directory was newly created (0 for no, 1 for yes), and the user name as its arguments. @@ -197,7 +197,7 @@ For certain trusted programs such as newrole, open session - is called from a child process while the parent perfoms + is called from a child process while the parent performs close session and pam end functions. For these commands use this option to instruct pam_close_session to not unmount the bind mounted polyinstantiated directory in the diff --git a/modules/pam_pwhistory/pam_pwhistory.8.xml b/modules/pam_pwhistory/pam_pwhistory.8.xml index cc216707..7696353f 100644 --- a/modules/pam_pwhistory/pam_pwhistory.8.xml +++ b/modules/pam_pwhistory/pam_pwhistory.8.xml @@ -50,8 +50,8 @@ alternating between the same password too frequently. - This module does not work togehter with kerberos. In general, - it does not make much sense to use this module in conjuction + This module does not work together with kerberos. In general, + it does not make much sense to use this module in conjunction with NIS or LDAP, since the old passwords are stored on the local machine and are not available on another machine for password history checking. diff --git a/modules/pam_selinux/pam_selinux.8.xml b/modules/pam_selinux/pam_selinux.8.xml index 3db26d04..2c1cdb24 100644 --- a/modules/pam_selinux/pam_selinux.8.xml +++ b/modules/pam_selinux/pam_selinux.8.xml @@ -162,7 +162,7 @@ Use the sensitivity level of the current process for the user context - instead of the default level. Also supresses asking of the + instead of the default level. Also suppresses asking of the sensitivity level from the user or obtaining it from PAM environment. @@ -192,7 +192,7 @@ PAM_SUCCESS - The security context was set successfull. + The security context was set successfully. diff --git a/modules/pam_succeed_if/pam_succeed_if.8.xml b/modules/pam_succeed_if/pam_succeed_if.8.xml index c99f6be5..67f9bbfd 100644 --- a/modules/pam_succeed_if/pam_succeed_if.8.xml +++ b/modules/pam_succeed_if/pam_succeed_if.8.xml @@ -249,7 +249,7 @@ PAM_SERVICE_ERR - A service error occured or the arguments can't be + A service error occurred or the arguments can't be parsed correctly. diff --git a/modules/pam_tally/pam_tally.8.xml b/modules/pam_tally/pam_tally.8.xml index 831ee1a5..91925688 100644 --- a/modules/pam_tally/pam_tally.8.xml +++ b/modules/pam_tally/pam_tally.8.xml @@ -129,7 +129,7 @@ If something weird happens (like unable to open the file), - return with PAM_SUCESS if + return with PAM_SUCCESS if is given, else with the corresponding PAM error code. @@ -237,7 +237,7 @@ If the module is invoked by a user with uid=0 the - counter is not incremented. The sys-admin should use this + counter is not incremented. The sysadmin should use this for user launched services, like su, otherwise this argument should be omitted. @@ -312,7 +312,7 @@ Account phase resets attempts counter if the user is not magic root. - This phase can be used optionaly for services which don't call + This phase can be used optionally for services which don't call pam_setcred3 correctly or if the reset should be done regardless @@ -326,7 +326,7 @@ If the module is invoked by a user with uid=0 the - counter is not incremented. The sys-admin should use this + counter is not incremented. The sysadmin should use this for user launched services, like su, otherwise this argument should be omitted. @@ -364,7 +364,7 @@ A invalid option was given, the module was not able - to retrive the user name, no valid counter file + to retrieve the user name, no valid counter file was found, or too many failed logins. @@ -373,7 +373,7 @@ PAM_SUCCESS - Everything was successfull. + Everything was successful. diff --git a/modules/pam_tally2/pam_tally2.8.xml b/modules/pam_tally2/pam_tally2.8.xml index 255fcea4..4ad529fd 100644 --- a/modules/pam_tally2/pam_tally2.8.xml +++ b/modules/pam_tally2/pam_tally2.8.xml @@ -122,7 +122,7 @@ If something weird happens (like unable to open the file), - return with PAM_SUCESS if + return with PAM_SUCCESS if is given, else with the corresponding PAM error code. @@ -230,7 +230,7 @@ If the module is invoked by a user with uid=0 the - counter is not incremented. The sys-admin should use this + counter is not incremented. The sysadmin should use this for user launched services, like su, otherwise this argument should be omitted. @@ -265,7 +265,7 @@ This option implies option. Allow access after n seconds - to root acccount after failed attempt. If this option is used + to root account after failed attempt. If this option is used the root user will be locked out for the specified amount of time after he exceeded his maximum allowed attempts. @@ -301,7 +301,7 @@ Account phase resets attempts counter if the user is not magic root. - This phase can be used optionaly for services which don't call + This phase can be used optionally for services which don't call pam_setcred3 correctly or if the reset should be done regardless @@ -315,7 +315,7 @@ If the module is invoked by a user with uid=0 the - counter is not changed. The sys-admin should use this + counter is not changed. The sysadmin should use this for user launched services, like su, otherwise this argument should be omitted. @@ -343,7 +343,7 @@ A invalid option was given, the module was not able - to retrive the user name, no valid counter file + to retrieve the user name, no valid counter file was found, or too many failed logins. @@ -352,7 +352,7 @@ PAM_SUCCESS - Everything was successfull. + Everything was successful. diff --git a/modules/pam_time/pam_time.8.xml b/modules/pam_time/pam_time.8.xml index 8e7f222c..b673beb5 100644 --- a/modules/pam_time/pam_time.8.xml +++ b/modules/pam_time/pam_time.8.xml @@ -63,7 +63,7 @@ - Some debug informations are printed with + Some debug information is printed with syslog3. diff --git a/modules/pam_timestamp/pam_timestamp.8.xml b/modules/pam_timestamp/pam_timestamp.8.xml index c96424ab..adb87a79 100644 --- a/modules/pam_timestamp/pam_timestamp.8.xml +++ b/modules/pam_timestamp/pam_timestamp.8.xml @@ -104,7 +104,7 @@ file as grounds for succeeding. PAM_AUTH_ERR - The module was not able to retrive the user name or + The module was not able to retrieve the user name or no valid timestamp file was found. @@ -113,7 +113,7 @@ file as grounds for succeeding. PAM_SUCCESS - Everything was successfull. + Everything was successful. diff --git a/modules/pam_timestamp/pam_timestamp_check.8.xml b/modules/pam_timestamp/pam_timestamp_check.8.xml index 85484a06..7ec7140e 100644 --- a/modules/pam_timestamp/pam_timestamp_check.8.xml +++ b/modules/pam_timestamp/pam_timestamp_check.8.xml @@ -77,7 +77,7 @@ see if the default timestamp is valid, or optionally remove it. timestamps generated by pam_timestamp when the user authenticates as herself. When the user authenticates as a different user, the name of the timestamp file changes to - accomodate this. target_user allows + accommodate this. target_user allows to specify this user name. diff --git a/modules/pam_tty_audit/pam_tty_audit.8.xml b/modules/pam_tty_audit/pam_tty_audit.8.xml index 005d2e85..7f233dfe 100644 --- a/modules/pam_tty_audit/pam_tty_audit.8.xml +++ b/modules/pam_tty_audit/pam_tty_audit.8.xml @@ -47,7 +47,7 @@ For each user matching one of comma-separated glob , disable TTY auditing. This overrides any previous - option matchin the same user name on the command line. + option matching the same user name on the command line. diff --git a/modules/pam_umask/pam_umask.8.xml b/modules/pam_umask/pam_umask.8.xml index b2858b57..09fc0e7c 100644 --- a/modules/pam_umask/pam_umask.8.xml +++ b/modules/pam_umask/pam_umask.8.xml @@ -157,7 +157,7 @@ PAM_SUCCESS - The new umask was set successfull. + The new umask was set successfully. diff --git a/modules/pam_unix/pam_unix.8.xml b/modules/pam_unix/pam_unix.8.xml index cc3affd9..a726e5e7 100644 --- a/modules/pam_unix/pam_unix.8.xml +++ b/modules/pam_unix/pam_unix.8.xml @@ -321,7 +321,7 @@ - Ignore errors reading shadow inforation for + Ignore errors reading shadow information for users in the account management module. diff --git a/modules/pam_xauth/pam_xauth.8.xml b/modules/pam_xauth/pam_xauth.8.xml index 353f1b6e..08c06cf8 100644 --- a/modules/pam_xauth/pam_xauth.8.xml +++ b/modules/pam_xauth/pam_xauth.8.xml @@ -43,7 +43,7 @@ Without pam_xauth, when xauth is enabled and a user uses the su1 - command to assume another user's priviledges, + command to assume another user's privileges, that user is no longer able to access the original user's X display because the new user does not have the key needed to access the display. pam_xauth solves the problem by forwarding the key from @@ -55,7 +55,7 @@ This means, for example, that when you run su1 - from an xterm sesssion, you will be able to run + from an xterm session, you will be able to run X programs without explicitly dealing with the xauth1 -- cgit v1.2.3 From 87d1508a7362e2f213a90b30a6e5bd72f47d6060 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 1 Jun 2009 07:07:35 +0000 Subject: Relevant BUGIDs: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purpose of commit: bugfix Commit summary: --------------- 2009-06-01 Tomáš Mráz * modules/pam_pwhistory/opasswd.c (save_old_password): Don't call fclose() on NULL descriptor. Found by Steve Grubb. --- modules/pam_pwhistory/opasswd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c index dbcd04e3..3c8e5cff 100644 --- a/modules/pam_pwhistory/opasswd.c +++ b/modules/pam_pwhistory/opasswd.c @@ -244,7 +244,8 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid, { pam_syslog (pamh, LOG_ERR, "Cannot create %s temp file: %m", OLD_PASSWORDS_FILE); - fclose (oldpf); + if (oldpf) + fclose (oldpf); return PAM_AUTHTOK_ERR; } if (do_create) @@ -273,7 +274,8 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid, if (newpf == NULL) { pam_syslog (pamh, LOG_ERR, "Cannot fdopen %s: %m", opasswd_tmp); - fclose (oldpf); + if (oldpf) + fclose (oldpf); close (newpf_fd); retval = PAM_AUTHTOK_ERR; goto error_opasswd; -- cgit v1.2.3