summaryrefslogtreecommitdiff
path: root/auth-pam.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2016-08-06 10:49:59 +0100
committerColin Watson <cjwatson@debian.org>2016-08-07 12:18:58 +0100
commit477bb7636238c106f8cd7c868a8c0c5eabcfb3db (patch)
tree601176af2ecf358c36b766776a86845ad7a3cd6f /auth-pam.c
parent747fac2de0d889183f67f6900194c0462c558544 (diff)
parent4c914ccd85bbf391c4dc61b85e3c178fef465e3f (diff)
New upstream release (7.3p1).
Diffstat (limited to 'auth-pam.c')
-rw-r--r--auth-pam.c72
1 files changed, 46 insertions, 26 deletions
diff --git a/auth-pam.c b/auth-pam.c
index abd6a5e1b..348fe370a 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -68,9 +68,9 @@
68 68
69/* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */ 69/* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */
70#ifdef PAM_SUN_CODEBASE 70#ifdef PAM_SUN_CODEBASE
71# define sshpam_const /* Solaris, HP-UX, AIX */ 71# define sshpam_const /* Solaris, HP-UX, SunOS */
72#else 72#else
73# define sshpam_const const /* LinuxPAM, OpenPAM */ 73# define sshpam_const const /* LinuxPAM, OpenPAM, AIX */
74#endif 74#endif
75 75
76/* Ambiguity in spec: is it an array of pointers or a pointer to an array? */ 76/* Ambiguity in spec: is it an array of pointers or a pointer to an array? */
@@ -154,9 +154,12 @@ sshpam_sigchld_handler(int sig)
154 <= 0) { 154 <= 0) {
155 /* PAM thread has not exitted, privsep slave must have */ 155 /* PAM thread has not exitted, privsep slave must have */
156 kill(cleanup_ctxt->pam_thread, SIGTERM); 156 kill(cleanup_ctxt->pam_thread, SIGTERM);
157 if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0) 157 while (waitpid(cleanup_ctxt->pam_thread,
158 <= 0) 158 &sshpam_thread_status, 0) == -1) {
159 return; /* could not wait */ 159 if (errno == EINTR)
160 continue;
161 return;
162 }
160 } 163 }
161 if (WIFSIGNALED(sshpam_thread_status) && 164 if (WIFSIGNALED(sshpam_thread_status) &&
162 WTERMSIG(sshpam_thread_status) == SIGTERM) 165 WTERMSIG(sshpam_thread_status) == SIGTERM)
@@ -217,7 +220,11 @@ pthread_join(sp_pthread_t thread, void **value)
217 if (sshpam_thread_status != -1) 220 if (sshpam_thread_status != -1)
218 return (sshpam_thread_status); 221 return (sshpam_thread_status);
219 signal(SIGCHLD, sshpam_oldsig); 222 signal(SIGCHLD, sshpam_oldsig);
220 waitpid(thread, &status, 0); 223 while (waitpid(thread, &status, 0) == -1) {
224 if (errno == EINTR)
225 continue;
226 fatal("%s: waitpid: %s", __func__, strerror(errno));
227 }
221 return (status); 228 return (status);
222} 229}
223#endif 230#endif
@@ -229,6 +236,7 @@ static int sshpam_authenticated = 0;
229static int sshpam_session_open = 0; 236static int sshpam_session_open = 0;
230static int sshpam_cred_established = 0; 237static int sshpam_cred_established = 0;
231static int sshpam_account_status = -1; 238static int sshpam_account_status = -1;
239static int sshpam_maxtries_reached = 0;
232static char **sshpam_env = NULL; 240static char **sshpam_env = NULL;
233static Authctxt *sshpam_authctxt = NULL; 241static Authctxt *sshpam_authctxt = NULL;
234static const char *sshpam_password = NULL; 242static const char *sshpam_password = NULL;
@@ -364,17 +372,6 @@ sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
364 for (i = 0; i < n; ++i) { 372 for (i = 0; i < n; ++i) {
365 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 373 switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
366 case PAM_PROMPT_ECHO_OFF: 374 case PAM_PROMPT_ECHO_OFF:
367 buffer_put_cstring(&buffer,
368 PAM_MSG_MEMBER(msg, i, msg));
369 if (ssh_msg_send(ctxt->pam_csock,
370 PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
371 goto fail;
372 if (ssh_msg_recv(ctxt->pam_csock, &buffer) == -1)
373 goto fail;
374 if (buffer_get_char(&buffer) != PAM_AUTHTOK)
375 goto fail;
376 reply[i].resp = buffer_get_string(&buffer, NULL);
377 break;
378 case PAM_PROMPT_ECHO_ON: 375 case PAM_PROMPT_ECHO_ON:
379 buffer_put_cstring(&buffer, 376 buffer_put_cstring(&buffer,
380 PAM_MSG_MEMBER(msg, i, msg)); 377 PAM_MSG_MEMBER(msg, i, msg));
@@ -388,12 +385,6 @@ sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
388 reply[i].resp = buffer_get_string(&buffer, NULL); 385 reply[i].resp = buffer_get_string(&buffer, NULL);
389 break; 386 break;
390 case PAM_ERROR_MSG: 387 case PAM_ERROR_MSG:
391 buffer_put_cstring(&buffer,
392 PAM_MSG_MEMBER(msg, i, msg));
393 if (ssh_msg_send(ctxt->pam_csock,
394 PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
395 goto fail;
396 break;
397 case PAM_TEXT_INFO: 388 case PAM_TEXT_INFO:
398 buffer_put_cstring(&buffer, 389 buffer_put_cstring(&buffer,
399 PAM_MSG_MEMBER(msg, i, msg)); 390 PAM_MSG_MEMBER(msg, i, msg));
@@ -467,6 +458,8 @@ sshpam_thread(void *ctxtp)
467 if (sshpam_err != PAM_SUCCESS) 458 if (sshpam_err != PAM_SUCCESS)
468 goto auth_fail; 459 goto auth_fail;
469 sshpam_err = pam_authenticate(sshpam_handle, flags); 460 sshpam_err = pam_authenticate(sshpam_handle, flags);
461 if (sshpam_err == PAM_MAXTRIES)
462 sshpam_set_maxtries_reached(1);
470 if (sshpam_err != PAM_SUCCESS) 463 if (sshpam_err != PAM_SUCCESS)
471 goto auth_fail; 464 goto auth_fail;
472 465
@@ -518,6 +511,8 @@ sshpam_thread(void *ctxtp)
518 /* XXX - can't do much about an error here */ 511 /* XXX - can't do much about an error here */
519 if (sshpam_err == PAM_ACCT_EXPIRED) 512 if (sshpam_err == PAM_ACCT_EXPIRED)
520 ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, &buffer); 513 ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, &buffer);
514 else if (sshpam_maxtries_reached)
515 ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, &buffer);
521 else 516 else
522 ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer); 517 ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer);
523 buffer_free(&buffer); 518 buffer_free(&buffer);
@@ -623,6 +618,7 @@ sshpam_init(Authctxt *authctxt)
623 extern char *__progname; 618 extern char *__progname;
624 const char *pam_rhost, *pam_user, *user = authctxt->user; 619 const char *pam_rhost, *pam_user, *user = authctxt->user;
625 const char **ptr_pam_user = &pam_user; 620 const char **ptr_pam_user = &pam_user;
621 struct ssh *ssh = active_state; /* XXX */
626 622
627 if (sshpam_handle != NULL) { 623 if (sshpam_handle != NULL) {
628 /* We already have a PAM context; check if the user matches */ 624 /* We already have a PAM context; check if the user matches */
@@ -643,7 +639,7 @@ sshpam_init(Authctxt *authctxt)
643 sshpam_handle = NULL; 639 sshpam_handle = NULL;
644 return (-1); 640 return (-1);
645 } 641 }
646 pam_rhost = get_remote_name_or_ip(utmp_len, options.use_dns); 642 pam_rhost = auth_get_canonical_hostname(ssh, options.use_dns);
647 debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost); 643 debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost);
648 sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost); 644 sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
649 if (sshpam_err != PAM_SUCCESS) { 645 if (sshpam_err != PAM_SUCCESS) {
@@ -714,6 +710,7 @@ static int
714sshpam_query(void *ctx, char **name, char **info, 710sshpam_query(void *ctx, char **name, char **info,
715 u_int *num, char ***prompts, u_int **echo_on) 711 u_int *num, char ***prompts, u_int **echo_on)
716{ 712{
713 struct ssh *ssh = active_state; /* XXX */
717 Buffer buffer; 714 Buffer buffer;
718 struct pam_ctxt *ctxt = ctx; 715 struct pam_ctxt *ctxt = ctx;
719 size_t plen; 716 size_t plen;
@@ -756,7 +753,11 @@ sshpam_query(void *ctx, char **name, char **info,
756 free(msg); 753 free(msg);
757 break; 754 break;
758 case PAM_ACCT_EXPIRED: 755 case PAM_ACCT_EXPIRED:
759 sshpam_account_status = 0; 756 case PAM_MAXTRIES:
757 if (type == PAM_ACCT_EXPIRED)
758 sshpam_account_status = 0;
759 if (type == PAM_MAXTRIES)
760 sshpam_set_maxtries_reached(1);
760 /* FALLTHROUGH */ 761 /* FALLTHROUGH */
761 case PAM_AUTH_ERR: 762 case PAM_AUTH_ERR:
762 debug3("PAM: %s", pam_strerror(sshpam_handle, type)); 763 debug3("PAM: %s", pam_strerror(sshpam_handle, type));
@@ -796,7 +797,7 @@ sshpam_query(void *ctx, char **name, char **info,
796 error("PAM: %s for %s%.100s from %.100s", msg, 797 error("PAM: %s for %s%.100s from %.100s", msg,
797 sshpam_authctxt->valid ? "" : "illegal user ", 798 sshpam_authctxt->valid ? "" : "illegal user ",
798 sshpam_authctxt->user, 799 sshpam_authctxt->user,
799 get_remote_name_or_ip(utmp_len, options.use_dns)); 800 auth_get_canonical_hostname(ssh, options.use_dns));
800 /* FALLTHROUGH */ 801 /* FALLTHROUGH */
801 default: 802 default:
802 *num = 0; 803 *num = 0;
@@ -1233,6 +1234,8 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
1233 sshpam_err = pam_authenticate(sshpam_handle, flags); 1234 sshpam_err = pam_authenticate(sshpam_handle, flags);
1234 sshpam_password = NULL; 1235 sshpam_password = NULL;
1235 free(fake); 1236 free(fake);
1237 if (sshpam_err == PAM_MAXTRIES)
1238 sshpam_set_maxtries_reached(1);
1236 if (sshpam_err == PAM_SUCCESS && authctxt->valid) { 1239 if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
1237 debug("PAM: password authentication accepted for %.100s", 1240 debug("PAM: password authentication accepted for %.100s",
1238 authctxt->user); 1241 authctxt->user);
@@ -1244,4 +1247,21 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
1244 return 0; 1247 return 0;
1245 } 1248 }
1246} 1249}
1250
1251int
1252sshpam_get_maxtries_reached(void)
1253{
1254 return sshpam_maxtries_reached;
1255}
1256
1257void
1258sshpam_set_maxtries_reached(int reached)
1259{
1260 if (reached == 0 || sshpam_maxtries_reached)
1261 return;
1262 sshpam_maxtries_reached = 1;
1263 options.password_authentication = 0;
1264 options.kbd_interactive_authentication = 0;
1265 options.challenge_response_authentication = 0;
1266}
1247#endif /* USE_PAM */ 1267#endif /* USE_PAM */