summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog75
-rw-r--r--Makefile.in6
-rw-r--r--auth-krb4.c16
-rw-r--r--auth-options.c48
-rw-r--r--auth-options.h3
-rw-r--r--auth-pam.c4
-rw-r--r--auth-passwd.c4
-rw-r--r--auth-rh-rsa.c6
-rw-r--r--auth-rhosts.c5
-rw-r--r--auth-rsa.c13
-rw-r--r--auth.c3
-rw-r--r--auth.h20
-rw-r--r--auth1.c246
-rw-r--r--auth2.c428
-rw-r--r--authfd.c13
-rw-r--r--authfd.h6
-rw-r--r--authfile.c44
-rw-r--r--bsd-vis.c137
-rw-r--r--bsd-vis.h32
-rw-r--r--cipher.c707
-rw-r--r--cipher.h129
-rw-r--r--cli.c195
-rw-r--r--cli.h14
-rw-r--r--compat.c41
-rw-r--r--configure.in4
-rw-r--r--dh.c157
-rw-r--r--dh.h35
-rw-r--r--includes.h4
-rw-r--r--kex.c169
-rw-r--r--kex.h35
-rw-r--r--log.c3
-rw-r--r--myproposal.h10
-rw-r--r--openbsd-compat.h1
-rw-r--r--packet.c72
-rw-r--r--readconf.c20
-rw-r--r--readconf.h4
-rw-r--r--readpass.c82
-rw-r--r--rijndael.c493
-rw-r--r--rijndael.h31
-rw-r--r--scp.19
-rw-r--r--scp.c155
-rw-r--r--servconf.c12
-rw-r--r--servconf.h3
-rw-r--r--session.c3
-rw-r--r--sftp-server.82
-rw-r--r--ssh-keygen.15
-rw-r--r--ssh-keygen.c105
-rw-r--r--ssh.18
-rw-r--r--ssh.c23
-rw-r--r--ssh.h13
-rw-r--r--ssh2.h8
-rw-r--r--sshconnect1.c15
-rw-r--r--sshconnect2.c461
-rw-r--r--sshd.816
-rw-r--r--sshd.c225
-rw-r--r--sshd_config1
56 files changed, 3173 insertions, 1206 deletions
diff --git a/ChangeLog b/ChangeLog
index 86e7cea96..61c08bc35 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,81 @@
3 - (djm) Revert SSH2 serverloop hack, will find a better way. 3 - (djm) Revert SSH2 serverloop hack, will find a better way.
4 - (djm) Add workaround for Linux 2.4's gratuitious errno change. Patch 4 - (djm) Add workaround for Linux 2.4's gratuitious errno change. Patch
5 from Martin Johansson <fatbob@acc.umu.se> 5 from Martin Johansson <fatbob@acc.umu.se>
6 - (djm) Big OpenBSD sync:
7 - markus@cvs.openbsd.org 2000/09/30 10:27:44
8 [log.c]
9 allow loglevel debug
10 - markus@cvs.openbsd.org 2000/10/03 11:59:57
11 [packet.c]
12 hmac->mac
13 - markus@cvs.openbsd.org 2000/10/03 12:03:03
14 [auth-krb4.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c]
15 move fake-auth from auth1.c to individual auth methods, disables s/key in
16 debug-msg
17 - markus@cvs.openbsd.org 2000/10/03 12:16:48
18 ssh.c
19 do not resolve canonname, i have no idea why this was added oin ossh
20 - markus@cvs.openbsd.org 2000/10/09 15:30:44
21 ssh-keygen.1 ssh-keygen.c
22 -X now reads private ssh.com DSA keys, too.
23 - markus@cvs.openbsd.org 2000/10/09 15:32:34
24 auth-options.c
25 clear options on every call.
26 - markus@cvs.openbsd.org 2000/10/09 15:51:00
27 authfd.c authfd.h
28 interop with ssh-agent2, from <res@shore.net>
29 - markus@cvs.openbsd.org 2000/10/10 14:20:45
30 compat.c
31 use rexexp for version string matching
32 - provos@cvs.openbsd.org 2000/10/10 22:02:18
33 [kex.c kex.h myproposal.h ssh.h ssh2.h sshconnect2.c sshd.c dh.c dh.h]
34 First rough implementation of the diffie-hellman group exchange. The
35 client can ask the server for bigger groups to perform the diffie-hellman
36 in, thus increasing the attack complexity when using ciphers with longer
37 keys. University of Windsor provided network, T the company.
38 - markus@cvs.openbsd.org 2000/10/11 13:59:52
39 [auth-rsa.c auth2.c]
40 clear auth options unless auth sucessfull
41 - markus@cvs.openbsd.org 2000/10/11 14:00:27
42 [auth-options.h]
43 clear auth options unless auth sucessfull
44 - markus@cvs.openbsd.org 2000/10/11 14:03:27
45 [scp.1 scp.c]
46 support 'scp -o' with help from mouring@pconline.com
47 - markus@cvs.openbsd.org 2000/10/11 14:11:35
48 [dh.c]
49 Wall
50 - markus@cvs.openbsd.org 2000/10/11 14:14:40
51 [auth.h auth2.c readconf.c readconf.h readpass.c servconf.c servconf.h]
52 [ssh.h sshconnect2.c sshd_config auth2-skey.c cli.c cli.h]
53 add support for s/key (kbd-interactive) to ssh2, based on work by
54 mkiernan@avantgo.com and me
55 - markus@cvs.openbsd.org 2000/10/11 14:27:24
56 [auth.c auth1.c auth2.c authfile.c cipher.c cipher.h kex.c kex.h]
57 [myproposal.h packet.c readconf.c session.c ssh.c ssh.h sshconnect1.c]
58 [sshconnect2.c sshd.c]
59 new cipher framework
60 - markus@cvs.openbsd.org 2000/10/11 14:45:21
61 [cipher.c]
62 remove DES
63 - markus@cvs.openbsd.org 2000/10/12 03:59:20
64 [cipher.c cipher.h sshconnect1.c sshconnect2.c sshd.c]
65 enable DES in SSH-1 clients only
66 - markus@cvs.openbsd.org 2000/10/12 08:21:13
67 [kex.h packet.c]
68 remove unused
69 - markus@cvs.openbsd.org 2000/10/13 12:34:46
70 [sshd.c]
71 Kludge for F-Secure Macintosh < 1.0.2; appro@fy.chalmers.se
72 - markus@cvs.openbsd.org 2000/10/13 12:59:15
73 [cipher.c cipher.h myproposal.h rijndael.c rijndael.h]
74 rijndael/aes support
75 - markus@cvs.openbsd.org 2000/10/13 13:10:54
76 [sshd.8]
77 more info about -V
78 - markus@cvs.openbsd.org 2000/10/13 13:12:02
79 [myproposal.h]
80 prefer no compression
6 81
720001007 8220001007
8 - (stevesk) Print PAM return value in PAM log messages to aid 83 - (stevesk) Print PAM return value in PAM log messages to aid
diff --git a/Makefile.in b/Makefile.in
index 2d47f637c..af0886cde 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -35,13 +35,13 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
35 35
36TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) $(EXTRA_TARGETS) 36TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) $(EXTRA_TARGETS)
37 37
38LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o cygwin_util.o deattack.o dispatch.o dsa.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o 38LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o cli.o compat.o compress.o crc32.o cygwin_util.o deattack.o dispatch.o dsa.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o
39 39
40LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o bsd-strtok.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o 40LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o bsd-strtok.o bsd-vis.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o
41 41
42SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o 42SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o
43 43
44SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-rhosts.o auth-options.o auth-krb4.o auth-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o loginrec.o servconf.o serverloop.o md5crypt.o session.o 44SSHDOBJS= sshd.o auth.o auth1.o auth2.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
45 45
46TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 sftp-server.8 46TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 sftp-server.8
47CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0 sftp-server.0 47CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0 sftp-server.0
diff --git a/auth-krb4.c b/auth-krb4.c
index 799cf261a..21a9625e3 100644
--- a/auth-krb4.c
+++ b/auth-krb4.c
@@ -28,7 +28,7 @@
28#include "ssh.h" 28#include "ssh.h"
29#include "servconf.h" 29#include "servconf.h"
30 30
31RCSID("$OpenBSD: auth-krb4.c,v 1.18 2000/09/07 20:27:49 deraadt Exp $"); 31RCSID("$OpenBSD: auth-krb4.c,v 1.19 2000/10/03 18:03:02 markus Exp $");
32 32
33#ifdef KRB4 33#ifdef KRB4
34char *ticket = NULL; 34char *ticket = NULL;
@@ -280,6 +280,8 @@ auth_kerberos_tgt(struct passwd *pw, const char *string)
280{ 280{
281 CREDENTIALS creds; 281 CREDENTIALS creds;
282 282
283 if (pw == NULL)
284 goto auth_kerberos_tgt_failure;
283 if (!radix_to_creds(string, &creds)) { 285 if (!radix_to_creds(string, &creds)) {
284 log("Protocol error decoding Kerberos V4 tgt"); 286 log("Protocol error decoding Kerberos V4 tgt");
285 packet_send_debug("Protocol error decoding Kerberos V4 tgt"); 287 packet_send_debug("Protocol error decoding Kerberos V4 tgt");
@@ -334,8 +336,16 @@ int
334auth_afs_token(struct passwd *pw, const char *token_string) 336auth_afs_token(struct passwd *pw, const char *token_string)
335{ 337{
336 CREDENTIALS creds; 338 CREDENTIALS creds;
337 uid_t uid = pw->pw_uid; 339 uid_t uid;
338 340
341 if (pw == NULL) {
342 /* XXX fake protocol error */
343 packet_send_debug("Protocol error decoding AFS token");
344 packet_start(SSH_SMSG_FAILURE);
345 packet_send();
346 packet_write_wait();
347 return 0;
348 }
339 if (!radix_to_creds(token_string, &creds)) { 349 if (!radix_to_creds(token_string, &creds)) {
340 log("Protocol error decoding AFS token"); 350 log("Protocol error decoding AFS token");
341 packet_send_debug("Protocol error decoding AFS token"); 351 packet_send_debug("Protocol error decoding AFS token");
@@ -349,6 +359,8 @@ auth_afs_token(struct passwd *pw, const char *token_string)
349 359
350 if (strncmp(creds.pname, "AFS ID ", 7) == 0) 360 if (strncmp(creds.pname, "AFS ID ", 7) == 0)
351 uid = atoi(creds.pname + 7); 361 uid = atoi(creds.pname + 7);
362 else
363 uid = pw->pw_uid;
352 364
353 if (kafs_settoken(creds.realm, uid, &creds)) { 365 if (kafs_settoken(creds.realm, uid, &creds)) {
354 log("AFS token (%s@%s) rejected for %s", creds.pname, creds.realm, 366 log("AFS token (%s@%s) rejected for %s", creds.pname, creds.realm,
diff --git a/auth-options.c b/auth-options.c
index da6965266..c9c149d69 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: auth-options.c,v 1.4 2000/09/07 21:13:36 markus Exp $"); 17RCSID("$OpenBSD: auth-options.c,v 1.5 2000/10/09 21:32:34 markus Exp $");
18 18
19#include "ssh.h" 19#include "ssh.h"
20#include "packet.h" 20#include "packet.h"
@@ -33,6 +33,25 @@ char *forced_command = NULL;
33/* "environment=" options. */ 33/* "environment=" options. */
34struct envstring *custom_environment = NULL; 34struct envstring *custom_environment = NULL;
35 35
36void
37auth_clear_options(void)
38{
39 no_agent_forwarding_flag = 0;
40 no_port_forwarding_flag = 0;
41 no_pty_flag = 0;
42 no_x11_forwarding_flag = 0;
43 while (custom_environment) {
44 struct envstring *ce = custom_environment;
45 custom_environment = ce->next;
46 xfree(ce->s);
47 xfree(ce);
48 }
49 if (forced_command) {
50 xfree(forced_command);
51 forced_command = NULL;
52 }
53}
54
36/* return 1 if access is granted, 0 if not. side effect: sets key option flags */ 55/* return 1 if access is granted, 0 if not. side effect: sets key option flags */
37int 56int
38auth_parse_options(struct passwd *pw, char *options, unsigned long linenum) 57auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
@@ -40,6 +59,10 @@ auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
40 const char *cp; 59 const char *cp;
41 if (!options) 60 if (!options)
42 return 1; 61 return 1;
62
63 /* reset options */
64 auth_clear_options();
65
43 while (*options && *options != ' ' && *options != '\t') { 66 while (*options && *options != ' ' && *options != '\t') {
44 cp = "no-port-forwarding"; 67 cp = "no-port-forwarding";
45 if (strncmp(options, cp, strlen(cp)) == 0) { 68 if (strncmp(options, cp, strlen(cp)) == 0) {
@@ -87,9 +110,9 @@ auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
87 } 110 }
88 if (!*options) { 111 if (!*options) {
89 debug("%.100s, line %lu: missing end quote", 112 debug("%.100s, line %lu: missing end quote",
90 SSH_USER_PERMITTED_KEYS, linenum); 113 SSH_USER_PERMITTED_KEYS, linenum);
91 packet_send_debug("%.100s, line %lu: missing end quote", 114 packet_send_debug("%.100s, line %lu: missing end quote",
92 SSH_USER_PERMITTED_KEYS, linenum); 115 SSH_USER_PERMITTED_KEYS, linenum);
93 continue; 116 continue;
94 } 117 }
95 forced_command[i] = 0; 118 forced_command[i] = 0;
@@ -117,9 +140,9 @@ auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
117 } 140 }
118 if (!*options) { 141 if (!*options) {
119 debug("%.100s, line %lu: missing end quote", 142 debug("%.100s, line %lu: missing end quote",
120 SSH_USER_PERMITTED_KEYS, linenum); 143 SSH_USER_PERMITTED_KEYS, linenum);
121 packet_send_debug("%.100s, line %lu: missing end quote", 144 packet_send_debug("%.100s, line %lu: missing end quote",
122 SSH_USER_PERMITTED_KEYS, linenum); 145 SSH_USER_PERMITTED_KEYS, linenum);
123 continue; 146 continue;
124 } 147 }
125 s[i] = 0; 148 s[i] = 0;
@@ -175,21 +198,6 @@ auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
175 get_remote_ipaddr()); 198 get_remote_ipaddr());
176 packet_send_debug("Your host '%.200s' is not permitted to use this key for login.", 199 packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
177 get_canonical_hostname()); 200 get_canonical_hostname());
178 /* key invalid for this host, reset flags */
179 no_agent_forwarding_flag = 0;
180 no_port_forwarding_flag = 0;
181 no_pty_flag = 0;
182 no_x11_forwarding_flag = 0;
183 while (custom_environment) {
184 struct envstring *ce = custom_environment;
185 custom_environment = ce->next;
186 xfree(ce->s);
187 xfree(ce);
188 }
189 if (forced_command) {
190 xfree(forced_command);
191 forced_command = NULL;
192 }
193 /* deny access */ 201 /* deny access */
194 return 0; 202 return 0;
195 } 203 }
diff --git a/auth-options.h b/auth-options.h
index 9044d98be..02ac5df1d 100644
--- a/auth-options.h
+++ b/auth-options.h
@@ -22,4 +22,7 @@ extern struct envstring *custom_environment;
22 22
23/* return 1 if access is granted, 0 if not. side effect: sets key option flags */ 23/* return 1 if access is granted, 0 if not. side effect: sets key option flags */
24int auth_parse_options(struct passwd *pw, char *options, unsigned long linenum); 24int auth_parse_options(struct passwd *pw, char *options, unsigned long linenum);
25/* reset options flags */
26void auth_clear_options(void);
27
25#endif 28#endif
diff --git a/auth-pam.c b/auth-pam.c
index f4cbd46e2..ab20782f2 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.15 2000/10/14 00:16:12 djm Exp $"); 32RCSID("$Id: auth-pam.c,v 1.16 2000/10/14 05:23:11 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"
@@ -257,7 +257,7 @@ void do_pam_setcred()
257 pam_retval = pam_setcred(pamh, PAM_ESTABLISH_CRED); 257 pam_retval = pam_setcred(pamh, PAM_ESTABLISH_CRED);
258 if (pam_retval != PAM_SUCCESS) { 258 if (pam_retval != PAM_SUCCESS) {
259 fatal("PAM setcred failed[%d]: %.200s", 259 fatal("PAM setcred failed[%d]: %.200s",
260 pam_setcred, PAM_STRERROR(pamh, pam_retval)); 260 pam_retval, PAM_STRERROR(pamh, pam_retval));
261 } 261 }
262} 262}
263 263
diff --git a/auth-passwd.c b/auth-passwd.c
index 8dd6034d8..184ce154c 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -59,7 +59,7 @@
59 */ 59 */
60 60
61#include "includes.h" 61#include "includes.h"
62RCSID("$OpenBSD: auth-passwd.c,v 1.17 2000/09/07 20:27:49 deraadt Exp $"); 62RCSID("$OpenBSD: auth-passwd.c,v 1.18 2000/10/03 18:03:03 markus Exp $");
63 63
64#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA) 64#if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
65 65
@@ -156,7 +156,7 @@ auth_password(struct passwd * pw, const char *password)
156 } 156 }
157#endif 157#endif
158 158
159#ifdef SKEY 159#ifdef SKEY_VIA_PASSWD_IS_DISABLED
160 if (options.skey_authentication == 1) { 160 if (options.skey_authentication == 1) {
161 int ret = auth_skey_password(pw, password); 161 int ret = auth_skey_password(pw, password);
162 if (ret == 1 || ret == 0) 162 if (ret == 1 || ret == 0)
diff --git a/auth-rh-rsa.c b/auth-rh-rsa.c
index 072e385ab..3070c9d41 100644
--- a/auth-rh-rsa.c
+++ b/auth-rh-rsa.c
@@ -13,7 +13,7 @@
13 */ 13 */
14 14
15#include "includes.h" 15#include "includes.h"
16RCSID("$OpenBSD: auth-rh-rsa.c,v 1.16 2000/09/07 21:13:36 markus Exp $"); 16RCSID("$OpenBSD: auth-rh-rsa.c,v 1.17 2000/10/03 18:03:03 markus Exp $");
17 17
18#include "packet.h" 18#include "packet.h"
19#include "ssh.h" 19#include "ssh.h"
@@ -39,9 +39,9 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key
39 HostStatus host_status; 39 HostStatus host_status;
40 Key *client_key, *found; 40 Key *client_key, *found;
41 41
42 debug("Trying rhosts with RSA host authentication for %.100s", client_user); 42 debug("Trying rhosts with RSA host authentication for client user %.100s", client_user);
43 43
44 if (client_host_key == NULL) 44 if (pw == NULL || client_host_key == NULL)
45 return 0; 45 return 0;
46 46
47 /* Check if we would accept it using rhosts authentication. */ 47 /* Check if we would accept it using rhosts authentication. */
diff --git a/auth-rhosts.c b/auth-rhosts.c
index 901c8d139..8314e23a1 100644
--- a/auth-rhosts.c
+++ b/auth-rhosts.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: auth-rhosts.c,v 1.15 2000/09/07 20:27:49 deraadt Exp $"); 17RCSID("$OpenBSD: auth-rhosts.c,v 1.16 2000/10/03 18:03:03 markus Exp $");
18 18
19#include "packet.h" 19#include "packet.h"
20#include "ssh.h" 20#include "ssh.h"
@@ -154,6 +154,9 @@ auth_rhosts(struct passwd *pw, const char *client_user)
154 static const char *rhosts_files[] = {".shosts", ".rhosts", NULL}; 154 static const char *rhosts_files[] = {".shosts", ".rhosts", NULL};
155 unsigned int rhosts_file_index; 155 unsigned int rhosts_file_index;
156 156
157 /* no user given */
158 if (pw == NULL)
159 return 0;
157 /* Switch to the user's uid. */ 160 /* Switch to the user's uid. */
158 temporarily_use_uid(pw->pw_uid); 161 temporarily_use_uid(pw->pw_uid);
159 /* 162 /*
diff --git a/auth-rsa.c b/auth-rsa.c
index 8aefc8fad..522f01f84 100644
--- a/auth-rsa.c
+++ b/auth-rsa.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: auth-rsa.c,v 1.29 2000/09/07 21:13:36 markus Exp $"); 17RCSID("$OpenBSD: auth-rsa.c,v 1.31 2000/10/11 19:59:52 markus Exp $");
18 18
19#include "rsa.h" 19#include "rsa.h"
20#include "packet.h" 20#include "packet.h"
@@ -29,6 +29,10 @@ RCSID("$OpenBSD: auth-rsa.c,v 1.29 2000/09/07 21:13:36 markus Exp $");
29#include <openssl/rsa.h> 29#include <openssl/rsa.h>
30#include <openssl/md5.h> 30#include <openssl/md5.h>
31 31
32
33/* import */
34extern ServerOptions options;
35
32/* 36/*
33 * Session identifier that is used to bind key exchange and authentication 37 * Session identifier that is used to bind key exchange and authentication
34 * responses to a particular session. 38 * responses to a particular session.
@@ -116,7 +120,6 @@ auth_rsa_challenge_dialog(RSA *pk)
116int 120int
117auth_rsa(struct passwd *pw, BIGNUM *client_n) 121auth_rsa(struct passwd *pw, BIGNUM *client_n)
118{ 122{
119 extern ServerOptions options;
120 char line[8192], file[1024]; 123 char line[8192], file[1024];
121 int authenticated; 124 int authenticated;
122 unsigned int bits; 125 unsigned int bits;
@@ -125,6 +128,10 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
125 struct stat st; 128 struct stat st;
126 RSA *pk; 129 RSA *pk;
127 130
131 /* no user given */
132 if (pw == NULL)
133 return 0;
134
128 /* Temporarily use the user's uid. */ 135 /* Temporarily use the user's uid. */
129 temporarily_use_uid(pw->pw_uid); 136 temporarily_use_uid(pw->pw_uid);
130 137
@@ -277,6 +284,8 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
277 284
278 if (authenticated) 285 if (authenticated)
279 packet_send_debug("RSA authentication accepted."); 286 packet_send_debug("RSA authentication accepted.");
287 else
288 auth_clear_options();
280 289
281 /* Return authentication result. */ 290 /* Return authentication result. */
282 return authenticated; 291 return authenticated;
diff --git a/auth.c b/auth.c
index 883f08ab0..bc42c96cb 100644
--- a/auth.c
+++ b/auth.c
@@ -33,7 +33,7 @@
33 */ 33 */
34 34
35#include "includes.h" 35#include "includes.h"
36RCSID("$OpenBSD: auth.c,v 1.10 2000/09/07 21:13:36 markus Exp $"); 36RCSID("$OpenBSD: auth.c,v 1.11 2000/10/11 20:27:23 markus Exp $");
37 37
38#include "xmalloc.h" 38#include "xmalloc.h"
39#include "rsa.h" 39#include "rsa.h"
@@ -41,7 +41,6 @@ RCSID("$OpenBSD: auth.c,v 1.10 2000/09/07 21:13:36 markus Exp $");
41#include "pty.h" 41#include "pty.h"
42#include "packet.h" 42#include "packet.h"
43#include "buffer.h" 43#include "buffer.h"
44#include "cipher.h"
45#include "mpaux.h" 44#include "mpaux.h"
46#include "servconf.h" 45#include "servconf.h"
47#include "compat.h" 46#include "compat.h"
diff --git a/auth.h b/auth.h
index 65bf7ae10..c4a8ac544 100644
--- a/auth.h
+++ b/auth.h
@@ -24,17 +24,29 @@
24#ifndef AUTH_H 24#ifndef AUTH_H
25#define AUTH_H 25#define AUTH_H
26 26
27typedef struct Authctxt Authctxt;
28struct Authctxt {
29 int success;
30 int valid;
31 int attempt;
32 char *user;
33 char *service;
34 struct passwd *pw;
35};
36
27void do_authentication(void); 37void do_authentication(void);
28void do_authentication2(void); 38void do_authentication2(void);
29 39
30struct passwd * 40void userauth_log(Authctxt *authctxt, int authenticated, char *method);
31auth_get_user(void); 41void userauth_reply(Authctxt *authctxt, int authenticated);
42
43int auth2_skey(Authctxt *authctxt);
32 44
33int allowed_user(struct passwd * pw); 45int allowed_user(struct passwd * pw);
46struct passwd * auth_get_user(void);
34 47
35#define AUTH_FAIL_MAX 6 48#define AUTH_FAIL_MAX 6
36#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2) 49#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
37#define AUTH_FAIL_MSG "Too many authentication failures for %.100s" 50#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
38 51
39#endif 52#endif
40
diff --git a/auth1.c b/auth1.c
index 99639b59f..520da640c 100644
--- a/auth1.c
+++ b/auth1.c
@@ -10,28 +10,31 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: auth1.c,v 1.4 2000/09/07 20:27:49 deraadt Exp $"); 13RCSID("$OpenBSD: auth1.c,v 1.6 2000/10/11 20:27:23 markus Exp $");
14
15#ifdef HAVE_OSF_SIA
16# include <sia.h>
17# include <siad.h>
18#endif
14 19
15#include "xmalloc.h" 20#include "xmalloc.h"
16#include "rsa.h" 21#include "rsa.h"
17#include "ssh.h" 22#include "ssh.h"
18#include "packet.h" 23#include "packet.h"
19#include "buffer.h" 24#include "buffer.h"
20#include "cipher.h"
21#include "mpaux.h" 25#include "mpaux.h"
22#include "servconf.h" 26#include "servconf.h"
23#include "compat.h" 27#include "compat.h"
24#include "auth.h" 28#include "auth.h"
25#include "session.h" 29#include "session.h"
26 30
27#ifdef HAVE_OSF_SIA
28# include <sia.h>
29# include <siad.h>
30#endif
31
32/* import */ 31/* import */
33extern ServerOptions options; 32extern ServerOptions options;
34extern char *forced_command; 33extern char *forced_command;
34
35#ifdef WITH_AIXAUTHENTICATE
36extern char *aixloginmsg;
37#endif /* WITH_AIXAUTHENTICATE */
35#ifdef HAVE_OSF_SIA 38#ifdef HAVE_OSF_SIA
36extern int saved_argc; 39extern int saved_argc;
37extern char **saved_argv; 40extern char **saved_argv;
@@ -67,89 +70,21 @@ get_authname(int type)
67} 70}
68 71
69/* 72/*
70 * The user does not exist or access is denied, 73 * read packets and try to authenticate local user 'luser'.
71 * but fake indication that authentication is needed. 74 * return if authentication is successfull. not that pw == NULL
75 * if the user does not exists or is not allowed to login.
76 * each auth method has to 'fake' authentication for nonexisting
77 * users.
72 */ 78 */
73void 79void
74do_fake_authloop1(char *user) 80do_authloop(struct passwd * pw, char *luser)
75{
76 int attempt = 0;
77
78 log("Faking authloop for illegal user %.200s from %.200s port %d",
79 user,
80 get_remote_ipaddr(),
81 get_remote_port());
82
83#ifdef WITH_AIXAUTHENTICATE
84 loginfailed(user,get_canonical_hostname(),"ssh");
85#endif /* WITH_AIXAUTHENTICATE */
86
87 /* Indicate that authentication is needed. */
88 packet_start(SSH_SMSG_FAILURE);
89 packet_send();
90 packet_write_wait();
91
92 /*
93 * Keep reading packets, and always respond with a failure. This is
94 * to avoid disclosing whether such a user really exists.
95 */
96 for (attempt = 1;; attempt++) {
97 /* Read a packet. This will not return if the client disconnects. */
98 int plen;
99#ifndef SKEY
100 (void)packet_read(&plen);
101#else /* SKEY */
102 int type = packet_read(&plen);
103 unsigned int dlen;
104 char *password, *skeyinfo;
105 password = NULL;
106 /* Try to send a fake s/key challenge. */
107 if (options.skey_authentication == 1 &&
108 (skeyinfo = skey_fake_keyinfo(user)) != NULL) {
109 if (type == SSH_CMSG_AUTH_TIS) {
110 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
111 packet_put_string(skeyinfo, strlen(skeyinfo));
112 packet_send();
113 packet_write_wait();
114 continue;
115 } else if (type == SSH_CMSG_AUTH_PASSWORD &&
116 options.password_authentication &&
117 (password = packet_get_string(&dlen)) != NULL &&
118 dlen == 5 &&
119 strncasecmp(password, "s/key", 5) == 0 ) {
120 packet_send_debug(skeyinfo);
121 }
122 }
123 if (password != NULL)
124 xfree(password);
125#endif
126 if (attempt > AUTH_FAIL_MAX)
127 packet_disconnect(AUTH_FAIL_MSG, user);
128
129 /*
130 * Send failure. This should be indistinguishable from a
131 * failed authentication.
132 */
133 packet_start(SSH_SMSG_FAILURE);
134 packet_send();
135 packet_write_wait();
136 }
137 /* NOTREACHED */
138 abort();
139}
140
141/*
142 * read packets and try to authenticate local user *pw.
143 * return if authentication is successfull
144 */
145void
146do_authloop(struct passwd * pw)
147{ 81{
82 int authenticated = 0;
148 int attempt = 0; 83 int attempt = 0;
149 unsigned int bits; 84 unsigned int bits;
150 RSA *client_host_key; 85 RSA *client_host_key;
151 BIGNUM *n; 86 BIGNUM *n;
152 char *client_user = NULL, *password = NULL; 87 char *client_user, *password;
153 char user[1024]; 88 char user[1024];
154 unsigned int dlen; 89 unsigned int dlen;
155 int plen, nlen, elen; 90 int plen, nlen, elen;
@@ -162,8 +97,12 @@ do_authloop(struct passwd * pw)
162 packet_send(); 97 packet_send();
163 packet_write_wait(); 98 packet_write_wait();
164 99
100 client_user = NULL;
101
165 for (attempt = 1;; attempt++) { 102 for (attempt = 1;; attempt++) {
166 int authenticated = 0; 103 /* default to fail */
104 authenticated = 0;
105
167 strlcpy(user, "", sizeof user); 106 strlcpy(user, "", sizeof user);
168 107
169 /* Get a packet from the client. */ 108 /* Get a packet from the client. */
@@ -174,7 +113,6 @@ do_authloop(struct passwd * pw)
174#ifdef AFS 113#ifdef AFS
175 case SSH_CMSG_HAVE_KERBEROS_TGT: 114 case SSH_CMSG_HAVE_KERBEROS_TGT:
176 if (!options.kerberos_tgt_passing) { 115 if (!options.kerberos_tgt_passing) {
177 /* packet_get_all(); */
178 verbose("Kerberos tgt passing disabled."); 116 verbose("Kerberos tgt passing disabled.");
179 break; 117 break;
180 } else { 118 } else {
@@ -182,14 +120,13 @@ do_authloop(struct passwd * pw)
182 char *tgt = packet_get_string(&dlen); 120 char *tgt = packet_get_string(&dlen);
183 packet_integrity_check(plen, 4 + dlen, type); 121 packet_integrity_check(plen, 4 + dlen, type);
184 if (!auth_kerberos_tgt(pw, tgt)) 122 if (!auth_kerberos_tgt(pw, tgt))
185 verbose("Kerberos tgt REFUSED for %s", pw->pw_name); 123 verbose("Kerberos tgt REFUSED for %.100s", luser);
186 xfree(tgt); 124 xfree(tgt);
187 } 125 }
188 continue; 126 continue;
189 127
190 case SSH_CMSG_HAVE_AFS_TOKEN: 128 case SSH_CMSG_HAVE_AFS_TOKEN:
191 if (!options.afs_token_passing || !k_hasafs()) { 129 if (!options.afs_token_passing || !k_hasafs()) {
192 /* packet_get_all(); */
193 verbose("AFS token passing disabled."); 130 verbose("AFS token passing disabled.");
194 break; 131 break;
195 } else { 132 } else {
@@ -197,7 +134,7 @@ do_authloop(struct passwd * pw)
197 char *token_string = packet_get_string(&dlen); 134 char *token_string = packet_get_string(&dlen);
198 packet_integrity_check(plen, 4 + dlen, type); 135 packet_integrity_check(plen, 4 + dlen, type);
199 if (!auth_afs_token(pw, token_string)) 136 if (!auth_afs_token(pw, token_string))
200 verbose("AFS token REFUSED for %s", pw->pw_name); 137 verbose("AFS token REFUSED for %.100s", luser);
201 xfree(token_string); 138 xfree(token_string);
202 } 139 }
203 continue; 140 continue;
@@ -219,11 +156,12 @@ do_authloop(struct passwd * pw)
219 memcpy(auth.dat, kdata, auth.length); 156 memcpy(auth.dat, kdata, auth.length);
220 xfree(kdata); 157 xfree(kdata);
221 158
222 authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user); 159 if (pw != NULL) {
223 160 authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
224 if (authenticated) { 161 if (authenticated) {
225 snprintf(user, sizeof user, " tktuser %s", tkt_user); 162 snprintf(user, sizeof user, " tktuser %s", tkt_user);
226 xfree(tkt_user); 163 xfree(tkt_user);
164 }
227 } 165 }
228 } 166 }
229 break; 167 break;
@@ -243,8 +181,7 @@ do_authloop(struct passwd * pw)
243 client_user = packet_get_string(&ulen); 181 client_user = packet_get_string(&ulen);
244 packet_integrity_check(plen, 4 + ulen, type); 182 packet_integrity_check(plen, 4 + ulen, type);
245 183
246 /* Try to authenticate using /etc/hosts.equiv and 184 /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
247 .rhosts. */
248 authenticated = auth_rhosts(pw, client_user); 185 authenticated = auth_rhosts(pw, client_user);
249 186
250 snprintf(user, sizeof user, " ruser %s", client_user); 187 snprintf(user, sizeof user, " ruser %s", client_user);
@@ -275,7 +212,7 @@ do_authloop(struct passwd * pw)
275 packet_get_bignum(client_host_key->n, &nlen); 212 packet_get_bignum(client_host_key->n, &nlen);
276 213
277 if (bits != BN_num_bits(client_host_key->n)) 214 if (bits != BN_num_bits(client_host_key->n))
278 log("Warning: keysize mismatch for client_host_key: " 215 verbose("Warning: keysize mismatch for client_host_key: "
279 "actual %d, announced %d", BN_num_bits(client_host_key->n), bits); 216 "actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
280 packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type); 217 packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
281 218
@@ -322,7 +259,7 @@ do_authloop(struct passwd * pw)
322 authenticated = 1; 259 authenticated = 1;
323 } 260 }
324#else /* !USE_PAM && !HAVE_OSF_SIA */ 261#else /* !USE_PAM && !HAVE_OSF_SIA */
325 /* Try authentication with the password. */ 262 /* Try authentication with the password. */
326 authenticated = auth_password(pw, password); 263 authenticated = auth_password(pw, password);
327#endif /* USE_PAM */ 264#endif /* USE_PAM */
328 265
@@ -334,16 +271,18 @@ do_authloop(struct passwd * pw)
334 case SSH_CMSG_AUTH_TIS: 271 case SSH_CMSG_AUTH_TIS:
335 debug("rcvd SSH_CMSG_AUTH_TIS"); 272 debug("rcvd SSH_CMSG_AUTH_TIS");
336 if (options.skey_authentication == 1) { 273 if (options.skey_authentication == 1) {
337 char *skeyinfo = skey_keyinfo(pw->pw_name); 274 char *skeyinfo = NULL;
275 if (pw != NULL)
276 skey_keyinfo(pw->pw_name);
338 if (skeyinfo == NULL) { 277 if (skeyinfo == NULL) {
339 debug("generating fake skeyinfo for %.100s.", pw->pw_name); 278 debug("generating fake skeyinfo for %.100s.", luser);
340 skeyinfo = skey_fake_keyinfo(pw->pw_name); 279 skeyinfo = skey_fake_keyinfo(luser);
341 } 280 }
342 if (skeyinfo != NULL) { 281 if (skeyinfo != NULL) {
343 /* we send our s/key- in tis-challenge messages */ 282 /* we send our s/key- in tis-challenge messages */
344 debug("sending challenge '%s'", skeyinfo); 283 debug("sending challenge '%s'", skeyinfo);
345 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); 284 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
346 packet_put_string(skeyinfo, strlen(skeyinfo)); 285 packet_put_cstring(skeyinfo);
347 packet_send(); 286 packet_send();
348 packet_write_wait(); 287 packet_write_wait();
349 continue; 288 continue;
@@ -356,8 +295,9 @@ do_authloop(struct passwd * pw)
356 char *response = packet_get_string(&dlen); 295 char *response = packet_get_string(&dlen);
357 debug("skey response == '%s'", response); 296 debug("skey response == '%s'", response);
358 packet_integrity_check(plen, 4 + dlen, type); 297 packet_integrity_check(plen, 4 + dlen, type);
359 authenticated = (skey_haskey(pw->pw_name) == 0 && 298 authenticated = (pw != NULL &&
360 skey_passcheck(pw->pw_name, response) != -1); 299 skey_haskey(pw->pw_name) == 0 &&
300 skey_passcheck(pw->pw_name, response) != -1);
361 xfree(response); 301 xfree(response);
362 } 302 }
363 break; 303 break;
@@ -376,12 +316,14 @@ do_authloop(struct passwd * pw)
376 log("Unknown message during authentication: type %d", type); 316 log("Unknown message during authentication: type %d", type);
377 break; 317 break;
378 } 318 }
319 if (authenticated && pw == NULL)
320 fatal("internal error: authenticated for pw == NULL");
379 321
380#ifdef HAVE_CYGWIN 322#ifdef HAVE_CYGWIN
381 if (authenticated && 323 if (authenticated &&
382 !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,pw->pw_uid)) { 324 !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,pw->pw_uid)) {
383 packet_disconnect("Authentication rejected for uid %d.", 325 packet_disconnect("Authentication rejected for uid %d.",
384 (int) pw->pw_uid); 326 (int)pw->pw_uid);
385 authenticated = 0; 327 authenticated = 0;
386 } 328 }
387#endif 329#endif
@@ -391,7 +333,7 @@ do_authloop(struct passwd * pw)
391 * are disallowed. 333 * are disallowed.
392 * Note that root login is allowed for forced commands. 334 * Note that root login is allowed for forced commands.
393 */ 335 */
394 if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) { 336 if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
395 if (forced_command) { 337 if (forced_command) {
396 log("Root login accepted for forced command."); 338 log("Root login accepted for forced command.");
397 } else { 339 } else {
@@ -407,41 +349,33 @@ do_authloop(struct passwd * pw)
407 type == SSH_CMSG_AUTH_PASSWORD) 349 type == SSH_CMSG_AUTH_PASSWORD)
408 authlog = log; 350 authlog = log;
409 351
410 authlog("%s %s for %.200s from %.200s port %d%s", 352 authlog("%s %s for %s%.100s from %.200s port %d%s",
411 authenticated ? "Accepted" : "Failed", 353 authenticated ? "Accepted" : "Failed",
412 get_authname(type), 354 get_authname(type),
413 pw->pw_uid == 0 ? "ROOT" : pw->pw_name, 355 pw ? "" : "illegal user ",
356 pw && pw->pw_uid == 0 ? "ROOT" : luser,
414 get_remote_ipaddr(), 357 get_remote_ipaddr(),
415 get_remote_port(), 358 get_remote_port(),
416 user); 359 user);
417 360
418#ifdef USE_PAM 361#ifdef USE_PAM
419 if (authenticated) { 362 if (authenticated && !do_pam_account(pw->pw_name, client_user))
420 if (!do_pam_account(pw->pw_name, client_user)) { 363 authenticated = 0;
421 if (client_user != NULL) { 364#endif
422 xfree(client_user);
423 client_user = NULL;
424 }
425 do_fake_authloop1(pw->pw_name);
426 }
427 return;
428 }
429#else /* USE_PAM */
430 if (authenticated) {
431 return;
432 }
433#endif /* USE_PAM */
434 365
435 if (client_user != NULL) { 366 if (client_user != NULL) {
436 xfree(client_user); 367 xfree(client_user);
437 client_user = NULL; 368 client_user = NULL;
438 } 369 }
439 370
371 if (authenticated)
372 return;
373
440 if (attempt > AUTH_FAIL_MAX) { 374 if (attempt > AUTH_FAIL_MAX) {
441#ifdef WITH_AIXAUTHENTICATE 375#ifdef WITH_AIXAUTHENTICATE
442 loginfailed(pw->pw_name,get_canonical_hostname(),"ssh"); 376 loginfailed(user,get_canonical_hostname(),"ssh");
443#endif /* WITH_AIXAUTHENTICATE */ 377#endif /* WITH_AIXAUTHENTICATE */
444 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name); 378 packet_disconnect(AUTH_FAIL_MSG, luser);
445 } 379 }
446 380
447 /* Send a message indicating that the authentication attempt failed. */ 381 /* Send a message indicating that the authentication attempt failed. */
@@ -462,9 +396,6 @@ do_authentication()
462 int plen; 396 int plen;
463 unsigned int ulen; 397 unsigned int ulen;
464 char *user; 398 char *user;
465#ifdef WITH_AIXAUTHENTICATE
466 extern char *aixloginmsg;
467#endif /* WITH_AIXAUTHENTICATE */
468 399
469 /* Get the name of the user that we wish to log in as. */ 400 /* Get the name of the user that we wish to log in as. */
470 packet_read_expect(&plen, SSH_CMSG_USER); 401 packet_read_expect(&plen, SSH_CMSG_USER);
@@ -485,38 +416,38 @@ do_authentication()
485 416
486 /* Verify that the user is a valid user. */ 417 /* Verify that the user is a valid user. */
487 pw = getpwnam(user); 418 pw = getpwnam(user);
488 if (!pw || !allowed_user(pw)) 419 if (pw && allowed_user(pw)) {
489 do_fake_authloop1(user); 420 /* Take a copy of the returned structure. */
490 xfree(user); 421 memset(&pwcopy, 0, sizeof(pwcopy));
491 422 pwcopy.pw_name = xstrdup(pw->pw_name);
492 /* Take a copy of the returned structure. */ 423 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
493 memset(&pwcopy, 0, sizeof(pwcopy)); 424 pwcopy.pw_uid = pw->pw_uid;
494 pwcopy.pw_name = xstrdup(pw->pw_name); 425 pwcopy.pw_gid = pw->pw_gid;
495 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
496 pwcopy.pw_uid = pw->pw_uid;
497 pwcopy.pw_gid = pw->pw_gid;
498#ifdef HAVE_PW_CLASS_IN_PASSWD 426#ifdef HAVE_PW_CLASS_IN_PASSWD
499 pwcopy.pw_class = xstrdup(pw->pw_class); 427 pwcopy.pw_class = xstrdup(pw->pw_class);
500#endif 428#endif
501 pwcopy.pw_dir = xstrdup(pw->pw_dir); 429 pwcopy.pw_dir = xstrdup(pw->pw_dir);
502 pwcopy.pw_shell = xstrdup(pw->pw_shell); 430 pwcopy.pw_shell = xstrdup(pw->pw_shell);
503 pw = &pwcopy; 431 pw = &pwcopy;
432 } else {
433 pw = NULL;
434 }
504 435
505#ifdef USE_PAM 436#ifdef USE_PAM
506 start_pam(pw); 437 if (pw)
438 start_pam(pw);
507#endif 439#endif
508 440
509#ifndef HAVE_CYGWIN
510 /* 441 /*
511 * If we are not running as root, the user must have the same uid as 442 * If we are not running as root, the user must have the same uid as
512 * the server. 443 * the server. (Unless you are running Windows)
513 * Rule not valid on Windows systems.
514 */ 444 */
515 if (getuid() != 0 && pw->pw_uid != getuid()) 445#ifndef HAVE_CYGWIN
446 if (getuid() != 0 && pw && pw->pw_uid != getuid())
516 packet_disconnect("Cannot change user when server not running as root."); 447 packet_disconnect("Cannot change user when server not running as root.");
517#endif 448#endif
518 449
519 debug("Attempting authentication for %.100s.", pw->pw_name); 450 debug("Attempting authentication for %s%.100s.", pw ? "" : "illegal user ", user);
520 451
521 /* If the user has no password, accept authentication immediately. */ 452 /* If the user has no password, accept authentication immediately. */
522 if (options.password_authentication && 453 if (options.password_authentication &&
@@ -527,30 +458,33 @@ do_authentication()
527 auth_pam_password(pw, "")) { 458 auth_pam_password(pw, "")) {
528#elif defined(HAVE_OSF_SIA) 459#elif defined(HAVE_OSF_SIA)
529 (sia_validate_user(NULL, saved_argc, saved_argv, 460 (sia_validate_user(NULL, saved_argc, saved_argv,
530 get_canonical_hostname(), pw->pw_name, NULL, 0, NULL, 461 get_canonical_hostname(), pw->pw_name, NULL, 0,
531 "") == SIASUCCESS)) { 462 NULL, "") == SIASUCCESS)) {
532#else /* !HAVE_OSF_SIA && !USE_PAM */ 463#else /* !HAVE_OSF_SIA && !USE_PAM */
533 auth_password(pw, "")) { 464 auth_password(pw, "")) {
534#endif /* USE_PAM */ 465#endif /* USE_PAM */
535 /* Authentication with empty password succeeded. */ 466 /* Authentication with empty password succeeded. */
536 log("Login for user %s from %.100s, accepted without authentication.", 467 log("Login for user %s from %.100s, accepted without authentication.",
537 pw->pw_name, get_remote_ipaddr()); 468 user, get_remote_ipaddr());
538 } else { 469 } else {
539 /* Loop until the user has been authenticated or the 470 /* Loop until the user has been authenticated or the
540 connection is closed, do_authloop() returns only if 471 connection is closed, do_authloop() returns only if
541 authentication is successfull */ 472 authentication is successfull */
542 do_authloop(pw); 473 do_authloop(pw, user);
543 } 474 }
475 if (pw == NULL)
476 fatal("internal error, authentication successfull for user '%.100s'", user);
544 477
545 /* The user has been authenticated and accepted. */ 478 /* The user has been authenticated and accepted. */
479 packet_start(SSH_SMSG_SUCCESS);
480 packet_send();
481 packet_write_wait();
482
546#ifdef WITH_AIXAUTHENTICATE 483#ifdef WITH_AIXAUTHENTICATE
547 /* We don't have a pty yet, so just label the line as "ssh" */ 484 /* We don't have a pty yet, so just label the line as "ssh" */
548 if (loginsuccess(user,get_canonical_hostname(),"ssh",&aixloginmsg) < 0) 485 if (loginsuccess(user,get_canonical_hostname(),"ssh",&aixloginmsg) < 0)
549 aixloginmsg = NULL; 486 aixloginmsg = NULL;
550#endif /* WITH_AIXAUTHENTICATE */ 487#endif /* WITH_AIXAUTHENTICATE */
551 packet_start(SSH_SMSG_SUCCESS);
552 packet_send();
553 packet_write_wait();
554 488
555 /* Perform session preparation. */ 489 /* Perform session preparation. */
556 do_authenticated(pw); 490 do_authenticated(pw);
diff --git a/auth2.c b/auth2.c
index 2c8c0bfdd..f34b586d4 100644
--- a/auth2.c
+++ b/auth2.c
@@ -23,7 +23,12 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: auth2.c,v 1.16 2000/09/27 21:41:34 markus Exp $"); 26RCSID("$OpenBSD: auth2.c,v 1.19 2000/10/11 20:27:23 markus Exp $");
27
28#ifdef HAVE_OSF_SIA
29# include <sia.h>
30# include <siad.h>
31#endif
27 32
28#include <openssl/dsa.h> 33#include <openssl/dsa.h>
29#include <openssl/rsa.h> 34#include <openssl/rsa.h>
@@ -35,7 +40,6 @@ RCSID("$OpenBSD: auth2.c,v 1.16 2000/09/27 21:41:34 markus Exp $");
35#include "pty.h" 40#include "pty.h"
36#include "packet.h" 41#include "packet.h"
37#include "buffer.h" 42#include "buffer.h"
38#include "cipher.h"
39#include "servconf.h" 43#include "servconf.h"
40#include "compat.h" 44#include "compat.h"
41#include "channels.h" 45#include "channels.h"
@@ -52,59 +56,85 @@ RCSID("$OpenBSD: auth2.c,v 1.16 2000/09/27 21:41:34 markus Exp $");
52#include "uidswap.h" 56#include "uidswap.h"
53#include "auth-options.h" 57#include "auth-options.h"
54 58
55#ifdef HAVE_OSF_SIA
56# include <sia.h>
57# include <siad.h>
58#endif
59
60/* import */ 59/* import */
61extern ServerOptions options; 60extern ServerOptions options;
62extern unsigned char *session_id2; 61extern unsigned char *session_id2;
63extern int session_id2_len; 62extern int session_id2_len;
64 63
64#ifdef WITH_AIXAUTHENTICATE
65extern char *aixloginmsg;
66#endif
67#ifdef HAVE_OSF_SIA
68extern int saved_argc;
69extern char **saved_argv;
70#endif
71
72static Authctxt *x_authctxt = NULL;
73static int one = 1;
74
75typedef struct Authmethod Authmethod;
76struct Authmethod {
77 char *name;
78 int (*userauth)(Authctxt *authctxt);
79 int *enabled;
80};
81
65/* protocol */ 82/* protocol */
66 83
67void input_service_request(int type, int plen, void *ctxt); 84void input_service_request(int type, int plen, void *ctxt);
68void input_userauth_request(int type, int plen, void *ctxt); 85void input_userauth_request(int type, int plen, void *ctxt);
69void protocol_error(int type, int plen, void *ctxt); 86void protocol_error(int type, int plen, void *ctxt);
70 87
71/* auth */
72int ssh2_auth_none(struct passwd *pw);
73int ssh2_auth_password(struct passwd *pw);
74int ssh2_auth_pubkey(struct passwd *pw, char *service);
75 88
76/* helper */ 89/* helper */
77struct passwd* auth_set_user(char *u, char *s); 90Authmethod *authmethod_lookup(const char *name);
91struct passwd *pwcopy(struct passwd *pw);
78int user_dsa_key_allowed(struct passwd *pw, Key *key); 92int user_dsa_key_allowed(struct passwd *pw, Key *key);
93char *authmethods_get(void);
79 94
80typedef struct Authctxt Authctxt; 95/* auth */
81struct Authctxt { 96int userauth_none(Authctxt *authctxt);
82 char *user; 97int userauth_passwd(Authctxt *authctxt);
83 char *service; 98int userauth_pubkey(Authctxt *authctxt);
84 struct passwd pw; 99int userauth_kbdint(Authctxt *authctxt);
85 int valid; 100
101Authmethod authmethods[] = {
102 {"none",
103 userauth_none,
104 &one},
105 {"publickey",
106 userauth_pubkey,
107 &options.dsa_authentication},
108 {"keyboard-interactive",
109 userauth_kbdint,
110 &options.kbd_interactive_authentication},
111 {"password",
112 userauth_passwd,
113 &options.password_authentication},
114 {NULL, NULL, NULL}
86}; 115};
87static Authctxt *authctxt = NULL;
88static int userauth_success = 0;
89 116
90/* 117/*
91 * loop until userauth_success == TRUE 118 * loop until authctxt->success == TRUE
92 */ 119 */
93 120
94void 121void
95do_authentication2() 122do_authentication2()
96{ 123{
97 /* turn off skey/kerberos, not supported by SSH2 */ 124 Authctxt *authctxt = xmalloc(sizeof(*authctxt));
98#ifdef SKEY 125 memset(authctxt, 'a', sizeof(*authctxt));
99 options.skey_authentication = 0; 126 authctxt->valid = 0;
100#endif 127 authctxt->attempt = 0;
128 authctxt->success = 0;
129 x_authctxt = authctxt; /*XXX*/
130
101#ifdef KRB4 131#ifdef KRB4
132 /* turn off kerberos, not supported by SSH2 */
102 options.kerberos_authentication = 0; 133 options.kerberos_authentication = 0;
103#endif 134#endif
104
105 dispatch_init(&protocol_error); 135 dispatch_init(&protocol_error);
106 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); 136 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
107 dispatch_run(DISPATCH_BLOCK, &userauth_success, NULL); 137 dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
108 do_authenticated2(); 138 do_authenticated2();
109} 139}
110 140
@@ -121,13 +151,17 @@ protocol_error(int type, int plen, void *ctxt)
121void 151void
122input_service_request(int type, int plen, void *ctxt) 152input_service_request(int type, int plen, void *ctxt)
123{ 153{
154 Authctxt *authctxt = ctxt;
124 unsigned int len; 155 unsigned int len;
125 int accept = 0; 156 int accept = 0;
126 char *service = packet_get_string(&len); 157 char *service = packet_get_string(&len);
127 packet_done(); 158 packet_done();
128 159
160 if (authctxt == NULL)
161 fatal("input_service_request: no authctxt");
162
129 if (strcmp(service, "ssh-userauth") == 0) { 163 if (strcmp(service, "ssh-userauth") == 0) {
130 if (!userauth_success) { 164 if (!authctxt->success) {
131 accept = 1; 165 accept = 1;
132 /* now we can handle user-auth requests */ 166 /* now we can handle user-auth requests */
133 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); 167 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
@@ -150,65 +184,99 @@ input_service_request(int type, int plen, void *ctxt)
150void 184void
151input_userauth_request(int type, int plen, void *ctxt) 185input_userauth_request(int type, int plen, void *ctxt)
152{ 186{
153 static void (*authlog) (const char *fmt,...) = verbose; 187 Authctxt *authctxt = ctxt;
154 static int attempt = 0; 188 Authmethod *m = NULL;
155 unsigned int len; 189 char *user, *service, *method;
156 int authenticated = 0; 190 int authenticated = 0;
157 char *user, *service, *method, *authmsg = NULL;
158 struct passwd *pw;
159#ifdef WITH_AIXAUTHENTICATE
160 extern char *aixloginmsg;
161#endif /* WITH_AIXAUTHENTICATE */
162 191
163 user = packet_get_string(&len); 192 if (authctxt == NULL)
164 service = packet_get_string(&len); 193 fatal("input_userauth_request: no authctxt");
165 method = packet_get_string(&len); 194 if (authctxt->attempt++ >= AUTH_FAIL_MAX) {
166 if (++attempt == AUTH_FAIL_MAX) {
167#ifdef WITH_AIXAUTHENTICATE 195#ifdef WITH_AIXAUTHENTICATE
168 loginfailed(user,get_canonical_hostname(),"ssh"); 196 loginfailed(user,get_canonical_hostname(),"ssh");
169#endif /* WITH_AIXAUTHENTICATE */ 197#endif /* WITH_AIXAUTHENTICATE */
170 packet_disconnect("too many failed userauth_requests"); 198 packet_disconnect("too many failed userauth_requests");
171 } 199 }
172 debug("userauth-request for user %s service %s method %s", user, service, method);
173 200
174 /* XXX we only allow the ssh-connection service */ 201 user = packet_get_string(NULL);
175 pw = auth_set_user(user, service); 202 service = packet_get_string(NULL);
176 if (pw && strcmp(service, "ssh-connection")==0) { 203 method = packet_get_string(NULL);
177 if (strcmp(method, "none") == 0) { 204 debug("userauth-request for user %s service %s method %s", user, service, method);
178 authenticated = ssh2_auth_none(pw); 205 debug("attempt #%d", authctxt->attempt);
179 } else if (strcmp(method, "password") == 0) { 206
180 authenticated = ssh2_auth_password(pw); 207 if (authctxt->attempt == 1) {
181 } else if (strcmp(method, "publickey") == 0) { 208 /* setup auth context */
182 authenticated = ssh2_auth_pubkey(pw, service); 209 struct passwd *pw = NULL;
210 setproctitle("%s", user);
211 pw = getpwnam(user);
212 if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
213 authctxt->pw = pwcopy(pw);
214 authctxt->valid = 1;
215 debug2("input_userauth_request: setting up authctxt for %s", user);
216#ifdef USE_PAM
217 start_pam(pw);
218#endif
219 } else {
220 log("input_userauth_request: illegal user %s", user);
221 }
222 authctxt->user = xstrdup(user);
223 authctxt->service = xstrdup(service);
224 } else if (authctxt->valid) {
225 if (strcmp(user, authctxt->user) != 0 ||
226 strcmp(service, authctxt->service) != 0) {
227 log("input_userauth_request: missmatch: (%s,%s)!=(%s,%s)",
228 user, service, authctxt->user, authctxt->service);
229 authctxt->valid = 0;
183 } 230 }
184 } 231 }
185 232
186#ifdef HAVE_CYGWIN 233 m = authmethod_lookup(method);
187 if (authenticated && !check_nt_auth(strcmp(method, "password") == 0, pw->pw_uid)) { 234 if (m != NULL) {
188 packet_disconnect("Authentication rejected for uid %d.", 235 debug2("input_userauth_request: try method %s", method);
189 (int) pw->pw_uid); 236 authenticated = m->userauth(authctxt);
237 } else {
238 debug2("input_userauth_request: unsupported method %s", method);
239 }
240 if (!authctxt->valid && authenticated == 1) {
241 log("input_userauth_request: INTERNAL ERROR: authenticated invalid user %s service %s", user, method);
190 authenticated = 0; 242 authenticated = 0;
191 } 243 }
192#endif
193 244
194 if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) { 245 /* Special handling for root */
246 if (authenticated == 1 &&
247 authctxt->valid && authctxt->pw->pw_uid == 0 && !options.permit_root_login) {
195 authenticated = 0; 248 authenticated = 0;
196 log("ROOT LOGIN REFUSED FROM %.200s", 249 log("ROOT LOGIN REFUSED FROM %.200s", get_canonical_hostname());
197 get_canonical_hostname());
198 } 250 }
199 251
200#ifdef USE_PAM 252#ifdef USE_PAM
201 if (authenticated && !do_pam_account(pw->pw_name, NULL)) 253 if (authenticated && !do_pam_account(authctxt->pw->pw_name, NULL))
202 authenticated = 0; 254 authenticated = 0;
203#endif /* USE_PAM */ 255#endif /* USE_PAM */
204 256
257 /* Log before sending the reply */
258 userauth_log(authctxt, authenticated, method);
259 userauth_reply(authctxt, authenticated);
260
261 xfree(service);
262 xfree(user);
263 xfree(method);
264}
265
266
267void
268userauth_log(Authctxt *authctxt, int authenticated, char *method)
269{
270 void (*authlog) (const char *fmt,...) = verbose;
271 char *user = NULL, *authmsg = NULL;
272
205 /* Raise logging level */ 273 /* Raise logging level */
206 if (authenticated == 1 || 274 if (authenticated == 1 ||
207 attempt == AUTH_FAIL_LOG || 275 !authctxt->valid ||
276 authctxt->attempt >= AUTH_FAIL_LOG ||
208 strcmp(method, "password") == 0) 277 strcmp(method, "password") == 0)
209 authlog = log; 278 authlog = log;
210 279
211 /* Log before sending the reply */
212 if (authenticated == 1) { 280 if (authenticated == 1) {
213 authmsg = "Accepted"; 281 authmsg = "Accepted";
214 } else if (authenticated == 0) { 282 } else if (authenticated == 0) {
@@ -216,18 +284,29 @@ input_userauth_request(int type, int plen, void *ctxt)
216 } else { 284 } else {
217 authmsg = "Postponed"; 285 authmsg = "Postponed";
218 } 286 }
287
288 if (authctxt->valid) {
289 user = authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user;
290 } else {
291 user = "NOUSER";
292 }
293
219 authlog("%s %s for %.200s from %.200s port %d ssh2", 294 authlog("%s %s for %.200s from %.200s port %d ssh2",
220 authmsg, 295 authmsg,
221 method, 296 method,
222 pw && pw->pw_uid == 0 ? "ROOT" : user, 297 user,
223 get_remote_ipaddr(), 298 get_remote_ipaddr(),
224 get_remote_port()); 299 get_remote_port());
300}
225 301
302void
303userauth_reply(Authctxt *authctxt, int authenticated)
304{
226 /* XXX todo: check if multiple auth methods are needed */ 305 /* XXX todo: check if multiple auth methods are needed */
227 if (authenticated == 1) { 306 if (authenticated == 1) {
228#ifdef WITH_AIXAUTHENTICATE 307#ifdef WITH_AIXAUTHENTICATE
229 /* We don't have a pty yet, so just label the line as "ssh" */ 308 /* We don't have a pty yet, so just label the line as "ssh" */
230 if (loginsuccess(user,get_canonical_hostname(),"ssh", 309 if (loginsuccess(user, get_canonical_hostname(), "ssh",
231 &aixloginmsg) < 0) 310 &aixloginmsg) < 0)
232 aixloginmsg = NULL; 311 aixloginmsg = NULL;
233#endif /* WITH_AIXAUTHENTICATE */ 312#endif /* WITH_AIXAUTHENTICATE */
@@ -237,73 +316,106 @@ input_userauth_request(int type, int plen, void *ctxt)
237 packet_send(); 316 packet_send();
238 packet_write_wait(); 317 packet_write_wait();
239 /* now we can break out */ 318 /* now we can break out */
240 userauth_success = 1; 319 authctxt->success = 1;
241 } else if (authenticated == 0) { 320 } else if (authenticated == 0) {
321 char *methods = authmethods_get();
242 packet_start(SSH2_MSG_USERAUTH_FAILURE); 322 packet_start(SSH2_MSG_USERAUTH_FAILURE);
243 packet_put_cstring("publickey,password"); /* XXX dynamic */ 323 packet_put_cstring(methods);
244 packet_put_char(0); /* XXX partial success, unused */ 324 packet_put_char(0); /* XXX partial success, unused */
245 packet_send(); 325 packet_send();
246 packet_write_wait(); 326 packet_write_wait();
327 xfree(methods);
328 } else {
329 /* do nothing, we did already send a reply */
247 } 330 }
248
249 xfree(service);
250 xfree(user);
251 xfree(method);
252} 331}
253 332
254int 333int
255ssh2_auth_none(struct passwd *pw) 334userauth_none(Authctxt *authctxt)
256{ 335{
257#ifdef HAVE_OSF_SIA 336 /* disable method "none", only allowed one time */
258 extern int saved_argc; 337 Authmethod *m = authmethod_lookup("none");
259 extern char **saved_argv; 338 if (m != NULL)
260#endif 339 m->enabled = NULL;
261
262 packet_done(); 340 packet_done();
263 341
342 if (authctxt->valid == 0)
343 return(0);
344
345#ifdef HAVE_CYGWIN
346 if (check_nt_auth(1, authctxt->pw->pw_uid) == 0)
347 return(0);
348#endif
264#ifdef USE_PAM 349#ifdef USE_PAM
265 return auth_pam_password(pw, ""); 350 return auth_pam_password(authctxt->pw, "");
266#elif defined(HAVE_OSF_SIA) 351#elif defined(HAVE_OSF_SIA)
267 return(sia_validate_user(NULL, saved_argc, saved_argv, 352 return (sia_validate_user(NULL, saved_argc, saved_argv,
268 get_canonical_hostname(), pw->pw_name, NULL, 0, NULL, 353 get_canonical_hostname(), authctxt->pw->pw_name, NULL,
269 "") == SIASUCCESS); 354 0, NULL, "") == SIASUCCESS);
270#else /* !HAVE_OSF_SIA && !USE_PAM */ 355#else /* !HAVE_OSF_SIA && !USE_PAM */
271 return auth_password(pw, ""); 356 return auth_password(authctxt->pw, "");
272#endif /* USE_PAM */ 357#endif /* USE_PAM */
273} 358}
359
274int 360int
275ssh2_auth_password(struct passwd *pw) 361userauth_passwd(Authctxt *authctxt)
276{ 362{
277 char *password; 363 char *password;
278 int authenticated = 0; 364 int authenticated = 0;
279 int change; 365 int change;
280 unsigned int len; 366 unsigned int len;
281#ifdef HAVE_OSF_SIA
282 extern int saved_argc;
283 extern char **saved_argv;
284#endif
285 change = packet_get_char(); 367 change = packet_get_char();
286 if (change) 368 if (change)
287 log("password change not supported"); 369 log("password change not supported");
288 password = packet_get_string(&len); 370 password = packet_get_string(&len);
289 packet_done(); 371 packet_done();
290 if (options.password_authentication && 372 if (authctxt->valid &&
373#ifdef HAVE_CYGWIN
374 check_nt_auth(1, authctxt->pw->pw_uid) &&
375#endif
291#ifdef USE_PAM 376#ifdef USE_PAM
292 auth_pam_password(pw, password) == 1) 377 auth_pam_password(authctxt->pw, password) == 1)
293#elif defined(HAVE_OSF_SIA) 378#elif defined(HAVE_OSF_SIA)
294 sia_validate_user(NULL, saved_argc, saved_argv, 379 sia_validate_user(NULL, saved_argc, saved_argv,
295 get_canonical_hostname(), pw->pw_name, NULL, 0, 380 get_canonical_hostname(), authctxt->pw->pw_name, NULL, 0,
296 NULL, password) == SIASUCCESS) 381 NULL, password) == SIASUCCESS)
297#else /* !USE_PAM && !HAVE_OSF_SIA */ 382#else /* !USE_PAM && !HAVE_OSF_SIA */
298 auth_password(pw, password) == 1) 383 auth_password(authctxt->pw, password) == 1)
299#endif /* USE_PAM */ 384#endif /* USE_PAM */
300 authenticated = 1; 385 authenticated = 1;
301 memset(password, 0, len); 386 memset(password, 0, len);
302 xfree(password); 387 xfree(password);
303 return authenticated; 388 return authenticated;
304} 389}
390
391int
392userauth_kbdint(Authctxt *authctxt)
393{
394 int authenticated = 0;
395 char *lang = NULL;
396 char *devs = NULL;
397
398 lang = packet_get_string(NULL);
399 devs = packet_get_string(NULL);
400 packet_done();
401
402 debug("keyboard-interactive language %s devs %s", lang, devs);
403#ifdef SKEY
404 /* XXX hardcoded, we should look at devs */
405 if (options.skey_authentication != 0)
406 authenticated = auth2_skey(authctxt);
407#endif
408 xfree(lang);
409 xfree(devs);
410#ifdef HAVE_CYGWIN
411 if (check_nt_auth(0, authctxt->pw->pw_uid) == 0)
412 return(0);
413#endif
414 return authenticated;
415}
416
305int 417int
306ssh2_auth_pubkey(struct passwd *pw, char *service) 418userauth_pubkey(Authctxt *authctxt)
307{ 419{
308 Buffer b; 420 Buffer b;
309 Key *key; 421 Key *key;
@@ -312,15 +424,15 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
312 int have_sig; 424 int have_sig;
313 int authenticated = 0; 425 int authenticated = 0;
314 426
315 if (options.dsa_authentication == 0) { 427 if (!authctxt->valid) {
316 debug("pubkey auth disabled"); 428 debug2("userauth_pubkey: disabled because of invalid user");
317 return 0; 429 return 0;
318 } 430 }
319 have_sig = packet_get_char(); 431 have_sig = packet_get_char();
320 pkalg = packet_get_string(&alen); 432 pkalg = packet_get_string(&alen);
321 if (strcmp(pkalg, KEX_DSS) != 0) { 433 if (strcmp(pkalg, KEX_DSS) != 0) {
322 xfree(pkalg);
323 log("bad pkalg %s", pkalg); /*XXX*/ 434 log("bad pkalg %s", pkalg); /*XXX*/
435 xfree(pkalg);
324 return 0; 436 return 0;
325 } 437 }
326 pkblob = packet_get_string(&blen); 438 pkblob = packet_get_string(&blen);
@@ -337,11 +449,11 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
337 } 449 }
338 /* reconstruct packet */ 450 /* reconstruct packet */
339 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 451 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
340 buffer_put_cstring(&b, pw->pw_name); 452 buffer_put_cstring(&b, authctxt->user);
341 buffer_put_cstring(&b, 453 buffer_put_cstring(&b,
342 datafellows & SSH_BUG_PUBKEYAUTH ? 454 datafellows & SSH_BUG_PUBKEYAUTH ?
343 "ssh-userauth" : 455 "ssh-userauth" :
344 service); 456 authctxt->service);
345 buffer_put_cstring(&b, "publickey"); 457 buffer_put_cstring(&b, "publickey");
346 buffer_put_char(&b, have_sig); 458 buffer_put_char(&b, have_sig);
347 buffer_put_cstring(&b, KEX_DSS); 459 buffer_put_cstring(&b, KEX_DSS);
@@ -350,15 +462,15 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
350 buffer_dump(&b); 462 buffer_dump(&b);
351#endif 463#endif
352 /* test for correct signature */ 464 /* test for correct signature */
353 if (user_dsa_key_allowed(pw, key) && 465 if (user_dsa_key_allowed(authctxt->pw, key) &&
354 dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) 466 dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
355 authenticated = 1; 467 authenticated = 1;
356 buffer_clear(&b); 468 buffer_clear(&b);
357 xfree(sig); 469 xfree(sig);
358 } else { 470 } else {
471 debug("test whether pkalg/pkblob are acceptable");
359 packet_done(); 472 packet_done();
360 debug("test key..."); 473
361 /* test whether pkalg/pkblob are acceptable */
362 /* XXX fake reply and always send PK_OK ? */ 474 /* XXX fake reply and always send PK_OK ? */
363 /* 475 /*
364 * XXX this allows testing whether a user is allowed 476 * XXX this allows testing whether a user is allowed
@@ -367,7 +479,7 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
367 * if a user is not allowed to login. is this an 479 * if a user is not allowed to login. is this an
368 * issue? -markus 480 * issue? -markus
369 */ 481 */
370 if (user_dsa_key_allowed(pw, key)) { 482 if (user_dsa_key_allowed(authctxt->pw, key)) {
371 packet_start(SSH2_MSG_USERAUTH_PK_OK); 483 packet_start(SSH2_MSG_USERAUTH_PK_OK);
372 packet_put_string(pkalg, alen); 484 packet_put_string(pkalg, alen);
373 packet_put_string(pkblob, blen); 485 packet_put_string(pkblob, blen);
@@ -376,61 +488,73 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
376 authenticated = -1; 488 authenticated = -1;
377 } 489 }
378 } 490 }
491 if (authenticated != 1)
492 auth_clear_options();
379 key_free(key); 493 key_free(key);
380 } 494 }
381 xfree(pkalg); 495 xfree(pkalg);
382 xfree(pkblob); 496 xfree(pkblob);
497#ifdef HAVE_CYGWIN
498 if (check_nt_auth(0, authctxt->pw->pw_uid) == 0)
499 return(0);
500#endif
383 return authenticated; 501 return authenticated;
384} 502}
385 503
386/* set and get current user */ 504/* get current user */
387 505
388struct passwd* 506struct passwd*
389auth_get_user(void) 507auth_get_user(void)
390{ 508{
391 return (authctxt != NULL && authctxt->valid) ? &authctxt->pw : NULL; 509 return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL;
392} 510}
393 511
394struct passwd* 512#define DELIM ","
395auth_set_user(char *u, char *s) 513
514char *
515authmethods_get(void)
396{ 516{
397 struct passwd *pw, *copy; 517 Authmethod *method = NULL;
398 518 unsigned int size = 0;
399 if (authctxt == NULL) { 519 char *list;
400 authctxt = xmalloc(sizeof(*authctxt)); 520
401 authctxt->valid = 0; 521 for (method = authmethods; method->name != NULL; method++) {
402 authctxt->user = xstrdup(u); 522 if (strcmp(method->name, "none") == 0)
403 authctxt->service = xstrdup(s); 523 continue;
404 setproctitle("%s", u); 524 if (method->enabled != NULL && *(method->enabled) != 0) {
405 pw = getpwnam(u); 525 if (size != 0)
406 if (!pw || !allowed_user(pw)) { 526 size += strlen(DELIM);
407 log("auth_set_user: illegal user %s", u); 527 size += strlen(method->name);
408 return NULL;
409 } 528 }
410#ifdef USE_PAM 529 }
411 start_pam(pw); 530 size++; /* trailing '\0' */
412#endif 531 list = xmalloc(size);
413 copy = &authctxt->pw; 532 list[0] = '\0';
414 memset(copy, 0, sizeof(*copy)); 533
415 copy->pw_name = xstrdup(pw->pw_name); 534 for (method = authmethods; method->name != NULL; method++) {
416 copy->pw_passwd = xstrdup(pw->pw_passwd); 535 if (strcmp(method->name, "none") == 0)
417 copy->pw_uid = pw->pw_uid; 536 continue;
418 copy->pw_gid = pw->pw_gid; 537 if (method->enabled != NULL && *(method->enabled) != 0) {
419#ifdef HAVE_PW_CLASS_IN_PASSWD 538 if (list[0] != '\0')
420 copy->pw_class = xstrdup(pw->pw_class); 539 strlcat(list, DELIM, size);
421#endif 540 strlcat(list, method->name, size);
422 copy->pw_dir = xstrdup(pw->pw_dir);
423 copy->pw_shell = xstrdup(pw->pw_shell);
424 authctxt->valid = 1;
425 } else {
426 if (strcmp(u, authctxt->user) != 0 ||
427 strcmp(s, authctxt->service) != 0) {
428 log("auth_set_user: missmatch: (%s,%s)!=(%s,%s)",
429 u, s, authctxt->user, authctxt->service);
430 return NULL;
431 } 541 }
432 } 542 }
433 return auth_get_user(); 543 return list;
544}
545
546Authmethod *
547authmethod_lookup(const char *name)
548{
549 Authmethod *method = NULL;
550 if (name != NULL)
551 for (method = authmethods; method->name != NULL; method++)
552 if (method->enabled != NULL &&
553 *(method->enabled) != 0 &&
554 strcmp(name, method->name) == 0)
555 return method;
556 debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
557 return NULL;
434} 558}
435 559
436/* return 1 if user allows given key */ 560/* return 1 if user allows given key */
@@ -445,6 +569,9 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
445 struct stat st; 569 struct stat st;
446 Key *found; 570 Key *found;
447 571
572 if (pw == NULL)
573 return 0;
574
448 /* Temporarily use the user's uid. */ 575 /* Temporarily use the user's uid. */
449 temporarily_use_uid(pw->pw_uid); 576 temporarily_use_uid(pw->pw_uid);
450 577
@@ -550,3 +677,20 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
550 key_free(found); 677 key_free(found);
551 return found_key; 678 return found_key;
552} 679}
680
681struct passwd *
682pwcopy(struct passwd *pw)
683{
684 struct passwd *copy = xmalloc(sizeof(*copy));
685 memset(copy, 0, sizeof(*copy));
686 copy->pw_name = xstrdup(pw->pw_name);
687 copy->pw_passwd = xstrdup(pw->pw_passwd);
688 copy->pw_uid = pw->pw_uid;
689 copy->pw_gid = pw->pw_gid;
690#ifdef HAVE_PW_CLASS_IN_PASSWD
691 copy->pw_class = xstrdup(pw->pw_class);
692#endif
693 copy->pw_dir = xstrdup(pw->pw_dir);
694 copy->pw_shell = xstrdup(pw->pw_shell);
695 return copy;
696}
diff --git a/authfd.c b/authfd.c
index 433623ef7..d06cc536c 100644
--- a/authfd.c
+++ b/authfd.c
@@ -35,7 +35,7 @@
35 */ 35 */
36 36
37#include "includes.h" 37#include "includes.h"
38RCSID("$OpenBSD: authfd.c,v 1.28 2000/09/21 11:07:50 markus Exp $"); 38RCSID("$OpenBSD: authfd.c,v 1.29 2000/10/09 21:51:00 markus Exp $");
39 39
40#include "ssh.h" 40#include "ssh.h"
41#include "rsa.h" 41#include "rsa.h"
@@ -56,6 +56,10 @@ RCSID("$OpenBSD: authfd.c,v 1.28 2000/09/21 11:07:50 markus Exp $");
56/* helper */ 56/* helper */
57int decode_reply(int type); 57int decode_reply(int type);
58 58
59/* macro to check for "agent failure" message */
60#define agent_failed(x) \
61 ((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE))
62
59/* Returns the number of the authentication fd, or -1 if there is none. */ 63/* Returns the number of the authentication fd, or -1 if there is none. */
60 64
61int 65int
@@ -242,7 +246,7 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
242 246
243 /* Get message type, and verify that we got a proper answer. */ 247 /* Get message type, and verify that we got a proper answer. */
244 type = buffer_get_char(&auth->identities); 248 type = buffer_get_char(&auth->identities);
245 if (type == SSH_AGENT_FAILURE) { 249 if (agent_failed(type)) {
246 return NULL; 250 return NULL;
247 } else if (type != code2) { 251 } else if (type != code2) {
248 fatal("Bad authentication reply message type: %d", type); 252 fatal("Bad authentication reply message type: %d", type);
@@ -341,7 +345,7 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
341 } 345 }
342 type = buffer_get_char(&buffer); 346 type = buffer_get_char(&buffer);
343 347
344 if (type == SSH_AGENT_FAILURE) { 348 if (agent_failed(type)) {
345 log("Agent admitted failure to authenticate using the key."); 349 log("Agent admitted failure to authenticate using the key.");
346 } else if (type != SSH_AGENT_RSA_RESPONSE) { 350 } else if (type != SSH_AGENT_RSA_RESPONSE) {
347 fatal("Bad authentication response: %d", type); 351 fatal("Bad authentication response: %d", type);
@@ -390,7 +394,7 @@ ssh_agent_sign(AuthenticationConnection *auth,
390 return -1; 394 return -1;
391 } 395 }
392 type = buffer_get_char(&msg); 396 type = buffer_get_char(&msg);
393 if (type == SSH_AGENT_FAILURE) { 397 if (agent_failed(type)) {
394 log("Agent admitted failure to sign using the key."); 398 log("Agent admitted failure to sign using the key.");
395 } else if (type != SSH2_AGENT_SIGN_RESPONSE) { 399 } else if (type != SSH2_AGENT_SIGN_RESPONSE) {
396 fatal("Bad authentication response: %d", type); 400 fatal("Bad authentication response: %d", type);
@@ -537,6 +541,7 @@ decode_reply(int type)
537{ 541{
538 switch (type) { 542 switch (type) {
539 case SSH_AGENT_FAILURE: 543 case SSH_AGENT_FAILURE:
544 case SSH_COM_AGENT2_FAILURE:
540 log("SSH_AGENT_FAILURE"); 545 log("SSH_AGENT_FAILURE");
541 return 0; 546 return 0;
542 case SSH_AGENT_SUCCESS: 547 case SSH_AGENT_SUCCESS:
diff --git a/authfd.h b/authfd.h
index 808575cd8..2d2465206 100644
--- a/authfd.h
+++ b/authfd.h
@@ -11,7 +11,7 @@
11 * called by a name other than "ssh" or "Secure Shell". 11 * called by a name other than "ssh" or "Secure Shell".
12 */ 12 */
13 13
14/* RCSID("$OpenBSD: authfd.h,v 1.12 2000/09/21 11:07:51 markus Exp $"); */ 14/* RCSID("$OpenBSD: authfd.h,v 1.13 2000/10/09 21:51:00 markus Exp $"); */
15 15
16#ifndef AUTHFD_H 16#ifndef AUTHFD_H
17#define AUTHFD_H 17#define AUTHFD_H
@@ -29,6 +29,7 @@
29#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8 29#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
30#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 30#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
31 31
32/* private OpenSSH extensions for SSH2 */
32#define SSH2_AGENTC_REQUEST_IDENTITIES 11 33#define SSH2_AGENTC_REQUEST_IDENTITIES 11
33#define SSH2_AGENT_IDENTITIES_ANSWER 12 34#define SSH2_AGENT_IDENTITIES_ANSWER 12
34#define SSH2_AGENTC_SIGN_REQUEST 13 35#define SSH2_AGENTC_SIGN_REQUEST 13
@@ -37,6 +38,9 @@
37#define SSH2_AGENTC_REMOVE_IDENTITY 18 38#define SSH2_AGENTC_REMOVE_IDENTITY 18
38#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 39#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
39 40
41/* additional error code for ssh.com's ssh-agent2 */
42#define SSH_COM_AGENT2_FAILURE 102
43
40#define SSH_AGENT_OLD_SIGNATURE 0x01 44#define SSH_AGENT_OLD_SIGNATURE 0x01
41 45
42 46
diff --git a/authfile.c b/authfile.c
index afedd7bbb..d1a97d773 100644
--- a/authfile.c
+++ b/authfile.c
@@ -36,7 +36,7 @@
36 */ 36 */
37 37
38#include "includes.h" 38#include "includes.h"
39RCSID("$OpenBSD: authfile.c,v 1.19 2000/09/07 20:27:49 deraadt Exp $"); 39RCSID("$OpenBSD: authfile.c,v 1.20 2000/10/11 20:27:23 markus Exp $");
40 40
41#include <openssl/bn.h> 41#include <openssl/bn.h>
42#include <openssl/dsa.h> 42#include <openssl/dsa.h>
@@ -47,7 +47,6 @@ RCSID("$OpenBSD: authfile.c,v 1.19 2000/09/07 20:27:49 deraadt Exp $");
47#include "xmalloc.h" 47#include "xmalloc.h"
48#include "buffer.h" 48#include "buffer.h"
49#include "bufaux.h" 49#include "bufaux.h"
50#include "cipher.h"
51#include "ssh.h" 50#include "ssh.h"
52#include "key.h" 51#include "key.h"
53 52
@@ -68,8 +67,8 @@ save_private_key_rsa(const char *filename, const char *passphrase,
68 Buffer buffer, encrypted; 67 Buffer buffer, encrypted;
69 char buf[100], *cp; 68 char buf[100], *cp;
70 int fd, i; 69 int fd, i;
71 CipherContext cipher; 70 CipherContext ciphercontext;
72 int cipher_type; 71 Cipher *cipher;
73 u_int32_t rand; 72 u_int32_t rand;
74 73
75 /* 74 /*
@@ -77,9 +76,11 @@ save_private_key_rsa(const char *filename, const char *passphrase,
77 * to another cipher; otherwise use SSH_AUTHFILE_CIPHER. 76 * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
78 */ 77 */
79 if (strcmp(passphrase, "") == 0) 78 if (strcmp(passphrase, "") == 0)
80 cipher_type = SSH_CIPHER_NONE; 79 cipher = cipher_by_number(SSH_CIPHER_NONE);
81 else 80 else
82 cipher_type = SSH_AUTHFILE_CIPHER; 81 cipher = cipher_by_number(SSH_AUTHFILE_CIPHER);
82 if (cipher == NULL)
83 fatal("save_private_key_rsa: bad cipher");
83 84
84 /* This buffer is used to built the secret part of the private key. */ 85 /* This buffer is used to built the secret part of the private key. */
85 buffer_init(&buffer); 86 buffer_init(&buffer);
@@ -116,7 +117,7 @@ save_private_key_rsa(const char *filename, const char *passphrase,
116 buffer_put_char(&encrypted, 0); 117 buffer_put_char(&encrypted, 0);
117 118
118 /* Store cipher type. */ 119 /* Store cipher type. */
119 buffer_put_char(&encrypted, cipher_type); 120 buffer_put_char(&encrypted, cipher->number);
120 buffer_put_int(&encrypted, 0); /* For future extension */ 121 buffer_put_int(&encrypted, 0); /* For future extension */
121 122
122 /* Store public key. This will be in plain text. */ 123 /* Store public key. This will be in plain text. */
@@ -128,11 +129,10 @@ save_private_key_rsa(const char *filename, const char *passphrase,
128 /* Allocate space for the private part of the key in the buffer. */ 129 /* Allocate space for the private part of the key in the buffer. */
129 buffer_append_space(&encrypted, &cp, buffer_len(&buffer)); 130 buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
130 131
131 cipher_set_key_string(&cipher, cipher_type, passphrase); 132 cipher_set_key_string(&ciphercontext, cipher, passphrase);
132 cipher_encrypt(&cipher, (unsigned char *) cp, 133 cipher_encrypt(&ciphercontext, (unsigned char *) cp,
133 (unsigned char *) buffer_ptr(&buffer), 134 (unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer));
134 buffer_len(&buffer)); 135 memset(&ciphercontext, 0, sizeof(ciphercontext));
135 memset(&cipher, 0, sizeof(cipher));
136 136
137 /* Destroy temporary data. */ 137 /* Destroy temporary data. */
138 memset(buf, 0, sizeof(buf)); 138 memset(buf, 0, sizeof(buf));
@@ -313,7 +313,8 @@ load_private_key_rsa(int fd, const char *filename,
313 off_t len; 313 off_t len;
314 Buffer buffer, decrypted; 314 Buffer buffer, decrypted;
315 char *cp; 315 char *cp;
316 CipherContext cipher; 316 CipherContext ciphercontext;
317 Cipher *cipher;
317 BN_CTX *ctx; 318 BN_CTX *ctx;
318 BIGNUM *aux; 319 BIGNUM *aux;
319 320
@@ -364,10 +365,10 @@ load_private_key_rsa(int fd, const char *filename,
364 xfree(buffer_get_string(&buffer, NULL)); 365 xfree(buffer_get_string(&buffer, NULL));
365 366
366 /* Check that it is a supported cipher. */ 367 /* Check that it is a supported cipher. */
367 if (((cipher_mask1() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) & 368 cipher = cipher_by_number(cipher_type);
368 (1 << cipher_type)) == 0) { 369 if (cipher == NULL) {
369 debug("Unsupported cipher %.100s used in key file %.200s.", 370 debug("Unsupported cipher %d used in key file %.200s.",
370 cipher_name(cipher_type), filename); 371 cipher_type, filename);
371 buffer_free(&buffer); 372 buffer_free(&buffer);
372 goto fail; 373 goto fail;
373 } 374 }
@@ -376,11 +377,10 @@ load_private_key_rsa(int fd, const char *filename,
376 buffer_append_space(&decrypted, &cp, buffer_len(&buffer)); 377 buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
377 378
378 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ 379 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
379 cipher_set_key_string(&cipher, cipher_type, passphrase); 380 cipher_set_key_string(&ciphercontext, cipher, passphrase);
380 cipher_decrypt(&cipher, (unsigned char *) cp, 381 cipher_decrypt(&ciphercontext, (unsigned char *) cp,
381 (unsigned char *) buffer_ptr(&buffer), 382 (unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer));
382 buffer_len(&buffer)); 383 memset(&ciphercontext, 0, sizeof(ciphercontext));
383
384 buffer_free(&buffer); 384 buffer_free(&buffer);
385 385
386 check1 = buffer_get_char(&decrypted); 386 check1 = buffer_get_char(&decrypted);
diff --git a/bsd-vis.c b/bsd-vis.c
new file mode 100644
index 000000000..94283a077
--- /dev/null
+++ b/bsd-vis.c
@@ -0,0 +1,137 @@
1/*-
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: vis.c,v 1.5 2000/07/19 15:25:13 deraadt Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#ifndef HAVE_VIS
39
40#include "includes.h"
41
42#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
43
44/*
45 * vis - visually encode characters
46 */
47char *vis(char *dst, int c, int flag, int nextc)
48{
49 if (((u_int)c <= UCHAR_MAX && isascii((u_char)c) &&
50 isgraph((u_char)c)) ||
51 ((flag & VIS_SP) == 0 && c == ' ') ||
52 ((flag & VIS_TAB) == 0 && c == '\t') ||
53 ((flag & VIS_NL) == 0 && c == '\n') ||
54 ((flag & VIS_SAFE) && (c == '\b' || c == '\007' || c == '\r'))) {
55 *dst++ = c;
56 if (c == '\\' && (flag & VIS_NOSLASH) == 0)
57 *dst++ = '\\';
58 *dst = '\0';
59 return (dst);
60 }
61
62 if (flag & VIS_CSTYLE) {
63 switch(c) {
64 case '\n':
65 *dst++ = '\\';
66 *dst++ = 'n';
67 goto done;
68 case '\r':
69 *dst++ = '\\';
70 *dst++ = 'r';
71 goto done;
72 case '\b':
73 *dst++ = '\\';
74 *dst++ = 'b';
75 goto done;
76#ifdef __STDC__
77 case '\a':
78#else
79 case '\007':
80#endif
81 *dst++ = '\\';
82 *dst++ = 'a';
83 goto done;
84 case '\v':
85 *dst++ = '\\';
86 *dst++ = 'v';
87 goto done;
88 case '\t':
89 *dst++ = '\\';
90 *dst++ = 't';
91 goto done;
92 case '\f':
93 *dst++ = '\\';
94 *dst++ = 'f';
95 goto done;
96 case ' ':
97 *dst++ = '\\';
98 *dst++ = 's';
99 goto done;
100 case '\0':
101 *dst++ = '\\';
102 *dst++ = '0';
103 if (isoctal(nextc)) {
104 *dst++ = '0';
105 *dst++ = '0';
106 }
107 goto done;
108 }
109 }
110 if (((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
111 *dst++ = '\\';
112 *dst++ = ((u_char)c >> 6 & 07) + '0';
113 *dst++ = ((u_char)c >> 3 & 07) + '0';
114 *dst++ = ((u_char)c & 07) + '0';
115 goto done;
116 }
117 if ((flag & VIS_NOSLASH) == 0)
118 *dst++ = '\\';
119 if (c & 0200) {
120 c &= 0177;
121 *dst++ = 'M';
122 }
123 if (iscntrl(c)) {
124 *dst++ = '^';
125 if (c == 0177)
126 *dst++ = '?';
127 else
128 *dst++ = c + '@';
129 } else {
130 *dst++ = '-';
131 *dst++ = c;
132 }
133done:
134 *dst = '\0';
135 return (dst);
136}
137#endif /* HAVE_VIS */
diff --git a/bsd-vis.h b/bsd-vis.h
new file mode 100644
index 000000000..52e867b94
--- /dev/null
+++ b/bsd-vis.h
@@ -0,0 +1,32 @@
1#ifndef _BSD_VIS_H
2#define _BSD_VIS_H
3
4#include "config.h"
5
6#ifndef HAVE_VIS
7
8/*
9 * to select alternate encoding format
10 */
11#define VIS_OCTAL 0x01 /* use octal \ddd format */
12#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropriate */
13
14/*
15 * to alter set of characters encoded (default is to encode all
16 * non-graphic except space, tab, and newline).
17 */
18#define VIS_SP 0x04 /* also encode space */
19#define VIS_TAB 0x08 /* also encode tab */
20#define VIS_NL 0x10 /* also encode newline */
21#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
22#define VIS_SAFE 0x20 /* only encode "unsafe" characters */
23
24/*
25 * other
26 */
27#define VIS_NOSLASH 0x40 /* inhibit printing '\' */
28
29char *vis (char *, int, int, int);
30#endif /* HAVE_VIS */
31
32#endif /* _BSD_VIS_H */
diff --git a/cipher.c b/cipher.c
index c7985a79c..226e4256a 100644
--- a/cipher.c
+++ b/cipher.c
@@ -35,14 +35,91 @@
35 */ 35 */
36 36
37#include "includes.h" 37#include "includes.h"
38RCSID("$OpenBSD: cipher.c,v 1.31 2000/09/12 00:38:32 deraadt Exp $"); 38RCSID("$OpenBSD: cipher.c,v 1.35 2000/10/13 18:59:13 markus Exp $");
39 39
40#include "ssh.h" 40#include "ssh.h"
41#include "cipher.h"
42#include "xmalloc.h" 41#include "xmalloc.h"
43 42
44#include <openssl/md5.h> 43#include <openssl/md5.h>
45 44
45
46/* no encryption */
47void
48none_setkey(CipherContext *cc, const u_char *key, u_int keylen)
49{
50}
51void
52none_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
53{
54}
55void
56none_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
57{
58 memcpy(dest, src, len);
59}
60
61/* DES */
62void
63des_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)
64{
65 static int dowarn = 1;
66 if (dowarn) {
67 error("Warning: use of DES is strongly discouraged "
68 "due to cryptographic weaknesses");
69 dowarn = 0;
70 }
71 des_set_key((void *)key, cc->u.des.key);
72}
73void
74des_ssh1_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
75{
76 memset(cc->u.des.iv, 0, sizeof(cc->u.des.iv));
77}
78void
79des_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
80{
81 des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,
82 DES_ENCRYPT);
83}
84void
85des_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
86{
87 des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,
88 DES_DECRYPT);
89}
90
91/* 3DES */
92void
93des3_setkey(CipherContext *cc, const u_char *key, u_int keylen)
94{
95 des_set_key((void *) key, cc->u.des3.key1);
96 des_set_key((void *) (key+8), cc->u.des3.key2);
97 des_set_key((void *) (key+16), cc->u.des3.key3);
98}
99void
100des3_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
101{
102 memset(cc->u.des3.iv2, 0, sizeof(cc->u.des3.iv2));
103 memset(cc->u.des3.iv3, 0, sizeof(cc->u.des3.iv3));
104 if (iv == NULL)
105 return;
106 memcpy(cc->u.des3.iv3, (char *)iv, 8);
107}
108void
109des3_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
110{
111 des_ede3_cbc_encrypt(src, dest, len,
112 cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3,
113 &cc->u.des3.iv3, DES_ENCRYPT);
114}
115void
116des3_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
117{
118 des_ede3_cbc_encrypt(src, dest, len,
119 cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3,
120 &cc->u.des3.iv3, DES_DECRYPT);
121}
122
46/* 123/*
47 * This is used by SSH1: 124 * This is used by SSH1:
48 * 125 *
@@ -58,48 +135,84 @@ RCSID("$OpenBSD: cipher.c,v 1.31 2000/09/12 00:38:32 deraadt Exp $");
58 * choosing the X block. 135 * choosing the X block.
59 */ 136 */
60void 137void
61SSH_3CBC_ENCRYPT(des_key_schedule ks1, 138des3_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)
62 des_key_schedule ks2, des_cblock * iv2, 139{
63 des_key_schedule ks3, des_cblock * iv3, 140 des_set_key((void *) key, cc->u.des3.key1);
64 unsigned char *dest, unsigned char *src, 141 des_set_key((void *) (key+8), cc->u.des3.key2);
65 unsigned int len) 142 if (keylen <= 16)
143 des_set_key((void *) key, cc->u.des3.key3);
144 else
145 des_set_key((void *) (key+16), cc->u.des3.key3);
146}
147void
148des3_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
149 u_int len)
66{ 150{
67 des_cblock iv1; 151 des_cblock iv1;
152 des_cblock *iv2 = &cc->u.des3.iv2;
153 des_cblock *iv3 = &cc->u.des3.iv3;
68 154
69 memcpy(&iv1, iv2, 8); 155 memcpy(&iv1, iv2, 8);
70 156
71 des_cbc_encrypt(src, dest, len, ks1, &iv1, DES_ENCRYPT); 157 des_cbc_encrypt(src, dest, len, cc->u.des3.key1, &iv1, DES_ENCRYPT);
72 memcpy(&iv1, dest + len - 8, 8); 158 memcpy(&iv1, dest + len - 8, 8);
73 159
74 des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_DECRYPT); 160 des_cbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_DECRYPT);
75 memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */ 161 memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */
76 162
77 des_cbc_encrypt(dest, dest, len, ks3, iv3, DES_ENCRYPT); 163 des_cbc_encrypt(dest, dest, len, cc->u.des3.key3, iv3, DES_ENCRYPT);
78 memcpy(iv3, dest + len - 8, 8); 164 memcpy(iv3, dest + len - 8, 8);
79} 165}
80
81void 166void
82SSH_3CBC_DECRYPT(des_key_schedule ks1, 167des3_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
83 des_key_schedule ks2, des_cblock * iv2, 168 u_int len)
84 des_key_schedule ks3, des_cblock * iv3,
85 unsigned char *dest, unsigned char *src,
86 unsigned int len)
87{ 169{
88 des_cblock iv1; 170 des_cblock iv1;
171 des_cblock *iv2 = &cc->u.des3.iv2;
172 des_cblock *iv3 = &cc->u.des3.iv3;
89 173
90 memcpy(&iv1, iv2, 8); 174 memcpy(&iv1, iv2, 8);
91 175
92 des_cbc_encrypt(src, dest, len, ks3, iv3, DES_DECRYPT); 176 des_cbc_encrypt(src, dest, len, cc->u.des3.key3, iv3, DES_DECRYPT);
93 memcpy(iv3, src + len - 8, 8); 177 memcpy(iv3, src + len - 8, 8);
94 178
95 des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_ENCRYPT); 179 des_cbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_ENCRYPT);
96 memcpy(iv2, dest + len - 8, 8); 180 memcpy(iv2, dest + len - 8, 8);
97 181
98 des_cbc_encrypt(dest, dest, len, ks1, &iv1, DES_DECRYPT); 182 des_cbc_encrypt(dest, dest, len, cc->u.des3.key1, &iv1, DES_DECRYPT);
99 /* memcpy(&iv1, iv2, 8); */ 183 /* memcpy(&iv1, iv2, 8); */
100 /* Note how iv1 == iv2 on entry and exit. */ 184 /* Note how iv1 == iv2 on entry and exit. */
101} 185}
102 186
187/* Blowfish */
188void
189blowfish_setkey(CipherContext *cc, const u_char *key, u_int keylen)
190{
191 BF_set_key(&cc->u.bf.key, keylen, (unsigned char *)key);
192}
193void
194blowfish_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
195{
196 if (iv == NULL)
197 memset(cc->u.bf.iv, 0, 8);
198 else
199 memcpy(cc->u.bf.iv, (char *)iv, 8);
200}
201void
202blowfish_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
203 u_int len)
204{
205 BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv,
206 BF_ENCRYPT);
207}
208void
209blowfish_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
210 u_int len)
211{
212 BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv,
213 BF_DECRYPT);
214}
215
103/* 216/*
104 * SSH1 uses a variation on Blowfish, all bytes must be swapped before 217 * SSH1 uses a variation on Blowfish, all bytes must be swapped before
105 * and after encryption/decryption. Thus the swap_bytes stuff (yuk). 218 * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
@@ -130,88 +243,255 @@ swap_bytes(const unsigned char *src, unsigned char *dst_, int n)
130 } 243 }
131} 244}
132 245
133/* 246void
134 * Names of all encryption algorithms. 247blowfish_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
135 * These must match the numbers defined in cipher.h. 248 u_int len)
136 */ 249{
137static char *cipher_names[] = 250 swap_bytes(src, dest, len);
138{ 251 BF_cbc_encrypt((void *)dest, dest, len, &cc->u.bf.key, cc->u.bf.iv,
139 "none", 252 BF_ENCRYPT);
140 "idea", 253 swap_bytes(dest, dest, len);
141 "des", 254}
142 "3des", 255void
143 "tss", 256blowfish_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
144 "rc4", /* Alleged RC4 */ 257 u_int len)
145 "blowfish", 258{
146 "reserved", 259 swap_bytes(src, dest, len);
147 "blowfish-cbc", 260 BF_cbc_encrypt((void *)dest, dest, len, &cc->u.bf.key, cc->u.bf.iv,
148 "3des-cbc", 261 BF_DECRYPT);
149 "arcfour", 262 swap_bytes(dest, dest, len);
150 "cast128-cbc" 263}
151};
152 264
153/* 265/* alleged rc4 */
154 * Returns a bit mask indicating which ciphers are supported by this 266void
155 * implementation. The bit mask has the corresponding bit set of each 267arcfour_setkey(CipherContext *cc, const u_char *key, u_int keylen)
156 * supported cipher. 268{
157 */ 269 RC4_set_key(&cc->u.rc4, keylen, (u_char *)key);
270}
271void
272arcfour_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
273{
274 RC4(&cc->u.rc4, len, (u_char *)src, dest);
275}
158 276
159unsigned int 277/* CAST */
160cipher_mask1() 278void
279cast_setkey(CipherContext *cc, const u_char *key, u_int keylen)
161{ 280{
162 unsigned int mask = 0; 281 CAST_set_key(&cc->u.cast.key, keylen, (unsigned char *) key);
163 mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ 282}
164 mask |= 1 << SSH_CIPHER_BLOWFISH; 283void
165 return mask; 284cast_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
285{
286 if (iv == NULL)
287 fatal("no IV for %s.", cc->cipher->name);
288 memcpy(cc->u.cast.iv, (char *)iv, 8);
289}
290void
291cast_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
292{
293 CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,
294 CAST_ENCRYPT);
295}
296void
297cast_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
298{
299 CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,
300 CAST_DECRYPT);
301}
302
303/* RIJNDAEL */
304
305#define RIJNDAEL_BLOCKSIZE 16
306void
307rijndael_setkey(CipherContext *cc, const u_char *key, u_int keylen)
308{
309 rijndael_set_key(&cc->u.rijndael.enc, (u4byte *)key, 8*keylen, 1);
310 rijndael_set_key(&cc->u.rijndael.dec, (u4byte *)key, 8*keylen, 0);
311}
312void
313rijndael_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
314{
315 if (iv == NULL)
316 fatal("no IV for %s.", cc->cipher->name);
317 memcpy((u_char *)cc->u.rijndael.iv, iv, RIJNDAEL_BLOCKSIZE);
166} 318}
319void
320rijndael_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
321 u_int len)
322{
323 rijndael_ctx *ctx = &cc->u.rijndael.enc;
324 u4byte *iv = cc->u.rijndael.iv;
325 u4byte in[4];
326 u4byte *cprev, *cnow, *plain;
327 int i, blocks = len / RIJNDAEL_BLOCKSIZE;
328 if (len == 0)
329 return;
330 if (len % RIJNDAEL_BLOCKSIZE)
331 fatal("rijndael_cbc_encrypt: bad len %d", len);
332 cnow = (u4byte*) dest;
333 plain = (u4byte*) src;
334 cprev = iv;
335 for(i = 0; i < blocks; i++, plain+=4, cnow+=4) {
336 in[0] = plain[0] ^ cprev[0];
337 in[1] = plain[1] ^ cprev[1];
338 in[2] = plain[2] ^ cprev[2];
339 in[3] = plain[3] ^ cprev[3];
340 rijndael_encrypt(ctx, in, cnow);
341 cprev = cnow;
342 }
343 memcpy(iv, cprev, RIJNDAEL_BLOCKSIZE);
344}
345
346void
347rijndael_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
348 u_int len)
349{
350 rijndael_ctx *ctx = &cc->u.rijndael.dec;
351 u4byte *iv = cc->u.rijndael.iv;
352 u4byte ivsaved[4];
353 u4byte *cnow = (u4byte*) (src+len-RIJNDAEL_BLOCKSIZE);
354 u4byte *plain = (u4byte*) (dest+len-RIJNDAEL_BLOCKSIZE);
355 u4byte *ivp;
356 int i, blocks = len / RIJNDAEL_BLOCKSIZE;
357 if (len == 0)
358 return;
359 if (len % RIJNDAEL_BLOCKSIZE)
360 fatal("rijndael_cbc_decrypt: bad len %d", len);
361 memcpy(ivsaved, cnow, RIJNDAEL_BLOCKSIZE);
362 for(i = blocks; i > 0; i--, cnow-=4, plain-=4) {
363 rijndael_decrypt(ctx, cnow, plain);
364 ivp = (i == 1) ? iv : cnow-4;
365 plain[0] ^= ivp[0];
366 plain[1] ^= ivp[1];
367 plain[2] ^= ivp[2];
368 plain[3] ^= ivp[3];
369 }
370 memcpy(iv, ivsaved, RIJNDAEL_BLOCKSIZE);
371}
372
373Cipher ciphers[] = {
374 { "none",
375 SSH_CIPHER_NONE, 8, 0,
376 none_setkey, none_setiv,
377 none_crypt, none_crypt },
378 { "des",
379 SSH_CIPHER_DES, 8, 8,
380 des_ssh1_setkey, des_ssh1_setiv,
381 des_ssh1_encrypt, des_ssh1_decrypt },
382 { "3des",
383 SSH_CIPHER_3DES, 8, 16,
384 des3_ssh1_setkey, des3_setiv,
385 des3_ssh1_encrypt, des3_ssh1_decrypt },
386 { "blowfish",
387 SSH_CIPHER_BLOWFISH, 8, 16,
388 blowfish_setkey, blowfish_setiv,
389 blowfish_ssh1_encrypt, blowfish_ssh1_decrypt },
390
391 { "3des-cbc",
392 SSH_CIPHER_SSH2, 8, 24,
393 des3_setkey, des3_setiv,
394 des3_cbc_encrypt, des3_cbc_decrypt },
395 { "blowfish-cbc",
396 SSH_CIPHER_SSH2, 8, 16,
397 blowfish_setkey, blowfish_setiv,
398 blowfish_cbc_encrypt, blowfish_cbc_decrypt },
399 { "cast128-cbc",
400 SSH_CIPHER_SSH2, 8, 16,
401 cast_setkey, cast_setiv,
402 cast_cbc_encrypt, cast_cbc_decrypt },
403 { "arcfour",
404 SSH_CIPHER_SSH2, 8, 16,
405 arcfour_setkey, none_setiv,
406 arcfour_crypt, arcfour_crypt },
407 { "aes128-cbc",
408 SSH_CIPHER_SSH2, 16, 16,
409 rijndael_setkey, rijndael_setiv,
410 rijndael_cbc_encrypt, rijndael_cbc_decrypt },
411 { "aes192-cbc",
412 SSH_CIPHER_SSH2, 16, 24,
413 rijndael_setkey, rijndael_setiv,
414 rijndael_cbc_encrypt, rijndael_cbc_decrypt },
415 { "aes256-cbc",
416 SSH_CIPHER_SSH2, 16, 32,
417 rijndael_setkey, rijndael_setiv,
418 rijndael_cbc_encrypt, rijndael_cbc_decrypt },
419 { "rijndael128-cbc",
420 SSH_CIPHER_SSH2, 16, 16,
421 rijndael_setkey, rijndael_setiv,
422 rijndael_cbc_encrypt, rijndael_cbc_decrypt },
423 { "rijndael192-cbc",
424 SSH_CIPHER_SSH2, 16, 24,
425 rijndael_setkey, rijndael_setiv,
426 rijndael_cbc_encrypt, rijndael_cbc_decrypt },
427 { "rijndael256-cbc",
428 SSH_CIPHER_SSH2, 16, 32,
429 rijndael_setkey, rijndael_setiv,
430 rijndael_cbc_encrypt, rijndael_cbc_decrypt },
431 { "rijndael-cbc@lysator.liu.se",
432 SSH_CIPHER_SSH2, 16, 32,
433 rijndael_setkey, rijndael_setiv,
434 rijndael_cbc_encrypt, rijndael_cbc_decrypt },
435 { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL, NULL, NULL, NULL }
436};
437
438/*--*/
439
167unsigned int 440unsigned int
168cipher_mask2() 441cipher_mask_ssh1(int client)
169{ 442{
170 unsigned int mask = 0; 443 unsigned int mask = 0;
171 mask |= 1 << SSH_CIPHER_BLOWFISH_CBC; 444 mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
172 mask |= 1 << SSH_CIPHER_3DES_CBC; 445 mask |= 1 << SSH_CIPHER_BLOWFISH;
173 mask |= 1 << SSH_CIPHER_ARCFOUR; 446 if (client) {
174 mask |= 1 << SSH_CIPHER_CAST128_CBC; 447 mask |= 1 << SSH_CIPHER_DES;
448 }
175 return mask; 449 return mask;
176} 450}
177unsigned int 451
178cipher_mask() 452Cipher *
453cipher_by_name(const char *name)
179{ 454{
180 return cipher_mask1() | cipher_mask2(); 455 Cipher *c;
456 for (c = ciphers; c->name != NULL; c++)
457 if (strcasecmp(c->name, name) == 0)
458 return c;
459 return NULL;
181} 460}
182 461
183/* Returns the name of the cipher. */ 462Cipher *
184 463cipher_by_number(int id)
185const char *
186cipher_name(int cipher)
187{ 464{
188 if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) || 465 Cipher *c;
189 cipher_names[cipher] == NULL) 466 for (c = ciphers; c->name != NULL; c++)
190 fatal("cipher_name: bad cipher name: %d", cipher); 467 if (c->number == id)
191 return cipher_names[cipher]; 468 return c;
469 return NULL;
192} 470}
193 471
194/* Returns 1 if the name of the ciphers are valid. */
195
196#define CIPHER_SEP "," 472#define CIPHER_SEP ","
197int 473int
198ciphers_valid(const char *names) 474ciphers_valid(const char *names)
199{ 475{
476 Cipher *c;
200 char *ciphers, *cp; 477 char *ciphers, *cp;
201 char *p; 478 char *p;
202 int i;
203 479
204 if (names == NULL || strcmp(names, "") == 0) 480 if (names == NULL || strcmp(names, "") == 0)
205 return 0; 481 return 0;
206 ciphers = cp = xstrdup(names); 482 ciphers = cp = xstrdup(names);
207 for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; 483 for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
208 (p = strsep(&cp, CIPHER_SEP))) { 484 (p = strsep(&cp, CIPHER_SEP))) {
209 i = cipher_number(p); 485 c = cipher_by_name(p);
210 if (i == -1 || !(cipher_mask2() & (1 << i))) { 486 if (c == NULL || c->number != SSH_CIPHER_SSH2) {
487 debug("bad cipher %s [%s]", p, names);
211 xfree(ciphers); 488 xfree(ciphers);
212 return 0; 489 return 0;
490 } else {
491 debug("cipher ok: %s [%s]", p, names);
213 } 492 }
214 } 493 }
494 debug("ciphers ok: [%s]", names);
215 xfree(ciphers); 495 xfree(ciphers);
216 return 1; 496 return 1;
217} 497}
@@ -224,14 +504,49 @@ ciphers_valid(const char *names)
224int 504int
225cipher_number(const char *name) 505cipher_number(const char *name)
226{ 506{
227 int i; 507 Cipher *c;
228 if (name == NULL) 508 if (name == NULL)
229 return -1; 509 return -1;
230 for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++) 510 c = cipher_by_name(name);
231 if (strcmp(cipher_names[i], name) == 0 && 511 return (c==NULL) ? -1 : c->number;
232 (cipher_mask() & (1 << i))) 512}
233 return i; 513
234 return -1; 514char *
515cipher_name(int id)
516{
517 Cipher *c = cipher_by_number(id);
518 return (c==NULL) ? "<unknown>" : c->name;
519}
520
521void
522cipher_init(CipherContext *cc, Cipher *cipher,
523 const u_char *key, u_int keylen, const u_char *iv, u_int ivlen)
524{
525 if (keylen < cipher->key_len)
526 fatal("cipher_init: key length %d is insufficient for %s.",
527 keylen, cipher->name);
528 if (iv != NULL && ivlen < cipher->block_size)
529 fatal("cipher_init: iv length %d is insufficient for %s.",
530 ivlen, cipher->name);
531 cc->cipher = cipher;
532 cipher->setkey(cc, key, keylen);
533 cipher->setiv(cc, iv, ivlen);
534}
535
536void
537cipher_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
538{
539 if (len % cc->cipher->block_size)
540 fatal("cipher_encrypt: bad plaintext length %d", len);
541 cc->cipher->encrypt(cc, dest, src, len);
542}
543
544void
545cipher_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
546{
547 if (len % cc->cipher->block_size)
548 fatal("cipher_decrypt: bad ciphertext length %d", len);
549 cc->cipher->decrypt(cc, dest, src, len);
235} 550}
236 551
237/* 552/*
@@ -240,248 +555,18 @@ cipher_number(const char *name)
240 */ 555 */
241 556
242void 557void
243cipher_set_key_string(CipherContext *context, int cipher, const char *passphrase) 558cipher_set_key_string(CipherContext *cc, Cipher *cipher,
559 const char *passphrase)
244{ 560{
245 MD5_CTX md; 561 MD5_CTX md;
246 unsigned char digest[16]; 562 unsigned char digest[16];
247 563
248 MD5_Init(&md); 564 MD5_Init(&md);
249 MD5_Update(&md, (const unsigned char *) passphrase, strlen(passphrase)); 565 MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
250 MD5_Final(digest, &md); 566 MD5_Final(digest, &md);
251 567
252 cipher_set_key(context, cipher, digest, 16); 568 cipher_init(cc, cipher, digest, 16, NULL, 0);
253 569
254 memset(digest, 0, sizeof(digest)); 570 memset(digest, 0, sizeof(digest));
255 memset(&md, 0, sizeof(md)); 571 memset(&md, 0, sizeof(md));
256} 572}
257
258/* Selects the cipher to use and sets the key. */
259
260void
261cipher_set_key(CipherContext *context, int cipher, const unsigned char *key,
262 int keylen)
263{
264 unsigned char padded[32];
265
266 /* Set cipher type. */
267 context->type = cipher;
268
269 /* Get 32 bytes of key data. Pad if necessary. (So that code
270 below does not need to worry about key size). */
271 memset(padded, 0, sizeof(padded));
272 memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded));
273
274 /* Initialize the initialization vector. */
275 switch (cipher) {
276 case SSH_CIPHER_NONE:
277 /*
278 * Has to stay for authfile saving of private key with no
279 * passphrase
280 */
281 break;
282
283 case SSH_CIPHER_3DES:
284 /*
285 * Note: the least significant bit of each byte of key is
286 * parity, and must be ignored by the implementation. 16
287 * bytes of key are used (first and last keys are the same).
288 */
289 if (keylen < 16)
290 error("Key length %d is insufficient for 3DES.", keylen);
291 des_set_key((void *) padded, context->u.des3.key1);
292 des_set_key((void *) (padded + 8), context->u.des3.key2);
293 if (keylen <= 16)
294 des_set_key((void *) padded, context->u.des3.key3);
295 else
296 des_set_key((void *) (padded + 16), context->u.des3.key3);
297 memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2));
298 memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3));
299 break;
300
301 case SSH_CIPHER_BLOWFISH:
302 if (keylen < 16)
303 error("Key length %d is insufficient for blowfish.", keylen);
304 BF_set_key(&context->u.bf.key, keylen, padded);
305 memset(context->u.bf.iv, 0, 8);
306 break;
307
308 case SSH_CIPHER_3DES_CBC:
309 case SSH_CIPHER_BLOWFISH_CBC:
310 case SSH_CIPHER_ARCFOUR:
311 case SSH_CIPHER_CAST128_CBC:
312 fatal("cipher_set_key: illegal cipher: %s", cipher_name(cipher));
313 break;
314
315 default:
316 fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
317 }
318 memset(padded, 0, sizeof(padded));
319}
320
321void
322cipher_set_key_iv(CipherContext * context, int cipher,
323 const unsigned char *key, int keylen,
324 const unsigned char *iv, int ivlen)
325{
326 /* Set cipher type. */
327 context->type = cipher;
328
329 /* Initialize the initialization vector. */
330 switch (cipher) {
331 case SSH_CIPHER_NONE:
332 break;
333
334 case SSH_CIPHER_3DES:
335 case SSH_CIPHER_BLOWFISH:
336 fatal("cipher_set_key_iv: illegal cipher: %s", cipher_name(cipher));
337 break;
338
339 case SSH_CIPHER_3DES_CBC:
340 if (keylen < 24)
341 error("Key length %d is insufficient for 3des-cbc.", keylen);
342 des_set_key((void *) key, context->u.des3.key1);
343 des_set_key((void *) (key+8), context->u.des3.key2);
344 des_set_key((void *) (key+16), context->u.des3.key3);
345 if (ivlen < 8)
346 error("IV length %d is insufficient for 3des-cbc.", ivlen);
347 memcpy(context->u.des3.iv3, (char *)iv, 8);
348 break;
349
350 case SSH_CIPHER_BLOWFISH_CBC:
351 if (keylen < 16)
352 error("Key length %d is insufficient for blowfish.", keylen);
353 if (ivlen < 8)
354 error("IV length %d is insufficient for blowfish.", ivlen);
355 BF_set_key(&context->u.bf.key, keylen, (unsigned char *)key);
356 memcpy(context->u.bf.iv, (char *)iv, 8);
357 break;
358
359 case SSH_CIPHER_ARCFOUR:
360 if (keylen < 16)
361 error("Key length %d is insufficient for arcfour.", keylen);
362 RC4_set_key(&context->u.rc4, keylen, (unsigned char *)key);
363 break;
364
365 case SSH_CIPHER_CAST128_CBC:
366 if (keylen < 16)
367 error("Key length %d is insufficient for cast128.", keylen);
368 if (ivlen < 8)
369 error("IV length %d is insufficient for cast128.", ivlen);
370 CAST_set_key(&context->u.cast.key, keylen, (unsigned char *) key);
371 memcpy(context->u.cast.iv, (char *)iv, 8);
372 break;
373
374 default:
375 fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
376 }
377}
378
379/* Encrypts data using the cipher. */
380
381void
382cipher_encrypt(CipherContext *context, unsigned char *dest,
383 const unsigned char *src, unsigned int len)
384{
385 if ((len & 7) != 0)
386 fatal("cipher_encrypt: bad plaintext length %d", len);
387
388 switch (context->type) {
389 case SSH_CIPHER_NONE:
390 memcpy(dest, src, len);
391 break;
392
393 case SSH_CIPHER_3DES:
394 SSH_3CBC_ENCRYPT(context->u.des3.key1,
395 context->u.des3.key2, &context->u.des3.iv2,
396 context->u.des3.key3, &context->u.des3.iv3,
397 dest, (unsigned char *) src, len);
398 break;
399
400 case SSH_CIPHER_BLOWFISH:
401 swap_bytes(src, dest, len);
402 BF_cbc_encrypt(dest, dest, len,
403 &context->u.bf.key, context->u.bf.iv,
404 BF_ENCRYPT);
405 swap_bytes(dest, dest, len);
406 break;
407
408 case SSH_CIPHER_BLOWFISH_CBC:
409 BF_cbc_encrypt((void *)src, dest, len,
410 &context->u.bf.key, context->u.bf.iv,
411 BF_ENCRYPT);
412 break;
413
414 case SSH_CIPHER_3DES_CBC:
415 des_ede3_cbc_encrypt(src, dest, len,
416 context->u.des3.key1, context->u.des3.key2,
417 context->u.des3.key3, &context->u.des3.iv3, DES_ENCRYPT);
418 break;
419
420 case SSH_CIPHER_ARCFOUR:
421 RC4(&context->u.rc4, len, (unsigned char *)src, dest);
422 break;
423
424 case SSH_CIPHER_CAST128_CBC:
425 CAST_cbc_encrypt(src, dest, len,
426 &context->u.cast.key, context->u.cast.iv, CAST_ENCRYPT);
427 break;
428
429 default:
430 fatal("cipher_encrypt: unknown cipher: %s", cipher_name(context->type));
431 }
432}
433
434/* Decrypts data using the cipher. */
435
436void
437cipher_decrypt(CipherContext *context, unsigned char *dest,
438 const unsigned char *src, unsigned int len)
439{
440 if ((len & 7) != 0)
441 fatal("cipher_decrypt: bad ciphertext length %d", len);
442
443 switch (context->type) {
444 case SSH_CIPHER_NONE:
445 memcpy(dest, src, len);
446 break;
447
448 case SSH_CIPHER_3DES:
449 SSH_3CBC_DECRYPT(context->u.des3.key1,
450 context->u.des3.key2, &context->u.des3.iv2,
451 context->u.des3.key3, &context->u.des3.iv3,
452 dest, (unsigned char *) src, len);
453 break;
454
455 case SSH_CIPHER_BLOWFISH:
456 swap_bytes(src, dest, len);
457 BF_cbc_encrypt((void *) dest, dest, len,
458 &context->u.bf.key, context->u.bf.iv,
459 BF_DECRYPT);
460 swap_bytes(dest, dest, len);
461 break;
462
463 case SSH_CIPHER_BLOWFISH_CBC:
464 BF_cbc_encrypt((void *) src, dest, len,
465 &context->u.bf.key, context->u.bf.iv,
466 BF_DECRYPT);
467 break;
468
469 case SSH_CIPHER_3DES_CBC:
470 des_ede3_cbc_encrypt(src, dest, len,
471 context->u.des3.key1, context->u.des3.key2,
472 context->u.des3.key3, &context->u.des3.iv3, DES_DECRYPT);
473 break;
474
475 case SSH_CIPHER_ARCFOUR:
476 RC4(&context->u.rc4, len, (unsigned char *)src, dest);
477 break;
478
479 case SSH_CIPHER_CAST128_CBC:
480 CAST_cbc_encrypt(src, dest, len,
481 &context->u.cast.key, context->u.cast.iv, CAST_DECRYPT);
482 break;
483
484 default:
485 fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type));
486 }
487}
diff --git a/cipher.h b/cipher.h
index bc7a5e224..97bc8891f 100644
--- a/cipher.h
+++ b/cipher.h
@@ -8,9 +8,31 @@
8 * software must be clearly marked as such, and if the derived work is 8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be 9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell". 10 * called by a name other than "ssh" or "Secure Shell".
11 *
12 * Copyright (c) 2000 Markus Friedl. All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11 */ 33 */
12 34
13/* RCSID("$OpenBSD: cipher.h,v 1.19 2000/09/07 20:27:50 deraadt Exp $"); */ 35/* RCSID("$OpenBSD: cipher.h,v 1.22 2000/10/13 18:59:14 markus Exp $"); */
14 36
15#ifndef CIPHER_H 37#ifndef CIPHER_H
16#define CIPHER_H 38#define CIPHER_H
@@ -19,9 +41,12 @@
19#include <openssl/blowfish.h> 41#include <openssl/blowfish.h>
20#include <openssl/rc4.h> 42#include <openssl/rc4.h>
21#include <openssl/cast.h> 43#include <openssl/cast.h>
22 44#include "rijndael.h"
23/* Cipher types. New types can be added, but old types should not be removed 45/*
24 for compatibility. The maximum allowed value is 31. */ 46 * Cipher types for SSH-1. New types can be added, but old types should not
47 * be removed for compatibility. The maximum allowed value is 31.
48 */
49#define SSH_CIPHER_SSH2 -3
25#define SSH_CIPHER_ILLEGAL -2 /* No valid cipher selected. */ 50#define SSH_CIPHER_ILLEGAL -2 /* No valid cipher selected. */
26#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */ 51#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */
27#define SSH_CIPHER_NONE 0 /* no encryption */ 52#define SSH_CIPHER_NONE 0 /* no encryption */
@@ -32,17 +57,18 @@
32#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */ 57#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
33#define SSH_CIPHER_BLOWFISH 6 58#define SSH_CIPHER_BLOWFISH 6
34#define SSH_CIPHER_RESERVED 7 59#define SSH_CIPHER_RESERVED 7
60#define SSH_CIPHER_MAX 31
35 61
36/* these ciphers are used in SSH2: */ 62typedef struct Cipher Cipher;
37#define SSH_CIPHER_BLOWFISH_CBC 8 63typedef struct CipherContext CipherContext;
38#define SSH_CIPHER_3DES_CBC 9
39#define SSH_CIPHER_ARCFOUR 10 /* Alleged RC4 */
40#define SSH_CIPHER_CAST128_CBC 11
41 64
42typedef struct { 65struct CipherContext {
43 unsigned int type;
44 union { 66 union {
45 struct { 67 struct {
68 des_key_schedule key;
69 des_cblock iv;
70 } des;
71 struct {
46 des_key_schedule key1; 72 des_key_schedule key1;
47 des_key_schedule key2; 73 des_key_schedule key2;
48 des_cblock iv2; 74 des_cblock iv2;
@@ -51,64 +77,41 @@ typedef struct {
51 } des3; 77 } des3;
52 struct { 78 struct {
53 struct bf_key_st key; 79 struct bf_key_st key;
54 unsigned char iv[8]; 80 u_char iv[8];
55 } bf; 81 } bf;
56 struct { 82 struct {
57 CAST_KEY key; 83 CAST_KEY key;
58 unsigned char iv[8]; 84 u_char iv[8];
59 } cast; 85 } cast;
86 struct {
87 u4byte iv[4];
88 rijndael_ctx enc;
89 rijndael_ctx dec;
90 } rijndael;
60 RC4_KEY rc4; 91 RC4_KEY rc4;
61 } u; 92 } u;
62} CipherContext; 93 Cipher *cipher;
63/* 94};
64 * Returns a bit mask indicating which ciphers are supported by this 95struct Cipher {
65 * implementation. The bit mask has the corresponding bit set of each 96 char *name;
66 * supported cipher. 97 int number; /* for ssh1 only */
67 */ 98 u_int block_size;
68unsigned int cipher_mask(); 99 u_int key_len;
69unsigned int cipher_mask1(); 100 void (*setkey)(CipherContext *, const u_char *, u_int);
70unsigned int cipher_mask2(); 101 void (*setiv)(CipherContext *, const u_char *, u_int);
71 102 void (*encrypt)(CipherContext *, u_char *, const u_char *, u_int);
72/* Returns the name of the cipher. */ 103 void (*decrypt)(CipherContext *, u_char *, const u_char *, u_int);
73const char *cipher_name(int cipher); 104};
74
75/*
76 * Parses the name of the cipher. Returns the number of the corresponding
77 * cipher, or -1 on error.
78 */
79int cipher_number(const char *name);
80
81/* returns 1 if all ciphers are supported (ssh2 only) */
82int ciphers_valid(const char *names);
83
84/*
85 * Selects the cipher to use and sets the key. If for_encryption is true,
86 * the key is setup for encryption; otherwise it is setup for decryption.
87 */
88void
89cipher_set_key(CipherContext * context, int cipher,
90 const unsigned char *key, int keylen);
91void
92cipher_set_key_iv(CipherContext * context, int cipher,
93 const unsigned char *key, int keylen,
94 const unsigned char *iv, int ivlen);
95
96/*
97 * Sets key for the cipher by computing the MD5 checksum of the passphrase,
98 * and using the resulting 16 bytes as the key.
99 */
100void
101cipher_set_key_string(CipherContext * context, int cipher,
102 const char *passphrase);
103
104/* Encrypts data using the cipher. */
105void
106cipher_encrypt(CipherContext * context, unsigned char *dest,
107 const unsigned char *src, unsigned int len);
108 105
109/* Decrypts data using the cipher. */ 106unsigned int cipher_mask_ssh1(int client);
110void 107Cipher *cipher_by_name(const char *name);
111cipher_decrypt(CipherContext * context, unsigned char *dest, 108Cipher *cipher_by_number(int id);
112 const unsigned char *src, unsigned int len); 109int cipher_number(const char *name);
110char *cipher_name(int id);
111int ciphers_valid(const char *names);
112void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, const u_char *, u_int);
113void cipher_encrypt(CipherContext *context, u_char *dest, const u_char *src, u_int len);
114void cipher_decrypt(CipherContext *context, u_char *dest, const u_char *src, u_int len);
115void cipher_set_key_string(CipherContext *context, Cipher *cipher, const char *passphrase);
113 116
114#endif /* CIPHER_H */ 117#endif /* CIPHER_H */
diff --git a/cli.c b/cli.c
new file mode 100644
index 000000000..7814a6188
--- /dev/null
+++ b/cli.c
@@ -0,0 +1,195 @@
1#include "includes.h"
2RCSID("$Id: cli.c,v 1.1 2000/10/14 05:23:12 djm Exp $");
3
4#include "xmalloc.h"
5#include "ssh.h"
6
7static int cli_input = -1;
8static int cli_output = -1;
9static int cli_from_stdin = 0;
10
11sigset_t oset;
12sigset_t nset;
13struct sigaction nsa;
14struct sigaction osa;
15struct termios ntio;
16struct termios otio;
17int echo_modified;
18
19volatile int intr;
20
21static int
22cli_open(int from_stdin)
23{
24 if (cli_input >= 0 && cli_output >= 0 && cli_from_stdin == from_stdin)
25 return 1;
26
27 if (from_stdin) {
28 if (!cli_from_stdin && cli_input >= 0) {
29 (void)close(cli_input);
30 }
31 cli_input = STDIN_FILENO;
32 cli_output = STDERR_FILENO;
33 } else {
34 cli_input = cli_output = open("/dev/tty", O_RDWR);
35 if (cli_input < 0)
36 fatal("You have no controlling tty. Cannot read passphrase.");
37 }
38
39 cli_from_stdin = from_stdin;
40
41 return cli_input >= 0 && cli_output >= 0 && cli_from_stdin == from_stdin;
42}
43
44static void
45cli_close()
46{
47 if (!cli_from_stdin && cli_input >= 0)
48 close(cli_input);
49 cli_input = -1;
50 cli_output = -1;
51 cli_from_stdin = 0;
52 return;
53}
54
55void
56intrcatch()
57{
58 intr = 1;
59}
60
61static void
62cli_echo_disable()
63{
64 sigemptyset(&nset);
65 sigaddset(&nset, SIGTSTP);
66 (void) sigprocmask(SIG_BLOCK, &nset, &oset);
67
68 intr = 0;
69
70 memset(&nsa, 0, sizeof(nsa));
71 nsa.sa_handler = intrcatch;
72 (void) sigaction(SIGINT, &nsa, &osa);
73
74 echo_modified = 0;
75 if (tcgetattr(cli_input, &otio) == 0 && (otio.c_lflag & ECHO)) {
76 echo_modified = 1;
77 ntio = otio;
78 ntio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
79 (void) tcsetattr(cli_input, TCSANOW, &ntio);
80 }
81 return;
82}
83
84static void
85cli_echo_restore()
86{
87 if (echo_modified != 0) {
88 tcsetattr(cli_input, TCSANOW, &otio);
89 echo_modified = 0;
90 }
91
92 (void) sigprocmask(SIG_SETMASK, &oset, NULL);
93 (void) sigaction(SIGINT, &osa, NULL);
94
95 if (intr != 0) {
96 kill(getpid(), SIGINT);
97 sigemptyset(&nset);
98 /* XXX tty has not neccessarily drained by now? */
99 sigsuspend(&nset);
100 intr = 0;
101 }
102 return;
103}
104
105static int
106cli_read(char* buf, int size, int echo)
107{
108 char ch = 0;
109 int i = 0;
110
111 if (!echo)
112 cli_echo_disable();
113
114 while (ch != '\n') {
115 if (read(cli_input, &ch, 1) != 1)
116 break;
117 if (ch == '\n' || intr != 0)
118 break;
119 if (i < size)
120 buf[i++] = ch;
121 }
122 buf[i] = '\0';
123
124 if (!echo)
125 cli_echo_restore();
126 if (!intr && !echo)
127 (void) write(cli_output, "\n", 1);
128 return i;
129}
130
131static int
132cli_write(char* buf, int size)
133{
134 int i, len, pos, ret = 0;
135 char *output, *p;
136
137 output = xmalloc(4*size);
138 for (p = output, i = 0; i < size; i++) {
139 if (buf[i] == '\n')
140 *p++ = buf[i];
141 else
142 p = vis(p, buf[i], 0, 0);
143 }
144 len = p - output;
145
146 for (pos = 0; pos < len; pos += ret) {
147 ret = write(cli_output, output + pos, len - pos);
148 if (ret == -1)
149 return -1;
150 }
151 return 0;
152}
153
154/*
155 * Presents a prompt and returns the response allocated with xmalloc().
156 * Uses /dev/tty or stdin/out depending on arg. Optionally disables echo
157 * of response depending on arg. Tries to ensure that no other userland
158 * buffer is storing the response.
159 */
160char*
161cli_read_passphrase(char* prompt, int from_stdin, int echo_enable)
162{
163 char buf[BUFSIZ];
164 char* p;
165
166 if (!cli_open(from_stdin))
167 fatal("Cannot read passphrase.");
168
169 fflush(stdout);
170
171 cli_write(prompt, strlen(prompt));
172 cli_read(buf, sizeof buf, echo_enable);
173
174 cli_close();
175
176 p = xstrdup(buf);
177 memset(buf, 0, sizeof(buf));
178 return (p);
179}
180
181char*
182cli_prompt(char* prompt, int echo_enable)
183{
184 return cli_read_passphrase(prompt, 0, echo_enable);
185}
186
187void
188cli_mesg(char* mesg)
189{
190 cli_open(0);
191 cli_write(mesg, strlen(mesg));
192 cli_write("\n", strlen("\n"));
193 cli_close();
194 return;
195}
diff --git a/cli.h b/cli.h
new file mode 100644
index 000000000..e33ce4a50
--- /dev/null
+++ b/cli.h
@@ -0,0 +1,14 @@
1#ifndef CLI_H
2#define CLI_H
3
4/*
5 * Presents a prompt and returns the response allocated with xmalloc().
6 * Uses /dev/tty or stdin/out depending on arg. Optionally disables echo
7 * of response depending on arg. Tries to ensure that no other userland
8 * buffer is storing the response.
9 */
10char* cli_read_passphrase(char* prompt, int from_stdin, int echo_enable);
11char* cli_prompt(char* prompt, int echo_enable);
12void cli_mesg(char* mesg);
13
14#endif /* CLI_H */
diff --git a/compat.c b/compat.c
index eeb6e2ef1..19dc76d96 100644
--- a/compat.c
+++ b/compat.c
@@ -23,12 +23,13 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: compat.c,v 1.23 2000/09/07 21:13:37 markus Exp $"); 26RCSID("$OpenBSD: compat.c,v 1.24 2000/10/10 20:20:45 markus Exp $");
27 27
28#include "ssh.h" 28#include "ssh.h"
29#include "packet.h" 29#include "packet.h"
30#include "xmalloc.h" 30#include "xmalloc.h"
31#include "compat.h" 31#include "compat.h"
32#include <regex.h>
32 33
33int compat13 = 0; 34int compat13 = 0;
34int compat20 = 0; 35int compat20 = 0;
@@ -50,27 +51,39 @@ enable_compat13(void)
50void 51void
51compat_datafellows(const char *version) 52compat_datafellows(const char *version)
52{ 53{
53 int i; 54 int i, ret;
54 size_t len; 55 char ebuf[1024];
55 struct { 56 regex_t reg;
56 char *version; 57 static struct {
58 char *pat;
57 int bugs; 59 int bugs;
58 } check[] = { 60 } check[] = {
59 {"2.1.0", SSH_BUG_SIGBLOB|SSH_BUG_HMAC}, 61 {"^.*MindTerm", 0},
60 {"2.0.1", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|SSH_BUG_PUBKEYAUTH|SSH_BUG_X11FWD}, 62 {"^2\\.1\\.0 ", SSH_BUG_SIGBLOB|SSH_BUG_HMAC},
61 {"2.", SSH_BUG_HMAC|SSH_COMPAT_SESSIONID_ENCODING}, 63 {"^2\\.0\\.", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|SSH_BUG_PUBKEYAUTH|SSH_BUG_X11FWD},
62 {NULL, 0} 64 {"^2\\.[23]\\.0 ", SSH_BUG_HMAC|SSH_COMPAT_SESSIONID_ENCODING},
65 {"^2\\.[2-9]\\.", SSH_COMPAT_SESSIONID_ENCODING},
66 {"^2\\.", SSH_BUG_HMAC|SSH_COMPAT_SESSIONID_ENCODING},
67 {NULL, 0}
63 }; 68 };
64 /* process table, return first match */ 69 /* process table, return first match */
65 for (i = 0; check[i].version; i++) { 70 for (i = 0; check[i].pat; i++) {
66 len = strlen(check[i].version); 71 ret = regcomp(&reg, check[i].pat, REG_EXTENDED|REG_NOSUB);
67 if (strlen(version) >= len && 72 if (ret != 0) {
68 (strncmp(version, check[i].version, len) == 0)) { 73 regerror(ret, &reg, ebuf, sizeof(ebuf));
69 verbose("datafellows: %.200s", version); 74 ebuf[sizeof(ebuf)-1] = '\0';
75 error("regerror: %s", ebuf);
76 continue;
77 }
78 ret = regexec(&reg, version, 0, NULL, 0);
79 regfree(&reg);
80 if (ret == 0) {
81 debug("match: %s pat %s\n", version, check[i].pat);
70 datafellows = check[i].bugs; 82 datafellows = check[i].bugs;
71 return; 83 return;
72 } 84 }
73 } 85 }
86 debug("no match: %s", version);
74} 87}
75 88
76#define SEP "," 89#define SEP ","
diff --git a/configure.in b/configure.in
index c342d14fa..b3ab2fdb8 100644
--- a/configure.in
+++ b/configure.in
@@ -265,10 +265,10 @@ if test -z "$no_libnsl" ; then
265fi 265fi
266 266
267# Checks for header files. 267# Checks for header files.
268AC_CHECK_HEADERS(bstring.h endian.h floatingpoint.h getopt.h lastlog.h limits.h login.h login_cap.h maillock.h netdb.h netgroup.h netinet/in_systm.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/select.h sys/stat.h sys/stropts.h sys/sysmacros.h sys/time.h sys/ttcompat.h sys/un.h stddef.h time.h ttyent.h usersec.h util.h utmp.h utmpx.h) 268AC_CHECK_HEADERS(bstring.h endian.h floatingpoint.h getopt.h lastlog.h limits.h login.h login_cap.h maillock.h netdb.h netgroup.h netinet/in_systm.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/select.h sys/stat.h sys/stropts.h sys/sysmacros.h sys/time.h sys/ttcompat.h sys/un.h stddef.h time.h ttyent.h usersec.h util.h utmp.h utmpx.h vis.h)
269 269
270dnl Checks for library functions. 270dnl Checks for library functions.
271AC_CHECK_FUNCS(arc4random atexit b64_ntop bcopy bindresvport_af clock fchmod freeaddrinfo futimes gai_strerror getaddrinfo getnameinfo getrusage getttyent inet_aton inet_ntoa innetgr login_getcapbool md5_crypt memmove mkdtemp on_exit openpty rresvport_af setenv seteuid setlogin setproctitle setreuid setrlimit sigaction sigvec snprintf strerror strlcat strlcpy strsep strtok_r vsnprintf vhangup _getpty __b64_ntop) 271AC_CHECK_FUNCS(arc4random atexit b64_ntop bcopy bindresvport_af clock fchmod freeaddrinfo futimes gai_strerror getaddrinfo getnameinfo getrusage getttyent inet_aton inet_ntoa innetgr login_getcapbool md5_crypt memmove mkdtemp on_exit openpty rresvport_af setenv seteuid setlogin setproctitle setreuid setrlimit sigaction sigvec snprintf strerror strlcat strlcpy strsep strtok_r vsnprintf vhangup vis _getpty __b64_ntop)
272dnl Checks for time functions 272dnl Checks for time functions
273AC_CHECK_FUNCS(gettimeofday time) 273AC_CHECK_FUNCS(gettimeofday time)
274dnl Checks for libutil functions 274dnl Checks for libutil functions
diff --git a/dh.c b/dh.c
new file mode 100644
index 000000000..ff84619cf
--- /dev/null
+++ b/dh.c
@@ -0,0 +1,157 @@
1/*
2 * Copyright (c) 2000 Niels Provos. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "includes.h"
26RCSID("$OpenBSD: dh.c,v 1.2 2000/10/11 20:11:35 markus Exp $");
27
28#include "xmalloc.h"
29
30#include <openssl/bn.h>
31#include <openssl/dh.h>
32#include <openssl/evp.h>
33
34#include "ssh.h"
35#include "buffer.h"
36#include "kex.h"
37#include "dh.h"
38
39int
40parse_prime(int linenum, char *line, struct dhgroup *dhg)
41{
42 char *cp, *arg;
43 char *strsize, *gen, *prime;
44
45 cp = line;
46 arg = strdelim(&cp);
47 /* Ignore leading whitespace */
48 if (*arg == '\0')
49 arg = strdelim(&cp);
50 if (!*arg || *arg == '#')
51 return 0;
52
53 /* time */
54 if (cp == NULL || *arg == '\0')
55 goto fail;
56 arg = strsep(&cp, " "); /* type */
57 if (cp == NULL || *arg == '\0')
58 goto fail;
59 arg = strsep(&cp, " "); /* tests */
60 if (cp == NULL || *arg == '\0')
61 goto fail;
62 arg = strsep(&cp, " "); /* tries */
63 if (cp == NULL || *arg == '\0')
64 goto fail;
65 strsize = strsep(&cp, " "); /* size */
66 if (cp == NULL || *strsize == '\0' ||
67 (dhg->size = atoi(strsize)) == 0)
68 goto fail;
69 gen = strsep(&cp, " "); /* gen */
70 if (cp == NULL || *gen == '\0')
71 goto fail;
72 prime = strsep(&cp, " "); /* prime */
73 if (cp != NULL || *prime == '\0')
74 goto fail;
75
76 dhg->g = BN_new();
77 if (BN_hex2bn(&dhg->g, gen) < 0) {
78 BN_free(dhg->g);
79 goto fail;
80 }
81 dhg->p = BN_new();
82 if (BN_hex2bn(&dhg->p, prime) < 0) {
83 BN_free(dhg->g);
84 BN_free(dhg->p);
85 goto fail;
86 }
87
88 return (1);
89 fail:
90 fprintf(stderr, "Bad prime description in line %d\n", linenum);
91 return (0);
92}
93
94DH *
95choose_dh(int minbits)
96{
97 FILE *f;
98 char line[1024];
99 int best, bestcount, which;
100 int linenum;
101 struct dhgroup dhg;
102
103 f = fopen(DH_PRIMES, "r");
104 if (!f) {
105 perror(DH_PRIMES);
106 log("WARNING: %s does not exist, using old prime", DH_PRIMES);
107 return (dh_new_group1());
108 }
109
110 linenum = 0;
111 best = bestcount = 0;
112 while (fgets(line, sizeof(line), f)) {
113 linenum++;
114 if (!parse_prime(linenum, line, &dhg))
115 continue;
116 BN_free(dhg.g);
117 BN_free(dhg.p);
118
119 if ((dhg.size > minbits && dhg.size < best) ||
120 (dhg.size > best && best < minbits)) {
121 best = dhg.size;
122 bestcount = 0;
123 }
124 if (dhg.size == best)
125 bestcount++;
126 }
127 fclose (f);
128
129 if (bestcount == 0) {
130 log("WARNING: no primes in %s, using old prime", DH_PRIMES);
131 return (dh_new_group1());
132 }
133
134 f = fopen(DH_PRIMES, "r");
135 if (!f) {
136 perror(DH_PRIMES);
137 exit(1);
138 }
139
140 linenum = 0;
141 which = arc4random() % bestcount;
142 while (fgets(line, sizeof(line), f)) {
143 if (!parse_prime(linenum, line, &dhg))
144 continue;
145 if (dhg.size != best)
146 continue;
147 if (linenum++ != which) {
148 BN_free(dhg.g);
149 BN_free(dhg.p);
150 continue;
151 }
152 break;
153 }
154 fclose(f);
155
156 return (dh_new_group(dhg.g, dhg.p));
157}
diff --git a/dh.h b/dh.h
new file mode 100644
index 000000000..09b11fdbb
--- /dev/null
+++ b/dh.h
@@ -0,0 +1,35 @@
1/*
2 * Copyright (c) 2000 Niels Provos. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24#ifndef DH_H
25#define DH_H
26
27struct dhgroup {
28 int size;
29 BIGNUM *g;
30 BIGNUM *p;
31};
32
33DH *choose_dh(int minbits);
34
35#endif
diff --git a/includes.h b/includes.h
index 37881f6b0..797c5e851 100644
--- a/includes.h
+++ b/includes.h
@@ -87,7 +87,9 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
87#ifdef HAVE_SYS_SYSMACROS_H 87#ifdef HAVE_SYS_SYSMACROS_H
88# include <sys/sysmacros.h> 88# include <sys/sysmacros.h>
89#endif 89#endif
90 90#ifdef HAVE_VIS_H
91# include <vis.h>
92#endif
91#include "version.h" 93#include "version.h"
92#include "openbsd-compat.h" 94#include "openbsd-compat.h"
93#include "cygwin_util.h" 95#include "cygwin_util.h"
diff --git a/kex.c b/kex.c
index 8a83db47e..68b9e522e 100644
--- a/kex.c
+++ b/kex.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: kex.c,v 1.10 2000/09/07 20:27:51 deraadt Exp $"); 26RCSID("$OpenBSD: kex.c,v 1.12 2000/10/11 20:27:23 markus Exp $");
27 27
28#include "ssh.h" 28#include "ssh.h"
29#include "ssh2.h" 29#include "ssh2.h"
@@ -31,7 +31,6 @@ RCSID("$OpenBSD: kex.c,v 1.10 2000/09/07 20:27:51 deraadt Exp $");
31#include "buffer.h" 31#include "buffer.h"
32#include "bufaux.h" 32#include "bufaux.h"
33#include "packet.h" 33#include "packet.h"
34#include "cipher.h"
35#include "compat.h" 34#include "compat.h"
36 35
37#include <openssl/bn.h> 36#include <openssl/bn.h>
@@ -123,11 +122,6 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
123 int n = BN_num_bits(dh_pub); 122 int n = BN_num_bits(dh_pub);
124 int bits_set = 0; 123 int bits_set = 0;
125 124
126 /* we only accept g==2 */
127 if (!BN_is_word(dh->g, 2)) {
128 log("invalid DH base != 2");
129 return 0;
130 }
131 if (dh_pub->neg) { 125 if (dh_pub->neg) {
132 log("invalid public DH value: negativ"); 126 log("invalid public DH value: negativ");
133 return 0; 127 return 0;
@@ -145,27 +139,10 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
145} 139}
146 140
147DH * 141DH *
148dh_new_group1() 142dh_gen_key(DH *dh)
149{ 143{
150 static char *group1 = 144 int tries = 0;
151 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" 145
152 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
153 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
154 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
155 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
156 "FFFFFFFF" "FFFFFFFF";
157 DH *dh;
158 int ret, tries = 0;
159 dh = DH_new();
160 if(dh == NULL)
161 fatal("DH_new");
162 ret = BN_hex2bn(&dh->p, group1);
163 if(ret<0)
164 fatal("BN_hex2bn");
165 dh->g = BN_new();
166 if(dh->g == NULL)
167 fatal("DH_new g");
168 BN_set_word(dh->g, 2);
169 do { 146 do {
170 if (DH_generate_key(dh) == 0) 147 if (DH_generate_key(dh) == 0)
171 fatal("DH_generate_key"); 148 fatal("DH_generate_key");
@@ -175,6 +152,52 @@ dh_new_group1()
175 return dh; 152 return dh;
176} 153}
177 154
155DH *
156dh_new_group_asc(const char *gen, const char *modulus)
157{
158 DH *dh;
159 int ret;
160
161 dh = DH_new();
162 if (dh == NULL)
163 fatal("DH_new");
164
165 if ((ret = BN_hex2bn(&dh->p, modulus)) < 0)
166 fatal("BN_hex2bn p");
167 if ((ret = BN_hex2bn(&dh->g, gen)) < 0)
168 fatal("BN_hex2bn g");
169
170 return (dh_gen_key(dh));
171}
172
173DH *
174dh_new_group(BIGNUM *gen, BIGNUM *modulus)
175{
176 DH *dh;
177
178 dh = DH_new();
179 if (dh == NULL)
180 fatal("DH_new");
181 dh->p = modulus;
182 dh->g = gen;
183
184 return (dh_gen_key(dh));
185}
186
187DH *
188dh_new_group1()
189{
190 static char *gen = "2", *group1 =
191 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
192 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
193 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
194 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
195 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
196 "FFFFFFFF" "FFFFFFFF";
197
198 return (dh_new_group_asc(gen, group1));
199}
200
178void 201void
179dump_digest(unsigned char *digest, int len) 202dump_digest(unsigned char *digest, int len)
180{ 203{
@@ -237,6 +260,59 @@ kex_hash(
237} 260}
238 261
239unsigned char * 262unsigned char *
263kex_hash_gex(
264 char *client_version_string,
265 char *server_version_string,
266 char *ckexinit, int ckexinitlen,
267 char *skexinit, int skexinitlen,
268 char *serverhostkeyblob, int sbloblen,
269 int minbits, BIGNUM *prime, BIGNUM *gen,
270 BIGNUM *client_dh_pub,
271 BIGNUM *server_dh_pub,
272 BIGNUM *shared_secret)
273{
274 Buffer b;
275 static unsigned char digest[EVP_MAX_MD_SIZE];
276 EVP_MD *evp_md = EVP_sha1();
277 EVP_MD_CTX md;
278
279 buffer_init(&b);
280 buffer_put_string(&b, client_version_string, strlen(client_version_string));
281 buffer_put_string(&b, server_version_string, strlen(server_version_string));
282
283 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
284 buffer_put_int(&b, ckexinitlen+1);
285 buffer_put_char(&b, SSH2_MSG_KEXINIT);
286 buffer_append(&b, ckexinit, ckexinitlen);
287 buffer_put_int(&b, skexinitlen+1);
288 buffer_put_char(&b, SSH2_MSG_KEXINIT);
289 buffer_append(&b, skexinit, skexinitlen);
290
291 buffer_put_string(&b, serverhostkeyblob, sbloblen);
292 buffer_put_int(&b, minbits);
293 buffer_put_bignum2(&b, prime);
294 buffer_put_bignum2(&b, gen);
295 buffer_put_bignum2(&b, client_dh_pub);
296 buffer_put_bignum2(&b, server_dh_pub);
297 buffer_put_bignum2(&b, shared_secret);
298
299#ifdef DEBUG_KEX
300 buffer_dump(&b);
301#endif
302
303 EVP_DigestInit(&md, evp_md);
304 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
305 EVP_DigestFinal(&md, digest, NULL);
306
307 buffer_free(&b);
308
309#ifdef DEBUG_KEX
310 dump_digest(digest, evp_md->md_size);
311#endif
312 return digest;
313}
314
315unsigned char *
240derive_key(int id, int need, char unsigned *hash, BIGNUM *shared_secret) 316derive_key(int id, int need, char unsigned *hash, BIGNUM *shared_secret)
241{ 317{
242 Buffer b; 318 Buffer b;
@@ -318,28 +394,9 @@ choose_enc(Enc *enc, char *client, char *server)
318 char *name = get_match(client, server); 394 char *name = get_match(client, server);
319 if (name == NULL) 395 if (name == NULL)
320 fatal("no matching cipher found: client %s server %s", client, server); 396 fatal("no matching cipher found: client %s server %s", client, server);
321 enc->type = cipher_number(name); 397 enc->cipher = cipher_by_name(name);
322 398 if (enc->cipher == NULL)
323 switch (enc->type) { 399 fatal("matching cipher is not supported: %s", name);
324 case SSH_CIPHER_3DES_CBC:
325 enc->key_len = 24;
326 enc->iv_len = 8;
327 enc->block_size = 8;
328 break;
329 case SSH_CIPHER_BLOWFISH_CBC:
330 case SSH_CIPHER_CAST128_CBC:
331 enc->key_len = 16;
332 enc->iv_len = 8;
333 enc->block_size = 8;
334 break;
335 case SSH_CIPHER_ARCFOUR:
336 enc->key_len = 16;
337 enc->iv_len = 0;
338 enc->block_size = 8;
339 break;
340 default:
341 fatal("unsupported cipher %s", name);
342 }
343 enc->name = name; 400 enc->name = name;
344 enc->enabled = 0; 401 enc->enabled = 0;
345 enc->iv = NULL; 402 enc->iv = NULL;
@@ -387,7 +444,11 @@ choose_kex(Kex *k, char *client, char *server)
387 k->name = get_match(client, server); 444 k->name = get_match(client, server);
388 if (k->name == NULL) 445 if (k->name == NULL)
389 fatal("no kex alg"); 446 fatal("no kex alg");
390 if (strcmp(k->name, KEX_DH1) != 0) 447 if (strcmp(k->name, KEX_DH1) == 0) {
448 k->kex_type = DH_GRP1_SHA1;
449 } else if (strcmp(k->name, KEX_DHGEX) == 0) {
450 k->kex_type = DH_GEX_SHA1;
451 } else
391 fatal("bad kex alg %s", k->name); 452 fatal("bad kex alg %s", k->name);
392} 453}
393void 454void
@@ -432,10 +493,10 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server
432 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); 493 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
433 need = 0; 494 need = 0;
434 for (mode = 0; mode < MODE_MAX; mode++) { 495 for (mode = 0; mode < MODE_MAX; mode++) {
435 if (need < k->enc[mode].key_len) 496 if (need < k->enc[mode].cipher->key_len)
436 need = k->enc[mode].key_len; 497 need = k->enc[mode].cipher->key_len;
437 if (need < k->enc[mode].iv_len) 498 if (need < k->enc[mode].cipher->block_size)
438 need = k->enc[mode].iv_len; 499 need = k->enc[mode].cipher->block_size;
439 if (need < k->mac[mode].key_len) 500 if (need < k->mac[mode].key_len)
440 need = k->mac[mode].key_len; 501 need = k->mac[mode].key_len;
441 } 502 }
diff --git a/kex.h b/kex.h
index 8c89687b6..212958131 100644
--- a/kex.h
+++ b/kex.h
@@ -24,8 +24,9 @@
24#ifndef KEX_H 24#ifndef KEX_H
25#define KEX_H 25#define KEX_H
26 26
27#define KEX_DH1 "diffie-hellman-group1-sha1" 27#define KEX_DH1 "diffie-hellman-group1-sha1"
28#define KEX_DSS "ssh-dss" 28#define KEX_DHGEX "diffie-hellman-group-exchange-sha1"
29#define KEX_DSS "ssh-dss"
29 30
30enum kex_init_proposals { 31enum kex_init_proposals {
31 PROPOSAL_KEX_ALGS, 32 PROPOSAL_KEX_ALGS,
@@ -47,28 +48,30 @@ enum kex_modes {
47 MODE_MAX 48 MODE_MAX
48}; 49};
49 50
51enum kex_exchange {
52 DH_GRP1_SHA1,
53 DH_GEX_SHA1
54};
55
50typedef struct Kex Kex; 56typedef struct Kex Kex;
51typedef struct Mac Mac; 57typedef struct Mac Mac;
52typedef struct Comp Comp; 58typedef struct Comp Comp;
53typedef struct Enc Enc; 59typedef struct Enc Enc;
54 60
55struct Enc { 61struct Enc {
56 int type; 62 char *name;
63 Cipher *cipher;
57 int enabled; 64 int enabled;
58 int block_size;
59 unsigned char *key; 65 unsigned char *key;
60 unsigned char *iv; 66 unsigned char *iv;
61 int key_len;
62 int iv_len;
63 char *name;
64}; 67};
65struct Mac { 68struct Mac {
66 EVP_MD *md; 69 char *name;
67 int enabled; 70 int enabled;
71 EVP_MD *md;
68 int mac_len; 72 int mac_len;
69 unsigned char *key; 73 unsigned char *key;
70 int key_len; 74 int key_len;
71 char *name;
72}; 75};
73struct Comp { 76struct Comp {
74 int type; 77 int type;
@@ -83,6 +86,7 @@ struct Kex {
83 int server; 86 int server;
84 char *name; 87 char *name;
85 char *hostkeyalg; 88 char *hostkeyalg;
89 int kex_type;
86}; 90};
87 91
88Buffer *kex_init(char *myproposal[PROPOSAL_MAX]); 92Buffer *kex_init(char *myproposal[PROPOSAL_MAX]);
@@ -96,6 +100,8 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX],
96int kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret); 100int kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret);
97void packet_set_kex(Kex *k); 101void packet_set_kex(Kex *k);
98int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub); 102int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub);
103DH *dh_new_group_asc(const char *, const char *);
104DH *dh_new_group(BIGNUM *, BIGNUM *);
99DH *dh_new_group1(); 105DH *dh_new_group1();
100 106
101unsigned char * 107unsigned char *
@@ -109,4 +115,15 @@ kex_hash(
109 BIGNUM *server_dh_pub, 115 BIGNUM *server_dh_pub,
110 BIGNUM *shared_secret); 116 BIGNUM *shared_secret);
111 117
118unsigned char *
119kex_hash_gex(
120 char *client_version_string,
121 char *server_version_string,
122 char *ckexinit, int ckexinitlen,
123 char *skexinit, int skexinitlen,
124 char *serverhostkeyblob, int sbloblen,
125 int minbits, BIGNUM *prime, BIGNUM *gen,
126 BIGNUM *client_dh_pub,
127 BIGNUM *server_dh_pub,
128 BIGNUM *shared_secret);
112#endif 129#endif
diff --git a/log.c b/log.c
index 13033ab42..ce89c59ba 100644
--- a/log.c
+++ b/log.c
@@ -36,7 +36,7 @@
36 */ 36 */
37 37
38#include "includes.h" 38#include "includes.h"
39RCSID("$OpenBSD: log.c,v 1.10 2000/09/12 20:53:10 markus Exp $"); 39RCSID("$OpenBSD: log.c,v 1.11 2000/09/30 16:27:43 markus Exp $");
40 40
41#include "ssh.h" 41#include "ssh.h"
42#include "xmalloc.h" 42#include "xmalloc.h"
@@ -208,6 +208,7 @@ static struct {
208 { "ERROR", SYSLOG_LEVEL_ERROR }, 208 { "ERROR", SYSLOG_LEVEL_ERROR },
209 { "INFO", SYSLOG_LEVEL_INFO }, 209 { "INFO", SYSLOG_LEVEL_INFO },
210 { "VERBOSE", SYSLOG_LEVEL_VERBOSE }, 210 { "VERBOSE", SYSLOG_LEVEL_VERBOSE },
211 { "DEBUG", SYSLOG_LEVEL_DEBUG1 },
211 { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, 212 { "DEBUG1", SYSLOG_LEVEL_DEBUG1 },
212 { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, 213 { "DEBUG2", SYSLOG_LEVEL_DEBUG2 },
213 { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, 214 { "DEBUG3", SYSLOG_LEVEL_DEBUG3 },
diff --git a/myproposal.h b/myproposal.h
index 18db954c5..98060dc35 100644
--- a/myproposal.h
+++ b/myproposal.h
@@ -21,11 +21,15 @@
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */ 23 */
24#define KEX_DEFAULT_KEX "diffie-hellman-group1-sha1" 24#define KEX_DEFAULT_KEX "diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1"
25#define KEX_DEFAULT_PK_ALG "ssh-dss" 25#define KEX_DEFAULT_PK_ALG "ssh-dss"
26#define KEX_DEFAULT_ENCRYPT "3des-cbc,blowfish-cbc,arcfour,cast128-cbc" 26#define KEX_DEFAULT_ENCRYPT \
27 "3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \
28 "aes128-cbc,aes192-cbc,aes256-cbc," \
29 "rijndael128-cbc,rijndael192-cbc,rijndael256-cbc," \
30 "rijndael-cbc@lysator.liu.se"
27#define KEX_DEFAULT_MAC "hmac-sha1,hmac-md5,hmac-ripemd160@openssh.com" 31#define KEX_DEFAULT_MAC "hmac-sha1,hmac-md5,hmac-ripemd160@openssh.com"
28#define KEX_DEFAULT_COMP "zlib,none" 32#define KEX_DEFAULT_COMP "none,zlib"
29#define KEX_DEFAULT_LANG "" 33#define KEX_DEFAULT_LANG ""
30 34
31 35
diff --git a/openbsd-compat.h b/openbsd-compat.h
index 671728fbc..f3ae2f3ff 100644
--- a/openbsd-compat.h
+++ b/openbsd-compat.h
@@ -19,6 +19,7 @@
19#include "bsd-inet_ntoa.h" 19#include "bsd-inet_ntoa.h"
20#include "bsd-strsep.h" 20#include "bsd-strsep.h"
21#include "bsd-strtok.h" 21#include "bsd-strtok.h"
22#include "bsd-vis.h"
22 23
23/* rfc2553 socket API replacements */ 24/* rfc2553 socket API replacements */
24#include "fake-getaddrinfo.h" 25#include "fake-getaddrinfo.h"
diff --git a/packet.c b/packet.c
index 62239eb7d..8c9374fca 100644
--- a/packet.c
+++ b/packet.c
@@ -37,7 +37,7 @@
37 */ 37 */
38 38
39#include "includes.h" 39#include "includes.h"
40RCSID("$OpenBSD: packet.c,v 1.35 2000/09/07 20:27:52 deraadt Exp $"); 40RCSID("$OpenBSD: packet.c,v 1.38 2000/10/12 14:21:12 markus Exp $");
41 41
42#include "xmalloc.h" 42#include "xmalloc.h"
43#include "buffer.h" 43#include "buffer.h"
@@ -45,7 +45,6 @@ RCSID("$OpenBSD: packet.c,v 1.35 2000/09/07 20:27:52 deraadt Exp $");
45#include "bufaux.h" 45#include "bufaux.h"
46#include "ssh.h" 46#include "ssh.h"
47#include "crc32.h" 47#include "crc32.h"
48#include "cipher.h"
49#include "getput.h" 48#include "getput.h"
50 49
51#include "compress.h" 50#include "compress.h"
@@ -59,6 +58,7 @@ RCSID("$OpenBSD: packet.c,v 1.35 2000/09/07 20:27:52 deraadt Exp $");
59#include <openssl/dh.h> 58#include <openssl/dh.h>
60#include <openssl/hmac.h> 59#include <openssl/hmac.h>
61#include "buffer.h" 60#include "buffer.h"
61#include "cipher.h"
62#include "kex.h" 62#include "kex.h"
63#include "hmac.h" 63#include "hmac.h"
64 64
@@ -161,11 +161,14 @@ packet_set_ssh2_format(void)
161void 161void
162packet_set_connection(int fd_in, int fd_out) 162packet_set_connection(int fd_in, int fd_out)
163{ 163{
164 Cipher *none = cipher_by_name("none");
165 if (none == NULL)
166 fatal("packet_set_connection: cannot load cipher 'none'");
164 connection_in = fd_in; 167 connection_in = fd_in;
165 connection_out = fd_out; 168 connection_out = fd_out;
166 cipher_type = SSH_CIPHER_NONE; 169 cipher_type = SSH_CIPHER_NONE;
167 cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *) "", 0); 170 cipher_init(&send_context, none, (unsigned char *) "", 0, NULL, 0);
168 cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *) "", 0); 171 cipher_init(&receive_context, none, (unsigned char *) "", 0, NULL, 0);
169 if (!initialized) { 172 if (!initialized) {
170 initialized = 1; 173 initialized = 1;
171 buffer_init(&input); 174 buffer_init(&input);
@@ -326,28 +329,18 @@ packet_encrypt(CipherContext * cc, void *dest, void *src,
326 */ 329 */
327 330
328void 331void
329packet_decrypt(CipherContext * cc, void *dest, void *src, 332packet_decrypt(CipherContext *context, void *dest, void *src, unsigned int bytes)
330 unsigned int bytes)
331{ 333{
332 int i;
333
334 if ((bytes % 8) != 0)
335 fatal("packet_decrypt: bad ciphertext length %d", bytes);
336
337 /* 334 /*
338 * Cryptographic attack detector for ssh - Modifications for packet.c 335 * Cryptographic attack detector for ssh - Modifications for packet.c
339 * (C)1998 CORE-SDI, Buenos Aires Argentina Ariel Futoransky(futo@core-sdi.com) 336 * (C)1998 CORE-SDI, Buenos Aires Argentina Ariel Futoransky(futo@core-sdi.com)
340 */ 337 */
341 338 if (!compat20 &&
342 if (cc->type == SSH_CIPHER_NONE || compat20) { 339 context->cipher->number != SSH_CIPHER_NONE &&
343 i = DEATTACK_OK; 340 detect_attack(src, bytes, NULL) == DEATTACK_DETECTED)
344 } else {
345 i = detect_attack(src, bytes, NULL);
346 }
347 if (i == DEATTACK_DETECTED)
348 packet_disconnect("crc32 compensation attack: network attack detected"); 341 packet_disconnect("crc32 compensation attack: network attack detected");
349 342
350 cipher_decrypt(cc, dest, src, bytes); 343 cipher_decrypt(context, dest, src, bytes);
351} 344}
352 345
353/* 346/*
@@ -358,14 +351,15 @@ packet_decrypt(CipherContext * cc, void *dest, void *src,
358 351
359void 352void
360packet_set_encryption_key(const unsigned char *key, unsigned int keylen, 353packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
361 int cipher) 354 int number)
362{ 355{
356 Cipher *cipher = cipher_by_number(number);
357 if (cipher == NULL)
358 fatal("packet_set_encryption_key: unknown cipher number %d", number);
363 if (keylen < 20) 359 if (keylen < 20)
364 fatal("keylen too small: %d", keylen); 360 fatal("packet_set_encryption_key: keylen too small: %d", keylen);
365 361 cipher_init(&receive_context, cipher, key, keylen, NULL, 0);
366 /* All other ciphers use the same key in both directions for now. */ 362 cipher_init(&send_context, cipher, key, keylen, NULL, 0);
367 cipher_set_key(&receive_context, cipher, key, keylen);
368 cipher_set_key(&send_context, cipher, key, keylen);
369} 363}
370 364
371/* Starts constructing a packet to send. */ 365/* Starts constructing a packet to send. */
@@ -553,7 +547,7 @@ packet_send2()
553 mac = &kex->mac[MODE_OUT]; 547 mac = &kex->mac[MODE_OUT];
554 comp = &kex->comp[MODE_OUT]; 548 comp = &kex->comp[MODE_OUT];
555 } 549 }
556 block_size = enc ? enc->block_size : 8; 550 block_size = enc ? enc->cipher->block_size : 8;
557 551
558 cp = buffer_ptr(&outgoing_packet); 552 cp = buffer_ptr(&outgoing_packet);
559 type = cp[5] & 0xff; 553 type = cp[5] & 0xff;
@@ -588,7 +582,7 @@ packet_send2()
588 if (padlen < 4) 582 if (padlen < 4)
589 padlen += block_size; 583 padlen += block_size;
590 buffer_append_space(&outgoing_packet, &cp, padlen); 584 buffer_append_space(&outgoing_packet, &cp, padlen);
591 if (enc && enc->type != SSH_CIPHER_NONE) { 585 if (enc && enc->cipher->number != SSH_CIPHER_NONE) {
592 /* random padding */ 586 /* random padding */
593 for (i = 0; i < padlen; i++) { 587 for (i = 0; i < padlen; i++) {
594 if (i % 4 == 0) 588 if (i % 4 == 0)
@@ -614,7 +608,7 @@ packet_send2()
614 buffer_len(&outgoing_packet), 608 buffer_len(&outgoing_packet),
615 mac->key, mac->key_len 609 mac->key, mac->key_len
616 ); 610 );
617 DBG(debug("done calc HMAC out #%d", seqnr)); 611 DBG(debug("done calc MAC out #%d", seqnr));
618 } 612 }
619 /* encrypt packet and append to output buffer. */ 613 /* encrypt packet and append to output buffer. */
620 buffer_append_space(&output, &cp, buffer_len(&outgoing_packet)); 614 buffer_append_space(&output, &cp, buffer_len(&outgoing_packet));
@@ -637,10 +631,10 @@ packet_send2()
637 fatal("packet_send2: no KEX"); 631 fatal("packet_send2: no KEX");
638 if (mac->md != NULL) 632 if (mac->md != NULL)
639 mac->enabled = 1; 633 mac->enabled = 1;
640 DBG(debug("cipher_set_key_iv send_context")); 634 DBG(debug("cipher_init send_context"));
641 cipher_set_key_iv(&send_context, enc->type, 635 cipher_init(&send_context, enc->cipher,
642 enc->key, enc->key_len, 636 enc->key, enc->cipher->key_len,
643 enc->iv, enc->iv_len); 637 enc->iv, enc->cipher->block_size);
644 clear_enc_keys(enc, kex->we_need); 638 clear_enc_keys(enc, kex->we_need);
645 if (comp->type != 0 && comp->enabled == 0) { 639 if (comp->type != 0 && comp->enabled == 0) {
646 comp->enabled = 1; 640 comp->enabled = 1;
@@ -841,7 +835,7 @@ packet_read_poll2(int *payload_len_ptr)
841 comp = &kex->comp[MODE_IN]; 835 comp = &kex->comp[MODE_IN];
842 } 836 }
843 maclen = mac && mac->enabled ? mac->mac_len : 0; 837 maclen = mac && mac->enabled ? mac->mac_len : 0;
844 block_size = enc ? enc->block_size : 8; 838 block_size = enc ? enc->cipher->block_size : 8;
845 839
846 if (packet_length == 0) { 840 if (packet_length == 0) {
847 /* 841 /*
@@ -894,8 +888,8 @@ packet_read_poll2(int *payload_len_ptr)
894 mac->key, mac->key_len 888 mac->key, mac->key_len
895 ); 889 );
896 if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 890 if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
897 packet_disconnect("Corrupted HMAC on input."); 891 packet_disconnect("Corrupted MAC on input.");
898 DBG(debug("HMAC #%d ok", seqnr)); 892 DBG(debug("MAC #%d ok", seqnr));
899 buffer_consume(&input, mac->mac_len); 893 buffer_consume(&input, mac->mac_len);
900 } 894 }
901 if (++seqnr == 0) 895 if (++seqnr == 0)
@@ -939,10 +933,10 @@ packet_read_poll2(int *payload_len_ptr)
939 fatal("packet_read_poll2: no KEX"); 933 fatal("packet_read_poll2: no KEX");
940 if (mac->md != NULL) 934 if (mac->md != NULL)
941 mac->enabled = 1; 935 mac->enabled = 1;
942 DBG(debug("cipher_set_key_iv receive_context")); 936 DBG(debug("cipher_init receive_context"));
943 cipher_set_key_iv(&receive_context, enc->type, 937 cipher_init(&receive_context, enc->cipher,
944 enc->key, enc->key_len, 938 enc->key, enc->cipher->key_len,
945 enc->iv, enc->iv_len); 939 enc->iv, enc->cipher->block_size);
946 clear_enc_keys(enc, kex->we_need); 940 clear_enc_keys(enc, kex->we_need);
947 if (comp->type != 0 && comp->enabled == 0) { 941 if (comp->type != 0 && comp->enabled == 0) {
948 comp->enabled = 1; 942 comp->enabled = 1;
diff --git a/readconf.c b/readconf.c
index 4f4a16de8..c6fdd5308 100644
--- a/readconf.c
+++ b/readconf.c
@@ -12,10 +12,9 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$OpenBSD: readconf.c,v 1.47 2000/09/07 21:13:37 markus Exp $"); 15RCSID("$OpenBSD: readconf.c,v 1.49 2000/10/11 20:27:23 markus Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "cipher.h"
19#include "readconf.h" 18#include "readconf.h"
20#include "match.h" 19#include "match.h"
21#include "xmalloc.h" 20#include "xmalloc.h"
@@ -103,7 +102,8 @@ typedef enum {
103 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 102 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
104 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication, 103 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
105 oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2, 104 oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2,
106 oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication 105 oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication,
106 oKbdInteractiveAuthentication, oKbdInteractiveDevices
107} OpCodes; 107} OpCodes;
108 108
109/* Textual representations of the tokens. */ 109/* Textual representations of the tokens. */
@@ -119,6 +119,8 @@ static struct {
119 { "useprivilegedport", oUsePrivilegedPort }, 119 { "useprivilegedport", oUsePrivilegedPort },
120 { "rhostsauthentication", oRhostsAuthentication }, 120 { "rhostsauthentication", oRhostsAuthentication },
121 { "passwordauthentication", oPasswordAuthentication }, 121 { "passwordauthentication", oPasswordAuthentication },
122 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
123 { "kbdinteractivedevices", oKbdInteractiveDevices },
122 { "rsaauthentication", oRSAAuthentication }, 124 { "rsaauthentication", oRSAAuthentication },
123 { "dsaauthentication", oDSAAuthentication }, 125 { "dsaauthentication", oDSAAuthentication },
124 { "skeyauthentication", oSkeyAuthentication }, 126 { "skeyauthentication", oSkeyAuthentication },
@@ -290,6 +292,14 @@ parse_flag:
290 intptr = &options->password_authentication; 292 intptr = &options->password_authentication;
291 goto parse_flag; 293 goto parse_flag;
292 294
295 case oKbdInteractiveAuthentication:
296 intptr = &options->kbd_interactive_authentication;
297 goto parse_flag;
298
299 case oKbdInteractiveDevices:
300 charptr = &options->kbd_interactive_devices;
301 goto parse_string;
302
293 case oDSAAuthentication: 303 case oDSAAuthentication:
294 intptr = &options->dsa_authentication; 304 intptr = &options->dsa_authentication;
295 goto parse_flag; 305 goto parse_flag;
@@ -664,6 +674,8 @@ initialize_options(Options * options)
664 options->afs_token_passing = -1; 674 options->afs_token_passing = -1;
665#endif 675#endif
666 options->password_authentication = -1; 676 options->password_authentication = -1;
677 options->kbd_interactive_authentication = -1;
678 options->kbd_interactive_devices = NULL;
667 options->rhosts_rsa_authentication = -1; 679 options->rhosts_rsa_authentication = -1;
668 options->fallback_to_rsh = -1; 680 options->fallback_to_rsh = -1;
669 options->use_rsh = -1; 681 options->use_rsh = -1;
@@ -734,6 +746,8 @@ fill_default_options(Options * options)
734#endif /* AFS */ 746#endif /* AFS */
735 if (options->password_authentication == -1) 747 if (options->password_authentication == -1)
736 options->password_authentication = 1; 748 options->password_authentication = 1;
749 if (options->kbd_interactive_authentication == -1)
750 options->kbd_interactive_authentication = 0;
737 if (options->rhosts_rsa_authentication == -1) 751 if (options->rhosts_rsa_authentication == -1)
738 options->rhosts_rsa_authentication = 1; 752 options->rhosts_rsa_authentication = 1;
739 if (options->fallback_to_rsh == -1) 753 if (options->fallback_to_rsh == -1)
diff --git a/readconf.h b/readconf.h
index 23df57b42..e94213fa1 100644
--- a/readconf.h
+++ b/readconf.h
@@ -11,7 +11,7 @@
11 * called by a name other than "ssh" or "Secure Shell". 11 * called by a name other than "ssh" or "Secure Shell".
12 */ 12 */
13 13
14/* RCSID("$OpenBSD: readconf.h,v 1.21 2000/09/07 20:27:53 deraadt Exp $"); */ 14/* RCSID("$OpenBSD: readconf.h,v 1.22 2000/10/11 20:14:39 markus Exp $"); */
15 15
16#ifndef READCONF_H 16#ifndef READCONF_H
17#define READCONF_H 17#define READCONF_H
@@ -47,6 +47,8 @@ typedef struct {
47#endif 47#endif
48 int password_authentication; /* Try password 48 int password_authentication; /* Try password
49 * authentication. */ 49 * authentication. */
50 int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
51 char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
50 int fallback_to_rsh;/* Use rsh if cannot connect with ssh. */ 52 int fallback_to_rsh;/* Use rsh if cannot connect with ssh. */
51 int use_rsh; /* Always use rsh (don\'t try ssh). */ 53 int use_rsh; /* Always use rsh (don\'t try ssh). */
52 int batch_mode; /* Batch mode: do not ask for passwords. */ 54 int batch_mode; /* Batch mode: do not ask for passwords. */
diff --git a/readpass.c b/readpass.c
index c38292f15..f3a7dcbed 100644
--- a/readpass.c
+++ b/readpass.c
@@ -32,88 +32,24 @@
32 */ 32 */
33 33
34#include "includes.h" 34#include "includes.h"
35RCSID("$OpenBSD: readpass.c,v 1.11 2000/06/20 01:39:44 markus Exp $"); 35RCSID("$OpenBSD: readpass.c,v 1.12 2000/10/11 20:14:39 markus Exp $");
36 36
37#include "xmalloc.h" 37#include "xmalloc.h"
38#include "ssh.h" 38#include "ssh.h"
39 39#include "cli.h"
40volatile int intr;
41
42void
43intcatch()
44{
45 intr = 1;
46}
47 40
48/* 41/*
49 * Reads a passphrase from /dev/tty with echo turned off. Returns the 42 * Reads a passphrase from /dev/tty with echo turned off. Returns the
50 * passphrase (allocated with xmalloc), being very careful to ensure that 43 * passphrase (allocated with xmalloc), being very careful to ensure that
51 * no other userland buffer is storing the password. 44 * no other userland buffer is storing the password.
52 */ 45 */
46/*
47 * Note: the funcationallity of this routing has been moved to
48 * cli_read_passphrase(). This routing remains to maintain
49 * compatibility with existing code.
50 */
53char * 51char *
54read_passphrase(const char *prompt, int from_stdin) 52read_passphrase(char *prompt, int from_stdin)
55{ 53{
56 char buf[1024], *p, ch; 54 return cli_read_passphrase(prompt, from_stdin, 0);
57 struct termios tio, saved_tio;
58 sigset_t oset, nset;
59 struct sigaction sa, osa;
60 int input, output, echo = 0;
61
62 if (from_stdin) {
63 input = STDIN_FILENO;
64 output = STDERR_FILENO;
65 } else
66 input = output = open("/dev/tty", O_RDWR);
67
68 if (input == -1)
69 fatal("You have no controlling tty. Cannot read passphrase.\n");
70
71 /* block signals, get terminal modes and turn off echo */
72 sigemptyset(&nset);
73 sigaddset(&nset, SIGTSTP);
74 (void) sigprocmask(SIG_BLOCK, &nset, &oset);
75 memset(&sa, 0, sizeof(sa));
76 sa.sa_handler = intcatch;
77 (void) sigaction(SIGINT, &sa, &osa);
78
79 intr = 0;
80
81 if (tcgetattr(input, &saved_tio) == 0 && (saved_tio.c_lflag & ECHO)) {
82 echo = 1;
83 tio = saved_tio;
84 tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
85 (void) tcsetattr(input, TCSANOW, &tio);
86 }
87
88 fflush(stdout);
89
90 (void)write(output, prompt, strlen(prompt));
91 for (p = buf; read(input, &ch, 1) == 1 && ch != '\n';) {
92 if (intr)
93 break;
94 if (p < buf + sizeof(buf) - 1)
95 *p++ = ch;
96 }
97 *p = '\0';
98 if (!intr)
99 (void)write(output, "\n", 1);
100
101 /* restore terminal modes and allow signals */
102 if (echo)
103 tcsetattr(input, TCSANOW, &saved_tio);
104 (void) sigprocmask(SIG_SETMASK, &oset, NULL);
105 (void) sigaction(SIGINT, &osa, NULL);
106
107 if (intr) {
108 kill(getpid(), SIGINT);
109 sigemptyset(&nset);
110 /* XXX tty has not neccessarily drained by now? */
111 sigsuspend(&nset);
112 }
113
114 if (!from_stdin)
115 (void)close(input);
116 p = xstrdup(buf);
117 memset(buf, 0, sizeof(buf));
118 return (p);
119} 55}
diff --git a/rijndael.c b/rijndael.c
new file mode 100644
index 000000000..bb592bc2f
--- /dev/null
+++ b/rijndael.c
@@ -0,0 +1,493 @@
1/* $OpenBSD: rijndael.c,v 1.1 2000/10/13 18:59:14 markus Exp $ */
2
3/* This is an independent implementation of the encryption algorithm: */
4/* */
5/* RIJNDAEL by Joan Daemen and Vincent Rijmen */
6/* */
7/* which is a candidate algorithm in the Advanced Encryption Standard */
8/* programme of the US National Institute of Standards and Technology. */
9/* */
10/* Copyright in this implementation is held by Dr B R Gladman but I */
11/* hereby give permission for its free direct or derivative use subject */
12/* to acknowledgment of its origin and compliance with any conditions */
13/* that the originators of the algorithm place on its exploitation. */
14/* */
15/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */
16
17/* Timing data for Rijndael (rijndael.c)
18
19Algorithm: rijndael (rijndael.c)
20
21128 bit key:
22Key Setup: 305/1389 cycles (encrypt/decrypt)
23Encrypt: 374 cycles = 68.4 mbits/sec
24Decrypt: 352 cycles = 72.7 mbits/sec
25Mean: 363 cycles = 70.5 mbits/sec
26
27192 bit key:
28Key Setup: 277/1595 cycles (encrypt/decrypt)
29Encrypt: 439 cycles = 58.3 mbits/sec
30Decrypt: 425 cycles = 60.2 mbits/sec
31Mean: 432 cycles = 59.3 mbits/sec
32
33256 bit key:
34Key Setup: 374/1960 cycles (encrypt/decrypt)
35Encrypt: 502 cycles = 51.0 mbits/sec
36Decrypt: 498 cycles = 51.4 mbits/sec
37Mean: 500 cycles = 51.2 mbits/sec
38
39*/
40
41#include <sys/types.h>
42#include "rijndael.h"
43
44void gen_tabs __P((void));
45
46/* 3. Basic macros for speeding up generic operations */
47
48/* Circular rotate of 32 bit values */
49
50#define rotr(x,n) (((x) >> ((int)(n))) | ((x) << (32 - (int)(n))))
51#define rotl(x,n) (((x) << ((int)(n))) | ((x) >> (32 - (int)(n))))
52
53/* Invert byte order in a 32 bit variable */
54
55#define bswap(x) (rotl(x, 8) & 0x00ff00ff | rotr(x, 8) & 0xff00ff00)
56
57/* Extract byte from a 32 bit quantity (little endian notation) */
58
59#define byte(x,n) ((u1byte)((x) >> (8 * n)))
60
61#if BYTE_ORDER != LITTLE_ENDIAN
62#define BLOCK_SWAP
63#endif
64
65/* For inverting byte order in input/output 32 bit words if needed */
66
67#ifdef BLOCK_SWAP
68#define BYTE_SWAP
69#define WORD_SWAP
70#endif
71
72#ifdef BYTE_SWAP
73#define io_swap(x) bswap(x)
74#else
75#define io_swap(x) (x)
76#endif
77
78/* For inverting the byte order of input/output blocks if needed */
79
80#ifdef WORD_SWAP
81
82#define get_block(x) \
83 ((u4byte*)(x))[0] = io_swap(in_blk[3]); \
84 ((u4byte*)(x))[1] = io_swap(in_blk[2]); \
85 ((u4byte*)(x))[2] = io_swap(in_blk[1]); \
86 ((u4byte*)(x))[3] = io_swap(in_blk[0])
87
88#define put_block(x) \
89 out_blk[3] = io_swap(((u4byte*)(x))[0]); \
90 out_blk[2] = io_swap(((u4byte*)(x))[1]); \
91 out_blk[1] = io_swap(((u4byte*)(x))[2]); \
92 out_blk[0] = io_swap(((u4byte*)(x))[3])
93
94#define get_key(x,len) \
95 ((u4byte*)(x))[4] = ((u4byte*)(x))[5] = \
96 ((u4byte*)(x))[6] = ((u4byte*)(x))[7] = 0; \
97 switch((((len) + 63) / 64)) { \
98 case 2: \
99 ((u4byte*)(x))[0] = io_swap(in_key[3]); \
100 ((u4byte*)(x))[1] = io_swap(in_key[2]); \
101 ((u4byte*)(x))[2] = io_swap(in_key[1]); \
102 ((u4byte*)(x))[3] = io_swap(in_key[0]); \
103 break; \
104 case 3: \
105 ((u4byte*)(x))[0] = io_swap(in_key[5]); \
106 ((u4byte*)(x))[1] = io_swap(in_key[4]); \
107 ((u4byte*)(x))[2] = io_swap(in_key[3]); \
108 ((u4byte*)(x))[3] = io_swap(in_key[2]); \
109 ((u4byte*)(x))[4] = io_swap(in_key[1]); \
110 ((u4byte*)(x))[5] = io_swap(in_key[0]); \
111 break; \
112 case 4: \
113 ((u4byte*)(x))[0] = io_swap(in_key[7]); \
114 ((u4byte*)(x))[1] = io_swap(in_key[6]); \
115 ((u4byte*)(x))[2] = io_swap(in_key[5]); \
116 ((u4byte*)(x))[3] = io_swap(in_key[4]); \
117 ((u4byte*)(x))[4] = io_swap(in_key[3]); \
118 ((u4byte*)(x))[5] = io_swap(in_key[2]); \
119 ((u4byte*)(x))[6] = io_swap(in_key[1]); \
120 ((u4byte*)(x))[7] = io_swap(in_key[0]); \
121 }
122
123#else
124
125#define get_block(x) \
126 ((u4byte*)(x))[0] = io_swap(in_blk[0]); \
127 ((u4byte*)(x))[1] = io_swap(in_blk[1]); \
128 ((u4byte*)(x))[2] = io_swap(in_blk[2]); \
129 ((u4byte*)(x))[3] = io_swap(in_blk[3])
130
131#define put_block(x) \
132 out_blk[0] = io_swap(((u4byte*)(x))[0]); \
133 out_blk[1] = io_swap(((u4byte*)(x))[1]); \
134 out_blk[2] = io_swap(((u4byte*)(x))[2]); \
135 out_blk[3] = io_swap(((u4byte*)(x))[3])
136
137#define get_key(x,len) \
138 ((u4byte*)(x))[4] = ((u4byte*)(x))[5] = \
139 ((u4byte*)(x))[6] = ((u4byte*)(x))[7] = 0; \
140 switch((((len) + 63) / 64)) { \
141 case 4: \
142 ((u4byte*)(x))[6] = io_swap(in_key[6]); \
143 ((u4byte*)(x))[7] = io_swap(in_key[7]); \
144 case 3: \
145 ((u4byte*)(x))[4] = io_swap(in_key[4]); \
146 ((u4byte*)(x))[5] = io_swap(in_key[5]); \
147 case 2: \
148 ((u4byte*)(x))[0] = io_swap(in_key[0]); \
149 ((u4byte*)(x))[1] = io_swap(in_key[1]); \
150 ((u4byte*)(x))[2] = io_swap(in_key[2]); \
151 ((u4byte*)(x))[3] = io_swap(in_key[3]); \
152 }
153
154#endif
155
156#define LARGE_TABLES
157
158u1byte pow_tab[256];
159u1byte log_tab[256];
160u1byte sbx_tab[256];
161u1byte isb_tab[256];
162u4byte rco_tab[ 10];
163u4byte ft_tab[4][256];
164u4byte it_tab[4][256];
165
166#ifdef LARGE_TABLES
167 u4byte fl_tab[4][256];
168 u4byte il_tab[4][256];
169#endif
170
171u4byte tab_gen = 0;
172
173#define ff_mult(a,b) (a && b ? pow_tab[(log_tab[a] + log_tab[b]) % 255] : 0)
174
175#define f_rn(bo, bi, n, k) \
176 bo[n] = ft_tab[0][byte(bi[n],0)] ^ \
177 ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
178 ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
179 ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
180
181#define i_rn(bo, bi, n, k) \
182 bo[n] = it_tab[0][byte(bi[n],0)] ^ \
183 it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
184 it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
185 it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
186
187#ifdef LARGE_TABLES
188
189#define ls_box(x) \
190 ( fl_tab[0][byte(x, 0)] ^ \
191 fl_tab[1][byte(x, 1)] ^ \
192 fl_tab[2][byte(x, 2)] ^ \
193 fl_tab[3][byte(x, 3)] )
194
195#define f_rl(bo, bi, n, k) \
196 bo[n] = fl_tab[0][byte(bi[n],0)] ^ \
197 fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
198 fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
199 fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
200
201#define i_rl(bo, bi, n, k) \
202 bo[n] = il_tab[0][byte(bi[n],0)] ^ \
203 il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
204 il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
205 il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
206
207#else
208
209#define ls_box(x) \
210 ((u4byte)sbx_tab[byte(x, 0)] << 0) ^ \
211 ((u4byte)sbx_tab[byte(x, 1)] << 8) ^ \
212 ((u4byte)sbx_tab[byte(x, 2)] << 16) ^ \
213 ((u4byte)sbx_tab[byte(x, 3)] << 24)
214
215#define f_rl(bo, bi, n, k) \
216 bo[n] = (u4byte)sbx_tab[byte(bi[n],0)] ^ \
217 rotl(((u4byte)sbx_tab[byte(bi[(n + 1) & 3],1)]), 8) ^ \
218 rotl(((u4byte)sbx_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \
219 rotl(((u4byte)sbx_tab[byte(bi[(n + 3) & 3],3)]), 24) ^ *(k + n)
220
221#define i_rl(bo, bi, n, k) \
222 bo[n] = (u4byte)isb_tab[byte(bi[n],0)] ^ \
223 rotl(((u4byte)isb_tab[byte(bi[(n + 3) & 3],1)]), 8) ^ \
224 rotl(((u4byte)isb_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \
225 rotl(((u4byte)isb_tab[byte(bi[(n + 1) & 3],3)]), 24) ^ *(k + n)
226
227#endif
228
229void
230gen_tabs(void)
231{
232 u4byte i, t;
233 u1byte p, q;
234
235 /* log and power tables for GF(2**8) finite field with */
236 /* 0x11b as modular polynomial - the simplest prmitive */
237 /* root is 0x11, used here to generate the tables */
238
239 for(i = 0,p = 1; i < 256; ++i) {
240 pow_tab[i] = (u1byte)p; log_tab[p] = (u1byte)i;
241
242 p = p ^ (p << 1) ^ (p & 0x80 ? 0x01b : 0);
243 }
244
245 log_tab[1] = 0; p = 1;
246
247 for(i = 0; i < 10; ++i) {
248 rco_tab[i] = p;
249
250 p = (p << 1) ^ (p & 0x80 ? 0x1b : 0);
251 }
252
253 /* note that the affine byte transformation matrix in */
254 /* rijndael specification is in big endian format with */
255 /* bit 0 as the most significant bit. In the remainder */
256 /* of the specification the bits are numbered from the */
257 /* least significant end of a byte. */
258
259 for(i = 0; i < 256; ++i) {
260 p = (i ? pow_tab[255 - log_tab[i]] : 0); q = p;
261 q = (q >> 7) | (q << 1); p ^= q;
262 q = (q >> 7) | (q << 1); p ^= q;
263 q = (q >> 7) | (q << 1); p ^= q;
264 q = (q >> 7) | (q << 1); p ^= q ^ 0x63;
265 sbx_tab[i] = (u1byte)p; isb_tab[p] = (u1byte)i;
266 }
267
268 for(i = 0; i < 256; ++i) {
269 p = sbx_tab[i];
270
271#ifdef LARGE_TABLES
272
273 t = p; fl_tab[0][i] = t;
274 fl_tab[1][i] = rotl(t, 8);
275 fl_tab[2][i] = rotl(t, 16);
276 fl_tab[3][i] = rotl(t, 24);
277#endif
278 t = ((u4byte)ff_mult(2, p)) |
279 ((u4byte)p << 8) |
280 ((u4byte)p << 16) |
281 ((u4byte)ff_mult(3, p) << 24);
282
283 ft_tab[0][i] = t;
284 ft_tab[1][i] = rotl(t, 8);
285 ft_tab[2][i] = rotl(t, 16);
286 ft_tab[3][i] = rotl(t, 24);
287
288 p = isb_tab[i];
289
290#ifdef LARGE_TABLES
291
292 t = p; il_tab[0][i] = t;
293 il_tab[1][i] = rotl(t, 8);
294 il_tab[2][i] = rotl(t, 16);
295 il_tab[3][i] = rotl(t, 24);
296#endif
297 t = ((u4byte)ff_mult(14, p)) |
298 ((u4byte)ff_mult( 9, p) << 8) |
299 ((u4byte)ff_mult(13, p) << 16) |
300 ((u4byte)ff_mult(11, p) << 24);
301
302 it_tab[0][i] = t;
303 it_tab[1][i] = rotl(t, 8);
304 it_tab[2][i] = rotl(t, 16);
305 it_tab[3][i] = rotl(t, 24);
306 }
307
308 tab_gen = 1;
309};
310
311#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
312
313#define imix_col(y,x) \
314 u = star_x(x); \
315 v = star_x(u); \
316 w = star_x(v); \
317 t = w ^ (x); \
318 (y) = u ^ v ^ w; \
319 (y) ^= rotr(u ^ t, 8) ^ \
320 rotr(v ^ t, 16) ^ \
321 rotr(t,24)
322
323/* initialise the key schedule from the user supplied key */
324
325#define loop4(i) \
326{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \
327 t ^= e_key[4 * i]; e_key[4 * i + 4] = t; \
328 t ^= e_key[4 * i + 1]; e_key[4 * i + 5] = t; \
329 t ^= e_key[4 * i + 2]; e_key[4 * i + 6] = t; \
330 t ^= e_key[4 * i + 3]; e_key[4 * i + 7] = t; \
331}
332
333#define loop6(i) \
334{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \
335 t ^= e_key[6 * i]; e_key[6 * i + 6] = t; \
336 t ^= e_key[6 * i + 1]; e_key[6 * i + 7] = t; \
337 t ^= e_key[6 * i + 2]; e_key[6 * i + 8] = t; \
338 t ^= e_key[6 * i + 3]; e_key[6 * i + 9] = t; \
339 t ^= e_key[6 * i + 4]; e_key[6 * i + 10] = t; \
340 t ^= e_key[6 * i + 5]; e_key[6 * i + 11] = t; \
341}
342
343#define loop8(i) \
344{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \
345 t ^= e_key[8 * i]; e_key[8 * i + 8] = t; \
346 t ^= e_key[8 * i + 1]; e_key[8 * i + 9] = t; \
347 t ^= e_key[8 * i + 2]; e_key[8 * i + 10] = t; \
348 t ^= e_key[8 * i + 3]; e_key[8 * i + 11] = t; \
349 t = e_key[8 * i + 4] ^ ls_box(t); \
350 e_key[8 * i + 12] = t; \
351 t ^= e_key[8 * i + 5]; e_key[8 * i + 13] = t; \
352 t ^= e_key[8 * i + 6]; e_key[8 * i + 14] = t; \
353 t ^= e_key[8 * i + 7]; e_key[8 * i + 15] = t; \
354}
355
356rijndael_ctx *
357rijndael_set_key(rijndael_ctx *ctx, const u4byte *in_key, const u4byte key_len,
358 int encrypt)
359{
360 u4byte i, t, u, v, w;
361 u4byte *e_key = ctx->e_key;
362 u4byte *d_key = ctx->d_key;
363
364 ctx->decrypt = !encrypt;
365
366 if(!tab_gen)
367 gen_tabs();
368
369 ctx->k_len = (key_len + 31) / 32;
370
371 e_key[0] = in_key[0]; e_key[1] = in_key[1];
372 e_key[2] = in_key[2]; e_key[3] = in_key[3];
373
374 switch(ctx->k_len) {
375 case 4: t = e_key[3];
376 for(i = 0; i < 10; ++i)
377 loop4(i);
378 break;
379
380 case 6: e_key[4] = in_key[4]; t = e_key[5] = in_key[5];
381 for(i = 0; i < 8; ++i)
382 loop6(i);
383 break;
384
385 case 8: e_key[4] = in_key[4]; e_key[5] = in_key[5];
386 e_key[6] = in_key[6]; t = e_key[7] = in_key[7];
387 for(i = 0; i < 7; ++i)
388 loop8(i);
389 break;
390 }
391
392 if (!encrypt) {
393 d_key[0] = e_key[0]; d_key[1] = e_key[1];
394 d_key[2] = e_key[2]; d_key[3] = e_key[3];
395
396 for(i = 4; i < 4 * ctx->k_len + 24; ++i) {
397 imix_col(d_key[i], e_key[i]);
398 }
399 }
400
401 return ctx;
402};
403
404/* encrypt a block of text */
405
406#define f_nround(bo, bi, k) \
407 f_rn(bo, bi, 0, k); \
408 f_rn(bo, bi, 1, k); \
409 f_rn(bo, bi, 2, k); \
410 f_rn(bo, bi, 3, k); \
411 k += 4
412
413#define f_lround(bo, bi, k) \
414 f_rl(bo, bi, 0, k); \
415 f_rl(bo, bi, 1, k); \
416 f_rl(bo, bi, 2, k); \
417 f_rl(bo, bi, 3, k)
418
419void
420rijndael_encrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk)
421{
422 u4byte k_len = ctx->k_len;
423 u4byte *e_key = ctx->e_key;
424 u4byte b0[4], b1[4], *kp;
425
426 b0[0] = in_blk[0] ^ e_key[0]; b0[1] = in_blk[1] ^ e_key[1];
427 b0[2] = in_blk[2] ^ e_key[2]; b0[3] = in_blk[3] ^ e_key[3];
428
429 kp = e_key + 4;
430
431 if(k_len > 6) {
432 f_nround(b1, b0, kp); f_nround(b0, b1, kp);
433 }
434
435 if(k_len > 4) {
436 f_nround(b1, b0, kp); f_nround(b0, b1, kp);
437 }
438
439 f_nround(b1, b0, kp); f_nround(b0, b1, kp);
440 f_nround(b1, b0, kp); f_nround(b0, b1, kp);
441 f_nround(b1, b0, kp); f_nround(b0, b1, kp);
442 f_nround(b1, b0, kp); f_nround(b0, b1, kp);
443 f_nround(b1, b0, kp); f_lround(b0, b1, kp);
444
445 out_blk[0] = b0[0]; out_blk[1] = b0[1];
446 out_blk[2] = b0[2]; out_blk[3] = b0[3];
447};
448
449/* decrypt a block of text */
450
451#define i_nround(bo, bi, k) \
452 i_rn(bo, bi, 0, k); \
453 i_rn(bo, bi, 1, k); \
454 i_rn(bo, bi, 2, k); \
455 i_rn(bo, bi, 3, k); \
456 k -= 4
457
458#define i_lround(bo, bi, k) \
459 i_rl(bo, bi, 0, k); \
460 i_rl(bo, bi, 1, k); \
461 i_rl(bo, bi, 2, k); \
462 i_rl(bo, bi, 3, k)
463
464void
465rijndael_decrypt(rijndael_ctx *ctx, const u4byte *in_blk, u4byte *out_blk)
466{
467 u4byte b0[4], b1[4], *kp;
468 u4byte k_len = ctx->k_len;
469 u4byte *e_key = ctx->e_key;
470 u4byte *d_key = ctx->d_key;
471
472 b0[0] = in_blk[0] ^ e_key[4 * k_len + 24]; b0[1] = in_blk[1] ^ e_key[4 * k_len + 25];
473 b0[2] = in_blk[2] ^ e_key[4 * k_len + 26]; b0[3] = in_blk[3] ^ e_key[4 * k_len + 27];
474
475 kp = d_key + 4 * (k_len + 5);
476
477 if(k_len > 6) {
478 i_nround(b1, b0, kp); i_nround(b0, b1, kp);
479 }
480
481 if(k_len > 4) {
482 i_nround(b1, b0, kp); i_nround(b0, b1, kp);
483 }
484
485 i_nround(b1, b0, kp); i_nround(b0, b1, kp);
486 i_nround(b1, b0, kp); i_nround(b0, b1, kp);
487 i_nround(b1, b0, kp); i_nround(b0, b1, kp);
488 i_nround(b1, b0, kp); i_nround(b0, b1, kp);
489 i_nround(b1, b0, kp); i_lround(b0, b1, kp);
490
491 out_blk[0] = b0[0]; out_blk[1] = b0[1];
492 out_blk[2] = b0[2]; out_blk[3] = b0[3];
493};
diff --git a/rijndael.h b/rijndael.h
new file mode 100644
index 000000000..c13f18c95
--- /dev/null
+++ b/rijndael.h
@@ -0,0 +1,31 @@
1#ifndef _RIJNDAEL_H_
2#define _RIJNDAEL_H_
3
4/* 1. Standard types for AES cryptography source code */
5
6typedef u_int8_t u1byte; /* an 8 bit unsigned character type */
7typedef u_int16_t u2byte; /* a 16 bit unsigned integer type */
8typedef u_int32_t u4byte; /* a 32 bit unsigned integer type */
9
10typedef int8_t s1byte; /* an 8 bit signed character type */
11typedef int16_t s2byte; /* a 16 bit signed integer type */
12typedef int32_t s4byte; /* a 32 bit signed integer type */
13
14typedef struct _rijndael_ctx {
15 u4byte k_len;
16 int decrypt;
17 u4byte e_key[64];
18 u4byte d_key[64];
19} rijndael_ctx;
20
21
22/* 2. Standard interface for AES cryptographic routines */
23
24/* These are all based on 32 bit unsigned values and will therefore */
25/* require endian conversions for big-endian architectures */
26
27rijndael_ctx *rijndael_set_key __P((rijndael_ctx *, const u4byte *, u4byte, int));
28void rijndael_encrypt __P((rijndael_ctx *, const u4byte *, u4byte *));
29void rijndael_decrypt __P((rijndael_ctx *, const u4byte *, u4byte *));
30
31#endif /* _RIJNDAEL_H_ */
diff --git a/scp.1 b/scp.1
index 51ef34c88..f92ba4476 100644
--- a/scp.1
+++ b/scp.1
@@ -9,7 +9,7 @@
9.\" 9.\"
10.\" Created: Sun May 7 00:14:37 1995 ylo 10.\" Created: Sun May 7 00:14:37 1995 ylo
11.\" 11.\"
12.\" $Id: scp.1,v 1.10 2000/09/05 02:34:54 djm Exp $ 12.\" $Id: scp.1,v 1.11 2000/10/14 05:23:12 djm Exp $
13.\" 13.\"
14.Dd September 25, 1999 14.Dd September 25, 1999
15.Dt SCP 1 15.Dt SCP 1
@@ -24,6 +24,7 @@
24.Op Fl P Ar port 24.Op Fl P Ar port
25.Op Fl c Ar cipher 25.Op Fl c Ar cipher
26.Op Fl i Ar identity_file 26.Op Fl i Ar identity_file
27.Op Fl o Ar option
27.Sm off 28.Sm off
28.Oo 29.Oo
29.Op Ar user@ 30.Op Ar user@
@@ -102,9 +103,13 @@ is already reserved for preserving the times and modes of the file in
102.It Fl S Ar program 103.It Fl S Ar program
103Name of 104Name of
104.Ar program 105.Ar program
105to use for the encrypted connection. The program must understand 106to use for the encrypted connection.
107The program must understand
106.Xr ssh 1 108.Xr ssh 1
107options. 109options.
110.It Fl o Ar option
111The given option is directly passed to
112.Xr ssh 1 .
108.It Fl 4 113.It Fl 4
109Forces 114Forces
110.Nm 115.Nm
diff --git a/scp.c b/scp.c
index 356d97e63..40cf72963 100644
--- a/scp.c
+++ b/scp.c
@@ -75,7 +75,7 @@
75 */ 75 */
76 76
77#include "includes.h" 77#include "includes.h"
78RCSID("$OpenBSD: scp.c,v 1.40 2000/09/21 11:11:42 markus Exp $"); 78RCSID("$OpenBSD: scp.c,v 1.41 2000/10/11 20:03:27 markus Exp $");
79 79
80#include "ssh.h" 80#include "ssh.h"
81#include "xmalloc.h" 81#include "xmalloc.h"
@@ -102,6 +102,9 @@ void progressmeter(int);
102int getttywidth(void); 102int getttywidth(void);
103int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); 103int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);
104 104
105/* setup arguments for the call to ssh */
106void addargs(char *fmt, ...) __attribute__((format(printf, 1, 2)));
107
105/* Time a transfer started. */ 108/* Time a transfer started. */
106static struct timeval start; 109static struct timeval start;
107 110
@@ -114,12 +117,6 @@ off_t totalbytes = 0;
114/* Name of current file being transferred. */ 117/* Name of current file being transferred. */
115char *curfile; 118char *curfile;
116 119
117/* This is set to non-zero if IPv4 is desired. */
118int IPv4 = 0;
119
120/* This is set to non-zero if IPv6 is desired. */
121int IPv6 = 0;
122
123/* This is set to non-zero to enable verbose mode. */ 120/* This is set to non-zero to enable verbose mode. */
124int verbose_mode = 0; 121int verbose_mode = 0;
125 122
@@ -129,23 +126,16 @@ int compress_flag = 0;
129/* This is set to zero if the progressmeter is not desired. */ 126/* This is set to zero if the progressmeter is not desired. */
130int showprogress = 1; 127int showprogress = 1;
131 128
132/* This is set to non-zero if running in batch mode (that is, password
133 and passphrase queries are not allowed). */
134int batchmode = 0;
135
136/* This is set to the cipher type string if given on the command line. */
137char *cipher = NULL;
138
139/* This is set to the RSA authentication identity file name if given on
140 the command line. */
141char *identity = NULL;
142
143/* This is the port to use in contacting the remote site (is non-NULL). */
144char *port = NULL;
145
146/* This is the program to execute for the secured connection. ("ssh" or -S) */ 129/* This is the program to execute for the secured connection. ("ssh" or -S) */
147char *ssh_program = SSH_PROGRAM; 130char *ssh_program = SSH_PROGRAM;
148 131
132/* This is the list of arguments that scp passes to ssh */
133struct {
134 char **list;
135 int num;
136 int nalloc;
137} args;
138
149/* 139/*
150 * This function executes the given command as the specified user on the 140 * This function executes the given command as the specified user on the
151 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This 141 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This
@@ -158,8 +148,8 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
158 int pin[2], pout[2], reserved[2]; 148 int pin[2], pout[2], reserved[2];
159 149
160 if (verbose_mode) 150 if (verbose_mode)
161 fprintf(stderr, "Executing: host %s, user %s, command %s\n", 151 fprintf(stderr, "Executing: program %s host %s, user %s, command %s\n",
162 host, remuser ? remuser : "(unspecified)", cmd); 152 ssh_program, host, remuser ? remuser : "(unspecified)", cmd);
163 153
164 /* 154 /*
165 * Reserve two descriptors so that the real pipes won't get 155 * Reserve two descriptors so that the real pipes won't get
@@ -178,10 +168,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
178 close(reserved[1]); 168 close(reserved[1]);
179 169
180 /* For a child to execute the command on the remote host using ssh. */ 170 /* For a child to execute the command on the remote host using ssh. */
181 if (fork() == 0) { 171 if (fork() == 0) {
182 char *args[100]; /* XXX careful */
183 unsigned int i;
184
185 /* Child. */ 172 /* Child. */
186 close(pin[1]); 173 close(pin[1]);
187 close(pout[0]); 174 close(pout[0]);
@@ -190,41 +177,13 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
190 close(pin[0]); 177 close(pin[0]);
191 close(pout[1]); 178 close(pout[1]);
192 179
193 i = 0; 180 args.list[0] = ssh_program;
194 args[i++] = ssh_program; 181 if (remuser != NULL)
195 args[i++] = "-x"; 182 addargs("-l %s", remuser);
196 args[i++] = "-oFallBackToRsh no"; 183 addargs("%s", host);
197 if (IPv4) 184 addargs("%s", cmd);
198 args[i++] = "-4";
199 if (IPv6)
200 args[i++] = "-6";
201 if (verbose_mode)
202 args[i++] = "-v";
203 if (compress_flag)
204 args[i++] = "-C";
205 if (batchmode)
206 args[i++] = "-oBatchMode yes";
207 if (cipher != NULL) {
208 args[i++] = "-c";
209 args[i++] = cipher;
210 }
211 if (identity != NULL) {
212 args[i++] = "-i";
213 args[i++] = identity;
214 }
215 if (port != NULL) {
216 args[i++] = "-p";
217 args[i++] = port;
218 }
219 if (remuser != NULL) {
220 args[i++] = "-l";
221 args[i++] = remuser;
222 }
223 args[i++] = host;
224 args[i++] = cmd;
225 args[i++] = NULL;
226 185
227 execvp(ssh_program, args); 186 execvp(ssh_program, args.list);
228 perror(ssh_program); 187 perror(ssh_program);
229 exit(1); 188 exit(1);
230 } 189 }
@@ -290,27 +249,45 @@ main(argc, argv)
290 extern char *optarg; 249 extern char *optarg;
291 extern int optind; 250 extern int optind;
292 251
252 args.list = NULL;
253 addargs("ssh"); /* overwritten with ssh_program */
254 addargs("-x");
255 addargs("-oFallBackToRsh no");
256
293 fflag = tflag = 0; 257 fflag = tflag = 0;
294 while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:")) != EOF) 258 while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:")) != EOF)
295 switch (ch) { 259 switch (ch) {
296 /* User-visible flags. */ 260 /* User-visible flags. */
297 case '4': 261 case '4':
298 IPv4 = 1;
299 break;
300 case '6': 262 case '6':
301 IPv6 = 1; 263 case 'C':
264 addargs("-%c", ch);
302 break; 265 break;
303 case 'p': 266 case 'o':
304 pflag = 1; 267 case 'c':
268 case 'i':
269 addargs("-%c %s", ch, optarg);
305 break; 270 break;
306 case 'P': 271 case 'P':
307 port = optarg; 272 addargs("-p %s", optarg);
273 break;
274 case 'B':
275 addargs("-o Batchmode yes");
276 break;
277 case 'p':
278 pflag = 1;
308 break; 279 break;
309 case 'r': 280 case 'r':
310 iamrecursive = 1; 281 iamrecursive = 1;
311 break; 282 break;
312 case 'S': 283 case 'S':
313 ssh_program = optarg; 284 ssh_program = xstrdup(optarg);
285 break;
286 case 'v':
287 verbose_mode = 1;
288 break;
289 case 'q':
290 showprogress = 0;
314 break; 291 break;
315 292
316 /* Server options. */ 293 /* Server options. */
@@ -325,24 +302,6 @@ main(argc, argv)
325 iamremote = 1; 302 iamremote = 1;
326 tflag = 1; 303 tflag = 1;
327 break; 304 break;
328 case 'c':
329 cipher = optarg;
330 break;
331 case 'i':
332 identity = optarg;
333 break;
334 case 'v':
335 verbose_mode = 1;
336 break;
337 case 'B':
338 batchmode = 1;
339 break;
340 case 'C':
341 compress_flag = 1;
342 break;
343 case 'q':
344 showprogress = 0;
345 break;
346 case '?': 305 case '?':
347 default: 306 default:
348 usage(); 307 usage();
@@ -1287,3 +1246,25 @@ getttywidth(void)
1287 else 1246 else
1288 return (80); 1247 return (80);
1289} 1248}
1249
1250void
1251addargs(char *fmt, ...)
1252{
1253 va_list ap;
1254 char buf[1024];
1255
1256 va_start(ap, fmt);
1257 vsnprintf(buf, sizeof(buf), fmt, ap);
1258 va_end(ap);
1259
1260 if (args.list == NULL) {
1261 args.nalloc = 32;
1262 args.num = 0;
1263 args.list = xmalloc(args.nalloc * sizeof(char *));
1264 } else if (args.num+2 >= args.nalloc) {
1265 args.nalloc *= 2;
1266 args.list = xrealloc(args.list, args.nalloc * sizeof(char *));
1267 }
1268 args.list[args.num++] = xstrdup(buf);
1269 args.list[args.num] = NULL;
1270}
diff --git a/servconf.c b/servconf.c
index 815510814..e90defe61 100644
--- a/servconf.c
+++ b/servconf.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: servconf.c,v 1.51 2000/09/07 20:27:53 deraadt Exp $"); 13RCSID("$OpenBSD: servconf.c,v 1.52 2000/10/11 20:14:39 markus Exp $");
14 14
15#include "ssh.h" 15#include "ssh.h"
16#include "servconf.h" 16#include "servconf.h"
@@ -61,6 +61,7 @@ initialize_server_options(ServerOptions *options)
61 options->afs_token_passing = -1; 61 options->afs_token_passing = -1;
62#endif 62#endif
63 options->password_authentication = -1; 63 options->password_authentication = -1;
64 options->kbd_interactive_authentication = -1;
64#ifdef SKEY 65#ifdef SKEY
65 options->skey_authentication = -1; 66 options->skey_authentication = -1;
66#endif 67#endif
@@ -148,6 +149,8 @@ fill_default_server_options(ServerOptions *options)
148#endif /* AFS */ 149#endif /* AFS */
149 if (options->password_authentication == -1) 150 if (options->password_authentication == -1)
150 options->password_authentication = 1; 151 options->password_authentication = 1;
152 if (options->kbd_interactive_authentication == -1)
153 options->kbd_interactive_authentication = 0;
151#ifdef SKEY 154#ifdef SKEY
152 if (options->skey_authentication == -1) 155 if (options->skey_authentication == -1)
153 options->skey_authentication = 1; 156 options->skey_authentication = 1;
@@ -183,7 +186,7 @@ typedef enum {
183#ifdef SKEY 186#ifdef SKEY
184 sSkeyAuthentication, 187 sSkeyAuthentication,
185#endif 188#endif
186 sPasswordAuthentication, sListenAddress, 189 sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
187 sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, 190 sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
188 sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail, 191 sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
189 sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 192 sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
@@ -220,6 +223,7 @@ static struct {
220 { "afstokenpassing", sAFSTokenPassing }, 223 { "afstokenpassing", sAFSTokenPassing },
221#endif 224#endif
222 { "passwordauthentication", sPasswordAuthentication }, 225 { "passwordauthentication", sPasswordAuthentication },
226 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
223#ifdef SKEY 227#ifdef SKEY
224 { "skeyauthentication", sSkeyAuthentication }, 228 { "skeyauthentication", sSkeyAuthentication },
225#endif 229#endif
@@ -497,6 +501,10 @@ parse_flag:
497 intptr = &options->password_authentication; 501 intptr = &options->password_authentication;
498 goto parse_flag; 502 goto parse_flag;
499 503
504 case sKbdInteractiveAuthentication:
505 intptr = &options->kbd_interactive_authentication;
506 goto parse_flag;
507
500 case sCheckMail: 508 case sCheckMail:
501 intptr = &options->check_mail; 509 intptr = &options->check_mail;
502 goto parse_flag; 510 goto parse_flag;
diff --git a/servconf.h b/servconf.h
index f00a1284f..ef0790c7b 100644
--- a/servconf.h
+++ b/servconf.h
@@ -11,7 +11,7 @@
11 * called by a name other than "ssh" or "Secure Shell". 11 * called by a name other than "ssh" or "Secure Shell".
12 */ 12 */
13 13
14/* RCSID("$OpenBSD: servconf.h,v 1.28 2000/09/07 20:27:53 deraadt Exp $"); */ 14/* RCSID("$OpenBSD: servconf.h,v 1.29 2000/10/11 20:14:39 markus Exp $"); */
15 15
16#ifndef SERVCONF_H 16#ifndef SERVCONF_H
17#define SERVCONF_H 17#define SERVCONF_H
@@ -78,6 +78,7 @@ typedef struct {
78#endif 78#endif
79 int password_authentication; /* If true, permit password 79 int password_authentication; /* If true, permit password
80 * authentication. */ 80 * authentication. */
81 int kbd_interactive_authentication; /* If true, permit */
81#ifdef SKEY 82#ifdef SKEY
82 int skey_authentication; /* If true, permit s/key 83 int skey_authentication; /* If true, permit s/key
83 * authentication. */ 84 * authentication. */
diff --git a/session.c b/session.c
index 0b31d5f19..dacb6a099 100644
--- a/session.c
+++ b/session.c
@@ -33,14 +33,13 @@
33 */ 33 */
34 34
35#include "includes.h" 35#include "includes.h"
36RCSID("$OpenBSD: session.c,v 1.37 2000/09/07 20:27:53 deraadt Exp $"); 36RCSID("$OpenBSD: session.c,v 1.38 2000/10/11 20:27:23 markus Exp $");
37 37
38#include "xmalloc.h" 38#include "xmalloc.h"
39#include "ssh.h" 39#include "ssh.h"
40#include "pty.h" 40#include "pty.h"
41#include "packet.h" 41#include "packet.h"
42#include "buffer.h" 42#include "buffer.h"
43#include "cipher.h"
44#include "mpaux.h" 43#include "mpaux.h"
45#include "servconf.h" 44#include "servconf.h"
46#include "uidswap.h" 45#include "uidswap.h"
diff --git a/sftp-server.8 b/sftp-server.8
index 59c997c3f..2a7ba258b 100644
--- a/sftp-server.8
+++ b/sftp-server.8
@@ -1,4 +1,4 @@
1.\" $OpenBSD: sftp-server.8,v 1.2 2000/09/07 20:27:53 deraadt Exp $ 1.\" $OpenBSD: sftp-server.8,v 1.3 2000/10/13 17:20:44 aaron Exp $
2.\" 2.\"
3.\" Copyright (c) 2000 Markus Friedl. All rights reserved. 3.\" Copyright (c) 2000 Markus Friedl. All rights reserved.
4.\" 4.\"
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index 337134465..b91a09827 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -168,8 +168,9 @@ removed once the RSA patent expires.
168This option will read a private 168This option will read a private
169OpenSSH DSA format file and print a SSH2-compatible public key to stdout. 169OpenSSH DSA format file and print a SSH2-compatible public key to stdout.
170.It Fl X 170.It Fl X
171This option will read a 171This option will read a unencrypted
172SSH2-compatible public key file and print an OpenSSH DSA compatible public key to stdout. 172SSH2-compatible private (or public) key file and
173print an OpenSSH compatible private (or public) key to stdout.
173.It Fl y 174.It Fl y
174This option will read a private 175This option will read a private
175OpenSSH DSA format file and print an OpenSSH DSA public key to stdout. 176OpenSSH DSA format file and print an OpenSSH DSA public key to stdout.
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 216a8b6ef..e050f4051 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$OpenBSD: ssh-keygen.c,v 1.31 2000/09/07 20:27:54 deraadt Exp $"); 15RCSID("$OpenBSD: ssh-keygen.c,v 1.32 2000/10/09 21:30:44 markus Exp $");
16 16
17#include <openssl/evp.h> 17#include <openssl/evp.h>
18#include <openssl/pem.h> 18#include <openssl/pem.h>
@@ -27,6 +27,9 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.31 2000/09/07 20:27:54 deraadt Exp $");
27#include "authfile.h" 27#include "authfile.h"
28#include "uuencode.h" 28#include "uuencode.h"
29 29
30#include "buffer.h"
31#include "bufaux.h"
32
30/* Number of bits in the RSA/DSA key. This value can be changed on the command line. */ 33/* Number of bits in the RSA/DSA key. This value can be changed on the command line. */
31int bits = 1024; 34int bits = 1024;
32 35
@@ -108,8 +111,10 @@ try_load_key(char *filename, Key *k)
108 return success; 111 return success;
109} 112}
110 113
111#define SSH_COM_MAGIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----" 114#define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
112#define SSH_COM_MAGIC_END "---- END SSH2 PUBLIC KEY ----" 115#define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
116#define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
117#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
113 118
114void 119void
115do_convert_to_ssh2(struct passwd *pw) 120do_convert_to_ssh2(struct passwd *pw)
@@ -131,19 +136,84 @@ do_convert_to_ssh2(struct passwd *pw)
131 exit(1); 136 exit(1);
132 } 137 }
133 dsa_make_key_blob(k, &blob, &len); 138 dsa_make_key_blob(k, &blob, &len);
134 fprintf(stdout, "%s\n", SSH_COM_MAGIC_BEGIN); 139 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
135 fprintf(stdout, 140 fprintf(stdout,
136 "Comment: \"%d-bit DSA, converted from openssh by %s@%s\"\n", 141 "Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n",
137 BN_num_bits(k->dsa->p), 142 key_size(k), key_type(k),
138 pw->pw_name, hostname); 143 pw->pw_name, hostname);
139 dump_base64(stdout, blob, len); 144 dump_base64(stdout, blob, len);
140 fprintf(stdout, "%s\n", SSH_COM_MAGIC_END); 145 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
141 key_free(k); 146 key_free(k);
142 xfree(blob); 147 xfree(blob);
143 exit(0); 148 exit(0);
144} 149}
145 150
146void 151void
152buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
153{
154 int bits = buffer_get_int(b);
155 int bytes = (bits + 7) / 8;
156 if (buffer_len(b) < bytes)
157 fatal("buffer_get_bignum_bits: input buffer too small");
158 BN_bin2bn((unsigned char *)buffer_ptr(b), bytes, value);
159 buffer_consume(b, bytes);
160}
161
162Key *
163do_convert_private_ssh2_from_blob(char *blob, int blen)
164{
165 Buffer b;
166 DSA *dsa;
167 Key *key = NULL;
168 int ignore, magic, rlen;
169 char *type, *cipher;
170
171 buffer_init(&b);
172 buffer_append(&b, blob, blen);
173
174 magic = buffer_get_int(&b);
175 if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
176 error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
177 buffer_free(&b);
178 return NULL;
179 }
180 ignore = buffer_get_int(&b);
181 type = buffer_get_string(&b, NULL);
182 cipher = buffer_get_string(&b, NULL);
183 ignore = buffer_get_int(&b);
184 ignore = buffer_get_int(&b);
185 ignore = buffer_get_int(&b);
186 xfree(type);
187
188 if (strcmp(cipher, "none") != 0) {
189 error("unsupported cipher %s", cipher);
190 xfree(cipher);
191 buffer_free(&b);
192 return NULL;
193 }
194 xfree(cipher);
195
196 key = key_new(KEY_DSA);
197 dsa = key->dsa;
198 dsa->priv_key = BN_new();
199 if (dsa->priv_key == NULL) {
200 error("alloc priv_key failed");
201 key_free(key);
202 return NULL;
203 }
204 buffer_get_bignum_bits(&b, dsa->p);
205 buffer_get_bignum_bits(&b, dsa->g);
206 buffer_get_bignum_bits(&b, dsa->q);
207 buffer_get_bignum_bits(&b, dsa->pub_key);
208 buffer_get_bignum_bits(&b, dsa->priv_key);
209 rlen = buffer_len(&b);
210 if(rlen != 0)
211 error("do_convert_private_ssh2_from_blob: remaining bytes in key blob %d", rlen);
212 buffer_free(&b);
213 return key;
214}
215
216void
147do_convert_from_ssh2(struct passwd *pw) 217do_convert_from_ssh2(struct passwd *pw)
148{ 218{
149 Key *k; 219 Key *k;
@@ -152,7 +222,7 @@ do_convert_from_ssh2(struct passwd *pw)
152 char blob[8096]; 222 char blob[8096];
153 char encoded[8096]; 223 char encoded[8096];
154 struct stat st; 224 struct stat st;
155 int escaped = 0; 225 int escaped = 0, private = 0, ok;
156 FILE *fp; 226 FILE *fp;
157 227
158 if (!have_identity) 228 if (!have_identity)
@@ -176,6 +246,8 @@ do_convert_from_ssh2(struct passwd *pw)
176 escaped++; 246 escaped++;
177 if (strncmp(line, "----", 4) == 0 || 247 if (strncmp(line, "----", 4) == 0 ||
178 strstr(line, ": ") != NULL) { 248 strstr(line, ": ") != NULL) {
249 if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
250 private = 1;
179 fprintf(stderr, "ignore: %s", line); 251 fprintf(stderr, "ignore: %s", line);
180 continue; 252 continue;
181 } 253 }
@@ -192,9 +264,20 @@ do_convert_from_ssh2(struct passwd *pw)
192 fprintf(stderr, "uudecode failed.\n"); 264 fprintf(stderr, "uudecode failed.\n");
193 exit(1); 265 exit(1);
194 } 266 }
195 k = dsa_key_from_blob(blob, blen); 267 k = private ?
196 if (!key_write(k, stdout)) 268 do_convert_private_ssh2_from_blob(blob, blen) :
197 fprintf(stderr, "key_write failed"); 269 dsa_key_from_blob(blob, blen);
270 if (k == NULL) {
271 fprintf(stderr, "decode blob failed.\n");
272 exit(1);
273 }
274 ok = private ?
275 PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
276 key_write(k, stdout);
277 if (!ok) {
278 fprintf(stderr, "key write failed");
279 exit(1);
280 }
198 key_free(k); 281 key_free(k);
199 fprintf(stdout, "\n"); 282 fprintf(stdout, "\n");
200 fclose(fp); 283 fclose(fp);
diff --git a/ssh.1 b/ssh.1
index 578678220..a73a07c65 100644
--- a/ssh.1
+++ b/ssh.1
@@ -374,8 +374,9 @@ is a fast block cipher, it appears very secure and is much faster than
374.Ar 3des . 374.Ar 3des .
375.It Fl c Ar "3des-cbc,blowfish-cbc,arcfour,cast128-cbc" 375.It Fl c Ar "3des-cbc,blowfish-cbc,arcfour,cast128-cbc"
376Additionally, for protocol version 2 a comma-separated list of ciphers can 376Additionally, for protocol version 2 a comma-separated list of ciphers can
377be specified in order of preference. Protocol version 2 supports 377be specified in order of preference.
3783DES, Blowfish and CAST128 in CBC mode and Arcfour. 378Protocol version 2 supports 3DES, Blowfish, and CAST128 in CBC mode
379and Arcfour.
379.It Fl e Ar ch|^ch|none 380.It Fl e Ar ch|^ch|none
380Sets the escape character for sessions with a pty (default: 381Sets the escape character for sessions with a pty (default:
381.Ql ~ ) . 382.Ql ~ ) .
@@ -483,7 +484,8 @@ debugging connection, authentication, and configuration problems.
483The verbose mode is also used to display 484The verbose mode is also used to display
484.Xr skey 1 485.Xr skey 1
485challenges, if the user entered "s/key" as password. 486challenges, if the user entered "s/key" as password.
486Multiple -v options increases the verbosity. Maximum is 3. 487Multiple -v options increases the verbosity.
488Maximum is 3.
487.It Fl x 489.It Fl x
488Disables X11 forwarding. 490Disables X11 forwarding.
489.It Fl X 491.It Fl X
diff --git a/ssh.c b/ssh.c
index 518854545..ed31007ad 100644
--- a/ssh.c
+++ b/ssh.c
@@ -39,7 +39,7 @@
39 */ 39 */
40 40
41#include "includes.h" 41#include "includes.h"
42RCSID("$OpenBSD: ssh.c,v 1.66 2000/09/12 20:53:10 markus Exp $"); 42RCSID("$OpenBSD: ssh.c,v 1.68 2000/10/11 20:27:24 markus Exp $");
43 43
44#include <openssl/evp.h> 44#include <openssl/evp.h>
45#include <openssl/dsa.h> 45#include <openssl/dsa.h>
@@ -425,11 +425,12 @@ main(int ac, char **av)
425 options.cipher = SSH_CIPHER_ILLEGAL; 425 options.cipher = SSH_CIPHER_ILLEGAL;
426 } else { 426 } else {
427 /* SSH1 only */ 427 /* SSH1 only */
428 options.cipher = cipher_number(optarg); 428 Cipher *c = cipher_by_name(optarg);
429 if (options.cipher == -1) { 429 if (c == NULL || c->number < 0) {
430 fprintf(stderr, "Unknown cipher type '%s'\n", optarg); 430 fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
431 exit(1); 431 exit(1);
432 } 432 }
433 options.cipher = c->number;
433 } 434 }
434 break; 435 break;
435 case 'p': 436 case 'p':
@@ -582,22 +583,6 @@ main(int ac, char **av)
582 if (options.hostname != NULL) 583 if (options.hostname != NULL)
583 host = options.hostname; 584 host = options.hostname;
584 585
585 /* Find canonic host name. */
586 if (strchr(host, '.') == 0) {
587 struct addrinfo hints;
588 struct addrinfo *ai = NULL;
589 int errgai;
590 memset(&hints, 0, sizeof(hints));
591 hints.ai_family = IPv4or6;
592 hints.ai_flags = AI_CANONNAME;
593 hints.ai_socktype = SOCK_STREAM;
594 errgai = getaddrinfo(host, NULL, &hints, &ai);
595 if (errgai == 0) {
596 if (ai->ai_canonname != NULL)
597 host = xstrdup(ai->ai_canonname);
598 freeaddrinfo(ai);
599 }
600 }
601 /* Disable rhosts authentication if not running as root. */ 586 /* Disable rhosts authentication if not running as root. */
602#ifdef HAVE_CYGWIN 587#ifdef HAVE_CYGWIN
603 /* Ignore uid if running under Windows */ 588 /* Ignore uid if running under Windows */
diff --git a/ssh.h b/ssh.h
index cc612d0d4..78254e45a 100644
--- a/ssh.h
+++ b/ssh.h
@@ -12,7 +12,7 @@
12 * called by a name other than "ssh" or "Secure Shell". 12 * called by a name other than "ssh" or "Secure Shell".
13 */ 13 */
14 14
15/* RCSID("$OpenBSD: ssh.h,v 1.51 2000/09/12 20:53:10 markus Exp $"); */ 15/* RCSID("$OpenBSD: ssh.h,v 1.54 2000/10/11 20:27:24 markus Exp $"); */
16 16
17#ifndef SSH_H 17#ifndef SSH_H
18#define SSH_H 18#define SSH_H
@@ -28,14 +28,6 @@
28#include "rsa.h" 28#include "rsa.h"
29#include "cipher.h" 29#include "cipher.h"
30 30
31/*
32 * XXX
33 * The default cipher used if IDEA is not supported by the remote host. It is
34 * recommended that this be one of the mandatory ciphers (DES, 3DES), though
35 * that is not required.
36 */
37#define SSH_FALLBACK_CIPHER SSH_CIPHER_3DES
38
39/* Cipher used for encrypting authentication files. */ 31/* Cipher used for encrypting authentication files. */
40#define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES 32#define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES
41 33
@@ -98,6 +90,7 @@
98#define SERVER_CONFIG_FILE ETCDIR "/sshd_config" 90#define SERVER_CONFIG_FILE ETCDIR "/sshd_config"
99#define HOST_CONFIG_FILE ETCDIR "/ssh_config" 91#define HOST_CONFIG_FILE ETCDIR "/ssh_config"
100#define HOST_DSA_KEY_FILE ETCDIR "/ssh_host_dsa_key" 92#define HOST_DSA_KEY_FILE ETCDIR "/ssh_host_dsa_key"
93#define DH_PRIMES ETCDIR "/primes"
101 94
102#ifndef SSH_PROGRAM 95#ifndef SSH_PROGRAM
103#define SSH_PROGRAM "/usr/bin/ssh" 96#define SSH_PROGRAM "/usr/bin/ssh"
@@ -423,7 +416,7 @@ int auth_rsa_challenge_dialog(RSA *pk);
423 * passphrase (allocated with xmalloc). Exits if EOF is encountered. If 416 * passphrase (allocated with xmalloc). Exits if EOF is encountered. If
424 * from_stdin is true, the passphrase will be read from stdin instead. 417 * from_stdin is true, the passphrase will be read from stdin instead.
425 */ 418 */
426char *read_passphrase(const char *prompt, int from_stdin); 419char *read_passphrase(char *prompt, int from_stdin);
427 420
428 421
429/*------------ Definitions for logging. -----------------------*/ 422/*------------ Definitions for logging. -----------------------*/
diff --git a/ssh2.h b/ssh2.h
index 47628ddd4..fe0146cbd 100644
--- a/ssh2.h
+++ b/ssh2.h
@@ -52,7 +52,7 @@
52 * 52 *
53 * 192-255 Local extensions 53 * 192-255 Local extensions
54 */ 54 */
55/* RCSID("$OpenBSD: ssh2.h,v 1.4 2000/09/07 20:27:54 deraadt Exp $"); */ 55/* RCSID("$OpenBSD: ssh2.h,v 1.5 2000/10/11 04:02:17 provos Exp $"); */
56 56
57/* transport layer: generic */ 57/* transport layer: generic */
58 58
@@ -73,6 +73,12 @@
73#define SSH2_MSG_KEXDH_INIT 30 73#define SSH2_MSG_KEXDH_INIT 30
74#define SSH2_MSG_KEXDH_REPLY 31 74#define SSH2_MSG_KEXDH_REPLY 31
75 75
76/* dh-group-exchange */
77#define SSH2_MSG_KEX_DH_GEX_REQUEST 30
78#define SSH2_MSG_KEX_DH_GEX_GROUP 31
79#define SSH2_MSG_KEX_DH_GEX_INIT 32
80#define SSH2_MSG_KEX_DH_GEX_REPLY 33
81
76/* user authentication: generic */ 82/* user authentication: generic */
77 83
78#define SSH2_MSG_USERAUTH_REQUEST 50 84#define SSH2_MSG_USERAUTH_REQUEST 50
diff --git a/sshconnect1.c b/sshconnect1.c
index 2bb4d5387..ce560791c 100644
--- a/sshconnect1.c
+++ b/sshconnect1.c
@@ -13,7 +13,7 @@
13 */ 13 */
14 14
15#include "includes.h" 15#include "includes.h"
16RCSID("$OpenBSD: sshconnect1.c,v 1.6 2000/09/07 20:27:54 deraadt Exp $"); 16RCSID("$OpenBSD: sshconnect1.c,v 1.8 2000/10/12 09:59:19 markus Exp $");
17 17
18#include <openssl/bn.h> 18#include <openssl/bn.h>
19#include <openssl/dsa.h> 19#include <openssl/dsa.h>
@@ -25,7 +25,6 @@ RCSID("$OpenBSD: sshconnect1.c,v 1.6 2000/09/07 20:27:54 deraadt Exp $");
25#include "ssh.h" 25#include "ssh.h"
26#include "buffer.h" 26#include "buffer.h"
27#include "packet.h" 27#include "packet.h"
28#include "cipher.h"
29#include "mpaux.h" 28#include "mpaux.h"
30#include "uidswap.h" 29#include "uidswap.h"
31#include "readconf.h" 30#include "readconf.h"
@@ -836,17 +835,11 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
836 835
837 if (options.cipher == SSH_CIPHER_ILLEGAL) { 836 if (options.cipher == SSH_CIPHER_ILLEGAL) {
838 log("No valid SSH1 cipher, using %.100s instead.", 837 log("No valid SSH1 cipher, using %.100s instead.",
839 cipher_name(SSH_FALLBACK_CIPHER)); 838 cipher_name(ssh_cipher_default));
840 options.cipher = SSH_FALLBACK_CIPHER; 839 options.cipher = ssh_cipher_default;
841 } else if (options.cipher == SSH_CIPHER_NOT_SET) { 840 } else if (options.cipher == SSH_CIPHER_NOT_SET) {
842 if (cipher_mask1() & supported_ciphers & (1 << ssh_cipher_default)) 841 if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default))
843 options.cipher = ssh_cipher_default; 842 options.cipher = ssh_cipher_default;
844 else {
845 debug("Cipher %s not supported, using %.100s instead.",
846 cipher_name(ssh_cipher_default),
847 cipher_name(SSH_FALLBACK_CIPHER));
848 options.cipher = SSH_FALLBACK_CIPHER;
849 }
850 } 843 }
851 /* Check that the selected cipher is supported. */ 844 /* Check that the selected cipher is supported. */
852 if (!(supported_ciphers & (1 << options.cipher))) 845 if (!(supported_ciphers & (1 << options.cipher)))
diff --git a/sshconnect2.c b/sshconnect2.c
index eee09a19c..ca459f62c 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: sshconnect2.c,v 1.21 2000/09/27 21:41:34 markus Exp $"); 26RCSID("$OpenBSD: sshconnect2.c,v 1.25 2000/10/12 09:59:19 markus Exp $");
27 27
28#include <openssl/bn.h> 28#include <openssl/bn.h>
29#include <openssl/rsa.h> 29#include <openssl/rsa.h>
@@ -37,7 +37,6 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.21 2000/09/27 21:41:34 markus Exp $");
37#include "rsa.h" 37#include "rsa.h"
38#include "buffer.h" 38#include "buffer.h"
39#include "packet.h" 39#include "packet.h"
40#include "cipher.h"
41#include "uidswap.h" 40#include "uidswap.h"
42#include "compat.h" 41#include "compat.h"
43#include "readconf.h" 42#include "readconf.h"
@@ -49,9 +48,13 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.21 2000/09/27 21:41:34 markus Exp $");
49#include "dsa.h" 48#include "dsa.h"
50#include "sshconnect.h" 49#include "sshconnect.h"
51#include "authfile.h" 50#include "authfile.h"
51#include "cli.h"
52#include "dispatch.h" 52#include "dispatch.h"
53#include "authfd.h" 53#include "authfd.h"
54 54
55void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
56void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
57
55/* import */ 58/* import */
56extern char *client_version_string; 59extern char *client_version_string;
57extern char *server_version_string; 60extern char *server_version_string;
@@ -65,8 +68,90 @@ unsigned char *session_id2 = NULL;
65int session_id2_len = 0; 68int session_id2_len = 0;
66 69
67void 70void
68ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr, 71ssh_kex2(char *host, struct sockaddr *hostaddr)
69 Buffer *client_kexinit, Buffer *server_kexinit) 72{
73 int i, plen;
74 Kex *kex;
75 Buffer *client_kexinit, *server_kexinit;
76 char *sprop[PROPOSAL_MAX];
77
78 if (options.ciphers == NULL) {
79 if (options.cipher == SSH_CIPHER_3DES) {
80 options.ciphers = "3des-cbc";
81 } else if (options.cipher == SSH_CIPHER_BLOWFISH) {
82 options.ciphers = "blowfish-cbc";
83 } else if (options.cipher == SSH_CIPHER_DES) {
84 fatal("cipher DES not supported for protocol version 2");
85 }
86 }
87 if (options.ciphers != NULL) {
88 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
89 myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
90 }
91 if (options.compression) {
92 myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib";
93 myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
94 } else {
95 myproposal[PROPOSAL_COMP_ALGS_CTOS] = "none";
96 myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
97 }
98
99 /* buffers with raw kexinit messages */
100 server_kexinit = xmalloc(sizeof(*server_kexinit));
101 buffer_init(server_kexinit);
102 client_kexinit = kex_init(myproposal);
103
104 /* algorithm negotiation */
105 kex_exchange_kexinit(client_kexinit, server_kexinit, sprop);
106 kex = kex_choose_conf(myproposal, sprop, 0);
107 for (i = 0; i < PROPOSAL_MAX; i++)
108 xfree(sprop[i]);
109
110 /* server authentication and session key agreement */
111 switch(kex->kex_type) {
112 case DH_GRP1_SHA1:
113 ssh_dh1_client(kex, host, hostaddr,
114 client_kexinit, server_kexinit);
115 break;
116 case DH_GEX_SHA1:
117 ssh_dhgex_client(kex, host, hostaddr, client_kexinit,
118 server_kexinit);
119 break;
120 default:
121 fatal("Unsupported key exchange %d", kex->kex_type);
122 }
123
124 buffer_free(client_kexinit);
125 buffer_free(server_kexinit);
126 xfree(client_kexinit);
127 xfree(server_kexinit);
128
129 debug("Wait SSH2_MSG_NEWKEYS.");
130 packet_read_expect(&plen, SSH2_MSG_NEWKEYS);
131 packet_done();
132 debug("GOT SSH2_MSG_NEWKEYS.");
133
134 debug("send SSH2_MSG_NEWKEYS.");
135 packet_start(SSH2_MSG_NEWKEYS);
136 packet_send();
137 packet_write_wait();
138 debug("done: send SSH2_MSG_NEWKEYS.");
139
140#ifdef DEBUG_KEXDH
141 /* send 1st encrypted/maced/compressed message */
142 packet_start(SSH2_MSG_IGNORE);
143 packet_put_cstring("markus");
144 packet_send();
145 packet_write_wait();
146#endif
147 debug("done: KEX2.");
148}
149
150/* diffie-hellman-group1-sha1 */
151
152void
153ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
154 Buffer *client_kexinit, Buffer *server_kexinit)
70{ 155{
71#ifdef DEBUG_KEXDH 156#ifdef DEBUG_KEXDH
72 int i; 157 int i;
@@ -116,7 +201,7 @@ ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr,
116 fatal("cannot decode server_host_key_blob"); 201 fatal("cannot decode server_host_key_blob");
117 202
118 check_host_key(host, hostaddr, server_host_key, 203 check_host_key(host, hostaddr, server_host_key,
119 options.user_hostfile2, options.system_hostfile2); 204 options.user_hostfile2, options.system_hostfile2);
120 205
121 /* DH paramter f, server public DH key */ 206 /* DH paramter f, server public DH key */
122 dh_server_pub = BN_new(); 207 dh_server_pub = BN_new();
@@ -186,72 +271,175 @@ ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr,
186 memcpy(session_id2, hash, session_id2_len); 271 memcpy(session_id2, hash, session_id2_len);
187} 272}
188 273
274/* diffie-hellman-group-exchange-sha1 */
275
276/*
277 * Estimates the group order for a Diffie-Hellman group that has an
278 * attack complexity approximately the same as O(2**bits). Estimate
279 * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
280 */
281
282int
283dh_estimate(int bits)
284{
285
286 if (bits < 64)
287 return (512); /* O(2**63) */
288 if (bits < 128)
289 return (1024); /* O(2**86) */
290 if (bits < 192)
291 return (2048); /* O(2**116) */
292 return (4096); /* O(2**156) */
293}
294
189void 295void
190ssh_kex2(char *host, struct sockaddr *hostaddr) 296ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
297 Buffer *client_kexinit, Buffer *server_kexinit)
191{ 298{
192 int i, plen; 299#ifdef DEBUG_KEXDH
193 Kex *kex; 300 int i;
194 Buffer *client_kexinit, *server_kexinit; 301#endif
195 char *sprop[PROPOSAL_MAX]; 302 int plen, dlen;
303 unsigned int klen, kout;
304 char *signature = NULL;
305 unsigned int slen, nbits;
306 char *server_host_key_blob = NULL;
307 Key *server_host_key;
308 unsigned int sbloblen;
309 DH *dh;
310 BIGNUM *dh_server_pub = 0;
311 BIGNUM *shared_secret = 0;
312 BIGNUM *p = 0, *g = 0;
313 unsigned char *kbuf;
314 unsigned char *hash;
196 315
197 if (options.ciphers != NULL) { 316 nbits = dh_estimate(kex->enc[MODE_OUT].cipher->key_len * 8);
198 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
199 myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
200 } else if (options.cipher == SSH_CIPHER_3DES) {
201 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
202 myproposal[PROPOSAL_ENC_ALGS_STOC] =
203 (char *) cipher_name(SSH_CIPHER_3DES_CBC);
204 } else if (options.cipher == SSH_CIPHER_BLOWFISH) {
205 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
206 myproposal[PROPOSAL_ENC_ALGS_STOC] =
207 (char *) cipher_name(SSH_CIPHER_BLOWFISH_CBC);
208 }
209 if (options.compression) {
210 myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib";
211 myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
212 } else {
213 myproposal[PROPOSAL_COMP_ALGS_CTOS] = "none";
214 myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
215 }
216 317
217 /* buffers with raw kexinit messages */ 318 debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST.");
218 server_kexinit = xmalloc(sizeof(*server_kexinit)); 319 packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
219 buffer_init(server_kexinit); 320 packet_put_int(nbits);
220 client_kexinit = kex_init(myproposal); 321 packet_send();
322 packet_write_wait();
221 323
222 /* algorithm negotiation */ 324#ifdef DEBUG_KEXDH
223 kex_exchange_kexinit(client_kexinit, server_kexinit, sprop); 325 fprintf(stderr, "\nnbits = %d", nbits);
224 kex = kex_choose_conf(myproposal, sprop, 0); 326#endif
225 for (i = 0; i < PROPOSAL_MAX; i++)
226 xfree(sprop[i]);
227 327
228 /* server authentication and session key agreement */ 328 debug("Wait SSH2_MSG_KEX_DH_GEX_GROUP.");
229 ssh_kex_dh(kex, host, hostaddr, client_kexinit, server_kexinit);
230 329
231 buffer_free(client_kexinit); 330 packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_GROUP);
232 buffer_free(server_kexinit);
233 xfree(client_kexinit);
234 xfree(server_kexinit);
235 331
236 debug("Wait SSH2_MSG_NEWKEYS."); 332 debug("Got SSH2_MSG_KEX_DH_GEX_GROUP.");
237 packet_read_expect(&plen, SSH2_MSG_NEWKEYS);
238 packet_done();
239 debug("GOT SSH2_MSG_NEWKEYS.");
240 333
241 debug("send SSH2_MSG_NEWKEYS."); 334 if ((p = BN_new()) == NULL)
242 packet_start(SSH2_MSG_NEWKEYS); 335 fatal("BN_new");
243 packet_send(); 336 packet_get_bignum2(p, &dlen);
244 packet_write_wait(); 337 if ((g = BN_new()) == NULL)
245 debug("done: send SSH2_MSG_NEWKEYS."); 338 fatal("BN_new");
339 packet_get_bignum2(g, &dlen);
340 if ((dh = dh_new_group(g, p)) == NULL)
341 fatal("dh_new_group");
246 342
247#ifdef DEBUG_KEXDH 343#ifdef DEBUG_KEXDH
248 /* send 1st encrypted/maced/compressed message */ 344 fprintf(stderr, "\np= ");
249 packet_start(SSH2_MSG_IGNORE); 345 BN_print_fp(stderr, dh->p);
250 packet_put_cstring("markus"); 346 fprintf(stderr, "\ng= ");
347 BN_print_fp(stderr, dh->g);
348 fprintf(stderr, "\npub= ");
349 BN_print_fp(stderr, dh->pub_key);
350 fprintf(stderr, "\n");
351 DHparams_print_fp(stderr, dh);
352#endif
353
354 debug("Sending SSH2_MSG_KEX_DH_GEX_INIT.");
355 /* generate and send 'e', client DH public key */
356 packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
357 packet_put_bignum2(dh->pub_key);
251 packet_send(); 358 packet_send();
252 packet_write_wait(); 359 packet_write_wait();
360
361 debug("Wait SSH2_MSG_KEX_DH_GEX_REPLY.");
362
363 packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_REPLY);
364
365 debug("Got SSH2_MSG_KEXDH_REPLY.");
366
367 /* key, cert */
368 server_host_key_blob = packet_get_string(&sbloblen);
369 server_host_key = dsa_key_from_blob(server_host_key_blob, sbloblen);
370 if (server_host_key == NULL)
371 fatal("cannot decode server_host_key_blob");
372
373 check_host_key(host, hostaddr, server_host_key,
374 options.user_hostfile2, options.system_hostfile2);
375
376 /* DH paramter f, server public DH key */
377 dh_server_pub = BN_new();
378 if (dh_server_pub == NULL)
379 fatal("dh_server_pub == NULL");
380 packet_get_bignum2(dh_server_pub, &dlen);
381
382#ifdef DEBUG_KEXDH
383 fprintf(stderr, "\ndh_server_pub= ");
384 BN_print_fp(stderr, dh_server_pub);
385 fprintf(stderr, "\n");
386 debug("bits %d", BN_num_bits(dh_server_pub));
253#endif 387#endif
254 debug("done: KEX2."); 388
389 /* signed H */
390 signature = packet_get_string(&slen);
391 packet_done();
392
393 if (!dh_pub_is_valid(dh, dh_server_pub))
394 packet_disconnect("bad server public DH value");
395
396 klen = DH_size(dh);
397 kbuf = xmalloc(klen);
398 kout = DH_compute_key(kbuf, dh_server_pub, dh);
399#ifdef DEBUG_KEXDH
400 debug("shared secret: len %d/%d", klen, kout);
401 fprintf(stderr, "shared secret == ");
402 for (i = 0; i< kout; i++)
403 fprintf(stderr, "%02x", (kbuf[i])&0xff);
404 fprintf(stderr, "\n");
405#endif
406 shared_secret = BN_new();
407
408 BN_bin2bn(kbuf, kout, shared_secret);
409 memset(kbuf, 0, klen);
410 xfree(kbuf);
411
412 /* calc and verify H */
413 hash = kex_hash_gex(
414 client_version_string,
415 server_version_string,
416 buffer_ptr(client_kexinit), buffer_len(client_kexinit),
417 buffer_ptr(server_kexinit), buffer_len(server_kexinit),
418 server_host_key_blob, sbloblen,
419 nbits, dh->p, dh->g,
420 dh->pub_key,
421 dh_server_pub,
422 shared_secret
423 );
424 xfree(server_host_key_blob);
425 DH_free(dh);
426#ifdef DEBUG_KEXDH
427 fprintf(stderr, "hash == ");
428 for (i = 0; i< 20; i++)
429 fprintf(stderr, "%02x", (hash[i])&0xff);
430 fprintf(stderr, "\n");
431#endif
432 if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
433 fatal("dsa_verify failed for server_host_key");
434 key_free(server_host_key);
435
436 kex_derive_keys(kex, hash, shared_secret);
437 packet_set_kex(kex);
438
439 /* save session id */
440 session_id2_len = 20;
441 session_id2 = xmalloc(session_id2_len);
442 memcpy(session_id2, hash, session_id2_len);
255} 443}
256 444
257/* 445/*
@@ -270,8 +458,8 @@ struct Authctxt {
270 const char *host; 458 const char *host;
271 const char *service; 459 const char *service;
272 AuthenticationConnection *agent; 460 AuthenticationConnection *agent;
273 int success;
274 Authmethod *method; 461 Authmethod *method;
462 int success;
275}; 463};
276struct Authmethod { 464struct Authmethod {
277 char *name; /* string to compare against server's list */ 465 char *name; /* string to compare against server's list */
@@ -283,11 +471,16 @@ struct Authmethod {
283void input_userauth_success(int type, int plen, void *ctxt); 471void input_userauth_success(int type, int plen, void *ctxt);
284void input_userauth_failure(int type, int plen, void *ctxt); 472void input_userauth_failure(int type, int plen, void *ctxt);
285void input_userauth_error(int type, int plen, void *ctxt); 473void input_userauth_error(int type, int plen, void *ctxt);
474void input_userauth_info_req(int type, int plen, void *ctxt);
475
476int userauth_none(Authctxt *authctxt);
286int userauth_pubkey(Authctxt *authctxt); 477int userauth_pubkey(Authctxt *authctxt);
287int userauth_passwd(Authctxt *authctxt); 478int userauth_passwd(Authctxt *authctxt);
479int userauth_kbdint(Authctxt *authctxt);
288 480
289void authmethod_clear(); 481void authmethod_clear();
290Authmethod *authmethod_get(char *auth_list); 482Authmethod *authmethod_get(char *authlist);
483Authmethod *authmethod_lookup(const char *name);
291 484
292Authmethod authmethods[] = { 485Authmethod authmethods[] = {
293 {"publickey", 486 {"publickey",
@@ -298,6 +491,14 @@ Authmethod authmethods[] = {
298 userauth_passwd, 491 userauth_passwd,
299 &options.password_authentication, 492 &options.password_authentication,
300 &options.batch_mode}, 493 &options.batch_mode},
494 {"keyboard-interactive",
495 userauth_kbdint,
496 &options.kbd_interactive_authentication,
497 &options.batch_mode},
498 {"none",
499 userauth_none,
500 NULL,
501 NULL},
301 {NULL, NULL, NULL, NULL} 502 {NULL, NULL, NULL, NULL}
302}; 503};
303 504
@@ -334,17 +535,13 @@ ssh_userauth2(const char *server_user, char *host)
334 authctxt.host = host; 535 authctxt.host = host;
335 authctxt.service = "ssh-connection"; /* service name */ 536 authctxt.service = "ssh-connection"; /* service name */
336 authctxt.success = 0; 537 authctxt.success = 0;
337 authctxt.method = NULL; 538 authctxt.method = authmethod_lookup("none");
539 if (authctxt.method == NULL)
540 fatal("ssh_userauth2: internal error: cannot send userauth none request");
541 authmethod_clear();
338 542
339 /* initial userauth request */ 543 /* initial userauth request */
340 packet_start(SSH2_MSG_USERAUTH_REQUEST); 544 userauth_none(&authctxt);
341 packet_put_cstring(authctxt.server_user);
342 packet_put_cstring(authctxt.service);
343 packet_put_cstring("none");
344 packet_send();
345 packet_write_wait();
346
347 authmethod_clear();
348 545
349 dispatch_init(&input_userauth_error); 546 dispatch_init(&input_userauth_error);
350 dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); 547 dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
@@ -354,7 +551,7 @@ ssh_userauth2(const char *server_user, char *host)
354 if (authctxt.agent != NULL) 551 if (authctxt.agent != NULL)
355 ssh_close_authentication_connection(authctxt.agent); 552 ssh_close_authentication_connection(authctxt.agent);
356 553
357 debug("ssh-userauth2 successfull"); 554 debug("ssh-userauth2 successfull: method %s", authctxt.method->name);
358} 555}
359void 556void
360input_userauth_error(int type, int plen, void *ctxt) 557input_userauth_error(int type, int plen, void *ctxt)
@@ -376,12 +573,11 @@ input_userauth_failure(int type, int plen, void *ctxt)
376 Authctxt *authctxt = ctxt; 573 Authctxt *authctxt = ctxt;
377 char *authlist = NULL; 574 char *authlist = NULL;
378 int partial; 575 int partial;
379 int dlen;
380 576
381 if (authctxt == NULL) 577 if (authctxt == NULL)
382 fatal("input_userauth_failure: no authentication context"); 578 fatal("input_userauth_failure: no authentication context");
383 579
384 authlist = packet_get_string(&dlen); 580 authlist = packet_get_string(NULL);
385 partial = packet_get_char(); 581 partial = packet_get_char();
386 packet_done(); 582 packet_done();
387 583
@@ -390,12 +586,12 @@ input_userauth_failure(int type, int plen, void *ctxt)
390 debug("authentications that can continue: %s", authlist); 586 debug("authentications that can continue: %s", authlist);
391 587
392 for (;;) { 588 for (;;) {
393 /* try old method or get next method */
394 method = authmethod_get(authlist); 589 method = authmethod_get(authlist);
395 if (method == NULL) 590 if (method == NULL)
396 fatal("Unable to find an authentication method"); 591 fatal("Unable to find an authentication method");
592 authctxt->method = method;
397 if (method->userauth(authctxt) != 0) { 593 if (method->userauth(authctxt) != 0) {
398 debug2("we sent a packet, wait for reply"); 594 debug2("we sent a %s packet, wait for reply", method->name);
399 break; 595 break;
400 } else { 596 } else {
401 debug2("we did not send a packet, disable method"); 597 debug2("we did not send a packet, disable method");
@@ -406,6 +602,19 @@ input_userauth_failure(int type, int plen, void *ctxt)
406} 602}
407 603
408int 604int
605userauth_none(Authctxt *authctxt)
606{
607 /* initial userauth request */
608 packet_start(SSH2_MSG_USERAUTH_REQUEST);
609 packet_put_cstring(authctxt->server_user);
610 packet_put_cstring(authctxt->service);
611 packet_put_cstring(authctxt->method->name);
612 packet_send();
613 packet_write_wait();
614 return 1;
615}
616
617int
409userauth_passwd(Authctxt *authctxt) 618userauth_passwd(Authctxt *authctxt)
410{ 619{
411 static int attempt = 0; 620 static int attempt = 0;
@@ -424,7 +633,7 @@ userauth_passwd(Authctxt *authctxt)
424 packet_start(SSH2_MSG_USERAUTH_REQUEST); 633 packet_start(SSH2_MSG_USERAUTH_REQUEST);
425 packet_put_cstring(authctxt->server_user); 634 packet_put_cstring(authctxt->server_user);
426 packet_put_cstring(authctxt->service); 635 packet_put_cstring(authctxt->service);
427 packet_put_cstring("password"); 636 packet_put_cstring(authctxt->method->name);
428 packet_put_char(0); 637 packet_put_char(0);
429 packet_put_cstring(password); 638 packet_put_cstring(password);
430 memset(password, 0, strlen(password)); 639 memset(password, 0, strlen(password));
@@ -442,6 +651,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
442 int bloblen, slen; 651 int bloblen, slen;
443 int skip = 0; 652 int skip = 0;
444 int ret = -1; 653 int ret = -1;
654 int have_sig = 1;
445 655
446 dsa_make_key_blob(k, &blob, &bloblen); 656 dsa_make_key_blob(k, &blob, &bloblen);
447 657
@@ -460,8 +670,8 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
460 datafellows & SSH_BUG_PUBKEYAUTH ? 670 datafellows & SSH_BUG_PUBKEYAUTH ?
461 "ssh-userauth" : 671 "ssh-userauth" :
462 authctxt->service); 672 authctxt->service);
463 buffer_put_cstring(&b, "publickey"); 673 buffer_put_cstring(&b, authctxt->method->name);
464 buffer_put_char(&b, 1); 674 buffer_put_char(&b, have_sig);
465 buffer_put_cstring(&b, KEX_DSS); 675 buffer_put_cstring(&b, KEX_DSS);
466 buffer_put_string(&b, blob, bloblen); 676 buffer_put_string(&b, blob, bloblen);
467 677
@@ -481,8 +691,8 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
481 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 691 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
482 buffer_put_cstring(&b, authctxt->server_user); 692 buffer_put_cstring(&b, authctxt->server_user);
483 buffer_put_cstring(&b, authctxt->service); 693 buffer_put_cstring(&b, authctxt->service);
484 buffer_put_cstring(&b, "publickey"); 694 buffer_put_cstring(&b, authctxt->method->name);
485 buffer_put_char(&b, 1); 695 buffer_put_char(&b, have_sig);
486 buffer_put_cstring(&b, KEX_DSS); 696 buffer_put_cstring(&b, KEX_DSS);
487 buffer_put_string(&b, blob, bloblen); 697 buffer_put_string(&b, blob, bloblen);
488 } 698 }
@@ -606,6 +816,92 @@ userauth_pubkey(Authctxt *authctxt)
606 return sent; 816 return sent;
607} 817}
608 818
819/*
820 * Send userauth request message specifying keyboard-interactive method.
821 */
822int
823userauth_kbdint(Authctxt *authctxt)
824{
825 static int attempt = 0;
826
827 if (attempt++ >= options.number_of_password_prompts)
828 return 0;
829
830 debug2("userauth_kbdint");
831 packet_start(SSH2_MSG_USERAUTH_REQUEST);
832 packet_put_cstring(authctxt->server_user);
833 packet_put_cstring(authctxt->service);
834 packet_put_cstring(authctxt->method->name);
835 packet_put_cstring(""); /* lang */
836 packet_put_cstring(options.kbd_interactive_devices ?
837 options.kbd_interactive_devices : "");
838 packet_send();
839 packet_write_wait();
840
841 dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
842 return 1;
843}
844
845/*
846 * parse SSH2_MSG_USERAUTH_INFO_REQUEST, prompt user and send
847 * SSH2_MSG_USERAUTH_INFO_RESPONSE
848 */
849void
850input_userauth_info_req(int type, int plen, void *ctxt)
851{
852 Authctxt *authctxt = ctxt;
853 char *name = NULL;
854 char *inst = NULL;
855 char *lang = NULL;
856 char *prompt = NULL;
857 char *response = NULL;
858 unsigned int num_prompts, i;
859 int echo = 0;
860
861 debug2("input_userauth_info_req");
862
863 if (authctxt == NULL)
864 fatal("input_userauth_info_req: no authentication context");
865
866 name = packet_get_string(NULL);
867 inst = packet_get_string(NULL);
868 lang = packet_get_string(NULL);
869
870 if (strlen(name) > 0)
871 cli_mesg(name);
872 xfree(name);
873
874 if (strlen(inst) > 0)
875 cli_mesg(inst);
876 xfree(inst);
877 xfree(lang); /* unused */
878
879 num_prompts = packet_get_int();
880 /*
881 * Begin to build info response packet based on prompts requested.
882 * We commit to providing the correct number of responses, so if
883 * further on we run into a problem that prevents this, we have to
884 * be sure and clean this up and send a correct error response.
885 */
886 packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
887 packet_put_int(num_prompts);
888
889 for (i = 0; i < num_prompts; i++) {
890 prompt = packet_get_string(NULL);
891 echo = packet_get_char();
892
893 response = cli_prompt(prompt, echo);
894
895 packet_put_cstring(response);
896 memset(response, 0, strlen(response));
897 xfree(response);
898 xfree(prompt);
899 }
900 packet_done(); /* done with parsing incoming message. */
901
902 packet_send();
903 packet_write_wait();
904}
609 905
610/* find auth method */ 906/* find auth method */
611 907
@@ -692,6 +988,7 @@ authmethod_get(char *authlist)
692 988
693 if (authlist_current == NULL || strcmp(authlist, authlist_current) != 0) { 989 if (authlist_current == NULL || strcmp(authlist, authlist_current) != 0) {
694 /* start over if passed a different list */ 990 /* start over if passed a different list */
991 debug3("start over, passed a different list");
695 authmethod_clear(); 992 authmethod_clear();
696 authlist_current = xstrdup(authlist); 993 authlist_current = xstrdup(authlist);
697 authlist_working = xstrdup(authlist); 994 authlist_working = xstrdup(authlist);
@@ -706,16 +1003,20 @@ authmethod_get(char *authlist)
706 } 1003 }
707 1004
708 while (name != NULL) { 1005 while (name != NULL) {
1006 debug3("authmethod_lookup %s", name);
709 method = authmethod_lookup(name); 1007 method = authmethod_lookup(name);
710 if (method != NULL && authmethod_is_enabled(method)) 1008 if (method != NULL && authmethod_is_enabled(method)) {
1009 debug3("authmethod_is_enabled %s", name);
711 break; 1010 break;
1011 }
712 name = strtok_r(NULL, DELIM, &authlist_state); 1012 name = strtok_r(NULL, DELIM, &authlist_state);
1013 method = NULL;
713 } 1014 }
714 1015
715 if (authname_current != NULL) 1016 if (authname_current != NULL)
716 xfree(authname_current); 1017 xfree(authname_current);
717 1018
718 if (name != NULL) { 1019 if (method != NULL) {
719 debug("next auth method to try is %s", name); 1020 debug("next auth method to try is %s", name);
720 authname_current = xstrdup(name); 1021 authname_current = xstrdup(name);
721 return method; 1022 return method;
diff --git a/sshd.8 b/sshd.8
index cd2a8e962..29ad2144a 100644
--- a/sshd.8
+++ b/sshd.8
@@ -186,7 +186,8 @@ The server sends verbose debug output to the system
186log, and does not put itself in the background. 186log, and does not put itself in the background.
187The server also will not fork and will only process one connection. 187The server also will not fork and will only process one connection.
188This option is only intended for debugging for the server. 188This option is only intended for debugging for the server.
189Multiple -d options increases the debugging level. Maximum is 3. 189Multiple -d options increases the debugging level.
190Maximum is 3.
190.It Fl f Ar configuration_file 191.It Fl f Ar configuration_file
191Specifies the name of the configuration file. 192Specifies the name of the configuration file.
192The default is 193The default is
@@ -255,12 +256,13 @@ file.
255.It Fl Q 256.It Fl Q
256Do not print an error message if RSA support is missing. 257Do not print an error message if RSA support is missing.
257.It Fl V Ar client_protocol_id 258.It Fl V Ar client_protocol_id
258SSH2 compatibility mode. 259SSH-2 compatibility mode.
259When this option is specified 260When this option is specified
260.Nm 261.Nm
261assumes the client has sent the supplied version string 262assumes the client has sent the supplied version string
262and skips the 263and skips the
263Protocol Version Identification Exchange. 264Protocol Version Identification Exchange.
265This option is not intended to be called directly.
264.It Fl 4 266.It Fl 4
265Forces 267Forces
266.Nm 268.Nm
@@ -424,7 +426,8 @@ Specifies whether Kerberos authentication is allowed.
424This can be in the form of a Kerberos ticket, or if 426This can be in the form of a Kerberos ticket, or if
425.Cm PasswordAuthentication 427.Cm PasswordAuthentication
426is yes, the password provided by the user will be validated through 428is yes, the password provided by the user will be validated through
427the Kerberos KDC. To use this option, the server needs a 429the Kerberos KDC.
430To use this option, the server needs a
428Kerberos servtab which allows the verification of the KDC's identity. 431Kerberos servtab which allows the verification of the KDC's identity.
429Default is 432Default is
430.Dq yes . 433.Dq yes .
@@ -488,7 +491,7 @@ The default is 10.
488Alternatively, random early drop can be enabled by specifying 491Alternatively, random early drop can be enabled by specifying
489the three colon separated values 492the three colon separated values
490.Dq start:rate:full 493.Dq start:rate:full
491(e.g. "10:30:60"). 494(e.g., "10:30:60").
492.Nm 495.Nm
493will refuse connection attempts with a probabillity of 496will refuse connection attempts with a probabillity of
494.Dq rate/100 497.Dq rate/100
@@ -610,8 +613,9 @@ directory or files world-writable.
610The default is 613The default is
611.Dq yes . 614.Dq yes .
612.It Cm Subsystem 615.It Cm Subsystem
613Configures an external subsystem (e.g. file transfer daemon). 616Configures an external subsystem (e.g., file transfer daemon).
614Arguments should be a subsystem name and a command to execute upon subsystem request. 617Arguments should be a subsystem name and a command to execute upon subsystem
618request.
615The command 619The command
616.Xr sftp-server 8 620.Xr sftp-server 8
617implements the 621implements the
diff --git a/sshd.c b/sshd.c
index ae22cd953..e5c2508a1 100644
--- a/sshd.c
+++ b/sshd.c
@@ -40,14 +40,13 @@
40 */ 40 */
41 41
42#include "includes.h" 42#include "includes.h"
43RCSID("$OpenBSD: sshd.c,v 1.128 2000/09/17 15:38:59 markus Exp $"); 43RCSID("$OpenBSD: sshd.c,v 1.132 2000/10/13 18:34:46 markus Exp $");
44 44
45#include "xmalloc.h" 45#include "xmalloc.h"
46#include "rsa.h" 46#include "rsa.h"
47#include "ssh.h" 47#include "ssh.h"
48#include "pty.h" 48#include "pty.h"
49#include "packet.h" 49#include "packet.h"
50#include "cipher.h"
51#include "mpaux.h" 50#include "mpaux.h"
52#include "servconf.h" 51#include "servconf.h"
53#include "uidswap.h" 52#include "uidswap.h"
@@ -63,6 +62,7 @@ RCSID("$OpenBSD: sshd.c,v 1.128 2000/09/17 15:38:59 markus Exp $");
63#include <openssl/rsa.h> 62#include <openssl/rsa.h>
64#include "key.h" 63#include "key.h"
65#include "dsa.h" 64#include "dsa.h"
65#include "dh.h"
66 66
67#include "auth.h" 67#include "auth.h"
68#include "myproposal.h" 68#include "myproposal.h"
@@ -172,6 +172,9 @@ unsigned int utmp_len = MAXHOSTNAMELEN;
172void do_ssh1_kex(); 172void do_ssh1_kex();
173void do_ssh2_kex(); 173void do_ssh2_kex();
174 174
175void ssh_dh1_server(Kex *, Buffer *_kexinit, Buffer *);
176void ssh_dhgex_server(Kex *, Buffer *_kexinit, Buffer *);
177
175/* 178/*
176 * Close all listening sockets 179 * Close all listening sockets
177 */ 180 */
@@ -333,6 +336,10 @@ sshd_exchange_identification(int sock_in, int sock_out)
333 if (buf[i] == '\r') { 336 if (buf[i] == '\r') {
334 buf[i] = '\n'; 337 buf[i] = '\n';
335 buf[i + 1] = 0; 338 buf[i + 1] = 0;
339 /* Kludge for F-Secure Macintosh < 1.0.2 */
340 if (i == 12 &&
341 strncmp(buf, "SSH-1.5-W1.0", 12) == 0)
342 break;
336 continue; 343 continue;
337 } 344 }
338 if (buf[i] == '\n') { 345 if (buf[i] == '\n') {
@@ -1151,7 +1158,7 @@ do_ssh1_kex()
1151 packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); 1158 packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
1152 1159
1153 /* Declare which ciphers we support. */ 1160 /* Declare which ciphers we support. */
1154 packet_put_int(cipher_mask1()); 1161 packet_put_int(cipher_mask_ssh1(0));
1155 1162
1156 /* Declare supported authentication types. */ 1163 /* Declare supported authentication types. */
1157 auth_mask = 0; 1164 auth_mask = 0;
@@ -1192,7 +1199,7 @@ do_ssh1_kex()
1192 /* Get cipher type and check whether we accept this. */ 1199 /* Get cipher type and check whether we accept this. */
1193 cipher_type = packet_get_char(); 1200 cipher_type = packet_get_char();
1194 1201
1195 if (!(cipher_mask() & (1 << cipher_type))) 1202 if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))
1196 packet_disconnect("Warning: client selects unsupported cipher."); 1203 packet_disconnect("Warning: client selects unsupported cipher.");
1197 1204
1198 /* Get check bytes from the packet. These must match those we 1205 /* Get check bytes from the packet. These must match those we
@@ -1296,18 +1303,8 @@ do_ssh2_kex()
1296{ 1303{
1297 Buffer *server_kexinit; 1304 Buffer *server_kexinit;
1298 Buffer *client_kexinit; 1305 Buffer *client_kexinit;
1299 int payload_len, dlen; 1306 int payload_len;
1300 int slen;
1301 unsigned int klen, kout;
1302 unsigned char *signature = NULL;
1303 unsigned char *server_host_key_blob = NULL;
1304 unsigned int sbloblen;
1305 DH *dh;
1306 BIGNUM *dh_client_pub = 0;
1307 BIGNUM *shared_secret = 0;
1308 int i; 1307 int i;
1309 unsigned char *kbuf;
1310 unsigned char *hash;
1311 Kex *kex; 1308 Kex *kex;
1312 char *cprop[PROPOSAL_MAX]; 1309 char *cprop[PROPOSAL_MAX];
1313 1310
@@ -1327,8 +1324,63 @@ do_ssh2_kex()
1327 for (i = 0; i < PROPOSAL_MAX; i++) 1324 for (i = 0; i < PROPOSAL_MAX; i++)
1328 xfree(cprop[i]); 1325 xfree(cprop[i]);
1329 1326
1330/* KEXDH */ 1327 switch (kex->kex_type) {
1328 case DH_GRP1_SHA1:
1329 ssh_dh1_server(kex, client_kexinit, server_kexinit);
1330 break;
1331 case DH_GEX_SHA1:
1332 ssh_dhgex_server(kex, client_kexinit, server_kexinit);
1333 break;
1334 default:
1335 fatal("Unsupported key exchange %d", kex->kex_type);
1336 }
1337
1338 debug("send SSH2_MSG_NEWKEYS.");
1339 packet_start(SSH2_MSG_NEWKEYS);
1340 packet_send();
1341 packet_write_wait();
1342 debug("done: send SSH2_MSG_NEWKEYS.");
1343
1344 debug("Wait SSH2_MSG_NEWKEYS.");
1345 packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS);
1346 debug("GOT SSH2_MSG_NEWKEYS.");
1347
1348#ifdef DEBUG_KEXDH
1349 /* send 1st encrypted/maced/compressed message */
1350 packet_start(SSH2_MSG_IGNORE);
1351 packet_put_cstring("markus");
1352 packet_send();
1353 packet_write_wait();
1354#endif
1355
1356 debug("done: KEX2.");
1357}
1358
1359/*
1360 * SSH2 key exchange
1361 */
1362
1363/* diffie-hellman-group1-sha1 */
1364
1365void
1366ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
1367{
1368#ifdef DEBUG_KEXDH
1369 int i;
1370#endif
1371 int payload_len, dlen;
1372 int slen;
1373 unsigned char *signature = NULL;
1374 unsigned char *server_host_key_blob = NULL;
1375 unsigned int sbloblen;
1376 unsigned int klen, kout;
1377 unsigned char *kbuf;
1378 unsigned char *hash;
1379 BIGNUM *shared_secret = 0;
1380 DH *dh;
1381 BIGNUM *dh_client_pub = 0;
1331 1382
1383/* KEXDH */
1332 debug("Wait SSH2_MSG_KEXDH_INIT."); 1384 debug("Wait SSH2_MSG_KEXDH_INIT.");
1333 packet_read_expect(&payload_len, SSH2_MSG_KEXDH_INIT); 1385 packet_read_expect(&payload_len, SSH2_MSG_KEXDH_INIT);
1334 1386
@@ -1379,7 +1431,8 @@ do_ssh2_kex()
1379 xfree(kbuf); 1431 xfree(kbuf);
1380 1432
1381 /* XXX precompute? */ 1433 /* XXX precompute? */
1382 dsa_make_key_blob(sensitive_data.dsa_host_key, &server_host_key_blob, &sbloblen); 1434 dsa_make_key_blob(sensitive_data.dsa_host_key,
1435 &server_host_key_blob, &sbloblen);
1383 1436
1384 /* calc H */ /* XXX depends on 'kex' */ 1437 /* calc H */ /* XXX depends on 'kex' */
1385 hash = kex_hash( 1438 hash = kex_hash(
@@ -1429,23 +1482,139 @@ do_ssh2_kex()
1429 1482
1430 /* have keys, free DH */ 1483 /* have keys, free DH */
1431 DH_free(dh); 1484 DH_free(dh);
1485}
1432 1486
1433 debug("send SSH2_MSG_NEWKEYS."); 1487/* diffie-hellman-group-exchange-sha1 */
1434 packet_start(SSH2_MSG_NEWKEYS); 1488
1489void
1490ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
1491{
1492#ifdef DEBUG_KEXDH
1493 int i;
1494#endif
1495 int payload_len, dlen;
1496 int slen, nbits;
1497 unsigned char *signature = NULL;
1498 unsigned char *server_host_key_blob = NULL;
1499 unsigned int sbloblen;
1500 unsigned int klen, kout;
1501 unsigned char *kbuf;
1502 unsigned char *hash;
1503 BIGNUM *shared_secret = 0;
1504 DH *dh;
1505 BIGNUM *dh_client_pub = 0;
1506
1507/* KEXDHGEX */
1508 debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST.");
1509 packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_REQUEST);
1510 nbits = packet_get_int();
1511 dh = choose_dh(nbits);
1512
1513 debug("Sending SSH2_MSG_KEX_DH_GEX_GROUP.");
1514 packet_start(SSH2_MSG_KEX_DH_GEX_GROUP);
1515 packet_put_bignum2(dh->p);
1516 packet_put_bignum2(dh->g);
1435 packet_send(); 1517 packet_send();
1436 packet_write_wait(); 1518 packet_write_wait();
1437 debug("done: send SSH2_MSG_NEWKEYS.");
1438 1519
1439 debug("Wait SSH2_MSG_NEWKEYS."); 1520 debug("Wait SSH2_MSG_KEX_DH_GEX_INIT.");
1440 packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS); 1521 packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_INIT);
1441 debug("GOT SSH2_MSG_NEWKEYS."); 1522
1523 /* key, cert */
1524 dh_client_pub = BN_new();
1525 if (dh_client_pub == NULL)
1526 fatal("dh_client_pub == NULL");
1527 packet_get_bignum2(dh_client_pub, &dlen);
1442 1528
1443#ifdef DEBUG_KEXDH 1529#ifdef DEBUG_KEXDH
1444 /* send 1st encrypted/maced/compressed message */ 1530 fprintf(stderr, "\ndh_client_pub= ");
1445 packet_start(SSH2_MSG_IGNORE); 1531 BN_print_fp(stderr, dh_client_pub);
1446 packet_put_cstring("markus"); 1532 fprintf(stderr, "\n");
1533 debug("bits %d", BN_num_bits(dh_client_pub));
1534#endif
1535
1536#ifdef DEBUG_KEXDH
1537 fprintf(stderr, "\np= ");
1538 BN_print_fp(stderr, dh->p);
1539 fprintf(stderr, "\ng= ");
1540 bn_print(dh->g);
1541 fprintf(stderr, "\npub= ");
1542 BN_print_fp(stderr, dh->pub_key);
1543 fprintf(stderr, "\n");
1544 DHparams_print_fp(stderr, dh);
1545#endif
1546 if (!dh_pub_is_valid(dh, dh_client_pub))
1547 packet_disconnect("bad client public DH value");
1548
1549 klen = DH_size(dh);
1550 kbuf = xmalloc(klen);
1551 kout = DH_compute_key(kbuf, dh_client_pub, dh);
1552
1553#ifdef DEBUG_KEXDH
1554 debug("shared secret: len %d/%d", klen, kout);
1555 fprintf(stderr, "shared secret == ");
1556 for (i = 0; i< kout; i++)
1557 fprintf(stderr, "%02x", (kbuf[i])&0xff);
1558 fprintf(stderr, "\n");
1559#endif
1560 shared_secret = BN_new();
1561
1562 BN_bin2bn(kbuf, kout, shared_secret);
1563 memset(kbuf, 0, klen);
1564 xfree(kbuf);
1565
1566 /* XXX precompute? */
1567 dsa_make_key_blob(sensitive_data.dsa_host_key,
1568 &server_host_key_blob, &sbloblen);
1569
1570 /* calc H */ /* XXX depends on 'kex' */
1571 hash = kex_hash_gex(
1572 client_version_string,
1573 server_version_string,
1574 buffer_ptr(client_kexinit), buffer_len(client_kexinit),
1575 buffer_ptr(server_kexinit), buffer_len(server_kexinit),
1576 (char *)server_host_key_blob, sbloblen,
1577 nbits, dh->p, dh->g,
1578 dh_client_pub,
1579 dh->pub_key,
1580 shared_secret
1581 );
1582 buffer_free(client_kexinit);
1583 buffer_free(server_kexinit);
1584 xfree(client_kexinit);
1585 xfree(server_kexinit);
1586#ifdef DEBUG_KEXDH
1587 fprintf(stderr, "hash == ");
1588 for (i = 0; i< 20; i++)
1589 fprintf(stderr, "%02x", (hash[i])&0xff);
1590 fprintf(stderr, "\n");
1591#endif
1592 /* save session id := H */
1593 /* XXX hashlen depends on KEX */
1594 session_id2_len = 20;
1595 session_id2 = xmalloc(session_id2_len);
1596 memcpy(session_id2, hash, session_id2_len);
1597
1598 /* sign H */
1599 /* XXX hashlen depends on KEX */
1600 dsa_sign(sensitive_data.dsa_host_key, &signature, &slen, hash, 20);
1601
1602 destroy_sensitive_data();
1603
1604 /* send server hostkey, DH pubkey 'f' and singed H */
1605 packet_start(SSH2_MSG_KEX_DH_GEX_REPLY);
1606 packet_put_string((char *)server_host_key_blob, sbloblen);
1607 packet_put_bignum2(dh->pub_key); /* f */
1608 packet_put_string((char *)signature, slen);
1447 packet_send(); 1609 packet_send();
1610 xfree(signature);
1611 xfree(server_host_key_blob);
1448 packet_write_wait(); 1612 packet_write_wait();
1449#endif 1613
1450 debug("done: KEX2."); 1614 kex_derive_keys(kex, hash, shared_secret);
1615 packet_set_kex(kex);
1616
1617 /* have keys, free DH */
1618 DH_free(dh);
1451} 1619}
1620
diff --git a/sshd_config b/sshd_config
index 43d2e8ea6..3b88062fa 100644
--- a/sshd_config
+++ b/sshd_config
@@ -37,6 +37,7 @@ PasswordAuthentication yes
37PermitEmptyPasswords no 37PermitEmptyPasswords no
38# Uncomment to disable s/key passwords 38# Uncomment to disable s/key passwords
39#SkeyAuthentication no 39#SkeyAuthentication no
40#KbdInteractiveAuthentication yes
40 41
41# To change Kerberos options 42# To change Kerberos options
42#KerberosAuthentication no 43#KerberosAuthentication no