summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--Makefile.in2
-rw-r--r--TODO2
-rw-r--r--auth-pam.c35
-rw-r--r--auth-pam.h2
-rw-r--r--auth.h3
-rw-r--r--auth2-pam.c170
-rw-r--r--auth2-pam.h6
-rw-r--r--auth2.c9
-rw-r--r--ssh.h4
10 files changed, 223 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index a3b829515..f598574cc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -29,6 +29,9 @@
29 [sshd.c] 29 [sshd.c]
30 sshd -D, startup w/o deamon(), for monitoring scripts or inittab; 30 sshd -D, startup w/o deamon(), for monitoring scripts or inittab;
31 from handler@sub-rosa.com and eric@urbanrange.com; ok niels@ 31 from handler@sub-rosa.com and eric@urbanrange.com; ok niels@
32 - (djm) Added patch from Nalin Dahyabhai <nalin@redhat.com> to enable
33 PAM authentication using KbdInteractive.
34 - (djm) Added another TODO
32 35
3320001202 3620001202
34 - (bal) Backed out of part of Alain St-Denis' loginrec.c patch. 37 - (bal) Backed out of part of Alain St-Denis' loginrec.c patch.
diff --git a/Makefile.in b/Makefile.in
index 3e7d7a89b..1e5d4105a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -42,7 +42,7 @@ LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daem
42 42
43SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o 43SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o
44 44
45SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-skey.o auth2-skey.o auth-rhosts.o auth-options.o auth-krb4.o auth-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o dh.o pty.o log-server.o login.o loginrec.o servconf.o serverloop.o md5crypt.o session.o 45SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-skey.o auth2-skey.o auth-rhosts.o auth-options.o auth-krb4.o auth-pam.o auth2-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o dh.o pty.o log-server.o login.o loginrec.o servconf.o serverloop.o md5crypt.o session.o
46 46
47TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 sftp-server.8 47TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 sftp-server.8
48CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0 sftp-server.0 48CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0 sftp-server.0
diff --git a/TODO b/TODO
index de51b3b07..318212ddc 100644
--- a/TODO
+++ b/TODO
@@ -19,6 +19,8 @@ Programming:
19 select() under Linux is not as nice as others, and two the children 19 select() under Linux is not as nice as others, and two the children
20 of the shell are not killed on exiting the shell. 20 of the shell are not killed on exiting the shell.
21 21
22- Build an automated test suite
23
22Documentation: 24Documentation:
23- More and better 25- More and better
24 26
diff --git a/auth-pam.c b/auth-pam.c
index 9c6e36af7..1e077602e 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -29,7 +29,7 @@
29#include "xmalloc.h" 29#include "xmalloc.h"
30#include "servconf.h" 30#include "servconf.h"
31 31
32RCSID("$Id: auth-pam.c,v 1.18 2000/10/14 15:08:49 stevesk Exp $"); 32RCSID("$Id: auth-pam.c,v 1.19 2000/12/03 00:51:51 djm Exp $");
33 33
34#define NEW_AUTHTOK_MSG \ 34#define NEW_AUTHTOK_MSG \
35 "Warning: Your password has expired, please change it now" 35 "Warning: Your password has expired, please change it now"
@@ -50,10 +50,26 @@ static const char *pampasswd = NULL;
50static char *pam_msg = NULL; 50static char *pam_msg = NULL;
51 51
52/* states for pamconv() */ 52/* states for pamconv() */
53typedef enum { INITIAL_LOGIN, OTHER } pamstates; 53enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN;
54static pamstates pamstate = INITIAL_LOGIN;
55/* remember whether pam_acct_mgmt() returned PAM_NEWAUTHTOK_REQD */ 54/* remember whether pam_acct_mgmt() returned PAM_NEWAUTHTOK_REQD */
56static int password_change_required = 0; 55static int password_change_required = 0;
56/* remember whether the last pam_authenticate() succeeded or not */
57static int was_authenticated = 0;
58
59/* accessor which allows us to switch conversation structs according to
60 * the authentication method being used */
61void pam_set_conv(struct pam_conv *conv)
62{
63 pam_set_item(pamh, PAM_CONV, conv);
64}
65
66/* start an authentication run */
67int do_pam_authenticate(int flags)
68{
69 int retval = pam_authenticate(pamh, flags);
70 was_authenticated = (retval == PAM_SUCCESS);
71 return retval;
72}
57 73
58/* 74/*
59 * PAM conversation function. 75 * PAM conversation function.
@@ -163,6 +179,8 @@ int auth_pam_password(struct passwd *pw, const char *password)
163 extern ServerOptions options; 179 extern ServerOptions options;
164 int pam_retval; 180 int pam_retval;
165 181
182 pam_set_conv(&conv);
183
166 /* deny if no user. */ 184 /* deny if no user. */
167 if (pw == NULL) 185 if (pw == NULL)
168 return 0; 186 return 0;
@@ -174,7 +192,7 @@ int auth_pam_password(struct passwd *pw, const char *password)
174 pampasswd = password; 192 pampasswd = password;
175 193
176 pamstate = INITIAL_LOGIN; 194 pamstate = INITIAL_LOGIN;
177 pam_retval = pam_authenticate(pamh, 0); 195 pam_retval = do_pam_authenticate(0);
178 if (pam_retval == PAM_SUCCESS) { 196 if (pam_retval == PAM_SUCCESS) {
179 debug("PAM Password authentication accepted for user \"%.100s\"", 197 debug("PAM Password authentication accepted for user \"%.100s\"",
180 pw->pw_name); 198 pw->pw_name);
@@ -256,8 +274,13 @@ void do_pam_setcred(void)
256 debug("PAM establishing creds"); 274 debug("PAM establishing creds");
257 pam_retval = pam_setcred(pamh, PAM_ESTABLISH_CRED); 275 pam_retval = pam_setcred(pamh, PAM_ESTABLISH_CRED);
258 if (pam_retval != PAM_SUCCESS) { 276 if (pam_retval != PAM_SUCCESS) {
259 fatal("PAM setcred failed[%d]: %.200s", 277 if(was_authenticated) {
260 pam_retval, PAM_STRERROR(pamh, pam_retval)); 278 fatal("PAM setcred failed[%d]: %.200s",
279 pam_retval, PAM_STRERROR(pamh, pam_retval));
280 } else {
281 debug("PAM setcred failed[%d]: %.200s",
282 pam_retval, PAM_STRERROR(pamh, pam_retval));
283 }
261 } 284 }
262} 285}
263 286
diff --git a/auth-pam.h b/auth-pam.h
index 73f68ec2d..ca261afeb 100644
--- a/auth-pam.h
+++ b/auth-pam.h
@@ -7,11 +7,13 @@ void start_pam(struct passwd *pw);
7void finish_pam(void); 7void finish_pam(void);
8int auth_pam_password(struct passwd *pw, const char *password); 8int auth_pam_password(struct passwd *pw, const char *password);
9char **fetch_pam_environment(void); 9char **fetch_pam_environment(void);
10int do_pam_authenticate(int flags);
10int do_pam_account(char *username, char *remote_user); 11int do_pam_account(char *username, char *remote_user);
11void do_pam_session(char *username, const char *ttyname); 12void do_pam_session(char *username, const char *ttyname);
12void do_pam_setcred(void); 13void do_pam_setcred(void);
13void print_pam_messages(void); 14void print_pam_messages(void);
14int pam_password_change_required(void); 15int pam_password_change_required(void);
15void do_pam_chauthtok(void); 16void do_pam_chauthtok(void);
17void pam_set_conv(struct pam_conv *);
16 18
17#endif /* USE_PAM */ 19#endif /* USE_PAM */
diff --git a/auth.h b/auth.h
index c4a8ac544..ef392ace5 100644
--- a/auth.h
+++ b/auth.h
@@ -34,6 +34,9 @@ struct Authctxt {
34 struct passwd *pw; 34 struct passwd *pw;
35}; 35};
36 36
37#include "auth-pam.h"
38#include "auth2-pam.h"
39
37void do_authentication(void); 40void do_authentication(void);
38void do_authentication2(void); 41void do_authentication2(void);
39 42
diff --git a/auth2-pam.c b/auth2-pam.c
new file mode 100644
index 000000000..8ffbc244c
--- /dev/null
+++ b/auth2-pam.c
@@ -0,0 +1,170 @@
1#include "includes.h"
2RCSID("$Id: auth2-pam.c,v 1.1 2000/12/03 00:51:51 djm Exp $");
3
4#ifdef USE_PAM
5#include "ssh.h"
6#include "ssh2.h"
7#include "auth.h"
8#include "packet.h"
9#include "xmalloc.h"
10#include "dispatch.h"
11#include <security/pam_appl.h>
12
13struct {
14 int finished, num_received, num_expected;
15 int *prompts;
16 struct pam_response *responses;
17} context_pam2 = {0, 0, 0, NULL};
18
19static int do_conversation2(int num_msg, const struct pam_message **msg,
20 struct pam_response **resp, void *appdata_ptr);
21
22static struct pam_conv
23conv2 = {
24 do_conversation2,
25 NULL,
26};
27
28void input_userauth_info_response_pam(int type, int plen, void *ctxt);
29
30int
31auth2_pam(Authctxt *authctxt)
32{
33 int retval = -1;
34 char *method = "PAM";
35
36 if (authctxt->user == NULL)
37 fatal("auth2_pam: internal error: no user");
38
39 if (authctxt->valid) {
40 conv2.appdata_ptr = authctxt;
41 pam_set_conv(&conv2);
42 }
43
44 dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE,
45 &input_userauth_info_response_pam);
46 retval = (do_pam_authenticate(0) == PAM_SUCCESS);
47 dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
48
49 userauth_log(authctxt, retval, method);
50
51 return retval;
52}
53
54static int
55do_conversation2(int num_msg, const struct pam_message **msg,
56 struct pam_response **resp, void *appdata_ptr)
57{
58 int echo = 0, i = 0, j = 0, done = 0;
59 char *tmp = NULL, *text = NULL;
60
61 context_pam2.finished = 0;
62 context_pam2.num_received = 0;
63 context_pam2.num_expected = 0;
64 context_pam2.prompts = xmalloc(sizeof(int) * num_msg);
65 context_pam2.responses = xmalloc(sizeof(struct pam_response) * num_msg);
66 memset(context_pam2.responses, 0, sizeof(struct pam_response) * num_msg);
67
68 packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
69 packet_put_cstring(""); /* Name */
70 packet_put_cstring(""); /* Instructions */
71 packet_put_cstring(""); /* Language */
72 for (i = 0, j = 0; i < num_msg; i++) {
73 if(((*msg)[i].msg_style == PAM_PROMPT_ECHO_ON) ||
74 ((*msg)[i].msg_style == PAM_PROMPT_ECHO_OFF) ||
75 (i == num_msg - 1)) {
76 j++;
77 }
78 }
79 packet_put_int(j); /* Number of prompts. */
80 context_pam2.num_expected = j;
81 for (i = 0, j = 0; i < num_msg; i++) {
82 switch((*msg)[i].msg_style) {
83 case PAM_PROMPT_ECHO_ON:
84 echo = 1;
85 break;
86 case PAM_PROMPT_ECHO_OFF:
87 echo = 0;
88 break;
89 default:
90 echo = 0;
91 break;
92 }
93 if(text) {
94 tmp = xmalloc(strlen(text) + strlen((*msg)[i].msg) + 2);
95 strcpy(tmp, text);
96 strcat(tmp, "\n");
97 strcat(tmp, (*msg)[i].msg);
98 xfree(text);
99 text = tmp;
100 tmp = NULL;
101 } else {
102 text = xstrdup((*msg)[i].msg);
103 }
104 if(((*msg)[i].msg_style == PAM_PROMPT_ECHO_ON) ||
105 ((*msg)[i].msg_style == PAM_PROMPT_ECHO_OFF) ||
106 (i == num_msg - 1)) {
107 debug("sending prompt ssh-%d(pam-%d) = \"%s\"",
108 j, i, text);
109 context_pam2.prompts[j++] = i;
110 packet_put_cstring(text);
111 packet_put_char(echo);
112 xfree(text);
113 text = NULL;
114 }
115 }
116 packet_send();
117 packet_write_wait();
118
119 /* Grabbing control of execution and spinning until we get what
120 * we want is probably rude, but it seems to work properly, and
121 * the client *should* be in lock-step with us, so the loop should
122 * only be traversed once. */
123 while(context_pam2.finished == 0) {
124 done = 1;
125 dispatch_run(DISPATCH_BLOCK, &done, appdata_ptr);
126 if(context_pam2.finished == 0) {
127 debug("extra packet during conversation");
128 }
129 }
130
131 if(context_pam2.num_received == context_pam2.num_expected) {
132 *resp = context_pam2.responses;
133 return PAM_SUCCESS;
134 } else {
135 return PAM_CONV_ERR;
136 }
137}
138
139void
140input_userauth_info_response_pam(int type, int plen, void *ctxt)
141{
142 Authctxt *authctxt = ctxt;
143 unsigned int nresp = 0, rlen = 0, i = 0;
144 char *resp;
145
146 if (authctxt == NULL)
147 fatal("input_userauth_info_response_pam: no authentication context");
148
149 if (authctxt->attempt++ >= AUTH_FAIL_MAX)
150 packet_disconnect("too many failed userauth_requests");
151
152 nresp = packet_get_int(); /* Number of responses. */
153 debug("got %d responses", nresp);
154
155 for (i = 0; i < nresp; i++) {
156 int j = context_pam2.prompts[i];
157 resp = packet_get_string(&rlen);
158 debug("response ssh-%d(pam-%d) = \"%s\"", i, j, resp);
159 context_pam2.responses[j].resp_retcode = PAM_SUCCESS;
160 context_pam2.responses[j].resp = xstrdup(resp);
161 xfree(resp);
162 context_pam2.num_received++;
163 }
164
165 context_pam2.finished = 1;
166
167 packet_done();
168}
169
170#endif
diff --git a/auth2-pam.h b/auth2-pam.h
new file mode 100644
index 000000000..db7aaae04
--- /dev/null
+++ b/auth2-pam.h
@@ -0,0 +1,6 @@
1#include "includes.h"
2#ifdef USE_PAM
3
4int auth2_pam(Authctxt *authctxt);
5
6#endif /* USE_PAM */
diff --git a/auth2.c b/auth2.c
index 46bf07c80..8e8edf920 100644
--- a/auth2.c
+++ b/auth2.c
@@ -400,10 +400,15 @@ userauth_kbdint(Authctxt *authctxt)
400 packet_done(); 400 packet_done();
401 401
402 debug("keyboard-interactive language %s devs %s", lang, devs); 402 debug("keyboard-interactive language %s devs %s", lang, devs);
403#ifdef USE_PAM
404 if (authenticated == 0)
405 authenticated = auth2_pam(authctxt);
406#endif
403#ifdef SKEY 407#ifdef SKEY
404 /* XXX hardcoded, we should look at devs */ 408 /* XXX hardcoded, we should look at devs */
405 if (options.skey_authentication != 0) 409 if (authenticated == 0)
406 authenticated = auth2_skey(authctxt); 410 if (options.skey_authentication != 0)
411 authenticated = auth2_skey(authctxt);
407#endif 412#endif
408 xfree(lang); 413 xfree(lang);
409 xfree(devs); 414 xfree(devs);
diff --git a/ssh.h b/ssh.h
index 2c2afd5a0..996b504a4 100644
--- a/ssh.h
+++ b/ssh.h
@@ -558,8 +558,4 @@ int auth_skey_password(struct passwd * pw, const char *password);
558/* AF_UNSPEC or AF_INET or AF_INET6 */ 558/* AF_UNSPEC or AF_INET or AF_INET6 */
559extern int IPv4or6; 559extern int IPv4or6;
560 560
561#ifdef USE_PAM
562#include "auth-pam.h"
563#endif /* USE_PAM */
564
565#endif /* SSH_H */ 561#endif /* SSH_H */