diff options
Diffstat (limited to 'auth-pam.c')
-rw-r--r-- | auth-pam.c | 140 |
1 files changed, 82 insertions, 58 deletions
diff --git a/auth-pam.c b/auth-pam.c index 147f4f8bb..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" |
50 | RCSID("$Id: auth-pam.c,v 1.114 2004/08/16 13:12:06 dtucker Exp $"); | 50 | RCSID("$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) |
@@ -185,8 +185,8 @@ static int sshpam_cred_established = 0; | |||
185 | static int sshpam_account_status = -1; | 185 | static int sshpam_account_status = -1; |
186 | static char **sshpam_env = NULL; | 186 | static char **sshpam_env = NULL; |
187 | static Authctxt *sshpam_authctxt = NULL; | 187 | static Authctxt *sshpam_authctxt = NULL; |
188 | static char badpw[] = "\b\n\r\177INCORRECT"; | ||
189 | static const char *sshpam_password = NULL; | 188 | static const char *sshpam_password = NULL; |
189 | static char badpw[] = "\b\n\r\177INCORRECT"; | ||
190 | 190 | ||
191 | /* Some PAM implementations don't implement this */ | 191 | /* Some PAM implementations don't implement this */ |
192 | #ifndef HAVE_PAM_GETENVLIST | 192 | #ifndef HAVE_PAM_GETENVLIST |
@@ -491,6 +491,51 @@ sshpam_null_conv(int n, struct pam_message **msg, | |||
491 | 491 | ||
492 | static struct pam_conv null_conv = { sshpam_null_conv, NULL }; | 492 | static struct pam_conv null_conv = { sshpam_null_conv, NULL }; |
493 | 493 | ||
494 | static int | ||
495 | sshpam_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 | |||
537 | static struct pam_conv store_conv = { sshpam_store_conv, NULL }; | ||
538 | |||
494 | void | 539 | void |
495 | sshpam_cleanup(void) | 540 | sshpam_cleanup(void) |
496 | { | 541 | { |
@@ -528,7 +573,7 @@ sshpam_init(Authctxt *authctxt) | |||
528 | } | 573 | } |
529 | debug("PAM: initializing for \"%s\"", user); | 574 | debug("PAM: initializing for \"%s\"", user); |
530 | sshpam_err = | 575 | sshpam_err = |
531 | pam_start(SSHD_PAM_SERVICE, user, &null_conv, &sshpam_handle); | 576 | pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle); |
532 | sshpam_authctxt = authctxt; | 577 | sshpam_authctxt = authctxt; |
533 | 578 | ||
534 | if (sshpam_err != PAM_SUCCESS) { | 579 | if (sshpam_err != PAM_SUCCESS) { |
@@ -610,7 +655,7 @@ sshpam_query(void *ctx, char **name, char **info, | |||
610 | size_t plen; | 655 | size_t plen; |
611 | u_char type; | 656 | u_char type; |
612 | char *msg; | 657 | char *msg; |
613 | size_t len; | 658 | size_t len, mlen; |
614 | 659 | ||
615 | debug3("PAM: %s entering", __func__); | 660 | debug3("PAM: %s entering", __func__); |
616 | buffer_init(&buffer); | 661 | buffer_init(&buffer); |
@@ -623,22 +668,27 @@ sshpam_query(void *ctx, char **name, char **info, | |||
623 | while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) { | 668 | while (ssh_msg_recv(ctxt->pam_psock, &buffer) == 0) { |
624 | type = buffer_get_char(&buffer); | 669 | type = buffer_get_char(&buffer); |
625 | msg = buffer_get_string(&buffer, NULL); | 670 | msg = buffer_get_string(&buffer, NULL); |
671 | mlen = strlen(msg); | ||
626 | switch (type) { | 672 | switch (type) { |
627 | case PAM_PROMPT_ECHO_ON: | 673 | case PAM_PROMPT_ECHO_ON: |
628 | case PAM_PROMPT_ECHO_OFF: | 674 | case PAM_PROMPT_ECHO_OFF: |
629 | *num = 1; | 675 | *num = 1; |
630 | len = plen + strlen(msg) + 1; | 676 | len = plen + mlen + 1; |
631 | **prompts = xrealloc(**prompts, len); | 677 | **prompts = xrealloc(**prompts, len); |
632 | plen += snprintf(**prompts + plen, len, "%s", msg); | 678 | strlcpy(**prompts + plen, msg, len - plen); |
679 | plen += mlen; | ||
633 | **echo_on = (type == PAM_PROMPT_ECHO_ON); | 680 | **echo_on = (type == PAM_PROMPT_ECHO_ON); |
634 | xfree(msg); | 681 | xfree(msg); |
635 | return (0); | 682 | return (0); |
636 | case PAM_ERROR_MSG: | 683 | case PAM_ERROR_MSG: |
637 | case PAM_TEXT_INFO: | 684 | case PAM_TEXT_INFO: |
638 | /* accumulate messages */ | 685 | /* accumulate messages */ |
639 | len = plen + strlen(msg) + 2; | 686 | len = plen + mlen + 2; |
640 | **prompts = xrealloc(**prompts, len); | 687 | **prompts = xrealloc(**prompts, len); |
641 | 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++; | ||
642 | xfree(msg); | 692 | xfree(msg); |
643 | break; | 693 | break; |
644 | case PAM_SUCCESS: | 694 | case PAM_SUCCESS: |
@@ -652,6 +702,12 @@ sshpam_query(void *ctx, char **name, char **info, | |||
652 | **prompts = NULL; | 702 | **prompts = NULL; |
653 | } | 703 | } |
654 | 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"); | ||
655 | import_environments(&buffer); | 711 | import_environments(&buffer); |
656 | *num = 0; | 712 | *num = 0; |
657 | **echo_on = 0; | 713 | **echo_on = 0; |
@@ -765,11 +821,13 @@ finish_pam(void) | |||
765 | u_int | 821 | u_int |
766 | do_pam_account(void) | 822 | do_pam_account(void) |
767 | { | 823 | { |
824 | debug("%s: called", __func__); | ||
768 | if (sshpam_account_status != -1) | 825 | if (sshpam_account_status != -1) |
769 | return (sshpam_account_status); | 826 | return (sshpam_account_status); |
770 | 827 | ||
771 | sshpam_err = pam_acct_mgmt(sshpam_handle, 0); | 828 | sshpam_err = pam_acct_mgmt(sshpam_handle, 0); |
772 | 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)); | ||
773 | 831 | ||
774 | if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) { | 832 | if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) { |
775 | sshpam_account_status = 0; | 833 | sshpam_account_status = 0; |
@@ -799,7 +857,7 @@ void | |||
799 | do_pam_setcred(int init) | 857 | do_pam_setcred(int init) |
800 | { | 858 | { |
801 | sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, | 859 | sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, |
802 | (const void *)&null_conv); | 860 | (const void *)&store_conv); |
803 | if (sshpam_err != PAM_SUCCESS) | 861 | if (sshpam_err != PAM_SUCCESS) |
804 | fatal("PAM: failed to set PAM_CONV: %s", | 862 | fatal("PAM: failed to set PAM_CONV: %s", |
805 | pam_strerror(sshpam_handle, sshpam_err)); | 863 | pam_strerror(sshpam_handle, sshpam_err)); |
@@ -900,51 +958,6 @@ do_pam_chauthtok(void) | |||
900 | pam_strerror(sshpam_handle, sshpam_err)); | 958 | pam_strerror(sshpam_handle, sshpam_err)); |
901 | } | 959 | } |
902 | 960 | ||
903 | static int | ||
904 | sshpam_store_conv(int n, struct pam_message **msg, | ||
905 | struct pam_response **resp, void *data) | ||
906 | { | ||
907 | struct pam_response *reply; | ||
908 | int i; | ||
909 | size_t len; | ||
910 | |||
911 | debug3("PAM: %s called with %d messages", __func__, n); | ||
912 | *resp = NULL; | ||
913 | |||
914 | if (n <= 0 || n > PAM_MAX_NUM_MSG) | ||
915 | return (PAM_CONV_ERR); | ||
916 | |||
917 | if ((reply = malloc(n * sizeof(*reply))) == NULL) | ||
918 | return (PAM_CONV_ERR); | ||
919 | memset(reply, 0, n * sizeof(*reply)); | ||
920 | |||
921 | for (i = 0; i < n; ++i) { | ||
922 | switch (PAM_MSG_MEMBER(msg, i, msg_style)) { | ||
923 | case PAM_ERROR_MSG: | ||
924 | case PAM_TEXT_INFO: | ||
925 | len = strlen(PAM_MSG_MEMBER(msg, i, msg)); | ||
926 | buffer_append(&loginmsg, PAM_MSG_MEMBER(msg, i, msg), len); | ||
927 | buffer_append(&loginmsg, "\n", 1 ); | ||
928 | reply[i].resp_retcode = PAM_SUCCESS; | ||
929 | break; | ||
930 | default: | ||
931 | goto fail; | ||
932 | } | ||
933 | } | ||
934 | *resp = reply; | ||
935 | return (PAM_SUCCESS); | ||
936 | |||
937 | fail: | ||
938 | for(i = 0; i < n; i++) { | ||
939 | if (reply[i].resp != NULL) | ||
940 | xfree(reply[i].resp); | ||
941 | } | ||
942 | xfree(reply); | ||
943 | return (PAM_CONV_ERR); | ||
944 | } | ||
945 | |||
946 | static struct pam_conv store_conv = { sshpam_store_conv, NULL }; | ||
947 | |||
948 | void | 961 | void |
949 | do_pam_session(void) | 962 | do_pam_session(void) |
950 | { | 963 | { |
@@ -955,10 +968,21 @@ do_pam_session(void) | |||
955 | fatal("PAM: failed to set PAM_CONV: %s", | 968 | fatal("PAM: failed to set PAM_CONV: %s", |
956 | pam_strerror(sshpam_handle, sshpam_err)); | 969 | pam_strerror(sshpam_handle, sshpam_err)); |
957 | sshpam_err = pam_open_session(sshpam_handle, 0); | 970 | sshpam_err = pam_open_session(sshpam_handle, 0); |
958 | if (sshpam_err != PAM_SUCCESS) | 971 | if (sshpam_err == PAM_SUCCESS) |
959 | 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", | ||
960 | pam_strerror(sshpam_handle, sshpam_err)); | 977 | pam_strerror(sshpam_handle, sshpam_err)); |
961 | sshpam_session_open = 1; | 978 | } |
979 | |||
980 | } | ||
981 | |||
982 | int | ||
983 | is_pam_session_open(void) | ||
984 | { | ||
985 | return sshpam_session_open; | ||
962 | } | 986 | } |
963 | 987 | ||
964 | /* | 988 | /* |