diff options
-rw-r--r-- | ChangeLog | 75 | ||||
-rw-r--r-- | Makefile.in | 6 | ||||
-rw-r--r-- | auth-krb4.c | 16 | ||||
-rw-r--r-- | auth-options.c | 48 | ||||
-rw-r--r-- | auth-options.h | 3 | ||||
-rw-r--r-- | auth-pam.c | 4 | ||||
-rw-r--r-- | auth-passwd.c | 4 | ||||
-rw-r--r-- | auth-rh-rsa.c | 6 | ||||
-rw-r--r-- | auth-rhosts.c | 5 | ||||
-rw-r--r-- | auth-rsa.c | 13 | ||||
-rw-r--r-- | auth.c | 3 | ||||
-rw-r--r-- | auth.h | 20 | ||||
-rw-r--r-- | auth1.c | 246 | ||||
-rw-r--r-- | auth2.c | 428 | ||||
-rw-r--r-- | authfd.c | 13 | ||||
-rw-r--r-- | authfd.h | 6 | ||||
-rw-r--r-- | authfile.c | 44 | ||||
-rw-r--r-- | bsd-vis.c | 137 | ||||
-rw-r--r-- | bsd-vis.h | 32 | ||||
-rw-r--r-- | cipher.c | 707 | ||||
-rw-r--r-- | cipher.h | 129 | ||||
-rw-r--r-- | cli.c | 195 | ||||
-rw-r--r-- | cli.h | 14 | ||||
-rw-r--r-- | compat.c | 41 | ||||
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | dh.c | 157 | ||||
-rw-r--r-- | dh.h | 35 | ||||
-rw-r--r-- | includes.h | 4 | ||||
-rw-r--r-- | kex.c | 169 | ||||
-rw-r--r-- | kex.h | 35 | ||||
-rw-r--r-- | log.c | 3 | ||||
-rw-r--r-- | myproposal.h | 10 | ||||
-rw-r--r-- | openbsd-compat.h | 1 | ||||
-rw-r--r-- | packet.c | 72 | ||||
-rw-r--r-- | readconf.c | 20 | ||||
-rw-r--r-- | readconf.h | 4 | ||||
-rw-r--r-- | readpass.c | 82 | ||||
-rw-r--r-- | rijndael.c | 493 | ||||
-rw-r--r-- | rijndael.h | 31 | ||||
-rw-r--r-- | scp.1 | 9 | ||||
-rw-r--r-- | scp.c | 155 | ||||
-rw-r--r-- | servconf.c | 12 | ||||
-rw-r--r-- | servconf.h | 3 | ||||
-rw-r--r-- | session.c | 3 | ||||
-rw-r--r-- | sftp-server.8 | 2 | ||||
-rw-r--r-- | ssh-keygen.1 | 5 | ||||
-rw-r--r-- | ssh-keygen.c | 105 | ||||
-rw-r--r-- | ssh.1 | 8 | ||||
-rw-r--r-- | ssh.c | 23 | ||||
-rw-r--r-- | ssh.h | 13 | ||||
-rw-r--r-- | ssh2.h | 8 | ||||
-rw-r--r-- | sshconnect1.c | 15 | ||||
-rw-r--r-- | sshconnect2.c | 461 | ||||
-rw-r--r-- | sshd.8 | 16 | ||||
-rw-r--r-- | sshd.c | 225 | ||||
-rw-r--r-- | sshd_config | 1 |
56 files changed, 3173 insertions, 1206 deletions
@@ -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 | ||
7 | 20001007 | 82 | 20001007 |
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 | ||
36 | TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) $(EXTRA_TARGETS) | 36 | TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) $(EXTRA_TARGETS) |
37 | 37 | ||
38 | LIBSSH_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 | 38 | LIBSSH_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 | ||
40 | LIBOPENBSD_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 | 40 | LIBOPENBSD_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 | ||
42 | SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o | 42 | SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o |
43 | 43 | ||
44 | SSHDOBJS= 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 | 44 | SSHDOBJS= 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 | ||
46 | TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 sftp-server.8 | 46 | TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 sftp-server.8 |
47 | CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0 sftp-server.0 | 47 | CATMAN = 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 | ||
31 | RCSID("$OpenBSD: auth-krb4.c,v 1.18 2000/09/07 20:27:49 deraadt Exp $"); | 31 | RCSID("$OpenBSD: auth-krb4.c,v 1.19 2000/10/03 18:03:02 markus Exp $"); |
32 | 32 | ||
33 | #ifdef KRB4 | 33 | #ifdef KRB4 |
34 | char *ticket = NULL; | 34 | char *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 | |||
334 | auth_afs_token(struct passwd *pw, const char *token_string) | 336 | auth_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" |
17 | RCSID("$OpenBSD: auth-options.c,v 1.4 2000/09/07 21:13:36 markus Exp $"); | 17 | RCSID("$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. */ |
34 | struct envstring *custom_environment = NULL; | 34 | struct envstring *custom_environment = NULL; |
35 | 35 | ||
36 | void | ||
37 | auth_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 */ |
37 | int | 56 | int |
38 | auth_parse_options(struct passwd *pw, char *options, unsigned long linenum) | 57 | auth_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 */ |
24 | int auth_parse_options(struct passwd *pw, char *options, unsigned long linenum); | 24 | int auth_parse_options(struct passwd *pw, char *options, unsigned long linenum); |
25 | /* reset options flags */ | ||
26 | void 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 | ||
32 | RCSID("$Id: auth-pam.c,v 1.15 2000/10/14 00:16:12 djm Exp $"); | 32 | RCSID("$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" |
62 | RCSID("$OpenBSD: auth-passwd.c,v 1.17 2000/09/07 20:27:49 deraadt Exp $"); | 62 | RCSID("$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" |
16 | RCSID("$OpenBSD: auth-rh-rsa.c,v 1.16 2000/09/07 21:13:36 markus Exp $"); | 16 | RCSID("$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" |
17 | RCSID("$OpenBSD: auth-rhosts.c,v 1.15 2000/09/07 20:27:49 deraadt Exp $"); | 17 | RCSID("$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" |
17 | RCSID("$OpenBSD: auth-rsa.c,v 1.29 2000/09/07 21:13:36 markus Exp $"); | 17 | RCSID("$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 */ | ||
34 | extern 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) | |||
116 | int | 120 | int |
117 | auth_rsa(struct passwd *pw, BIGNUM *client_n) | 121 | auth_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; |
@@ -33,7 +33,7 @@ | |||
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include "includes.h" | 35 | #include "includes.h" |
36 | RCSID("$OpenBSD: auth.c,v 1.10 2000/09/07 21:13:36 markus Exp $"); | 36 | RCSID("$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" |
@@ -24,17 +24,29 @@ | |||
24 | #ifndef AUTH_H | 24 | #ifndef AUTH_H |
25 | #define AUTH_H | 25 | #define AUTH_H |
26 | 26 | ||
27 | typedef struct Authctxt Authctxt; | ||
28 | struct Authctxt { | ||
29 | int success; | ||
30 | int valid; | ||
31 | int attempt; | ||
32 | char *user; | ||
33 | char *service; | ||
34 | struct passwd *pw; | ||
35 | }; | ||
36 | |||
27 | void do_authentication(void); | 37 | void do_authentication(void); |
28 | void do_authentication2(void); | 38 | void do_authentication2(void); |
29 | 39 | ||
30 | struct passwd * | 40 | void userauth_log(Authctxt *authctxt, int authenticated, char *method); |
31 | auth_get_user(void); | 41 | void userauth_reply(Authctxt *authctxt, int authenticated); |
42 | |||
43 | int auth2_skey(Authctxt *authctxt); | ||
32 | 44 | ||
33 | int allowed_user(struct passwd * pw); | 45 | int allowed_user(struct passwd * pw); |
46 | struct 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 | |||
@@ -10,28 +10,31 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include "includes.h" | 12 | #include "includes.h" |
13 | RCSID("$OpenBSD: auth1.c,v 1.4 2000/09/07 20:27:49 deraadt Exp $"); | 13 | RCSID("$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 */ |
33 | extern ServerOptions options; | 32 | extern ServerOptions options; |
34 | extern char *forced_command; | 33 | extern char *forced_command; |
34 | |||
35 | #ifdef WITH_AIXAUTHENTICATE | ||
36 | extern char *aixloginmsg; | ||
37 | #endif /* WITH_AIXAUTHENTICATE */ | ||
35 | #ifdef HAVE_OSF_SIA | 38 | #ifdef HAVE_OSF_SIA |
36 | extern int saved_argc; | 39 | extern int saved_argc; |
37 | extern char **saved_argv; | 40 | extern 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 | */ |
73 | void | 79 | void |
74 | do_fake_authloop1(char *user) | 80 | do_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 | */ | ||
145 | void | ||
146 | do_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); |
@@ -23,7 +23,12 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: auth2.c,v 1.16 2000/09/27 21:41:34 markus Exp $"); | 26 | RCSID("$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 */ |
61 | extern ServerOptions options; | 60 | extern ServerOptions options; |
62 | extern unsigned char *session_id2; | 61 | extern unsigned char *session_id2; |
63 | extern int session_id2_len; | 62 | extern int session_id2_len; |
64 | 63 | ||
64 | #ifdef WITH_AIXAUTHENTICATE | ||
65 | extern char *aixloginmsg; | ||
66 | #endif | ||
67 | #ifdef HAVE_OSF_SIA | ||
68 | extern int saved_argc; | ||
69 | extern char **saved_argv; | ||
70 | #endif | ||
71 | |||
72 | static Authctxt *x_authctxt = NULL; | ||
73 | static int one = 1; | ||
74 | |||
75 | typedef struct Authmethod Authmethod; | ||
76 | struct Authmethod { | ||
77 | char *name; | ||
78 | int (*userauth)(Authctxt *authctxt); | ||
79 | int *enabled; | ||
80 | }; | ||
81 | |||
65 | /* protocol */ | 82 | /* protocol */ |
66 | 83 | ||
67 | void input_service_request(int type, int plen, void *ctxt); | 84 | void input_service_request(int type, int plen, void *ctxt); |
68 | void input_userauth_request(int type, int plen, void *ctxt); | 85 | void input_userauth_request(int type, int plen, void *ctxt); |
69 | void protocol_error(int type, int plen, void *ctxt); | 86 | void protocol_error(int type, int plen, void *ctxt); |
70 | 87 | ||
71 | /* auth */ | ||
72 | int ssh2_auth_none(struct passwd *pw); | ||
73 | int ssh2_auth_password(struct passwd *pw); | ||
74 | int ssh2_auth_pubkey(struct passwd *pw, char *service); | ||
75 | 88 | ||
76 | /* helper */ | 89 | /* helper */ |
77 | struct passwd* auth_set_user(char *u, char *s); | 90 | Authmethod *authmethod_lookup(const char *name); |
91 | struct passwd *pwcopy(struct passwd *pw); | ||
78 | int user_dsa_key_allowed(struct passwd *pw, Key *key); | 92 | int user_dsa_key_allowed(struct passwd *pw, Key *key); |
93 | char *authmethods_get(void); | ||
79 | 94 | ||
80 | typedef struct Authctxt Authctxt; | 95 | /* auth */ |
81 | struct Authctxt { | 96 | int userauth_none(Authctxt *authctxt); |
82 | char *user; | 97 | int userauth_passwd(Authctxt *authctxt); |
83 | char *service; | 98 | int userauth_pubkey(Authctxt *authctxt); |
84 | struct passwd pw; | 99 | int userauth_kbdint(Authctxt *authctxt); |
85 | int valid; | 100 | |
101 | Authmethod 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 | }; |
87 | static Authctxt *authctxt = NULL; | ||
88 | static int userauth_success = 0; | ||
89 | 116 | ||
90 | /* | 117 | /* |
91 | * loop until userauth_success == TRUE | 118 | * loop until authctxt->success == TRUE |
92 | */ | 119 | */ |
93 | 120 | ||
94 | void | 121 | void |
95 | do_authentication2() | 122 | do_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) | |||
121 | void | 151 | void |
122 | input_service_request(int type, int plen, void *ctxt) | 152 | input_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) | |||
150 | void | 184 | void |
151 | input_userauth_request(int type, int plen, void *ctxt) | 185 | input_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 | |||
267 | void | ||
268 | userauth_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 | ||
302 | void | ||
303 | userauth_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 | ||
254 | int | 333 | int |
255 | ssh2_auth_none(struct passwd *pw) | 334 | userauth_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 | |||
274 | int | 360 | int |
275 | ssh2_auth_password(struct passwd *pw) | 361 | userauth_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 | |||
391 | int | ||
392 | userauth_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 | |||
305 | int | 417 | int |
306 | ssh2_auth_pubkey(struct passwd *pw, char *service) | 418 | userauth_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 | ||
388 | struct passwd* | 506 | struct passwd* |
389 | auth_get_user(void) | 507 | auth_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 | ||
394 | struct passwd* | 512 | #define DELIM "," |
395 | auth_set_user(char *u, char *s) | 513 | |
514 | char * | ||
515 | authmethods_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 | |||
546 | Authmethod * | ||
547 | authmethod_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 | |||
681 | struct passwd * | ||
682 | pwcopy(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 | } | ||
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | RCSID("$OpenBSD: authfd.c,v 1.28 2000/09/21 11:07:50 markus Exp $"); | 38 | RCSID("$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 */ |
57 | int decode_reply(int type); | 57 | int 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 | ||
61 | int | 65 | int |
@@ -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: |
@@ -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" |
39 | RCSID("$OpenBSD: authfile.c,v 1.19 2000/09/07 20:27:49 deraadt Exp $"); | 39 | RCSID("$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) | ||
35 | static 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 | */ | ||
47 | char *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 | } | ||
133 | done: | ||
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 | |||
29 | char *vis (char *, int, int, int); | ||
30 | #endif /* HAVE_VIS */ | ||
31 | |||
32 | #endif /* _BSD_VIS_H */ | ||
@@ -35,14 +35,91 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | RCSID("$OpenBSD: cipher.c,v 1.31 2000/09/12 00:38:32 deraadt Exp $"); | 38 | RCSID("$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 */ | ||
47 | void | ||
48 | none_setkey(CipherContext *cc, const u_char *key, u_int keylen) | ||
49 | { | ||
50 | } | ||
51 | void | ||
52 | none_setiv(CipherContext *cc, const u_char *iv, u_int ivlen) | ||
53 | { | ||
54 | } | ||
55 | void | ||
56 | none_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) | ||
57 | { | ||
58 | memcpy(dest, src, len); | ||
59 | } | ||
60 | |||
61 | /* DES */ | ||
62 | void | ||
63 | des_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 | } | ||
73 | void | ||
74 | des_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 | } | ||
78 | void | ||
79 | des_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 | } | ||
84 | void | ||
85 | des_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 */ | ||
92 | void | ||
93 | des3_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 | } | ||
99 | void | ||
100 | des3_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 | } | ||
108 | void | ||
109 | des3_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 | } | ||
115 | void | ||
116 | des3_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 | */ |
60 | void | 137 | void |
61 | SSH_3CBC_ENCRYPT(des_key_schedule ks1, | 138 | des3_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 | } | ||
147 | void | ||
148 | des3_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 | |||
81 | void | 166 | void |
82 | SSH_3CBC_DECRYPT(des_key_schedule ks1, | 167 | des3_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 */ | ||
188 | void | ||
189 | blowfish_setkey(CipherContext *cc, const u_char *key, u_int keylen) | ||
190 | { | ||
191 | BF_set_key(&cc->u.bf.key, keylen, (unsigned char *)key); | ||
192 | } | ||
193 | void | ||
194 | blowfish_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 | } | ||
201 | void | ||
202 | blowfish_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 | } | ||
208 | void | ||
209 | blowfish_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 | /* | 246 | void |
134 | * Names of all encryption algorithms. | 247 | blowfish_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 | { |
137 | static 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", | 255 | void |
143 | "tss", | 256 | blowfish_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 | 266 | void |
155 | * implementation. The bit mask has the corresponding bit set of each | 267 | arcfour_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 | } | ||
271 | void | ||
272 | arcfour_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 | ||
159 | unsigned int | 277 | /* CAST */ |
160 | cipher_mask1() | 278 | void |
279 | cast_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; | 283 | void |
165 | return mask; | 284 | cast_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 | } | ||
290 | void | ||
291 | cast_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 | } | ||
296 | void | ||
297 | cast_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 | ||
306 | void | ||
307 | rijndael_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 | } | ||
312 | void | ||
313 | rijndael_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 | } |
319 | void | ||
320 | rijndael_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 | |||
346 | void | ||
347 | rijndael_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 | |||
373 | Cipher 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 | |||
167 | unsigned int | 440 | unsigned int |
168 | cipher_mask2() | 441 | cipher_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 | } |
177 | unsigned int | 451 | |
178 | cipher_mask() | 452 | Cipher * |
453 | cipher_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. */ | 462 | Cipher * |
184 | 463 | cipher_by_number(int id) | |
185 | const char * | ||
186 | cipher_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 "," |
197 | int | 473 | int |
198 | ciphers_valid(const char *names) | 474 | ciphers_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) | |||
224 | int | 504 | int |
225 | cipher_number(const char *name) | 505 | cipher_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; | 514 | char * |
515 | cipher_name(int id) | ||
516 | { | ||
517 | Cipher *c = cipher_by_number(id); | ||
518 | return (c==NULL) ? "<unknown>" : c->name; | ||
519 | } | ||
520 | |||
521 | void | ||
522 | cipher_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 | |||
536 | void | ||
537 | cipher_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 | |||
544 | void | ||
545 | cipher_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 | ||
242 | void | 557 | void |
243 | cipher_set_key_string(CipherContext *context, int cipher, const char *passphrase) | 558 | cipher_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 | |||
260 | void | ||
261 | cipher_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 | |||
321 | void | ||
322 | cipher_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 | |||
381 | void | ||
382 | cipher_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 | |||
436 | void | ||
437 | cipher_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 | } | ||
@@ -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: */ | 62 | typedef struct Cipher Cipher; |
37 | #define SSH_CIPHER_BLOWFISH_CBC 8 | 63 | typedef 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 | ||
42 | typedef struct { | 65 | struct 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 | 95 | struct 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; |
68 | unsigned int cipher_mask(); | 99 | u_int key_len; |
69 | unsigned int cipher_mask1(); | 100 | void (*setkey)(CipherContext *, const u_char *, u_int); |
70 | unsigned 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); |
73 | const 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 | */ | ||
79 | int cipher_number(const char *name); | ||
80 | |||
81 | /* returns 1 if all ciphers are supported (ssh2 only) */ | ||
82 | int 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 | */ | ||
88 | void | ||
89 | cipher_set_key(CipherContext * context, int cipher, | ||
90 | const unsigned char *key, int keylen); | ||
91 | void | ||
92 | cipher_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 | */ | ||
100 | void | ||
101 | cipher_set_key_string(CipherContext * context, int cipher, | ||
102 | const char *passphrase); | ||
103 | |||
104 | /* Encrypts data using the cipher. */ | ||
105 | void | ||
106 | cipher_encrypt(CipherContext * context, unsigned char *dest, | ||
107 | const unsigned char *src, unsigned int len); | ||
108 | 105 | ||
109 | /* Decrypts data using the cipher. */ | 106 | unsigned int cipher_mask_ssh1(int client); |
110 | void | 107 | Cipher *cipher_by_name(const char *name); |
111 | cipher_decrypt(CipherContext * context, unsigned char *dest, | 108 | Cipher *cipher_by_number(int id); |
112 | const unsigned char *src, unsigned int len); | 109 | int cipher_number(const char *name); |
110 | char *cipher_name(int id); | ||
111 | int ciphers_valid(const char *names); | ||
112 | void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, const u_char *, u_int); | ||
113 | void cipher_encrypt(CipherContext *context, u_char *dest, const u_char *src, u_int len); | ||
114 | void cipher_decrypt(CipherContext *context, u_char *dest, const u_char *src, u_int len); | ||
115 | void cipher_set_key_string(CipherContext *context, Cipher *cipher, const char *passphrase); | ||
113 | 116 | ||
114 | #endif /* CIPHER_H */ | 117 | #endif /* CIPHER_H */ |
@@ -0,0 +1,195 @@ | |||
1 | #include "includes.h" | ||
2 | RCSID("$Id: cli.c,v 1.1 2000/10/14 05:23:12 djm Exp $"); | ||
3 | |||
4 | #include "xmalloc.h" | ||
5 | #include "ssh.h" | ||
6 | |||
7 | static int cli_input = -1; | ||
8 | static int cli_output = -1; | ||
9 | static int cli_from_stdin = 0; | ||
10 | |||
11 | sigset_t oset; | ||
12 | sigset_t nset; | ||
13 | struct sigaction nsa; | ||
14 | struct sigaction osa; | ||
15 | struct termios ntio; | ||
16 | struct termios otio; | ||
17 | int echo_modified; | ||
18 | |||
19 | volatile int intr; | ||
20 | |||
21 | static int | ||
22 | cli_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 | |||
44 | static void | ||
45 | cli_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 | |||
55 | void | ||
56 | intrcatch() | ||
57 | { | ||
58 | intr = 1; | ||
59 | } | ||
60 | |||
61 | static void | ||
62 | cli_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 | |||
84 | static void | ||
85 | cli_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 | |||
105 | static int | ||
106 | cli_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 | |||
131 | static int | ||
132 | cli_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 | */ | ||
160 | char* | ||
161 | cli_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 | |||
181 | char* | ||
182 | cli_prompt(char* prompt, int echo_enable) | ||
183 | { | ||
184 | return cli_read_passphrase(prompt, 0, echo_enable); | ||
185 | } | ||
186 | |||
187 | void | ||
188 | cli_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 | } | ||
@@ -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 | */ | ||
10 | char* cli_read_passphrase(char* prompt, int from_stdin, int echo_enable); | ||
11 | char* cli_prompt(char* prompt, int echo_enable); | ||
12 | void cli_mesg(char* mesg); | ||
13 | |||
14 | #endif /* CLI_H */ | ||
@@ -23,12 +23,13 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: compat.c,v 1.23 2000/09/07 21:13:37 markus Exp $"); | 26 | RCSID("$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 | ||
33 | int compat13 = 0; | 34 | int compat13 = 0; |
34 | int compat20 = 0; | 35 | int compat20 = 0; |
@@ -50,27 +51,39 @@ enable_compat13(void) | |||
50 | void | 51 | void |
51 | compat_datafellows(const char *version) | 52 | compat_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(®, 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, ®, 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(®, version, 0, NULL, 0); | ||
79 | regfree(®); | ||
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 | |||
265 | fi | 265 | fi |
266 | 266 | ||
267 | # Checks for header files. | 267 | # Checks for header files. |
268 | AC_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) | 268 | AC_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 | ||
270 | dnl Checks for library functions. | 270 | dnl Checks for library functions. |
271 | AC_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) | 271 | AC_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) |
272 | dnl Checks for time functions | 272 | dnl Checks for time functions |
273 | AC_CHECK_FUNCS(gettimeofday time) | 273 | AC_CHECK_FUNCS(gettimeofday time) |
274 | dnl Checks for libutil functions | 274 | dnl Checks for libutil functions |
@@ -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" | ||
26 | RCSID("$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 | |||
39 | int | ||
40 | parse_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 | |||
94 | DH * | ||
95 | choose_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 | } | ||
@@ -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 | |||
27 | struct dhgroup { | ||
28 | int size; | ||
29 | BIGNUM *g; | ||
30 | BIGNUM *p; | ||
31 | }; | ||
32 | |||
33 | DH *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" |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: kex.c,v 1.10 2000/09/07 20:27:51 deraadt Exp $"); | 26 | RCSID("$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 | ||
147 | DH * | 141 | DH * |
148 | dh_new_group1() | 142 | dh_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 | ||
155 | DH * | ||
156 | dh_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 | |||
173 | DH * | ||
174 | dh_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 | |||
187 | DH * | ||
188 | dh_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 | |||
178 | void | 201 | void |
179 | dump_digest(unsigned char *digest, int len) | 202 | dump_digest(unsigned char *digest, int len) |
180 | { | 203 | { |
@@ -237,6 +260,59 @@ kex_hash( | |||
237 | } | 260 | } |
238 | 261 | ||
239 | unsigned char * | 262 | unsigned char * |
263 | kex_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 | |||
315 | unsigned char * | ||
240 | derive_key(int id, int need, char unsigned *hash, BIGNUM *shared_secret) | 316 | derive_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 | } |
393 | void | 454 | void |
@@ -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 | } |
@@ -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 | ||
30 | enum kex_init_proposals { | 31 | enum 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 | ||
51 | enum kex_exchange { | ||
52 | DH_GRP1_SHA1, | ||
53 | DH_GEX_SHA1 | ||
54 | }; | ||
55 | |||
50 | typedef struct Kex Kex; | 56 | typedef struct Kex Kex; |
51 | typedef struct Mac Mac; | 57 | typedef struct Mac Mac; |
52 | typedef struct Comp Comp; | 58 | typedef struct Comp Comp; |
53 | typedef struct Enc Enc; | 59 | typedef struct Enc Enc; |
54 | 60 | ||
55 | struct Enc { | 61 | struct 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 | }; |
65 | struct Mac { | 68 | struct 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 | }; |
73 | struct Comp { | 76 | struct 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 | ||
88 | Buffer *kex_init(char *myproposal[PROPOSAL_MAX]); | 92 | Buffer *kex_init(char *myproposal[PROPOSAL_MAX]); |
@@ -96,6 +100,8 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX], | |||
96 | int kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret); | 100 | int kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret); |
97 | void packet_set_kex(Kex *k); | 101 | void packet_set_kex(Kex *k); |
98 | int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub); | 102 | int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub); |
103 | DH *dh_new_group_asc(const char *, const char *); | ||
104 | DH *dh_new_group(BIGNUM *, BIGNUM *); | ||
99 | DH *dh_new_group1(); | 105 | DH *dh_new_group1(); |
100 | 106 | ||
101 | unsigned char * | 107 | unsigned 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 | ||
118 | unsigned char * | ||
119 | kex_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 |
@@ -36,7 +36,7 @@ | |||
36 | */ | 36 | */ |
37 | 37 | ||
38 | #include "includes.h" | 38 | #include "includes.h" |
39 | RCSID("$OpenBSD: log.c,v 1.10 2000/09/12 20:53:10 markus Exp $"); | 39 | RCSID("$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" |
@@ -37,7 +37,7 @@ | |||
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include "includes.h" | 39 | #include "includes.h" |
40 | RCSID("$OpenBSD: packet.c,v 1.35 2000/09/07 20:27:52 deraadt Exp $"); | 40 | RCSID("$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) | |||
161 | void | 161 | void |
162 | packet_set_connection(int fd_in, int fd_out) | 162 | packet_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 | ||
328 | void | 331 | void |
329 | packet_decrypt(CipherContext * cc, void *dest, void *src, | 332 | packet_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 | ||
359 | void | 352 | void |
360 | packet_set_encryption_key(const unsigned char *key, unsigned int keylen, | 353 | packet_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" |
15 | RCSID("$OpenBSD: readconf.c,v 1.47 2000/09/07 21:13:37 markus Exp $"); | 15 | RCSID("$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" |
35 | RCSID("$OpenBSD: readpass.c,v 1.11 2000/06/20 01:39:44 markus Exp $"); | 35 | RCSID("$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" | |
40 | volatile int intr; | ||
41 | |||
42 | void | ||
43 | intcatch() | ||
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 | */ | ||
53 | char * | 51 | char * |
54 | read_passphrase(const char *prompt, int from_stdin) | 52 | read_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 | |||
19 | Algorithm: rijndael (rijndael.c) | ||
20 | |||
21 | 128 bit key: | ||
22 | Key Setup: 305/1389 cycles (encrypt/decrypt) | ||
23 | Encrypt: 374 cycles = 68.4 mbits/sec | ||
24 | Decrypt: 352 cycles = 72.7 mbits/sec | ||
25 | Mean: 363 cycles = 70.5 mbits/sec | ||
26 | |||
27 | 192 bit key: | ||
28 | Key Setup: 277/1595 cycles (encrypt/decrypt) | ||
29 | Encrypt: 439 cycles = 58.3 mbits/sec | ||
30 | Decrypt: 425 cycles = 60.2 mbits/sec | ||
31 | Mean: 432 cycles = 59.3 mbits/sec | ||
32 | |||
33 | 256 bit key: | ||
34 | Key Setup: 374/1960 cycles (encrypt/decrypt) | ||
35 | Encrypt: 502 cycles = 51.0 mbits/sec | ||
36 | Decrypt: 498 cycles = 51.4 mbits/sec | ||
37 | Mean: 500 cycles = 51.2 mbits/sec | ||
38 | |||
39 | */ | ||
40 | |||
41 | #include <sys/types.h> | ||
42 | #include "rijndael.h" | ||
43 | |||
44 | void 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 | |||
158 | u1byte pow_tab[256]; | ||
159 | u1byte log_tab[256]; | ||
160 | u1byte sbx_tab[256]; | ||
161 | u1byte isb_tab[256]; | ||
162 | u4byte rco_tab[ 10]; | ||
163 | u4byte ft_tab[4][256]; | ||
164 | u4byte it_tab[4][256]; | ||
165 | |||
166 | #ifdef LARGE_TABLES | ||
167 | u4byte fl_tab[4][256]; | ||
168 | u4byte il_tab[4][256]; | ||
169 | #endif | ||
170 | |||
171 | u4byte 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 | |||
229 | void | ||
230 | gen_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 | |||
356 | rijndael_ctx * | ||
357 | rijndael_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 | |||
419 | void | ||
420 | rijndael_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 | |||
464 | void | ||
465 | rijndael_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 | |||
6 | typedef u_int8_t u1byte; /* an 8 bit unsigned character type */ | ||
7 | typedef u_int16_t u2byte; /* a 16 bit unsigned integer type */ | ||
8 | typedef u_int32_t u4byte; /* a 32 bit unsigned integer type */ | ||
9 | |||
10 | typedef int8_t s1byte; /* an 8 bit signed character type */ | ||
11 | typedef int16_t s2byte; /* a 16 bit signed integer type */ | ||
12 | typedef int32_t s4byte; /* a 32 bit signed integer type */ | ||
13 | |||
14 | typedef 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 | |||
27 | rijndael_ctx *rijndael_set_key __P((rijndael_ctx *, const u4byte *, u4byte, int)); | ||
28 | void rijndael_encrypt __P((rijndael_ctx *, const u4byte *, u4byte *)); | ||
29 | void rijndael_decrypt __P((rijndael_ctx *, const u4byte *, u4byte *)); | ||
30 | |||
31 | #endif /* _RIJNDAEL_H_ */ | ||
@@ -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 |
103 | Name of | 104 | Name of |
104 | .Ar program | 105 | .Ar program |
105 | to use for the encrypted connection. The program must understand | 106 | to use for the encrypted connection. |
107 | The program must understand | ||
106 | .Xr ssh 1 | 108 | .Xr ssh 1 |
107 | options. | 109 | options. |
110 | .It Fl o Ar option | ||
111 | The given option is directly passed to | ||
112 | .Xr ssh 1 . | ||
108 | .It Fl 4 | 113 | .It Fl 4 |
109 | Forces | 114 | Forces |
110 | .Nm | 115 | .Nm |
@@ -75,7 +75,7 @@ | |||
75 | */ | 75 | */ |
76 | 76 | ||
77 | #include "includes.h" | 77 | #include "includes.h" |
78 | RCSID("$OpenBSD: scp.c,v 1.40 2000/09/21 11:11:42 markus Exp $"); | 78 | RCSID("$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); | |||
102 | int getttywidth(void); | 102 | int getttywidth(void); |
103 | int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); | 103 | int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); |
104 | 104 | ||
105 | /* setup arguments for the call to ssh */ | ||
106 | void addargs(char *fmt, ...) __attribute__((format(printf, 1, 2))); | ||
107 | |||
105 | /* Time a transfer started. */ | 108 | /* Time a transfer started. */ |
106 | static struct timeval start; | 109 | static 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. */ |
115 | char *curfile; | 118 | char *curfile; |
116 | 119 | ||
117 | /* This is set to non-zero if IPv4 is desired. */ | ||
118 | int IPv4 = 0; | ||
119 | |||
120 | /* This is set to non-zero if IPv6 is desired. */ | ||
121 | int 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. */ |
124 | int verbose_mode = 0; | 121 | int 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. */ |
130 | int showprogress = 1; | 127 | int 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). */ | ||
134 | int batchmode = 0; | ||
135 | |||
136 | /* This is set to the cipher type string if given on the command line. */ | ||
137 | char *cipher = NULL; | ||
138 | |||
139 | /* This is set to the RSA authentication identity file name if given on | ||
140 | the command line. */ | ||
141 | char *identity = NULL; | ||
142 | |||
143 | /* This is the port to use in contacting the remote site (is non-NULL). */ | ||
144 | char *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) */ |
147 | char *ssh_program = SSH_PROGRAM; | 130 | char *ssh_program = SSH_PROGRAM; |
148 | 131 | ||
132 | /* This is the list of arguments that scp passes to ssh */ | ||
133 | struct { | ||
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 | |||
1250 | void | ||
1251 | addargs(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" |
13 | RCSID("$OpenBSD: servconf.c,v 1.51 2000/09/07 20:27:53 deraadt Exp $"); | 13 | RCSID("$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. */ |
@@ -33,14 +33,13 @@ | |||
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include "includes.h" | 35 | #include "includes.h" |
36 | RCSID("$OpenBSD: session.c,v 1.37 2000/09/07 20:27:53 deraadt Exp $"); | 36 | RCSID("$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. | |||
168 | This option will read a private | 168 | This option will read a private |
169 | OpenSSH DSA format file and print a SSH2-compatible public key to stdout. | 169 | OpenSSH DSA format file and print a SSH2-compatible public key to stdout. |
170 | .It Fl X | 170 | .It Fl X |
171 | This option will read a | 171 | This option will read a unencrypted |
172 | SSH2-compatible public key file and print an OpenSSH DSA compatible public key to stdout. | 172 | SSH2-compatible private (or public) key file and |
173 | print an OpenSSH compatible private (or public) key to stdout. | ||
173 | .It Fl y | 174 | .It Fl y |
174 | This option will read a private | 175 | This option will read a private |
175 | OpenSSH DSA format file and print an OpenSSH DSA public key to stdout. | 176 | OpenSSH 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" |
15 | RCSID("$OpenBSD: ssh-keygen.c,v 1.31 2000/09/07 20:27:54 deraadt Exp $"); | 15 | RCSID("$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. */ |
31 | int bits = 1024; | 34 | int 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 | ||
114 | void | 119 | void |
115 | do_convert_to_ssh2(struct passwd *pw) | 120 | do_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 | ||
146 | void | 151 | void |
152 | buffer_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 | |||
162 | Key * | ||
163 | do_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 | |||
216 | void | ||
147 | do_convert_from_ssh2(struct passwd *pw) | 217 | do_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); |
@@ -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" |
376 | Additionally, for protocol version 2 a comma-separated list of ciphers can | 376 | Additionally, for protocol version 2 a comma-separated list of ciphers can |
377 | be specified in order of preference. Protocol version 2 supports | 377 | be specified in order of preference. |
378 | 3DES, Blowfish and CAST128 in CBC mode and Arcfour. | 378 | Protocol version 2 supports 3DES, Blowfish, and CAST128 in CBC mode |
379 | and Arcfour. | ||
379 | .It Fl e Ar ch|^ch|none | 380 | .It Fl e Ar ch|^ch|none |
380 | Sets the escape character for sessions with a pty (default: | 381 | Sets the escape character for sessions with a pty (default: |
381 | .Ql ~ ) . | 382 | .Ql ~ ) . |
@@ -483,7 +484,8 @@ debugging connection, authentication, and configuration problems. | |||
483 | The verbose mode is also used to display | 484 | The verbose mode is also used to display |
484 | .Xr skey 1 | 485 | .Xr skey 1 |
485 | challenges, if the user entered "s/key" as password. | 486 | challenges, if the user entered "s/key" as password. |
486 | Multiple -v options increases the verbosity. Maximum is 3. | 487 | Multiple -v options increases the verbosity. |
488 | Maximum is 3. | ||
487 | .It Fl x | 489 | .It Fl x |
488 | Disables X11 forwarding. | 490 | Disables X11 forwarding. |
489 | .It Fl X | 491 | .It Fl X |
@@ -39,7 +39,7 @@ | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | #include "includes.h" | 41 | #include "includes.h" |
42 | RCSID("$OpenBSD: ssh.c,v 1.66 2000/09/12 20:53:10 markus Exp $"); | 42 | RCSID("$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 */ |
@@ -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 | */ |
426 | char *read_passphrase(const char *prompt, int from_stdin); | 419 | char *read_passphrase(char *prompt, int from_stdin); |
427 | 420 | ||
428 | 421 | ||
429 | /*------------ Definitions for logging. -----------------------*/ | 422 | /*------------ Definitions for logging. -----------------------*/ |
@@ -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" |
16 | RCSID("$OpenBSD: sshconnect1.c,v 1.6 2000/09/07 20:27:54 deraadt Exp $"); | 16 | RCSID("$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" |
26 | RCSID("$OpenBSD: sshconnect2.c,v 1.21 2000/09/27 21:41:34 markus Exp $"); | 26 | RCSID("$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 | ||
55 | void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *); | ||
56 | void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *); | ||
57 | |||
55 | /* import */ | 58 | /* import */ |
56 | extern char *client_version_string; | 59 | extern char *client_version_string; |
57 | extern char *server_version_string; | 60 | extern char *server_version_string; |
@@ -65,8 +68,90 @@ unsigned char *session_id2 = NULL; | |||
65 | int session_id2_len = 0; | 68 | int session_id2_len = 0; |
66 | 69 | ||
67 | void | 70 | void |
68 | ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr, | 71 | ssh_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 | |||
152 | void | ||
153 | ssh_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 | |||
282 | int | ||
283 | dh_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 | |||
189 | void | 295 | void |
190 | ssh_kex2(char *host, struct sockaddr *hostaddr) | 296 | ssh_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 | }; |
276 | struct Authmethod { | 464 | struct 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 { | |||
283 | void input_userauth_success(int type, int plen, void *ctxt); | 471 | void input_userauth_success(int type, int plen, void *ctxt); |
284 | void input_userauth_failure(int type, int plen, void *ctxt); | 472 | void input_userauth_failure(int type, int plen, void *ctxt); |
285 | void input_userauth_error(int type, int plen, void *ctxt); | 473 | void input_userauth_error(int type, int plen, void *ctxt); |
474 | void input_userauth_info_req(int type, int plen, void *ctxt); | ||
475 | |||
476 | int userauth_none(Authctxt *authctxt); | ||
286 | int userauth_pubkey(Authctxt *authctxt); | 477 | int userauth_pubkey(Authctxt *authctxt); |
287 | int userauth_passwd(Authctxt *authctxt); | 478 | int userauth_passwd(Authctxt *authctxt); |
479 | int userauth_kbdint(Authctxt *authctxt); | ||
288 | 480 | ||
289 | void authmethod_clear(); | 481 | void authmethod_clear(); |
290 | Authmethod *authmethod_get(char *auth_list); | 482 | Authmethod *authmethod_get(char *authlist); |
483 | Authmethod *authmethod_lookup(const char *name); | ||
291 | 484 | ||
292 | Authmethod authmethods[] = { | 485 | Authmethod 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 | } |
359 | void | 556 | void |
360 | input_userauth_error(int type, int plen, void *ctxt) | 557 | input_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 | ||
408 | int | 604 | int |
605 | userauth_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 | |||
617 | int | ||
409 | userauth_passwd(Authctxt *authctxt) | 618 | userauth_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 | */ | ||
822 | int | ||
823 | userauth_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 | */ | ||
849 | void | ||
850 | input_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; |
@@ -186,7 +186,8 @@ The server sends verbose debug output to the system | |||
186 | log, and does not put itself in the background. | 186 | log, and does not put itself in the background. |
187 | The server also will not fork and will only process one connection. | 187 | The server also will not fork and will only process one connection. |
188 | This option is only intended for debugging for the server. | 188 | This option is only intended for debugging for the server. |
189 | Multiple -d options increases the debugging level. Maximum is 3. | 189 | Multiple -d options increases the debugging level. |
190 | Maximum is 3. | ||
190 | .It Fl f Ar configuration_file | 191 | .It Fl f Ar configuration_file |
191 | Specifies the name of the configuration file. | 192 | Specifies the name of the configuration file. |
192 | The default is | 193 | The default is |
@@ -255,12 +256,13 @@ file. | |||
255 | .It Fl Q | 256 | .It Fl Q |
256 | Do not print an error message if RSA support is missing. | 257 | Do 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 |
258 | SSH2 compatibility mode. | 259 | SSH-2 compatibility mode. |
259 | When this option is specified | 260 | When this option is specified |
260 | .Nm | 261 | .Nm |
261 | assumes the client has sent the supplied version string | 262 | assumes the client has sent the supplied version string |
262 | and skips the | 263 | and skips the |
263 | Protocol Version Identification Exchange. | 264 | Protocol Version Identification Exchange. |
265 | This option is not intended to be called directly. | ||
264 | .It Fl 4 | 266 | .It Fl 4 |
265 | Forces | 267 | Forces |
266 | .Nm | 268 | .Nm |
@@ -424,7 +426,8 @@ Specifies whether Kerberos authentication is allowed. | |||
424 | This can be in the form of a Kerberos ticket, or if | 426 | This can be in the form of a Kerberos ticket, or if |
425 | .Cm PasswordAuthentication | 427 | .Cm PasswordAuthentication |
426 | is yes, the password provided by the user will be validated through | 428 | is yes, the password provided by the user will be validated through |
427 | the Kerberos KDC. To use this option, the server needs a | 429 | the Kerberos KDC. |
430 | To use this option, the server needs a | ||
428 | Kerberos servtab which allows the verification of the KDC's identity. | 431 | Kerberos servtab which allows the verification of the KDC's identity. |
429 | Default is | 432 | Default is |
430 | .Dq yes . | 433 | .Dq yes . |
@@ -488,7 +491,7 @@ The default is 10. | |||
488 | Alternatively, random early drop can be enabled by specifying | 491 | Alternatively, random early drop can be enabled by specifying |
489 | the three colon separated values | 492 | the 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 |
493 | will refuse connection attempts with a probabillity of | 496 | will refuse connection attempts with a probabillity of |
494 | .Dq rate/100 | 497 | .Dq rate/100 |
@@ -610,8 +613,9 @@ directory or files world-writable. | |||
610 | The default is | 613 | The default is |
611 | .Dq yes . | 614 | .Dq yes . |
612 | .It Cm Subsystem | 615 | .It Cm Subsystem |
613 | Configures an external subsystem (e.g. file transfer daemon). | 616 | Configures an external subsystem (e.g., file transfer daemon). |
614 | Arguments should be a subsystem name and a command to execute upon subsystem request. | 617 | Arguments should be a subsystem name and a command to execute upon subsystem |
618 | request. | ||
615 | The command | 619 | The command |
616 | .Xr sftp-server 8 | 620 | .Xr sftp-server 8 |
617 | implements the | 621 | implements the |
@@ -40,14 +40,13 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: sshd.c,v 1.128 2000/09/17 15:38:59 markus Exp $"); | 43 | RCSID("$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; | |||
172 | void do_ssh1_kex(); | 172 | void do_ssh1_kex(); |
173 | void do_ssh2_kex(); | 173 | void do_ssh2_kex(); |
174 | 174 | ||
175 | void ssh_dh1_server(Kex *, Buffer *_kexinit, Buffer *); | ||
176 | void 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 | |||
1365 | void | ||
1366 | ssh_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 | |
1489 | void | ||
1490 | ssh_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 | |||
37 | PermitEmptyPasswords no | 37 | PermitEmptyPasswords 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 |