summaryrefslogtreecommitdiff
path: root/auth-pam.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth-pam.c')
-rw-r--r--auth-pam.c65
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"
50RCSID("$Id: auth-pam.c,v 1.121 2005/01/20 02:29:51 dtucker Exp $"); 50RCSID("$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;
76extern int compat20; 83extern int compat20;
77extern u_int utmp_len; 84extern 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 {
98static void sshpam_free_ctx(void *); 115static void sshpam_free_ctx(void *);
99static struct pam_ctxt *cleanup_ctxt; 116static 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;
106static int sshpam_thread_status = -1; 123static int sshpam_thread_status = -1;
107static mysig_t sshpam_oldsig; 124static mysig_t sshpam_oldsig;
108 125
109static void 126static void
110sshpam_sigchld_handler(int sig) 127sshpam_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 */
292static int 314static int
293sshpam_thread_conv(int n, struct pam_message **msg, 315sshpam_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
484static int 508static int
485sshpam_null_conv(int n, struct pam_message **msg, 509sshpam_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,
492static struct pam_conv null_conv = { sshpam_null_conv, NULL }; 516static struct pam_conv null_conv = { sshpam_null_conv, NULL };
493 517
494static int 518static int
495sshpam_store_conv(int n, struct pam_message **msg, 519sshpam_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
883static int 908static int
884sshpam_tty_conv(int n, struct pam_message **msg, 909sshpam_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 */
1042static int 1067static int
1043sshpam_passwd_conv(int n, struct pam_message **msg, 1068sshpam_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",