diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-08-01 21:07:27 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-08-01 21:14:22 +0300 |
commit | d211d9ec0cf708b047a0fb0d4019a16a806bbf4c (patch) | |
tree | ecffe1e8c9939e794ca7fbfc066e28c0e2aff2aa | |
parent | f6cde78d9891ad9b07daf6f1b8a822a2a26a250c (diff) | |
download | pam-modules-d211d9ec0cf708b047a0fb0d4019a16a806bbf4c.tar.gz pam-modules-d211d9ec0cf708b047a0fb0d4019a16a806bbf4c.tar.bz2 |
Improve pam_ldaphome
New keywords: bindpwfile and keyfile-mode.
* doc/pam-modules.texi: Document bindpwfile and keyfile-mode.
* pam_ldaphome/pam_ldaphome.c (ldap_bind): Read password from
file, if bindpwfile is given.
(store_pubkeys): Optionally enforce file mode, given by the
keyfile-mode configuration statement.
* pamck/pamck.c (main): Fix a typo.
-rw-r--r-- | doc/pam-modules.texi | 8 | ||||
-rw-r--r-- | pam_ldaphome/pam_ldaphome.c | 108 | ||||
-rw-r--r-- | pamck/pamck.c | 2 |
3 files changed, 108 insertions, 10 deletions
diff --git a/doc/pam-modules.texi b/doc/pam-modules.texi index d263d57..e7b460f 100644 --- a/doc/pam-modules.texi +++ b/doc/pam-modules.texi @@ -1213,6 +1213,10 @@ If @code{binddn} statement is used, this statement supplies the password for simple authentication. @end deffn +@deffn {pam_ldaphome config} bindpwfile file +Read password for simple authentication from @var{file}. +@end deffn + @deffn {pam_ldaphome config} tls val Controls whether TLS is desired or required. If @var{val} is @samp{no} (the default), TLS will not be used. If it is @samp{yes}, @@ -1259,6 +1263,10 @@ directory to the newly created home. The default size is 16384 bytes. Sets the mode (octal) for the created user directories. @end deffn +@deffn {pam_ldaphome config} keyfile-mode mode +Sets the mode (octal) for the created authorized keys file. +@end deffn + @deffn {pam_ldaphome config} authorized_keys name Sets the pathname (relative to the home directory) for the authorized keys file. The default is @samp{.ssh/authorized_keys}. For normal diff --git a/pam_ldaphome/pam_ldaphome.c b/pam_ldaphome/pam_ldaphome.c index 9e5b440..83c10c1 100644 --- a/pam_ldaphome/pam_ldaphome.c +++ b/pam_ldaphome/pam_ldaphome.c @@ -411,6 +411,76 @@ ldap_connect(struct gray_env *env) } static int +full_read(int fd, char *file, char *buf, size_t size) +{ + while (size) { + ssize_t n; + + n = read(fd, buf, size); + if (n == -1) { + if (errno == EAGAIN || errno == EINTR) + continue; + _pam_log(LOG_ERR, "error reading from %s: %s", + file, strerror(errno)); + return -1; + } else if (n == 0) { + _pam_log(LOG_ERR, "short read from %s", file); + return -1; + } + + buf += n; + size -= n; + } + return 0; +} + +static int +get_passwd(struct gray_env *env, struct berval *pwd, char **palloc) +{ + char *file; + + file = gray_env_get(env, "bindpwfile"); + if (file) { + struct stat st; + int fd, rc; + char *mem, *p; + + fd = open(file, O_RDONLY); + if (fd == -1) { + _pam_log(LOG_ERR, "can't open password file %s: %s", + file, strerror(errno)); + return -1; + } + if (fstat(fd, &st)) { + _pam_log(LOG_ERR, "can't stat password file %s: %s", + file, strerror(errno)); + close(fd); + return -1; + } + mem = malloc(st.st_size + 1); + if (!mem) { + _pam_log(LOG_ERR, "can't allocate memory (%lu bytes)", + (unsigned long) st.st_size+1); + close(fd); + return -1; + } + rc = full_read(fd, file, mem, st.st_size); + close(fd); + if (rc) + return rc; + mem[st.st_size] = 0; + p = strchr(mem, '\n'); + if (p) + *p = 0; + *palloc = mem; + pwd->bv_val = mem; + } else + pwd->bv_val = gray_env_get(env, "bindpw"); + pwd->bv_len = pwd->bv_val ? strlen(pwd->bv_val) : 0; + return 0; +} + +static int ldap_bind(LDAP *ld, struct gray_env *env) { int msgid, err, rc; @@ -420,12 +490,14 @@ ldap_bind (LDAP *ld, struct gray_env *env) char *matched = NULL; char *info = NULL; char **refs = NULL; - static struct berval passwd; + struct berval passwd; char *binddn; + char *alloc_ptr = NULL; binddn = gray_env_get(env, "binddn"); - passwd.bv_val = gray_env_get(env, "bindpw"); - passwd.bv_len = passwd.bv_val ? strlen(passwd.bv_val) : 0; + + if (get_passwd(env, &passwd, &alloc_ptr)) + return 1; msgbuf[0] = 0; @@ -435,11 +507,13 @@ ldap_bind (LDAP *ld, struct gray_env *env) _pam_log(LOG_ERR, "ldap_sasl_bind(SIMPLE) failed: %s", ldap_err2string(rc)); + free(alloc_ptr); return 1; } if (ldap_result(ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1) { _pam_log(LOG_ERR, "ldap_result failed"); + free(alloc_ptr); return 1; } @@ -448,6 +522,7 @@ ldap_bind (LDAP *ld, struct gray_env *env) if (rc != LDAP_SUCCESS) { _pam_log(LOG_ERR, "ldap_parse_result failed: %s", ldap_err2string(rc)); + free(alloc_ptr); return 1; } @@ -484,6 +559,8 @@ ldap_bind (LDAP *ld, struct gray_env *env) if (refs) ber_memvfree((void **)refs); + free(alloc_ptr); + return !(err == LDAP_SUCCESS); } @@ -1137,7 +1214,7 @@ populate_homedir(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env) } static int -store_pubkeys(char **keys, struct passwd *pw) +store_pubkeys(char **keys, struct passwd *pw, struct gray_env *env) { FILE *fp; int c; @@ -1145,6 +1222,8 @@ store_pubkeys(char **keys, struct passwd *pw) size_t homelen, pathlen, len; int retval, i; int update = 0; + int oldmask; + unsigned long mode; homelen = strlen(pw->pw_dir); pathlen = strlen(authorized_keys_file); @@ -1157,11 +1236,25 @@ store_pubkeys(char **keys, struct passwd *pw) file_name[homelen++] = '/'; strcpy(file_name + homelen, authorized_keys_file); + switch (get_intval(env, "keyfile-mode", 8, &mode)) { + case -1: + return PAM_SERVICE_ERR; + case 1: + oldmask = -1; + break; + case 0: + oldmask = umask(0666 ^ (mode & 0777)); + } + fp = fopen(file_name, "r+"); if (!fp && create_interdir(file_name, pw) == 0) { fp = fopen(file_name, "w"); update = 1; } + + if (oldmask != -1) + umask(oldmask); + if (!fp) { _pam_log(LOG_EMERG, "cannot open file %s: %s", file_name, strerror(errno)); @@ -1244,7 +1337,7 @@ import_public_key(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env) keys = get_pubkeys(ld, base, filter, attr); gray_slist_free(&slist); - retval = store_pubkeys(keys, pw); + retval = store_pubkeys(keys, pw, env); argcvz_free(keys); } ldap_unbind(ld); @@ -1290,10 +1383,7 @@ create_home_dir(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env) } PAM_EXTERN int -pam_sm_authenticate(pam_handle_t *pamh, - int flags, - int argc, - const char **argv) +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { int retval = PAM_AUTH_ERR; struct gray_env *env; diff --git a/pamck/pamck.c b/pamck/pamck.c index 8c5336e..497300b 100644 --- a/pamck/pamck.c +++ b/pamck/pamck.c @@ -162,7 +162,7 @@ main (int argc, char **argv) exit(0); } group = find_group(optarg); - if (!service) + if (!group) error(1, "no such management group, try `%s -g help' for the list", program_name); |