summaryrefslogtreecommitdiff
path: root/auth-pam.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth-pam.c')
-rw-r--r--auth-pam.c85
1 files changed, 63 insertions, 22 deletions
diff --git a/auth-pam.c b/auth-pam.c
index fb9ae954a..c08d47229 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -47,7 +47,16 @@
47 47
48/* Based on $FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */ 48/* Based on $FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */
49#include "includes.h" 49#include "includes.h"
50RCSID("$Id: auth-pam.c,v 1.128 2006/01/29 05:46:13 dtucker Exp $"); 50
51#include <sys/types.h>
52#include <sys/stat.h>
53#include <sys/wait.h>
54
55#include <errno.h>
56#include <signal.h>
57#include <stdarg.h>
58#include <string.h>
59#include <unistd.h>
51 60
52#ifdef USE_PAM 61#ifdef USE_PAM
53#if defined(HAVE_SECURITY_PAM_APPL_H) 62#if defined(HAVE_SECURITY_PAM_APPL_H)
@@ -63,20 +72,31 @@ RCSID("$Id: auth-pam.c,v 1.128 2006/01/29 05:46:13 dtucker Exp $");
63# define sshpam_const const /* LinuxPAM, OpenPAM */ 72# define sshpam_const const /* LinuxPAM, OpenPAM */
64#endif 73#endif
65 74
75/* Ambiguity in spec: is it an array of pointers or a pointer to an array? */
76#ifdef PAM_SUN_CODEBASE
77# define PAM_MSG_MEMBER(msg, n, member) ((*(msg))[(n)].member)
78#else
79# define PAM_MSG_MEMBER(msg, n, member) ((msg)[(n)]->member)
80#endif
81
82#include "xmalloc.h"
83#include "buffer.h"
84#include "key.h"
85#include "hostfile.h"
66#include "auth.h" 86#include "auth.h"
67#include "auth-pam.h" 87#include "auth-pam.h"
68#include "buffer.h"
69#include "bufaux.h"
70#include "canohost.h" 88#include "canohost.h"
71#include "log.h" 89#include "log.h"
72#include "monitor_wrap.h"
73#include "msg.h" 90#include "msg.h"
74#include "packet.h" 91#include "packet.h"
75#include "misc.h" 92#include "misc.h"
76#include "servconf.h" 93#include "servconf.h"
77#include "ssh2.h" 94#include "ssh2.h"
78#include "xmalloc.h"
79#include "auth-options.h" 95#include "auth-options.h"
96#ifdef GSSAPI
97#include "ssh-gss.h"
98#endif
99#include "monitor_wrap.h"
80 100
81extern ServerOptions options; 101extern ServerOptions options;
82extern Buffer loginmsg; 102extern Buffer loginmsg;
@@ -146,14 +166,16 @@ sshpam_sigchld_handler(int sig)
146 fatal("PAM: authentication thread exited uncleanly"); 166 fatal("PAM: authentication thread exited uncleanly");
147} 167}
148 168
169/* ARGSUSED */
149static void 170static void
150pthread_exit(void *value __unused) 171pthread_exit(void *value)
151{ 172{
152 _exit(0); 173 _exit(0);
153} 174}
154 175
176/* ARGSUSED */
155static int 177static int
156pthread_create(sp_pthread_t *thread, const void *attr __unused, 178pthread_create(sp_pthread_t *thread, const void *attr,
157 void *(*thread_start)(void *), void *arg) 179 void *(*thread_start)(void *), void *arg)
158{ 180{
159 pid_t pid; 181 pid_t pid;
@@ -185,8 +207,9 @@ pthread_cancel(sp_pthread_t thread)
185 return (kill(thread, SIGTERM)); 207 return (kill(thread, SIGTERM));
186} 208}
187 209
210/* ARGSUSED */
188static int 211static int
189pthread_join(sp_pthread_t thread, void **value __unused) 212pthread_join(sp_pthread_t thread, void **value)
190{ 213{
191 int status; 214 int status;
192 215
@@ -284,7 +307,10 @@ import_environments(Buffer *b)
284 307
285 /* Import environment from subprocess */ 308 /* Import environment from subprocess */
286 num_env = buffer_get_int(b); 309 num_env = buffer_get_int(b);
287 sshpam_env = xmalloc((num_env + 1) * sizeof(*sshpam_env)); 310 if (num_env > 1024)
311 fatal("%s: received %u environment variables, expected <= 1024",
312 __func__, num_env);
313 sshpam_env = xcalloc(num_env + 1, sizeof(*sshpam_env));
288 debug3("PAM: num env strings %d", num_env); 314 debug3("PAM: num env strings %d", num_env);
289 for(i = 0; i < num_env; i++) 315 for(i = 0; i < num_env; i++)
290 sshpam_env[i] = buffer_get_string(b, NULL); 316 sshpam_env[i] = buffer_get_string(b, NULL);
@@ -331,9 +357,8 @@ sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
331 if (n <= 0 || n > PAM_MAX_NUM_MSG) 357 if (n <= 0 || n > PAM_MAX_NUM_MSG)
332 return (PAM_CONV_ERR); 358 return (PAM_CONV_ERR);
333 359
334 if ((reply = malloc(n * sizeof(*reply))) == NULL) 360 if ((reply = calloc(n, sizeof(*reply))) == NULL)
335 return (PAM_CONV_ERR); 361 return (PAM_CONV_ERR);
336 memset(reply, 0, n * sizeof(*reply));
337 362
338 buffer_init(&buffer); 363 buffer_init(&buffer);
339 for (i = 0; i < n; ++i) { 364 for (i = 0; i < n; ++i) {
@@ -412,10 +437,16 @@ sshpam_thread(void *ctxtp)
412 u_int i; 437 u_int i;
413 const char *pam_user; 438 const char *pam_user;
414 const char **ptr_pam_user = &pam_user; 439 const char **ptr_pam_user = &pam_user;
440 char *tz = getenv("TZ");
415 441
416 pam_get_item(sshpam_handle, PAM_USER, 442 pam_get_item(sshpam_handle, PAM_USER,
417 (sshpam_const void **)ptr_pam_user); 443 (sshpam_const void **)ptr_pam_user);
444
418 environ[0] = NULL; 445 environ[0] = NULL;
446 if (tz != NULL)
447 if (setenv("TZ", tz, 1) == -1)
448 error("PAM: could not set TZ environment: %s",
449 strerror(errno));
419 450
420 if (sshpam_authctxt != NULL) { 451 if (sshpam_authctxt != NULL) {
421 setproctitle("%s [pam]", 452 setproctitle("%s [pam]",
@@ -439,8 +470,10 @@ sshpam_thread(void *ctxtp)
439 goto auth_fail; 470 goto auth_fail;
440 471
441 if (compat20) { 472 if (compat20) {
442 if (!do_pam_account()) 473 if (!do_pam_account()) {
474 sshpam_err = PAM_ACCT_EXPIRED;
443 goto auth_fail; 475 goto auth_fail;
476 }
444 if (sshpam_authctxt->force_pwchange) { 477 if (sshpam_authctxt->force_pwchange) {
445 sshpam_err = pam_chauthtok(sshpam_handle, 478 sshpam_err = pam_chauthtok(sshpam_handle,
446 PAM_CHANGE_EXPIRED_AUTHTOK); 479 PAM_CHANGE_EXPIRED_AUTHTOK);
@@ -482,7 +515,10 @@ sshpam_thread(void *ctxtp)
482 buffer_put_cstring(&buffer, 515 buffer_put_cstring(&buffer,
483 pam_strerror(sshpam_handle, sshpam_err)); 516 pam_strerror(sshpam_handle, sshpam_err));
484 /* XXX - can't do much about an error here */ 517 /* XXX - can't do much about an error here */
485 ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer); 518 if (sshpam_err == PAM_ACCT_EXPIRED)
519 ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, &buffer);
520 else
521 ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer);
486 buffer_free(&buffer); 522 buffer_free(&buffer);
487 pthread_exit(NULL); 523 pthread_exit(NULL);
488 524
@@ -529,9 +565,8 @@ sshpam_store_conv(int n, sshpam_const struct pam_message **msg,
529 if (n <= 0 || n > PAM_MAX_NUM_MSG) 565 if (n <= 0 || n > PAM_MAX_NUM_MSG)
530 return (PAM_CONV_ERR); 566 return (PAM_CONV_ERR);
531 567
532 if ((reply = malloc(n * sizeof(*reply))) == NULL) 568 if ((reply = calloc(n, sizeof(*reply))) == NULL)
533 return (PAM_CONV_ERR); 569 return (PAM_CONV_ERR);
534 memset(reply, 0, n * sizeof(*reply));
535 570
536 for (i = 0; i < n; ++i) { 571 for (i = 0; i < n; ++i) {
537 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 572 switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
@@ -638,8 +673,11 @@ sshpam_init_ctx(Authctxt *authctxt)
638 int socks[2]; 673 int socks[2];
639 674
640 debug3("PAM: %s entering", __func__); 675 debug3("PAM: %s entering", __func__);
641 /* Refuse to start if we don't have PAM enabled */ 676 /*
642 if (!options.use_pam) 677 * Refuse to start if we don't have PAM enabled or do_pam_account
678 * has previously failed.
679 */
680 if (!options.use_pam || sshpam_account_status == 0)
643 return NULL; 681 return NULL;
644 682
645 /* Initialize PAM */ 683 /* Initialize PAM */
@@ -699,7 +737,7 @@ sshpam_query(void *ctx, char **name, char **info,
699 case PAM_PROMPT_ECHO_OFF: 737 case PAM_PROMPT_ECHO_OFF:
700 *num = 1; 738 *num = 1;
701 len = plen + mlen + 1; 739 len = plen + mlen + 1;
702 **prompts = xrealloc(**prompts, len); 740 **prompts = xrealloc(**prompts, 1, len);
703 strlcpy(**prompts + plen, msg, len - plen); 741 strlcpy(**prompts + plen, msg, len - plen);
704 plen += mlen; 742 plen += mlen;
705 **echo_on = (type == PAM_PROMPT_ECHO_ON); 743 **echo_on = (type == PAM_PROMPT_ECHO_ON);
@@ -709,21 +747,25 @@ sshpam_query(void *ctx, char **name, char **info,
709 case PAM_TEXT_INFO: 747 case PAM_TEXT_INFO:
710 /* accumulate messages */ 748 /* accumulate messages */
711 len = plen + mlen + 2; 749 len = plen + mlen + 2;
712 **prompts = xrealloc(**prompts, len); 750 **prompts = xrealloc(**prompts, 1, len);
713 strlcpy(**prompts + plen, msg, len - plen); 751 strlcpy(**prompts + plen, msg, len - plen);
714 plen += mlen; 752 plen += mlen;
715 strlcat(**prompts + plen, "\n", len - plen); 753 strlcat(**prompts + plen, "\n", len - plen);
716 plen++; 754 plen++;
717 xfree(msg); 755 xfree(msg);
718 break; 756 break;
757 case PAM_ACCT_EXPIRED:
758 sshpam_account_status = 0;
759 /* FALLTHROUGH */
719 case PAM_AUTH_ERR: 760 case PAM_AUTH_ERR:
720 debug3("PAM: PAM_AUTH_ERR"); 761 debug3("PAM: %s", pam_strerror(sshpam_handle, type));
721 if (**prompts != NULL && strlen(**prompts) != 0) { 762 if (**prompts != NULL && strlen(**prompts) != 0) {
722 *info = **prompts; 763 *info = **prompts;
723 **prompts = NULL; 764 **prompts = NULL;
724 *num = 0; 765 *num = 0;
725 **echo_on = 0; 766 **echo_on = 0;
726 ctxt->pam_done = -1; 767 ctxt->pam_done = -1;
768 xfree(msg);
727 return 0; 769 return 0;
728 } 770 }
729 /* FALLTHROUGH */ 771 /* FALLTHROUGH */
@@ -930,9 +972,8 @@ sshpam_tty_conv(int n, sshpam_const struct pam_message **msg,
930 if (n <= 0 || n > PAM_MAX_NUM_MSG || !isatty(STDIN_FILENO)) 972 if (n <= 0 || n > PAM_MAX_NUM_MSG || !isatty(STDIN_FILENO))
931 return (PAM_CONV_ERR); 973 return (PAM_CONV_ERR);
932 974
933 if ((reply = malloc(n * sizeof(*reply))) == NULL) 975 if ((reply = calloc(n, sizeof(*reply))) == NULL)
934 return (PAM_CONV_ERR); 976 return (PAM_CONV_ERR);
935 memset(reply, 0, n * sizeof(*reply));
936 977
937 for (i = 0; i < n; ++i) { 978 for (i = 0; i < n; ++i) {
938 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 979 switch (PAM_MSG_MEMBER(msg, i, msg_style)) {