diff options
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | Makefile.in | 16 | ||||
-rw-r--r-- | auth-rh-rsa.c | 6 | ||||
-rw-r--r-- | auth1.c | 2 | ||||
-rw-r--r-- | auth2.c | 38 | ||||
-rw-r--r-- | authfd.c | 76 | ||||
-rw-r--r-- | authfd.h | 7 | ||||
-rw-r--r-- | authfile.c | 136 | ||||
-rw-r--r-- | channels.c | 159 | ||||
-rw-r--r-- | channels.h | 18 | ||||
-rw-r--r-- | clientloop.c | 122 | ||||
-rwxr-xr-x | contrib/redhat/sshd.init | 27 | ||||
-rw-r--r-- | hostfile.c | 12 | ||||
-rw-r--r-- | kex.c | 12 | ||||
-rw-r--r-- | kex.h | 2 | ||||
-rw-r--r-- | key.c | 388 | ||||
-rw-r--r-- | key.h | 28 | ||||
-rw-r--r-- | myproposal.h | 2 | ||||
-rw-r--r-- | nchan.c | 6 | ||||
-rw-r--r-- | readconf.c | 55 | ||||
-rw-r--r-- | readconf.h | 9 | ||||
-rw-r--r-- | rsa.c | 79 | ||||
-rw-r--r-- | rsa.h | 13 | ||||
-rw-r--r-- | servconf.c | 57 | ||||
-rw-r--r-- | servconf.h | 9 | ||||
-rw-r--r-- | serverloop.c | 128 | ||||
-rw-r--r-- | session.c | 17 | ||||
-rw-r--r-- | sftp-server.8 | 4 | ||||
-rw-r--r-- | ssh-add.1 | 2 | ||||
-rw-r--r-- | ssh-add.c | 26 | ||||
-rw-r--r-- | ssh-agent.1 | 4 | ||||
-rw-r--r-- | ssh-agent.c | 143 | ||||
-rw-r--r-- | ssh-dss.c (renamed from dsa.c) | 118 | ||||
-rw-r--r-- | ssh-dss.h (renamed from dsa.h) | 10 | ||||
-rw-r--r-- | ssh-keygen.1 | 24 | ||||
-rw-r--r-- | ssh-keygen.c | 115 | ||||
-rw-r--r-- | ssh-rsa.c | 163 | ||||
-rw-r--r-- | ssh-rsa.h | 39 | ||||
-rw-r--r-- | ssh.1 | 53 | ||||
-rw-r--r-- | ssh.c | 193 | ||||
-rw-r--r-- | ssh_config | 13 | ||||
-rw-r--r-- | sshconnect.c | 12 | ||||
-rw-r--r-- | sshconnect1.c | 13 | ||||
-rw-r--r-- | sshconnect2.c | 77 | ||||
-rw-r--r-- | sshd.8 | 30 | ||||
-rw-r--r-- | sshd.c | 316 | ||||
-rw-r--r-- | sshd_config | 2 |
47 files changed, 1817 insertions, 997 deletions
@@ -1,6 +1,39 @@ | |||
1 | 20001113 | 1 | 20001113 |
2 | - (djm) Add pointer to http://www.imasy.or.jp/~gotoh/connect.c to | 2 | - (djm) Add pointer to http://www.imasy.or.jp/~gotoh/connect.c to |
3 | contrib/README | 3 | contrib/README |
4 | - (djm) Merge OpenBSD changes: | ||
5 | - markus@cvs.openbsd.org 2000/11/06 16:04:56 | ||
6 | [channels.c channels.h clientloop.c nchan.c serverloop.c] | ||
7 | [session.c ssh.c] | ||
8 | agent forwarding and -R for ssh2, based on work from | ||
9 | jhuuskon@messi.uku.fi | ||
10 | - markus@cvs.openbsd.org 2000/11/06 16:13:27 | ||
11 | [ssh.c sshconnect.c sshd.c] | ||
12 | do not disabled rhosts(rsa) if server port > 1024; from | ||
13 | pekkas@netcore.fi | ||
14 | - markus@cvs.openbsd.org 2000/11/06 16:16:35 | ||
15 | [sshconnect.c] | ||
16 | downgrade client to 1.3 if server is 1.4; help from mdb@juniper.net | ||
17 | - markus@cvs.openbsd.org 2000/11/09 18:04:40 | ||
18 | [auth1.c] | ||
19 | typo; from mouring@pconline.com | ||
20 | - markus@cvs.openbsd.org 2000/11/12 12:03:28 | ||
21 | [ssh-agent.c] | ||
22 | off-by-one when removing a key from the agent | ||
23 | - markus@cvs.openbsd.org 2000/11/12 12:50:39 | ||
24 | [auth-rh-rsa.c auth2.c authfd.c authfd.h] | ||
25 | [authfile.c hostfile.c kex.c kex.h key.c key.h myproposal.h] | ||
26 | [readconf.c readconf.h rsa.c rsa.h servconf.c servconf.h ssh-add.c] | ||
27 | [ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config] | ||
28 | [sshconnect1.c sshconnect2.c sshd.8 sshd.c sshd_config ssh-dss.c] | ||
29 | [ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h] | ||
30 | add support for RSA to SSH2. please test. | ||
31 | there are now 3 types of keys: RSA1 is used by ssh-1 only, | ||
32 | RSA and DSA are used by SSH2. | ||
33 | you can use 'ssh-keygen -t rsa -f ssh2_rsa_file' to generate RSA | ||
34 | keys for SSH2 and use the RSA keys for hostkeys or for user keys. | ||
35 | SSH2 RSA or DSA keys are added to .ssh/authorised_keys2 as before. | ||
36 | - (djm) Fix up Makefile and Redhat init script to create RSA host keys | ||
4 | 37 | ||
5 | 20001112 | 38 | 20001112 |
6 | - (bal) SCO Patch to add needed libraries for configure.in. Patch by | 39 | - (bal) SCO Patch to add needed libraries for configure.in. Patch by |
diff --git a/Makefile.in b/Makefile.in index cc49517b4..c93e7eab2 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -35,7 +35,7 @@ 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 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 | 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 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 ssh-dss.o ssh-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-getcwd.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-realpath.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 bsd-setproctitle.o bsd-waitpid.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-getcwd.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-realpath.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 bsd-setproctitle.o bsd-waitpid.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o |
41 | 41 | ||
@@ -179,18 +179,24 @@ host-key: ssh-keygen$(EXEEXT) | |||
179 | if [ -f "$(DESTDIR)$(sysconfdir)/ssh_host_key" ] ; then \ | 179 | if [ -f "$(DESTDIR)$(sysconfdir)/ssh_host_key" ] ; then \ |
180 | echo "$(DESTDIR)$(sysconfdir)/ssh_host_key already exists, skipping." ; \ | 180 | echo "$(DESTDIR)$(sysconfdir)/ssh_host_key already exists, skipping." ; \ |
181 | else \ | 181 | else \ |
182 | $(srcdir)/ssh-keygen -b 1024 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" ; \ | 182 | $(srcdir)/ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" ; \ |
183 | fi ; \ | 183 | fi ; \ |
184 | if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key ] ; then \ | 184 | if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key ] ; then \ |
185 | echo "$(DESTDIR)$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \ | 185 | echo "$(DESTDIR)$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \ |
186 | else \ | 186 | else \ |
187 | $(srcdir)/ssh-keygen -d -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" ; \ | 187 | $(srcdir)/ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" ; \ |
188 | fi ; \ | ||
189 | if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key ] ; then \ | ||
190 | echo "$(DESTDIR)$(sysconfdir)/ssh_host_rsa_key already exists, skipping." ; \ | ||
191 | else \ | ||
192 | $(srcdir)/ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N "" ; \ | ||
188 | fi ; \ | 193 | fi ; \ |
189 | fi ; | 194 | fi ; |
190 | 195 | ||
191 | host-key-force: ssh-keygen$(EXEEXT) | 196 | host-key-force: ssh-keygen$(EXEEXT) |
192 | $(srcdir)/ssh-keygen -b 1024 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" | 197 | $(srcdir)/ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" |
193 | $(srcdir)/ssh-keygen -d -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" | 198 | $(srcdir)/ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" |
199 | $(srcdir)/ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N "" | ||
194 | 200 | ||
195 | uninstallall: uninstall | 201 | uninstallall: uninstall |
196 | -rm -f $(DESTDIR)$(sysconfdir)/ssh_config | 202 | -rm -f $(DESTDIR)$(sysconfdir)/ssh_config |
diff --git a/auth-rh-rsa.c b/auth-rh-rsa.c index 3070c9d41..a9f17ef83 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.17 2000/10/03 18:03:03 markus Exp $"); | 16 | RCSID("$OpenBSD: auth-rh-rsa.c,v 1.18 2000/11/12 19:50:37 markus Exp $"); |
17 | 17 | ||
18 | #include "packet.h" | 18 | #include "packet.h" |
19 | #include "ssh.h" | 19 | #include "ssh.h" |
@@ -53,10 +53,10 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key | |||
53 | debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname); | 53 | debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname); |
54 | 54 | ||
55 | /* wrap the RSA key into a 'generic' key */ | 55 | /* wrap the RSA key into a 'generic' key */ |
56 | client_key = key_new(KEY_RSA); | 56 | client_key = key_new(KEY_RSA1); |
57 | BN_copy(client_key->rsa->e, client_host_key->e); | 57 | BN_copy(client_key->rsa->e, client_host_key->e); |
58 | BN_copy(client_key->rsa->n, client_host_key->n); | 58 | BN_copy(client_key->rsa->n, client_host_key->n); |
59 | found = key_new(KEY_RSA); | 59 | found = key_new(KEY_RSA1); |
60 | 60 | ||
61 | /* Check if we know the host and its host key. */ | 61 | /* Check if we know the host and its host key. */ |
62 | host_status = check_host_in_hostfile(SSH_SYSTEM_HOSTFILE, canonical_hostname, | 62 | host_status = check_host_in_hostfile(SSH_SYSTEM_HOSTFILE, canonical_hostname, |
@@ -10,7 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include "includes.h" | 12 | #include "includes.h" |
13 | RCSID("$OpenBSD: auth1.c,v 1.6 2000/10/11 20:27:23 markus Exp $"); | 13 | RCSID("$OpenBSD: auth1.c,v 1.7 2000/11/10 01:04:40 markus Exp $"); |
14 | 14 | ||
15 | #ifdef HAVE_OSF_SIA | 15 | #ifdef HAVE_OSF_SIA |
16 | # include <sia.h> | 16 | # include <sia.h> |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: auth2.c,v 1.20 2000/10/14 12:16:56 markus Exp $"); | 26 | RCSID("$OpenBSD: auth2.c,v 1.21 2000/11/12 19:50:37 markus Exp $"); |
27 | 27 | ||
28 | #ifdef HAVE_OSF_SIA | 28 | #ifdef HAVE_OSF_SIA |
29 | # include <sia.h> | 29 | # include <sia.h> |
@@ -52,7 +52,6 @@ RCSID("$OpenBSD: auth2.c,v 1.20 2000/10/14 12:16:56 markus Exp $"); | |||
52 | #include "key.h" | 52 | #include "key.h" |
53 | #include "kex.h" | 53 | #include "kex.h" |
54 | 54 | ||
55 | #include "dsa.h" | ||
56 | #include "uidswap.h" | 55 | #include "uidswap.h" |
57 | #include "auth-options.h" | 56 | #include "auth-options.h" |
58 | 57 | ||
@@ -89,7 +88,7 @@ void protocol_error(int type, int plen, void *ctxt); | |||
89 | /* helper */ | 88 | /* helper */ |
90 | Authmethod *authmethod_lookup(const char *name); | 89 | Authmethod *authmethod_lookup(const char *name); |
91 | struct passwd *pwcopy(struct passwd *pw); | 90 | struct passwd *pwcopy(struct passwd *pw); |
92 | int user_dsa_key_allowed(struct passwd *pw, Key *key); | 91 | int user_key_allowed(struct passwd *pw, Key *key); |
93 | char *authmethods_get(void); | 92 | char *authmethods_get(void); |
94 | 93 | ||
95 | /* auth */ | 94 | /* auth */ |
@@ -104,7 +103,7 @@ Authmethod authmethods[] = { | |||
104 | &one}, | 103 | &one}, |
105 | {"publickey", | 104 | {"publickey", |
106 | userauth_pubkey, | 105 | userauth_pubkey, |
107 | &options.dsa_authentication}, | 106 | &options.pubkey_authentication}, |
108 | {"keyboard-interactive", | 107 | {"keyboard-interactive", |
109 | userauth_kbdint, | 108 | userauth_kbdint, |
110 | &options.kbd_interactive_authentication}, | 109 | &options.kbd_interactive_authentication}, |
@@ -422,7 +421,7 @@ userauth_pubkey(Authctxt *authctxt) | |||
422 | Key *key; | 421 | Key *key; |
423 | char *pkalg, *pkblob, *sig; | 422 | char *pkalg, *pkblob, *sig; |
424 | unsigned int alen, blen, slen; | 423 | unsigned int alen, blen, slen; |
425 | int have_sig; | 424 | int have_sig, pktype; |
426 | int authenticated = 0; | 425 | int authenticated = 0; |
427 | 426 | ||
428 | if (!authctxt->valid) { | 427 | if (!authctxt->valid) { |
@@ -431,13 +430,14 @@ userauth_pubkey(Authctxt *authctxt) | |||
431 | } | 430 | } |
432 | have_sig = packet_get_char(); | 431 | have_sig = packet_get_char(); |
433 | pkalg = packet_get_string(&alen); | 432 | pkalg = packet_get_string(&alen); |
434 | if (strcmp(pkalg, KEX_DSS) != 0) { | 433 | pktype = key_type_from_name(pkalg); |
435 | log("bad pkalg %s", pkalg); /*XXX*/ | 434 | if (pktype == KEY_UNSPEC) { |
435 | log("bad pkalg %s", pkalg); | ||
436 | xfree(pkalg); | 436 | xfree(pkalg); |
437 | return 0; | 437 | return 0; |
438 | } | 438 | } |
439 | pkblob = packet_get_string(&blen); | 439 | pkblob = packet_get_string(&blen); |
440 | key = dsa_key_from_blob(pkblob, blen); | 440 | key = key_from_blob(pkblob, blen); |
441 | if (key != NULL) { | 441 | if (key != NULL) { |
442 | if (have_sig) { | 442 | if (have_sig) { |
443 | sig = packet_get_string(&slen); | 443 | sig = packet_get_string(&slen); |
@@ -457,14 +457,14 @@ userauth_pubkey(Authctxt *authctxt) | |||
457 | authctxt->service); | 457 | authctxt->service); |
458 | buffer_put_cstring(&b, "publickey"); | 458 | buffer_put_cstring(&b, "publickey"); |
459 | buffer_put_char(&b, have_sig); | 459 | buffer_put_char(&b, have_sig); |
460 | buffer_put_cstring(&b, KEX_DSS); | 460 | buffer_put_cstring(&b, key_ssh_name(key)); |
461 | buffer_put_string(&b, pkblob, blen); | 461 | buffer_put_string(&b, pkblob, blen); |
462 | #ifdef DEBUG_DSS | 462 | #ifdef DEBUG_PK |
463 | buffer_dump(&b); | 463 | buffer_dump(&b); |
464 | #endif | 464 | #endif |
465 | /* test for correct signature */ | 465 | /* test for correct signature */ |
466 | if (user_dsa_key_allowed(authctxt->pw, key) && | 466 | if (user_key_allowed(authctxt->pw, key) && |
467 | dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) | 467 | key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) |
468 | authenticated = 1; | 468 | authenticated = 1; |
469 | buffer_clear(&b); | 469 | buffer_clear(&b); |
470 | xfree(sig); | 470 | xfree(sig); |
@@ -480,7 +480,7 @@ userauth_pubkey(Authctxt *authctxt) | |||
480 | * if a user is not allowed to login. is this an | 480 | * if a user is not allowed to login. is this an |
481 | * issue? -markus | 481 | * issue? -markus |
482 | */ | 482 | */ |
483 | if (user_dsa_key_allowed(authctxt->pw, key)) { | 483 | if (user_key_allowed(authctxt->pw, key)) { |
484 | packet_start(SSH2_MSG_USERAUTH_PK_OK); | 484 | packet_start(SSH2_MSG_USERAUTH_PK_OK); |
485 | packet_put_string(pkalg, alen); | 485 | packet_put_string(pkalg, alen); |
486 | packet_put_string(pkblob, blen); | 486 | packet_put_string(pkblob, blen); |
@@ -493,6 +493,7 @@ userauth_pubkey(Authctxt *authctxt) | |||
493 | auth_clear_options(); | 493 | auth_clear_options(); |
494 | key_free(key); | 494 | key_free(key); |
495 | } | 495 | } |
496 | debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg); | ||
496 | xfree(pkalg); | 497 | xfree(pkalg); |
497 | xfree(pkblob); | 498 | xfree(pkblob); |
498 | #ifdef HAVE_CYGWIN | 499 | #ifdef HAVE_CYGWIN |
@@ -560,11 +561,10 @@ authmethod_lookup(const char *name) | |||
560 | 561 | ||
561 | /* return 1 if user allows given key */ | 562 | /* return 1 if user allows given key */ |
562 | int | 563 | int |
563 | user_dsa_key_allowed(struct passwd *pw, Key *key) | 564 | user_key_allowed(struct passwd *pw, Key *key) |
564 | { | 565 | { |
565 | char line[8192], file[1024]; | 566 | char line[8192], file[1024]; |
566 | int found_key = 0; | 567 | int found_key = 0; |
567 | unsigned int bits = -1; | ||
568 | FILE *f; | 568 | FILE *f; |
569 | unsigned long linenum = 0; | 569 | unsigned long linenum = 0; |
570 | struct stat st; | 570 | struct stat st; |
@@ -645,10 +645,10 @@ user_dsa_key_allowed(struct passwd *pw, Key *key) | |||
645 | if (!*cp || *cp == '\n' || *cp == '#') | 645 | if (!*cp || *cp == '\n' || *cp == '#') |
646 | continue; | 646 | continue; |
647 | 647 | ||
648 | bits = key_read(found, &cp); | 648 | if (key_read(found, &cp) == -1) { |
649 | if (bits == 0) { | ||
650 | /* no key? check if there are options for this key */ | 649 | /* no key? check if there are options for this key */ |
651 | int quoted = 0; | 650 | int quoted = 0; |
651 | debug2("user_key_allowed: check options: '%s'", cp); | ||
652 | options = cp; | 652 | options = cp; |
653 | for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { | 653 | for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { |
654 | if (*cp == '\\' && cp[1] == '"') | 654 | if (*cp == '\\' && cp[1] == '"') |
@@ -659,8 +659,8 @@ user_dsa_key_allowed(struct passwd *pw, Key *key) | |||
659 | /* Skip remaining whitespace. */ | 659 | /* Skip remaining whitespace. */ |
660 | for (; *cp == ' ' || *cp == '\t'; cp++) | 660 | for (; *cp == ' ' || *cp == '\t'; cp++) |
661 | ; | 661 | ; |
662 | bits = key_read(found, &cp); | 662 | if (key_read(found, &cp) == -1) { |
663 | if (bits == 0) { | 663 | debug2("user_key_allowed: advance: '%s'", cp); |
664 | /* still no key? advance to next line*/ | 664 | /* still no key? advance to next line*/ |
665 | continue; | 665 | continue; |
666 | } | 666 | } |
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | RCSID("$OpenBSD: authfd.c,v 1.29 2000/10/09 21:51:00 markus Exp $"); | 38 | RCSID("$OpenBSD: authfd.c,v 1.30 2000/11/12 19:50:37 markus Exp $"); |
39 | 39 | ||
40 | #include "ssh.h" | 40 | #include "ssh.h" |
41 | #include "rsa.h" | 41 | #include "rsa.h" |
@@ -50,7 +50,6 @@ RCSID("$OpenBSD: authfd.c,v 1.29 2000/10/09 21:51:00 markus Exp $"); | |||
50 | #include "key.h" | 50 | #include "key.h" |
51 | #include "authfd.h" | 51 | #include "authfd.h" |
52 | #include "kex.h" | 52 | #include "kex.h" |
53 | #include "dsa.h" | ||
54 | #include "compat.h" | 53 | #include "compat.h" |
55 | 54 | ||
56 | /* helper */ | 55 | /* helper */ |
@@ -211,8 +210,8 @@ ssh_close_authentication_connection(AuthenticationConnection *auth) | |||
211 | * Returns the first authentication identity held by the agent. | 210 | * Returns the first authentication identity held by the agent. |
212 | */ | 211 | */ |
213 | 212 | ||
214 | Key * | 213 | int |
215 | ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version) | 214 | ssh_get_num_identities(AuthenticationConnection *auth, int version) |
216 | { | 215 | { |
217 | int type, code1 = 0, code2 = 0; | 216 | int type, code1 = 0, code2 = 0; |
218 | Buffer request; | 217 | Buffer request; |
@@ -227,7 +226,7 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi | |||
227 | code2 = SSH2_AGENT_IDENTITIES_ANSWER; | 226 | code2 = SSH2_AGENT_IDENTITIES_ANSWER; |
228 | break; | 227 | break; |
229 | default: | 228 | default: |
230 | return NULL; | 229 | return 0; |
231 | } | 230 | } |
232 | 231 | ||
233 | /* | 232 | /* |
@@ -240,14 +239,14 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi | |||
240 | buffer_clear(&auth->identities); | 239 | buffer_clear(&auth->identities); |
241 | if (ssh_request_reply(auth, &request, &auth->identities) == 0) { | 240 | if (ssh_request_reply(auth, &request, &auth->identities) == 0) { |
242 | buffer_free(&request); | 241 | buffer_free(&request); |
243 | return NULL; | 242 | return 0; |
244 | } | 243 | } |
245 | buffer_free(&request); | 244 | buffer_free(&request); |
246 | 245 | ||
247 | /* Get message type, and verify that we got a proper answer. */ | 246 | /* Get message type, and verify that we got a proper answer. */ |
248 | type = buffer_get_char(&auth->identities); | 247 | type = buffer_get_char(&auth->identities); |
249 | if (agent_failed(type)) { | 248 | if (agent_failed(type)) { |
250 | return NULL; | 249 | return 0; |
251 | } else if (type != code2) { | 250 | } else if (type != code2) { |
252 | fatal("Bad authentication reply message type: %d", type); | 251 | fatal("Bad authentication reply message type: %d", type); |
253 | } | 252 | } |
@@ -258,8 +257,16 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi | |||
258 | fatal("Too many identities in authentication reply: %d\n", | 257 | fatal("Too many identities in authentication reply: %d\n", |
259 | auth->howmany); | 258 | auth->howmany); |
260 | 259 | ||
261 | /* Return the first entry (if any). */ | 260 | return auth->howmany; |
262 | return ssh_get_next_identity(auth, comment, version); | 261 | } |
262 | |||
263 | Key * | ||
264 | ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version) | ||
265 | { | ||
266 | /* get number of identities and return the first entry (if any). */ | ||
267 | if (ssh_get_num_identities(auth, version) > 0) | ||
268 | return ssh_get_next_identity(auth, comment, version); | ||
269 | return NULL; | ||
263 | } | 270 | } |
264 | 271 | ||
265 | Key * | 272 | Key * |
@@ -280,7 +287,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio | |||
280 | */ | 287 | */ |
281 | switch(version){ | 288 | switch(version){ |
282 | case 1: | 289 | case 1: |
283 | key = key_new(KEY_RSA); | 290 | key = key_new(KEY_RSA1); |
284 | bits = buffer_get_int(&auth->identities); | 291 | bits = buffer_get_int(&auth->identities); |
285 | buffer_get_bignum(&auth->identities, key->rsa->e); | 292 | buffer_get_bignum(&auth->identities, key->rsa->e); |
286 | buffer_get_bignum(&auth->identities, key->rsa->n); | 293 | buffer_get_bignum(&auth->identities, key->rsa->n); |
@@ -292,7 +299,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio | |||
292 | case 2: | 299 | case 2: |
293 | blob = buffer_get_string(&auth->identities, &blen); | 300 | blob = buffer_get_string(&auth->identities, &blen); |
294 | *comment = buffer_get_string(&auth->identities, NULL); | 301 | *comment = buffer_get_string(&auth->identities, NULL); |
295 | key = dsa_key_from_blob(blob, blen); | 302 | key = key_from_blob(blob, blen); |
296 | xfree(blob); | 303 | xfree(blob); |
297 | break; | 304 | break; |
298 | default: | 305 | default: |
@@ -324,7 +331,7 @@ ssh_decrypt_challenge(AuthenticationConnection *auth, | |||
324 | int i; | 331 | int i; |
325 | int type; | 332 | int type; |
326 | 333 | ||
327 | if (key->type != KEY_RSA) | 334 | if (key->type != KEY_RSA1) |
328 | return 0; | 335 | return 0; |
329 | if (response_type == 0) { | 336 | if (response_type == 0) { |
330 | log("Compatibility with ssh protocol version 1.0 no longer supported."); | 337 | log("Compatibility with ssh protocol version 1.0 no longer supported."); |
@@ -376,7 +383,7 @@ ssh_agent_sign(AuthenticationConnection *auth, | |||
376 | int type, flags = 0; | 383 | int type, flags = 0; |
377 | int ret = -1; | 384 | int ret = -1; |
378 | 385 | ||
379 | if (dsa_make_key_blob(key, &blob, &blen) == 0) | 386 | if (key_to_blob(key, &blob, &blen) == 0) |
380 | return -1; | 387 | return -1; |
381 | 388 | ||
382 | if (datafellows & SSH_BUG_SIGBLOB) | 389 | if (datafellows & SSH_BUG_SIGBLOB) |
@@ -409,7 +416,7 @@ ssh_agent_sign(AuthenticationConnection *auth, | |||
409 | /* Encode key for a message to the agent. */ | 416 | /* Encode key for a message to the agent. */ |
410 | 417 | ||
411 | void | 418 | void |
412 | ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment) | 419 | ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment) |
413 | { | 420 | { |
414 | buffer_clear(b); | 421 | buffer_clear(b); |
415 | buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY); | 422 | buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY); |
@@ -425,17 +432,29 @@ ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment) | |||
425 | } | 432 | } |
426 | 433 | ||
427 | void | 434 | void |
428 | ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment) | 435 | ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) |
429 | { | 436 | { |
430 | buffer_clear(b); | 437 | buffer_clear(b); |
431 | buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY); | 438 | buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY); |
432 | buffer_put_cstring(b, KEX_DSS); | 439 | buffer_put_cstring(b, key_ssh_name(key)); |
433 | buffer_put_bignum2(b, key->p); | 440 | switch(key->type){ |
434 | buffer_put_bignum2(b, key->q); | 441 | case KEY_RSA: |
435 | buffer_put_bignum2(b, key->g); | 442 | buffer_put_bignum2(b, key->rsa->n); |
436 | buffer_put_bignum2(b, key->pub_key); | 443 | buffer_put_bignum2(b, key->rsa->e); |
437 | buffer_put_bignum2(b, key->priv_key); | 444 | buffer_put_bignum2(b, key->rsa->d); |
438 | buffer_put_string(b, comment, strlen(comment)); | 445 | buffer_put_bignum2(b, key->rsa->iqmp); |
446 | buffer_put_bignum2(b, key->rsa->p); | ||
447 | buffer_put_bignum2(b, key->rsa->q); | ||
448 | break; | ||
449 | case KEY_DSA: | ||
450 | buffer_put_bignum2(b, key->dsa->p); | ||
451 | buffer_put_bignum2(b, key->dsa->q); | ||
452 | buffer_put_bignum2(b, key->dsa->g); | ||
453 | buffer_put_bignum2(b, key->dsa->pub_key); | ||
454 | buffer_put_bignum2(b, key->dsa->priv_key); | ||
455 | break; | ||
456 | } | ||
457 | buffer_put_cstring(b, comment); | ||
439 | } | 458 | } |
440 | 459 | ||
441 | /* | 460 | /* |
@@ -452,11 +471,12 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) | |||
452 | buffer_init(&msg); | 471 | buffer_init(&msg); |
453 | 472 | ||
454 | switch (key->type) { | 473 | switch (key->type) { |
455 | case KEY_RSA: | 474 | case KEY_RSA1: |
456 | ssh_encode_identity_rsa(&msg, key->rsa, comment); | 475 | ssh_encode_identity_rsa1(&msg, key->rsa, comment); |
457 | break; | 476 | break; |
477 | case KEY_RSA: | ||
458 | case KEY_DSA: | 478 | case KEY_DSA: |
459 | ssh_encode_identity_dsa(&msg, key->dsa, comment); | 479 | ssh_encode_identity_ssh2(&msg, key, comment); |
460 | break; | 480 | break; |
461 | default: | 481 | default: |
462 | buffer_free(&msg); | 482 | buffer_free(&msg); |
@@ -487,13 +507,13 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key) | |||
487 | 507 | ||
488 | buffer_init(&msg); | 508 | buffer_init(&msg); |
489 | 509 | ||
490 | if (key->type == KEY_RSA) { | 510 | if (key->type == KEY_RSA1) { |
491 | buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY); | 511 | buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY); |
492 | buffer_put_int(&msg, BN_num_bits(key->rsa->n)); | 512 | buffer_put_int(&msg, BN_num_bits(key->rsa->n)); |
493 | buffer_put_bignum(&msg, key->rsa->e); | 513 | buffer_put_bignum(&msg, key->rsa->e); |
494 | buffer_put_bignum(&msg, key->rsa->n); | 514 | buffer_put_bignum(&msg, key->rsa->n); |
495 | } else if (key->type == KEY_DSA) { | 515 | } else if (key->type == KEY_DSA || key->type == KEY_RSA) { |
496 | dsa_make_key_blob(key, &blob, &blen); | 516 | key_to_blob(key, &blob, &blen); |
497 | buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); | 517 | buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); |
498 | buffer_put_string(&msg, blob, blen); | 518 | buffer_put_string(&msg, blob, blen); |
499 | xfree(blob); | 519 | xfree(blob); |
@@ -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.13 2000/10/09 21:51:00 markus Exp $"); */ | 14 | /* RCSID("$OpenBSD: authfd.h,v 1.14 2000/11/12 19:50:37 markus Exp $"); */ |
15 | 15 | ||
16 | #ifndef AUTHFD_H | 16 | #ifndef AUTHFD_H |
17 | #define AUTHFD_H | 17 | #define AUTHFD_H |
@@ -75,6 +75,11 @@ AuthenticationConnection *ssh_get_authentication_connection(); | |||
75 | void ssh_close_authentication_connection(AuthenticationConnection *auth); | 75 | void ssh_close_authentication_connection(AuthenticationConnection *auth); |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * Returns the number authentication identity held by the agent. | ||
79 | */ | ||
80 | int ssh_get_num_identities(AuthenticationConnection *auth, int version); | ||
81 | |||
82 | /* | ||
78 | * Returns the first authentication identity held by the agent or NULL if | 83 | * Returns the first authentication identity held by the agent or NULL if |
79 | * no identies are available. Caller must free comment and key. | 84 | * no identies are available. Caller must free comment and key. |
80 | * Note that you cannot mix calls with different versions. | 85 | * Note that you cannot mix calls with different versions. |
diff --git a/authfile.c b/authfile.c index d1a97d773..986b10f6b 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -36,11 +36,12 @@ | |||
36 | */ | 36 | */ |
37 | 37 | ||
38 | #include "includes.h" | 38 | #include "includes.h" |
39 | RCSID("$OpenBSD: authfile.c,v 1.20 2000/10/11 20:27:23 markus Exp $"); | 39 | RCSID("$OpenBSD: authfile.c,v 1.21 2000/11/12 19:50:37 markus Exp $"); |
40 | 40 | ||
41 | #include <openssl/bn.h> | 41 | #include <openssl/bn.h> |
42 | #include <openssl/dsa.h> | 42 | #include <openssl/dsa.h> |
43 | #include <openssl/rsa.h> | 43 | #include <openssl/rsa.h> |
44 | #include <openssl/err.h> | ||
44 | #include <openssl/pem.h> | 45 | #include <openssl/pem.h> |
45 | #include <openssl/evp.h> | 46 | #include <openssl/evp.h> |
46 | 47 | ||
@@ -61,7 +62,7 @@ RCSID("$OpenBSD: authfile.c,v 1.20 2000/10/11 20:27:23 markus Exp $"); | |||
61 | */ | 62 | */ |
62 | 63 | ||
63 | int | 64 | int |
64 | save_private_key_rsa(const char *filename, const char *passphrase, | 65 | save_private_key_rsa1(const char *filename, const char *passphrase, |
65 | RSA *key, const char *comment) | 66 | RSA *key, const char *comment) |
66 | { | 67 | { |
67 | Buffer buffer, encrypted; | 68 | Buffer buffer, encrypted; |
@@ -155,16 +156,17 @@ save_private_key_rsa(const char *filename, const char *passphrase, | |||
155 | return 1; | 156 | return 1; |
156 | } | 157 | } |
157 | 158 | ||
158 | /* save DSA key in OpenSSL PEM format */ | 159 | /* save SSH2 key in OpenSSL PEM format */ |
159 | |||
160 | int | 160 | int |
161 | save_private_key_dsa(const char *filename, const char *passphrase, | 161 | save_private_key_ssh2(const char *filename, const char *_passphrase, |
162 | DSA *dsa, const char *comment) | 162 | Key *key, const char *comment) |
163 | { | 163 | { |
164 | FILE *fp; | 164 | FILE *fp; |
165 | int fd; | 165 | int fd; |
166 | int success = 1; | 166 | int success = 0; |
167 | int len = strlen(passphrase); | 167 | int len = strlen(_passphrase); |
168 | char *passphrase = (len > 0) ? (char *)_passphrase : NULL; | ||
169 | EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; | ||
168 | 170 | ||
169 | if (len > 0 && len <= 4) { | 171 | if (len > 0 && len <= 4) { |
170 | error("passphrase too short: %d bytes", len); | 172 | error("passphrase too short: %d bytes", len); |
@@ -182,14 +184,15 @@ save_private_key_dsa(const char *filename, const char *passphrase, | |||
182 | close(fd); | 184 | close(fd); |
183 | return 0; | 185 | return 0; |
184 | } | 186 | } |
185 | if (len > 0) { | 187 | switch (key->type) { |
186 | if (!PEM_write_DSAPrivateKey(fp, dsa, EVP_des_ede3_cbc(), | 188 | case KEY_DSA: |
187 | (char *)passphrase, strlen(passphrase), NULL, NULL)) | 189 | success = PEM_write_DSAPrivateKey(fp, key->dsa, |
188 | success = 0; | 190 | cipher, passphrase, len, NULL, NULL); |
189 | } else { | 191 | break; |
190 | if (!PEM_write_DSAPrivateKey(fp, dsa, NULL, | 192 | case KEY_RSA: |
191 | NULL, 0, NULL, NULL)) | 193 | success = PEM_write_RSAPrivateKey(fp, key->rsa, |
192 | success = 0; | 194 | cipher, passphrase, len, NULL, NULL); |
195 | break; | ||
193 | } | 196 | } |
194 | fclose(fp); | 197 | fclose(fp); |
195 | return success; | 198 | return success; |
@@ -200,11 +203,12 @@ save_private_key(const char *filename, const char *passphrase, Key *key, | |||
200 | const char *comment) | 203 | const char *comment) |
201 | { | 204 | { |
202 | switch (key->type) { | 205 | switch (key->type) { |
203 | case KEY_RSA: | 206 | case KEY_RSA1: |
204 | return save_private_key_rsa(filename, passphrase, key->rsa, comment); | 207 | return save_private_key_rsa1(filename, passphrase, key->rsa, comment); |
205 | break; | 208 | break; |
206 | case KEY_DSA: | 209 | case KEY_DSA: |
207 | return save_private_key_dsa(filename, passphrase, key->dsa, comment); | 210 | case KEY_RSA: |
211 | return save_private_key_ssh2(filename, passphrase, key, comment); | ||
208 | break; | 212 | break; |
209 | default: | 213 | default: |
210 | break; | 214 | break; |
@@ -246,7 +250,7 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return) | |||
246 | 250 | ||
247 | /* Check that it is at least big enought to contain the ID string. */ | 251 | /* Check that it is at least big enought to contain the ID string. */ |
248 | if (len < strlen(AUTHFILE_ID_STRING) + 1) { | 252 | if (len < strlen(AUTHFILE_ID_STRING) + 1) { |
249 | debug("Bad key file %.200s.", filename); | 253 | debug3("Bad RSA1 key file %.200s.", filename); |
250 | buffer_free(&buffer); | 254 | buffer_free(&buffer); |
251 | return 0; | 255 | return 0; |
252 | } | 256 | } |
@@ -256,7 +260,7 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return) | |||
256 | */ | 260 | */ |
257 | for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++) | 261 | for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++) |
258 | if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) { | 262 | if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) { |
259 | debug("Bad key file %.200s.", filename); | 263 | debug3("Bad RSA1 key file %.200s.", filename); |
260 | buffer_free(&buffer); | 264 | buffer_free(&buffer); |
261 | return 0; | 265 | return 0; |
262 | } | 266 | } |
@@ -288,10 +292,11 @@ int | |||
288 | load_public_key(const char *filename, Key * key, char **comment_return) | 292 | load_public_key(const char *filename, Key * key, char **comment_return) |
289 | { | 293 | { |
290 | switch (key->type) { | 294 | switch (key->type) { |
291 | case KEY_RSA: | 295 | case KEY_RSA1: |
292 | return load_public_key_rsa(filename, key->rsa, comment_return); | 296 | return load_public_key_rsa(filename, key->rsa, comment_return); |
293 | break; | 297 | break; |
294 | case KEY_DSA: | 298 | case KEY_DSA: |
299 | case KEY_RSA: | ||
295 | default: | 300 | default: |
296 | break; | 301 | break; |
297 | } | 302 | } |
@@ -306,7 +311,7 @@ load_public_key(const char *filename, Key * key, char **comment_return) | |||
306 | */ | 311 | */ |
307 | 312 | ||
308 | int | 313 | int |
309 | load_private_key_rsa(int fd, const char *filename, | 314 | load_private_key_rsa1(int fd, const char *filename, |
310 | const char *passphrase, RSA * prv, char **comment_return) | 315 | const char *passphrase, RSA * prv, char **comment_return) |
311 | { | 316 | { |
312 | int i, check1, check2, cipher_type; | 317 | int i, check1, check2, cipher_type; |
@@ -326,7 +331,7 @@ load_private_key_rsa(int fd, const char *filename, | |||
326 | 331 | ||
327 | if (read(fd, cp, (size_t) len) != (size_t) len) { | 332 | if (read(fd, cp, (size_t) len) != (size_t) len) { |
328 | debug("Read from key file %.200s failed: %.100s", filename, | 333 | debug("Read from key file %.200s failed: %.100s", filename, |
329 | strerror(errno)); | 334 | strerror(errno)); |
330 | buffer_free(&buffer); | 335 | buffer_free(&buffer); |
331 | close(fd); | 336 | close(fd); |
332 | return 0; | 337 | return 0; |
@@ -335,7 +340,7 @@ load_private_key_rsa(int fd, const char *filename, | |||
335 | 340 | ||
336 | /* Check that it is at least big enought to contain the ID string. */ | 341 | /* Check that it is at least big enought to contain the ID string. */ |
337 | if (len < strlen(AUTHFILE_ID_STRING) + 1) { | 342 | if (len < strlen(AUTHFILE_ID_STRING) + 1) { |
338 | debug("Bad key file %.200s.", filename); | 343 | debug3("Bad RSA1 key file %.200s.", filename); |
339 | buffer_free(&buffer); | 344 | buffer_free(&buffer); |
340 | return 0; | 345 | return 0; |
341 | } | 346 | } |
@@ -344,8 +349,8 @@ load_private_key_rsa(int fd, const char *filename, | |||
344 | * from the buffer. | 349 | * from the buffer. |
345 | */ | 350 | */ |
346 | for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++) | 351 | for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++) |
347 | if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) { | 352 | if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) { |
348 | debug("Bad key file %.200s.", filename); | 353 | debug3("Bad RSA1 key file %.200s.", filename); |
349 | buffer_free(&buffer); | 354 | buffer_free(&buffer); |
350 | return 0; | 355 | return 0; |
351 | } | 356 | } |
@@ -431,40 +436,59 @@ fail: | |||
431 | } | 436 | } |
432 | 437 | ||
433 | int | 438 | int |
434 | load_private_key_dsa(int fd, const char *passphrase, Key *k, char **comment_return) | 439 | load_private_key_ssh2(int fd, const char *passphrase, Key *k, char **comment_return) |
435 | { | 440 | { |
436 | DSA *dsa; | ||
437 | BIO *in; | ||
438 | FILE *fp; | 441 | FILE *fp; |
442 | int success = 0; | ||
443 | EVP_PKEY *pk = NULL; | ||
444 | char *name = "<no key>"; | ||
439 | 445 | ||
440 | in = BIO_new(BIO_s_file()); | ||
441 | if (in == NULL) { | ||
442 | error("BIO_new failed"); | ||
443 | return 0; | ||
444 | } | ||
445 | fp = fdopen(fd, "r"); | 446 | fp = fdopen(fd, "r"); |
446 | if (fp == NULL) { | 447 | if (fp == NULL) { |
447 | error("fdopen failed"); | 448 | error("fdopen failed"); |
448 | return 0; | 449 | return 0; |
449 | } | 450 | } |
450 | BIO_set_fp(in, fp, BIO_NOCLOSE); | 451 | pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase); |
451 | dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, (char *)passphrase); | 452 | if (pk == NULL) { |
452 | if (dsa == NULL) { | 453 | debug("PEM_read_PrivateKey failed"); |
453 | debug("PEM_read_bio_DSAPrivateKey failed"); | 454 | (void)ERR_get_error(); |
454 | } else { | 455 | } else if (pk->type == EVP_PKEY_RSA) { |
456 | /* replace k->rsa with loaded key */ | ||
457 | if (k->type == KEY_RSA || k->type == KEY_UNSPEC) { | ||
458 | if (k->rsa != NULL) | ||
459 | RSA_free(k->rsa); | ||
460 | k->rsa = EVP_PKEY_get1_RSA(pk); | ||
461 | k->type = KEY_RSA; | ||
462 | name = "rsa w/o comment"; | ||
463 | success = 1; | ||
464 | #ifdef DEBUG_PK | ||
465 | RSA_print_fp(stderr, k->rsa, 8); | ||
466 | #endif | ||
467 | } | ||
468 | } else if (pk->type == EVP_PKEY_DSA) { | ||
455 | /* replace k->dsa with loaded key */ | 469 | /* replace k->dsa with loaded key */ |
456 | DSA_free(k->dsa); | 470 | if (k->type == KEY_DSA || k->type == KEY_UNSPEC) { |
457 | k->dsa = dsa; | 471 | if (k->dsa != NULL) |
472 | DSA_free(k->dsa); | ||
473 | k->dsa = EVP_PKEY_get1_DSA(pk); | ||
474 | k->type = KEY_DSA; | ||
475 | name = "dsa w/o comment"; | ||
476 | #ifdef DEBUG_PK | ||
477 | DSA_print_fp(stderr, k->dsa, 8); | ||
478 | #endif | ||
479 | success = 1; | ||
480 | } | ||
481 | } else { | ||
482 | error("PEM_read_PrivateKey: mismatch or " | ||
483 | "unknown EVP_PKEY save_type %d", pk->save_type); | ||
458 | } | 484 | } |
459 | BIO_free(in); | ||
460 | fclose(fp); | 485 | fclose(fp); |
461 | if (comment_return) | 486 | if (pk != NULL) |
462 | *comment_return = xstrdup("dsa w/o comment"); | 487 | EVP_PKEY_free(pk); |
463 | debug("read DSA private key done"); | 488 | if (success && comment_return) |
464 | #ifdef DEBUG_DSS | 489 | *comment_return = xstrdup(name); |
465 | DSA_print_fp(stderr, dsa, 8); | 490 | debug("read SSH2 private key done: name %s success %d", name, success); |
466 | #endif | 491 | return success; |
467 | return dsa != NULL ? 1 : 0; | ||
468 | } | 492 | } |
469 | 493 | ||
470 | int | 494 | int |
@@ -496,7 +520,7 @@ load_private_key(const char *filename, const char *passphrase, Key *key, | |||
496 | return 0; | 520 | return 0; |
497 | } | 521 | } |
498 | switch (key->type) { | 522 | switch (key->type) { |
499 | case KEY_RSA: | 523 | case KEY_RSA1: |
500 | if (key->rsa->e != NULL) { | 524 | if (key->rsa->e != NULL) { |
501 | BN_clear_free(key->rsa->e); | 525 | BN_clear_free(key->rsa->e); |
502 | key->rsa->e = NULL; | 526 | key->rsa->e = NULL; |
@@ -505,11 +529,13 @@ load_private_key(const char *filename, const char *passphrase, Key *key, | |||
505 | BN_clear_free(key->rsa->n); | 529 | BN_clear_free(key->rsa->n); |
506 | key->rsa->n = NULL; | 530 | key->rsa->n = NULL; |
507 | } | 531 | } |
508 | ret = load_private_key_rsa(fd, filename, passphrase, | 532 | ret = load_private_key_rsa1(fd, filename, passphrase, |
509 | key->rsa, comment_return); | 533 | key->rsa, comment_return); |
510 | break; | 534 | break; |
511 | case KEY_DSA: | 535 | case KEY_DSA: |
512 | ret = load_private_key_dsa(fd, passphrase, key, comment_return); | 536 | case KEY_RSA: |
537 | case KEY_UNSPEC: | ||
538 | ret = load_private_key_ssh2(fd, passphrase, key, comment_return); | ||
513 | default: | 539 | default: |
514 | break; | 540 | break; |
515 | } | 541 | } |
@@ -521,7 +547,6 @@ int | |||
521 | do_load_public_key(const char *filename, Key *k, char **commentp) | 547 | do_load_public_key(const char *filename, Key *k, char **commentp) |
522 | { | 548 | { |
523 | FILE *f; | 549 | FILE *f; |
524 | unsigned int bits; | ||
525 | char line[1024]; | 550 | char line[1024]; |
526 | char *cp; | 551 | char *cp; |
527 | 552 | ||
@@ -540,8 +565,7 @@ do_load_public_key(const char *filename, Key *k, char **commentp) | |||
540 | for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) | 565 | for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) |
541 | ; | 566 | ; |
542 | if (*cp) { | 567 | if (*cp) { |
543 | bits = key_read(k, &cp); | 568 | if (key_read(k, &cp) == 1) { |
544 | if (bits != 0) { | ||
545 | if (commentp) | 569 | if (commentp) |
546 | *commentp=xstrdup(filename); | 570 | *commentp=xstrdup(filename); |
547 | fclose(f); | 571 | fclose(f); |
diff --git a/channels.c b/channels.c index 028c09e6a..0886a91ef 100644 --- a/channels.c +++ b/channels.c | |||
@@ -40,7 +40,7 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: channels.c,v 1.72 2000/10/27 07:48:22 markus Exp $"); | 43 | RCSID("$OpenBSD: channels.c,v 1.73 2000/11/06 23:04:55 markus Exp $"); |
44 | 44 | ||
45 | #include "ssh.h" | 45 | #include "ssh.h" |
46 | #include "packet.h" | 46 | #include "packet.h" |
@@ -588,9 +588,12 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) | |||
588 | struct sockaddr addr; | 588 | struct sockaddr addr; |
589 | int newsock, newch; | 589 | int newsock, newch; |
590 | socklen_t addrlen; | 590 | socklen_t addrlen; |
591 | char buf[1024], *remote_hostname; | 591 | char buf[1024], *remote_hostname, *rtype; |
592 | int remote_port; | 592 | int remote_port; |
593 | 593 | ||
594 | rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ? | ||
595 | "forwarded-tcpip" : "direct-tcpip"; | ||
596 | |||
594 | if (FD_ISSET(c->sock, readset)) { | 597 | if (FD_ISSET(c->sock, readset)) { |
595 | debug("Connection to port %d forwarding " | 598 | debug("Connection to port %d forwarding " |
596 | "to %.100s port %d requested.", | 599 | "to %.100s port %d requested.", |
@@ -608,19 +611,26 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) | |||
608 | "connect from %.200s port %d", | 611 | "connect from %.200s port %d", |
609 | c->listening_port, c->path, c->host_port, | 612 | c->listening_port, c->path, c->host_port, |
610 | remote_hostname, remote_port); | 613 | remote_hostname, remote_port); |
611 | newch = channel_new("direct-tcpip", | 614 | |
615 | newch = channel_new(rtype, | ||
612 | SSH_CHANNEL_OPENING, newsock, newsock, -1, | 616 | SSH_CHANNEL_OPENING, newsock, newsock, -1, |
613 | c->local_window_max, c->local_maxpacket, | 617 | c->local_window_max, c->local_maxpacket, |
614 | 0, xstrdup(buf), 1); | 618 | 0, xstrdup(buf), 1); |
615 | if (compat20) { | 619 | if (compat20) { |
616 | packet_start(SSH2_MSG_CHANNEL_OPEN); | 620 | packet_start(SSH2_MSG_CHANNEL_OPEN); |
617 | packet_put_cstring("direct-tcpip"); | 621 | packet_put_cstring(rtype); |
618 | packet_put_int(newch); | 622 | packet_put_int(newch); |
619 | packet_put_int(c->local_window_max); | 623 | packet_put_int(c->local_window_max); |
620 | packet_put_int(c->local_maxpacket); | 624 | packet_put_int(c->local_maxpacket); |
621 | /* target host and port */ | 625 | if (c->type == SSH_CHANNEL_RPORT_LISTENER) { |
622 | packet_put_string(c->path, strlen(c->path)); | 626 | /* listen address, port */ |
623 | packet_put_int(c->host_port); | 627 | packet_put_string(c->path, strlen(c->path)); |
628 | packet_put_int(c->listening_port); | ||
629 | } else { | ||
630 | /* target host, port */ | ||
631 | packet_put_string(c->path, strlen(c->path)); | ||
632 | packet_put_int(c->host_port); | ||
633 | } | ||
624 | /* originator host and port */ | 634 | /* originator host and port */ |
625 | packet_put_cstring(remote_hostname); | 635 | packet_put_cstring(remote_hostname); |
626 | packet_put_int(remote_port); | 636 | packet_put_int(remote_port); |
@@ -657,10 +667,20 @@ channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset) | |||
657 | error("accept from auth socket: %.100s", strerror(errno)); | 667 | error("accept from auth socket: %.100s", strerror(errno)); |
658 | return; | 668 | return; |
659 | } | 669 | } |
660 | newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, | 670 | newch = channel_new("accepted auth socket", |
661 | xstrdup("accepted auth socket")); | 671 | SSH_CHANNEL_OPENING, newsock, newsock, -1, |
662 | packet_start(SSH_SMSG_AGENT_OPEN); | 672 | c->local_window_max, c->local_maxpacket, |
663 | packet_put_int(newch); | 673 | 0, xstrdup("accepted auth socket"), 1); |
674 | if (compat20) { | ||
675 | packet_start(SSH2_MSG_CHANNEL_OPEN); | ||
676 | packet_put_cstring("auth-agent@openssh.com"); | ||
677 | packet_put_int(newch); | ||
678 | packet_put_int(c->local_window_max); | ||
679 | packet_put_int(c->local_maxpacket); | ||
680 | } else { | ||
681 | packet_start(SSH_SMSG_AGENT_OPEN); | ||
682 | packet_put_int(newch); | ||
683 | } | ||
664 | packet_send(); | 684 | packet_send(); |
665 | } | 685 | } |
666 | } | 686 | } |
@@ -820,11 +840,15 @@ channel_handler_init_20(void) | |||
820 | channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20; | 840 | channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20; |
821 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; | 841 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; |
822 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; | 842 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; |
843 | channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; | ||
823 | channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; | 844 | channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; |
845 | channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; | ||
824 | 846 | ||
825 | channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2; | 847 | channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2; |
826 | channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; | 848 | channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; |
849 | channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; | ||
827 | channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; | 850 | channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; |
851 | channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; | ||
828 | } | 852 | } |
829 | 853 | ||
830 | void | 854 | void |
@@ -1326,6 +1350,7 @@ channel_stop_listening() | |||
1326 | channel_free(i); | 1350 | channel_free(i); |
1327 | break; | 1351 | break; |
1328 | case SSH_CHANNEL_PORT_LISTENER: | 1352 | case SSH_CHANNEL_PORT_LISTENER: |
1353 | case SSH_CHANNEL_RPORT_LISTENER: | ||
1329 | case SSH_CHANNEL_X11_LISTENER: | 1354 | case SSH_CHANNEL_X11_LISTENER: |
1330 | close(channels[i].sock); | 1355 | close(channels[i].sock); |
1331 | channel_free(i); | 1356 | channel_free(i); |
@@ -1369,6 +1394,7 @@ channel_still_open() | |||
1369 | case SSH_CHANNEL_FREE: | 1394 | case SSH_CHANNEL_FREE: |
1370 | case SSH_CHANNEL_X11_LISTENER: | 1395 | case SSH_CHANNEL_X11_LISTENER: |
1371 | case SSH_CHANNEL_PORT_LISTENER: | 1396 | case SSH_CHANNEL_PORT_LISTENER: |
1397 | case SSH_CHANNEL_RPORT_LISTENER: | ||
1372 | case SSH_CHANNEL_CLOSED: | 1398 | case SSH_CHANNEL_CLOSED: |
1373 | case SSH_CHANNEL_AUTH_SOCKET: | 1399 | case SSH_CHANNEL_AUTH_SOCKET: |
1374 | continue; | 1400 | continue; |
@@ -1414,6 +1440,7 @@ channel_open_message() | |||
1414 | case SSH_CHANNEL_FREE: | 1440 | case SSH_CHANNEL_FREE: |
1415 | case SSH_CHANNEL_X11_LISTENER: | 1441 | case SSH_CHANNEL_X11_LISTENER: |
1416 | case SSH_CHANNEL_PORT_LISTENER: | 1442 | case SSH_CHANNEL_PORT_LISTENER: |
1443 | case SSH_CHANNEL_RPORT_LISTENER: | ||
1417 | case SSH_CHANNEL_CLOSED: | 1444 | case SSH_CHANNEL_CLOSED: |
1418 | case SSH_CHANNEL_AUTH_SOCKET: | 1445 | case SSH_CHANNEL_AUTH_SOCKET: |
1419 | continue; | 1446 | continue; |
@@ -1446,19 +1473,44 @@ channel_open_message() | |||
1446 | * Initiate forwarding of connections to local port "port" through the secure | 1473 | * Initiate forwarding of connections to local port "port" through the secure |
1447 | * channel to host:port from remote side. | 1474 | * channel to host:port from remote side. |
1448 | */ | 1475 | */ |
1476 | void | ||
1477 | channel_request_local_forwarding(u_short listen_port, const char *host_to_connect, | ||
1478 | u_short port_to_connect, int gateway_ports) | ||
1479 | { | ||
1480 | channel_request_forwarding( | ||
1481 | NULL, listen_port, | ||
1482 | host_to_connect, port_to_connect, | ||
1483 | gateway_ports, /*remote_fwd*/ 0); | ||
1484 | } | ||
1449 | 1485 | ||
1486 | /* | ||
1487 | * If 'remote_fwd' is true we have a '-R style' listener for protocol 2 | ||
1488 | * (SSH_CHANNEL_RPORT_LISTENER). | ||
1489 | */ | ||
1450 | void | 1490 | void |
1451 | channel_request_local_forwarding(u_short port, const char *host, | 1491 | channel_request_forwarding( |
1452 | u_short host_port, int gateway_ports) | 1492 | const char *listen_address, u_short listen_port, |
1493 | const char *host_to_connect, u_short port_to_connect, | ||
1494 | int gateway_ports, int remote_fwd) | ||
1453 | { | 1495 | { |
1454 | int success, ch, sock, on = 1; | 1496 | int success, ch, sock, on = 1, ctype; |
1455 | struct addrinfo hints, *ai, *aitop; | 1497 | struct addrinfo hints, *ai, *aitop; |
1456 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | 1498 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; |
1499 | const char *host; | ||
1457 | struct linger linger; | 1500 | struct linger linger; |
1458 | 1501 | ||
1502 | if (remote_fwd) { | ||
1503 | host = listen_address; | ||
1504 | ctype = SSH_CHANNEL_RPORT_LISTENER; | ||
1505 | } else { | ||
1506 | host = host_to_connect; | ||
1507 | ctype =SSH_CHANNEL_PORT_LISTENER; | ||
1508 | } | ||
1509 | |||
1459 | if (strlen(host) > sizeof(channels[0].path) - 1) | 1510 | if (strlen(host) > sizeof(channels[0].path) - 1) |
1460 | packet_disconnect("Forward host name too long."); | 1511 | packet_disconnect("Forward host name too long."); |
1461 | 1512 | ||
1513 | /* XXX listen_address is currently ignored */ | ||
1462 | /* | 1514 | /* |
1463 | * getaddrinfo returns a loopback address if the hostname is | 1515 | * getaddrinfo returns a loopback address if the hostname is |
1464 | * set to NULL and hints.ai_flags is not AI_PASSIVE | 1516 | * set to NULL and hints.ai_flags is not AI_PASSIVE |
@@ -1467,7 +1519,7 @@ channel_request_local_forwarding(u_short port, const char *host, | |||
1467 | hints.ai_family = IPv4or6; | 1519 | hints.ai_family = IPv4or6; |
1468 | hints.ai_flags = gateway_ports ? AI_PASSIVE : 0; | 1520 | hints.ai_flags = gateway_ports ? AI_PASSIVE : 0; |
1469 | hints.ai_socktype = SOCK_STREAM; | 1521 | hints.ai_socktype = SOCK_STREAM; |
1470 | snprintf(strport, sizeof strport, "%d", port); | 1522 | snprintf(strport, sizeof strport, "%d", listen_port); |
1471 | if (getaddrinfo(NULL, strport, &hints, &aitop) != 0) | 1523 | if (getaddrinfo(NULL, strport, &hints, &aitop) != 0) |
1472 | packet_disconnect("getaddrinfo: fatal error"); | 1524 | packet_disconnect("getaddrinfo: fatal error"); |
1473 | 1525 | ||
@@ -1477,7 +1529,7 @@ channel_request_local_forwarding(u_short port, const char *host, | |||
1477 | continue; | 1529 | continue; |
1478 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), | 1530 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), |
1479 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { | 1531 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { |
1480 | error("channel_request_local_forwarding: getnameinfo failed"); | 1532 | error("channel_request_forwarding: getnameinfo failed"); |
1481 | continue; | 1533 | continue; |
1482 | } | 1534 | } |
1483 | /* Create a port to listen for the host. */ | 1535 | /* Create a port to listen for the host. */ |
@@ -1515,18 +1567,16 @@ channel_request_local_forwarding(u_short port, const char *host, | |||
1515 | continue; | 1567 | continue; |
1516 | } | 1568 | } |
1517 | /* Allocate a channel number for the socket. */ | 1569 | /* Allocate a channel number for the socket. */ |
1518 | ch = channel_new( | 1570 | ch = channel_new("port listener", ctype, sock, sock, -1, |
1519 | "port listener", SSH_CHANNEL_PORT_LISTENER, | ||
1520 | sock, sock, -1, | ||
1521 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | 1571 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
1522 | 0, xstrdup("port listener"), 1); | 1572 | 0, xstrdup("port listener"), 1); |
1523 | strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); | 1573 | strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); |
1524 | channels[ch].host_port = host_port; | 1574 | channels[ch].host_port = port_to_connect; |
1525 | channels[ch].listening_port = port; | 1575 | channels[ch].listening_port = listen_port; |
1526 | success = 1; | 1576 | success = 1; |
1527 | } | 1577 | } |
1528 | if (success == 0) | 1578 | if (success == 0) |
1529 | packet_disconnect("cannot listen port: %d", port); | 1579 | packet_disconnect("cannot listen port: %d", listen_port); /*XXX ?disconnect? */ |
1530 | freeaddrinfo(aitop); | 1580 | freeaddrinfo(aitop); |
1531 | } | 1581 | } |
1532 | 1582 | ||
@@ -1536,19 +1586,15 @@ channel_request_local_forwarding(u_short port, const char *host, | |||
1536 | */ | 1586 | */ |
1537 | 1587 | ||
1538 | void | 1588 | void |
1539 | channel_request_remote_forwarding(u_short listen_port, const char *host_to_connect, | 1589 | channel_request_remote_forwarding(u_short listen_port, |
1540 | u_short port_to_connect) | 1590 | const char *host_to_connect, u_short port_to_connect) |
1541 | { | 1591 | { |
1542 | int payload_len; | 1592 | int payload_len, type, success = 0; |
1593 | |||
1543 | /* Record locally that connection to this host/port is permitted. */ | 1594 | /* Record locally that connection to this host/port is permitted. */ |
1544 | if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) | 1595 | if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) |
1545 | fatal("channel_request_remote_forwarding: too many forwards"); | 1596 | fatal("channel_request_remote_forwarding: too many forwards"); |
1546 | 1597 | ||
1547 | permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect); | ||
1548 | permitted_opens[num_permitted_opens].port_to_connect = port_to_connect; | ||
1549 | permitted_opens[num_permitted_opens].listen_port = listen_port; | ||
1550 | num_permitted_opens++; | ||
1551 | |||
1552 | /* Send the forward request to the remote side. */ | 1598 | /* Send the forward request to the remote side. */ |
1553 | if (compat20) { | 1599 | if (compat20) { |
1554 | const char *address_to_bind = "0.0.0.0"; | 1600 | const char *address_to_bind = "0.0.0.0"; |
@@ -1557,6 +1603,10 @@ channel_request_remote_forwarding(u_short listen_port, const char *host_to_conne | |||
1557 | packet_put_char(0); /* boolean: want reply */ | 1603 | packet_put_char(0); /* boolean: want reply */ |
1558 | packet_put_cstring(address_to_bind); | 1604 | packet_put_cstring(address_to_bind); |
1559 | packet_put_int(listen_port); | 1605 | packet_put_int(listen_port); |
1606 | packet_send(); | ||
1607 | packet_write_wait(); | ||
1608 | /* Assume that server accepts the request */ | ||
1609 | success = 1; | ||
1560 | } else { | 1610 | } else { |
1561 | packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); | 1611 | packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); |
1562 | packet_put_int(listen_port); | 1612 | packet_put_int(listen_port); |
@@ -1564,11 +1614,27 @@ channel_request_remote_forwarding(u_short listen_port, const char *host_to_conne | |||
1564 | packet_put_int(port_to_connect); | 1614 | packet_put_int(port_to_connect); |
1565 | packet_send(); | 1615 | packet_send(); |
1566 | packet_write_wait(); | 1616 | packet_write_wait(); |
1567 | /* | 1617 | |
1568 | * Wait for response from the remote side. It will send a disconnect | 1618 | /* Wait for response from the remote side. */ |
1569 | * message on failure, and we will never see it here. | 1619 | type = packet_read(&payload_len); |
1570 | */ | 1620 | switch (type) { |
1571 | packet_read_expect(&payload_len, SSH_SMSG_SUCCESS); | 1621 | case SSH_SMSG_SUCCESS: |
1622 | success = 1; | ||
1623 | break; | ||
1624 | case SSH_SMSG_FAILURE: | ||
1625 | log("Warning: Server denied remote port forwarding."); | ||
1626 | break; | ||
1627 | default: | ||
1628 | /* Unknown packet */ | ||
1629 | packet_disconnect("Protocol error for port forward request:" | ||
1630 | "received packet type %d.", type); | ||
1631 | } | ||
1632 | } | ||
1633 | if (success) { | ||
1634 | permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect); | ||
1635 | permitted_opens[num_permitted_opens].port_to_connect = port_to_connect; | ||
1636 | permitted_opens[num_permitted_opens].listen_port = listen_port; | ||
1637 | num_permitted_opens++; | ||
1572 | } | 1638 | } |
1573 | } | 1639 | } |
1574 | 1640 | ||
@@ -1598,9 +1664,7 @@ channel_input_port_forward_request(int is_root, int gateway_ports) | |||
1598 | packet_disconnect("Requested forwarding of port %d but user is not root.", | 1664 | packet_disconnect("Requested forwarding of port %d but user is not root.", |
1599 | port); | 1665 | port); |
1600 | #endif | 1666 | #endif |
1601 | /* | 1667 | /* Initiate forwarding */ |
1602 | * Initiate forwarding, | ||
1603 | */ | ||
1604 | channel_request_local_forwarding(port, hostname, host_port, gateway_ports); | 1668 | channel_request_local_forwarding(port, hostname, host_port, gateway_ports); |
1605 | 1669 | ||
1606 | /* Free the argument string. */ | 1670 | /* Free the argument string. */ |
@@ -1656,6 +1720,18 @@ channel_connect_to(const char *host, u_short host_port) | |||
1656 | /* success */ | 1720 | /* success */ |
1657 | return sock; | 1721 | return sock; |
1658 | } | 1722 | } |
1723 | int | ||
1724 | channel_connect_by_listen_adress(u_short listen_port) | ||
1725 | { | ||
1726 | int i; | ||
1727 | for (i = 0; i < num_permitted_opens; i++) | ||
1728 | if (permitted_opens[i].listen_port == listen_port) | ||
1729 | return channel_connect_to( | ||
1730 | permitted_opens[i].host_to_connect, | ||
1731 | permitted_opens[i].port_to_connect); | ||
1732 | debug("channel_connect_by_listen_adress: unknown listen_port %d", listen_port); | ||
1733 | return -1; | ||
1734 | } | ||
1659 | 1735 | ||
1660 | /* | 1736 | /* |
1661 | * This is called after receiving PORT_OPEN message. This attempts to | 1737 | * This is called after receiving PORT_OPEN message. This attempts to |
@@ -2233,8 +2309,11 @@ auth_input_request_forwarding(struct passwd * pw) | |||
2233 | packet_disconnect("listen: %.100s", strerror(errno)); | 2309 | packet_disconnect("listen: %.100s", strerror(errno)); |
2234 | 2310 | ||
2235 | /* Allocate a channel for the authentication agent socket. */ | 2311 | /* Allocate a channel for the authentication agent socket. */ |
2236 | newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock, | 2312 | newch = channel_new("auth socket", |
2237 | xstrdup("auth socket")); | 2313 | SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, |
2314 | CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, | ||
2315 | 0, xstrdup("auth socket"), 1); | ||
2316 | |||
2238 | strlcpy(channels[newch].path, channel_forwarded_auth_socket_name, | 2317 | strlcpy(channels[newch].path, channel_forwarded_auth_socket_name, |
2239 | sizeof(channels[newch].path)); | 2318 | sizeof(channels[newch].path)); |
2240 | return 1; | 2319 | return 1; |
diff --git a/channels.h b/channels.h index 00526860c..8f5e987fc 100644 --- a/channels.h +++ b/channels.h | |||
@@ -32,7 +32,7 @@ | |||
32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
34 | */ | 34 | */ |
35 | /* RCSID("$OpenBSD: channels.h,v 1.22 2000/10/27 07:48:22 markus Exp $"); */ | 35 | /* RCSID("$OpenBSD: channels.h,v 1.23 2000/11/06 23:04:56 markus Exp $"); */ |
36 | 36 | ||
37 | #ifndef CHANNELS_H | 37 | #ifndef CHANNELS_H |
38 | #define CHANNELS_H | 38 | #define CHANNELS_H |
@@ -49,7 +49,8 @@ | |||
49 | #define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */ | 49 | #define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */ |
50 | #define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */ | 50 | #define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */ |
51 | #define SSH_CHANNEL_LARVAL 10 /* larval session */ | 51 | #define SSH_CHANNEL_LARVAL 10 /* larval session */ |
52 | #define SSH_CHANNEL_MAX_TYPE 11 | 52 | #define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */ |
53 | #define SSH_CHANNEL_MAX_TYPE 12 | ||
53 | 54 | ||
54 | /* | 55 | /* |
55 | * Data structure for channel data. This is iniailized in channel_allocate | 56 | * Data structure for channel data. This is iniailized in channel_allocate |
@@ -147,7 +148,6 @@ void channel_input_open_confirmation(int type, int plen, void *ctxt); | |||
147 | void channel_input_open_failure(int type, int plen, void *ctxt); | 148 | void channel_input_open_failure(int type, int plen, void *ctxt); |
148 | void channel_input_port_open(int type, int plen, void *ctxt); | 149 | void channel_input_port_open(int type, int plen, void *ctxt); |
149 | void channel_input_window_adjust(int type, int plen, void *ctxt); | 150 | void channel_input_window_adjust(int type, int plen, void *ctxt); |
150 | void channel_input_open(int type, int plen, void *ctxt); | ||
151 | 151 | ||
152 | /* Sets specific protocol options. */ | 152 | /* Sets specific protocol options. */ |
153 | void channel_set_options(int hostname_in_open); | 153 | void channel_set_options(int hostname_in_open); |
@@ -202,12 +202,15 @@ char *channel_open_message(void); | |||
202 | 202 | ||
203 | /* | 203 | /* |
204 | * Initiate forwarding of connections to local port "port" through the secure | 204 | * Initiate forwarding of connections to local port "port" through the secure |
205 | * channel to host:port from remote side. This never returns if there was an | 205 | * channel to host:port from remote side. |
206 | * error. | ||
207 | */ | 206 | */ |
208 | void | 207 | void |
209 | channel_request_local_forwarding(u_short port, const char *host, | 208 | channel_request_local_forwarding(u_short listen_port, |
210 | u_short remote_port, int gateway_ports); | 209 | const char *host_to_connect, u_short port_to_connect, int gateway_ports); |
210 | void | ||
211 | channel_request_forwarding(const char *listen_address, u_short listen_port, | ||
212 | const char *host_to_connect, u_short port_to_connect, int gateway_ports, | ||
213 | int remote_fwd); | ||
211 | 214 | ||
212 | /* | 215 | /* |
213 | * Initiate forwarding of connections to port "port" on remote host through | 216 | * Initiate forwarding of connections to port "port" on remote host through |
@@ -288,6 +291,7 @@ void auth_input_open_request(int type, int plen, void *ctxt); | |||
288 | 291 | ||
289 | /* XXX */ | 292 | /* XXX */ |
290 | int channel_connect_to(const char *host, u_short host_port); | 293 | int channel_connect_to(const char *host, u_short host_port); |
294 | int channel_connect_by_listen_adress(u_short listen_port); | ||
291 | int x11_connect_display(void); | 295 | int x11_connect_display(void); |
292 | 296 | ||
293 | #endif | 297 | #endif |
diff --git a/clientloop.c b/clientloop.c index bccb9be2f..8f16d2fb9 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -59,7 +59,7 @@ | |||
59 | */ | 59 | */ |
60 | 60 | ||
61 | #include "includes.h" | 61 | #include "includes.h" |
62 | RCSID("$OpenBSD: clientloop.c,v 1.39 2000/10/27 07:48:22 markus Exp $"); | 62 | RCSID("$OpenBSD: clientloop.c,v 1.40 2000/11/06 23:04:56 markus Exp $"); |
63 | 63 | ||
64 | #include "xmalloc.h" | 64 | #include "xmalloc.h" |
65 | #include "ssh.h" | 65 | #include "ssh.h" |
@@ -75,6 +75,10 @@ RCSID("$OpenBSD: clientloop.c,v 1.39 2000/10/27 07:48:22 markus Exp $"); | |||
75 | #include "buffer.h" | 75 | #include "buffer.h" |
76 | #include "bufaux.h" | 76 | #include "bufaux.h" |
77 | 77 | ||
78 | #include <openssl/dsa.h> | ||
79 | #include <openssl/rsa.h> | ||
80 | #include "key.h" | ||
81 | #include "authfd.h" | ||
78 | 82 | ||
79 | /* import options */ | 83 | /* import options */ |
80 | extern Options options; | 84 | extern Options options; |
@@ -1016,13 +1020,99 @@ client_input_exit_status(int type, int plen, void *ctxt) | |||
1016 | quit_pending = 1; | 1020 | quit_pending = 1; |
1017 | } | 1021 | } |
1018 | 1022 | ||
1023 | Channel * | ||
1024 | client_request_forwarded_tcpip(const char *request_type, int rchan) | ||
1025 | { | ||
1026 | Channel* c = NULL; | ||
1027 | char *listen_address, *originator_address; | ||
1028 | int listen_port, originator_port; | ||
1029 | int sock, newch; | ||
1030 | |||
1031 | /* Get rest of the packet */ | ||
1032 | listen_address = packet_get_string(NULL); | ||
1033 | listen_port = packet_get_int(); | ||
1034 | originator_address = packet_get_string(NULL); | ||
1035 | originator_port = packet_get_int(); | ||
1036 | packet_done(); | ||
1037 | |||
1038 | debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d", | ||
1039 | listen_address, listen_port, originator_address, originator_port); | ||
1040 | |||
1041 | sock = channel_connect_by_listen_adress(listen_port); | ||
1042 | if (sock >= 0) { | ||
1043 | newch = channel_new("forwarded-tcpip", | ||
1044 | SSH_CHANNEL_OPEN, sock, sock, -1, | ||
1045 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, | ||
1046 | xstrdup(originator_address), 1); | ||
1047 | c = channel_lookup(newch); | ||
1048 | } | ||
1049 | xfree(originator_address); | ||
1050 | xfree(listen_address); | ||
1051 | return c; | ||
1052 | } | ||
1053 | |||
1054 | Channel* | ||
1055 | client_request_x11(const char *request_type, int rchan) | ||
1056 | { | ||
1057 | Channel *c = NULL; | ||
1058 | char *originator; | ||
1059 | int originator_port; | ||
1060 | int sock, newch; | ||
1061 | |||
1062 | if (!options.forward_x11) { | ||
1063 | error("Warning: ssh server tried X11 forwarding."); | ||
1064 | error("Warning: this is probably a break in attempt by a malicious server."); | ||
1065 | return NULL; | ||
1066 | } | ||
1067 | originator = packet_get_string(NULL); | ||
1068 | if (datafellows & SSH_BUG_X11FWD) { | ||
1069 | debug2("buggy server: x11 request w/o originator_port"); | ||
1070 | originator_port = 0; | ||
1071 | } else { | ||
1072 | originator_port = packet_get_int(); | ||
1073 | } | ||
1074 | packet_done(); | ||
1075 | /* XXX check permission */ | ||
1076 | sock = x11_connect_display(); | ||
1077 | if (sock >= 0) { | ||
1078 | newch = channel_new("x11", | ||
1079 | SSH_CHANNEL_X11_OPEN, sock, sock, -1, | ||
1080 | CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, | ||
1081 | xstrdup("x11"), 1); | ||
1082 | c = channel_lookup(newch); | ||
1083 | } | ||
1084 | xfree(originator); | ||
1085 | return c; | ||
1086 | } | ||
1087 | |||
1088 | Channel* | ||
1089 | client_request_agent(const char *request_type, int rchan) | ||
1090 | { | ||
1091 | Channel *c = NULL; | ||
1092 | int sock, newch; | ||
1093 | |||
1094 | if (!options.forward_agent) { | ||
1095 | error("Warning: ssh server tried agent forwarding."); | ||
1096 | error("Warning: this is probably a break in attempt by a malicious server."); | ||
1097 | return NULL; | ||
1098 | } | ||
1099 | sock = ssh_get_authentication_socket(); | ||
1100 | if (sock >= 0) { | ||
1101 | newch = channel_new("authentication agent connection", | ||
1102 | SSH_CHANNEL_OPEN, sock, sock, -1, | ||
1103 | CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, | ||
1104 | xstrdup("authentication agent connection"), 1); | ||
1105 | c = channel_lookup(newch); | ||
1106 | } | ||
1107 | return c; | ||
1108 | } | ||
1109 | |||
1019 | /* XXXX move to generic input handler */ | 1110 | /* XXXX move to generic input handler */ |
1020 | void | 1111 | void |
1021 | client_input_channel_open(int type, int plen, void *ctxt) | 1112 | client_input_channel_open(int type, int plen, void *ctxt) |
1022 | { | 1113 | { |
1023 | Channel *c = NULL; | 1114 | Channel *c = NULL; |
1024 | char *ctype; | 1115 | char *ctype; |
1025 | int id; | ||
1026 | unsigned int len; | 1116 | unsigned int len; |
1027 | int rchan; | 1117 | int rchan; |
1028 | int rmaxpack; | 1118 | int rmaxpack; |
@@ -1036,28 +1126,12 @@ client_input_channel_open(int type, int plen, void *ctxt) | |||
1036 | debug("client_input_channel_open: ctype %s rchan %d win %d max %d", | 1126 | debug("client_input_channel_open: ctype %s rchan %d win %d max %d", |
1037 | ctype, rchan, rwindow, rmaxpack); | 1127 | ctype, rchan, rwindow, rmaxpack); |
1038 | 1128 | ||
1039 | if (strcmp(ctype, "x11") == 0 && options.forward_x11) { | 1129 | if (strcmp(ctype, "forwarded-tcpip") == 0) { |
1040 | int sock; | 1130 | c = client_request_forwarded_tcpip(ctype, rchan); |
1041 | char *originator; | 1131 | } else if (strcmp(ctype, "x11") == 0) { |
1042 | int originator_port; | 1132 | c = client_request_x11(ctype, rchan); |
1043 | originator = packet_get_string(NULL); | 1133 | } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { |
1044 | if (datafellows & SSH_BUG_X11FWD) { | 1134 | c = client_request_agent(ctype, rchan); |
1045 | debug2("buggy server: x11 request w/o originator_port"); | ||
1046 | originator_port = 0; | ||
1047 | } else { | ||
1048 | originator_port = packet_get_int(); | ||
1049 | } | ||
1050 | packet_done(); | ||
1051 | /* XXX check permission */ | ||
1052 | xfree(originator); | ||
1053 | /* XXX move to channels.c */ | ||
1054 | sock = x11_connect_display(); | ||
1055 | if (sock >= 0) { | ||
1056 | id = channel_new("x11", SSH_CHANNEL_X11_OPEN, | ||
1057 | sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, | ||
1058 | CHAN_X11_PACKET_DEFAULT, 0, xstrdup("x11"), 1); | ||
1059 | c = channel_lookup(id); | ||
1060 | } | ||
1061 | } | 1135 | } |
1062 | /* XXX duplicate : */ | 1136 | /* XXX duplicate : */ |
1063 | if (c != NULL) { | 1137 | if (c != NULL) { |
diff --git a/contrib/redhat/sshd.init b/contrib/redhat/sshd.init index 41f98ad88..a4df64276 100755 --- a/contrib/redhat/sshd.init +++ b/contrib/redhat/sshd.init | |||
@@ -19,13 +19,27 @@ RETVAL=0 | |||
19 | 19 | ||
20 | # Some functions to make the below more readable | 20 | # Some functions to make the below more readable |
21 | KEYGEN=/usr/bin/ssh-keygen | 21 | KEYGEN=/usr/bin/ssh-keygen |
22 | RSA_KEY=/etc/ssh/ssh_host_key | 22 | RSA1_KEY=/etc/ssh/ssh_host_key |
23 | RSA_KEY=/etc/ssh/ssh_host_rsa_key | ||
23 | DSA_KEY=/etc/ssh/ssh_host_dsa_key | 24 | DSA_KEY=/etc/ssh/ssh_host_dsa_key |
24 | PID_FILE=/var/run/sshd.pid | 25 | PID_FILE=/var/run/sshd.pid |
26 | do_rsa1_keygen() { | ||
27 | if ! test -f $RSA1_KEY ; then | ||
28 | echo -n "Generating SSH1 RSA host key: " | ||
29 | if $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N '' >&/dev/null; then | ||
30 | success "RSA1 key generation" | ||
31 | echo | ||
32 | else | ||
33 | failure "RSA1 key generation" | ||
34 | echo | ||
35 | exit 1 | ||
36 | fi | ||
37 | fi | ||
38 | } | ||
25 | do_rsa_keygen() { | 39 | do_rsa_keygen() { |
26 | if $KEYGEN -R && ! test -f $RSA_KEY ; then | 40 | if ! test -f $RSA_KEY ; then |
27 | echo -n "Generating SSH RSA host key: " | 41 | echo -n "Generating SSH2 RSA host key: " |
28 | if $KEYGEN -q -b 1024 -f $RSA_KEY -C '' -N '' >&/dev/null; then | 42 | if $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N '' >&/dev/null; then |
29 | success "RSA key generation" | 43 | success "RSA key generation" |
30 | echo | 44 | echo |
31 | else | 45 | else |
@@ -37,8 +51,8 @@ do_rsa_keygen() { | |||
37 | } | 51 | } |
38 | do_dsa_keygen() { | 52 | do_dsa_keygen() { |
39 | if ! test -f $DSA_KEY ; then | 53 | if ! test -f $DSA_KEY ; then |
40 | echo -n "Generating SSH DSA host key: " | 54 | echo -n "Generating SSH2 DSA host key: " |
41 | if $KEYGEN -q -d -b 1024 -f $DSA_KEY -C '' -N '' >&/dev/null; then | 55 | if $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N '' >&/dev/null; then |
42 | success "DSA key generation" | 56 | success "DSA key generation" |
43 | echo | 57 | echo |
44 | else | 58 | else |
@@ -52,6 +66,7 @@ do_dsa_keygen() { | |||
52 | case "$1" in | 66 | case "$1" in |
53 | start) | 67 | start) |
54 | # Create keys if necessary | 68 | # Create keys if necessary |
69 | do_rsa1_keygen; | ||
55 | do_rsa_keygen; | 70 | do_rsa_keygen; |
56 | do_dsa_keygen; | 71 | do_dsa_keygen; |
57 | 72 | ||
diff --git a/hostfile.c b/hostfile.c index 9c03a4688..3b0f286fd 100644 --- a/hostfile.c +++ b/hostfile.c | |||
@@ -36,7 +36,7 @@ | |||
36 | */ | 36 | */ |
37 | 37 | ||
38 | #include "includes.h" | 38 | #include "includes.h" |
39 | RCSID("$OpenBSD: hostfile.c,v 1.20 2000/09/07 20:27:51 deraadt Exp $"); | 39 | RCSID("$OpenBSD: hostfile.c,v 1.21 2000/11/12 19:50:37 markus Exp $"); |
40 | 40 | ||
41 | #include "packet.h" | 41 | #include "packet.h" |
42 | #include "match.h" | 42 | #include "match.h" |
@@ -54,15 +54,13 @@ RCSID("$OpenBSD: hostfile.c,v 1.20 2000/09/07 20:27:51 deraadt Exp $"); | |||
54 | int | 54 | int |
55 | hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret) | 55 | hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret) |
56 | { | 56 | { |
57 | unsigned int bits; | ||
58 | char *cp; | 57 | char *cp; |
59 | 58 | ||
60 | /* Skip leading whitespace. */ | 59 | /* Skip leading whitespace. */ |
61 | for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) | 60 | for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) |
62 | ; | 61 | ; |
63 | 62 | ||
64 | bits = key_read(ret, &cp); | 63 | if (key_read(ret, &cp) != 1) |
65 | if (bits == 0) | ||
66 | return 0; | 64 | return 0; |
67 | 65 | ||
68 | /* Skip trailing whitespace. */ | 66 | /* Skip trailing whitespace. */ |
@@ -71,14 +69,14 @@ hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret) | |||
71 | 69 | ||
72 | /* Return results. */ | 70 | /* Return results. */ |
73 | *cpp = cp; | 71 | *cpp = cp; |
74 | *bitsp = bits; | 72 | *bitsp = key_size(ret); |
75 | return 1; | 73 | return 1; |
76 | } | 74 | } |
77 | 75 | ||
78 | int | 76 | int |
79 | auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n) | 77 | auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n) |
80 | { | 78 | { |
81 | Key *k = key_new(KEY_RSA); | 79 | Key *k = key_new(KEY_RSA1); |
82 | int ret = hostfile_read_key(cpp, bitsp, k); | 80 | int ret = hostfile_read_key(cpp, bitsp, k); |
83 | BN_copy(e, k->rsa->e); | 81 | BN_copy(e, k->rsa->e); |
84 | BN_copy(n, k->rsa->n); | 82 | BN_copy(n, k->rsa->n); |
@@ -89,7 +87,7 @@ auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n) | |||
89 | int | 87 | int |
90 | hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum) | 88 | hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum) |
91 | { | 89 | { |
92 | if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) | 90 | if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL) |
93 | return 1; | 91 | return 1; |
94 | if (bits != BN_num_bits(key->rsa->n)) { | 92 | if (bits != BN_num_bits(key->rsa->n)) { |
95 | log("Warning: %s, line %d: keysize mismatch for host %s: " | 93 | log("Warning: %s, line %d: keysize mismatch for host %s: " |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: kex.c,v 1.12 2000/10/11 20:27:23 markus Exp $"); | 26 | RCSID("$OpenBSD: kex.c,v 1.13 2000/11/12 19:50:37 markus Exp $"); |
27 | 27 | ||
28 | #include "ssh.h" | 28 | #include "ssh.h" |
29 | #include "ssh2.h" | 29 | #include "ssh2.h" |
@@ -43,6 +43,7 @@ RCSID("$OpenBSD: kex.c,v 1.12 2000/10/11 20:27:23 markus Exp $"); | |||
43 | #include <openssl/pem.h> | 43 | #include <openssl/pem.h> |
44 | 44 | ||
45 | #include "kex.h" | 45 | #include "kex.h" |
46 | #include "key.h" | ||
46 | 47 | ||
47 | #define KEX_COOKIE_LEN 16 | 48 | #define KEX_COOKIE_LEN 16 |
48 | 49 | ||
@@ -454,11 +455,12 @@ choose_kex(Kex *k, char *client, char *server) | |||
454 | void | 455 | void |
455 | choose_hostkeyalg(Kex *k, char *client, char *server) | 456 | choose_hostkeyalg(Kex *k, char *client, char *server) |
456 | { | 457 | { |
457 | k->hostkeyalg = get_match(client, server); | 458 | char *hostkeyalg = get_match(client, server); |
458 | if (k->hostkeyalg == NULL) | 459 | if (hostkeyalg == NULL) |
459 | fatal("no hostkey alg"); | 460 | fatal("no hostkey alg"); |
460 | if (strcmp(k->hostkeyalg, KEX_DSS) != 0) | 461 | k->hostkey_type = key_type_from_name(hostkeyalg); |
461 | fatal("bad hostkey alg %s", k->hostkeyalg); | 462 | if (k->hostkey_type == KEY_UNSPEC) |
463 | fatal("bad hostkey alg '%s'", hostkeyalg); | ||
462 | } | 464 | } |
463 | 465 | ||
464 | Kex * | 466 | Kex * |
@@ -85,7 +85,7 @@ struct Kex { | |||
85 | int we_need; | 85 | int we_need; |
86 | int server; | 86 | int server; |
87 | char *name; | 87 | char *name; |
88 | char *hostkeyalg; | 88 | int hostkey_type; |
89 | int kex_type; | 89 | int kex_type; |
90 | }; | 90 | }; |
91 | 91 | ||
@@ -39,12 +39,14 @@ | |||
39 | #include <openssl/evp.h> | 39 | #include <openssl/evp.h> |
40 | #include "xmalloc.h" | 40 | #include "xmalloc.h" |
41 | #include "key.h" | 41 | #include "key.h" |
42 | #include "dsa.h" | 42 | #include "rsa.h" |
43 | #include "ssh-dss.h" | ||
44 | #include "ssh-rsa.h" | ||
43 | #include "uuencode.h" | 45 | #include "uuencode.h" |
46 | #include "buffer.h" | ||
47 | #include "bufaux.h" | ||
44 | 48 | ||
45 | RCSID("$OpenBSD: key.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $"); | 49 | RCSID("$OpenBSD: key.c,v 1.12 2000/11/12 19:50:37 markus Exp $"); |
46 | |||
47 | #define SSH_DSS "ssh-dss" | ||
48 | 50 | ||
49 | Key * | 51 | Key * |
50 | key_new(int type) | 52 | key_new(int type) |
@@ -57,6 +59,7 @@ key_new(int type) | |||
57 | k->dsa = NULL; | 59 | k->dsa = NULL; |
58 | k->rsa = NULL; | 60 | k->rsa = NULL; |
59 | switch (k->type) { | 61 | switch (k->type) { |
62 | case KEY_RSA1: | ||
60 | case KEY_RSA: | 63 | case KEY_RSA: |
61 | rsa = RSA_new(); | 64 | rsa = RSA_new(); |
62 | rsa->n = BN_new(); | 65 | rsa->n = BN_new(); |
@@ -71,7 +74,7 @@ key_new(int type) | |||
71 | dsa->pub_key = BN_new(); | 74 | dsa->pub_key = BN_new(); |
72 | k->dsa = dsa; | 75 | k->dsa = dsa; |
73 | break; | 76 | break; |
74 | case KEY_EMPTY: | 77 | case KEY_UNSPEC: |
75 | break; | 78 | break; |
76 | default: | 79 | default: |
77 | fatal("key_new: bad key type %d", k->type); | 80 | fatal("key_new: bad key type %d", k->type); |
@@ -79,10 +82,35 @@ key_new(int type) | |||
79 | } | 82 | } |
80 | return k; | 83 | return k; |
81 | } | 84 | } |
85 | Key * | ||
86 | key_new_private(int type) | ||
87 | { | ||
88 | Key *k = key_new(type); | ||
89 | switch (k->type) { | ||
90 | case KEY_RSA1: | ||
91 | case KEY_RSA: | ||
92 | k->rsa->d = BN_new(); | ||
93 | k->rsa->iqmp = BN_new(); | ||
94 | k->rsa->q = BN_new(); | ||
95 | k->rsa->p = BN_new(); | ||
96 | k->rsa->dmq1 = BN_new(); | ||
97 | k->rsa->dmp1 = BN_new(); | ||
98 | break; | ||
99 | case KEY_DSA: | ||
100 | k->dsa->priv_key = BN_new(); | ||
101 | break; | ||
102 | case KEY_UNSPEC: | ||
103 | break; | ||
104 | default: | ||
105 | break; | ||
106 | } | ||
107 | return k; | ||
108 | } | ||
82 | void | 109 | void |
83 | key_free(Key *k) | 110 | key_free(Key *k) |
84 | { | 111 | { |
85 | switch (k->type) { | 112 | switch (k->type) { |
113 | case KEY_RSA1: | ||
86 | case KEY_RSA: | 114 | case KEY_RSA: |
87 | if (k->rsa != NULL) | 115 | if (k->rsa != NULL) |
88 | RSA_free(k->rsa); | 116 | RSA_free(k->rsa); |
@@ -93,6 +121,8 @@ key_free(Key *k) | |||
93 | DSA_free(k->dsa); | 121 | DSA_free(k->dsa); |
94 | k->dsa = NULL; | 122 | k->dsa = NULL; |
95 | break; | 123 | break; |
124 | case KEY_UNSPEC: | ||
125 | break; | ||
96 | default: | 126 | default: |
97 | fatal("key_free: bad key type %d", k->type); | 127 | fatal("key_free: bad key type %d", k->type); |
98 | break; | 128 | break; |
@@ -105,6 +135,7 @@ key_equal(Key *a, Key *b) | |||
105 | if (a == NULL || b == NULL || a->type != b->type) | 135 | if (a == NULL || b == NULL || a->type != b->type) |
106 | return 0; | 136 | return 0; |
107 | switch (a->type) { | 137 | switch (a->type) { |
138 | case KEY_RSA1: | ||
108 | case KEY_RSA: | 139 | case KEY_RSA: |
109 | return a->rsa != NULL && b->rsa != NULL && | 140 | return a->rsa != NULL && b->rsa != NULL && |
110 | BN_cmp(a->rsa->e, b->rsa->e) == 0 && | 141 | BN_cmp(a->rsa->e, b->rsa->e) == 0 && |
@@ -136,8 +167,9 @@ key_fingerprint(Key *k) | |||
136 | int len = 0; | 167 | int len = 0; |
137 | int nlen, elen; | 168 | int nlen, elen; |
138 | 169 | ||
170 | retval[0] = '\0'; | ||
139 | switch (k->type) { | 171 | switch (k->type) { |
140 | case KEY_RSA: | 172 | case KEY_RSA1: |
141 | nlen = BN_num_bytes(k->rsa->n); | 173 | nlen = BN_num_bytes(k->rsa->n); |
142 | elen = BN_num_bytes(k->rsa->e); | 174 | elen = BN_num_bytes(k->rsa->e); |
143 | len = nlen + elen; | 175 | len = nlen + elen; |
@@ -146,14 +178,16 @@ key_fingerprint(Key *k) | |||
146 | BN_bn2bin(k->rsa->e, blob + nlen); | 178 | BN_bn2bin(k->rsa->e, blob + nlen); |
147 | break; | 179 | break; |
148 | case KEY_DSA: | 180 | case KEY_DSA: |
149 | dsa_make_key_blob(k, &blob, &len); | 181 | case KEY_RSA: |
182 | key_to_blob(k, &blob, &len); | ||
183 | break; | ||
184 | case KEY_UNSPEC: | ||
185 | return retval; | ||
150 | break; | 186 | break; |
151 | default: | 187 | default: |
152 | fatal("key_fingerprint: bad key type %d", k->type); | 188 | fatal("key_fingerprint: bad key type %d", k->type); |
153 | break; | 189 | break; |
154 | } | 190 | } |
155 | retval[0] = '\0'; | ||
156 | |||
157 | if (blob != NULL) { | 191 | if (blob != NULL) { |
158 | int i; | 192 | int i; |
159 | unsigned char digest[EVP_MAX_MD_SIZE]; | 193 | unsigned char digest[EVP_MAX_MD_SIZE]; |
@@ -229,56 +263,106 @@ write_bignum(FILE *f, BIGNUM *num) | |||
229 | free(buf); | 263 | free(buf); |
230 | return 1; | 264 | return 1; |
231 | } | 265 | } |
232 | unsigned int | 266 | |
267 | /* returns 1 ok, -1 error, 0 type mismatch */ | ||
268 | int | ||
233 | key_read(Key *ret, char **cpp) | 269 | key_read(Key *ret, char **cpp) |
234 | { | 270 | { |
235 | Key *k; | 271 | Key *k; |
236 | unsigned int bits = 0; | 272 | int success = -1; |
237 | char *cp; | 273 | char *cp, *space; |
238 | int len, n; | 274 | int len, n, type; |
275 | u_int bits; | ||
239 | unsigned char *blob; | 276 | unsigned char *blob; |
240 | 277 | ||
241 | cp = *cpp; | 278 | cp = *cpp; |
242 | 279 | ||
243 | switch(ret->type) { | 280 | switch(ret->type) { |
244 | case KEY_RSA: | 281 | case KEY_RSA1: |
245 | /* Get number of bits. */ | 282 | /* Get number of bits. */ |
246 | if (*cp < '0' || *cp > '9') | 283 | if (*cp < '0' || *cp > '9') |
247 | return 0; /* Bad bit count... */ | 284 | return -1; /* Bad bit count... */ |
248 | for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) | 285 | for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) |
249 | bits = 10 * bits + *cp - '0'; | 286 | bits = 10 * bits + *cp - '0'; |
250 | if (bits == 0) | 287 | if (bits == 0) |
251 | return 0; | 288 | return -1; |
252 | *cpp = cp; | 289 | *cpp = cp; |
253 | /* Get public exponent, public modulus. */ | 290 | /* Get public exponent, public modulus. */ |
254 | if (!read_bignum(cpp, ret->rsa->e)) | 291 | if (!read_bignum(cpp, ret->rsa->e)) |
255 | return 0; | 292 | return -1; |
256 | if (!read_bignum(cpp, ret->rsa->n)) | 293 | if (!read_bignum(cpp, ret->rsa->n)) |
257 | return 0; | 294 | return -1; |
295 | success = 1; | ||
258 | break; | 296 | break; |
297 | case KEY_UNSPEC: | ||
298 | case KEY_RSA: | ||
259 | case KEY_DSA: | 299 | case KEY_DSA: |
260 | if (strncmp(cp, SSH_DSS " ", 7) != 0) | 300 | space = strchr(cp, ' '); |
301 | if (space == NULL) { | ||
302 | debug3("key_read: no space"); | ||
303 | return -1; | ||
304 | } | ||
305 | *space = '\0'; | ||
306 | type = key_type_from_name(cp); | ||
307 | *space = ' '; | ||
308 | if (type == KEY_UNSPEC) { | ||
309 | debug3("key_read: no key found"); | ||
310 | return -1; | ||
311 | } | ||
312 | cp = space+1; | ||
313 | if (*cp == '\0') { | ||
314 | debug3("key_read: short string"); | ||
315 | return -1; | ||
316 | } | ||
317 | if (ret->type == KEY_UNSPEC) { | ||
318 | ret->type = type; | ||
319 | } else if (ret->type != type) { | ||
320 | /* is a key, but different type */ | ||
321 | debug3("key_read: type mismatch"); | ||
261 | return 0; | 322 | return 0; |
262 | cp += 7; | 323 | } |
263 | len = 2*strlen(cp); | 324 | len = 2*strlen(cp); |
264 | blob = xmalloc(len); | 325 | blob = xmalloc(len); |
265 | n = uudecode(cp, blob, len); | 326 | n = uudecode(cp, blob, len); |
266 | if (n < 0) { | 327 | if (n < 0) { |
267 | error("key_read: uudecode %s failed", cp); | 328 | error("key_read: uudecode %s failed", cp); |
268 | return 0; | 329 | return -1; |
269 | } | 330 | } |
270 | k = dsa_key_from_blob(blob, n); | 331 | k = key_from_blob(blob, n); |
271 | if (k == NULL) { | 332 | if (k == NULL) { |
272 | error("key_read: dsa_key_from_blob %s failed", cp); | 333 | error("key_read: key_from_blob %s failed", cp); |
273 | return 0; | 334 | return -1; |
274 | } | 335 | } |
275 | xfree(blob); | 336 | xfree(blob); |
276 | if (ret->dsa != NULL) | 337 | if (k->type != type) { |
277 | DSA_free(ret->dsa); | 338 | error("key_read: type mismatch: encoding error"); |
278 | ret->dsa = k->dsa; | 339 | key_free(k); |
279 | k->dsa = NULL; | 340 | return -1; |
341 | } | ||
342 | /*XXXX*/ | ||
343 | if (ret->type == KEY_RSA) { | ||
344 | if (ret->rsa != NULL) | ||
345 | RSA_free(ret->rsa); | ||
346 | ret->rsa = k->rsa; | ||
347 | k->rsa = NULL; | ||
348 | success = 1; | ||
349 | #ifdef DEBUG_PK | ||
350 | RSA_print_fp(stderr, ret->rsa, 8); | ||
351 | #endif | ||
352 | } else { | ||
353 | if (ret->dsa != NULL) | ||
354 | DSA_free(ret->dsa); | ||
355 | ret->dsa = k->dsa; | ||
356 | k->dsa = NULL; | ||
357 | success = 1; | ||
358 | #ifdef DEBUG_PK | ||
359 | DSA_print_fp(stderr, ret->dsa, 8); | ||
360 | #endif | ||
361 | } | ||
362 | /*XXXX*/ | ||
363 | if (success != 1) | ||
364 | break; | ||
280 | key_free(k); | 365 | key_free(k); |
281 | bits = BN_num_bits(ret->dsa->p); | ||
282 | /* advance cp: skip whitespace and data */ | 366 | /* advance cp: skip whitespace and data */ |
283 | while (*cp == ' ' || *cp == '\t') | 367 | while (*cp == ' ' || *cp == '\t') |
284 | cp++; | 368 | cp++; |
@@ -290,7 +374,7 @@ key_read(Key *ret, char **cpp) | |||
290 | fatal("key_read: bad key type: %d", ret->type); | 374 | fatal("key_read: bad key type: %d", ret->type); |
291 | break; | 375 | break; |
292 | } | 376 | } |
293 | return bits; | 377 | return success; |
294 | } | 378 | } |
295 | int | 379 | int |
296 | key_write(Key *key, FILE *f) | 380 | key_write(Key *key, FILE *f) |
@@ -298,7 +382,7 @@ key_write(Key *key, FILE *f) | |||
298 | int success = 0; | 382 | int success = 0; |
299 | unsigned int bits = 0; | 383 | unsigned int bits = 0; |
300 | 384 | ||
301 | if (key->type == KEY_RSA && key->rsa != NULL) { | 385 | if (key->type == KEY_RSA1 && key->rsa != NULL) { |
302 | /* size of modulus 'n' */ | 386 | /* size of modulus 'n' */ |
303 | bits = BN_num_bits(key->rsa->n); | 387 | bits = BN_num_bits(key->rsa->n); |
304 | fprintf(f, "%u", bits); | 388 | fprintf(f, "%u", bits); |
@@ -308,14 +392,15 @@ key_write(Key *key, FILE *f) | |||
308 | } else { | 392 | } else { |
309 | error("key_write: failed for RSA key"); | 393 | error("key_write: failed for RSA key"); |
310 | } | 394 | } |
311 | } else if (key->type == KEY_DSA && key->dsa != NULL) { | 395 | } else if ((key->type == KEY_DSA && key->dsa != NULL) || |
396 | (key->type == KEY_RSA && key->rsa != NULL)) { | ||
312 | int len, n; | 397 | int len, n; |
313 | unsigned char *blob, *uu; | 398 | unsigned char *blob, *uu; |
314 | dsa_make_key_blob(key, &blob, &len); | 399 | key_to_blob(key, &blob, &len); |
315 | uu = xmalloc(2*len); | 400 | uu = xmalloc(2*len); |
316 | n = uuencode(blob, len, uu, 2*len); | 401 | n = uuencode(blob, len, uu, 2*len); |
317 | if (n > 0) { | 402 | if (n > 0) { |
318 | fprintf(f, "%s %s", SSH_DSS, uu); | 403 | fprintf(f, "%s %s", key_ssh_name(key), uu); |
319 | success = 1; | 404 | success = 1; |
320 | } | 405 | } |
321 | xfree(blob); | 406 | xfree(blob); |
@@ -327,6 +412,9 @@ char * | |||
327 | key_type(Key *k) | 412 | key_type(Key *k) |
328 | { | 413 | { |
329 | switch (k->type) { | 414 | switch (k->type) { |
415 | case KEY_RSA1: | ||
416 | return "RSA1"; | ||
417 | break; | ||
330 | case KEY_RSA: | 418 | case KEY_RSA: |
331 | return "RSA"; | 419 | return "RSA"; |
332 | break; | 420 | break; |
@@ -336,9 +424,23 @@ key_type(Key *k) | |||
336 | } | 424 | } |
337 | return "unknown"; | 425 | return "unknown"; |
338 | } | 426 | } |
339 | unsigned int | 427 | char * |
428 | key_ssh_name(Key *k) | ||
429 | { | ||
430 | switch (k->type) { | ||
431 | case KEY_RSA: | ||
432 | return "ssh-rsa"; | ||
433 | break; | ||
434 | case KEY_DSA: | ||
435 | return "ssh-dss"; | ||
436 | break; | ||
437 | } | ||
438 | return "ssh-unknown"; | ||
439 | } | ||
440 | u_int | ||
340 | key_size(Key *k){ | 441 | key_size(Key *k){ |
341 | switch (k->type) { | 442 | switch (k->type) { |
443 | case KEY_RSA1: | ||
342 | case KEY_RSA: | 444 | case KEY_RSA: |
343 | return BN_num_bits(k->rsa->n); | 445 | return BN_num_bits(k->rsa->n); |
344 | break; | 446 | break; |
@@ -348,3 +450,219 @@ key_size(Key *k){ | |||
348 | } | 450 | } |
349 | return 0; | 451 | return 0; |
350 | } | 452 | } |
453 | |||
454 | RSA * | ||
455 | rsa_generate_private_key(unsigned int bits) | ||
456 | { | ||
457 | RSA *private; | ||
458 | private = RSA_generate_key(bits, 35, NULL, NULL); | ||
459 | if (private == NULL) | ||
460 | fatal("rsa_generate_private_key: key generation failed."); | ||
461 | return private; | ||
462 | } | ||
463 | |||
464 | DSA* | ||
465 | dsa_generate_private_key(unsigned int bits) | ||
466 | { | ||
467 | DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL); | ||
468 | if (private == NULL) | ||
469 | fatal("dsa_generate_private_key: DSA_generate_parameters failed"); | ||
470 | if (!DSA_generate_key(private)) | ||
471 | fatal("dsa_generate_private_key: DSA_generate_key failed."); | ||
472 | if (private == NULL) | ||
473 | fatal("dsa_generate_private_key: NULL."); | ||
474 | return private; | ||
475 | } | ||
476 | |||
477 | Key * | ||
478 | key_generate(int type, unsigned int bits) | ||
479 | { | ||
480 | Key *k = key_new(KEY_UNSPEC); | ||
481 | switch (type) { | ||
482 | case KEY_DSA: | ||
483 | k->dsa = dsa_generate_private_key(bits); | ||
484 | break; | ||
485 | case KEY_RSA: | ||
486 | case KEY_RSA1: | ||
487 | k->rsa = rsa_generate_private_key(bits); | ||
488 | break; | ||
489 | default: | ||
490 | fatal("key_generate: unknown type %d", type); | ||
491 | } | ||
492 | k->type = type; | ||
493 | return k; | ||
494 | } | ||
495 | |||
496 | Key * | ||
497 | key_from_private(Key *k) | ||
498 | { | ||
499 | Key *n = NULL; | ||
500 | switch (k->type) { | ||
501 | case KEY_DSA: | ||
502 | n = key_new(k->type); | ||
503 | BN_copy(n->dsa->p, k->dsa->p); | ||
504 | BN_copy(n->dsa->q, k->dsa->q); | ||
505 | BN_copy(n->dsa->g, k->dsa->g); | ||
506 | BN_copy(n->dsa->pub_key, k->dsa->pub_key); | ||
507 | break; | ||
508 | case KEY_RSA: | ||
509 | case KEY_RSA1: | ||
510 | n = key_new(k->type); | ||
511 | BN_copy(n->rsa->n, k->rsa->n); | ||
512 | BN_copy(n->rsa->e, k->rsa->e); | ||
513 | break; | ||
514 | default: | ||
515 | fatal("key_from_private: unknown type %d", k->type); | ||
516 | break; | ||
517 | } | ||
518 | return n; | ||
519 | } | ||
520 | |||
521 | int | ||
522 | key_type_from_name(char *name) | ||
523 | { | ||
524 | if (strcmp(name, "rsa1") == 0){ | ||
525 | return KEY_RSA1; | ||
526 | } else if (strcmp(name, "rsa") == 0){ | ||
527 | return KEY_RSA; | ||
528 | } else if (strcmp(name, "dsa") == 0){ | ||
529 | return KEY_DSA; | ||
530 | } else if (strcmp(name, "ssh-rsa") == 0){ | ||
531 | return KEY_RSA; | ||
532 | } else if (strcmp(name, "ssh-dss") == 0){ | ||
533 | return KEY_DSA; | ||
534 | } | ||
535 | debug("key_type_from_name: unknown key type '%s'", name); | ||
536 | return KEY_UNSPEC; | ||
537 | } | ||
538 | |||
539 | Key * | ||
540 | key_from_blob(char *blob, int blen) | ||
541 | { | ||
542 | Buffer b; | ||
543 | char *ktype; | ||
544 | int rlen, type; | ||
545 | Key *key = NULL; | ||
546 | |||
547 | #ifdef DEBUG_PK | ||
548 | dump_base64(stderr, blob, blen); | ||
549 | #endif | ||
550 | buffer_init(&b); | ||
551 | buffer_append(&b, blob, blen); | ||
552 | ktype = buffer_get_string(&b, NULL); | ||
553 | type = key_type_from_name(ktype); | ||
554 | |||
555 | switch(type){ | ||
556 | case KEY_RSA: | ||
557 | key = key_new(type); | ||
558 | buffer_get_bignum2(&b, key->rsa->n); | ||
559 | buffer_get_bignum2(&b, key->rsa->e); | ||
560 | #ifdef DEBUG_PK | ||
561 | RSA_print_fp(stderr, key->rsa, 8); | ||
562 | #endif | ||
563 | break; | ||
564 | case KEY_DSA: | ||
565 | key = key_new(type); | ||
566 | buffer_get_bignum2(&b, key->dsa->p); | ||
567 | buffer_get_bignum2(&b, key->dsa->q); | ||
568 | buffer_get_bignum2(&b, key->dsa->g); | ||
569 | buffer_get_bignum2(&b, key->dsa->pub_key); | ||
570 | #ifdef DEBUG_PK | ||
571 | DSA_print_fp(stderr, key->dsa, 8); | ||
572 | #endif | ||
573 | break; | ||
574 | case KEY_UNSPEC: | ||
575 | key = key_new(type); | ||
576 | break; | ||
577 | default: | ||
578 | error("key_from_blob: cannot handle type %s", ktype); | ||
579 | break; | ||
580 | } | ||
581 | rlen = buffer_len(&b); | ||
582 | if (key != NULL && rlen != 0) | ||
583 | error("key_from_blob: remaining bytes in key blob %d", rlen); | ||
584 | xfree(ktype); | ||
585 | buffer_free(&b); | ||
586 | return key; | ||
587 | } | ||
588 | |||
589 | int | ||
590 | key_to_blob(Key *key, unsigned char **blobp, unsigned int *lenp) | ||
591 | { | ||
592 | Buffer b; | ||
593 | int len; | ||
594 | unsigned char *buf; | ||
595 | |||
596 | if (key == NULL) { | ||
597 | error("key_to_blob: key == NULL"); | ||
598 | return 0; | ||
599 | } | ||
600 | buffer_init(&b); | ||
601 | switch(key->type){ | ||
602 | case KEY_DSA: | ||
603 | buffer_put_cstring(&b, key_ssh_name(key)); | ||
604 | buffer_put_bignum2(&b, key->dsa->p); | ||
605 | buffer_put_bignum2(&b, key->dsa->q); | ||
606 | buffer_put_bignum2(&b, key->dsa->g); | ||
607 | buffer_put_bignum2(&b, key->dsa->pub_key); | ||
608 | break; | ||
609 | case KEY_RSA: | ||
610 | buffer_put_cstring(&b, key_ssh_name(key)); | ||
611 | buffer_put_bignum2(&b, key->rsa->n); | ||
612 | buffer_put_bignum2(&b, key->rsa->e); | ||
613 | break; | ||
614 | default: | ||
615 | error("key_to_blob: illegal key type %d", key->type); | ||
616 | break; | ||
617 | } | ||
618 | len = buffer_len(&b); | ||
619 | buf = xmalloc(len); | ||
620 | memcpy(buf, buffer_ptr(&b), len); | ||
621 | memset(buffer_ptr(&b), 0, len); | ||
622 | buffer_free(&b); | ||
623 | if (lenp != NULL) | ||
624 | *lenp = len; | ||
625 | if (blobp != NULL) | ||
626 | *blobp = buf; | ||
627 | return len; | ||
628 | } | ||
629 | |||
630 | int | ||
631 | key_sign( | ||
632 | Key *key, | ||
633 | unsigned char **sigp, int *lenp, | ||
634 | unsigned char *data, int datalen) | ||
635 | { | ||
636 | switch(key->type){ | ||
637 | case KEY_DSA: | ||
638 | return ssh_dss_sign(key, sigp, lenp, data, datalen); | ||
639 | break; | ||
640 | case KEY_RSA: | ||
641 | return ssh_rsa_sign(key, sigp, lenp, data, datalen); | ||
642 | break; | ||
643 | default: | ||
644 | error("key_sign: illegal key type %d", key->type); | ||
645 | return -1; | ||
646 | break; | ||
647 | } | ||
648 | } | ||
649 | |||
650 | int | ||
651 | key_verify( | ||
652 | Key *key, | ||
653 | unsigned char *signature, int signaturelen, | ||
654 | unsigned char *data, int datalen) | ||
655 | { | ||
656 | switch(key->type){ | ||
657 | case KEY_DSA: | ||
658 | return ssh_dss_verify(key, signature, signaturelen, data, datalen); | ||
659 | break; | ||
660 | case KEY_RSA: | ||
661 | return ssh_rsa_verify(key, signature, signaturelen, data, datalen); | ||
662 | break; | ||
663 | default: | ||
664 | error("key_verify: illegal key type %d", key->type); | ||
665 | return -1; | ||
666 | break; | ||
667 | } | ||
668 | } | ||
@@ -26,9 +26,10 @@ | |||
26 | 26 | ||
27 | typedef struct Key Key; | 27 | typedef struct Key Key; |
28 | enum types { | 28 | enum types { |
29 | KEY_RSA1, | ||
29 | KEY_RSA, | 30 | KEY_RSA, |
30 | KEY_DSA, | 31 | KEY_DSA, |
31 | KEY_EMPTY | 32 | KEY_UNSPEC |
32 | }; | 33 | }; |
33 | struct Key { | 34 | struct Key { |
34 | int type; | 35 | int type; |
@@ -37,12 +38,33 @@ struct Key { | |||
37 | }; | 38 | }; |
38 | 39 | ||
39 | Key *key_new(int type); | 40 | Key *key_new(int type); |
41 | Key *key_new_private(int type); | ||
40 | void key_free(Key *k); | 42 | void key_free(Key *k); |
41 | int key_equal(Key *a, Key *b); | 43 | int key_equal(Key *a, Key *b); |
42 | char *key_fingerprint(Key *k); | 44 | char *key_fingerprint(Key *k); |
43 | char *key_type(Key *k); | 45 | char *key_type(Key *k); |
44 | int key_write(Key *key, FILE *f); | 46 | int key_write(Key *key, FILE *f); |
45 | unsigned int key_read(Key *key, char **cpp); | 47 | int key_read(Key *key, char **cpp); |
46 | unsigned int key_size(Key *k); | 48 | u_int key_size(Key *k); |
49 | |||
50 | Key *key_generate(int type, unsigned int bits); | ||
51 | Key *key_from_private(Key *k); | ||
52 | int key_type_from_name(char *name); | ||
53 | |||
54 | Key *key_from_blob(char *blob, int blen); | ||
55 | int key_to_blob(Key *key, unsigned char **blobp, unsigned int *lenp); | ||
56 | char *key_ssh_name(Key *k); | ||
57 | |||
58 | int | ||
59 | key_sign( | ||
60 | Key *key, | ||
61 | unsigned char **sigp, int *lenp, | ||
62 | unsigned char *data, int datalen); | ||
63 | |||
64 | int | ||
65 | key_verify( | ||
66 | Key *key, | ||
67 | unsigned char *signature, int signaturelen, | ||
68 | unsigned char *data, int datalen); | ||
47 | 69 | ||
48 | #endif | 70 | #endif |
diff --git a/myproposal.h b/myproposal.h index 98060dc35..5abb0e5a6 100644 --- a/myproposal.h +++ b/myproposal.h | |||
@@ -22,7 +22,7 @@ | |||
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-group-exchange-sha1,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-rsa,ssh-dss" |
26 | #define KEX_DEFAULT_ENCRYPT \ | 26 | #define KEX_DEFAULT_ENCRYPT \ |
27 | "3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \ | 27 | "3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \ |
28 | "aes128-cbc,aes192-cbc,aes256-cbc," \ | 28 | "aes128-cbc,aes192-cbc,aes256-cbc," \ |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: nchan.c,v 1.19 2000/09/07 20:27:52 deraadt Exp $"); | 26 | RCSID("$OpenBSD: nchan.c,v 1.20 2000/11/06 23:04:56 markus Exp $"); |
27 | 27 | ||
28 | #include "ssh.h" | 28 | #include "ssh.h" |
29 | 29 | ||
@@ -253,6 +253,8 @@ chan_send_oclose1(Channel *c) | |||
253 | static void | 253 | static void |
254 | chan_delete_if_full_closed1(Channel *c) | 254 | chan_delete_if_full_closed1(Channel *c) |
255 | { | 255 | { |
256 | debug3("channel %d: chan_delete_if_full_closed1: istate %d ostate %d", | ||
257 | c->self, c->istate, c->ostate); | ||
256 | if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { | 258 | if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { |
257 | debug("channel %d: full closed", c->self); | 259 | debug("channel %d: full closed", c->self); |
258 | channel_free(c->self); | 260 | channel_free(c->self); |
@@ -403,6 +405,8 @@ chan_send_close2(Channel *c) | |||
403 | static void | 405 | static void |
404 | chan_delete_if_full_closed2(Channel *c) | 406 | chan_delete_if_full_closed2(Channel *c) |
405 | { | 407 | { |
408 | debug3("channel %d: chan_delete_if_full_closed2: istate %d ostate %d", | ||
409 | c->self, c->istate, c->ostate); | ||
406 | if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { | 410 | if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { |
407 | if (!(c->flags & CHAN_CLOSE_SENT)) { | 411 | if (!(c->flags & CHAN_CLOSE_SENT)) { |
408 | chan_send_close2(c); | 412 | chan_send_close2(c); |
diff --git a/readconf.c b/readconf.c index c6fdd5308..c821d8408 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -12,7 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include "includes.h" | 14 | #include "includes.h" |
15 | RCSID("$OpenBSD: readconf.c,v 1.49 2000/10/11 20:27:23 markus Exp $"); | 15 | RCSID("$OpenBSD: readconf.c,v 1.50 2000/11/12 19:50:37 markus Exp $"); |
16 | 16 | ||
17 | #include "ssh.h" | 17 | #include "ssh.h" |
18 | #include "readconf.h" | 18 | #include "readconf.h" |
@@ -68,7 +68,7 @@ RCSID("$OpenBSD: readconf.c,v 1.49 2000/10/11 20:27:23 markus Exp $"); | |||
68 | # Defaults for various options | 68 | # Defaults for various options |
69 | Host * | 69 | Host * |
70 | ForwardAgent no | 70 | ForwardAgent no |
71 | ForwardX11 yes | 71 | ForwardX11 no |
72 | RhostsAuthentication yes | 72 | RhostsAuthentication yes |
73 | PasswordAuthentication yes | 73 | PasswordAuthentication yes |
74 | RSAAuthentication yes | 74 | RSAAuthentication yes |
@@ -101,8 +101,8 @@ typedef enum { | |||
101 | oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, | 101 | oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, |
102 | oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, | 102 | oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, |
103 | oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication, | 103 | oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication, |
104 | oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2, | 104 | oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, |
105 | oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication, | 105 | oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, |
106 | oKbdInteractiveAuthentication, oKbdInteractiveDevices | 106 | oKbdInteractiveAuthentication, oKbdInteractiveDevices |
107 | } OpCodes; | 107 | } OpCodes; |
108 | 108 | ||
@@ -122,7 +122,8 @@ static struct { | |||
122 | { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, | 122 | { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, |
123 | { "kbdinteractivedevices", oKbdInteractiveDevices }, | 123 | { "kbdinteractivedevices", oKbdInteractiveDevices }, |
124 | { "rsaauthentication", oRSAAuthentication }, | 124 | { "rsaauthentication", oRSAAuthentication }, |
125 | { "dsaauthentication", oDSAAuthentication }, | 125 | { "pubkeyauthentication", oPubkeyAuthentication }, |
126 | { "dsaauthentication", oPubkeyAuthentication }, /* alias */ | ||
126 | { "skeyauthentication", oSkeyAuthentication }, | 127 | { "skeyauthentication", oSkeyAuthentication }, |
127 | #ifdef KRB4 | 128 | #ifdef KRB4 |
128 | { "kerberosauthentication", oKerberosAuthentication }, | 129 | { "kerberosauthentication", oKerberosAuthentication }, |
@@ -134,7 +135,7 @@ static struct { | |||
134 | { "fallbacktorsh", oFallBackToRsh }, | 135 | { "fallbacktorsh", oFallBackToRsh }, |
135 | { "usersh", oUseRsh }, | 136 | { "usersh", oUseRsh }, |
136 | { "identityfile", oIdentityFile }, | 137 | { "identityfile", oIdentityFile }, |
137 | { "identityfile2", oIdentityFile2 }, | 138 | { "identityfile2", oIdentityFile }, /* alias */ |
138 | { "hostname", oHostName }, | 139 | { "hostname", oHostName }, |
139 | { "proxycommand", oProxyCommand }, | 140 | { "proxycommand", oProxyCommand }, |
140 | { "port", oPort }, | 141 | { "port", oPort }, |
@@ -300,8 +301,8 @@ parse_flag: | |||
300 | charptr = &options->kbd_interactive_devices; | 301 | charptr = &options->kbd_interactive_devices; |
301 | goto parse_string; | 302 | goto parse_string; |
302 | 303 | ||
303 | case oDSAAuthentication: | 304 | case oPubkeyAuthentication: |
304 | intptr = &options->dsa_authentication; | 305 | intptr = &options->pubkey_authentication; |
305 | goto parse_flag; | 306 | goto parse_flag; |
306 | 307 | ||
307 | case oRSAAuthentication: | 308 | case oRSAAuthentication: |
@@ -386,20 +387,15 @@ parse_flag: | |||
386 | goto parse_int; | 387 | goto parse_int; |
387 | 388 | ||
388 | case oIdentityFile: | 389 | case oIdentityFile: |
389 | case oIdentityFile2: | ||
390 | arg = strdelim(&s); | 390 | arg = strdelim(&s); |
391 | if (!arg || *arg == '\0') | 391 | if (!arg || *arg == '\0') |
392 | fatal("%.200s line %d: Missing argument.", filename, linenum); | 392 | fatal("%.200s line %d: Missing argument.", filename, linenum); |
393 | if (*activep) { | 393 | if (*activep) { |
394 | intptr = (opcode == oIdentityFile) ? | 394 | intptr = &options->num_identity_files; |
395 | &options->num_identity_files : | ||
396 | &options->num_identity_files2; | ||
397 | if (*intptr >= SSH_MAX_IDENTITY_FILES) | 395 | if (*intptr >= SSH_MAX_IDENTITY_FILES) |
398 | fatal("%.200s line %d: Too many identity files specified (max %d).", | 396 | fatal("%.200s line %d: Too many identity files specified (max %d).", |
399 | filename, linenum, SSH_MAX_IDENTITY_FILES); | 397 | filename, linenum, SSH_MAX_IDENTITY_FILES); |
400 | charptr = (opcode == oIdentityFile) ? | 398 | charptr = &options->identity_files[*intptr]; |
401 | &options->identity_files[*intptr] : | ||
402 | &options->identity_files2[*intptr]; | ||
403 | *charptr = xstrdup(arg); | 399 | *charptr = xstrdup(arg); |
404 | *intptr = *intptr + 1; | 400 | *intptr = *intptr + 1; |
405 | } | 401 | } |
@@ -664,7 +660,7 @@ initialize_options(Options * options) | |||
664 | options->use_privileged_port = -1; | 660 | options->use_privileged_port = -1; |
665 | options->rhosts_authentication = -1; | 661 | options->rhosts_authentication = -1; |
666 | options->rsa_authentication = -1; | 662 | options->rsa_authentication = -1; |
667 | options->dsa_authentication = -1; | 663 | options->pubkey_authentication = -1; |
668 | options->skey_authentication = -1; | 664 | options->skey_authentication = -1; |
669 | #ifdef KRB4 | 665 | #ifdef KRB4 |
670 | options->kerberos_authentication = -1; | 666 | options->kerberos_authentication = -1; |
@@ -692,7 +688,6 @@ initialize_options(Options * options) | |||
692 | options->ciphers = NULL; | 688 | options->ciphers = NULL; |
693 | options->protocol = SSH_PROTO_UNKNOWN; | 689 | options->protocol = SSH_PROTO_UNKNOWN; |
694 | options->num_identity_files = 0; | 690 | options->num_identity_files = 0; |
695 | options->num_identity_files2 = 0; | ||
696 | options->hostname = NULL; | 691 | options->hostname = NULL; |
697 | options->proxy_command = NULL; | 692 | options->proxy_command = NULL; |
698 | options->user = NULL; | 693 | options->user = NULL; |
@@ -730,8 +725,8 @@ fill_default_options(Options * options) | |||
730 | options->rhosts_authentication = 1; | 725 | options->rhosts_authentication = 1; |
731 | if (options->rsa_authentication == -1) | 726 | if (options->rsa_authentication == -1) |
732 | options->rsa_authentication = 1; | 727 | options->rsa_authentication = 1; |
733 | if (options->dsa_authentication == -1) | 728 | if (options->pubkey_authentication == -1) |
734 | options->dsa_authentication = 1; | 729 | options->pubkey_authentication = 1; |
735 | if (options->skey_authentication == -1) | 730 | if (options->skey_authentication == -1) |
736 | options->skey_authentication = 0; | 731 | options->skey_authentication = 0; |
737 | #ifdef KRB4 | 732 | #ifdef KRB4 |
@@ -779,16 +774,18 @@ fill_default_options(Options * options) | |||
779 | if (options->protocol == SSH_PROTO_UNKNOWN) | 774 | if (options->protocol == SSH_PROTO_UNKNOWN) |
780 | options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED; | 775 | options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED; |
781 | if (options->num_identity_files == 0) { | 776 | if (options->num_identity_files == 0) { |
782 | options->identity_files[0] = | 777 | if (options->protocol & SSH_PROTO_1) { |
783 | xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1); | 778 | options->identity_files[options->num_identity_files] = |
784 | sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY); | 779 | xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1); |
785 | options->num_identity_files = 1; | 780 | sprintf(options->identity_files[options->num_identity_files++], |
786 | } | 781 | "~/%.100s", SSH_CLIENT_IDENTITY); |
787 | if (options->num_identity_files2 == 0) { | 782 | } |
788 | options->identity_files2[0] = | 783 | if (options->protocol & SSH_PROTO_2) { |
789 | xmalloc(2 + strlen(SSH_CLIENT_ID_DSA) + 1); | 784 | options->identity_files[options->num_identity_files] = |
790 | sprintf(options->identity_files2[0], "~/%.100s", SSH_CLIENT_ID_DSA); | 785 | xmalloc(2 + strlen(SSH_CLIENT_ID_DSA) + 1); |
791 | options->num_identity_files2 = 1; | 786 | sprintf(options->identity_files[options->num_identity_files++], |
787 | "~/%.100s", SSH_CLIENT_ID_DSA); | ||
788 | } | ||
792 | } | 789 | } |
793 | if (options->escape_char == -1) | 790 | if (options->escape_char == -1) |
794 | options->escape_char = '~'; | 791 | options->escape_char = '~'; |
diff --git a/readconf.h b/readconf.h index e94213fa1..85d937d87 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.22 2000/10/11 20:14:39 markus Exp $"); */ | 14 | /* RCSID("$OpenBSD: readconf.h,v 1.23 2000/11/12 19:50:37 markus Exp $"); */ |
15 | 15 | ||
16 | #ifndef READCONF_H | 16 | #ifndef READCONF_H |
17 | #define READCONF_H | 17 | #define READCONF_H |
@@ -35,7 +35,7 @@ typedef struct { | |||
35 | int rhosts_rsa_authentication; /* Try rhosts with RSA | 35 | int rhosts_rsa_authentication; /* Try rhosts with RSA |
36 | * authentication. */ | 36 | * authentication. */ |
37 | int rsa_authentication; /* Try RSA authentication. */ | 37 | int rsa_authentication; /* Try RSA authentication. */ |
38 | int dsa_authentication; /* Try DSA authentication. */ | 38 | int pubkey_authentication; /* Try ssh2 pubkey authentication. */ |
39 | int skey_authentication; /* Try S/Key or TIS authentication. */ | 39 | int skey_authentication; /* Try S/Key or TIS authentication. */ |
40 | #ifdef KRB4 | 40 | #ifdef KRB4 |
41 | int kerberos_authentication; /* Try Kerberos | 41 | int kerberos_authentication; /* Try Kerberos |
@@ -78,10 +78,9 @@ typedef struct { | |||
78 | char *system_hostfile2; | 78 | char *system_hostfile2; |
79 | char *user_hostfile2; | 79 | char *user_hostfile2; |
80 | 80 | ||
81 | int num_identity_files; /* Number of files for RSA identities. */ | 81 | int num_identity_files; /* Number of files for RSA/DSA identities. */ |
82 | int num_identity_files2; /* DSA identities. */ | ||
83 | char *identity_files[SSH_MAX_IDENTITY_FILES]; | 82 | char *identity_files[SSH_MAX_IDENTITY_FILES]; |
84 | char *identity_files2[SSH_MAX_IDENTITY_FILES]; | 83 | int identity_files_type[SSH_MAX_IDENTITY_FILES]; |
85 | 84 | ||
86 | /* Local TCP/IP forward requests. */ | 85 | /* Local TCP/IP forward requests. */ |
87 | int num_local_forwards; | 86 | int num_local_forwards; |
@@ -60,82 +60,13 @@ | |||
60 | */ | 60 | */ |
61 | 61 | ||
62 | #include "includes.h" | 62 | #include "includes.h" |
63 | RCSID("$OpenBSD: rsa.c,v 1.16 2000/09/07 20:27:53 deraadt Exp $"); | 63 | RCSID("$OpenBSD: rsa.c,v 1.17 2000/11/12 19:50:37 markus Exp $"); |
64 | 64 | ||
65 | #include "rsa.h" | 65 | #include "rsa.h" |
66 | #include "ssh.h" | 66 | #include "ssh.h" |
67 | #include "xmalloc.h" | 67 | #include "xmalloc.h" |
68 | #include "entropy.h" | 68 | #include "entropy.h" |
69 | 69 | ||
70 | int rsa_verbose = 1; | ||
71 | |||
72 | int | ||
73 | rsa_alive() | ||
74 | { | ||
75 | RSA *key; | ||
76 | |||
77 | seed_rng(); | ||
78 | key = RSA_generate_key(32, 3, NULL, NULL); | ||
79 | if (key == NULL) | ||
80 | return (0); | ||
81 | RSA_free(key); | ||
82 | return (1); | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * Generates RSA public and private keys. This initializes the data | ||
87 | * structures; they should be freed with rsa_clear_private_key and | ||
88 | * rsa_clear_public_key. | ||
89 | */ | ||
90 | |||
91 | void | ||
92 | rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits) | ||
93 | { | ||
94 | RSA *key; | ||
95 | |||
96 | seed_rng(); | ||
97 | |||
98 | if (rsa_verbose) { | ||
99 | printf("Generating RSA keys: "); | ||
100 | fflush(stdout); | ||
101 | } | ||
102 | key = RSA_generate_key(bits, 35, NULL, NULL); | ||
103 | if (key == NULL) | ||
104 | fatal("rsa_generate_key: key generation failed."); | ||
105 | |||
106 | /* Copy public key parameters */ | ||
107 | pub->n = BN_new(); | ||
108 | BN_copy(pub->n, key->n); | ||
109 | pub->e = BN_new(); | ||
110 | BN_copy(pub->e, key->e); | ||
111 | |||
112 | /* Copy private key parameters */ | ||
113 | prv->n = BN_new(); | ||
114 | BN_copy(prv->n, key->n); | ||
115 | prv->e = BN_new(); | ||
116 | BN_copy(prv->e, key->e); | ||
117 | prv->d = BN_new(); | ||
118 | BN_copy(prv->d, key->d); | ||
119 | prv->p = BN_new(); | ||
120 | BN_copy(prv->p, key->p); | ||
121 | prv->q = BN_new(); | ||
122 | BN_copy(prv->q, key->q); | ||
123 | |||
124 | prv->dmp1 = BN_new(); | ||
125 | BN_copy(prv->dmp1, key->dmp1); | ||
126 | |||
127 | prv->dmq1 = BN_new(); | ||
128 | BN_copy(prv->dmq1, key->dmq1); | ||
129 | |||
130 | prv->iqmp = BN_new(); | ||
131 | BN_copy(prv->iqmp, key->iqmp); | ||
132 | |||
133 | RSA_free(key); | ||
134 | |||
135 | if (rsa_verbose) | ||
136 | printf("Key generation complete.\n"); | ||
137 | } | ||
138 | |||
139 | void | 70 | void |
140 | rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) | 71 | rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) |
141 | { | 72 | { |
@@ -188,11 +119,3 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) | |||
188 | xfree(outbuf); | 119 | xfree(outbuf); |
189 | xfree(inbuf); | 120 | xfree(inbuf); |
190 | } | 121 | } |
191 | |||
192 | /* Set whether to output verbose messages during key generation. */ | ||
193 | |||
194 | void | ||
195 | rsa_set_verbose(int verbose) | ||
196 | { | ||
197 | rsa_verbose = verbose; | ||
198 | } | ||
@@ -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: rsa.h,v 1.8 2000/09/07 20:27:53 deraadt Exp $"); */ | 14 | /* RCSID("$OpenBSD: rsa.h,v 1.9 2000/11/12 19:50:38 markus Exp $"); */ |
15 | 15 | ||
16 | #ifndef RSA_H | 16 | #ifndef RSA_H |
17 | #define RSA_H | 17 | #define RSA_H |
@@ -19,17 +19,6 @@ | |||
19 | #include <openssl/bn.h> | 19 | #include <openssl/bn.h> |
20 | #include <openssl/rsa.h> | 20 | #include <openssl/rsa.h> |
21 | 21 | ||
22 | /* Calls SSL RSA_generate_key, only copies to prv and pub */ | ||
23 | void rsa_generate_key(RSA * prv, RSA * pub, unsigned int bits); | ||
24 | |||
25 | /* | ||
26 | * Indicates whether the rsa module is permitted to show messages on the | ||
27 | * terminal. | ||
28 | */ | ||
29 | void rsa_set_verbose __P((int verbose)); | ||
30 | |||
31 | int rsa_alive __P((void)); | ||
32 | |||
33 | void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv)); | 22 | void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv)); |
34 | void rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv)); | 23 | void rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv)); |
35 | 24 | ||
diff --git a/servconf.c b/servconf.c index 76702a836..5da55de03 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.53 2000/10/14 12:12:09 markus Exp $"); | 13 | RCSID("$OpenBSD: servconf.c,v 1.54 2000/11/12 19:50:38 markus Exp $"); |
14 | 14 | ||
15 | #include "ssh.h" | 15 | #include "ssh.h" |
16 | #include "servconf.h" | 16 | #include "servconf.h" |
@@ -29,8 +29,7 @@ initialize_server_options(ServerOptions *options) | |||
29 | options->num_ports = 0; | 29 | options->num_ports = 0; |
30 | options->ports_from_cmdline = 0; | 30 | options->ports_from_cmdline = 0; |
31 | options->listen_addrs = NULL; | 31 | options->listen_addrs = NULL; |
32 | options->host_key_file = NULL; | 32 | options->num_host_key_files = 0; |
33 | options->host_dsa_key_file = NULL; | ||
34 | options->pid_file = NULL; | 33 | options->pid_file = NULL; |
35 | options->server_key_bits = -1; | 34 | options->server_key_bits = -1; |
36 | options->login_grace_time = -1; | 35 | options->login_grace_time = -1; |
@@ -50,7 +49,7 @@ initialize_server_options(ServerOptions *options) | |||
50 | options->rhosts_authentication = -1; | 49 | options->rhosts_authentication = -1; |
51 | options->rhosts_rsa_authentication = -1; | 50 | options->rhosts_rsa_authentication = -1; |
52 | options->rsa_authentication = -1; | 51 | options->rsa_authentication = -1; |
53 | options->dsa_authentication = -1; | 52 | options->pubkey_authentication = -1; |
54 | #ifdef KRB4 | 53 | #ifdef KRB4 |
55 | options->kerberos_authentication = -1; | 54 | options->kerberos_authentication = -1; |
56 | options->kerberos_or_local_passwd = -1; | 55 | options->kerberos_or_local_passwd = -1; |
@@ -84,14 +83,19 @@ initialize_server_options(ServerOptions *options) | |||
84 | void | 83 | void |
85 | fill_default_server_options(ServerOptions *options) | 84 | fill_default_server_options(ServerOptions *options) |
86 | { | 85 | { |
86 | if (options->protocol == SSH_PROTO_UNKNOWN) | ||
87 | options->protocol = SSH_PROTO_1|SSH_PROTO_2; | ||
88 | if (options->num_host_key_files == 0) { | ||
89 | /* fill default hostkeys for protocols */ | ||
90 | if (options->protocol & SSH_PROTO_1) | ||
91 | options->host_key_files[options->num_host_key_files++] = HOST_KEY_FILE; | ||
92 | if (options->protocol & SSH_PROTO_2) | ||
93 | options->host_key_files[options->num_host_key_files++] = HOST_DSA_KEY_FILE; | ||
94 | } | ||
87 | if (options->num_ports == 0) | 95 | if (options->num_ports == 0) |
88 | options->ports[options->num_ports++] = SSH_DEFAULT_PORT; | 96 | options->ports[options->num_ports++] = SSH_DEFAULT_PORT; |
89 | if (options->listen_addrs == NULL) | 97 | if (options->listen_addrs == NULL) |
90 | add_listen_addr(options, NULL); | 98 | add_listen_addr(options, NULL); |
91 | if (options->host_key_file == NULL) | ||
92 | options->host_key_file = HOST_KEY_FILE; | ||
93 | if (options->host_dsa_key_file == NULL) | ||
94 | options->host_dsa_key_file = HOST_DSA_KEY_FILE; | ||
95 | if (options->pid_file == NULL) | 99 | if (options->pid_file == NULL) |
96 | options->pid_file = SSH_DAEMON_PID_FILE; | 100 | options->pid_file = SSH_DAEMON_PID_FILE; |
97 | if (options->server_key_bits == -1) | 101 | if (options->server_key_bits == -1) |
@@ -132,8 +136,8 @@ fill_default_server_options(ServerOptions *options) | |||
132 | options->rhosts_rsa_authentication = 0; | 136 | options->rhosts_rsa_authentication = 0; |
133 | if (options->rsa_authentication == -1) | 137 | if (options->rsa_authentication == -1) |
134 | options->rsa_authentication = 1; | 138 | options->rsa_authentication = 1; |
135 | if (options->dsa_authentication == -1) | 139 | if (options->pubkey_authentication == -1) |
136 | options->dsa_authentication = 1; | 140 | options->pubkey_authentication = 1; |
137 | #ifdef KRB4 | 141 | #ifdef KRB4 |
138 | if (options->kerberos_authentication == -1) | 142 | if (options->kerberos_authentication == -1) |
139 | options->kerberos_authentication = (access(KEYFILE, R_OK) == 0); | 143 | options->kerberos_authentication = (access(KEYFILE, R_OK) == 0); |
@@ -162,8 +166,6 @@ fill_default_server_options(ServerOptions *options) | |||
162 | options->use_login = 0; | 166 | options->use_login = 0; |
163 | if (options->allow_tcp_forwarding == -1) | 167 | if (options->allow_tcp_forwarding == -1) |
164 | options->allow_tcp_forwarding = 1; | 168 | options->allow_tcp_forwarding = 1; |
165 | if (options->protocol == SSH_PROTO_UNKNOWN) | ||
166 | options->protocol = SSH_PROTO_1|SSH_PROTO_2; | ||
167 | if (options->gateway_ports == -1) | 169 | if (options->gateway_ports == -1) |
168 | options->gateway_ports = 0; | 170 | options->gateway_ports = 0; |
169 | if (options->max_startups == -1) | 171 | if (options->max_startups == -1) |
@@ -194,8 +196,8 @@ typedef enum { | |||
194 | sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail, | 196 | sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail, |
195 | sUseLogin, sAllowTcpForwarding, | 197 | sUseLogin, sAllowTcpForwarding, |
196 | sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, | 198 | sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, |
197 | sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile, | 199 | sIgnoreUserKnownHosts, sCiphers, sProtocol, sPidFile, |
198 | sGatewayPorts, sDSAAuthentication, sXAuthLocation, sSubsystem, sMaxStartups | 200 | sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups, |
199 | } ServerOpCodes; | 201 | } ServerOpCodes; |
200 | 202 | ||
201 | /* Textual representation of the tokens. */ | 203 | /* Textual representation of the tokens. */ |
@@ -205,7 +207,7 @@ static struct { | |||
205 | } keywords[] = { | 207 | } keywords[] = { |
206 | { "port", sPort }, | 208 | { "port", sPort }, |
207 | { "hostkey", sHostKeyFile }, | 209 | { "hostkey", sHostKeyFile }, |
208 | { "hostdsakey", sHostDSAKeyFile }, | 210 | { "hostdsakey", sHostKeyFile }, /* alias */ |
209 | { "pidfile", sPidFile }, | 211 | { "pidfile", sPidFile }, |
210 | { "serverkeybits", sServerKeyBits }, | 212 | { "serverkeybits", sServerKeyBits }, |
211 | { "logingracetime", sLoginGraceTime }, | 213 | { "logingracetime", sLoginGraceTime }, |
@@ -216,7 +218,8 @@ static struct { | |||
216 | { "rhostsauthentication", sRhostsAuthentication }, | 218 | { "rhostsauthentication", sRhostsAuthentication }, |
217 | { "rhostsrsaauthentication", sRhostsRSAAuthentication }, | 219 | { "rhostsrsaauthentication", sRhostsRSAAuthentication }, |
218 | { "rsaauthentication", sRSAAuthentication }, | 220 | { "rsaauthentication", sRSAAuthentication }, |
219 | { "dsaauthentication", sDSAAuthentication }, | 221 | { "pubkeyauthentication", sPubkeyAuthentication }, |
222 | { "dsaauthentication", sPubkeyAuthentication }, /* alias */ | ||
220 | #ifdef KRB4 | 223 | #ifdef KRB4 |
221 | { "kerberosauthentication", sKerberosAuthentication }, | 224 | { "kerberosauthentication", sKerberosAuthentication }, |
222 | { "kerberosorlocalpasswd", sKerberosOrLocalPasswd }, | 225 | { "kerberosorlocalpasswd", sKerberosOrLocalPasswd }, |
@@ -336,6 +339,8 @@ read_server_config(ServerOptions *options, const char *filename) | |||
336 | arg = strdelim(&cp); | 339 | arg = strdelim(&cp); |
337 | if (!*arg || *arg == '#') | 340 | if (!*arg || *arg == '#') |
338 | continue; | 341 | continue; |
342 | intptr = NULL; | ||
343 | charptr = NULL; | ||
339 | opcode = parse_token(arg, filename, linenum); | 344 | opcode = parse_token(arg, filename, linenum); |
340 | switch (opcode) { | 345 | switch (opcode) { |
341 | case sBadOption: | 346 | case sBadOption: |
@@ -389,9 +394,13 @@ parse_int: | |||
389 | break; | 394 | break; |
390 | 395 | ||
391 | case sHostKeyFile: | 396 | case sHostKeyFile: |
392 | case sHostDSAKeyFile: | 397 | intptr = &options->num_host_key_files; |
393 | charptr = (opcode == sHostKeyFile ) ? | 398 | if (*intptr >= MAX_HOSTKEYS) { |
394 | &options->host_key_file : &options->host_dsa_key_file; | 399 | fprintf(stderr, "%s line %d: to many host keys specified (max %d).\n", |
400 | filename, linenum, MAX_HOSTKEYS); | ||
401 | exit(1); | ||
402 | } | ||
403 | charptr = &options->host_key_files[*intptr]; | ||
395 | parse_filename: | 404 | parse_filename: |
396 | arg = strdelim(&cp); | 405 | arg = strdelim(&cp); |
397 | if (!arg || *arg == '\0') { | 406 | if (!arg || *arg == '\0') { |
@@ -399,8 +408,12 @@ parse_filename: | |||
399 | filename, linenum); | 408 | filename, linenum); |
400 | exit(1); | 409 | exit(1); |
401 | } | 410 | } |
402 | if (*charptr == NULL) | 411 | if (*charptr == NULL) { |
403 | *charptr = tilde_expand_filename(arg, getuid()); | 412 | *charptr = tilde_expand_filename(arg, getuid()); |
413 | /* increase optional counter */ | ||
414 | if (intptr != NULL) | ||
415 | *intptr = *intptr + 1; | ||
416 | } | ||
404 | break; | 417 | break; |
405 | 418 | ||
406 | case sPidFile: | 419 | case sPidFile: |
@@ -474,8 +487,8 @@ parse_flag: | |||
474 | intptr = &options->rsa_authentication; | 487 | intptr = &options->rsa_authentication; |
475 | goto parse_flag; | 488 | goto parse_flag; |
476 | 489 | ||
477 | case sDSAAuthentication: | 490 | case sPubkeyAuthentication: |
478 | intptr = &options->dsa_authentication; | 491 | intptr = &options->pubkey_authentication; |
479 | goto parse_flag; | 492 | goto parse_flag; |
480 | 493 | ||
481 | #ifdef KRB4 | 494 | #ifdef KRB4 |
diff --git a/servconf.h b/servconf.h index 0188b9b89..3ecf6a00d 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.30 2000/10/14 12:12:09 markus Exp $"); */ | 14 | /* RCSID("$OpenBSD: servconf.h,v 1.31 2000/11/12 19:50:38 markus Exp $"); */ |
15 | 15 | ||
16 | #ifndef SERVCONF_H | 16 | #ifndef SERVCONF_H |
17 | #define SERVCONF_H | 17 | #define SERVCONF_H |
@@ -23,6 +23,7 @@ | |||
23 | #define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */ | 23 | #define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */ |
24 | #define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */ | 24 | #define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */ |
25 | #define MAX_SUBSYSTEMS 256 /* Max # subsystems. */ | 25 | #define MAX_SUBSYSTEMS 256 /* Max # subsystems. */ |
26 | #define MAX_HOSTKEYS 256 /* Max # hostkeys. */ | ||
26 | 27 | ||
27 | typedef struct { | 28 | typedef struct { |
28 | unsigned int num_ports; | 29 | unsigned int num_ports; |
@@ -30,8 +31,8 @@ typedef struct { | |||
30 | u_short ports[MAX_PORTS]; /* Port number to listen on. */ | 31 | u_short ports[MAX_PORTS]; /* Port number to listen on. */ |
31 | char *listen_addr; /* Address on which the server listens. */ | 32 | char *listen_addr; /* Address on which the server listens. */ |
32 | struct addrinfo *listen_addrs; /* Addresses on which the server listens. */ | 33 | struct addrinfo *listen_addrs; /* Addresses on which the server listens. */ |
33 | char *host_key_file; /* File containing host key. */ | 34 | char *host_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */ |
34 | char *host_dsa_key_file; /* File containing dsa host key. */ | 35 | int num_host_key_files; /* Number of files for host keys. */ |
35 | char *pid_file; /* Where to put our pid */ | 36 | char *pid_file; /* Where to put our pid */ |
36 | int server_key_bits;/* Size of the server key. */ | 37 | int server_key_bits;/* Size of the server key. */ |
37 | int login_grace_time; /* Disconnect if no auth in this time | 38 | int login_grace_time; /* Disconnect if no auth in this time |
@@ -59,7 +60,7 @@ typedef struct { | |||
59 | int rhosts_rsa_authentication; /* If true, permit rhosts RSA | 60 | int rhosts_rsa_authentication; /* If true, permit rhosts RSA |
60 | * authentication. */ | 61 | * authentication. */ |
61 | int rsa_authentication; /* If true, permit RSA authentication. */ | 62 | int rsa_authentication; /* If true, permit RSA authentication. */ |
62 | int dsa_authentication; /* If true, permit DSA authentication. */ | 63 | int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */ |
63 | #ifdef KRB4 | 64 | #ifdef KRB4 |
64 | int kerberos_authentication; /* If true, permit Kerberos | 65 | int kerberos_authentication; /* If true, permit Kerberos |
65 | * authentication. */ | 66 | * authentication. */ |
diff --git a/serverloop.c b/serverloop.c index 6a81806bb..dfef6f333 100644 --- a/serverloop.c +++ b/serverloop.c | |||
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | RCSID("$OpenBSD: serverloop.c,v 1.34 2000/10/27 07:32:18 markus Exp $"); | 38 | RCSID("$OpenBSD: serverloop.c,v 1.35 2000/11/06 23:04:56 markus Exp $"); |
39 | 39 | ||
40 | #include "xmalloc.h" | 40 | #include "xmalloc.h" |
41 | #include "ssh.h" | 41 | #include "ssh.h" |
@@ -50,6 +50,7 @@ RCSID("$OpenBSD: serverloop.c,v 1.34 2000/10/27 07:32:18 markus Exp $"); | |||
50 | #include "session.h" | 50 | #include "session.h" |
51 | #include "dispatch.h" | 51 | #include "dispatch.h" |
52 | #include "auth-options.h" | 52 | #include "auth-options.h" |
53 | #include "auth.h" | ||
53 | 54 | ||
54 | extern ServerOptions options; | 55 | extern ServerOptions options; |
55 | 56 | ||
@@ -739,10 +740,10 @@ server_input_window_size(int type, int plen, void *ctxt) | |||
739 | pty_change_window_size(fdin, row, col, xpixel, ypixel); | 740 | pty_change_window_size(fdin, row, col, xpixel, ypixel); |
740 | } | 741 | } |
741 | 742 | ||
742 | int | 743 | Channel * |
743 | input_direct_tcpip(void) | 744 | server_request_direct_tcpip(char *ctype) |
744 | { | 745 | { |
745 | int sock; | 746 | int sock, newch; |
746 | char *target, *originator; | 747 | char *target, *originator; |
747 | int target_port, originator_port; | 748 | int target_port, originator_port; |
748 | 749 | ||
@@ -752,23 +753,52 @@ input_direct_tcpip(void) | |||
752 | originator_port = packet_get_int(); | 753 | originator_port = packet_get_int(); |
753 | packet_done(); | 754 | packet_done(); |
754 | 755 | ||
755 | debug("open direct-tcpip: from %s port %d to %s port %d", | 756 | debug("server_request_direct_tcpip: originator %s port %d, target %s port %d", |
756 | originator, originator_port, target, target_port); | 757 | originator, originator_port, target, target_port); |
757 | 758 | ||
758 | /* XXX check permission */ | 759 | /* XXX check permission */ |
759 | if (no_port_forwarding_flag || !options.allow_tcp_forwarding) { | 760 | if (no_port_forwarding_flag || !options.allow_tcp_forwarding) { |
760 | xfree(target); | 761 | xfree(target); |
761 | xfree(originator); | 762 | xfree(originator); |
762 | return -1; | 763 | return NULL; |
763 | } | 764 | } |
764 | sock = channel_connect_to(target, target_port); | 765 | sock = channel_connect_to(target, target_port); |
765 | xfree(target); | 766 | xfree(target); |
766 | xfree(originator); | 767 | xfree(originator); |
767 | if (sock < 0) | 768 | if (sock < 0) |
768 | return -1; | 769 | return NULL; |
769 | return channel_new("direct-tcpip", SSH_CHANNEL_OPEN, | 770 | newch = channel_new(ctype, SSH_CHANNEL_OPEN, |
770 | sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, | 771 | sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, |
771 | CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1); | 772 | CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1); |
773 | return (newch >= 0) ? channel_lookup(newch) : NULL; | ||
774 | } | ||
775 | |||
776 | Channel * | ||
777 | server_request_session(char *ctype) | ||
778 | { | ||
779 | int newch; | ||
780 | |||
781 | debug("input_session_request"); | ||
782 | packet_done(); | ||
783 | /* | ||
784 | * A server session has no fd to read or write until a | ||
785 | * CHANNEL_REQUEST for a shell is made, so we set the type to | ||
786 | * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all | ||
787 | * CHANNEL_REQUEST messages is registered. | ||
788 | */ | ||
789 | newch = channel_new(ctype, SSH_CHANNEL_LARVAL, | ||
790 | -1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT, | ||
791 | 0, xstrdup("server-session"), 1); | ||
792 | if (session_open(newch) == 1) { | ||
793 | channel_register_callback(newch, SSH2_MSG_CHANNEL_REQUEST, | ||
794 | session_input_channel_req, (void *)0); | ||
795 | channel_register_cleanup(newch, session_close_by_channel); | ||
796 | return channel_lookup(newch); | ||
797 | } else { | ||
798 | debug("session open failed, free channel %d", newch); | ||
799 | channel_free(newch); | ||
800 | } | ||
801 | return NULL; | ||
772 | } | 802 | } |
773 | 803 | ||
774 | void | 804 | void |
@@ -776,7 +806,6 @@ server_input_channel_open(int type, int plen, void *ctxt) | |||
776 | { | 806 | { |
777 | Channel *c = NULL; | 807 | Channel *c = NULL; |
778 | char *ctype; | 808 | char *ctype; |
779 | int id; | ||
780 | unsigned int len; | 809 | unsigned int len; |
781 | int rchan; | 810 | int rchan; |
782 | int rmaxpack; | 811 | int rmaxpack; |
@@ -791,34 +820,12 @@ server_input_channel_open(int type, int plen, void *ctxt) | |||
791 | ctype, rchan, rwindow, rmaxpack); | 820 | ctype, rchan, rwindow, rmaxpack); |
792 | 821 | ||
793 | if (strcmp(ctype, "session") == 0) { | 822 | if (strcmp(ctype, "session") == 0) { |
794 | debug("open session"); | 823 | c = server_request_session(ctype); |
795 | packet_done(); | ||
796 | /* | ||
797 | * A server session has no fd to read or write | ||
798 | * until a CHANNEL_REQUEST for a shell is made, | ||
799 | * so we set the type to SSH_CHANNEL_LARVAL. | ||
800 | * Additionally, a callback for handling all | ||
801 | * CHANNEL_REQUEST messages is registered. | ||
802 | */ | ||
803 | id = channel_new(ctype, SSH_CHANNEL_LARVAL, | ||
804 | -1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT, | ||
805 | 0, xstrdup("server-session"), 1); | ||
806 | if (session_open(id) == 1) { | ||
807 | channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST, | ||
808 | session_input_channel_req, (void *)0); | ||
809 | channel_register_cleanup(id, session_close_by_channel); | ||
810 | c = channel_lookup(id); | ||
811 | } else { | ||
812 | debug("session open failed, free channel %d", id); | ||
813 | channel_free(id); | ||
814 | } | ||
815 | } else if (strcmp(ctype, "direct-tcpip") == 0) { | 824 | } else if (strcmp(ctype, "direct-tcpip") == 0) { |
816 | id = input_direct_tcpip(); | 825 | c = server_request_direct_tcpip(ctype); |
817 | if (id >= 0) | ||
818 | c = channel_lookup(id); | ||
819 | } | 826 | } |
820 | if (c != NULL) { | 827 | if (c != NULL) { |
821 | debug("confirm %s", ctype); | 828 | debug("server_input_channel_open: confirm %s", ctype); |
822 | c->remote_id = rchan; | 829 | c->remote_id = rchan; |
823 | c->remote_window = rwindow; | 830 | c->remote_window = rwindow; |
824 | c->remote_maxpacket = rmaxpack; | 831 | c->remote_maxpacket = rmaxpack; |
@@ -830,7 +837,7 @@ server_input_channel_open(int type, int plen, void *ctxt) | |||
830 | packet_put_int(c->local_maxpacket); | 837 | packet_put_int(c->local_maxpacket); |
831 | packet_send(); | 838 | packet_send(); |
832 | } else { | 839 | } else { |
833 | debug("failure %s", ctype); | 840 | debug("server_input_channel_open: failure %s", ctype); |
834 | packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); | 841 | packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); |
835 | packet_put_int(rchan); | 842 | packet_put_int(rchan); |
836 | packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); | 843 | packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); |
@@ -841,6 +848,56 @@ server_input_channel_open(int type, int plen, void *ctxt) | |||
841 | xfree(ctype); | 848 | xfree(ctype); |
842 | } | 849 | } |
843 | 850 | ||
851 | void | ||
852 | server_input_global_request(int type, int plen, void *ctxt) | ||
853 | { | ||
854 | char *rtype; | ||
855 | int want_reply; | ||
856 | int success = 0; | ||
857 | |||
858 | rtype = packet_get_string(NULL); | ||
859 | want_reply = packet_get_char(); | ||
860 | debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply); | ||
861 | |||
862 | if (strcmp(rtype, "tcpip-forward") == 0) { | ||
863 | struct passwd *pw; | ||
864 | char *listen_address; | ||
865 | u_short listen_port; | ||
866 | |||
867 | pw = auth_get_user(); | ||
868 | if (pw == NULL) | ||
869 | fatal("server_input_global_request: no user"); | ||
870 | listen_address = packet_get_string(NULL); /* XXX currently ignored */ | ||
871 | listen_port = (u_short)packet_get_int(); | ||
872 | debug("server_input_global_request: tcpip-forward listen %s port %d", | ||
873 | listen_address, listen_port); | ||
874 | |||
875 | /* check permissions */ | ||
876 | if (!options.allow_tcp_forwarding || | ||
877 | no_port_forwarding_flag || | ||
878 | (listen_port < IPPORT_RESERVED && pw->pw_uid != 0)) { | ||
879 | success = 0; | ||
880 | packet_send_debug("Server has disabled port forwarding."); | ||
881 | } else { | ||
882 | /* Start listening on the port */ | ||
883 | channel_request_forwarding( | ||
884 | listen_address, listen_port, | ||
885 | /*unspec host_to_connect*/ "<unspec host>", | ||
886 | /*unspec port_to_connect*/ 0, | ||
887 | options.gateway_ports, /*remote*/ 1); | ||
888 | success = 1; | ||
889 | } | ||
890 | xfree(listen_address); | ||
891 | } | ||
892 | if (want_reply) { | ||
893 | packet_start(success ? | ||
894 | SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); | ||
895 | packet_send(); | ||
896 | packet_write_wait(); | ||
897 | } | ||
898 | xfree(rtype); | ||
899 | } | ||
900 | |||
844 | void | 901 | void |
845 | server_init_dispatch_20() | 902 | server_init_dispatch_20() |
846 | { | 903 | { |
@@ -855,6 +912,7 @@ server_init_dispatch_20() | |||
855 | dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); | 912 | dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); |
856 | dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request); | 913 | dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request); |
857 | dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); | 914 | dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); |
915 | dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request); | ||
858 | } | 916 | } |
859 | void | 917 | void |
860 | server_init_dispatch_13() | 918 | server_init_dispatch_13() |
@@ -33,7 +33,7 @@ | |||
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include "includes.h" | 35 | #include "includes.h" |
36 | RCSID("$OpenBSD: session.c,v 1.42 2000/10/27 07:32:18 markus Exp $"); | 36 | RCSID("$OpenBSD: session.c,v 1.43 2000/11/06 23:04:56 markus Exp $"); |
37 | 37 | ||
38 | #include "xmalloc.h" | 38 | #include "xmalloc.h" |
39 | #include "ssh.h" | 39 | #include "ssh.h" |
@@ -1735,6 +1735,19 @@ session_exec_req(Session *s) | |||
1735 | return 1; | 1735 | return 1; |
1736 | } | 1736 | } |
1737 | 1737 | ||
1738 | int | ||
1739 | session_auth_agent_req(Session *s) | ||
1740 | { | ||
1741 | static int called = 0; | ||
1742 | packet_done(); | ||
1743 | if (called) { | ||
1744 | return 0; | ||
1745 | } else { | ||
1746 | called = 1; | ||
1747 | return auth_input_request_forwarding(s->pw); | ||
1748 | } | ||
1749 | } | ||
1750 | |||
1738 | void | 1751 | void |
1739 | session_input_channel_req(int id, void *arg) | 1752 | session_input_channel_req(int id, void *arg) |
1740 | { | 1753 | { |
@@ -1771,6 +1784,8 @@ session_input_channel_req(int id, void *arg) | |||
1771 | success = session_pty_req(s); | 1784 | success = session_pty_req(s); |
1772 | } else if (strcmp(rtype, "x11-req") == 0) { | 1785 | } else if (strcmp(rtype, "x11-req") == 0) { |
1773 | success = session_x11_req(s); | 1786 | success = session_x11_req(s); |
1787 | } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) { | ||
1788 | success = session_auth_agent_req(s); | ||
1774 | } else if (strcmp(rtype, "subsystem") == 0) { | 1789 | } else if (strcmp(rtype, "subsystem") == 0) { |
1775 | success = session_subsystem_req(s); | 1790 | success = session_subsystem_req(s); |
1776 | } | 1791 | } |
diff --git a/sftp-server.8 b/sftp-server.8 index fb4706c43..b8d579a9f 100644 --- a/sftp-server.8 +++ b/sftp-server.8 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: sftp-server.8,v 1.3 2000/10/13 17:20:44 aaron Exp $ | 1 | .\" $OpenBSD: sftp-server.8,v 1.4 2000/11/10 05:10:40 aaron Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | .\" Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | .\" | 4 | .\" |
@@ -48,7 +48,7 @@ for more information. | |||
48 | .Xr ssh-add 1 , | 48 | .Xr ssh-add 1 , |
49 | .Xr ssh-keygen 1 , | 49 | .Xr ssh-keygen 1 , |
50 | .Xr sshd 8 | 50 | .Xr sshd 8 |
51 | .Sh AUTHOR | 51 | .Sh AUTHORS |
52 | Markus Friedl <markus@openbsd.org> | 52 | Markus Friedl <markus@openbsd.org> |
53 | .Sh HISTORY | 53 | .Sh HISTORY |
54 | .Nm | 54 | .Nm |
@@ -116,7 +116,7 @@ may be necessary to redirect the input from | |||
116 | .Pa /dev/null | 116 | .Pa /dev/null |
117 | to make this work.) | 117 | to make this work.) |
118 | .El | 118 | .El |
119 | .Sh AUTHOR | 119 | .Sh AUTHORS |
120 | Tatu Ylonen <ylo@cs.hut.fi> | 120 | Tatu Ylonen <ylo@cs.hut.fi> |
121 | .Pp | 121 | .Pp |
122 | OpenSSH | 122 | OpenSSH |
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | RCSID("$OpenBSD: ssh-add.c,v 1.22 2000/09/07 20:27:54 deraadt Exp $"); | 38 | RCSID("$OpenBSD: ssh-add.c,v 1.23 2000/11/12 19:50:38 markus Exp $"); |
39 | 39 | ||
40 | #include <openssl/evp.h> | 40 | #include <openssl/evp.h> |
41 | #include <openssl/rsa.h> | 41 | #include <openssl/rsa.h> |
@@ -60,10 +60,10 @@ delete_file(AuthenticationConnection *ac, const char *filename) | |||
60 | Key *public; | 60 | Key *public; |
61 | char *comment; | 61 | char *comment; |
62 | 62 | ||
63 | public = key_new(KEY_RSA); | 63 | public = key_new(KEY_RSA1); |
64 | if (!load_public_key(filename, public, &comment)) { | 64 | if (!load_public_key(filename, public, &comment)) { |
65 | key_free(public); | 65 | key_free(public); |
66 | public = key_new(KEY_DSA); | 66 | public = key_new(KEY_UNSPEC); |
67 | if (!try_load_public_key(filename, public, &comment)) { | 67 | if (!try_load_public_key(filename, public, &comment)) { |
68 | printf("Bad key file %s\n", filename); | 68 | printf("Bad key file %s\n", filename); |
69 | return; | 69 | return; |
@@ -144,7 +144,7 @@ add_file(AuthenticationConnection *ac, const char *filename) | |||
144 | char buf[1024], msg[1024]; | 144 | char buf[1024], msg[1024]; |
145 | int success; | 145 | int success; |
146 | int interactive = isatty(STDIN_FILENO); | 146 | int interactive = isatty(STDIN_FILENO); |
147 | int type = KEY_RSA; | 147 | int type = KEY_RSA1; |
148 | 148 | ||
149 | if (stat(filename, &st) < 0) { | 149 | if (stat(filename, &st) < 0) { |
150 | perror(filename); | 150 | perror(filename); |
@@ -154,10 +154,10 @@ add_file(AuthenticationConnection *ac, const char *filename) | |||
154 | * try to load the public key. right now this only works for RSA, | 154 | * try to load the public key. right now this only works for RSA, |
155 | * since DSA keys are fully encrypted | 155 | * since DSA keys are fully encrypted |
156 | */ | 156 | */ |
157 | public = key_new(KEY_RSA); | 157 | public = key_new(KEY_RSA1); |
158 | if (!load_public_key(filename, public, &saved_comment)) { | 158 | if (!load_public_key(filename, public, &saved_comment)) { |
159 | /* ok, so we will asume this is a DSA key */ | 159 | /* ok, so we will assume this is 'some' key */ |
160 | type = KEY_DSA; | 160 | type = KEY_UNSPEC; |
161 | saved_comment = xstrdup(filename); | 161 | saved_comment = xstrdup(filename); |
162 | } | 162 | } |
163 | key_free(public); | 163 | key_free(public); |
@@ -223,8 +223,9 @@ list_identities(AuthenticationConnection *ac, int fp) | |||
223 | key = ssh_get_next_identity(ac, &comment, version)) { | 223 | key = ssh_get_next_identity(ac, &comment, version)) { |
224 | had_identities = 1; | 224 | had_identities = 1; |
225 | if (fp) { | 225 | if (fp) { |
226 | printf("%d %s %s\n", | 226 | printf("%d %s %s (%s)\n", |
227 | key_size(key), key_fingerprint(key), comment); | 227 | key_size(key), key_fingerprint(key), |
228 | comment, key_type(key)); | ||
228 | } else { | 229 | } else { |
229 | if (!key_write(key, stdout)) | 230 | if (!key_write(key, stdout)) |
230 | fprintf(stderr, "key_write failed"); | 231 | fprintf(stderr, "key_write failed"); |
@@ -250,13 +251,6 @@ main(int argc, char **argv) | |||
250 | 251 | ||
251 | init_rng(); | 252 | init_rng(); |
252 | 253 | ||
253 | /* check if RSA support exists */ | ||
254 | if (rsa_alive() == 0) { | ||
255 | fprintf(stderr, | ||
256 | "%s: no RSA support in libssl and libcrypto. See ssl(8).\n", | ||
257 | __progname); | ||
258 | exit(1); | ||
259 | } | ||
260 | SSLeay_add_all_algorithms(); | 254 | SSLeay_add_all_algorithms(); |
261 | 255 | ||
262 | /* At first, get a connection to the authentication agent. */ | 256 | /* At first, get a connection to the authentication agent. */ |
diff --git a/ssh-agent.1 b/ssh-agent.1 index 064d9d4cf..31ea2b318 100644 --- a/ssh-agent.1 +++ b/ssh-agent.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-agent.1,v 1.16 2000/09/07 20:27:54 deraadt Exp $ | 1 | .\" $OpenBSD: ssh-agent.1,v 1.17 2000/11/10 05:10:40 aaron Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -160,7 +160,7 @@ authentication agent. | |||
160 | These sockets should only be readable by the owner. | 160 | These sockets should only be readable by the owner. |
161 | The sockets should get automatically removed when the agent exits. | 161 | The sockets should get automatically removed when the agent exits. |
162 | .El | 162 | .El |
163 | .Sh AUTHOR | 163 | .Sh AUTHORS |
164 | Tatu Ylonen <ylo@cs.hut.fi> | 164 | Tatu Ylonen <ylo@cs.hut.fi> |
165 | .Pp | 165 | .Pp |
166 | OpenSSH | 166 | OpenSSH |
diff --git a/ssh-agent.c b/ssh-agent.c index 479388fab..9f61aec3b 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.39 2000/11/12 19:50:38 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -37,7 +37,7 @@ | |||
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include "includes.h" | 39 | #include "includes.h" |
40 | RCSID("$OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $"); | 40 | RCSID("$OpenBSD: ssh-agent.c,v 1.39 2000/11/12 19:50:38 markus Exp $"); |
41 | 41 | ||
42 | #include "ssh.h" | 42 | #include "ssh.h" |
43 | #include "rsa.h" | 43 | #include "rsa.h" |
@@ -54,7 +54,6 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $"); | |||
54 | #include <openssl/rsa.h> | 54 | #include <openssl/rsa.h> |
55 | #include "key.h" | 55 | #include "key.h" |
56 | #include "authfd.h" | 56 | #include "authfd.h" |
57 | #include "dsa.h" | ||
58 | #include "kex.h" | 57 | #include "kex.h" |
59 | #include "compat.h" | 58 | #include "compat.h" |
60 | 59 | ||
@@ -147,14 +146,14 @@ process_request_identities(SocketEntry *e, int version) | |||
147 | buffer_put_int(&msg, tab->nentries); | 146 | buffer_put_int(&msg, tab->nentries); |
148 | for (i = 0; i < tab->nentries; i++) { | 147 | for (i = 0; i < tab->nentries; i++) { |
149 | Identity *id = &tab->identities[i]; | 148 | Identity *id = &tab->identities[i]; |
150 | if (id->key->type == KEY_RSA) { | 149 | if (id->key->type == KEY_RSA1) { |
151 | buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); | 150 | buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); |
152 | buffer_put_bignum(&msg, id->key->rsa->e); | 151 | buffer_put_bignum(&msg, id->key->rsa->e); |
153 | buffer_put_bignum(&msg, id->key->rsa->n); | 152 | buffer_put_bignum(&msg, id->key->rsa->n); |
154 | } else { | 153 | } else { |
155 | unsigned char *blob; | 154 | unsigned char *blob; |
156 | unsigned int blen; | 155 | unsigned int blen; |
157 | dsa_make_key_blob(id->key, &blob, &blen); | 156 | key_to_blob(id->key, &blob, &blen); |
158 | buffer_put_string(&msg, blob, blen); | 157 | buffer_put_string(&msg, blob, blen); |
159 | xfree(blob); | 158 | xfree(blob); |
160 | } | 159 | } |
@@ -178,7 +177,7 @@ process_authentication_challenge1(SocketEntry *e) | |||
178 | unsigned int response_type; | 177 | unsigned int response_type; |
179 | 178 | ||
180 | buffer_init(&msg); | 179 | buffer_init(&msg); |
181 | key = key_new(KEY_RSA); | 180 | key = key_new(KEY_RSA1); |
182 | challenge = BN_new(); | 181 | challenge = BN_new(); |
183 | 182 | ||
184 | buffer_get_int(&e->input); /* ignored */ | 183 | buffer_get_int(&e->input); /* ignored */ |
@@ -251,11 +250,11 @@ process_sign_request2(SocketEntry *e) | |||
251 | if (flags & SSH_AGENT_OLD_SIGNATURE) | 250 | if (flags & SSH_AGENT_OLD_SIGNATURE) |
252 | datafellows = SSH_BUG_SIGBLOB; | 251 | datafellows = SSH_BUG_SIGBLOB; |
253 | 252 | ||
254 | key = dsa_key_from_blob(blob, blen); | 253 | key = key_from_blob(blob, blen); |
255 | if (key != NULL) { | 254 | if (key != NULL) { |
256 | private = lookup_private_key(key, NULL, 2); | 255 | private = lookup_private_key(key, NULL, 2); |
257 | if (private != NULL) | 256 | if (private != NULL) |
258 | ok = dsa_sign(private, &signature, &slen, data, dlen); | 257 | ok = key_sign(private, &signature, &slen, data, dlen); |
259 | } | 258 | } |
260 | key_free(key); | 259 | key_free(key); |
261 | buffer_init(&msg); | 260 | buffer_init(&msg); |
@@ -287,7 +286,7 @@ process_remove_identity(SocketEntry *e, int version) | |||
287 | 286 | ||
288 | switch(version){ | 287 | switch(version){ |
289 | case 1: | 288 | case 1: |
290 | key = key_new(KEY_RSA); | 289 | key = key_new(KEY_RSA1); |
291 | bits = buffer_get_int(&e->input); | 290 | bits = buffer_get_int(&e->input); |
292 | buffer_get_bignum(&e->input, key->rsa->e); | 291 | buffer_get_bignum(&e->input, key->rsa->e); |
293 | buffer_get_bignum(&e->input, key->rsa->n); | 292 | buffer_get_bignum(&e->input, key->rsa->n); |
@@ -298,7 +297,7 @@ process_remove_identity(SocketEntry *e, int version) | |||
298 | break; | 297 | break; |
299 | case 2: | 298 | case 2: |
300 | blob = buffer_get_string(&e->input, &blen); | 299 | blob = buffer_get_string(&e->input, &blen); |
301 | key = dsa_key_from_blob(blob, blen); | 300 | key = key_from_blob(blob, blen); |
302 | xfree(blob); | 301 | xfree(blob); |
303 | break; | 302 | break; |
304 | } | 303 | } |
@@ -315,8 +314,12 @@ process_remove_identity(SocketEntry *e, int version) | |||
315 | Idtab *tab = idtab_lookup(version); | 314 | Idtab *tab = idtab_lookup(version); |
316 | key_free(tab->identities[idx].key); | 315 | key_free(tab->identities[idx].key); |
317 | xfree(tab->identities[idx].comment); | 316 | xfree(tab->identities[idx].comment); |
318 | if (idx != tab->nentries) | 317 | if (tab->nentries < 1) |
319 | tab->identities[idx] = tab->identities[tab->nentries]; | 318 | fatal("process_remove_identity: " |
319 | "internal error: tab->nentries %d", | ||
320 | tab->nentries); | ||
321 | if (idx != tab->nentries - 1) | ||
322 | tab->identities[idx] = tab->identities[tab->nentries - 1]; | ||
320 | tab->nentries--; | 323 | tab->nentries--; |
321 | success = 1; | 324 | success = 1; |
322 | } | 325 | } |
@@ -349,79 +352,80 @@ process_remove_all_identities(SocketEntry *e, int version) | |||
349 | } | 352 | } |
350 | 353 | ||
351 | void | 354 | void |
352 | process_add_identity(SocketEntry *e, int version) | 355 | generate_additional_parameters(RSA *rsa) |
353 | { | 356 | { |
354 | Key *k = NULL; | ||
355 | RSA *rsa; | ||
356 | BIGNUM *aux; | 357 | BIGNUM *aux; |
357 | BN_CTX *ctx; | 358 | BN_CTX *ctx; |
358 | char *type; | 359 | /* Generate additional parameters */ |
360 | aux = BN_new(); | ||
361 | ctx = BN_CTX_new(); | ||
362 | |||
363 | BN_sub(aux, rsa->q, BN_value_one()); | ||
364 | BN_mod(rsa->dmq1, rsa->d, aux, ctx); | ||
365 | |||
366 | BN_sub(aux, rsa->p, BN_value_one()); | ||
367 | BN_mod(rsa->dmp1, rsa->d, aux, ctx); | ||
368 | |||
369 | BN_clear_free(aux); | ||
370 | BN_CTX_free(ctx); | ||
371 | } | ||
372 | |||
373 | void | ||
374 | process_add_identity(SocketEntry *e, int version) | ||
375 | { | ||
376 | Key *k = NULL; | ||
377 | char *type_name; | ||
359 | char *comment; | 378 | char *comment; |
360 | int success = 0; | 379 | int type, success = 0; |
361 | Idtab *tab = idtab_lookup(version); | 380 | Idtab *tab = idtab_lookup(version); |
362 | 381 | ||
363 | switch (version) { | 382 | switch (version) { |
364 | case 1: | 383 | case 1: |
365 | k = key_new(KEY_RSA); | 384 | k = key_new_private(KEY_RSA1); |
366 | rsa = k->rsa; | 385 | buffer_get_int(&e->input); /* ignored */ |
367 | 386 | buffer_get_bignum(&e->input, k->rsa->n); | |
368 | /* allocate mem for private key */ | 387 | buffer_get_bignum(&e->input, k->rsa->e); |
369 | /* XXX rsa->n and rsa->e are already allocated */ | 388 | buffer_get_bignum(&e->input, k->rsa->d); |
370 | rsa->d = BN_new(); | 389 | buffer_get_bignum(&e->input, k->rsa->iqmp); |
371 | rsa->iqmp = BN_new(); | ||
372 | rsa->q = BN_new(); | ||
373 | rsa->p = BN_new(); | ||
374 | rsa->dmq1 = BN_new(); | ||
375 | rsa->dmp1 = BN_new(); | ||
376 | |||
377 | buffer_get_int(&e->input); /* ignored */ | ||
378 | |||
379 | buffer_get_bignum(&e->input, rsa->n); | ||
380 | buffer_get_bignum(&e->input, rsa->e); | ||
381 | buffer_get_bignum(&e->input, rsa->d); | ||
382 | buffer_get_bignum(&e->input, rsa->iqmp); | ||
383 | 390 | ||
384 | /* SSH and SSL have p and q swapped */ | 391 | /* SSH and SSL have p and q swapped */ |
385 | buffer_get_bignum(&e->input, rsa->q); /* p */ | 392 | buffer_get_bignum(&e->input, k->rsa->q); /* p */ |
386 | buffer_get_bignum(&e->input, rsa->p); /* q */ | 393 | buffer_get_bignum(&e->input, k->rsa->p); /* q */ |
387 | 394 | ||
388 | /* Generate additional parameters */ | 395 | /* Generate additional parameters */ |
389 | aux = BN_new(); | 396 | generate_additional_parameters(k->rsa); |
390 | ctx = BN_CTX_new(); | ||
391 | |||
392 | BN_sub(aux, rsa->q, BN_value_one()); | ||
393 | BN_mod(rsa->dmq1, rsa->d, aux, ctx); | ||
394 | |||
395 | BN_sub(aux, rsa->p, BN_value_one()); | ||
396 | BN_mod(rsa->dmp1, rsa->d, aux, ctx); | ||
397 | |||
398 | BN_clear_free(aux); | ||
399 | BN_CTX_free(ctx); | ||
400 | |||
401 | break; | 397 | break; |
402 | case 2: | 398 | case 2: |
403 | type = buffer_get_string(&e->input, NULL); | 399 | type_name = buffer_get_string(&e->input, NULL); |
404 | if (strcmp(type, KEX_DSS)) { | 400 | type = key_type_from_name(type_name); |
401 | xfree(type_name); | ||
402 | switch(type) { | ||
403 | case KEY_DSA: | ||
404 | k = key_new_private(type); | ||
405 | buffer_get_bignum2(&e->input, k->dsa->p); | ||
406 | buffer_get_bignum2(&e->input, k->dsa->q); | ||
407 | buffer_get_bignum2(&e->input, k->dsa->g); | ||
408 | buffer_get_bignum2(&e->input, k->dsa->pub_key); | ||
409 | buffer_get_bignum2(&e->input, k->dsa->priv_key); | ||
410 | break; | ||
411 | case KEY_RSA: | ||
412 | k = key_new_private(type); | ||
413 | buffer_get_bignum2(&e->input, k->rsa->n); | ||
414 | buffer_get_bignum2(&e->input, k->rsa->e); | ||
415 | buffer_get_bignum2(&e->input, k->rsa->d); | ||
416 | buffer_get_bignum2(&e->input, k->rsa->iqmp); | ||
417 | buffer_get_bignum2(&e->input, k->rsa->p); | ||
418 | buffer_get_bignum2(&e->input, k->rsa->q); | ||
419 | |||
420 | /* Generate additional parameters */ | ||
421 | generate_additional_parameters(k->rsa); | ||
422 | break; | ||
423 | default: | ||
405 | buffer_clear(&e->input); | 424 | buffer_clear(&e->input); |
406 | xfree(type); | ||
407 | goto send; | 425 | goto send; |
408 | } | 426 | } |
409 | xfree(type); | ||
410 | |||
411 | k = key_new(KEY_DSA); | ||
412 | |||
413 | /* allocate mem for private key */ | ||
414 | k->dsa->priv_key = BN_new(); | ||
415 | |||
416 | buffer_get_bignum2(&e->input, k->dsa->p); | ||
417 | buffer_get_bignum2(&e->input, k->dsa->q); | ||
418 | buffer_get_bignum2(&e->input, k->dsa->g); | ||
419 | buffer_get_bignum2(&e->input, k->dsa->pub_key); | ||
420 | buffer_get_bignum2(&e->input, k->dsa->priv_key); | ||
421 | |||
422 | break; | 427 | break; |
423 | } | 428 | } |
424 | |||
425 | comment = buffer_get_string(&e->input, NULL); | 429 | comment = buffer_get_string(&e->input, NULL); |
426 | if (k == NULL) { | 430 | if (k == NULL) { |
427 | xfree(comment); | 431 | xfree(comment); |
@@ -670,13 +674,6 @@ main(int ac, char **av) | |||
670 | 674 | ||
671 | init_rng(); | 675 | init_rng(); |
672 | 676 | ||
673 | /* check if RSA support exists */ | ||
674 | if (rsa_alive() == 0) { | ||
675 | fprintf(stderr, | ||
676 | "%s: no RSA support in libssl and libcrypto. See ssl(8).\n", | ||
677 | __progname); | ||
678 | exit(1); | ||
679 | } | ||
680 | #ifdef __GNU_LIBRARY__ | 677 | #ifdef __GNU_LIBRARY__ |
681 | while ((ch = getopt(ac, av, "+cks")) != -1) { | 678 | while ((ch = getopt(ac, av, "+cks")) != -1) { |
682 | #else /* __GNU_LIBRARY__ */ | 679 | #else /* __GNU_LIBRARY__ */ |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: dsa.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $"); | 26 | RCSID("$OpenBSD: ssh-dss.c,v 1.1 2000/11/12 19:50:38 markus Exp $"); |
27 | 27 | ||
28 | #include "ssh.h" | 28 | #include "ssh.h" |
29 | #include "xmalloc.h" | 29 | #include "xmalloc.h" |
@@ -32,88 +32,17 @@ RCSID("$OpenBSD: dsa.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $"); | |||
32 | #include "compat.h" | 32 | #include "compat.h" |
33 | 33 | ||
34 | #include <openssl/bn.h> | 34 | #include <openssl/bn.h> |
35 | #include <openssl/dh.h> | ||
36 | #include <openssl/rsa.h> | 35 | #include <openssl/rsa.h> |
37 | #include <openssl/dsa.h> | 36 | #include <openssl/dsa.h> |
38 | #include <openssl/evp.h> | 37 | #include <openssl/evp.h> |
39 | #include <openssl/bio.h> | ||
40 | #include <openssl/pem.h> | ||
41 | 38 | ||
42 | #include <openssl/hmac.h> | ||
43 | #include "kex.h" | ||
44 | #include "key.h" | 39 | #include "key.h" |
45 | #include "uuencode.h" | ||
46 | 40 | ||
47 | #define INTBLOB_LEN 20 | 41 | #define INTBLOB_LEN 20 |
48 | #define SIGBLOB_LEN (2*INTBLOB_LEN) | 42 | #define SIGBLOB_LEN (2*INTBLOB_LEN) |
49 | 43 | ||
50 | Key * | ||
51 | dsa_key_from_blob(char *blob, int blen) | ||
52 | { | ||
53 | Buffer b; | ||
54 | char *ktype; | ||
55 | int rlen; | ||
56 | DSA *dsa; | ||
57 | Key *key; | ||
58 | |||
59 | #ifdef DEBUG_DSS | ||
60 | dump_base64(stderr, blob, blen); | ||
61 | #endif | ||
62 | /* fetch & parse DSA/DSS pubkey */ | ||
63 | buffer_init(&b); | ||
64 | buffer_append(&b, blob, blen); | ||
65 | ktype = buffer_get_string(&b, NULL); | ||
66 | if (strcmp(KEX_DSS, ktype) != 0) { | ||
67 | error("dsa_key_from_blob: cannot handle type %s", ktype); | ||
68 | buffer_free(&b); | ||
69 | xfree(ktype); | ||
70 | return NULL; | ||
71 | } | ||
72 | key = key_new(KEY_DSA); | ||
73 | dsa = key->dsa; | ||
74 | buffer_get_bignum2(&b, dsa->p); | ||
75 | buffer_get_bignum2(&b, dsa->q); | ||
76 | buffer_get_bignum2(&b, dsa->g); | ||
77 | buffer_get_bignum2(&b, dsa->pub_key); | ||
78 | rlen = buffer_len(&b); | ||
79 | if(rlen != 0) | ||
80 | error("dsa_key_from_blob: remaining bytes in key blob %d", rlen); | ||
81 | buffer_free(&b); | ||
82 | xfree(ktype); | ||
83 | |||
84 | #ifdef DEBUG_DSS | ||
85 | DSA_print_fp(stderr, dsa, 8); | ||
86 | #endif | ||
87 | return key; | ||
88 | } | ||
89 | int | ||
90 | dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp) | ||
91 | { | ||
92 | Buffer b; | ||
93 | int len; | ||
94 | unsigned char *buf; | ||
95 | |||
96 | if (key == NULL || key->type != KEY_DSA) | ||
97 | return 0; | ||
98 | buffer_init(&b); | ||
99 | buffer_put_cstring(&b, KEX_DSS); | ||
100 | buffer_put_bignum2(&b, key->dsa->p); | ||
101 | buffer_put_bignum2(&b, key->dsa->q); | ||
102 | buffer_put_bignum2(&b, key->dsa->g); | ||
103 | buffer_put_bignum2(&b, key->dsa->pub_key); | ||
104 | len = buffer_len(&b); | ||
105 | buf = xmalloc(len); | ||
106 | memcpy(buf, buffer_ptr(&b), len); | ||
107 | memset(buffer_ptr(&b), 0, len); | ||
108 | buffer_free(&b); | ||
109 | if (lenp != NULL) | ||
110 | *lenp = len; | ||
111 | if (blobp != NULL) | ||
112 | *blobp = buf; | ||
113 | return len; | ||
114 | } | ||
115 | int | 44 | int |
116 | dsa_sign( | 45 | ssh_dss_sign( |
117 | Key *key, | 46 | Key *key, |
118 | unsigned char **sigp, int *lenp, | 47 | unsigned char **sigp, int *lenp, |
119 | unsigned char *data, int datalen) | 48 | unsigned char *data, int datalen) |
@@ -130,7 +59,7 @@ dsa_sign( | |||
130 | Buffer b; | 59 | Buffer b; |
131 | 60 | ||
132 | if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { | 61 | if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { |
133 | error("dsa_sign: no DSA key"); | 62 | error("ssh_dss_sign: no DSA key"); |
134 | return -1; | 63 | return -1; |
135 | } | 64 | } |
136 | digest = xmalloc(evp_md->md_size); | 65 | digest = xmalloc(evp_md->md_size); |
@@ -140,7 +69,7 @@ dsa_sign( | |||
140 | 69 | ||
141 | sig = DSA_do_sign(digest, evp_md->md_size, key->dsa); | 70 | sig = DSA_do_sign(digest, evp_md->md_size, key->dsa); |
142 | if (sig == NULL) { | 71 | if (sig == NULL) { |
143 | fatal("dsa_sign: cannot sign"); | 72 | fatal("ssh_dss_sign: cannot sign"); |
144 | } | 73 | } |
145 | 74 | ||
146 | rlen = BN_num_bytes(sig->r); | 75 | rlen = BN_num_bytes(sig->r); |
@@ -168,7 +97,7 @@ dsa_sign( | |||
168 | } else { | 97 | } else { |
169 | /* ietf-drafts */ | 98 | /* ietf-drafts */ |
170 | buffer_init(&b); | 99 | buffer_init(&b); |
171 | buffer_put_cstring(&b, KEX_DSS); | 100 | buffer_put_cstring(&b, "ssh-dss"); |
172 | buffer_put_string(&b, sigblob, SIGBLOB_LEN); | 101 | buffer_put_string(&b, sigblob, SIGBLOB_LEN); |
173 | len = buffer_len(&b); | 102 | len = buffer_len(&b); |
174 | ret = xmalloc(len); | 103 | ret = xmalloc(len); |
@@ -182,7 +111,7 @@ dsa_sign( | |||
182 | return 0; | 111 | return 0; |
183 | } | 112 | } |
184 | int | 113 | int |
185 | dsa_verify( | 114 | ssh_dss_verify( |
186 | Key *key, | 115 | Key *key, |
187 | unsigned char *signature, int signaturelen, | 116 | unsigned char *signature, int signaturelen, |
188 | unsigned char *data, int datalen) | 117 | unsigned char *data, int datalen) |
@@ -194,12 +123,12 @@ dsa_verify( | |||
194 | EVP_MD_CTX md; | 123 | EVP_MD_CTX md; |
195 | unsigned char *sigblob; | 124 | unsigned char *sigblob; |
196 | char *txt; | 125 | char *txt; |
197 | unsigned int len; | 126 | unsigned int len, dlen; |
198 | int rlen; | 127 | int rlen; |
199 | int ret; | 128 | int ret; |
200 | 129 | ||
201 | if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { | 130 | if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) { |
202 | error("dsa_verify: no DSA key"); | 131 | error("ssh_dss_verify: no DSA key"); |
203 | return -1; | 132 | return -1; |
204 | } | 133 | } |
205 | 134 | ||
@@ -225,8 +154,8 @@ dsa_verify( | |||
225 | buffer_init(&b); | 154 | buffer_init(&b); |
226 | buffer_append(&b, (char *) signature, signaturelen); | 155 | buffer_append(&b, (char *) signature, signaturelen); |
227 | ktype = buffer_get_string(&b, NULL); | 156 | ktype = buffer_get_string(&b, NULL); |
228 | if (strcmp(KEX_DSS, ktype) != 0) { | 157 | if (strcmp("ssh-dss", ktype) != 0) { |
229 | error("dsa_verify: cannot handle type %s", ktype); | 158 | error("ssh_dss_verify: cannot handle type %s", ktype); |
230 | buffer_free(&b); | 159 | buffer_free(&b); |
231 | return -1; | 160 | return -1; |
232 | } | 161 | } |
@@ -258,14 +187,15 @@ dsa_verify( | |||
258 | } | 187 | } |
259 | 188 | ||
260 | /* sha1 the data */ | 189 | /* sha1 the data */ |
261 | digest = xmalloc(evp_md->md_size); | 190 | dlen = evp_md->md_size; |
191 | digest = xmalloc(dlen); | ||
262 | EVP_DigestInit(&md, evp_md); | 192 | EVP_DigestInit(&md, evp_md); |
263 | EVP_DigestUpdate(&md, data, datalen); | 193 | EVP_DigestUpdate(&md, data, datalen); |
264 | EVP_DigestFinal(&md, digest, NULL); | 194 | EVP_DigestFinal(&md, digest, NULL); |
265 | 195 | ||
266 | ret = DSA_do_verify(digest, evp_md->md_size, sig, key->dsa); | 196 | ret = DSA_do_verify(digest, dlen, sig, key->dsa); |
267 | 197 | ||
268 | memset(digest, 0, evp_md->md_size); | 198 | memset(digest, 0, dlen); |
269 | xfree(digest); | 199 | xfree(digest); |
270 | DSA_SIG_free(sig); | 200 | DSA_SIG_free(sig); |
271 | 201 | ||
@@ -281,24 +211,6 @@ dsa_verify( | |||
281 | txt = "error"; | 211 | txt = "error"; |
282 | break; | 212 | break; |
283 | } | 213 | } |
284 | debug("dsa_verify: signature %s", txt); | 214 | debug("ssh_dss_verify: signature %s", txt); |
285 | return ret; | 215 | return ret; |
286 | } | 216 | } |
287 | |||
288 | Key * | ||
289 | dsa_generate_key(unsigned int bits) | ||
290 | { | ||
291 | DSA *dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL); | ||
292 | Key *k; | ||
293 | if (dsa == NULL) { | ||
294 | fatal("DSA_generate_parameters failed"); | ||
295 | } | ||
296 | if (!DSA_generate_key(dsa)) { | ||
297 | fatal("DSA_generate_keys failed"); | ||
298 | } | ||
299 | |||
300 | k = key_new(KEY_EMPTY); | ||
301 | k->type = KEY_DSA; | ||
302 | k->dsa = dsa; | ||
303 | return k; | ||
304 | } | ||
@@ -24,22 +24,16 @@ | |||
24 | #ifndef DSA_H | 24 | #ifndef DSA_H |
25 | #define DSA_H | 25 | #define DSA_H |
26 | 26 | ||
27 | Key *dsa_key_from_blob(char *blob, int blen); | ||
28 | int dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp); | ||
29 | |||
30 | int | 27 | int |
31 | dsa_sign( | 28 | ssh_dss_sign( |
32 | Key *key, | 29 | Key *key, |
33 | unsigned char **sigp, int *lenp, | 30 | unsigned char **sigp, int *lenp, |
34 | unsigned char *data, int datalen); | 31 | unsigned char *data, int datalen); |
35 | 32 | ||
36 | int | 33 | int |
37 | dsa_verify( | 34 | ssh_dss_verify( |
38 | Key *key, | 35 | Key *key, |
39 | unsigned char *signature, int signaturelen, | 36 | unsigned char *signature, int signaturelen, |
40 | unsigned char *data, int datalen); | 37 | unsigned char *data, int datalen); |
41 | 38 | ||
42 | Key * | ||
43 | dsa_generate_key(unsigned int bits); | ||
44 | |||
45 | #endif | 39 | #endif |
diff --git a/ssh-keygen.1 b/ssh-keygen.1 index b91a09827..b1430f143 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 | |||
@@ -43,8 +43,9 @@ | |||
43 | .Nd authentication key generation | 43 | .Nd authentication key generation |
44 | .Sh SYNOPSIS | 44 | .Sh SYNOPSIS |
45 | .Nm ssh-keygen | 45 | .Nm ssh-keygen |
46 | .Op Fl dq | 46 | .Op Fl q |
47 | .Op Fl b Ar bits | 47 | .Op Fl b Ar bits |
48 | .Op Fl t Ar type | ||
48 | .Op Fl N Ar new_passphrase | 49 | .Op Fl N Ar new_passphrase |
49 | .Op Fl C Ar comment | 50 | .Op Fl C Ar comment |
50 | .Op Fl f Ar output_keyfile | 51 | .Op Fl f Ar output_keyfile |
@@ -79,8 +80,8 @@ generates and manages authentication keys for | |||
79 | .Nm | 80 | .Nm |
80 | defaults to generating an RSA key for use by protocols 1.3 and 1.5; | 81 | defaults to generating an RSA key for use by protocols 1.3 and 1.5; |
81 | specifying the | 82 | specifying the |
82 | .Fl d | 83 | .Fl t |
83 | flag will create a DSA key instead for use by protocol 2.0. | 84 | allows you to create a key for use by protocol 2.0. |
84 | .Pp | 85 | .Pp |
85 | Normally each user wishing to use SSH | 86 | Normally each user wishing to use SSH |
86 | with RSA or DSA authentication runs this once to create the authentication | 87 | with RSA or DSA authentication runs this once to create the authentication |
@@ -154,6 +155,17 @@ Silence | |||
154 | Used by | 155 | Used by |
155 | .Pa /etc/rc | 156 | .Pa /etc/rc |
156 | when creating a new key. | 157 | when creating a new key. |
158 | .It Fl t Ar type | ||
159 | Specifies the type of the key to create. | ||
160 | The possible values are | ||
161 | .Dq rsa1 | ||
162 | for protocol version 1 and | ||
163 | .Dq rsa | ||
164 | or | ||
165 | .Dq dsa | ||
166 | for protocol version 2. | ||
167 | The default is | ||
168 | .Dq rsa . | ||
157 | .It Fl C Ar comment | 169 | .It Fl C Ar comment |
158 | Provides the new comment. | 170 | Provides the new comment. |
159 | .It Fl N Ar new_passphrase | 171 | .It Fl N Ar new_passphrase |
@@ -173,7 +185,7 @@ SSH2-compatible private (or public) key file and | |||
173 | print an OpenSSH compatible private (or public) key to stdout. | 185 | print an OpenSSH compatible private (or public) key to stdout. |
174 | .It Fl y | 186 | .It Fl y |
175 | This option will read a private | 187 | This option will read a private |
176 | OpenSSH DSA format file and print an OpenSSH DSA public key to stdout. | 188 | OpenSSH format file and print an OpenSSH public key to stdout. |
177 | .El | 189 | .El |
178 | .Sh FILES | 190 | .Sh FILES |
179 | .Bl -tag -width Ds | 191 | .Bl -tag -width Ds |
@@ -211,10 +223,10 @@ Contains the public key for authentication. | |||
211 | The contents of this file should be added to | 223 | The contents of this file should be added to |
212 | .Pa $HOME/.ssh/authorized_keys2 | 224 | .Pa $HOME/.ssh/authorized_keys2 |
213 | on all machines | 225 | on all machines |
214 | where you wish to log in using DSA authentication. | 226 | where you wish to log in using public key authentication. |
215 | There is no need to keep the contents of this file secret. | 227 | There is no need to keep the contents of this file secret. |
216 | .El | 228 | .El |
217 | .Sh AUTHOR | 229 | .Sh AUTHORS |
218 | Tatu Ylonen <ylo@cs.hut.fi> | 230 | Tatu Ylonen <ylo@cs.hut.fi> |
219 | .Pp | 231 | .Pp |
220 | OpenSSH | 232 | OpenSSH |
diff --git a/ssh-keygen.c b/ssh-keygen.c index e050f4051..76edc5301 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.32 2000/10/09 21:30:44 markus Exp $"); | 15 | RCSID("$OpenBSD: ssh-keygen.c,v 1.33 2000/11/12 19:50:38 markus Exp $"); |
16 | 16 | ||
17 | #include <openssl/evp.h> | 17 | #include <openssl/evp.h> |
18 | #include <openssl/pem.h> | 18 | #include <openssl/pem.h> |
@@ -23,7 +23,6 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.32 2000/10/09 21:30:44 markus Exp $"); | |||
23 | #include "xmalloc.h" | 23 | #include "xmalloc.h" |
24 | #include "key.h" | 24 | #include "key.h" |
25 | #include "rsa.h" | 25 | #include "rsa.h" |
26 | #include "dsa.h" | ||
27 | #include "authfile.h" | 26 | #include "authfile.h" |
28 | #include "uuencode.h" | 27 | #include "uuencode.h" |
29 | 28 | ||
@@ -67,7 +66,10 @@ char *identity_comment = NULL; | |||
67 | int convert_to_ssh2 = 0; | 66 | int convert_to_ssh2 = 0; |
68 | int convert_from_ssh2 = 0; | 67 | int convert_from_ssh2 = 0; |
69 | int print_public = 0; | 68 | int print_public = 0; |
70 | int dsa_mode = 0; | 69 | |
70 | /* key type */ | ||
71 | int dsa_mode = 0; /* compat */ | ||
72 | char *key_type_name = NULL; | ||
71 | 73 | ||
72 | /* argv0 */ | 74 | /* argv0 */ |
73 | #ifdef HAVE___PROGNAME | 75 | #ifdef HAVE___PROGNAME |
@@ -130,12 +132,12 @@ do_convert_to_ssh2(struct passwd *pw) | |||
130 | perror(identity_file); | 132 | perror(identity_file); |
131 | exit(1); | 133 | exit(1); |
132 | } | 134 | } |
133 | k = key_new(KEY_DSA); | 135 | k = key_new(KEY_UNSPEC); |
134 | if (!try_load_key(identity_file, k)) { | 136 | if (!try_load_key(identity_file, k)) { |
135 | fprintf(stderr, "load failed\n"); | 137 | fprintf(stderr, "load failed\n"); |
136 | exit(1); | 138 | exit(1); |
137 | } | 139 | } |
138 | dsa_make_key_blob(k, &blob, &len); | 140 | key_to_blob(k, &blob, &len); |
139 | fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN); | 141 | fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN); |
140 | fprintf(stdout, | 142 | fprintf(stdout, |
141 | "Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n", | 143 | "Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n", |
@@ -266,7 +268,7 @@ do_convert_from_ssh2(struct passwd *pw) | |||
266 | } | 268 | } |
267 | k = private ? | 269 | k = private ? |
268 | do_convert_private_ssh2_from_blob(blob, blen) : | 270 | do_convert_private_ssh2_from_blob(blob, blen) : |
269 | dsa_key_from_blob(blob, blen); | 271 | key_from_blob(blob, blen); |
270 | if (k == NULL) { | 272 | if (k == NULL) { |
271 | fprintf(stderr, "decode blob failed.\n"); | 273 | fprintf(stderr, "decode blob failed.\n"); |
272 | exit(1); | 274 | exit(1); |
@@ -288,8 +290,6 @@ void | |||
288 | do_print_public(struct passwd *pw) | 290 | do_print_public(struct passwd *pw) |
289 | { | 291 | { |
290 | Key *k; | 292 | Key *k; |
291 | int len; | ||
292 | unsigned char *blob; | ||
293 | struct stat st; | 293 | struct stat st; |
294 | 294 | ||
295 | if (!have_identity) | 295 | if (!have_identity) |
@@ -298,16 +298,14 @@ do_print_public(struct passwd *pw) | |||
298 | perror(identity_file); | 298 | perror(identity_file); |
299 | exit(1); | 299 | exit(1); |
300 | } | 300 | } |
301 | k = key_new(KEY_DSA); | 301 | k = key_new(KEY_UNSPEC); |
302 | if (!try_load_key(identity_file, k)) { | 302 | if (!try_load_key(identity_file, k)) { |
303 | fprintf(stderr, "load failed\n"); | 303 | fprintf(stderr, "load failed\n"); |
304 | exit(1); | 304 | exit(1); |
305 | } | 305 | } |
306 | dsa_make_key_blob(k, &blob, &len); | ||
307 | if (!key_write(k, stdout)) | 306 | if (!key_write(k, stdout)) |
308 | fprintf(stderr, "key_write failed"); | 307 | fprintf(stderr, "key_write failed"); |
309 | key_free(k); | 308 | key_free(k); |
310 | xfree(blob); | ||
311 | fprintf(stdout, "\n"); | 309 | fprintf(stdout, "\n"); |
312 | exit(0); | 310 | exit(0); |
313 | } | 311 | } |
@@ -315,12 +313,11 @@ do_print_public(struct passwd *pw) | |||
315 | void | 313 | void |
316 | do_fingerprint(struct passwd *pw) | 314 | do_fingerprint(struct passwd *pw) |
317 | { | 315 | { |
318 | /* XXX RSA1 only */ | ||
319 | 316 | ||
320 | FILE *f; | 317 | FILE *f; |
321 | Key *public; | 318 | Key *public; |
322 | char *comment = NULL, *cp, *ep, line[16*1024]; | 319 | char *comment = NULL, *cp, *ep, line[16*1024]; |
323 | int i, skip = 0, num = 1, invalid = 1; | 320 | int i, skip = 0, num = 1, invalid = 1, success = 0; |
324 | unsigned int ignore; | 321 | unsigned int ignore; |
325 | struct stat st; | 322 | struct stat st; |
326 | 323 | ||
@@ -330,14 +327,27 @@ do_fingerprint(struct passwd *pw) | |||
330 | perror(identity_file); | 327 | perror(identity_file); |
331 | exit(1); | 328 | exit(1); |
332 | } | 329 | } |
333 | public = key_new(KEY_RSA); | 330 | public = key_new(KEY_RSA1); |
334 | if (load_public_key(identity_file, public, &comment)) { | 331 | if (load_public_key(identity_file, public, &comment)) { |
335 | printf("%d %s %s\n", BN_num_bits(public->rsa->n), | 332 | success = 1; |
336 | key_fingerprint(public), comment); | 333 | } else { |
334 | key_free(public); | ||
335 | public = key_new(KEY_UNSPEC); | ||
336 | if (try_load_public_key(identity_file, public, &comment)) | ||
337 | success = 1; | ||
338 | else | ||
339 | error("try_load_public_key KEY_UNSPEC failed"); | ||
340 | } | ||
341 | if (success) { | ||
342 | printf("%d %s %s\n", key_size(public), key_fingerprint(public), comment); | ||
337 | key_free(public); | 343 | key_free(public); |
344 | xfree(comment); | ||
338 | exit(0); | 345 | exit(0); |
339 | } | 346 | } |
340 | 347 | ||
348 | /* XXX RSA1 only */ | ||
349 | |||
350 | public = key_new(KEY_RSA1); | ||
341 | f = fopen(identity_file, "r"); | 351 | f = fopen(identity_file, "r"); |
342 | if (f != NULL) { | 352 | if (f != NULL) { |
343 | while (fgets(line, sizeof(line), f)) { | 353 | while (fgets(line, sizeof(line), f)) { |
@@ -404,7 +414,7 @@ do_change_passphrase(struct passwd *pw) | |||
404 | struct stat st; | 414 | struct stat st; |
405 | Key *private; | 415 | Key *private; |
406 | Key *public; | 416 | Key *public; |
407 | int type = dsa_mode ? KEY_DSA : KEY_RSA; | 417 | int type = KEY_RSA1; |
408 | 418 | ||
409 | if (!have_identity) | 419 | if (!have_identity) |
410 | ask_filename(pw, "Enter file in which the key is"); | 420 | ask_filename(pw, "Enter file in which the key is"); |
@@ -412,18 +422,13 @@ do_change_passphrase(struct passwd *pw) | |||
412 | perror(identity_file); | 422 | perror(identity_file); |
413 | exit(1); | 423 | exit(1); |
414 | } | 424 | } |
415 | 425 | public = key_new(type); | |
416 | if (type == KEY_RSA) { | 426 | if (!load_public_key(identity_file, public, NULL)) { |
417 | /* XXX this works currently only for RSA */ | 427 | type = KEY_UNSPEC; |
418 | public = key_new(type); | 428 | } else { |
419 | if (!load_public_key(identity_file, public, NULL)) { | ||
420 | printf("%s is not a valid key file.\n", identity_file); | ||
421 | exit(1); | ||
422 | } | ||
423 | /* Clear the public key since we are just about to load the whole file. */ | 429 | /* Clear the public key since we are just about to load the whole file. */ |
424 | key_free(public); | 430 | key_free(public); |
425 | } | 431 | } |
426 | |||
427 | /* Try to load the file with empty passphrase. */ | 432 | /* Try to load the file with empty passphrase. */ |
428 | private = key_new(type); | 433 | private = key_new(type); |
429 | if (!load_private_key(identity_file, "", private, &comment)) { | 434 | if (!load_private_key(identity_file, "", private, &comment)) { |
@@ -508,13 +513,13 @@ do_change_comment(struct passwd *pw) | |||
508 | * Try to load the public key from the file the verify that it is | 513 | * Try to load the public key from the file the verify that it is |
509 | * readable and of the proper format. | 514 | * readable and of the proper format. |
510 | */ | 515 | */ |
511 | public = key_new(KEY_RSA); | 516 | public = key_new(KEY_RSA1); |
512 | if (!load_public_key(identity_file, public, NULL)) { | 517 | if (!load_public_key(identity_file, public, NULL)) { |
513 | printf("%s is not a valid key file.\n", identity_file); | 518 | printf("%s is not a valid key file.\n", identity_file); |
514 | exit(1); | 519 | exit(1); |
515 | } | 520 | } |
516 | 521 | ||
517 | private = key_new(KEY_RSA); | 522 | private = key_new(KEY_RSA1); |
518 | if (load_private_key(identity_file, "", private, &comment)) | 523 | if (load_private_key(identity_file, "", private, &comment)) |
519 | passphrase = xstrdup(""); | 524 | passphrase = xstrdup(""); |
520 | else { | 525 | else { |
@@ -583,7 +588,7 @@ do_change_comment(struct passwd *pw) | |||
583 | void | 588 | void |
584 | usage(void) | 589 | usage(void) |
585 | { | 590 | { |
586 | printf("Usage: %s [-lpqxXydc] [-b bits] [-f file] [-C comment] [-N new-pass] [-P pass]\n", __progname); | 591 | printf("Usage: %s [-lpqxXyc] [-t type] [-b bits] [-f file] [-C comment] [-N new-pass] [-P pass]\n", __progname); |
587 | exit(1); | 592 | exit(1); |
588 | } | 593 | } |
589 | 594 | ||
@@ -598,8 +603,10 @@ main(int ac, char **av) | |||
598 | int opt; | 603 | int opt; |
599 | struct stat st; | 604 | struct stat st; |
600 | FILE *f; | 605 | FILE *f; |
606 | int type = KEY_RSA1; | ||
601 | Key *private; | 607 | Key *private; |
602 | Key *public; | 608 | Key *public; |
609 | |||
603 | extern int optind; | 610 | extern int optind; |
604 | extern char *optarg; | 611 | extern char *optarg; |
605 | 612 | ||
@@ -618,7 +625,7 @@ main(int ac, char **av) | |||
618 | exit(1); | 625 | exit(1); |
619 | } | 626 | } |
620 | 627 | ||
621 | while ((opt = getopt(ac, av, "dqpclRxXyb:f:P:N:C:")) != EOF) { | 628 | while ((opt = getopt(ac, av, "dqpclRxXyb:f:t:P:N:C:")) != EOF) { |
622 | switch (opt) { | 629 | switch (opt) { |
623 | case 'b': | 630 | case 'b': |
624 | bits = atoi(optarg); | 631 | bits = atoi(optarg); |
@@ -662,10 +669,8 @@ main(int ac, char **av) | |||
662 | break; | 669 | break; |
663 | 670 | ||
664 | case 'R': | 671 | case 'R': |
665 | if (rsa_alive() == 0) | 672 | /* unused */ |
666 | exit(1); | 673 | exit(0); |
667 | else | ||
668 | exit(0); | ||
669 | break; | 674 | break; |
670 | 675 | ||
671 | case 'x': | 676 | case 'x': |
@@ -681,9 +686,15 @@ main(int ac, char **av) | |||
681 | break; | 686 | break; |
682 | 687 | ||
683 | case 'd': | 688 | case 'd': |
689 | key_type_name = "dsa"; | ||
684 | dsa_mode = 1; | 690 | dsa_mode = 1; |
685 | break; | 691 | break; |
686 | 692 | ||
693 | case 't': | ||
694 | key_type_name = optarg; | ||
695 | dsa_mode = (strcmp(optarg, "dsa") == 0); | ||
696 | break; | ||
697 | |||
687 | case '?': | 698 | case '?': |
688 | default: | 699 | default: |
689 | usage(); | 700 | usage(); |
@@ -697,13 +708,6 @@ main(int ac, char **av) | |||
697 | printf("Can only have one of -p and -c.\n"); | 708 | printf("Can only have one of -p and -c.\n"); |
698 | usage(); | 709 | usage(); |
699 | } | 710 | } |
700 | /* check if RSA support is needed and exists */ | ||
701 | if (dsa_mode == 0 && rsa_alive() == 0) { | ||
702 | fprintf(stderr, | ||
703 | "%s: no RSA support in libssl and libcrypto. See ssl(8).\n", | ||
704 | __progname); | ||
705 | exit(1); | ||
706 | } | ||
707 | if (print_fingerprint) | 711 | if (print_fingerprint) |
708 | do_fingerprint(pw); | 712 | do_fingerprint(pw); |
709 | if (change_passphrase) | 713 | if (change_passphrase) |
@@ -719,22 +723,21 @@ main(int ac, char **av) | |||
719 | 723 | ||
720 | arc4random_stir(); | 724 | arc4random_stir(); |
721 | 725 | ||
722 | if (dsa_mode != 0) { | 726 | if (key_type_name != NULL) { |
723 | if (!quiet) | 727 | type = key_type_from_name(key_type_name); |
724 | printf("Generating DSA parameter and key.\n"); | 728 | if (type == KEY_UNSPEC) { |
725 | public = private = dsa_generate_key(bits); | 729 | fprintf(stderr, "unknown key type %s", key_type_name); |
726 | if (private == NULL) { | ||
727 | fprintf(stderr, "dsa_generate_keys failed"); | ||
728 | exit(1); | 730 | exit(1); |
729 | } | 731 | } |
730 | } else { | ||
731 | if (quiet) | ||
732 | rsa_set_verbose(0); | ||
733 | /* Generate the rsa key pair. */ | ||
734 | public = key_new(KEY_RSA); | ||
735 | private = key_new(KEY_RSA); | ||
736 | rsa_generate_key(private->rsa, public->rsa, bits); | ||
737 | } | 732 | } |
733 | if (!quiet) | ||
734 | printf("Generating public/private key pair.\n"); | ||
735 | private = key_generate(type, bits); | ||
736 | if (private == NULL) { | ||
737 | fprintf(stderr, "key_generate failed"); | ||
738 | exit(1); | ||
739 | } | ||
740 | public = key_from_private(private); | ||
738 | 741 | ||
739 | if (!have_identity) | 742 | if (!have_identity) |
740 | ask_filename(pw, "Enter file in which to save the key"); | 743 | ask_filename(pw, "Enter file in which to save the key"); |
@@ -803,9 +806,7 @@ passphrase_again: | |||
803 | xfree(passphrase1); | 806 | xfree(passphrase1); |
804 | 807 | ||
805 | /* Clear the private key and the random number generator. */ | 808 | /* Clear the private key and the random number generator. */ |
806 | if (private != public) { | 809 | key_free(private); |
807 | key_free(private); | ||
808 | } | ||
809 | arc4random_stir(); | 810 | arc4random_stir(); |
810 | 811 | ||
811 | if (!quiet) | 812 | if (!quiet) |
diff --git a/ssh-rsa.c b/ssh-rsa.c new file mode 100644 index 000000000..cc31154d9 --- /dev/null +++ b/ssh-rsa.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000 Markus Friedl. 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: ssh-rsa.c,v 1.1 2000/11/12 19:50:38 markus Exp $"); | ||
27 | |||
28 | #include "ssh.h" | ||
29 | #include "xmalloc.h" | ||
30 | #include "buffer.h" | ||
31 | #include "bufaux.h" | ||
32 | |||
33 | #include <openssl/evp.h> | ||
34 | #include <openssl/dsa.h> | ||
35 | #include <openssl/rsa.h> | ||
36 | #include <openssl/err.h> | ||
37 | |||
38 | #include "key.h" | ||
39 | |||
40 | #define INTBLOB_LEN 20 | ||
41 | #define SIGBLOB_LEN (2*INTBLOB_LEN) | ||
42 | |||
43 | /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ | ||
44 | int | ||
45 | ssh_rsa_sign( | ||
46 | Key *key, | ||
47 | unsigned char **sigp, int *lenp, | ||
48 | unsigned char *data, int datalen) | ||
49 | { | ||
50 | EVP_MD *evp_md = EVP_sha1(); | ||
51 | EVP_MD_CTX md; | ||
52 | unsigned char *digest, *sig, *ret; | ||
53 | unsigned int slen, dlen, len; | ||
54 | int ok; | ||
55 | Buffer b; | ||
56 | |||
57 | if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) { | ||
58 | error("ssh_rsa_sign: no RSA key"); | ||
59 | return -1; | ||
60 | } | ||
61 | slen = RSA_size(key->rsa); | ||
62 | sig = xmalloc(slen); | ||
63 | |||
64 | dlen = evp_md->md_size; | ||
65 | digest = xmalloc(dlen); | ||
66 | EVP_DigestInit(&md, evp_md); | ||
67 | EVP_DigestUpdate(&md, data, datalen); | ||
68 | EVP_DigestFinal(&md, digest, NULL); | ||
69 | |||
70 | ok = RSA_sign(NID_sha1, digest, dlen, sig, &len, key->rsa); | ||
71 | memset(digest, 'd', dlen); | ||
72 | xfree(digest); | ||
73 | |||
74 | if (ok != 1) { | ||
75 | int ecode = ERR_get_error(); | ||
76 | error("ssh_rsa_sign: RSA_sign failed: %s", ERR_error_string(ecode, NULL)); | ||
77 | xfree(sig); | ||
78 | return -1; | ||
79 | } | ||
80 | if (len < slen) { | ||
81 | int diff = slen - len; | ||
82 | debug("slen %d > len %d", slen, len); | ||
83 | memmove(sig + diff, sig, len); | ||
84 | memset(sig, 0, diff); | ||
85 | } else if (len > slen) { | ||
86 | error("ssh_rsa_sign: slen %d slen2 %d", slen, len); | ||
87 | xfree(sig); | ||
88 | return -1; | ||
89 | } | ||
90 | /* encode signature */ | ||
91 | buffer_init(&b); | ||
92 | buffer_put_cstring(&b, "ssh-rsa"); | ||
93 | buffer_put_string(&b, sig, slen); | ||
94 | len = buffer_len(&b); | ||
95 | ret = xmalloc(len); | ||
96 | memcpy(ret, buffer_ptr(&b), len); | ||
97 | buffer_free(&b); | ||
98 | memset(sig, 's', slen); | ||
99 | xfree(sig); | ||
100 | |||
101 | if (lenp != NULL) | ||
102 | *lenp = len; | ||
103 | if (sigp != NULL) | ||
104 | *sigp = ret; | ||
105 | debug2("ssh_rsa_sign: done"); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | int | ||
110 | ssh_rsa_verify( | ||
111 | Key *key, | ||
112 | unsigned char *signature, int signaturelen, | ||
113 | unsigned char *data, int datalen) | ||
114 | { | ||
115 | Buffer b; | ||
116 | EVP_MD *evp_md = EVP_sha1(); | ||
117 | EVP_MD_CTX md; | ||
118 | char *ktype; | ||
119 | unsigned char *sigblob, *digest; | ||
120 | unsigned int len, dlen; | ||
121 | int rlen; | ||
122 | int ret; | ||
123 | |||
124 | if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) { | ||
125 | error("ssh_rsa_verify: no RSA key"); | ||
126 | return -1; | ||
127 | } | ||
128 | buffer_init(&b); | ||
129 | buffer_append(&b, (char *) signature, signaturelen); | ||
130 | ktype = buffer_get_string(&b, NULL); | ||
131 | if (strcmp("ssh-rsa", ktype) != 0) { | ||
132 | error("ssh_rsa_verify: cannot handle type %s", ktype); | ||
133 | buffer_free(&b); | ||
134 | xfree(ktype); | ||
135 | return -1; | ||
136 | } | ||
137 | xfree(ktype); | ||
138 | sigblob = (unsigned char *)buffer_get_string(&b, &len); | ||
139 | rlen = buffer_len(&b); | ||
140 | buffer_free(&b); | ||
141 | if(rlen != 0) { | ||
142 | error("ssh_rsa_verify: remaining bytes in signature %d", rlen); | ||
143 | return -1; | ||
144 | } | ||
145 | |||
146 | dlen = evp_md->md_size; | ||
147 | digest = xmalloc(dlen); | ||
148 | EVP_DigestInit(&md, evp_md); | ||
149 | EVP_DigestUpdate(&md, data, datalen); | ||
150 | EVP_DigestFinal(&md, digest, NULL); | ||
151 | |||
152 | ret = RSA_verify(NID_sha1, digest, dlen, sigblob, len, key->rsa); | ||
153 | memset(digest, 'd', dlen); | ||
154 | xfree(digest); | ||
155 | memset(sigblob, 's', len); | ||
156 | xfree(sigblob); | ||
157 | if (ret == 0) { | ||
158 | int ecode = ERR_get_error(); | ||
159 | error("ssh_rsa_verify: RSA_verify failed: %s", ERR_error_string(ecode, NULL)); | ||
160 | } | ||
161 | debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); | ||
162 | return ret; | ||
163 | } | ||
diff --git a/ssh-rsa.h b/ssh-rsa.h new file mode 100644 index 000000000..29a0c029c --- /dev/null +++ b/ssh-rsa.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000 Markus Friedl. 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 SSH_RSA_H | ||
25 | #define SSH_RSA_H | ||
26 | |||
27 | int | ||
28 | ssh_rsa_sign( | ||
29 | Key *key, | ||
30 | unsigned char **sigp, int *lenp, | ||
31 | unsigned char *data, int datalen); | ||
32 | |||
33 | int | ||
34 | ssh_rsa_verify( | ||
35 | Key *key, | ||
36 | unsigned char *signature, int signaturelen, | ||
37 | unsigned char *data, int datalen); | ||
38 | |||
39 | #endif | ||
@@ -34,7 +34,7 @@ | |||
34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | .\" | 36 | .\" |
37 | .\" $OpenBSD: ssh.1,v 1.64 2000/10/16 21:46:31 markus Exp $ | 37 | .\" $OpenBSD: ssh.1,v 1.68 2000/11/12 19:50:38 markus Exp $ |
38 | .Dd September 25, 1999 | 38 | .Dd September 25, 1999 |
39 | .Dt SSH 1 | 39 | .Dt SSH 1 |
40 | .Os | 40 | .Os |
@@ -209,9 +209,9 @@ At first, the client attempts to authenticate using the public key method. | |||
209 | If this method fails password authentication is tried. | 209 | If this method fails password authentication is tried. |
210 | .Pp | 210 | .Pp |
211 | The public key method is similar to RSA authentication described | 211 | The public key method is similar to RSA authentication described |
212 | in the previous section except that the DSA algorithm is used | 212 | in the previous section except that the DSA or RSA algorithm is used |
213 | instead of the patented RSA algorithm. | 213 | instead. |
214 | The client uses his private DSA key | 214 | The client uses his private key |
215 | .Pa $HOME/.ssh/id_dsa | 215 | .Pa $HOME/.ssh/id_dsa |
216 | to sign the session identifier and sends the result to the server. | 216 | to sign the session identifier and sends the result to the server. |
217 | The server checks whether the matching public key is listed in | 217 | The server checks whether the matching public key is listed in |
@@ -331,7 +331,7 @@ identifications for all hosts it has ever been used with. | |||
331 | RSA host keys are stored in | 331 | RSA host keys are stored in |
332 | .Pa $HOME/.ssh/known_hosts | 332 | .Pa $HOME/.ssh/known_hosts |
333 | and | 333 | and |
334 | DSA host keys are stored in | 334 | host keys used in the protocol version 2 are stored in |
335 | .Pa $HOME/.ssh/known_hosts2 | 335 | .Pa $HOME/.ssh/known_hosts2 |
336 | in the user's home directory. | 336 | in the user's home directory. |
337 | Additionally, the files | 337 | Additionally, the files |
@@ -352,7 +352,8 @@ The | |||
352 | .Cm StrictHostKeyChecking | 352 | .Cm StrictHostKeyChecking |
353 | option (see below) can be used to prevent logins to machines whose | 353 | option (see below) can be used to prevent logins to machines whose |
354 | host key is not known or has changed. | 354 | host key is not known or has changed. |
355 | .Sh OPTIONS | 355 | .Pp |
356 | The options are as follows: | ||
356 | .Bl -tag -width Ds | 357 | .Bl -tag -width Ds |
357 | .It Fl a | 358 | .It Fl a |
358 | Disables forwarding of the authentication agent connection. | 359 | Disables forwarding of the authentication agent connection. |
@@ -407,7 +408,7 @@ something like | |||
407 | Allows remote hosts to connect to local forwarded ports. | 408 | Allows remote hosts to connect to local forwarded ports. |
408 | .It Fl i Ar identity_file | 409 | .It Fl i Ar identity_file |
409 | Selects the file from which the identity (private key) for | 410 | Selects the file from which the identity (private key) for |
410 | RSA authentication is read. | 411 | RSA or DSA authentication is read. |
411 | Default is | 412 | Default is |
412 | .Pa $HOME/.ssh/identity | 413 | .Pa $HOME/.ssh/identity |
413 | in the user's home directory. | 414 | in the user's home directory. |
@@ -552,6 +553,22 @@ Forces | |||
552 | .Nm | 553 | .Nm |
553 | to use IPv6 addresses only. | 554 | to use IPv6 addresses only. |
554 | .El | 555 | .El |
556 | .Pp | ||
557 | If | ||
558 | .Nm | ||
559 | is not invoked with one of the standard program names | ||
560 | .Pf ( Dq ssh , | ||
561 | .Dq slogin , | ||
562 | .Dq rsh , | ||
563 | .Dq rlogin , | ||
564 | or | ||
565 | .Dq remsh ) , | ||
566 | it uses this name as its | ||
567 | .Ar hostname | ||
568 | argument. | ||
569 | This is consistent with traditional | ||
570 | .Xr rsh 1 | ||
571 | behavior. | ||
555 | .Sh CONFIGURATION FILES | 572 | .Sh CONFIGURATION FILES |
556 | .Nm | 573 | .Nm |
557 | obtains configuration data from the following sources (in this order): | 574 | obtains configuration data from the following sources (in this order): |
@@ -660,14 +677,12 @@ Specifies the number of tries (one per second) to make before falling | |||
660 | back to rsh or exiting. | 677 | back to rsh or exiting. |
661 | The argument must be an integer. | 678 | The argument must be an integer. |
662 | This may be useful in scripts if the connection sometimes fails. | 679 | This may be useful in scripts if the connection sometimes fails. |
663 | .It Cm DSAAuthentication | 680 | .It Cm PubkeyAuthentication |
664 | Specifies whether to try DSA authentication. | 681 | Specifies whether to try public key authentication. |
665 | The argument to this keyword must be | 682 | The argument to this keyword must be |
666 | .Dq yes | 683 | .Dq yes |
667 | or | 684 | or |
668 | .Dq no . | 685 | .Dq no . |
669 | DSA authentication will only be | ||
670 | attempted if a DSA identity file exists. | ||
671 | Note that this option applies to protocol version 2 only. | 686 | Note that this option applies to protocol version 2 only. |
672 | .It Cm EscapeChar | 687 | .It Cm EscapeChar |
673 | Sets the escape character (default: | 688 | Sets the escape character (default: |
@@ -745,16 +760,6 @@ syntax to refer to a user's home directory. | |||
745 | It is possible to have | 760 | It is possible to have |
746 | multiple identity files specified in configuration files; all these | 761 | multiple identity files specified in configuration files; all these |
747 | identities will be tried in sequence. | 762 | identities will be tried in sequence. |
748 | .It Cm IdentityFile2 | ||
749 | Specifies the file from which the user's DSA authentication identity | ||
750 | is read (default | ||
751 | .Pa $HOME/.ssh/id_dsa | ||
752 | in the user's home directory). | ||
753 | The file name may use the tilde | ||
754 | syntax to refer to a user's home directory. | ||
755 | It is possible to have | ||
756 | multiple identity files specified in configuration files; all these | ||
757 | identities will be tried in sequence. | ||
758 | .It Cm KeepAlive | 763 | .It Cm KeepAlive |
759 | Specifies whether the system should send keepalive messages to the | 764 | Specifies whether the system should send keepalive messages to the |
760 | other side. | 765 | other side. |
@@ -1096,7 +1101,7 @@ spaces). | |||
1096 | This file is not highly sensitive, but the recommended | 1101 | This file is not highly sensitive, but the recommended |
1097 | permissions are read/write for the user, and not accessible by others. | 1102 | permissions are read/write for the user, and not accessible by others. |
1098 | .It Pa $HOME/.ssh/authorized_keys2 | 1103 | .It Pa $HOME/.ssh/authorized_keys2 |
1099 | Lists the DSA keys that can be used for logging in as this user. | 1104 | Lists the public keys (DSA/RSA) that can be used for logging in as this user. |
1100 | This file is not highly sensitive, but the recommended | 1105 | This file is not highly sensitive, but the recommended |
1101 | permissions are read/write for the user, and not accessible by others. | 1106 | permissions are read/write for the user, and not accessible by others. |
1102 | .It Pa /etc/ssh_known_hosts, /etc/ssh_known_hosts2 | 1107 | .It Pa /etc/ssh_known_hosts, /etc/ssh_known_hosts2 |
@@ -1104,7 +1109,7 @@ Systemwide list of known host keys. | |||
1104 | .Pa /etc/ssh_known_hosts | 1109 | .Pa /etc/ssh_known_hosts |
1105 | contains RSA and | 1110 | contains RSA and |
1106 | .Pa /etc/ssh_known_hosts2 | 1111 | .Pa /etc/ssh_known_hosts2 |
1107 | contains DSA keys. | 1112 | contains DSA or RSA keys for protocol version 2. |
1108 | These files should be prepared by the | 1113 | These files should be prepared by the |
1109 | system administrator to contain the public host keys of all machines in the | 1114 | system administrator to contain the public host keys of all machines in the |
1110 | organization. | 1115 | organization. |
@@ -1219,7 +1224,7 @@ above. | |||
1219 | A version of this library which includes support for the RSA algorithm | 1224 | A version of this library which includes support for the RSA algorithm |
1220 | is required for proper operation. | 1225 | is required for proper operation. |
1221 | .El | 1226 | .El |
1222 | .Sh AUTHOR | 1227 | .Sh AUTHORS |
1223 | OpenSSH | 1228 | OpenSSH |
1224 | is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen, | 1229 | is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen, |
1225 | but with bugs removed and newer features re-added. | 1230 | but with bugs removed and newer features re-added. |
@@ -39,11 +39,12 @@ | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | #include "includes.h" | 41 | #include "includes.h" |
42 | RCSID("$OpenBSD: ssh.c,v 1.69 2000/10/27 07:32:19 markus Exp $"); | 42 | RCSID("$OpenBSD: ssh.c,v 1.72 2000/11/12 19:50:38 markus Exp $"); |
43 | 43 | ||
44 | #include <openssl/evp.h> | 44 | #include <openssl/evp.h> |
45 | #include <openssl/dsa.h> | 45 | #include <openssl/dsa.h> |
46 | #include <openssl/rsa.h> | 46 | #include <openssl/rsa.h> |
47 | #include <openssl/err.h> | ||
47 | 48 | ||
48 | #include "xmalloc.h" | 49 | #include "xmalloc.h" |
49 | #include "ssh.h" | 50 | #include "ssh.h" |
@@ -218,8 +219,9 @@ rsh_connect(char *host, char *user, Buffer * command) | |||
218 | exit(1); | 219 | exit(1); |
219 | } | 220 | } |
220 | 221 | ||
221 | int ssh_session(void); | 222 | int ssh_session(void); |
222 | int ssh_session2(void); | 223 | int ssh_session2(void); |
224 | int guess_identity_file_type(const char *filename); | ||
223 | 225 | ||
224 | /* | 226 | /* |
225 | * Main program for the ssh client. | 227 | * Main program for the ssh client. |
@@ -370,14 +372,13 @@ main(int ac, char **av) | |||
370 | case 'i': | 372 | case 'i': |
371 | if (stat(optarg, &st) < 0) { | 373 | if (stat(optarg, &st) < 0) { |
372 | fprintf(stderr, "Warning: Identity file %s does not exist.\n", | 374 | fprintf(stderr, "Warning: Identity file %s does not exist.\n", |
373 | optarg); | 375 | optarg); |
374 | break; | 376 | break; |
375 | } | 377 | } |
376 | if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES) | 378 | if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES) |
377 | fatal("Too many identity files specified (max %d)", | 379 | fatal("Too many identity files specified (max %d)", |
378 | SSH_MAX_IDENTITY_FILES); | 380 | SSH_MAX_IDENTITY_FILES); |
379 | options.identity_files[options.num_identity_files++] = | 381 | options.identity_files[options.num_identity_files++] = xstrdup(optarg); |
380 | xstrdup(optarg); | ||
381 | break; | 382 | break; |
382 | case 't': | 383 | case 't': |
383 | tty_flag = 1; | 384 | tty_flag = 1; |
@@ -487,6 +488,7 @@ main(int ac, char **av) | |||
487 | usage(); | 488 | usage(); |
488 | 489 | ||
489 | SSLeay_add_all_algorithms(); | 490 | SSLeay_add_all_algorithms(); |
491 | ERR_load_crypto_strings(); | ||
490 | 492 | ||
491 | /* Initialize the command to execute on remote host. */ | 493 | /* Initialize the command to execute on remote host. */ |
492 | buffer_init(&command); | 494 | buffer_init(&command); |
@@ -563,20 +565,6 @@ main(int ac, char **av) | |||
563 | /* reinit */ | 565 | /* reinit */ |
564 | log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0); | 566 | log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0); |
565 | 567 | ||
566 | /* check if RSA support exists */ | ||
567 | if ((options.protocol & SSH_PROTO_1) && | ||
568 | rsa_alive() == 0) { | ||
569 | log("%s: no RSA support in libssl and libcrypto. See ssl(8).", | ||
570 | __progname); | ||
571 | log("Disabling protocol version 1"); | ||
572 | options.protocol &= ~ (SSH_PROTO_1|SSH_PROTO_1_PREFERRED); | ||
573 | } | ||
574 | if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) { | ||
575 | fprintf(stderr, "%s: No protocol version available.\n", | ||
576 | __progname); | ||
577 | exit(1); | ||
578 | } | ||
579 | |||
580 | if (options.user == NULL) | 568 | if (options.user == NULL) |
581 | options.user = xstrdup(pw->pw_name); | 569 | options.user = xstrdup(pw->pw_name); |
582 | 570 | ||
@@ -589,6 +577,8 @@ main(int ac, char **av) | |||
589 | if (!options.use_privileged_port) { | 577 | if (!options.use_privileged_port) { |
590 | #else | 578 | #else |
591 | if (original_effective_uid != 0 || !options.use_privileged_port) { | 579 | if (original_effective_uid != 0 || !options.use_privileged_port) { |
580 | debug("Rhosts Authentication methods disabled, " | ||
581 | "originating port will not be trusted."); | ||
592 | #endif | 582 | #endif |
593 | options.rhosts_authentication = 0; | 583 | options.rhosts_authentication = 0; |
594 | options.rhosts_rsa_authentication = 0; | 584 | options.rhosts_rsa_authentication = 0; |
@@ -635,7 +625,7 @@ main(int ac, char **av) | |||
635 | if (ok && (options.protocol & SSH_PROTO_1)) { | 625 | if (ok && (options.protocol & SSH_PROTO_1)) { |
636 | Key k; | 626 | Key k; |
637 | host_private_key = RSA_new(); | 627 | host_private_key = RSA_new(); |
638 | k.type = KEY_RSA; | 628 | k.type = KEY_RSA1; |
639 | k.rsa = host_private_key; | 629 | k.rsa = host_private_key; |
640 | if (load_private_key(HOST_KEY_FILE, "", &k, NULL)) | 630 | if (load_private_key(HOST_KEY_FILE, "", &k, NULL)) |
641 | host_private_key_loaded = 1; | 631 | host_private_key_loaded = 1; |
@@ -682,23 +672,23 @@ main(int ac, char **av) | |||
682 | } | 672 | } |
683 | exit(1); | 673 | exit(1); |
684 | } | 674 | } |
685 | /* Expand ~ in options.identity_files. */ | 675 | /* Expand ~ in options.identity_files, known host file names. */ |
686 | /* XXX mem-leaks */ | 676 | /* XXX mem-leaks */ |
687 | for (i = 0; i < options.num_identity_files; i++) | 677 | for (i = 0; i < options.num_identity_files; i++) { |
688 | options.identity_files[i] = | 678 | options.identity_files[i] = |
689 | tilde_expand_filename(options.identity_files[i], original_real_uid); | 679 | tilde_expand_filename(options.identity_files[i], original_real_uid); |
690 | for (i = 0; i < options.num_identity_files2; i++) | 680 | options.identity_files_type[i] = guess_identity_file_type(options.identity_files[i]); |
691 | options.identity_files2[i] = | 681 | debug("identity file %s type %d", options.identity_files[i], |
692 | tilde_expand_filename(options.identity_files2[i], original_real_uid); | 682 | options.identity_files_type[i]); |
693 | /* Expand ~ in known host file names. */ | 683 | } |
694 | options.system_hostfile = tilde_expand_filename(options.system_hostfile, | 684 | options.system_hostfile = |
695 | original_real_uid); | 685 | tilde_expand_filename(options.system_hostfile, original_real_uid); |
696 | options.user_hostfile = tilde_expand_filename(options.user_hostfile, | 686 | options.user_hostfile = |
697 | original_real_uid); | 687 | tilde_expand_filename(options.user_hostfile, original_real_uid); |
698 | options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2, | 688 | options.system_hostfile2 = |
699 | original_real_uid); | 689 | tilde_expand_filename(options.system_hostfile2, original_real_uid); |
700 | options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2, | 690 | options.user_hostfile2 = |
701 | original_real_uid); | 691 | tilde_expand_filename(options.user_hostfile2, original_real_uid); |
702 | 692 | ||
703 | /* Log into the remote system. This never returns if the login fails. */ | 693 | /* Log into the remote system. This never returns if the login fails. */ |
704 | ssh_login(host_private_key_loaded, host_private_key, | 694 | ssh_login(host_private_key_loaded, host_private_key, |
@@ -752,16 +742,57 @@ x11_get_proto(char *proto, int proto_len, char *data, int data_len) | |||
752 | } | 742 | } |
753 | } | 743 | } |
754 | 744 | ||
745 | void | ||
746 | ssh_init_forwarding(void) | ||
747 | { | ||
748 | int i; | ||
749 | /* Initiate local TCP/IP port forwardings. */ | ||
750 | for (i = 0; i < options.num_local_forwards; i++) { | ||
751 | debug("Connections to local port %d forwarded to remote address %.200s:%d", | ||
752 | options.local_forwards[i].port, | ||
753 | options.local_forwards[i].host, | ||
754 | options.local_forwards[i].host_port); | ||
755 | channel_request_local_forwarding( | ||
756 | options.local_forwards[i].port, | ||
757 | options.local_forwards[i].host, | ||
758 | options.local_forwards[i].host_port, | ||
759 | options.gateway_ports); | ||
760 | } | ||
761 | |||
762 | /* Initiate remote TCP/IP port forwardings. */ | ||
763 | for (i = 0; i < options.num_remote_forwards; i++) { | ||
764 | debug("Connections to remote port %d forwarded to local address %.200s:%d", | ||
765 | options.remote_forwards[i].port, | ||
766 | options.remote_forwards[i].host, | ||
767 | options.remote_forwards[i].host_port); | ||
768 | channel_request_remote_forwarding( | ||
769 | options.remote_forwards[i].port, | ||
770 | options.remote_forwards[i].host, | ||
771 | options.remote_forwards[i].host_port); | ||
772 | } | ||
773 | } | ||
774 | |||
775 | void | ||
776 | check_agent_present(void) | ||
777 | { | ||
778 | if (options.forward_agent) { | ||
779 | /* Clear agent forwarding if we don\'t have an agent. */ | ||
780 | int authfd = ssh_get_authentication_socket(); | ||
781 | if (authfd < 0) | ||
782 | options.forward_agent = 0; | ||
783 | else | ||
784 | ssh_close_authentication_socket(authfd); | ||
785 | } | ||
786 | } | ||
787 | |||
755 | int | 788 | int |
756 | ssh_session(void) | 789 | ssh_session(void) |
757 | { | 790 | { |
758 | int type; | 791 | int type; |
759 | int i; | ||
760 | int plen; | 792 | int plen; |
761 | int interactive = 0; | 793 | int interactive = 0; |
762 | int have_tty = 0; | 794 | int have_tty = 0; |
763 | struct winsize ws; | 795 | struct winsize ws; |
764 | int authfd; | ||
765 | char *cp; | 796 | char *cp; |
766 | 797 | ||
767 | /* Enable compression if requested. */ | 798 | /* Enable compression if requested. */ |
@@ -845,14 +876,10 @@ ssh_session(void) | |||
845 | /* Tell the packet module whether this is an interactive session. */ | 876 | /* Tell the packet module whether this is an interactive session. */ |
846 | packet_set_interactive(interactive, options.keepalives); | 877 | packet_set_interactive(interactive, options.keepalives); |
847 | 878 | ||
848 | /* Clear agent forwarding if we don\'t have an agent. */ | ||
849 | authfd = ssh_get_authentication_socket(); | ||
850 | if (authfd < 0) | ||
851 | options.forward_agent = 0; | ||
852 | else | ||
853 | ssh_close_authentication_socket(authfd); | ||
854 | 879 | ||
855 | /* Request authentication agent forwarding if appropriate. */ | 880 | /* Request authentication agent forwarding if appropriate. */ |
881 | check_agent_present(); | ||
882 | |||
856 | if (options.forward_agent) { | 883 | if (options.forward_agent) { |
857 | debug("Requesting authentication agent forwarding."); | 884 | debug("Requesting authentication agent forwarding."); |
858 | auth_request_forwarding(); | 885 | auth_request_forwarding(); |
@@ -863,28 +890,9 @@ ssh_session(void) | |||
863 | if (type != SSH_SMSG_SUCCESS) | 890 | if (type != SSH_SMSG_SUCCESS) |
864 | log("Warning: Remote host denied authentication agent forwarding."); | 891 | log("Warning: Remote host denied authentication agent forwarding."); |
865 | } | 892 | } |
866 | /* Initiate local TCP/IP port forwardings. */ | ||
867 | for (i = 0; i < options.num_local_forwards; i++) { | ||
868 | debug("Connections to local port %d forwarded to remote address %.200s:%d", | ||
869 | options.local_forwards[i].port, | ||
870 | options.local_forwards[i].host, | ||
871 | options.local_forwards[i].host_port); | ||
872 | channel_request_local_forwarding(options.local_forwards[i].port, | ||
873 | options.local_forwards[i].host, | ||
874 | options.local_forwards[i].host_port, | ||
875 | options.gateway_ports); | ||
876 | } | ||
877 | 893 | ||
878 | /* Initiate remote TCP/IP port forwardings. */ | 894 | /* Initiate port forwardings. */ |
879 | for (i = 0; i < options.num_remote_forwards; i++) { | 895 | ssh_init_forwarding(); |
880 | debug("Connections to remote port %d forwarded to local address %.200s:%d", | ||
881 | options.remote_forwards[i].port, | ||
882 | options.remote_forwards[i].host, | ||
883 | options.remote_forwards[i].host_port); | ||
884 | channel_request_remote_forwarding(options.remote_forwards[i].port, | ||
885 | options.remote_forwards[i].host, | ||
886 | options.remote_forwards[i].host_port); | ||
887 | } | ||
888 | 896 | ||
889 | /* If requested, let ssh continue in the background. */ | 897 | /* If requested, let ssh continue in the background. */ |
890 | if (fork_after_authentication_flag) | 898 | if (fork_after_authentication_flag) |
@@ -915,27 +923,10 @@ ssh_session(void) | |||
915 | return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0); | 923 | return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0); |
916 | } | 924 | } |
917 | 925 | ||
918 | void | ||
919 | init_local_fwd(void) | ||
920 | { | ||
921 | int i; | ||
922 | /* Initiate local TCP/IP port forwardings. */ | ||
923 | for (i = 0; i < options.num_local_forwards; i++) { | ||
924 | debug("Connections to local port %d forwarded to remote address %.200s:%d", | ||
925 | options.local_forwards[i].port, | ||
926 | options.local_forwards[i].host, | ||
927 | options.local_forwards[i].host_port); | ||
928 | channel_request_local_forwarding(options.local_forwards[i].port, | ||
929 | options.local_forwards[i].host, | ||
930 | options.local_forwards[i].host_port, | ||
931 | options.gateway_ports); | ||
932 | } | ||
933 | } | ||
934 | |||
935 | extern void client_set_session_ident(int id); | 926 | extern void client_set_session_ident(int id); |
936 | 927 | ||
937 | void | 928 | void |
938 | client_init(int id, void *arg) | 929 | ssh_session2_callback(int id, void *arg) |
939 | { | 930 | { |
940 | int len; | 931 | int len; |
941 | debug("client_init id %d arg %d", id, (int)arg); | 932 | debug("client_init id %d arg %d", id, (int)arg); |
@@ -974,6 +965,13 @@ client_init(int id, void *arg) | |||
974 | /* XXX wait for reply */ | 965 | /* XXX wait for reply */ |
975 | } | 966 | } |
976 | 967 | ||
968 | check_agent_present(); | ||
969 | if (options.forward_agent) { | ||
970 | debug("Requesting authentication agent forwarding."); | ||
971 | channel_request_start(id, "auth-agent-req@openssh.com", 0); | ||
972 | packet_send(); | ||
973 | } | ||
974 | |||
977 | len = buffer_len(&command); | 975 | len = buffer_len(&command); |
978 | if (len > 0) { | 976 | if (len > 0) { |
979 | if (len > 900) | 977 | if (len > 900) |
@@ -1016,8 +1014,8 @@ ssh_session2(void) | |||
1016 | if (!isatty(err)) | 1014 | if (!isatty(err)) |
1017 | set_nonblock(err); | 1015 | set_nonblock(err); |
1018 | 1016 | ||
1019 | /* should be pre-session */ | 1017 | /* XXX should be pre-session */ |
1020 | init_local_fwd(); | 1018 | ssh_init_forwarding(); |
1021 | 1019 | ||
1022 | /* If requested, let ssh continue in the background. */ | 1020 | /* If requested, let ssh continue in the background. */ |
1023 | if (fork_after_authentication_flag) | 1021 | if (fork_after_authentication_flag) |
@@ -1036,7 +1034,28 @@ ssh_session2(void) | |||
1036 | xstrdup("client-session"), /*nonblock*/0); | 1034 | xstrdup("client-session"), /*nonblock*/0); |
1037 | 1035 | ||
1038 | channel_open(id); | 1036 | channel_open(id); |
1039 | channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0); | 1037 | channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, |
1038 | ssh_session2_callback, (void *)0); | ||
1040 | 1039 | ||
1041 | return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id); | 1040 | return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id); |
1042 | } | 1041 | } |
1042 | |||
1043 | int | ||
1044 | guess_identity_file_type(const char *filename) | ||
1045 | { | ||
1046 | struct stat st; | ||
1047 | Key *public; | ||
1048 | int type = KEY_RSA1; /* default */ | ||
1049 | |||
1050 | if (stat(filename, &st) < 0) { | ||
1051 | perror(filename); | ||
1052 | return KEY_UNSPEC; | ||
1053 | } | ||
1054 | public = key_new(type); | ||
1055 | if (!load_public_key(filename, public, NULL)) { | ||
1056 | /* ok, so we will assume this is 'some' key */ | ||
1057 | type = KEY_UNSPEC; | ||
1058 | } | ||
1059 | key_free(public); | ||
1060 | return type; | ||
1061 | } | ||
diff --git a/ssh_config b/ssh_config index cb360d04b..fdac1313c 100644 --- a/ssh_config +++ b/ssh_config | |||
@@ -13,9 +13,9 @@ | |||
13 | # Site-wide defaults for various options | 13 | # Site-wide defaults for various options |
14 | 14 | ||
15 | # Host * | 15 | # Host * |
16 | # ForwardAgent yes | 16 | # ForwardAgent no |
17 | # ForwardX11 yes | 17 | # ForwardX11 no |
18 | # RhostsAuthentication yes | 18 | # RhostsAuthentication no |
19 | # RhostsRSAAuthentication yes | 19 | # RhostsRSAAuthentication yes |
20 | # RSAAuthentication yes | 20 | # RSAAuthentication yes |
21 | # PasswordAuthentication yes | 21 | # PasswordAuthentication yes |
@@ -23,9 +23,12 @@ | |||
23 | # UseRsh no | 23 | # UseRsh no |
24 | # BatchMode no | 24 | # BatchMode no |
25 | # CheckHostIP yes | 25 | # CheckHostIP yes |
26 | # StrictHostKeyChecking no | 26 | # StrictHostKeyChecking yes |
27 | # IdentityFile ~/.ssh/identity | 27 | # IdentityFile ~/.ssh/identity |
28 | # IdentityFile ~/.ssh/id_dsa | ||
29 | # IdentityFile ~/.ssh/id_rsa1 | ||
30 | # IdentityFile ~/.ssh/id_rsa2 | ||
28 | # Port 22 | 31 | # Port 22 |
29 | # Protocol 2,1 | 32 | # Protocol 1,2 |
30 | # Cipher blowfish | 33 | # Cipher blowfish |
31 | # EscapeChar ~ | 34 | # EscapeChar ~ |
diff --git a/sshconnect.c b/sshconnect.c index d6072b36c..12ca69fd6 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -13,7 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include "includes.h" | 15 | #include "includes.h" |
16 | RCSID("$OpenBSD: sshconnect.c,v 1.79 2000/09/17 15:52:51 markus Exp $"); | 16 | RCSID("$OpenBSD: sshconnect.c,v 1.81 2000/11/06 23:16:35 markus Exp $"); |
17 | 17 | ||
18 | #include <openssl/bn.h> | 18 | #include <openssl/bn.h> |
19 | #include <openssl/dsa.h> | 19 | #include <openssl/dsa.h> |
@@ -249,9 +249,9 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | |||
249 | /* Create a socket for connecting. */ | 249 | /* Create a socket for connecting. */ |
250 | sock = ssh_create_socket(original_real_uid, | 250 | sock = ssh_create_socket(original_real_uid, |
251 | #ifdef HAVE_CYGWIN | 251 | #ifdef HAVE_CYGWIN |
252 | !anonymous && port < IPPORT_RESERVED, | 252 | !anonymous, |
253 | #else | 253 | #else |
254 | !anonymous && geteuid() == 0 && port < IPPORT_RESERVED, | 254 | !anonymous && geteuid() == 0, |
255 | #endif | 255 | #endif |
256 | ai->ai_family); | 256 | ai->ai_family); |
257 | if (sock < 0) | 257 | if (sock < 0) |
@@ -321,6 +321,7 @@ ssh_exchange_identification() | |||
321 | int remote_major, remote_minor, i, mismatch; | 321 | int remote_major, remote_minor, i, mismatch; |
322 | int connection_in = packet_get_connection_in(); | 322 | int connection_in = packet_get_connection_in(); |
323 | int connection_out = packet_get_connection_out(); | 323 | int connection_out = packet_get_connection_out(); |
324 | int minor1 = PROTOCOL_MINOR_1; | ||
324 | 325 | ||
325 | /* Read other side\'s version identification. */ | 326 | /* Read other side\'s version identification. */ |
326 | for (;;) { | 327 | for (;;) { |
@@ -374,9 +375,10 @@ ssh_exchange_identification() | |||
374 | } | 375 | } |
375 | if (remote_minor < 3) { | 376 | if (remote_minor < 3) { |
376 | fatal("Remote machine has too old SSH software version."); | 377 | fatal("Remote machine has too old SSH software version."); |
377 | } else if (remote_minor == 3) { | 378 | } else if (remote_minor == 3 || remote_minor == 4) { |
378 | /* We speak 1.3, too. */ | 379 | /* We speak 1.3, too. */ |
379 | enable_compat13(); | 380 | enable_compat13(); |
381 | minor1 = 3; | ||
380 | if (options.forward_agent) { | 382 | if (options.forward_agent) { |
381 | log("Agent forwarding disabled for protocol 1.3"); | 383 | log("Agent forwarding disabled for protocol 1.3"); |
382 | options.forward_agent = 0; | 384 | options.forward_agent = 0; |
@@ -402,7 +404,7 @@ ssh_exchange_identification() | |||
402 | /* Send our own protocol version identification. */ | 404 | /* Send our own protocol version identification. */ |
403 | snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", | 405 | snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", |
404 | compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, | 406 | compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, |
405 | compat20 ? PROTOCOL_MINOR_2 : PROTOCOL_MINOR_1, | 407 | compat20 ? PROTOCOL_MINOR_2 : minor1, |
406 | SSH_VERSION); | 408 | SSH_VERSION); |
407 | if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf)) | 409 | if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf)) |
408 | fatal("write: %.100s", strerror(errno)); | 410 | fatal("write: %.100s", strerror(errno)); |
diff --git a/sshconnect1.c b/sshconnect1.c index ce560791c..227e10b4b 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.8 2000/10/12 09:59:19 markus Exp $"); | 16 | RCSID("$OpenBSD: sshconnect1.c,v 1.9 2000/11/12 19:50:38 markus Exp $"); |
17 | 17 | ||
18 | #include <openssl/bn.h> | 18 | #include <openssl/bn.h> |
19 | #include <openssl/dsa.h> | 19 | #include <openssl/dsa.h> |
@@ -62,7 +62,7 @@ try_agent_authentication() | |||
62 | return 0; | 62 | return 0; |
63 | 63 | ||
64 | challenge = BN_new(); | 64 | challenge = BN_new(); |
65 | key = key_new(KEY_RSA); | 65 | key = key_new(KEY_RSA1); |
66 | 66 | ||
67 | /* Loop through identities served by the agent. */ | 67 | /* Loop through identities served by the agent. */ |
68 | for (key = ssh_get_first_identity(auth, &comment, 1); | 68 | for (key = ssh_get_first_identity(auth, &comment, 1); |
@@ -196,7 +196,7 @@ try_rsa_authentication(const char *authfile) | |||
196 | int plen, clen; | 196 | int plen, clen; |
197 | 197 | ||
198 | /* Try to load identification for the authentication key. */ | 198 | /* Try to load identification for the authentication key. */ |
199 | public = key_new(KEY_RSA); | 199 | public = key_new(KEY_RSA1); |
200 | if (!load_public_key(authfile, public, &comment)) { | 200 | if (!load_public_key(authfile, public, &comment)) { |
201 | key_free(public); | 201 | key_free(public); |
202 | /* Could not load it. Fail. */ | 202 | /* Could not load it. Fail. */ |
@@ -237,7 +237,7 @@ try_rsa_authentication(const char *authfile) | |||
237 | 237 | ||
238 | debug("Received RSA challenge from server."); | 238 | debug("Received RSA challenge from server."); |
239 | 239 | ||
240 | private = key_new(KEY_RSA); | 240 | private = key_new(KEY_RSA1); |
241 | /* | 241 | /* |
242 | * Load the private key. Try first with empty passphrase; if it | 242 | * Load the private key. Try first with empty passphrase; if it |
243 | * fails, ask for a passphrase. | 243 | * fails, ask for a passphrase. |
@@ -760,7 +760,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr) | |||
760 | packet_integrity_check(payload_len, | 760 | packet_integrity_check(payload_len, |
761 | 8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4, | 761 | 8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4, |
762 | SSH_SMSG_PUBLIC_KEY); | 762 | SSH_SMSG_PUBLIC_KEY); |
763 | k.type = KEY_RSA; | 763 | k.type = KEY_RSA1; |
764 | k.rsa = host_key; | 764 | k.rsa = host_key; |
765 | check_host_key(host, hostaddr, &k, | 765 | check_host_key(host, hostaddr, &k, |
766 | options.user_hostfile, options.system_hostfile); | 766 | options.user_hostfile, options.system_hostfile); |
@@ -994,7 +994,8 @@ ssh_userauth( | |||
994 | 994 | ||
995 | /* Try RSA authentication for each identity. */ | 995 | /* Try RSA authentication for each identity. */ |
996 | for (i = 0; i < options.num_identity_files; i++) | 996 | for (i = 0; i < options.num_identity_files; i++) |
997 | if (try_rsa_authentication(options.identity_files[i])) | 997 | if (options.identity_files_type[i] == KEY_RSA1 && |
998 | try_rsa_authentication(options.identity_files[i])) | ||
998 | return; | 999 | return; |
999 | } | 1000 | } |
1000 | /* Try skey authentication if the server supports it. */ | 1001 | /* Try skey authentication if the server supports it. */ |
diff --git a/sshconnect2.c b/sshconnect2.c index 6ba23d445..bb4774aa4 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.27 2000/10/19 16:45:16 provos Exp $"); | 26 | RCSID("$OpenBSD: sshconnect2.c,v 1.28 2000/11/12 19:50:38 markus Exp $"); |
27 | 27 | ||
28 | #include <openssl/bn.h> | 28 | #include <openssl/bn.h> |
29 | #include <openssl/rsa.h> | 29 | #include <openssl/rsa.h> |
@@ -45,7 +45,6 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.27 2000/10/19 16:45:16 provos Exp $"); | |||
45 | #include "kex.h" | 45 | #include "kex.h" |
46 | #include "myproposal.h" | 46 | #include "myproposal.h" |
47 | #include "key.h" | 47 | #include "key.h" |
48 | #include "dsa.h" | ||
49 | #include "sshconnect.h" | 48 | #include "sshconnect.h" |
50 | #include "authfile.h" | 49 | #include "authfile.h" |
51 | #include "cli.h" | 50 | #include "cli.h" |
@@ -196,7 +195,7 @@ ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr, | |||
196 | 195 | ||
197 | /* key, cert */ | 196 | /* key, cert */ |
198 | server_host_key_blob = packet_get_string(&sbloblen); | 197 | server_host_key_blob = packet_get_string(&sbloblen); |
199 | server_host_key = dsa_key_from_blob(server_host_key_blob, sbloblen); | 198 | server_host_key = key_from_blob(server_host_key_blob, sbloblen); |
200 | if (server_host_key == NULL) | 199 | if (server_host_key == NULL) |
201 | fatal("cannot decode server_host_key_blob"); | 200 | fatal("cannot decode server_host_key_blob"); |
202 | 201 | ||
@@ -258,8 +257,8 @@ ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr, | |||
258 | fprintf(stderr, "%02x", (hash[i])&0xff); | 257 | fprintf(stderr, "%02x", (hash[i])&0xff); |
259 | fprintf(stderr, "\n"); | 258 | fprintf(stderr, "\n"); |
260 | #endif | 259 | #endif |
261 | if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1) | 260 | if (key_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1) |
262 | fatal("dsa_verify failed for server_host_key"); | 261 | fatal("key_verify failed for server_host_key"); |
263 | key_free(server_host_key); | 262 | key_free(server_host_key); |
264 | 263 | ||
265 | kex_derive_keys(kex, hash, shared_secret); | 264 | kex_derive_keys(kex, hash, shared_secret); |
@@ -366,7 +365,7 @@ ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr, | |||
366 | 365 | ||
367 | /* key, cert */ | 366 | /* key, cert */ |
368 | server_host_key_blob = packet_get_string(&sbloblen); | 367 | server_host_key_blob = packet_get_string(&sbloblen); |
369 | server_host_key = dsa_key_from_blob(server_host_key_blob, sbloblen); | 368 | server_host_key = key_from_blob(server_host_key_blob, sbloblen); |
370 | if (server_host_key == NULL) | 369 | if (server_host_key == NULL) |
371 | fatal("cannot decode server_host_key_blob"); | 370 | fatal("cannot decode server_host_key_blob"); |
372 | 371 | ||
@@ -429,8 +428,8 @@ ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr, | |||
429 | fprintf(stderr, "%02x", (hash[i])&0xff); | 428 | fprintf(stderr, "%02x", (hash[i])&0xff); |
430 | fprintf(stderr, "\n"); | 429 | fprintf(stderr, "\n"); |
431 | #endif | 430 | #endif |
432 | if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1) | 431 | if (key_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1) |
433 | fatal("dsa_verify failed for server_host_key"); | 432 | fatal("key_verify failed for server_host_key"); |
434 | key_free(server_host_key); | 433 | key_free(server_host_key); |
435 | 434 | ||
436 | kex_derive_keys(kex, hash, shared_secret); | 435 | kex_derive_keys(kex, hash, shared_secret); |
@@ -485,7 +484,7 @@ Authmethod *authmethod_lookup(const char *name); | |||
485 | Authmethod authmethods[] = { | 484 | Authmethod authmethods[] = { |
486 | {"publickey", | 485 | {"publickey", |
487 | userauth_pubkey, | 486 | userauth_pubkey, |
488 | &options.dsa_authentication, | 487 | &options.pubkey_authentication, |
489 | NULL}, | 488 | NULL}, |
490 | {"password", | 489 | {"password", |
491 | userauth_passwd, | 490 | userauth_passwd, |
@@ -653,8 +652,10 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) | |||
653 | int ret = -1; | 652 | int ret = -1; |
654 | int have_sig = 1; | 653 | int have_sig = 1; |
655 | 654 | ||
656 | dsa_make_key_blob(k, &blob, &bloblen); | 655 | if (key_to_blob(k, &blob, &bloblen) == 0) { |
657 | 656 | /* we cannot handle this key */ | |
657 | return 0; | ||
658 | } | ||
658 | /* data to be signed */ | 659 | /* data to be signed */ |
659 | buffer_init(&b); | 660 | buffer_init(&b); |
660 | if (datafellows & SSH_OLD_SESSIONID) { | 661 | if (datafellows & SSH_OLD_SESSIONID) { |
@@ -672,7 +673,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) | |||
672 | authctxt->service); | 673 | authctxt->service); |
673 | buffer_put_cstring(&b, authctxt->method->name); | 674 | buffer_put_cstring(&b, authctxt->method->name); |
674 | buffer_put_char(&b, have_sig); | 675 | buffer_put_char(&b, have_sig); |
675 | buffer_put_cstring(&b, KEX_DSS); | 676 | buffer_put_cstring(&b, key_ssh_name(k)); |
676 | buffer_put_string(&b, blob, bloblen); | 677 | buffer_put_string(&b, blob, bloblen); |
677 | 678 | ||
678 | /* generate signature */ | 679 | /* generate signature */ |
@@ -682,7 +683,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) | |||
682 | buffer_free(&b); | 683 | buffer_free(&b); |
683 | return 0; | 684 | return 0; |
684 | } | 685 | } |
685 | #ifdef DEBUG_DSS | 686 | #ifdef DEBUG_PK |
686 | buffer_dump(&b); | 687 | buffer_dump(&b); |
687 | #endif | 688 | #endif |
688 | if (datafellows & SSH_BUG_PUBKEYAUTH) { | 689 | if (datafellows & SSH_BUG_PUBKEYAUTH) { |
@@ -693,7 +694,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) | |||
693 | buffer_put_cstring(&b, authctxt->service); | 694 | buffer_put_cstring(&b, authctxt->service); |
694 | buffer_put_cstring(&b, authctxt->method->name); | 695 | buffer_put_cstring(&b, authctxt->method->name); |
695 | buffer_put_char(&b, have_sig); | 696 | buffer_put_char(&b, have_sig); |
696 | buffer_put_cstring(&b, KEX_DSS); | 697 | buffer_put_cstring(&b, key_ssh_name(k)); |
697 | buffer_put_string(&b, blob, bloblen); | 698 | buffer_put_string(&b, blob, bloblen); |
698 | } | 699 | } |
699 | xfree(blob); | 700 | xfree(blob); |
@@ -719,10 +720,10 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) | |||
719 | } | 720 | } |
720 | 721 | ||
721 | /* sign callback */ | 722 | /* sign callback */ |
722 | int dsa_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp, | 723 | int key_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp, |
723 | unsigned char *data, int datalen) | 724 | unsigned char *data, int datalen) |
724 | { | 725 | { |
725 | return dsa_sign(key, sigp, lenp, data, datalen); | 726 | return key_sign(key, sigp, lenp, data, datalen); |
726 | } | 727 | } |
727 | 728 | ||
728 | int | 729 | int |
@@ -738,14 +739,13 @@ userauth_pubkey_identity(Authctxt *authctxt, char *filename) | |||
738 | } | 739 | } |
739 | debug("try pubkey: %s", filename); | 740 | debug("try pubkey: %s", filename); |
740 | 741 | ||
741 | k = key_new(KEY_DSA); | 742 | k = key_new(KEY_UNSPEC); |
742 | if (!load_private_key(filename, "", k, NULL)) { | 743 | if (!load_private_key(filename, "", k, NULL)) { |
743 | int success = 0; | 744 | int success = 0; |
744 | char *passphrase; | 745 | char *passphrase; |
745 | char prompt[300]; | 746 | char prompt[300]; |
746 | snprintf(prompt, sizeof prompt, | 747 | snprintf(prompt, sizeof prompt, |
747 | "Enter passphrase for %s key '%.100s': ", | 748 | "Enter passphrase for key '%.100s': ", filename); |
748 | key_type(k), filename); | ||
749 | for (i = 0; i < options.number_of_password_prompts; i++) { | 749 | for (i = 0; i < options.number_of_password_prompts; i++) { |
750 | passphrase = read_passphrase(prompt, 0); | 750 | passphrase = read_passphrase(prompt, 0); |
751 | if (strcmp(passphrase, "") != 0) { | 751 | if (strcmp(passphrase, "") != 0) { |
@@ -766,7 +766,7 @@ userauth_pubkey_identity(Authctxt *authctxt, char *filename) | |||
766 | return 0; | 766 | return 0; |
767 | } | 767 | } |
768 | } | 768 | } |
769 | ret = sign_and_send_pubkey(authctxt, k, dsa_sign_cb); | 769 | ret = sign_and_send_pubkey(authctxt, k, key_sign_cb); |
770 | key_free(k); | 770 | key_free(k); |
771 | return ret; | 771 | return ret; |
772 | } | 772 | } |
@@ -782,24 +782,26 @@ int | |||
782 | userauth_pubkey_agent(Authctxt *authctxt) | 782 | userauth_pubkey_agent(Authctxt *authctxt) |
783 | { | 783 | { |
784 | static int called = 0; | 784 | static int called = 0; |
785 | int ret = 0; | ||
785 | char *comment; | 786 | char *comment; |
786 | Key *k; | 787 | Key *k; |
787 | int ret; | ||
788 | 788 | ||
789 | if (called == 0) { | 789 | if (called == 0) { |
790 | k = ssh_get_first_identity(authctxt->agent, &comment, 2); | 790 | if (ssh_get_num_identities(authctxt->agent, 2) == 0) |
791 | debug2("userauth_pubkey_agent: no keys at all"); | ||
791 | called = 1; | 792 | called = 1; |
792 | } else { | ||
793 | k = ssh_get_next_identity(authctxt->agent, &comment, 2); | ||
794 | } | 793 | } |
794 | k = ssh_get_next_identity(authctxt->agent, &comment, 2); | ||
795 | if (k == NULL) { | 795 | if (k == NULL) { |
796 | debug2("no more DSA keys from agent"); | 796 | debug2("userauth_pubkey_agent: no more keys"); |
797 | return 0; | 797 | } else { |
798 | debug("userauth_pubkey_agent: trying agent key %s", comment); | ||
799 | xfree(comment); | ||
800 | ret = sign_and_send_pubkey(authctxt, k, agent_sign_cb); | ||
801 | key_free(k); | ||
798 | } | 802 | } |
799 | debug("trying DSA agent key %s", comment); | 803 | if (ret == 0) |
800 | xfree(comment); | 804 | debug2("userauth_pubkey_agent: no message sent"); |
801 | ret = sign_and_send_pubkey(authctxt, k, agent_sign_cb); | ||
802 | key_free(k); | ||
803 | return ret; | 805 | return ret; |
804 | } | 806 | } |
805 | 807 | ||
@@ -809,10 +811,17 @@ userauth_pubkey(Authctxt *authctxt) | |||
809 | static int idx = 0; | 811 | static int idx = 0; |
810 | int sent = 0; | 812 | int sent = 0; |
811 | 813 | ||
812 | if (authctxt->agent != NULL) | 814 | if (authctxt->agent != NULL) { |
813 | sent = userauth_pubkey_agent(authctxt); | 815 | do { |
814 | while (sent == 0 && idx < options.num_identity_files2) | 816 | sent = userauth_pubkey_agent(authctxt); |
815 | sent = userauth_pubkey_identity(authctxt, options.identity_files2[idx++]); | 817 | } while(!sent && authctxt->agent->howmany > 0); |
818 | } | ||
819 | while (!sent && idx < options.num_identity_files) { | ||
820 | if (options.identity_files_type[idx] != KEY_RSA1) | ||
821 | sent = userauth_pubkey_identity(authctxt, | ||
822 | options.identity_files[idx]); | ||
823 | idx++; | ||
824 | } | ||
816 | return sent; | 825 | return sent; |
817 | } | 826 | } |
818 | 827 | ||
@@ -34,7 +34,7 @@ | |||
34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | .\" | 36 | .\" |
37 | .\" $OpenBSD: sshd.8,v 1.70 2000/10/16 09:38:44 djm Exp $ | 37 | .\" $OpenBSD: sshd.8,v 1.72 2000/11/12 19:50:38 markus Exp $ |
38 | .Dd September 25, 1999 | 38 | .Dd September 25, 1999 |
39 | .Dt SSHD 8 | 39 | .Dt SSHD 8 |
40 | .Os | 40 | .Os |
@@ -144,7 +144,7 @@ through a cryptographic message authentication code | |||
144 | (hmac-sha1 or hmac-md5). | 144 | (hmac-sha1 or hmac-md5). |
145 | .Pp | 145 | .Pp |
146 | Protocol version 2 provides a public key based | 146 | Protocol version 2 provides a public key based |
147 | user authentication method (DSAAuthentication) | 147 | user authentication method (PubkeyAuthentication) |
148 | and conventional password authentication. | 148 | and conventional password authentication. |
149 | .Pp | 149 | .Pp |
150 | .Ss Command execution and data forwarding | 150 | .Ss Command execution and data forwarding |
@@ -359,8 +359,8 @@ and | |||
359 | can be used as wildcards in the patterns. | 359 | can be used as wildcards in the patterns. |
360 | Only user names are valid; a numerical user ID isn't recognized. | 360 | Only user names are valid; a numerical user ID isn't recognized. |
361 | By default login is allowed regardless of the user name. | 361 | By default login is allowed regardless of the user name. |
362 | .It Cm DSAAuthentication | 362 | .It Cm PubkeyAuthentication |
363 | Specifies whether DSA authentication is allowed. | 363 | Specifies whether public key authentication is allowed. |
364 | The default is | 364 | The default is |
365 | .Dq yes . | 365 | .Dq yes . |
366 | Note that this option applies to protocol version 2 only. | 366 | Note that this option applies to protocol version 2 only. |
@@ -373,20 +373,20 @@ or | |||
373 | .Dq no . | 373 | .Dq no . |
374 | The default is | 374 | The default is |
375 | .Dq no . | 375 | .Dq no . |
376 | .It Cm HostDSAKey | ||
377 | Specifies the file containing the private DSA host key (default | ||
378 | .Pa /etc/ssh_host_dsa_key ) | ||
379 | used by SSH protocol 2.0. | ||
380 | Note that | ||
381 | .Nm | ||
382 | disables protocol 2.0 if this file is group/world-accessible. | ||
383 | .It Cm HostKey | 376 | .It Cm HostKey |
384 | Specifies the file containing the private RSA host key (default | 377 | Specifies the file containing the private host keys (default |
385 | .Pa /etc/ssh_host_key ) | 378 | .Pa /etc/ssh_host_key ) |
386 | used by SSH protocols 1.3 and 1.5. | 379 | used by SSH protocol versions 1 and 2. |
387 | Note that | 380 | Note that |
388 | .Nm | 381 | .Nm |
389 | disables protocols 1.3 and 1.5 if this file is group/world-accessible. | 382 | if this file is group/world-accessible. |
383 | It is possible to have multiple host key files. | ||
384 | .Dq rsa1 | ||
385 | keys are used for version 1 and | ||
386 | .Dq dsa | ||
387 | or | ||
388 | .Dq rsa | ||
389 | are used for version 2 of the SSH protocol. | ||
390 | .It Cm IgnoreRhosts | 390 | .It Cm IgnoreRhosts |
391 | Specifies that | 391 | Specifies that |
392 | .Pa .rhosts | 392 | .Pa .rhosts |
@@ -1039,7 +1039,7 @@ This can be used to specify | |||
1039 | machine-specific login-time initializations globally. | 1039 | machine-specific login-time initializations globally. |
1040 | This file should be writable only by root, and should be world-readable. | 1040 | This file should be writable only by root, and should be world-readable. |
1041 | .El | 1041 | .El |
1042 | .Sh AUTHOR | 1042 | .Sh AUTHORS |
1043 | OpenSSH | 1043 | OpenSSH |
1044 | is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen, | 1044 | is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen, |
1045 | but with bugs removed and newer features re-added. | 1045 | but with bugs removed and newer features re-added. |
@@ -40,7 +40,7 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: sshd.c,v 1.132 2000/10/13 18:34:46 markus Exp $"); | 43 | RCSID("$OpenBSD: sshd.c,v 1.134 2000/11/12 19:50:38 markus Exp $"); |
44 | 44 | ||
45 | #include "xmalloc.h" | 45 | #include "xmalloc.h" |
46 | #include "rsa.h" | 46 | #include "rsa.h" |
@@ -61,7 +61,6 @@ RCSID("$OpenBSD: sshd.c,v 1.132 2000/10/13 18:34:46 markus Exp $"); | |||
61 | #include <openssl/dsa.h> | 61 | #include <openssl/dsa.h> |
62 | #include <openssl/rsa.h> | 62 | #include <openssl/rsa.h> |
63 | #include "key.h" | 63 | #include "key.h" |
64 | #include "dsa.h" | ||
65 | #include "dh.h" | 64 | #include "dh.h" |
66 | 65 | ||
67 | #include "auth.h" | 66 | #include "auth.h" |
@@ -140,9 +139,11 @@ char *server_version_string = NULL; | |||
140 | * not very useful. Currently, memory locking is not implemented. | 139 | * not very useful. Currently, memory locking is not implemented. |
141 | */ | 140 | */ |
142 | struct { | 141 | struct { |
143 | RSA *private_key; /* Private part of empheral server key. */ | 142 | Key *server_key; /* empheral server key */ |
144 | RSA *host_key; /* Private part of host key. */ | 143 | Key *ssh1_host_key; /* ssh1 host key */ |
145 | Key *dsa_host_key; /* Private DSA host key. */ | 144 | Key **host_keys; /* all private host keys */ |
145 | int have_ssh1_key; | ||
146 | int have_ssh2_key; | ||
146 | } sensitive_data; | 147 | } sensitive_data; |
147 | 148 | ||
148 | /* | 149 | /* |
@@ -154,10 +155,6 @@ int key_used = 0; | |||
154 | /* This is set to true when SIGHUP is received. */ | 155 | /* This is set to true when SIGHUP is received. */ |
155 | int received_sighup = 0; | 156 | int received_sighup = 0; |
156 | 157 | ||
157 | /* Public side of the server key. This value is regenerated regularly with | ||
158 | the private key. */ | ||
159 | RSA *public_key; | ||
160 | |||
161 | /* session identifier, used by RSA-auth */ | 158 | /* session identifier, used by RSA-auth */ |
162 | unsigned char session_id[16]; | 159 | unsigned char session_id[16]; |
163 | 160 | ||
@@ -266,6 +263,17 @@ grace_alarm_handler(int sig) | |||
266 | */ | 263 | */ |
267 | /* XXX do we really want this work to be done in a signal handler ? -m */ | 264 | /* XXX do we really want this work to be done in a signal handler ? -m */ |
268 | void | 265 | void |
266 | generate_empheral_server_key(void) | ||
267 | { | ||
268 | log("Generating %s%d bit RSA key.", sensitive_data.server_key ? "new " : "", | ||
269 | options.server_key_bits); | ||
270 | if (sensitive_data.server_key != NULL) | ||
271 | key_free(sensitive_data.server_key); | ||
272 | sensitive_data.server_key = key_generate(KEY_RSA1, options.server_key_bits); | ||
273 | arc4random_stir(); | ||
274 | log("RSA key generation complete."); | ||
275 | } | ||
276 | void | ||
269 | key_regeneration_alarm(int sig) | 277 | key_regeneration_alarm(int sig) |
270 | { | 278 | { |
271 | int save_errno = errno; | 279 | int save_errno = errno; |
@@ -273,21 +281,8 @@ key_regeneration_alarm(int sig) | |||
273 | /* Check if we should generate a new key. */ | 281 | /* Check if we should generate a new key. */ |
274 | if (key_used) { | 282 | if (key_used) { |
275 | /* This should really be done in the background. */ | 283 | /* This should really be done in the background. */ |
276 | log("Generating new %d bit RSA key.", options.server_key_bits); | 284 | generate_empheral_server_key(); |
277 | |||
278 | if (sensitive_data.private_key != NULL) | ||
279 | RSA_free(sensitive_data.private_key); | ||
280 | sensitive_data.private_key = RSA_new(); | ||
281 | |||
282 | if (public_key != NULL) | ||
283 | RSA_free(public_key); | ||
284 | public_key = RSA_new(); | ||
285 | |||
286 | rsa_generate_key(sensitive_data.private_key, public_key, | ||
287 | options.server_key_bits); | ||
288 | arc4random_stir(); | ||
289 | key_used = 0; | 285 | key_used = 0; |
290 | log("RSA key generation complete."); | ||
291 | } | 286 | } |
292 | /* Reschedule the alarm. */ | 287 | /* Reschedule the alarm. */ |
293 | signal(SIGALRM, key_regeneration_alarm); | 288 | signal(SIGALRM, key_regeneration_alarm); |
@@ -422,18 +417,93 @@ sshd_exchange_identification(int sock_in, int sock_out) | |||
422 | } | 417 | } |
423 | 418 | ||
424 | 419 | ||
420 | /* Destroy the host and server keys. They will no longer be needed. */ | ||
425 | void | 421 | void |
426 | destroy_sensitive_data(void) | 422 | destroy_sensitive_data(void) |
427 | { | 423 | { |
428 | /* Destroy the private and public keys. They will no longer be needed. */ | 424 | int i; |
429 | if (public_key) | 425 | |
430 | RSA_free(public_key); | 426 | if (sensitive_data.server_key) { |
431 | if (sensitive_data.private_key) | 427 | key_free(sensitive_data.server_key); |
432 | RSA_free(sensitive_data.private_key); | 428 | sensitive_data.server_key = NULL; |
433 | if (sensitive_data.host_key) | 429 | } |
434 | RSA_free(sensitive_data.host_key); | 430 | for(i = 0; i < options.num_host_key_files; i++) { |
435 | if (sensitive_data.dsa_host_key != NULL) | 431 | if (sensitive_data.host_keys[i]) { |
436 | key_free(sensitive_data.dsa_host_key); | 432 | key_free(sensitive_data.host_keys[i]); |
433 | sensitive_data.host_keys[i] = NULL; | ||
434 | } | ||
435 | } | ||
436 | sensitive_data.ssh1_host_key = NULL; | ||
437 | } | ||
438 | Key * | ||
439 | load_private_key_autodetect(const char *filename) | ||
440 | { | ||
441 | struct stat st; | ||
442 | int type; | ||
443 | Key *public, *private; | ||
444 | |||
445 | if (stat(filename, &st) < 0) { | ||
446 | perror(filename); | ||
447 | return NULL; | ||
448 | } | ||
449 | /* | ||
450 | * try to load the public key. right now this only works for RSA1, | ||
451 | * since SSH2 keys are fully encrypted | ||
452 | */ | ||
453 | type = KEY_RSA1; | ||
454 | public = key_new(type); | ||
455 | if (!load_public_key(filename, public, NULL)) { | ||
456 | /* ok, so we will assume this is 'some' key */ | ||
457 | type = KEY_UNSPEC; | ||
458 | } | ||
459 | key_free(public); | ||
460 | |||
461 | /* Ok, try key with empty passphrase */ | ||
462 | private = key_new(type); | ||
463 | if (load_private_key(filename, "", private, NULL)) { | ||
464 | debug("load_private_key_autodetect: type %d %s", | ||
465 | private->type, key_type(private)); | ||
466 | return private; | ||
467 | } | ||
468 | key_free(private); | ||
469 | return NULL; | ||
470 | } | ||
471 | |||
472 | char * | ||
473 | list_hostkey_types(void) | ||
474 | { | ||
475 | static char buf[1024]; | ||
476 | int i; | ||
477 | buf[0] = '\0'; | ||
478 | for(i = 0; i < options.num_host_key_files; i++) { | ||
479 | Key *key = sensitive_data.host_keys[i]; | ||
480 | if (key == NULL) | ||
481 | continue; | ||
482 | switch(key->type) { | ||
483 | case KEY_RSA: | ||
484 | case KEY_DSA: | ||
485 | strlcat(buf, key_ssh_name(key), sizeof buf); | ||
486 | strlcat(buf, ",", sizeof buf); | ||
487 | break; | ||
488 | } | ||
489 | } | ||
490 | i = strlen(buf); | ||
491 | if (i > 0 && buf[i-1] == ',') | ||
492 | buf[i-1] = '\0'; | ||
493 | debug("list_hostkey_types: %s", buf); | ||
494 | return buf; | ||
495 | } | ||
496 | |||
497 | Key * | ||
498 | get_hostkey_by_type(int type) | ||
499 | { | ||
500 | int i; | ||
501 | for(i = 0; i < options.num_host_key_files; i++) { | ||
502 | Key *key = sensitive_data.host_keys[i]; | ||
503 | if (key != NULL && key->type == type) | ||
504 | return key; | ||
505 | } | ||
506 | return NULL; | ||
437 | } | 507 | } |
438 | 508 | ||
439 | /* | 509 | /* |
@@ -555,7 +625,11 @@ main(int ac, char **av) | |||
555 | options.key_regeneration_time = atoi(optarg); | 625 | options.key_regeneration_time = atoi(optarg); |
556 | break; | 626 | break; |
557 | case 'h': | 627 | case 'h': |
558 | options.host_key_file = optarg; | 628 | if (options.num_host_key_files >= MAX_HOSTKEYS) { |
629 | fprintf(stderr, "too many host keys.\n"); | ||
630 | exit(1); | ||
631 | } | ||
632 | options.host_key_files[options.num_host_key_files++] = optarg; | ||
559 | break; | 633 | break; |
560 | case 'V': | 634 | case 'V': |
561 | client_version_string = optarg; | 635 | client_version_string = optarg; |
@@ -610,39 +684,39 @@ main(int ac, char **av) | |||
610 | 684 | ||
611 | debug("sshd version %.100s", SSH_VERSION); | 685 | debug("sshd version %.100s", SSH_VERSION); |
612 | 686 | ||
613 | sensitive_data.dsa_host_key = NULL; | 687 | /* load private host keys */ |
614 | sensitive_data.host_key = NULL; | 688 | sensitive_data.host_keys = xmalloc(options.num_host_key_files*sizeof(Key*)); |
689 | sensitive_data.server_key = NULL; | ||
690 | sensitive_data.ssh1_host_key = NULL; | ||
691 | sensitive_data.have_ssh1_key = 0; | ||
692 | sensitive_data.have_ssh2_key = 0; | ||
615 | 693 | ||
616 | /* check if RSA support exists */ | 694 | for(i = 0; i < options.num_host_key_files; i++) { |
617 | if ((options.protocol & SSH_PROTO_1) && | 695 | Key *key = load_private_key_autodetect(options.host_key_files[i]); |
618 | rsa_alive() == 0) { | 696 | if (key == NULL) { |
619 | log("no RSA support in libssl and libcrypto. See ssl(8)"); | ||
620 | log("Disabling protocol version 1"); | ||
621 | options.protocol &= ~SSH_PROTO_1; | ||
622 | } | ||
623 | /* Load the RSA/DSA host key. It must have empty passphrase. */ | ||
624 | if (options.protocol & SSH_PROTO_1) { | ||
625 | Key k; | ||
626 | sensitive_data.host_key = RSA_new(); | ||
627 | k.type = KEY_RSA; | ||
628 | k.rsa = sensitive_data.host_key; | ||
629 | errno = 0; | ||
630 | if (!load_private_key(options.host_key_file, "", &k, NULL)) { | ||
631 | error("Could not load host key: %.200s: %.100s", | 697 | error("Could not load host key: %.200s: %.100s", |
632 | options.host_key_file, strerror(errno)); | 698 | options.host_key_files[i], strerror(errno)); |
633 | log("Disabling protocol version 1"); | 699 | continue; |
634 | options.protocol &= ~SSH_PROTO_1; | ||
635 | } | 700 | } |
636 | k.rsa = NULL; | 701 | switch(key->type){ |
637 | } | 702 | case KEY_RSA1: |
638 | if (options.protocol & SSH_PROTO_2) { | 703 | sensitive_data.ssh1_host_key = key; |
639 | sensitive_data.dsa_host_key = key_new(KEY_DSA); | 704 | sensitive_data.have_ssh1_key = 1; |
640 | if (!load_private_key(options.host_dsa_key_file, "", sensitive_data.dsa_host_key, NULL)) { | 705 | break; |
641 | 706 | case KEY_RSA: | |
642 | error("Could not load DSA host key: %.200s", options.host_dsa_key_file); | 707 | case KEY_DSA: |
643 | log("Disabling protocol version 2"); | 708 | sensitive_data.have_ssh2_key = 1; |
644 | options.protocol &= ~SSH_PROTO_2; | 709 | break; |
645 | } | 710 | } |
711 | sensitive_data.host_keys[i] = key; | ||
712 | } | ||
713 | if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { | ||
714 | log("Disabling protocol version 1. Could not load host key"); | ||
715 | options.protocol &= ~SSH_PROTO_1; | ||
716 | } | ||
717 | if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { | ||
718 | log("Disabling protocol version 2. Could not load host key"); | ||
719 | options.protocol &= ~SSH_PROTO_2; | ||
646 | } | 720 | } |
647 | if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) { | 721 | if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) { |
648 | if (silent == 0) | 722 | if (silent == 0) |
@@ -664,11 +738,11 @@ main(int ac, char **av) | |||
664 | * hate software patents. I dont know if this can go? Niels | 738 | * hate software patents. I dont know if this can go? Niels |
665 | */ | 739 | */ |
666 | if (options.server_key_bits > | 740 | if (options.server_key_bits > |
667 | BN_num_bits(sensitive_data.host_key->n) - SSH_KEY_BITS_RESERVED && | 741 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) - SSH_KEY_BITS_RESERVED && |
668 | options.server_key_bits < | 742 | options.server_key_bits < |
669 | BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED) { | 743 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { |
670 | options.server_key_bits = | 744 | options.server_key_bits = |
671 | BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED; | 745 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED; |
672 | debug("Forcing server key to %d bits to make it differ from host key.", | 746 | debug("Forcing server key to %d bits to make it differ from host key.", |
673 | options.server_key_bits); | 747 | options.server_key_bits); |
674 | } | 748 | } |
@@ -707,9 +781,6 @@ main(int ac, char **av) | |||
707 | /* Reinitialize the log (because of the fork above). */ | 781 | /* Reinitialize the log (because of the fork above). */ |
708 | log_init(av0, options.log_level, options.log_facility, log_stderr); | 782 | log_init(av0, options.log_level, options.log_facility, log_stderr); |
709 | 783 | ||
710 | /* Do not display messages to stdout in RSA code. */ | ||
711 | rsa_set_verbose(0); | ||
712 | |||
713 | /* Initialize the random number generator. */ | 784 | /* Initialize the random number generator. */ |
714 | arc4random_stir(); | 785 | arc4random_stir(); |
715 | 786 | ||
@@ -731,16 +802,8 @@ main(int ac, char **av) | |||
731 | * ttyfd happens to be one of those. | 802 | * ttyfd happens to be one of those. |
732 | */ | 803 | */ |
733 | debug("inetd sockets after dupping: %d, %d", sock_in, sock_out); | 804 | debug("inetd sockets after dupping: %d, %d", sock_in, sock_out); |
734 | 805 | if (options.protocol & SSH_PROTO_1) | |
735 | if (options.protocol & SSH_PROTO_1) { | 806 | generate_empheral_server_key(); |
736 | public_key = RSA_new(); | ||
737 | sensitive_data.private_key = RSA_new(); | ||
738 | log("Generating %d bit RSA key.", options.server_key_bits); | ||
739 | rsa_generate_key(sensitive_data.private_key, public_key, | ||
740 | options.server_key_bits); | ||
741 | arc4random_stir(); | ||
742 | log("RSA key generation complete."); | ||
743 | } | ||
744 | } else { | 807 | } else { |
745 | for (ai = options.listen_addrs; ai; ai = ai->ai_next) { | 808 | for (ai = options.listen_addrs; ai; ai = ai->ai_next) { |
746 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) | 809 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) |
@@ -818,14 +881,7 @@ main(int ac, char **av) | |||
818 | } | 881 | } |
819 | } | 882 | } |
820 | if (options.protocol & SSH_PROTO_1) { | 883 | if (options.protocol & SSH_PROTO_1) { |
821 | public_key = RSA_new(); | 884 | generate_empheral_server_key(); |
822 | sensitive_data.private_key = RSA_new(); | ||
823 | |||
824 | log("Generating %d bit RSA key.", options.server_key_bits); | ||
825 | rsa_generate_key(sensitive_data.private_key, public_key, | ||
826 | options.server_key_bits); | ||
827 | arc4random_stir(); | ||
828 | log("RSA key generation complete."); | ||
829 | 885 | ||
830 | /* Schedule server key regeneration alarm. */ | 886 | /* Schedule server key regeneration alarm. */ |
831 | signal(SIGALRM, key_regeneration_alarm); | 887 | signal(SIGALRM, key_regeneration_alarm); |
@@ -1065,6 +1121,8 @@ main(int ac, char **av) | |||
1065 | */ | 1121 | */ |
1066 | if (remote_port >= IPPORT_RESERVED || | 1122 | if (remote_port >= IPPORT_RESERVED || |
1067 | remote_port < IPPORT_RESERVED / 2) { | 1123 | remote_port < IPPORT_RESERVED / 2) { |
1124 | debug("Rhosts Authentication methods disabled, " | ||
1125 | "originating port not trusted."); | ||
1068 | options.rhosts_authentication = 0; | 1126 | options.rhosts_authentication = 0; |
1069 | options.rhosts_rsa_authentication = 0; | 1127 | options.rhosts_rsa_authentication = 0; |
1070 | } | 1128 | } |
@@ -1145,14 +1203,14 @@ do_ssh1_kex() | |||
1145 | packet_put_char(cookie[i]); | 1203 | packet_put_char(cookie[i]); |
1146 | 1204 | ||
1147 | /* Store our public server RSA key. */ | 1205 | /* Store our public server RSA key. */ |
1148 | packet_put_int(BN_num_bits(public_key->n)); | 1206 | packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n)); |
1149 | packet_put_bignum(public_key->e); | 1207 | packet_put_bignum(sensitive_data.server_key->rsa->e); |
1150 | packet_put_bignum(public_key->n); | 1208 | packet_put_bignum(sensitive_data.server_key->rsa->n); |
1151 | 1209 | ||
1152 | /* Store our public host RSA key. */ | 1210 | /* Store our public host RSA key. */ |
1153 | packet_put_int(BN_num_bits(sensitive_data.host_key->n)); | 1211 | packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n)); |
1154 | packet_put_bignum(sensitive_data.host_key->e); | 1212 | packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e); |
1155 | packet_put_bignum(sensitive_data.host_key->n); | 1213 | packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n); |
1156 | 1214 | ||
1157 | /* Put protocol flags. */ | 1215 | /* Put protocol flags. */ |
1158 | packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); | 1216 | packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); |
@@ -1190,8 +1248,9 @@ do_ssh1_kex() | |||
1190 | packet_send(); | 1248 | packet_send(); |
1191 | packet_write_wait(); | 1249 | packet_write_wait(); |
1192 | 1250 | ||
1193 | debug("Sent %d bit public key and %d bit host key.", | 1251 | debug("Sent %d bit server key and %d bit host key.", |
1194 | BN_num_bits(public_key->n), BN_num_bits(sensitive_data.host_key->n)); | 1252 | BN_num_bits(sensitive_data.server_key->rsa->n), |
1253 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n)); | ||
1195 | 1254 | ||
1196 | /* Read clients reply (cipher type and session key). */ | 1255 | /* Read clients reply (cipher type and session key). */ |
1197 | packet_read_expect(&plen, SSH_CMSG_SESSION_KEY); | 1256 | packet_read_expect(&plen, SSH_CMSG_SESSION_KEY); |
@@ -1223,39 +1282,39 @@ do_ssh1_kex() | |||
1223 | * Decrypt it using our private server key and private host key (key | 1282 | * Decrypt it using our private server key and private host key (key |
1224 | * with larger modulus first). | 1283 | * with larger modulus first). |
1225 | */ | 1284 | */ |
1226 | if (BN_cmp(sensitive_data.private_key->n, sensitive_data.host_key->n) > 0) { | 1285 | if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) { |
1227 | /* Private key has bigger modulus. */ | 1286 | /* Private key has bigger modulus. */ |
1228 | if (BN_num_bits(sensitive_data.private_key->n) < | 1287 | if (BN_num_bits(sensitive_data.server_key->rsa->n) < |
1229 | BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED) { | 1288 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { |
1230 | fatal("do_connection: %s: private_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", | 1289 | fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", |
1231 | get_remote_ipaddr(), | 1290 | get_remote_ipaddr(), |
1232 | BN_num_bits(sensitive_data.private_key->n), | 1291 | BN_num_bits(sensitive_data.server_key->rsa->n), |
1233 | BN_num_bits(sensitive_data.host_key->n), | 1292 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), |
1234 | SSH_KEY_BITS_RESERVED); | 1293 | SSH_KEY_BITS_RESERVED); |
1235 | } | 1294 | } |
1236 | rsa_private_decrypt(session_key_int, session_key_int, | 1295 | rsa_private_decrypt(session_key_int, session_key_int, |
1237 | sensitive_data.private_key); | 1296 | sensitive_data.server_key->rsa); |
1238 | rsa_private_decrypt(session_key_int, session_key_int, | 1297 | rsa_private_decrypt(session_key_int, session_key_int, |
1239 | sensitive_data.host_key); | 1298 | sensitive_data.ssh1_host_key->rsa); |
1240 | } else { | 1299 | } else { |
1241 | /* Host key has bigger modulus (or they are equal). */ | 1300 | /* Host key has bigger modulus (or they are equal). */ |
1242 | if (BN_num_bits(sensitive_data.host_key->n) < | 1301 | if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < |
1243 | BN_num_bits(sensitive_data.private_key->n) + SSH_KEY_BITS_RESERVED) { | 1302 | BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { |
1244 | fatal("do_connection: %s: host_key %d < private_key %d + SSH_KEY_BITS_RESERVED %d", | 1303 | fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d", |
1245 | get_remote_ipaddr(), | 1304 | get_remote_ipaddr(), |
1246 | BN_num_bits(sensitive_data.host_key->n), | 1305 | BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), |
1247 | BN_num_bits(sensitive_data.private_key->n), | 1306 | BN_num_bits(sensitive_data.server_key->rsa->n), |
1248 | SSH_KEY_BITS_RESERVED); | 1307 | SSH_KEY_BITS_RESERVED); |
1249 | } | 1308 | } |
1250 | rsa_private_decrypt(session_key_int, session_key_int, | 1309 | rsa_private_decrypt(session_key_int, session_key_int, |
1251 | sensitive_data.host_key); | 1310 | sensitive_data.ssh1_host_key->rsa); |
1252 | rsa_private_decrypt(session_key_int, session_key_int, | 1311 | rsa_private_decrypt(session_key_int, session_key_int, |
1253 | sensitive_data.private_key); | 1312 | sensitive_data.server_key->rsa); |
1254 | } | 1313 | } |
1255 | 1314 | ||
1256 | compute_session_id(session_id, cookie, | 1315 | compute_session_id(session_id, cookie, |
1257 | sensitive_data.host_key->n, | 1316 | sensitive_data.ssh1_host_key->rsa->n, |
1258 | sensitive_data.private_key->n); | 1317 | sensitive_data.server_key->rsa->n); |
1259 | 1318 | ||
1260 | /* Destroy the private and public keys. They will no longer be needed. */ | 1319 | /* Destroy the private and public keys. They will no longer be needed. */ |
1261 | destroy_sensitive_data(); | 1320 | destroy_sensitive_data(); |
@@ -1269,8 +1328,8 @@ do_ssh1_kex() | |||
1269 | len = BN_num_bytes(session_key_int); | 1328 | len = BN_num_bytes(session_key_int); |
1270 | if (len < 0 || len > sizeof(session_key)) | 1329 | if (len < 0 || len > sizeof(session_key)) |
1271 | fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d", | 1330 | fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d", |
1272 | get_remote_ipaddr(), | 1331 | get_remote_ipaddr(), |
1273 | len, (int) sizeof(session_key)); | 1332 | len, sizeof(session_key)); |
1274 | memset(session_key, 0, sizeof(session_key)); | 1333 | memset(session_key, 0, sizeof(session_key)); |
1275 | BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len); | 1334 | BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len); |
1276 | 1335 | ||
@@ -1314,6 +1373,8 @@ do_ssh2_kex() | |||
1314 | myproposal[PROPOSAL_ENC_ALGS_CTOS] = | 1373 | myproposal[PROPOSAL_ENC_ALGS_CTOS] = |
1315 | myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; | 1374 | myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; |
1316 | } | 1375 | } |
1376 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); | ||
1377 | |||
1317 | server_kexinit = kex_init(myproposal); | 1378 | server_kexinit = kex_init(myproposal); |
1318 | client_kexinit = xmalloc(sizeof(*client_kexinit)); | 1379 | client_kexinit = xmalloc(sizeof(*client_kexinit)); |
1319 | buffer_init(client_kexinit); | 1380 | buffer_init(client_kexinit); |
@@ -1379,6 +1440,11 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) | |||
1379 | BIGNUM *shared_secret = 0; | 1440 | BIGNUM *shared_secret = 0; |
1380 | DH *dh; | 1441 | DH *dh; |
1381 | BIGNUM *dh_client_pub = 0; | 1442 | BIGNUM *dh_client_pub = 0; |
1443 | Key *hostkey; | ||
1444 | |||
1445 | hostkey = get_hostkey_by_type(kex->hostkey_type); | ||
1446 | if (hostkey == NULL) | ||
1447 | fatal("Unsupported hostkey type %d", kex->hostkey_type); | ||
1382 | 1448 | ||
1383 | /* KEXDH */ | 1449 | /* KEXDH */ |
1384 | debug("Wait SSH2_MSG_KEXDH_INIT."); | 1450 | debug("Wait SSH2_MSG_KEXDH_INIT."); |
@@ -1431,8 +1497,7 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) | |||
1431 | xfree(kbuf); | 1497 | xfree(kbuf); |
1432 | 1498 | ||
1433 | /* XXX precompute? */ | 1499 | /* XXX precompute? */ |
1434 | dsa_make_key_blob(sensitive_data.dsa_host_key, | 1500 | key_to_blob(hostkey, &server_host_key_blob, &sbloblen); |
1435 | &server_host_key_blob, &sbloblen); | ||
1436 | 1501 | ||
1437 | /* calc H */ /* XXX depends on 'kex' */ | 1502 | /* calc H */ /* XXX depends on 'kex' */ |
1438 | hash = kex_hash( | 1503 | hash = kex_hash( |
@@ -1463,7 +1528,7 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) | |||
1463 | 1528 | ||
1464 | /* sign H */ | 1529 | /* sign H */ |
1465 | /* XXX hashlen depends on KEX */ | 1530 | /* XXX hashlen depends on KEX */ |
1466 | dsa_sign(sensitive_data.dsa_host_key, &signature, &slen, hash, 20); | 1531 | key_sign(hostkey, &signature, &slen, hash, 20); |
1467 | 1532 | ||
1468 | destroy_sensitive_data(); | 1533 | destroy_sensitive_data(); |
1469 | 1534 | ||
@@ -1503,6 +1568,11 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) | |||
1503 | BIGNUM *shared_secret = 0; | 1568 | BIGNUM *shared_secret = 0; |
1504 | DH *dh; | 1569 | DH *dh; |
1505 | BIGNUM *dh_client_pub = 0; | 1570 | BIGNUM *dh_client_pub = 0; |
1571 | Key *hostkey; | ||
1572 | |||
1573 | hostkey = get_hostkey_by_type(kex->hostkey_type); | ||
1574 | if (hostkey == NULL) | ||
1575 | fatal("Unsupported hostkey type %d", kex->hostkey_type); | ||
1506 | 1576 | ||
1507 | /* KEXDHGEX */ | 1577 | /* KEXDHGEX */ |
1508 | debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST."); | 1578 | debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST."); |
@@ -1564,8 +1634,7 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) | |||
1564 | xfree(kbuf); | 1634 | xfree(kbuf); |
1565 | 1635 | ||
1566 | /* XXX precompute? */ | 1636 | /* XXX precompute? */ |
1567 | dsa_make_key_blob(sensitive_data.dsa_host_key, | 1637 | key_to_blob(hostkey, &server_host_key_blob, &sbloblen); |
1568 | &server_host_key_blob, &sbloblen); | ||
1569 | 1638 | ||
1570 | /* calc H */ /* XXX depends on 'kex' */ | 1639 | /* calc H */ /* XXX depends on 'kex' */ |
1571 | hash = kex_hash_gex( | 1640 | hash = kex_hash_gex( |
@@ -1597,7 +1666,7 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) | |||
1597 | 1666 | ||
1598 | /* sign H */ | 1667 | /* sign H */ |
1599 | /* XXX hashlen depends on KEX */ | 1668 | /* XXX hashlen depends on KEX */ |
1600 | dsa_sign(sensitive_data.dsa_host_key, &signature, &slen, hash, 20); | 1669 | key_sign(hostkey, &signature, &slen, hash, 20); |
1601 | 1670 | ||
1602 | destroy_sensitive_data(); | 1671 | destroy_sensitive_data(); |
1603 | 1672 | ||
@@ -1617,4 +1686,3 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) | |||
1617 | /* have keys, free DH */ | 1686 | /* have keys, free DH */ |
1618 | DH_free(dh); | 1687 | DH_free(dh); |
1619 | } | 1688 | } |
1620 | |||
diff --git a/sshd_config b/sshd_config index 3b88062fa..f368b97ac 100644 --- a/sshd_config +++ b/sshd_config | |||
@@ -5,6 +5,8 @@ Port 22 | |||
5 | ListenAddress 0.0.0.0 | 5 | ListenAddress 0.0.0.0 |
6 | #ListenAddress :: | 6 | #ListenAddress :: |
7 | HostKey /etc/ssh_host_key | 7 | HostKey /etc/ssh_host_key |
8 | HostKey /etc/ssh_host_rsa_key | ||
9 | HostKey /etc/ssh_host_dsa_key | ||
8 | ServerKeyBits 768 | 10 | ServerKeyBits 768 |
9 | LoginGraceTime 600 | 11 | LoginGraceTime 600 |
10 | KeyRegenerationInterval 3600 | 12 | KeyRegenerationInterval 3600 |