Deleted Added
full compact
auth-pam.c (147005) auth-pam.c (149753)
1/*-
2 * Copyright (c) 2002 Networks Associates Technology, Inc.
3 * All rights reserved.
4 *
5 * This software was developed for the FreeBSD Project by ThinkSec AS and
6 * NAI Labs, the Security Research Division of Network Associates, Inc.
7 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
8 * DARPA CHATS research program.

--- 33 unchanged lines hidden (view full) ---

42 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
43 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
44 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
45 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
46 */
47
48/* Based on $xFreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */
49#include "includes.h"
1/*-
2 * Copyright (c) 2002 Networks Associates Technology, Inc.
3 * All rights reserved.
4 *
5 * This software was developed for the FreeBSD Project by ThinkSec AS and
6 * NAI Labs, the Security Research Division of Network Associates, Inc.
7 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
8 * DARPA CHATS research program.

--- 33 unchanged lines hidden (view full) ---

42 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
43 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
44 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
45 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
46 */
47
48/* Based on $xFreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */
49#include "includes.h"
50RCSID("$Id: auth-pam.c,v 1.122 2005/05/25 06:18:10 dtucker Exp $");
51RCSID("$FreeBSD: head/crypto/openssh/auth-pam.c 147005 2005-06-05 15:46:09Z des $");
50RCSID("$Id: auth-pam.c,v 1.126 2005/07/17 07:18:50 djm Exp $");
51RCSID("$FreeBSD: head/crypto/openssh/auth-pam.c 149753 2005-09-03 07:04:25Z des $");
52
53#ifdef USE_PAM
54#if defined(HAVE_SECURITY_PAM_APPL_H)
55#include <security/pam_appl.h>
56#elif defined (HAVE_PAM_PAM_APPL_H)
57#include <pam/pam_appl.h>
58#endif
59
52
53#ifdef USE_PAM
54#if defined(HAVE_SECURITY_PAM_APPL_H)
55#include <security/pam_appl.h>
56#elif defined (HAVE_PAM_PAM_APPL_H)
57#include <pam/pam_appl.h>
58#endif
59
60/* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */
61#ifdef PAM_SUN_CODEBASE
62# define sshpam_const /* Solaris, HP-UX, AIX */
63#else
64# define sshpam_const const /* LinuxPAM, OpenPAM */
65#endif
66
60#include "auth.h"
61#include "auth-pam.h"
62#include "buffer.h"
63#include "bufaux.h"
64#include "canohost.h"
65#include "log.h"
66#include "monitor_wrap.h"
67#include "msg.h"

--- 44 unchanged lines hidden (view full) ---

112#ifndef UNSUPPORTED_POSIX_THREADS_HACK
113/*
114 * Simulate threads with processes.
115 */
116
117static int sshpam_thread_status = -1;
118static mysig_t sshpam_oldsig;
119
67#include "auth.h"
68#include "auth-pam.h"
69#include "buffer.h"
70#include "bufaux.h"
71#include "canohost.h"
72#include "log.h"
73#include "monitor_wrap.h"
74#include "msg.h"

--- 44 unchanged lines hidden (view full) ---

119#ifndef UNSUPPORTED_POSIX_THREADS_HACK
120/*
121 * Simulate threads with processes.
122 */
123
124static int sshpam_thread_status = -1;
125static mysig_t sshpam_oldsig;
126
120static void
127static void
121sshpam_sigchld_handler(int sig)
122{
123 signal(SIGCHLD, SIG_DFL);
124 if (cleanup_ctxt == NULL)
125 return; /* handler called after PAM cleanup, shouldn't happen */
126 if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG)
128sshpam_sigchld_handler(int sig)
129{
130 signal(SIGCHLD, SIG_DFL);
131 if (cleanup_ctxt == NULL)
132 return; /* handler called after PAM cleanup, shouldn't happen */
133 if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG)
127 <= 0) {
134 <= 0) {
128 /* PAM thread has not exitted, privsep slave must have */
129 kill(cleanup_ctxt->pam_thread, SIGTERM);
130 if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0)
131 <= 0)
132 return; /* could not wait */
133 }
134 if (WIFSIGNALED(sshpam_thread_status) &&
135 WTERMSIG(sshpam_thread_status) == SIGTERM)

