aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-08-01 21:07:27 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2012-08-01 21:14:22 +0300
commitd211d9ec0cf708b047a0fb0d4019a16a806bbf4c (patch)
treeecffe1e8c9939e794ca7fbfc066e28c0e2aff2aa
parentf6cde78d9891ad9b07daf6f1b8a822a2a26a250c (diff)
downloadpam-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.texi8
-rw-r--r--pam_ldaphome/pam_ldaphome.c108
-rw-r--r--pamck/pamck.c2
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);

Return to:

Send suggestions and report system problems to the System administrator.