summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2012-08-01 18:07:27 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2012-08-01 18:14:22 (GMT)
commitd211d9ec0cf708b047a0fb0d4019a16a806bbf4c (patch) (side-by-side diff)
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.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--doc/pam-modules.texi8
-rw-r--r--pam_ldaphome/pam_ldaphome.c124
-rw-r--r--pamck/pamck.c2
3 files changed, 116 insertions, 18 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
@@ -202,7 +202,7 @@ parse_ldap_uri(const char *uri)
char *domain = NULL, *hostlist = NULL;
size_t i;
- if (ldap_dn2domain (lud->lud_dn, &domain) ||
+ if (ldap_dn2domain(lud->lud_dn, &domain) ||
!domain) {
_pam_log(LOG_ERR,
"DNS SRV: cannot convert "
@@ -288,14 +288,14 @@ parse_ldap_uri(const char *uri)
}
if (ludlist) {
- ldap_free_urldesc (ludlist);
+ ldap_free_urldesc(ludlist);
return NULL;
} else if (!urls)
return NULL;
ldapuri = argcv_concat(nurls, urls);
if (!ldapuri)
_pam_log(LOG_ERR, "%s", strerror(errno));
- ber_memvfree ((void **)urls);
+ ber_memvfree((void **)urls);
return ldapuri;
}
@@ -312,14 +312,14 @@ ldap_connect(struct gray_env *env)
unsigned long lval;
if (ldap_debug_level) {
- if (ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL,
+ if (ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL,
&ldap_debug_level)
!= LBER_OPT_SUCCESS )
_pam_log(LOG_ERR,
"cannot set LBER_OPT_DEBUG_LEVEL %d",
ldap_debug_level);
- if (ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL,
+ if (ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL,
&ldap_debug_level)
!= LDAP_OPT_SUCCESS )
_pam_log(LOG_ERR,
@@ -411,7 +411,77 @@ ldap_connect(struct gray_env *env)
}
static int
-ldap_bind (LDAP *ld, struct gray_env *env)
+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;
LDAPMessage *result;
@@ -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;
}
@@ -447,7 +521,8 @@ ldap_bind (LDAP *ld, struct gray_env *env)
&ctrls, 1);
if (rc != LDAP_SUCCESS) {
_pam_log(LOG_ERR, "ldap_parse_result failed: %s",
- ldap_err2string (rc));
+ 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);
}
@@ -783,7 +860,7 @@ read_link_name(const char *name, char **pbuf, size_t *psize, size_t *plen)
if (rc) {
if (buf) {
- free (buf);
+ free(buf);
buf = NULL;
}
size = 0;
@@ -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);
@@ -1156,12 +1235,26 @@ store_pubkeys(char **keys, struct passwd *pw)
if (pw->pw_dir[homelen - 1] != '/')
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.