--- 10 unchanged lines hidden (view full) ---

146 _exit(0);
147}
148
149static int
150pthread_create(sp_pthread_t *thread, const void *attr __unused,
151 void *(*thread_start)(void *), void *arg)
152{
153 pid_t pid;
135 /* PAM thread has not exitted, privsep slave must have */
136 kill(cleanup_ctxt->pam_thread, SIGTERM);
137 if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0)
138 <= 0)
139 return; /* could not wait */
140 }
141 if (WIFSIGNALED(sshpam_thread_status) &&
142 WTERMSIG(sshpam_thread_status) == SIGTERM)

--- 10 unchanged lines hidden (view full) ---

153 _exit(0);
154}
155
156static int
157pthread_create(sp_pthread_t *thread, const void *attr __unused,
158 void *(*thread_start)(void *), void *arg)
159{
160 pid_t pid;
161 struct pam_ctxt *ctx = arg;
154
155 sshpam_thread_status = -1;
156 switch ((pid = fork())) {
157 case -1:
158 error("fork(): %s", strerror(errno));
159 return (-1);
160 case 0:
162
163 sshpam_thread_status = -1;
164 switch ((pid = fork())) {
165 case -1:
166 error("fork(): %s", strerror(errno));
167 return (-1);
168 case 0:
169 close(ctx->pam_psock);
170 ctx->pam_psock = -1;
161 thread_start(arg);
162 _exit(1);
163 default:
164 *thread = pid;
171 thread_start(arg);
172 _exit(1);
173 default:
174 *thread = pid;
175 close(ctx->pam_csock);
176 ctx->pam_csock = -1;
165 sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler);
166 return (0);
167 }
168}
169
170static int
171pthread_cancel(sp_pthread_t thread)
172{

--- 123 unchanged lines hidden (view full) ---

296 }
297#endif
298}
299
300/*
301 * Conversation function for authentication thread.
302 */
303static int
177 sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler);
178 return (0);
179 }
180}
181
182static int
183pthread_cancel(sp_pthread_t thread)
184{

--- 123 unchanged lines hidden (view full) ---

308 }
309#endif
310}
311
312/*
313 * Conversation function for authentication thread.
314 */
315static int
304sshpam_thread_conv(int n, struct pam_message **msg,
316sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
305 struct pam_response **resp, void *data)
306{
307 Buffer buffer;
308 struct pam_ctxt *ctxt;
309 struct pam_response *reply;
310 int i;
311
312 debug3("PAM: %s entering, %d messages", __func__, n);

--- 82 unchanged lines hidden (view full) ---

395 struct pam_conv sshpam_conv;
396 int flags = (options.permit_empty_passwd == 0 ?
397 PAM_DISALLOW_NULL_AUTHTOK : 0);
398#ifndef UNSUPPORTED_POSIX_THREADS_HACK
399 extern char **environ;
400 char **env_from_pam;
401 u_int i;
402 const char *pam_user;
317 struct pam_response **resp, void *data)
318{
319 Buffer buffer;
320 struct pam_ctxt *ctxt;
321 struct pam_response *reply;
322 int i;
323
324 debug3("PAM: %s entering, %d messages", __func__, n);

--- 82 unchanged lines hidden (view full) ---

407 struct pam_conv sshpam_conv;
408 int flags = (options.permit_empty_passwd == 0 ?
409 PAM_DISALLOW_NULL_AUTHTOK : 0);
410#ifndef UNSUPPORTED_POSIX_THREADS_HACK
411 extern char **environ;
412 char **env_from_pam;
413 u_int i;
414 const char *pam_user;
415 const char **ptr_pam_user = &pam_user;
403
416
404 pam_get_item(sshpam_handle, PAM_USER, (void **)&pam_user);
417 pam_get_item(sshpam_handle, PAM_USER,
418 (sshpam_const void **)ptr_pam_user);
405 environ[0] = NULL;
406
407 if (sshpam_authctxt != NULL) {
408 setproctitle("%s [pam]",
409 sshpam_authctxt->valid ? pam_user : "unknown");
410 }
411#endif
412

--- 75 unchanged lines hidden (view full) ---

488 close(ctxt->pam_psock);
489 close(ctxt->pam_csock);
490 memset(ctxt, 0, sizeof(*ctxt));
491 cleanup_ctxt = NULL;
492 }
493}
494
495static int
419 environ[0] = NULL;
420
421 if (sshpam_authctxt != NULL) {
422 setproctitle("%s [pam]",
423 sshpam_authctxt->valid ? pam_user : "unknown");
424 }
425#endif
426

