diff options
Diffstat (limited to 'auth-pam.c')
-rw-r--r-- | auth-pam.c | 65 |
1 files changed, 45 insertions, 20 deletions
diff --git a/auth-pam.c b/auth-pam.c index 6ce8c429b..0446cd559 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.121 2005/01/20 02:29:51 dtucker Exp $"); | 50 | RCSID("$Id: auth-pam.c,v 1.126 2005/07/17 07:18:50 djm 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) |
@@ -56,6 +56,13 @@ RCSID("$Id: auth-pam.c,v 1.121 2005/01/20 02:29:51 dtucker Exp $"); | |||
56 | #include <pam/pam_appl.h> | 56 | #include <pam/pam_appl.h> |
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | /* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */ | ||
60 | #ifdef PAM_SUN_CODEBASE | ||
61 | # define sshpam_const /* Solaris, HP-UX, AIX */ | ||
62 | #else | ||
63 | # define sshpam_const const /* LinuxPAM, OpenPAM */ | ||
64 | #endif | ||
65 | |||
59 | #include "auth.h" | 66 | #include "auth.h" |
60 | #include "auth-pam.h" | 67 | #include "auth-pam.h" |
61 | #include "buffer.h" | 68 | #include "buffer.h" |
@@ -76,7 +83,17 @@ extern Buffer loginmsg; | |||
76 | extern int compat20; | 83 | extern int compat20; |
77 | extern u_int utmp_len; | 84 | extern u_int utmp_len; |
78 | 85 | ||
86 | /* so we don't silently change behaviour */ | ||
79 | #ifdef USE_POSIX_THREADS | 87 | #ifdef USE_POSIX_THREADS |
88 | # error "USE_POSIX_THREADS replaced by UNSUPPORTED_POSIX_THREADS_HACK" | ||
89 | #endif | ||
90 | |||
91 | /* | ||
92 | * Formerly known as USE_POSIX_THREADS, using this is completely unsupported | ||
93 | * and generally a bad idea. Use at own risk and do not expect support if | ||
94 | * this breaks. | ||
95 | */ | ||
96 | #ifdef UNSUPPORTED_POSIX_THREADS_HACK | ||
80 | #include <pthread.h> | 97 | #include <pthread.h> |
81 | /* | 98 | /* |
82 | * Avoid namespace clash when *not* using pthreads for systems *with* | 99 | * Avoid namespace clash when *not* using pthreads for systems *with* |
@@ -98,7 +115,7 @@ struct pam_ctxt { | |||
98 | static void sshpam_free_ctx(void *); | 115 | static void sshpam_free_ctx(void *); |
99 | static struct pam_ctxt *cleanup_ctxt; | 116 | static struct pam_ctxt *cleanup_ctxt; |
100 | 117 | ||
101 | #ifndef USE_POSIX_THREADS | 118 | #ifndef UNSUPPORTED_POSIX_THREADS_HACK |
102 | /* | 119 | /* |
103 | * Simulate threads with processes. | 120 | * Simulate threads with processes. |
104 | */ | 121 | */ |
@@ -106,14 +123,14 @@ static struct pam_ctxt *cleanup_ctxt; | |||
106 | static int sshpam_thread_status = -1; | 123 | static int sshpam_thread_status = -1; |
107 | static mysig_t sshpam_oldsig; | 124 | static mysig_t sshpam_oldsig; |
108 | 125 | ||
109 | static void | 126 | static void |
110 | sshpam_sigchld_handler(int sig) | 127 | sshpam_sigchld_handler(int sig) |
111 | { | 128 | { |
112 | signal(SIGCHLD, SIG_DFL); | 129 | signal(SIGCHLD, SIG_DFL); |
113 | if (cleanup_ctxt == NULL) | 130 | if (cleanup_ctxt == NULL) |
114 | return; /* handler called after PAM cleanup, shouldn't happen */ | 131 | return; /* handler called after PAM cleanup, shouldn't happen */ |
115 | if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG) | 132 | if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG) |
116 | <= 0) { | 133 | <= 0) { |
117 | /* PAM thread has not exitted, privsep slave must have */ | 134 | /* PAM thread has not exitted, privsep slave must have */ |
118 | kill(cleanup_ctxt->pam_thread, SIGTERM); | 135 | kill(cleanup_ctxt->pam_thread, SIGTERM); |
119 | if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0) | 136 | if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0) |
@@ -140,6 +157,7 @@ pthread_create(sp_pthread_t *thread, const void *attr __unused, | |||
140 | void *(*thread_start)(void *), void *arg) | 157 | void *(*thread_start)(void *), void *arg) |
141 | { | 158 | { |
142 | pid_t pid; | 159 | pid_t pid; |
160 | struct pam_ctxt *ctx = arg; | ||
143 | 161 | ||
144 | sshpam_thread_status = -1; | 162 | sshpam_thread_status = -1; |
145 | switch ((pid = fork())) { | 163 | switch ((pid = fork())) { |
@@ -147,10 +165,14 @@ pthread_create(sp_pthread_t *thread, const void *attr __unused, | |||
147 | error("fork(): %s", strerror(errno)); | 165 | error("fork(): %s", strerror(errno)); |
148 | return (-1); | 166 | return (-1); |
149 | case 0: | 167 | case 0: |
168 | close(ctx->pam_psock); | ||
169 | ctx->pam_psock = -1; | ||
150 | thread_start(arg); | 170 | thread_start(arg); |
151 | _exit(1); | 171 | _exit(1); |
152 | default: | 172 | default: |
153 | *thread = pid; | 173 | *thread = pid; |
174 | close(ctx->pam_csock); | ||
175 | ctx->pam_csock = -1; | ||
154 | sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler); | 176 | sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler); |
155 | return (0); | 177 | return (0); |
156 | } | 178 | } |
@@ -255,7 +277,7 @@ import_environments(Buffer *b) | |||
255 | 277 | ||
256 | debug3("PAM: %s entering", __func__); | 278 | debug3("PAM: %s entering", __func__); |
257 | 279 | ||
258 | #ifndef USE_POSIX_THREADS | 280 | #ifndef UNSUPPORTED_POSIX_THREADS_HACK |
259 | /* Import variables set by do_pam_account */ | 281 | /* Import variables set by do_pam_account */ |
260 | sshpam_account_status = buffer_get_int(b); | 282 | sshpam_account_status = buffer_get_int(b); |
261 | sshpam_password_change_required(buffer_get_int(b)); | 283 | sshpam_password_change_required(buffer_get_int(b)); |
@@ -290,7 +312,7 @@ import_environments(Buffer *b) | |||
290 | * Conversation function for authentication thread. | 312 | * Conversation function for authentication thread. |
291 | */ | 313 | */ |
292 | static int | 314 | static int |
293 | sshpam_thread_conv(int n, struct pam_message **msg, | 315 | sshpam_thread_conv(int n, sshpam_const struct pam_message **msg, |
294 | struct pam_response **resp, void *data) | 316 | struct pam_response **resp, void *data) |
295 | { | 317 | { |
296 | Buffer buffer; | 318 | Buffer buffer; |
@@ -384,13 +406,15 @@ sshpam_thread(void *ctxtp) | |||
384 | struct pam_conv sshpam_conv; | 406 | struct pam_conv sshpam_conv; |
385 | int flags = (options.permit_empty_passwd == 0 ? | 407 | int flags = (options.permit_empty_passwd == 0 ? |
386 | PAM_DISALLOW_NULL_AUTHTOK : 0); | 408 | PAM_DISALLOW_NULL_AUTHTOK : 0); |
387 | #ifndef USE_POSIX_THREADS | 409 | #ifndef UNSUPPORTED_POSIX_THREADS_HACK |
388 | extern char **environ; | 410 | extern char **environ; |
389 | char **env_from_pam; | 411 | char **env_from_pam; |
390 | u_int i; | 412 | u_int i; |
391 | const char *pam_user; | 413 | const char *pam_user; |
414 | const char **ptr_pam_user = &pam_user; | ||
392 | 415 | ||
393 | pam_get_item(sshpam_handle, PAM_USER, (void **)&pam_user); | 416 | pam_get_item(sshpam_handle, PAM_USER, |
417 | (sshpam_const void **)ptr_pam_user); | ||
394 | environ[0] = NULL; | 418 | environ[0] = NULL; |
395 | 419 | ||
396 | if (sshpam_authctxt != NULL) { | 420 | if (sshpam_authctxt != NULL) { |
@@ -428,7 +452,7 @@ sshpam_thread(void *ctxtp) | |||
428 | 452 | ||
429 | buffer_put_cstring(&buffer, "OK"); | 453 | buffer_put_cstring(&buffer, "OK"); |
430 | 454 | ||
431 | #ifndef USE_POSIX_THREADS | 455 | #ifndef UNSUPPORTED_POSIX_THREADS_HACK |
432 | /* Export variables set by do_pam_account */ | 456 | /* Export variables set by do_pam_account */ |
433 | buffer_put_int(&buffer, sshpam_account_status); | 457 | buffer_put_int(&buffer, sshpam_account_status); |
434 | buffer_put_int(&buffer, sshpam_authctxt->force_pwchange); | 458 | buffer_put_int(&buffer, sshpam_authctxt->force_pwchange); |
@@ -447,7 +471,7 @@ sshpam_thread(void *ctxtp) | |||
447 | buffer_put_int(&buffer, i); | 471 | buffer_put_int(&buffer, i); |
448 | for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) | 472 | for(i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) |
449 | buffer_put_cstring(&buffer, env_from_pam[i]); | 473 | buffer_put_cstring(&buffer, env_from_pam[i]); |
450 | #endif /* USE_POSIX_THREADS */ | 474 | #endif /* UNSUPPORTED_POSIX_THREADS_HACK */ |
451 | 475 | ||
452 | /* XXX - can't do much about an error here */ | 476 | /* XXX - can't do much about an error here */ |
453 | ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer); | 477 | ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer); |
@@ -482,7 +506,7 @@ sshpam_thread_cleanup(void) | |||
482 | } | 506 | } |
483 | 507 | ||
484 | static int | 508 | static int |
485 | sshpam_null_conv(int n, struct pam_message **msg, | 509 | sshpam_null_conv(int n, sshpam_const struct pam_message **msg, |
486 | struct pam_response **resp, void *data) | 510 | struct pam_response **resp, void *data) |
487 | { | 511 | { |
488 | debug3("PAM: %s entering, %d messages", __func__, n); | 512 | debug3("PAM: %s entering, %d messages", __func__, n); |
@@ -492,7 +516,7 @@ sshpam_null_conv(int n, struct pam_message **msg, | |||
492 | static struct pam_conv null_conv = { sshpam_null_conv, NULL }; | 516 | static struct pam_conv null_conv = { sshpam_null_conv, NULL }; |
493 | 517 | ||
494 | static int | 518 | static int |
495 | sshpam_store_conv(int n, struct pam_message **msg, | 519 | sshpam_store_conv(int n, sshpam_const struct pam_message **msg, |
496 | struct pam_response **resp, void *data) | 520 | struct pam_response **resp, void *data) |
497 | { | 521 | { |
498 | struct pam_response *reply; | 522 | struct pam_response *reply; |
@@ -561,11 +585,12 @@ sshpam_init(Authctxt *authctxt) | |||
561 | { | 585 | { |
562 | extern char *__progname; | 586 | extern char *__progname; |
563 | const char *pam_rhost, *pam_user, *user = authctxt->user; | 587 | const char *pam_rhost, *pam_user, *user = authctxt->user; |
588 | const char **ptr_pam_user = &pam_user; | ||
564 | 589 | ||
565 | if (sshpam_handle != NULL) { | 590 | if (sshpam_handle != NULL) { |
566 | /* We already have a PAM context; check if the user matches */ | 591 | /* We already have a PAM context; check if the user matches */ |
567 | sshpam_err = pam_get_item(sshpam_handle, | 592 | sshpam_err = pam_get_item(sshpam_handle, |
568 | PAM_USER, (void **)&pam_user); | 593 | PAM_USER, (sshpam_const void **)ptr_pam_user); |
569 | if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0) | 594 | if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0) |
570 | return (0); | 595 | return (0); |
571 | pam_end(sshpam_handle, sshpam_err); | 596 | pam_end(sshpam_handle, sshpam_err); |
@@ -755,7 +780,7 @@ sshpam_respond(void *ctx, u_int num, char **resp) | |||
755 | buffer_init(&buffer); | 780 | buffer_init(&buffer); |
756 | if (sshpam_authctxt->valid && | 781 | if (sshpam_authctxt->valid && |
757 | (sshpam_authctxt->pw->pw_uid != 0 || | 782 | (sshpam_authctxt->pw->pw_uid != 0 || |
758 | options.permit_root_login == PERMIT_YES)) | 783 | options.permit_root_login == PERMIT_YES)) |
759 | buffer_put_cstring(&buffer, *resp); | 784 | buffer_put_cstring(&buffer, *resp); |
760 | else | 785 | else |
761 | buffer_put_cstring(&buffer, badpw); | 786 | buffer_put_cstring(&buffer, badpw); |
@@ -828,7 +853,7 @@ do_pam_account(void) | |||
828 | sshpam_err = pam_acct_mgmt(sshpam_handle, 0); | 853 | sshpam_err = pam_acct_mgmt(sshpam_handle, 0); |
829 | debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err, | 854 | debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err, |
830 | pam_strerror(sshpam_handle, sshpam_err)); | 855 | pam_strerror(sshpam_handle, sshpam_err)); |
831 | 856 | ||
832 | if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) { | 857 | if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) { |
833 | sshpam_account_status = 0; | 858 | sshpam_account_status = 0; |
834 | return (sshpam_account_status); | 859 | return (sshpam_account_status); |
@@ -881,7 +906,7 @@ do_pam_setcred(int init) | |||
881 | } | 906 | } |
882 | 907 | ||
883 | static int | 908 | static int |
884 | sshpam_tty_conv(int n, struct pam_message **msg, | 909 | sshpam_tty_conv(int n, sshpam_const struct pam_message **msg, |
885 | struct pam_response **resp, void *data) | 910 | struct pam_response **resp, void *data) |
886 | { | 911 | { |
887 | char input[PAM_MAX_MSG_SIZE]; | 912 | char input[PAM_MAX_MSG_SIZE]; |
@@ -1040,7 +1065,7 @@ free_pam_environment(char **env) | |||
1040 | * display. | 1065 | * display. |
1041 | */ | 1066 | */ |
1042 | static int | 1067 | static int |
1043 | sshpam_passwd_conv(int n, struct pam_message **msg, | 1068 | sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg, |
1044 | struct pam_response **resp, void *data) | 1069 | struct pam_response **resp, void *data) |
1045 | { | 1070 | { |
1046 | struct pam_response *reply; | 1071 | struct pam_response *reply; |
@@ -1086,7 +1111,7 @@ sshpam_passwd_conv(int n, struct pam_message **msg, | |||
1086 | *resp = reply; | 1111 | *resp = reply; |
1087 | return (PAM_SUCCESS); | 1112 | return (PAM_SUCCESS); |
1088 | 1113 | ||
1089 | fail: | 1114 | fail: |
1090 | for(i = 0; i < n; i++) { | 1115 | for(i = 0; i < n; i++) { |
1091 | if (reply[i].resp != NULL) | 1116 | if (reply[i].resp != NULL) |
1092 | xfree(reply[i].resp); | 1117 | xfree(reply[i].resp); |
@@ -1119,7 +1144,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password) | |||
1119 | * information via timing (eg if the PAM config has a delay on fail). | 1144 | * information via timing (eg if the PAM config has a delay on fail). |
1120 | */ | 1145 | */ |
1121 | if (!authctxt->valid || (authctxt->pw->pw_uid == 0 && | 1146 | if (!authctxt->valid || (authctxt->pw->pw_uid == 0 && |
1122 | options.permit_root_login != PERMIT_YES)) | 1147 | options.permit_root_login != PERMIT_YES)) |
1123 | sshpam_password = badpw; | 1148 | sshpam_password = badpw; |
1124 | 1149 | ||
1125 | sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, | 1150 | sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, |
@@ -1133,7 +1158,7 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password) | |||
1133 | if (sshpam_err == PAM_SUCCESS && authctxt->valid) { | 1158 | if (sshpam_err == PAM_SUCCESS && authctxt->valid) { |
1134 | debug("PAM: password authentication accepted for %.100s", | 1159 | debug("PAM: password authentication accepted for %.100s", |
1135 | authctxt->user); | 1160 | authctxt->user); |
1136 | return 1; | 1161 | return 1; |
1137 | } else { | 1162 | } else { |
1138 | debug("PAM: password authentication failed for %.100s: %s", | 1163 | debug("PAM: password authentication failed for %.100s: %s", |
1139 | authctxt->valid ? authctxt->user : "an illegal user", | 1164 | authctxt->valid ? authctxt->user : "an illegal user", |