summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>1999-12-30 15:08:44 +1100
committerDamien Miller <djm@mindrot.org>1999-12-30 15:08:44 +1100
commite72b7af17e519eb1d433b5119ef551f2584f8be6 (patch)
tree7ebbc8fefdfcfd9669dbe05718b142996df69a85
parentece22a8312357e1f34916659d77fa7dd8d15ae32 (diff)
- Removed most of the pam code into its own file auth-pam.[ch]. This
cleaned up sshd.c up significantly. - Several other cleanups
-rw-r--r--ChangeLog3
-rw-r--r--Makefile.in21
-rw-r--r--auth-pam.c239
-rw-r--r--auth-pam.h15
-rw-r--r--bsd-misc.c22
-rw-r--r--bsd-misc.h13
-rw-r--r--defines.h8
-rw-r--r--includes.h7
-rw-r--r--ssh.h6
-rw-r--r--sshd.c321
10 files changed, 374 insertions, 281 deletions
diff --git a/ChangeLog b/ChangeLog
index 38bd45060..66d77b0ac 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,9 @@
2 - OpenBSD CVS updates: 2 - OpenBSD CVS updates:
3 - [auth-passwd.c] 3 - [auth-passwd.c]
4 check for NULL 1st 4 check for NULL 1st
5 - Removed most of the pam code into its own file auth-pam.[ch]. This
6 cleaned up sshd.c up significantly.
7 - Several other cleanups
5 8
619991229 919991229
7 - Applied another NetBSD portability patch from David Rankin 10 - Applied another NetBSD portability patch from David Rankin
diff --git a/Makefile.in b/Makefile.in
index 050032277..3364a20ad 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -31,7 +31,7 @@ LDFLAGS=-L. @LDFLAGS@
31GNOME_CFLAGS=`gnome-config --cflags gnome gnomeui` 31GNOME_CFLAGS=`gnome-config --cflags gnome gnomeui`
32GNOME_LIBS=`gnome-config --libs gnome gnomeui` 32GNOME_LIBS=`gnome-config --libs gnome gnomeui`
33 33
34OBJS= atomicio.o authfd.o authfile.o auth-krb4.o auth-passwd.o \ 34OBJS= atomicio.o authfd.o authfile.o auth-krb4.o auth-passwd.o auth-pam.o \
35 auth-rhosts.o auth-rh-rsa.o auth-rsa.o auth-skey.o bsd-daemon.o \ 35 auth-rhosts.o auth-rh-rsa.o auth-rsa.o auth-skey.o bsd-daemon.o \
36 bsd-login.o bsd-misc.o bsd-mktemp.o bsd-snprintf.o bsd-strlcat.o \ 36 bsd-login.o bsd-misc.o bsd-mktemp.o bsd-snprintf.o bsd-strlcat.o \
37 bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o \ 37 bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o \
@@ -48,6 +48,12 @@ LIBOBJS= atomicio.o authfd.o authfile.o bsd-daemon.o bsd-misc.o \
48 packet.o radix.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o \ 48 packet.o radix.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o \
49 xmalloc.o 49 xmalloc.o
50 50
51SSHOBJS= ssh.o sshconnect.o log-client.o readconf.o clientloop.o
52
53SSHDOBJS= sshd.o auth-rhosts.o auth-krb4.o auth-pam.o auth-passwd.o \
54 auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o servconf.o \
55 serverloop.o bsd-login.o md5crypt.o
56
51all: $(OBJS) $(TARGETS) manpages 57all: $(OBJS) $(TARGETS) manpages
52 58
53$(OBJS): config.h 59$(OBJS): config.h
@@ -58,16 +64,11 @@ libssh.a: $(LIBOBJS)
58 $(AR) rv $@ $(LIBOBJS) 64 $(AR) rv $@ $(LIBOBJS)
59 $(RANLIB) $@ 65 $(RANLIB) $@
60 66
61ssh: ssh.o sshconnect.o log-client.o readconf.o clientloop.o libssh.a 67ssh: $(SSHOBJS) libssh.a
62 $(CC) -o $@ ssh.o sshconnect.o log-client.o readconf.o \ 68 $(CC) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh $(LIBS)
63 clientloop.o $(LDFLAGS) -lssh $(LIBS)
64 69
65sshd: sshd.o auth-rhosts.o auth-krb4.o auth-passwd.o auth-rsa.o \ 70sshd: $(SSHDOBJS) libssh.a
66 auth-rh-rsa.o pty.o log-server.o login.o servconf.o serverloop.o \ 71 $(CC) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh $(LIBS) $(LIBWRAP)
67 bsd-login.o md5crypt.o libssh.a
68 $(CC) -o $@ sshd.o auth-rhosts.o auth-krb4.o auth-passwd.o \
69 auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o servconf.o \
70 serverloop.o bsd-login.o md5crypt.o $(LDFLAGS) -lssh $(LIBS) $(LIBWRAP)
71 72
72scp: scp.o libssh.a 73scp: scp.o libssh.a
73 $(CC) -o $@ scp.o $(LDFLAGS) -lssh $(LIBS) 74 $(CC) -o $@ scp.o $(LDFLAGS) -lssh $(LIBS)
diff --git a/auth-pam.c b/auth-pam.c
new file mode 100644
index 000000000..8d872689c
--- /dev/null
+++ b/auth-pam.c
@@ -0,0 +1,239 @@
1/*
2 * Author: Damien Miller
3 * Copyright (c) 1999 Damien Miller <djm@mindrot.org>
4 * All rights reserved
5 * Created: Thursday December 30 1999
6 * PAM authentication and session management code.
7 */
8
9#include "includes.h"
10
11#ifdef USE_PAM
12#include "ssh.h"
13#include "xmalloc.h"
14#include "servconf.h"
15
16RCSID("$Id: auth-pam.c,v 1.1 1999/12/30 04:11:25 damien Exp $");
17
18/* Callbacks */
19static int pamconv(int num_msg, const struct pam_message **msg,
20 struct pam_response **resp, void *appdata_ptr);
21void pam_cleanup_proc(void *context);
22
23/* module-local variables */
24static struct pam_conv conv = {
25 pamconv,
26 NULL
27};
28static struct pam_handle_t *pamh = NULL;
29static const char *pampasswd = NULL;
30static char *pamconv_msg = NULL;
31
32/* PAM conversation function. This is really a kludge to get the password */
33/* into PAM and to pick up any messages generated by PAM into pamconv_msg */
34static int pamconv(int num_msg, const struct pam_message **msg,
35 struct pam_response **resp, void *appdata_ptr)
36{
37 struct pam_response *reply;
38 int count;
39 size_t msg_len;
40 char *p;
41
42 /* PAM will free this later */
43 reply = malloc(num_msg * sizeof(*reply));
44 if (reply == NULL)
45 return PAM_CONV_ERR;
46
47 for(count = 0; count < num_msg; count++) {
48 switch (msg[count]->msg_style) {
49 case PAM_PROMPT_ECHO_OFF:
50 if (pampasswd == NULL) {
51 free(reply);
52 return PAM_CONV_ERR;
53 }
54 reply[count].resp_retcode = PAM_SUCCESS;
55 reply[count].resp = xstrdup(pampasswd);
56 break;
57
58 case PAM_TEXT_INFO:
59 reply[count].resp_retcode = PAM_SUCCESS;
60 reply[count].resp = xstrdup("");
61
62 if (msg[count]->msg == NULL)
63 break;
64
65 debug("Adding PAM message: %s", msg[count]->msg);
66
67 msg_len = strlen(msg[count]->msg);
68 if (pamconv_msg) {
69 size_t n = strlen(pamconv_msg);
70 pamconv_msg = xrealloc(pamconv_msg, n + msg_len + 2);
71 p = pamconv_msg + n;
72 } else {
73 pamconv_msg = p = xmalloc(msg_len + 2);
74 }
75 memcpy(p, msg[count]->msg, msg_len);
76 p[msg_len] = '\n';
77 p[msg_len + 1] = '\0';
78 break;
79
80 case PAM_PROMPT_ECHO_ON:
81 case PAM_ERROR_MSG:
82 default:
83 free(reply);
84 return PAM_CONV_ERR;
85 }
86 }
87
88 *resp = reply;
89
90 return PAM_SUCCESS;
91}
92
93/* Called at exit to cleanly shutdown PAM */
94void pam_cleanup_proc(void *context)
95{
96 int pam_retval;
97
98 if (pamh != NULL)
99 {
100 pam_retval = pam_close_session((pam_handle_t *)pamh, 0);
101 if (pam_retval != PAM_SUCCESS) {
102 log("Cannot close PAM session: %.200s",
103 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
104 }
105
106 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_DELETE_CRED);
107 if (pam_retval != PAM_SUCCESS) {
108 log("Cannot delete credentials: %.200s",
109 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
110 }
111
112 pam_retval = pam_end((pam_handle_t *)pamh, pam_retval);
113 if (pam_retval != PAM_SUCCESS) {
114 log("Cannot release PAM authentication: %.200s",
115 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
116 }
117 }
118}
119
120/* Attempt password authentation using PAM */
121int auth_pam_password(struct passwd *pw, const char *password)
122{
123 extern ServerOptions options;
124 int pam_retval;
125
126 /* deny if no user. */
127 if (pw == NULL)
128 return 0;
129 if (pw->pw_uid == 0 && options.permit_root_login == 2)
130 return 0;
131 if (*password == '\0' && options.permit_empty_passwd == 0)
132 return 0;
133
134 pampasswd = password;
135
136 pam_retval = pam_authenticate((pam_handle_t *)pamh, 0);
137 if (pam_retval == PAM_SUCCESS) {
138 debug("PAM Password authentication accepted for user \"%.100s\"", pw->pw_name);
139 return 1;
140 } else {
141 debug("PAM Password authentication for \"%.100s\" failed: %s",
142 pw->pw_name, PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
143 return 0;
144 }
145}
146
147/* Do account management using PAM */
148int do_pam_account(char *username, char *remote_user)
149{
150 int pam_retval;
151
152 debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname());
153 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RHOST,
154 get_canonical_hostname());
155 if (pam_retval != PAM_SUCCESS) {
156 fatal("PAM set rhost failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
157 }
158
159 if (remote_user != NULL) {
160 debug("PAM setting ruser to \"%.200s\"", remote_user);
161 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user);
162 if (pam_retval != PAM_SUCCESS) {
163 fatal("PAM set ruser failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
164 }
165 }
166
167 pam_retval = pam_acct_mgmt((pam_handle_t *)pamh, 0);
168 if (pam_retval != PAM_SUCCESS) {
169 log("PAM rejected by account configuration: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
170 return(0);
171 }
172
173 return(1);
174}
175
176/* Do PAM-specific session initialisation */
177void do_pam_session(char *username, char *ttyname)
178{
179 int pam_retval;
180
181 if (ttyname != NULL) {
182 debug("PAM setting tty to \"%.200s\"", ttyname);
183 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_TTY, ttyname);
184 if (pam_retval != PAM_SUCCESS)
185 fatal("PAM set tty failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
186 }
187
188 pam_retval = pam_open_session((pam_handle_t *)pamh, 0);
189 if (pam_retval != PAM_SUCCESS)
190 fatal("PAM session setup failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
191}
192
193/* Set PAM credentials */
194void do_pam_setcred()
195{
196 int pam_retval;
197
198 debug("PAM establishing creds");
199 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_ESTABLISH_CRED);
200 if (pam_retval != PAM_SUCCESS)
201 fatal("PAM setcred failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
202}
203
204/* Cleanly shutdown PAM */
205void finish_pam(void)
206{
207 pam_cleanup_proc(NULL);
208 fatal_remove_cleanup(&pam_cleanup_proc, NULL);
209}
210
211/* Start PAM authentication for specified account */
212void start_pam(struct passwd *pw)
213{
214 int pam_retval;
215
216 debug("Starting up PAM with username \"%.200s\"", pw->pw_name);
217
218 pam_retval = pam_start("sshd", pw->pw_name, &conv, (pam_handle_t**)&pamh);
219 if (pam_retval != PAM_SUCCESS)
220 fatal("PAM initialisation failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
221
222 fatal_add_cleanup(&pam_cleanup_proc, NULL);
223}
224
225/* Return list of PAM enviornment strings */
226char **fetch_pam_environment(void)
227{
228 return(pam_getenvlist((pam_handle_t *)pamh));
229}
230
231/* Print any messages that have been generated during authentication */
232/* or account checking to stderr */
233void print_pam_messages(void)
234{
235 if (pamconv_msg != NULL)
236 fprintf(stderr, pamconv_msg);
237}
238
239#endif /* USE_PAM */
diff --git a/auth-pam.h b/auth-pam.h
new file mode 100644
index 000000000..1f3bc252f
--- /dev/null
+++ b/auth-pam.h
@@ -0,0 +1,15 @@
1#include "includes.h"
2#ifdef USE_PAM
3
4#include <pwd.h> /* For struct passwd */
5
6void start_pam(struct passwd *pw);
7void finish_pam(void);
8int auth_pam_password(struct passwd *pw, const char *password);
9char **fetch_pam_environment(void);
10int do_pam_account(char *username, char *remote_user);
11void do_pam_session(char *username, char *ttyname);
12void do_pam_setcred();
13void print_pam_messages(void);
14
15#endif /* USE_PAM */
diff --git a/bsd-misc.c b/bsd-misc.c
index c952fd0f3..0ffe5168b 100644
--- a/bsd-misc.c
+++ b/bsd-misc.c
@@ -212,3 +212,25 @@ int setenv(const char *name, const char *value, int overwrite)
212 return(result); 212 return(result);
213} 213}
214#endif /* !HAVE_SETENV */ 214#endif /* !HAVE_SETENV */
215
216#ifndef HAVE_SETLOGIN
217int setlogin(const char *name)
218{
219 return(0);
220}
221#endif /* !HAVE_SETLOGIN */
222
223#ifndef HAVE_INNETGR
224int innetgr(const char *netgroup, const char *host,
225 const char *user, const char *domain)
226{
227 return(0);
228}
229#endif /* HAVE_INNETGR */
230
231#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
232int seteuid(uid_t euid)
233{
234 return(setreuid(-1,euid));
235}
236#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */
diff --git a/bsd-misc.h b/bsd-misc.h
index 990dd408e..fabaa00b3 100644
--- a/bsd-misc.h
+++ b/bsd-misc.h
@@ -51,4 +51,17 @@ void setproctitle(const char *fmt, ...);
51int setenv(const char *name, const char *value, int overwrite); 51int setenv(const char *name, const char *value, int overwrite);
52#endif /* !HAVE_SETENV */ 52#endif /* !HAVE_SETENV */
53 53
54#ifndef HAVE_SETLOGIN
55int setlogin(const char *name);
56#endif /* !HAVE_SETLOGIN */
57
58#ifndef HAVE_INNETGR
59int innetgr(const char *netgroup, const char *host,
60 const char *user, const char *domain);
61#endif /* HAVE_INNETGR */
62
63#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
64int seteuid(uid_t euid);
65#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */
66
54#endif /* _BSD_MISC_H */ 67#endif /* _BSD_MISC_H */
diff --git a/defines.h b/defines.h
index 1a6639976..10f72f478 100644
--- a/defines.h
+++ b/defines.h
@@ -226,11 +226,3 @@ typedef unsigned int size_t;
226# define PAM_STRERROR(a,b) pam_strerror((a),(b)) 226# define PAM_STRERROR(a,b) pam_strerror((a),(b))
227#endif 227#endif
228 228
229#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
230# define seteuid(a) setreuid(-1,a)
231#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */
232
233#ifndef HAVE_INNETGR
234# define innetgr(a,b,c,d) (0)
235#endif /* HAVE_INNETGR */
236
diff --git a/includes.h b/includes.h
index 3fe76553b..bc7db419a 100644
--- a/includes.h
+++ b/includes.h
@@ -79,6 +79,13 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
79#ifdef USE_PAM 79#ifdef USE_PAM
80# include <security/pam_appl.h> 80# include <security/pam_appl.h>
81#endif 81#endif
82#ifdef HAVE_POLL_H
83# include <poll.h>
84#else
85# ifdef HAVE_SYS_POLL_H
86# include <sys/poll.h>
87# endif
88#endif
82 89
83#include "version.h" 90#include "version.h"
84#include "bsd-misc.h" 91#include "bsd-misc.h"
diff --git a/ssh.h b/ssh.h
index 0efabda8f..48bcd5ea6 100644
--- a/ssh.h
+++ b/ssh.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$Id: ssh.h,v 1.21 1999/12/21 13:12:39 damien Exp $"); */ 16/* RCSID("$Id: ssh.h,v 1.22 1999/12/30 04:08:44 damien Exp $"); */
17 17
18#ifndef SSH_H 18#ifndef SSH_H
19#define SSH_H 19#define SSH_H
@@ -741,4 +741,8 @@ char *skey_fake_keyinfo(char *username);
741int auth_skey_password(struct passwd * pw, const char *password); 741int auth_skey_password(struct passwd * pw, const char *password);
742#endif /* SKEY */ 742#endif /* SKEY */
743 743
744#ifdef USE_PAM
745#include "auth-pam.h"
746#endif /* USE_PAM */
747
744#endif /* SSH_H */ 748#endif /* SSH_H */
diff --git a/sshd.c b/sshd.c
index 73a33b785..0cf664087 100644
--- a/sshd.c
+++ b/sshd.c
@@ -11,15 +11,7 @@
11 */ 11 */
12 12
13#include "includes.h" 13#include "includes.h"
14RCSID("$Id: sshd.c,v 1.48 1999/12/28 23:25:41 damien Exp $"); 14RCSID("$Id: sshd.c,v 1.49 1999/12/30 04:08:44 damien Exp $");
15
16#ifdef HAVE_POLL_H
17# include <poll.h>
18#else /* HAVE_POLL_H */
19# ifdef HAVE_SYS_POLL_H
20# include <sys/poll.h>
21# endif /* HAVE_SYS_POLL_H */
22#endif /* HAVE_POLL_H */
23 15
24#include "xmalloc.h" 16#include "xmalloc.h"
25#include "rsa.h" 17#include "rsa.h"
@@ -143,183 +135,6 @@ void do_child(const char *command, struct passwd * pw, const char *term,
143 const char *display, const char *auth_proto, 135 const char *display, const char *auth_proto,
144 const char *auth_data, const char *ttyname); 136 const char *auth_data, const char *ttyname);
145 137
146#ifdef USE_PAM
147static int pamconv(int num_msg, const struct pam_message **msg,
148 struct pam_response **resp, void *appdata_ptr);
149int do_pam_auth(const char *user, const char *password);
150void do_pam_account(char *username, char *remote_user);
151void do_pam_session(char *username, char *ttyname);
152void do_pam_setcred();
153void pam_cleanup_proc(void *context);
154
155static struct pam_conv conv = {
156 pamconv,
157 NULL
158};
159struct pam_handle_t *pamh = NULL;
160const char *pampasswd = NULL;
161char *pamconv_msg = NULL;
162
163static int pamconv(int num_msg, const struct pam_message **msg,
164 struct pam_response **resp, void *appdata_ptr)
165{
166 struct pam_response *reply;
167 int count;
168 size_t msg_len;
169 char *p;
170
171 /* PAM will free this later */
172 reply = malloc(num_msg * sizeof(*reply));
173 if (reply == NULL)
174 return PAM_CONV_ERR;
175
176 for(count = 0; count < num_msg; count++) {
177 switch (msg[count]->msg_style) {
178 case PAM_PROMPT_ECHO_OFF:
179 if (pampasswd == NULL) {
180 free(reply);
181 return PAM_CONV_ERR;
182 }
183 reply[count].resp_retcode = PAM_SUCCESS;
184 reply[count].resp = xstrdup(pampasswd);
185 break;
186
187 case PAM_TEXT_INFO:
188 reply[count].resp_retcode = PAM_SUCCESS;
189 reply[count].resp = xstrdup("");
190
191 if (msg[count]->msg == NULL)
192 break;
193
194 debug("Adding PAM message: %s", msg[count]->msg);
195
196 msg_len = strlen(msg[count]->msg);
197 if (pamconv_msg) {
198 size_t n = strlen(pamconv_msg);
199 pamconv_msg = xrealloc(pamconv_msg, n + msg_len + 2);
200 p = pamconv_msg + n;
201 } else {
202 pamconv_msg = p = xmalloc(msg_len + 2);
203 }
204 memcpy(p, msg[count]->msg, msg_len);
205 p[msg_len] = '\n';
206 p[msg_len + 1] = '\0';
207 break;
208
209 case PAM_PROMPT_ECHO_ON:
210 case PAM_ERROR_MSG:
211 default:
212 free(reply);
213 return PAM_CONV_ERR;
214 }
215 }
216
217 *resp = reply;
218
219 return PAM_SUCCESS;
220}
221
222void pam_cleanup_proc(void *context)
223{
224 int pam_retval;
225
226 if (pamh != NULL)
227 {
228 pam_retval = pam_close_session((pam_handle_t *)pamh, 0);
229 if (pam_retval != PAM_SUCCESS) {
230 log("Cannot close PAM session: %.200s",
231 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
232 }
233
234 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_DELETE_CRED);
235 if (pam_retval != PAM_SUCCESS) {
236 log("Cannot delete credentials: %.200s",
237 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
238 }
239
240 pam_retval = pam_end((pam_handle_t *)pamh, pam_retval);
241 if (pam_retval != PAM_SUCCESS) {
242 log("Cannot release PAM authentication: %.200s",
243 PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
244 }
245 }
246}
247
248int do_pam_auth(const char *user, const char *password)
249{
250 int pam_retval;
251
252 if ((options.permit_empty_passwd == 0) && (password[0] == '\0'))
253 return 0;
254
255 pampasswd = password;
256
257 pam_retval = pam_authenticate((pam_handle_t *)pamh, 0);
258 if (pam_retval == PAM_SUCCESS) {
259 debug("PAM Password authentication accepted for user \"%.100s\"", user);
260 return 1;
261 } else {
262 debug("PAM Password authentication for \"%.100s\" failed: %s",
263 user, PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
264 return 0;
265 }
266}
267
268void do_pam_account(char *username, char *remote_user)
269{
270 int pam_retval;
271
272 debug("PAM setting rhost to \"%.200s\"", get_canonical_hostname());
273 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RHOST,
274 get_canonical_hostname());
275 if (pam_retval != PAM_SUCCESS) {
276 log("PAM set rhost failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
277 do_fake_authloop(username);
278 }
279
280 if (remote_user != NULL) {
281 debug("PAM setting ruser to \"%.200s\"", remote_user);
282 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user);
283 if (pam_retval != PAM_SUCCESS) {
284 log("PAM set ruser failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
285 do_fake_authloop(username);
286 }
287 }
288
289 pam_retval = pam_acct_mgmt((pam_handle_t *)pamh, 0);
290 if (pam_retval != PAM_SUCCESS) {
291 log("PAM rejected by account configuration: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
292 do_fake_authloop(username);
293 }
294}
295
296void do_pam_session(char *username, char *ttyname)
297{
298 int pam_retval;
299
300 if (ttyname != NULL) {
301 debug("PAM setting tty to \"%.200s\"", ttyname);
302 pam_retval = pam_set_item((pam_handle_t *)pamh, PAM_TTY, ttyname);
303 if (pam_retval != PAM_SUCCESS)
304 fatal("PAM set tty failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
305 }
306
307 pam_retval = pam_open_session((pam_handle_t *)pamh, 0);
308 if (pam_retval != PAM_SUCCESS)
309 fatal("PAM session setup failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
310}
311
312void do_pam_setcred()
313{
314 int pam_retval;
315
316 debug("PAM establishing creds");
317 pam_retval = pam_setcred((pam_handle_t *)pamh, PAM_ESTABLISH_CRED);
318 if (pam_retval != PAM_SUCCESS)
319 fatal("PAM setcred failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
320}
321#endif /* USE_PAM */
322
323/* 138/*
324 * Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP; 139 * Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP;
325 * the effect is to reread the configuration file (and to regenerate 140 * the effect is to reread the configuration file (and to regenerate
@@ -973,20 +788,7 @@ main(int ac, char **av)
973 verbose("Closing connection to %.100s", remote_ip); 788 verbose("Closing connection to %.100s", remote_ip);
974 789
975#ifdef USE_PAM 790#ifdef USE_PAM
976 { 791 finish_pam();
977 int retval;
978
979 if (pamh != NULL) {
980 debug("Closing PAM session.");
981 retval = pam_close_session((pam_handle_t *)pamh, 0);
982
983 debug("Terminating PAM library.");
984 if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
985 log("Cannot release PAM authentication.");
986
987 fatal_remove_cleanup(&pam_cleanup_proc, NULL);
988 }
989 }
990#endif /* USE_PAM */ 792#endif /* USE_PAM */
991 793
992 packet_close(); 794 packet_close();
@@ -1306,17 +1108,7 @@ do_authentication(char *user)
1306 pw = &pwcopy; 1108 pw = &pwcopy;
1307 1109
1308#ifdef USE_PAM 1110#ifdef USE_PAM
1309 { 1111 start_pam(pw);
1310 int pam_retval;
1311
1312 debug("Starting up PAM with username \"%.200s\"", pw->pw_name);
1313
1314 pam_retval = pam_start("sshd", pw->pw_name, &conv, (pam_handle_t**)&pamh);
1315 if (pam_retval != PAM_SUCCESS)
1316 fatal("PAM initialisation failed: %.200s", PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
1317
1318 fatal_add_cleanup(&pam_cleanup_proc, NULL);
1319 }
1320#endif 1112#endif
1321 1113
1322 /* 1114 /*
@@ -1334,7 +1126,7 @@ do_authentication(char *user)
1334 (!options.kerberos_authentication || options.kerberos_or_local_passwd) && 1126 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
1335#endif /* KRB4 */ 1127#endif /* KRB4 */
1336#ifdef USE_PAM 1128#ifdef USE_PAM
1337 do_pam_auth(pw->pw_name, "")) { 1129 auth_pam_password(pw, "")) {
1338#else /* USE_PAM */ 1130#else /* USE_PAM */
1339 auth_password(pw, "")) { 1131 auth_password(pw, "")) {
1340#endif /* USE_PAM */ 1132#endif /* USE_PAM */
@@ -1477,9 +1269,6 @@ do_authloop(struct passwd * pw)
1477 authenticated = auth_rhosts(pw, client_user); 1269 authenticated = auth_rhosts(pw, client_user);
1478 1270
1479 snprintf(user, sizeof user, " ruser %s", client_user); 1271 snprintf(user, sizeof user, " ruser %s", client_user);
1480#ifndef USE_PAM
1481 xfree(client_user);
1482#endif /* USE_PAM */
1483 break; 1272 break;
1484 1273
1485 case SSH_CMSG_AUTH_RHOSTS_RSA: 1274 case SSH_CMSG_AUTH_RHOSTS_RSA:
@@ -1512,9 +1301,6 @@ do_authloop(struct passwd * pw)
1512 BN_clear_free(client_host_key_n); 1301 BN_clear_free(client_host_key_n);
1513 1302
1514 snprintf(user, sizeof user, " ruser %s", client_user); 1303 snprintf(user, sizeof user, " ruser %s", client_user);
1515#ifndef USE_PAM
1516 xfree(client_user);
1517#endif /* USE_PAM */
1518 break; 1304 break;
1519 1305
1520 case SSH_CMSG_AUTH_RSA: 1306 case SSH_CMSG_AUTH_RSA:
@@ -1545,7 +1331,7 @@ do_authloop(struct passwd * pw)
1545 1331
1546#ifdef USE_PAM 1332#ifdef USE_PAM
1547 /* Do PAM auth with password */ 1333 /* Do PAM auth with password */
1548 authenticated = do_pam_auth(pw->pw_name, password); 1334 authenticated = auth_pam_password(pw, password);
1549#else /* USE_PAM */ 1335#else /* USE_PAM */
1550 /* Try authentication with the password. */ 1336 /* Try authentication with the password. */
1551 authenticated = auth_password(pw, password); 1337 authenticated = auth_password(pw, password);
@@ -1615,29 +1401,24 @@ do_authloop(struct passwd * pw)
1615 get_remote_port(), 1401 get_remote_port(),
1616 user); 1402 user);
1617 1403
1618#ifndef USE_PAM
1619 if (authenticated)
1620 return;
1621
1622 if (attempt > AUTH_FAIL_MAX)
1623 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
1624#else /* USE_PAM */
1625 if (authenticated) { 1404 if (authenticated) {
1626 do_pam_account(pw->pw_name, client_user); 1405#ifdef USE_PAM
1627 1406 if (!do_pam_account(pw->pw_name, client_user))
1628 if (client_user != NULL) 1407 {
1629 xfree(client_user); 1408 if (client_user != NULL)
1409 xfree(client_user);
1630 1410
1411 do_fake_authloop(pw->pw_name);
1412 }
1413#endif /* USE_PAM */
1631 return; 1414 return;
1632 } 1415 }
1633 1416
1634 if (attempt > AUTH_FAIL_MAX) { 1417 if (client_user != NULL)
1635 if (client_user != NULL) 1418 xfree(client_user);
1636 xfree(client_user);
1637 1419
1420 if (attempt > AUTH_FAIL_MAX)
1638 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name); 1421 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
1639 }
1640#endif /* USE_PAM */
1641 1422
1642 /* Send a message indicating that the authentication attempt failed. */ 1423 /* Send a message indicating that the authentication attempt failed. */
1643 packet_start(SSH_SMSG_FAILURE); 1424 packet_start(SSH_SMSG_FAILURE);
@@ -1672,8 +1453,10 @@ do_fake_authloop(char *user)
1672 for (attempt = 1;; attempt++) { 1453 for (attempt = 1;; attempt++) {
1673 /* Read a packet. This will not return if the client disconnects. */ 1454 /* Read a packet. This will not return if the client disconnects. */
1674 int plen; 1455 int plen;
1456#ifndef SKEY
1457 (void)packet_read(&plen);
1458#else /* SKEY */
1675 int type = packet_read(&plen); 1459 int type = packet_read(&plen);
1676#ifdef SKEY
1677 int dlen; 1460 int dlen;
1678 char *password, *skeyinfo; 1461 char *password, *skeyinfo;
1679 /* Try to send a fake s/key challenge. */ 1462 /* Try to send a fake s/key challenge. */
@@ -1845,7 +1628,7 @@ do_authenticated(struct passwd * pw)
1845 1628
1846#ifdef USE_PAM 1629#ifdef USE_PAM
1847 /* do the pam_open_session since we have the pty */ 1630 /* do the pam_open_session since we have the pty */
1848 do_pam_session(pw->pw_name,ttyname); 1631 do_pam_session(pw->pw_name, ttyname);
1849#endif /* USE_PAM */ 1632#endif /* USE_PAM */
1850 1633
1851 break; 1634 break;
@@ -1925,7 +1708,7 @@ do_authenticated(struct passwd * pw)
1925 1708
1926#ifdef USE_PAM 1709#ifdef USE_PAM
1927 do_pam_setcred(); 1710 do_pam_setcred();
1928#endif 1711#endif /* USE_PAM */
1929 if (forced_command != NULL) 1712 if (forced_command != NULL)
1930 goto do_forced_command; 1713 goto do_forced_command;
1931 debug("Forking shell."); 1714 debug("Forking shell.");
@@ -1943,7 +1726,7 @@ do_authenticated(struct passwd * pw)
1943 1726
1944#ifdef USE_PAM 1727#ifdef USE_PAM
1945 do_pam_setcred(); 1728 do_pam_setcred();
1946#endif 1729#endif /* USE_PAM */
1947 if (forced_command != NULL) 1730 if (forced_command != NULL)
1948 goto do_forced_command; 1731 goto do_forced_command;
1949 /* Get command from the packet. */ 1732 /* Get command from the packet. */
@@ -2221,10 +2004,9 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
2221 quiet_login = stat(line, &st) >= 0; 2004 quiet_login = stat(line, &st) >= 0;
2222 2005
2223#ifdef USE_PAM 2006#ifdef USE_PAM
2224 /* output the results of the pamconv() */ 2007 if (!quiet_login)
2225 if (!quiet_login && pamconv_msg != NULL) 2008 print_pam_messages();
2226 fprintf(stderr, pamconv_msg); 2009#endif /* USE_PAM */
2227#endif
2228 2010
2229 /* 2011 /*
2230 * If the user has logged in before, display the time of last 2012 * If the user has logged in before, display the time of last
@@ -2389,6 +2171,39 @@ read_environment_file(char ***env, unsigned int *envsize,
2389 fclose(f); 2171 fclose(f);
2390} 2172}
2391 2173
2174#ifdef USE_PAM
2175/*
2176 * Sets any environment variables which have been specified by PAM
2177 */
2178void do_pam_environment(char ***env, int *envsize)
2179{
2180 char *equals, var_name[512], var_val[512];
2181 char **pam_env;
2182 int i;
2183
2184 if ((pam_env = fetch_pam_environment()) == NULL)
2185 return;
2186
2187 for(i = 0; pam_env[i] != NULL; i++) {
2188 if ((equals = strstr(pam_env[i], "=")) == NULL)
2189 continue;
2190
2191 if (strlen(pam_env[i]) < (sizeof(var_name) - 1))
2192 {
2193 memset(var_name, '\0', sizeof(var_name));
2194 memset(var_val, '\0', sizeof(var_val));
2195
2196 strncpy(var_name, pam_env[i], equals - pam_env[i]);
2197 strcpy(var_val, equals + 1);
2198
2199 debug("PAM environment: %s=%s", var_name, var_val);
2200
2201 child_set_env(env, envsize, var_name, var_val);
2202 }
2203 }
2204}
2205#endif /* USE_PAM */
2206
2392/* 2207/*
2393 * Performs common processing for the child, such as setting up the 2208 * Performs common processing for the child, such as setting up the
2394 * environment, closing extra file descriptors, setting the user and group 2209 * environment, closing extra file descriptors, setting the user and group
@@ -2421,11 +2236,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
2421 } 2236 }
2422#endif /* USE_PAM */ 2237#endif /* USE_PAM */
2423 2238
2424#ifdef HAVE_SETLOGIN
2425 /* Set login name in the kernel. */ 2239 /* Set login name in the kernel. */
2426 if (setlogin(pw->pw_name) < 0) 2240 if (setlogin(pw->pw_name) < 0)
2427 error("setlogin failed: %s", strerror(errno)); 2241 error("setlogin failed: %s", strerror(errno));
2428#endif /* HAVE_SETLOGIN */
2429 2242
2430 /* Set uid, gid, and groups. */ 2243 /* Set uid, gid, and groups. */
2431 /* Login(1) does this as well, and it needs uid 0 for the "-h" 2244 /* Login(1) does this as well, and it needs uid 0 for the "-h"
@@ -2526,23 +2339,7 @@ do_child(const char *command, struct passwd * pw, const char *term,
2526 2339
2527#ifdef USE_PAM 2340#ifdef USE_PAM
2528 /* Pull in any environment variables that may have been set by PAM. */ 2341 /* Pull in any environment variables that may have been set by PAM. */
2529 { 2342 do_pam_environment(&env, &envsize);
2530 char *equals, var_name[512], var_val[512];
2531 char **pam_env = pam_getenvlist((pam_handle_t *)pamh);
2532 int i;
2533 for(i = 0; pam_env && pam_env[i]; i++) {
2534 equals = strstr(pam_env[i], "=");
2535 if ((strlen(pam_env[i]) < (sizeof(var_name) - 1)) && (equals != NULL))
2536 {
2537 debug("PAM environment: %s=%s", var_name, var_val);
2538 memset(var_name, '\0', sizeof(var_name));
2539 memset(var_val, '\0', sizeof(var_val));
2540 strncpy(var_name, pam_env[i], equals - pam_env[i]);
2541 strcpy(var_val, equals + 1);
2542 child_set_env(&env, &envsize, var_name, var_val);
2543 }
2544 }
2545 }
2546#endif /* USE_PAM */ 2343#endif /* USE_PAM */
2547 2344
2548 if (xauthfile) 2345 if (xauthfile)