--- 75 unchanged lines hidden (view full) ---

502 close(ctxt->pam_psock);
503 close(ctxt->pam_csock);
504 memset(ctxt, 0, sizeof(*ctxt));
505 cleanup_ctxt = NULL;
506 }
507}
508
509static int
496sshpam_null_conv(int n, struct pam_message **msg,
510sshpam_null_conv(int n, sshpam_const struct pam_message **msg,
497 struct pam_response **resp, void *data)
498{
499 debug3("PAM: %s entering, %d messages", __func__, n);
500 return (PAM_CONV_ERR);
501}
502
503static struct pam_conv null_conv = { sshpam_null_conv, NULL };
504
505static int
511 struct pam_response **resp, void *data)
512{
513 debug3("PAM: %s entering, %d messages", __func__, n);
514 return (PAM_CONV_ERR);
515}
516
517static struct pam_conv null_conv = { sshpam_null_conv, NULL };
518
519static int
506sshpam_store_conv(int n, struct pam_message **msg,
520sshpam_store_conv(int n, sshpam_const struct pam_message **msg,
507 struct pam_response **resp, void *data)
508{
509 struct pam_response *reply;
510 int i;
511 size_t len;
512
513 debug3("PAM: %s called with %d messages", __func__, n);
514 *resp = NULL;

--- 52 unchanged lines hidden (view full) ---

567 sshpam_handle = NULL;
568}
569
570static int
571sshpam_init(Authctxt *authctxt)
572{
573 extern char *__progname;
574 const char *pam_rhost, *pam_user, *user = authctxt->user;
521 struct pam_response **resp, void *data)
522{
523 struct pam_response *reply;
524 int i;
525 size_t len;
526
527 debug3("PAM: %s called with %d messages", __func__, n);
528 *resp = NULL;

--- 52 unchanged lines hidden (view full) ---

581 sshpam_handle = NULL;
582}
583
584static int
585sshpam_init(Authctxt *authctxt)
586{
587 extern char *__progname;
588 const char *pam_rhost, *pam_user, *user = authctxt->user;
589 const char **ptr_pam_user = &pam_user;
575
576 if (sshpam_handle != NULL) {
577 /* We already have a PAM context; check if the user matches */
578 sshpam_err = pam_get_item(sshpam_handle,
590
591 if (sshpam_handle != NULL) {
592 /* We already have a PAM context; check if the user matches */
593 sshpam_err = pam_get_item(sshpam_handle,
579 PAM_USER, (void **)&pam_user);
594 PAM_USER, (sshpam_const void **)ptr_pam_user);
580 if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
581 return (0);
582 pam_end(sshpam_handle, sshpam_err);
583 sshpam_handle = NULL;
584 }
585 debug("PAM: initializing for \"%s\"", user);
586 sshpam_err =
587 pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);

--- 173 unchanged lines hidden (view full) ---

761 }
762 if (num != 1) {
763 error("PAM: expected one response, got %u", num);
764 return (-1);
765 }
766 buffer_init(&buffer);
767 if (sshpam_authctxt->valid &&
768 (sshpam_authctxt->pw->pw_uid != 0 ||
595 if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
596 return (0);
597 pam_end(sshpam_handle, sshpam_err);
598 sshpam_handle = NULL;
599 }
600 debug("PAM: initializing for \"%s\"", user);
601 sshpam_err =
602 pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);

--- 173 unchanged lines hidden (view full) ---

776 }
777 if (num != 1) {
778 error("PAM: expected one response, got %u", num);
779 return (-1);
780 }
781 buffer_init(&buffer);
782 if (sshpam_authctxt->valid &&
783 (sshpam_authctxt->pw->pw_uid != 0 ||
769 options.permit_root_login == PERMIT_YES))
784 options.permit_root_login == PERMIT_YES))
770 buffer_put_cstring(&buffer, *resp);
771 else
772 buffer_put_cstring(&buffer, badpw);
773 if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) {
774 buffer_free(&buffer);
775 return (-1);
776 }
777 buffer_free(&buffer);

