summaryrefslogtreecommitdiff
path: root/auth-pam.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth-pam.c')
-rw-r--r--auth-pam.c147
1 files changed, 88 insertions, 59 deletions
diff --git a/auth-pam.c b/auth-pam.c
index b93241f48..6ce8c429b 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -47,7 +47,7 @@
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.114 2004/08/16 13:12:06 dtucker Exp $"); 50RCSID("$Id: auth-pam.c,v 1.121 2005/01/20 02:29:51 dtucker Exp $");
51 51
52#ifdef USE_PAM 52#ifdef USE_PAM
53#if defined(HAVE_SECURITY_PAM_APPL_H) 53#if defined(HAVE_SECURITY_PAM_APPL_H)
@@ -186,6 +186,7 @@ static int sshpam_account_status = -1;
186static char **sshpam_env = NULL; 186static char **sshpam_env = NULL;
187static Authctxt *sshpam_authctxt = NULL; 187static Authctxt *sshpam_authctxt = NULL;
188static const char *sshpam_password = NULL; 188static const char *sshpam_password = NULL;
189static char badpw[] = "\b\n\r\177INCORRECT";
189 190
190/* Some PAM implementations don't implement this */ 191/* Some PAM implementations don't implement this */
191#ifndef HAVE_PAM_GETENVLIST 192#ifndef HAVE_PAM_GETENVLIST
@@ -490,6 +491,51 @@ sshpam_null_conv(int n, struct pam_message **msg,
490 491
491static struct pam_conv null_conv = { sshpam_null_conv, NULL }; 492static struct pam_conv null_conv = { sshpam_null_conv, NULL };
492 493
494static int
495sshpam_store_conv(int n, struct pam_message **msg,
496 struct pam_response **resp, void *data)
497{
498 struct pam_response *reply;
499 int i;
500 size_t len;
501
502 debug3("PAM: %s called with %d messages", __func__, n);
503 *resp = NULL;
504
505 if (n <= 0 || n > PAM_MAX_NUM_MSG)
506 return (PAM_CONV_ERR);
507
508 if ((reply = malloc(n * sizeof(*reply))) == NULL)
509 return (PAM_CONV_ERR);
510 memset(reply, 0, n * sizeof(*reply));
511
512 for (i = 0; i < n; ++i) {
513 switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
514 case PAM_ERROR_MSG:
515 case PAM_TEXT_INFO:
516 len = strlen(PAM_MSG_MEMBER(msg, i, msg));
517 buffer_append(&loginmsg, PAM_MSG_MEMBER(msg, i, msg), len);
518 buffer_append(&loginmsg, "\n", 1 );
519 reply[i].resp_retcode = PAM_SUCCESS;
520 break;
521 default:
522 goto fail;
523 }
524 }
525 *resp = reply;
526 return (PAM_SUCCESS);
527
528 fail:
529 for(i = 0; i < n; i++) {
530 if (reply[i].resp != NULL)
531 xfree(reply[i].resp);
532 }
533 xfree(reply);
534 return (PAM_CONV_ERR);
535}
536
537static struct pam_conv store_conv = { sshpam_store_conv, NULL };
538
493void 539void
494sshpam_cleanup(void) 540sshpam_cleanup(void)
495{ 541{
@@ -527,7 +573,7 @@ sshpam_init(Authctxt *authctxt)
527 } 573 }
528 debug("PAM: initializing for \"%s\"", user); 574 debug("PAM: initializing for \"%s\"", user);
529 sshpam_err = 575 sshpam_err =
530 pam_start(SSHD_PAM_SERVICE, user, &null_conv, &sshpam_handle); 576 pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);
531 sshpam_authctxt = authctxt; 577 sshpam_authctxt = authctxt;
532 578
533 if (sshpam_err != PAM_SUCCESS) { 579 if (sshpam_err != PAM_SUCCESS) {
@@ -609,7 +655,7 @@ sshpam_query(void *ctx, char **name, char **info,
609 size_t plen; 655 size_t plen;
610 u_char type; 656 u_char type;
611 char *msg; 657 char *msg;
612 size_t len; 658 size_t len, mlen;
613 659
614 debug3("PAM: %s entering", __func__); 660 debug3("PAM: %s entering", __func__);
615 buffer_init(&buffer); 661 buffer_init(&buffer);
@@ -622,22 +668,27 @@ sshpam_query(void *ctx, char **name, char **info,
622 while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) { 668 while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) {
623 type = buffer_get_char(&buffer); 669 type = buffer_get_char(&buffer);
624 msg = buffer_get_string(&buffer, NULL); 670 msg = buffer_get_string(&buffer, NULL);
671 mlen = strlen(msg);
625 switch (type) { 672 switch (type) {
626 case PAM_PROMPT_ECHO_ON: 673 case PAM_PROMPT_ECHO_ON:
627 case PAM_PROMPT_ECHO_OFF: 674 case PAM_PROMPT_ECHO_OFF:
628 *num = 1; 675 *num = 1;
629 len = plen + strlen(msg) + 1; 676 len = plen + mlen + 1;
630 **prompts = xrealloc(**prompts, len); 677 **prompts = xrealloc(**prompts, len);
631 plen += snprintf(**prompts + plen, len, "%s", msg); 678 strlcpy(**prompts + plen, msg, len - plen);
679 plen += mlen;
632 **echo_on = (type == PAM_PROMPT_ECHO_ON); 680 **echo_on = (type == PAM_PROMPT_ECHO_ON);
633 xfree(msg); 681 xfree(msg);
634 return (0); 682 return (0);
635 case PAM_ERROR_MSG: 683 case PAM_ERROR_MSG:
636 case PAM_TEXT_INFO: 684 case PAM_TEXT_INFO:
637 /* accumulate messages */ 685 /* accumulate messages */
638 len = plen + strlen(msg) + 2; 686 len = plen + mlen + 2;
639 **prompts = xrealloc(**prompts, len); 687 **prompts = xrealloc(**prompts, len);
640 plen += snprintf(**prompts + plen, len, "%s\n", msg); 688 strlcpy(**prompts + plen, msg, len - plen);
689 plen += mlen;
690 strlcat(**prompts + plen, "\n", len - plen);
691 plen++;
641 xfree(msg); 692 xfree(msg);
642 break; 693 break;
643 case PAM_SUCCESS: 694 case PAM_SUCCESS:
@@ -651,6 +702,12 @@ sshpam_query(void *ctx, char **name, char **info,
651 **prompts = NULL; 702 **prompts = NULL;
652 } 703 }
653 if (type == PAM_SUCCESS) { 704 if (type == PAM_SUCCESS) {
705 if (!sshpam_authctxt->valid ||
706 (sshpam_authctxt->pw->pw_uid == 0 &&
707 options.permit_root_login != PERMIT_YES))
708 fatal("Internal error: PAM auth "
709 "succeeded when it should have "
710 "failed");
654 import_environments(&buffer); 711 import_environments(&buffer);
655 *num = 0; 712 *num = 0;
656 **echo_on = 0; 713 **echo_on = 0;
@@ -696,7 +753,12 @@ sshpam_respond(void *ctx, u_int num, char **resp)
696 return (-1); 753 return (-1);
697 } 754 }
698 buffer_init(&buffer); 755 buffer_init(&buffer);
699 buffer_put_cstring(&buffer, *resp); 756 if (sshpam_authctxt->valid &&
757 (sshpam_authctxt->pw->pw_uid != 0 ||
758 options.permit_root_login == PERMIT_YES))
759 buffer_put_cstring(&buffer, *resp);
760 else
761 buffer_put_cstring(&buffer, badpw);
700 if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) { 762 if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) {
701 buffer_free(&buffer); 763 buffer_free(&buffer);
702 return (-1); 764 return (-1);
@@ -759,11 +821,13 @@ finish_pam(void)
759u_int 821u_int
760do_pam_account(void) 822do_pam_account(void)
761{ 823{
824 debug("%s: called", __func__);
762 if (sshpam_account_status != -1) 825 if (sshpam_account_status != -1)
763 return (sshpam_account_status); 826 return (sshpam_account_status);
764 827
765 sshpam_err = pam_acct_mgmt(sshpam_handle, 0); 828 sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
766 debug3("PAM: %s pam_acct_mgmt = %d", __func__, sshpam_err); 829 debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
830 pam_strerror(sshpam_handle, sshpam_err));
767 831
768 if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) { 832 if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
769 sshpam_account_status = 0; 833 sshpam_account_status = 0;
@@ -793,7 +857,7 @@ void
793do_pam_setcred(int init) 857do_pam_setcred(int init)
794{ 858{
795 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, 859 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
796 (const void *)&null_conv); 860 (const void *)&store_conv);
797 if (sshpam_err != PAM_SUCCESS) 861 if (sshpam_err != PAM_SUCCESS)
798 fatal("PAM: failed to set PAM_CONV: %s", 862 fatal("PAM: failed to set PAM_CONV: %s",
799 pam_strerror(sshpam_handle, sshpam_err)); 863 pam_strerror(sshpam_handle, sshpam_err));
@@ -894,51 +958,6 @@ do_pam_chauthtok(void)
894 pam_strerror(sshpam_handle, sshpam_err)); 958 pam_strerror(sshpam_handle, sshpam_err));
895} 959}
896 960
897static int
898sshpam_store_conv(int n, struct pam_message **msg,
899 struct pam_response **resp, void *data)
900{
901 struct pam_response *reply;
902 int i;
903 size_t len;
904
905 debug3("PAM: %s called with %d messages", __func__, n);
906 *resp = NULL;
907
908 if (n <= 0 || n > PAM_MAX_NUM_MSG)
909 return (PAM_CONV_ERR);
910
911 if ((reply = malloc(n * sizeof(*reply))) == NULL)
912 return (PAM_CONV_ERR);
913 memset(reply, 0, n * sizeof(*reply));
914
915 for (i = 0; i < n; ++i) {
916 switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
917 case PAM_ERROR_MSG:
918 case PAM_TEXT_INFO:
919 len = strlen(PAM_MSG_MEMBER(msg, i, msg));
920 buffer_append(&loginmsg, PAM_MSG_MEMBER(msg, i, msg), len);
921 buffer_append(&loginmsg, "\n", 1 );
922 reply[i].resp_retcode = PAM_SUCCESS;
923 break;
924 default:
925 goto fail;
926 }
927 }
928 *resp = reply;
929 return (PAM_SUCCESS);
930
931 fail:
932 for(i = 0; i < n; i++) {
933 if (reply[i].resp != NULL)
934 xfree(reply[i].resp);
935 }
936 xfree(reply);
937 return (PAM_CONV_ERR);
938}
939
940static struct pam_conv store_conv = { sshpam_store_conv, NULL };
941
942void 961void
943do_pam_session(void) 962do_pam_session(void)
944{ 963{
@@ -949,10 +968,21 @@ do_pam_session(void)
949 fatal("PAM: failed to set PAM_CONV: %s", 968 fatal("PAM: failed to set PAM_CONV: %s",
950 pam_strerror(sshpam_handle, sshpam_err)); 969 pam_strerror(sshpam_handle, sshpam_err));
951 sshpam_err = pam_open_session(sshpam_handle, 0); 970 sshpam_err = pam_open_session(sshpam_handle, 0);
952 if (sshpam_err != PAM_SUCCESS) 971 if (sshpam_err == PAM_SUCCESS)
953 fatal("PAM: pam_open_session(): %s", 972 sshpam_session_open = 1;
973 else {
974 sshpam_session_open = 0;
975 disable_forwarding();
976 error("PAM: pam_open_session(): %s",
954 pam_strerror(sshpam_handle, sshpam_err)); 977 pam_strerror(sshpam_handle, sshpam_err));
955 sshpam_session_open = 1; 978 }
979
980}
981
982int
983is_pam_session_open(void)
984{
985 return sshpam_session_open;
956} 986}
957 987
958/* 988/*
@@ -1075,7 +1105,6 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
1075{ 1105{
1076 int flags = (options.permit_empty_passwd == 0 ? 1106 int flags = (options.permit_empty_passwd == 0 ?
1077 PAM_DISALLOW_NULL_AUTHTOK : 0); 1107 PAM_DISALLOW_NULL_AUTHTOK : 0);
1078 static char badpw[] = "\b\n\r\177INCORRECT";
1079 1108
1080 if (!options.use_pam || sshpam_handle == NULL) 1109 if (!options.use_pam || sshpam_handle == NULL)
1081 fatal("PAM: %s called when PAM disabled or failed to " 1110 fatal("PAM: %s called when PAM disabled or failed to "