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 | 124 | ||||
-rw-r--r-- | pamck/pamck.c | 2 |
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 | |||
1213 | password for simple authentication. | 1213 | password for simple authentication. |
1214 | @end deffn | 1214 | @end deffn |
1215 | 1215 | ||
1216 | @deffn {pam_ldaphome config} bindpwfile file | ||
1217 | Read password for simple authentication from @var{file}. | ||
1218 | @end deffn | ||
1219 | |||
1216 | @deffn {pam_ldaphome config} tls val | 1220 | @deffn {pam_ldaphome config} tls val |
1217 | Controls whether TLS is desired or required. If @var{val} is | 1221 | Controls whether TLS is desired or required. If @var{val} is |
1218 | @samp{no} (the default), TLS will not be used. If it is @samp{yes}, | 1222 | @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. | |||
1259 | Sets the mode (octal) for the created user directories. | 1263 | Sets the mode (octal) for the created user directories. |
1260 | @end deffn | 1264 | @end deffn |
1261 | 1265 | ||
1266 | @deffn {pam_ldaphome config} keyfile-mode mode | ||
1267 | Sets the mode (octal) for the created authorized keys file. | ||
1268 | @end deffn | ||
1269 | |||
1262 | @deffn {pam_ldaphome config} authorized_keys name | 1270 | @deffn {pam_ldaphome config} authorized_keys name |
1263 | Sets the pathname (relative to the home directory) for the authorized | 1271 | Sets the pathname (relative to the home directory) for the authorized |
1264 | keys file. The default is @samp{.ssh/authorized_keys}. For normal | 1272 | 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) | |||
202 | char *domain = NULL, *hostlist = NULL; | 202 | char *domain = NULL, *hostlist = NULL; |
203 | size_t i; | 203 | size_t i; |
204 | 204 | ||
205 | if (ldap_dn2domain (lud->lud_dn, &domain) || | 205 | if (ldap_dn2domain(lud->lud_dn, &domain) || |
206 | !domain) { | 206 | !domain) { |
207 | _pam_log(LOG_ERR, | 207 | _pam_log(LOG_ERR, |
208 | "DNS SRV: cannot convert " | 208 | "DNS SRV: cannot convert " |
@@ -288,14 +288,14 @@ parse_ldap_uri(const char *uri) | |||
288 | } | 288 | } |
289 | 289 | ||
290 | if (ludlist) { | 290 | if (ludlist) { |
291 | ldap_free_urldesc (ludlist); | 291 | ldap_free_urldesc(ludlist); |
292 | return NULL; | 292 | return NULL; |
293 | } else if (!urls) | 293 | } else if (!urls) |
294 | return NULL; | 294 | return NULL; |
295 | ldapuri = argcv_concat(nurls, urls); | 295 | ldapuri = argcv_concat(nurls, urls); |
296 | if (!ldapuri) | 296 | if (!ldapuri) |
297 | _pam_log(LOG_ERR, "%s", strerror(errno)); | 297 | _pam_log(LOG_ERR, "%s", strerror(errno)); |
298 | ber_memvfree ((void **)urls); | 298 | ber_memvfree((void **)urls); |
299 | return ldapuri; | 299 | return ldapuri; |
300 | } | 300 | } |
301 | 301 | ||
@@ -312,14 +312,14 @@ ldap_connect(struct gray_env *env) | |||
312 | unsigned long lval; | 312 | unsigned long lval; |
313 | 313 | ||
314 | if (ldap_debug_level) { | 314 | if (ldap_debug_level) { |
315 | if (ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL, | 315 | if (ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, |
316 | &ldap_debug_level) | 316 | &ldap_debug_level) |
317 | != LBER_OPT_SUCCESS ) | 317 | != LBER_OPT_SUCCESS ) |
318 | _pam_log(LOG_ERR, | 318 | _pam_log(LOG_ERR, |
319 | "cannot set LBER_OPT_DEBUG_LEVEL %d", | 319 | "cannot set LBER_OPT_DEBUG_LEVEL %d", |
320 | ldap_debug_level); | 320 | ldap_debug_level); |
321 | 321 | ||
322 | if (ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, | 322 | if (ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, |
323 | &ldap_debug_level) | 323 | &ldap_debug_level) |
324 | != LDAP_OPT_SUCCESS ) | 324 | != LDAP_OPT_SUCCESS ) |
325 | _pam_log(LOG_ERR, | 325 | _pam_log(LOG_ERR, |
@@ -411,7 +411,77 @@ ldap_connect(struct gray_env *env) | |||
411 | } | 411 | } |
412 | 412 | ||
413 | static int | 413 | static int |
414 | ldap_bind (LDAP *ld, struct gray_env *env) | 414 | full_read(int fd, char *file, char *buf, size_t size) |
415 | { | ||
416 | while (size) { | ||
417 | ssize_t n; | ||
418 | |||
419 | n = read(fd, buf, size); | ||
420 | if (n == -1) { | ||
421 | if (errno == EAGAIN || errno == EINTR) | ||
422 | continue; | ||
423 | _pam_log(LOG_ERR, "error reading from %s: %s", | ||
424 | file, strerror(errno)); | ||
425 | return -1; | ||
426 | } else if (n == 0) { | ||
427 | _pam_log(LOG_ERR, "short read from %s", file); | ||
428 | return -1; | ||
429 | } | ||
430 | |||
431 | buf += n; | ||
432 | size -= n; | ||
433 | } | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static int | ||
438 | get_passwd(struct gray_env *env, struct berval *pwd, char **palloc) | ||
439 | { | ||
440 | char *file; | ||
441 | |||
442 | file = gray_env_get(env, "bindpwfile"); | ||
443 | if (file) { | ||
444 | struct stat st; | ||
445 | int fd, rc; | ||
446 | char *mem, *p; | ||
447 | |||
448 | fd = open(file, O_RDONLY); | ||
449 | if (fd == -1) { | ||
450 | _pam_log(LOG_ERR, "can't open password file %s: %s", | ||
451 | file, strerror(errno)); | ||
452 | return -1; | ||
453 | } | ||
454 | if (fstat(fd, &st)) { | ||
455 | _pam_log(LOG_ERR, "can't stat password file %s: %s", | ||
456 | file, strerror(errno)); | ||
457 | close(fd); | ||
458 | return -1; | ||
459 | } | ||
460 | mem = malloc(st.st_size + 1); | ||
461 | if (!mem) { | ||
462 | _pam_log(LOG_ERR, "can't allocate memory (%lu bytes)", | ||
463 | (unsigned long) st.st_size+1); | ||
464 | close(fd); | ||
465 | return -1; | ||
466 | } | ||
467 | rc = full_read(fd, file, mem, st.st_size); | ||
468 | close(fd); | ||
469 | if (rc) | ||
470 | return rc; | ||
471 | mem[st.st_size] = 0; | ||
472 | p = strchr(mem, '\n'); | ||
473 | if (p) | ||
474 | *p = 0; | ||
475 | *palloc = mem; | ||
476 | pwd->bv_val = mem; | ||
477 | } else | ||
478 | pwd->bv_val = gray_env_get(env, "bindpw"); | ||
479 | pwd->bv_len = pwd->bv_val ? strlen(pwd->bv_val) : 0; | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static int | ||
484 | ldap_bind(LDAP *ld, struct gray_env *env) | ||
415 | { | 485 | { |
416 | int msgid, err, rc; | 486 | int msgid, err, rc; |
417 | LDAPMessage *result; | 487 | LDAPMessage *result; |
@@ -420,12 +490,14 @@ ldap_bind (LDAP *ld, struct gray_env *env) | |||
420 | char *matched = NULL; | 490 | char *matched = NULL; |
421 | char *info = NULL; | 491 | char *info = NULL; |
422 | char **refs = NULL; | 492 | char **refs = NULL; |
423 | static struct berval passwd; | 493 | struct berval passwd; |
424 | char *binddn; | 494 | char *binddn; |
495 | char *alloc_ptr = NULL; | ||
425 | 496 | ||
426 | binddn = gray_env_get(env, "binddn"); | 497 | binddn = gray_env_get(env, "binddn"); |
427 | passwd.bv_val = gray_env_get(env, "bindpw"); | 498 | |
428 | passwd.bv_len = passwd.bv_val ? strlen(passwd.bv_val) : 0; | 499 | if (get_passwd(env, &passwd, &alloc_ptr)) |
500 | return 1; | ||
429 | 501 | ||
430 | msgbuf[0] = 0; | 502 | msgbuf[0] = 0; |
431 | 503 | ||
@@ -435,11 +507,13 @@ ldap_bind (LDAP *ld, struct gray_env *env) | |||
435 | _pam_log(LOG_ERR, | 507 | _pam_log(LOG_ERR, |
436 | "ldap_sasl_bind(SIMPLE) failed: %s", | 508 | "ldap_sasl_bind(SIMPLE) failed: %s", |
437 | ldap_err2string(rc)); | 509 | ldap_err2string(rc)); |
510 | free(alloc_ptr); | ||
438 | return 1; | 511 | return 1; |
439 | } | 512 | } |
440 | 513 | ||
441 | if (ldap_result(ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1) { | 514 | if (ldap_result(ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1) { |
442 | _pam_log(LOG_ERR, "ldap_result failed"); | 515 | _pam_log(LOG_ERR, "ldap_result failed"); |
516 | free(alloc_ptr); | ||
443 | return 1; | 517 | return 1; |
444 | } | 518 | } |
445 | 519 | ||
@@ -447,7 +521,8 @@ ldap_bind (LDAP *ld, struct gray_env *env) | |||
447 | &ctrls, 1); | 521 | &ctrls, 1); |
448 | if (rc != LDAP_SUCCESS) { | 522 | if (rc != LDAP_SUCCESS) { |
449 | _pam_log(LOG_ERR, "ldap_parse_result failed: %s", | 523 | _pam_log(LOG_ERR, "ldap_parse_result failed: %s", |
450 | ldap_err2string (rc)); |