--- 56 unchanged lines hidden (view full) ---

834{
835 debug("%s: called", __func__);
836 if (sshpam_account_status != -1)
837 return (sshpam_account_status);
838
839 sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
840 debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
841 pam_strerror(sshpam_handle, sshpam_err));
785 buffer_put_cstring(&buffer, *resp);
786 else
787 buffer_put_cstring(&buffer, badpw);
788 if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, &buffer) == -1) {
789 buffer_free(&buffer);
790 return (-1);
791 }
792 buffer_free(&buffer);

--- 56 unchanged lines hidden (view full) ---

849{
850 debug("%s: called", __func__);
851 if (sshpam_account_status != -1)
852 return (sshpam_account_status);
853
854 sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
855 debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
856 pam_strerror(sshpam_handle, sshpam_err));
842
857
843 if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
844 sshpam_account_status = 0;
845 return (sshpam_account_status);
846 }
847
848 if (sshpam_err == PAM_NEW_AUTHTOK_REQD)
849 sshpam_password_change_required(1);
850

--- 36 unchanged lines hidden (view full) ---

887 fatal("PAM: pam_setcred(): %s",
888 pam_strerror(sshpam_handle, sshpam_err));
889 else
890 debug("PAM: pam_setcred(): %s",
891 pam_strerror(sshpam_handle, sshpam_err));
892}
893
894static int
858 if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
859 sshpam_account_status = 0;
860 return (sshpam_account_status);
861 }
862
863 if (sshpam_err == PAM_NEW_AUTHTOK_REQD)
864 sshpam_password_change_required(1);
865

--- 36 unchanged lines hidden (view full) ---

902 fatal("PAM: pam_setcred(): %s",
903 pam_strerror(sshpam_handle, sshpam_err));
904 else
905 debug("PAM: pam_setcred(): %s",
906 pam_strerror(sshpam_handle, sshpam_err));
907}
908
909static int
895sshpam_tty_conv(int n, struct pam_message **msg,
910sshpam_tty_conv(int n, sshpam_const struct pam_message **msg,
896 struct pam_response **resp, void *data)
897{
898 char input[PAM_MAX_MSG_SIZE];
899 struct pam_response *reply;
900 int i;
901
902 debug3("PAM: %s called with %d messages", __func__, n);
903

--- 142 unchanged lines hidden (view full) ---

1046}
1047
1048/*
1049 * "Blind" conversation function for password authentication. Assumes that
1050 * echo-off prompts are for the password and stores messages for later
1051 * display.
1052 */
1053static int
911 struct pam_response **resp, void *data)
912{
913 char input[PAM_MAX_MSG_SIZE];
914 struct pam_response *reply;
915 int i;
916
917 debug3("PAM: %s called with %d messages", __func__, n);
918

--- 142 unchanged lines hidden (view full) ---

1061}
1062
1063/*
1064 * "Blind" conversation function for password authentication. Assumes that
1065 * echo-off prompts are for the password and stores messages for later
1066 * display.
1067 */
1068static int
1054sshpam_passwd_conv(int n, struct pam_message **msg,
1069sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg,
1055 struct pam_response **resp, void *data)
1056{
1057 struct pam_response *reply;
1058 int i;
1059 size_t len;
1060
1061 debug3("PAM: %s called with %d messages", __func__, n);
1062

--- 29 unchanged lines hidden (view full) ---

1092 break;
1093 default:
1094 goto fail;
1095 }
1096 }
1097 *resp = reply;
1098 return (PAM_SUCCESS);
1099
1070 struct pam_response **resp, void *data)
1071{
1072 struct pam_response *reply;
1073 int i;
1074 size_t len;
1075
1076 debug3("PAM: %s called with %d messages", __func__, n);
1077

--- 29 unchanged lines hidden (view full) ---

1107 break;
1108 default:
1109 goto fail;
1110 }
1111 }
1112 *resp = reply;
1113 return (PAM_SUCCESS);
1114
1100 fail:
1115 fail:
1101 for(i = 0; i < n; i++) {
1102 if (reply[i].resp != NULL)
1103 xfree(reply[i].resp);
1104 }
1105 xfree(reply);
1106 return (PAM_CONV_ERR);
1107}
1108

--- 16 unchanged lines hidden (view full) ---

1125 sshpam_authctxt = authctxt;
1126
1127 /*
1128 * If the user logging in is invalid, or is root but is not permitted
1129 * by PermitRootLogin, use an invalid password to prevent leaking
1130 * information via timing (eg if the PAM config has a delay on fail).
1131 */
1132 if (!authctxt->valid || (authctxt->pw->pw_uid == 0 &&
1116 for(i = 0; i < n; i++) {
1117 if (reply[i].resp != NULL)
1118 xfree(reply[i].resp);
1119 }
1120 xfree(reply);
1121 return (PAM_CONV_ERR);
1122}
1123

--- 16 unchanged lines hidden (view full) ---

1140 sshpam_authctxt = authctxt;
1141
1142 /*
1143 * If the user logging in is invalid, or is root but is not permitted
1144 * by PermitRootLogin, use an invalid password to prevent leaking
1145 * information via timing (eg if the PAM config has a delay on fail).
1146 */
1147 if (!authctxt->valid || (authctxt->pw->pw_uid == 0 &&
1133 options.permit_root_login != PERMIT_YES))
1148 options.permit_root_login != PERMIT_YES))
1134 sshpam_password = badpw;
1135
1136 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1137 (const void *)&passwd_conv);
1138 if (sshpam_err != PAM_SUCCESS)
1139 fatal("PAM: %s: failed to set PAM_CONV: %s", __func__,
1140 pam_strerror(sshpam_handle, sshpam_err));
1141
1142 sshpam_err = pam_authenticate(sshpam_handle, flags);
1143 sshpam_password = NULL;
1144 if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
1145 debug("PAM: password authentication accepted for %.100s",
1146 authctxt->user);
1149 sshpam_password = badpw;
1150
1151 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
1152 (const void *)&passwd_conv);
1153 if (sshpam_err != PAM_SUCCESS)
1154 fatal("PAM: %s: failed to set PAM_CONV: %s", __func__,
1155 pam_strerror(sshpam_handle, sshpam_err));
1156
1157 sshpam_err = pam_authenticate(sshpam_handle, flags);
1158 sshpam_password = NULL;
1159 if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
1160 debug("PAM: password authentication accepted for %.100s",
1161 authctxt->user);
1147 return 1;
1162 return 1;
1148 } else {
1149 debug("PAM: password authentication failed for %.100s: %s",
1150 authctxt->valid ? authctxt->user : "an illegal user",
1151 pam_strerror(sshpam_handle, sshpam_err));
1152 return 0;
1153 }
1154}
1155#endif /* USE_PAM */
1163 } else {
1164 debug("PAM: password authentication failed for %.100s: %s",
1165 authctxt->valid ? authctxt->user : "an illegal user",
1166 pam_strerror(sshpam_handle, sshpam_err));
1167 return 0;
1168 }
1169}
1170#endif /* USE_PAM */