From 874d77bb134a21a5cf625956b60173376a993ba8 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sat, 14 Oct 2000 16:23:11 +1100 Subject: - (djm) Big OpenBSD sync: - markus@cvs.openbsd.org 2000/09/30 10:27:44 [log.c] allow loglevel debug - markus@cvs.openbsd.org 2000/10/03 11:59:57 [packet.c] hmac->mac - markus@cvs.openbsd.org 2000/10/03 12:03:03 [auth-krb4.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c] move fake-auth from auth1.c to individual auth methods, disables s/key in debug-msg - markus@cvs.openbsd.org 2000/10/03 12:16:48 ssh.c do not resolve canonname, i have no idea why this was added oin ossh - markus@cvs.openbsd.org 2000/10/09 15:30:44 ssh-keygen.1 ssh-keygen.c -X now reads private ssh.com DSA keys, too. - markus@cvs.openbsd.org 2000/10/09 15:32:34 auth-options.c clear options on every call. - markus@cvs.openbsd.org 2000/10/09 15:51:00 authfd.c authfd.h interop with ssh-agent2, from - markus@cvs.openbsd.org 2000/10/10 14:20:45 compat.c use rexexp for version string matching - provos@cvs.openbsd.org 2000/10/10 22:02:18 [kex.c kex.h myproposal.h ssh.h ssh2.h sshconnect2.c sshd.c dh.c dh.h] First rough implementation of the diffie-hellman group exchange. The client can ask the server for bigger groups to perform the diffie-hellman in, thus increasing the attack complexity when using ciphers with longer keys. University of Windsor provided network, T the company. - markus@cvs.openbsd.org 2000/10/11 13:59:52 [auth-rsa.c auth2.c] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:00:27 [auth-options.h] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:03:27 [scp.1 scp.c] support 'scp -o' with help from mouring@pconline.com - markus@cvs.openbsd.org 2000/10/11 14:11:35 [dh.c] Wall - markus@cvs.openbsd.org 2000/10/11 14:14:40 [auth.h auth2.c readconf.c readconf.h readpass.c servconf.c servconf.h] [ssh.h sshconnect2.c sshd_config auth2-skey.c cli.c cli.h] add support for s/key (kbd-interactive) to ssh2, based on work by mkiernan@avantgo.com and me - markus@cvs.openbsd.org 2000/10/11 14:27:24 [auth.c auth1.c auth2.c authfile.c cipher.c cipher.h kex.c kex.h] [myproposal.h packet.c readconf.c session.c ssh.c ssh.h sshconnect1.c] [sshconnect2.c sshd.c] new cipher framework - markus@cvs.openbsd.org 2000/10/11 14:45:21 [cipher.c] remove DES - markus@cvs.openbsd.org 2000/10/12 03:59:20 [cipher.c cipher.h sshconnect1.c sshconnect2.c sshd.c] enable DES in SSH-1 clients only - markus@cvs.openbsd.org 2000/10/12 08:21:13 [kex.h packet.c] remove unused - markus@cvs.openbsd.org 2000/10/13 12:34:46 [sshd.c] Kludge for F-Secure Macintosh < 1.0.2; appro@fy.chalmers.se - markus@cvs.openbsd.org 2000/10/13 12:59:15 [cipher.c cipher.h myproposal.h rijndael.c rijndael.h] rijndael/aes support - markus@cvs.openbsd.org 2000/10/13 13:10:54 [sshd.8] more info about -V - markus@cvs.openbsd.org 2000/10/13 13:12:02 [myproposal.h] prefer no compression --- sshd.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 197 insertions(+), 28 deletions(-) (limited to 'sshd.c') diff --git a/sshd.c b/sshd.c index ae22cd953..e5c2508a1 100644 --- a/sshd.c +++ b/sshd.c @@ -40,14 +40,13 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.128 2000/09/17 15:38:59 markus Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.132 2000/10/13 18:34:46 markus Exp $"); #include "xmalloc.h" #include "rsa.h" #include "ssh.h" #include "pty.h" #include "packet.h" -#include "cipher.h" #include "mpaux.h" #include "servconf.h" #include "uidswap.h" @@ -63,6 +62,7 @@ RCSID("$OpenBSD: sshd.c,v 1.128 2000/09/17 15:38:59 markus Exp $"); #include #include "key.h" #include "dsa.h" +#include "dh.h" #include "auth.h" #include "myproposal.h" @@ -172,6 +172,9 @@ unsigned int utmp_len = MAXHOSTNAMELEN; void do_ssh1_kex(); void do_ssh2_kex(); +void ssh_dh1_server(Kex *, Buffer *_kexinit, Buffer *); +void ssh_dhgex_server(Kex *, Buffer *_kexinit, Buffer *); + /* * Close all listening sockets */ @@ -333,6 +336,10 @@ sshd_exchange_identification(int sock_in, int sock_out) if (buf[i] == '\r') { buf[i] = '\n'; buf[i + 1] = 0; + /* Kludge for F-Secure Macintosh < 1.0.2 */ + if (i == 12 && + strncmp(buf, "SSH-1.5-W1.0", 12) == 0) + break; continue; } if (buf[i] == '\n') { @@ -1151,7 +1158,7 @@ do_ssh1_kex() packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); /* Declare which ciphers we support. */ - packet_put_int(cipher_mask1()); + packet_put_int(cipher_mask_ssh1(0)); /* Declare supported authentication types. */ auth_mask = 0; @@ -1192,7 +1199,7 @@ do_ssh1_kex() /* Get cipher type and check whether we accept this. */ cipher_type = packet_get_char(); - if (!(cipher_mask() & (1 << cipher_type))) + if (!(cipher_mask_ssh1(0) & (1 << cipher_type))) packet_disconnect("Warning: client selects unsupported cipher."); /* Get check bytes from the packet. These must match those we @@ -1296,18 +1303,8 @@ do_ssh2_kex() { Buffer *server_kexinit; Buffer *client_kexinit; - int payload_len, dlen; - int slen; - unsigned int klen, kout; - unsigned char *signature = NULL; - unsigned char *server_host_key_blob = NULL; - unsigned int sbloblen; - DH *dh; - BIGNUM *dh_client_pub = 0; - BIGNUM *shared_secret = 0; + int payload_len; int i; - unsigned char *kbuf; - unsigned char *hash; Kex *kex; char *cprop[PROPOSAL_MAX]; @@ -1327,8 +1324,63 @@ do_ssh2_kex() for (i = 0; i < PROPOSAL_MAX; i++) xfree(cprop[i]); -/* KEXDH */ + switch (kex->kex_type) { + case DH_GRP1_SHA1: + ssh_dh1_server(kex, client_kexinit, server_kexinit); + break; + case DH_GEX_SHA1: + ssh_dhgex_server(kex, client_kexinit, server_kexinit); + break; + default: + fatal("Unsupported key exchange %d", kex->kex_type); + } + + debug("send SSH2_MSG_NEWKEYS."); + packet_start(SSH2_MSG_NEWKEYS); + packet_send(); + packet_write_wait(); + debug("done: send SSH2_MSG_NEWKEYS."); + + debug("Wait SSH2_MSG_NEWKEYS."); + packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS); + debug("GOT SSH2_MSG_NEWKEYS."); + +#ifdef DEBUG_KEXDH + /* send 1st encrypted/maced/compressed message */ + packet_start(SSH2_MSG_IGNORE); + packet_put_cstring("markus"); + packet_send(); + packet_write_wait(); +#endif + + debug("done: KEX2."); +} + +/* + * SSH2 key exchange + */ + +/* diffie-hellman-group1-sha1 */ + +void +ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) +{ +#ifdef DEBUG_KEXDH + int i; +#endif + int payload_len, dlen; + int slen; + unsigned char *signature = NULL; + unsigned char *server_host_key_blob = NULL; + unsigned int sbloblen; + unsigned int klen, kout; + unsigned char *kbuf; + unsigned char *hash; + BIGNUM *shared_secret = 0; + DH *dh; + BIGNUM *dh_client_pub = 0; +/* KEXDH */ debug("Wait SSH2_MSG_KEXDH_INIT."); packet_read_expect(&payload_len, SSH2_MSG_KEXDH_INIT); @@ -1379,7 +1431,8 @@ do_ssh2_kex() xfree(kbuf); /* XXX precompute? */ - dsa_make_key_blob(sensitive_data.dsa_host_key, &server_host_key_blob, &sbloblen); + dsa_make_key_blob(sensitive_data.dsa_host_key, + &server_host_key_blob, &sbloblen); /* calc H */ /* XXX depends on 'kex' */ hash = kex_hash( @@ -1429,23 +1482,139 @@ do_ssh2_kex() /* have keys, free DH */ DH_free(dh); +} - debug("send SSH2_MSG_NEWKEYS."); - packet_start(SSH2_MSG_NEWKEYS); +/* diffie-hellman-group-exchange-sha1 */ + +void +ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) +{ +#ifdef DEBUG_KEXDH + int i; +#endif + int payload_len, dlen; + int slen, nbits; + unsigned char *signature = NULL; + unsigned char *server_host_key_blob = NULL; + unsigned int sbloblen; + unsigned int klen, kout; + unsigned char *kbuf; + unsigned char *hash; + BIGNUM *shared_secret = 0; + DH *dh; + BIGNUM *dh_client_pub = 0; + +/* KEXDHGEX */ + debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST."); + packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_REQUEST); + nbits = packet_get_int(); + dh = choose_dh(nbits); + + debug("Sending SSH2_MSG_KEX_DH_GEX_GROUP."); + packet_start(SSH2_MSG_KEX_DH_GEX_GROUP); + packet_put_bignum2(dh->p); + packet_put_bignum2(dh->g); packet_send(); packet_write_wait(); - debug("done: send SSH2_MSG_NEWKEYS."); - debug("Wait SSH2_MSG_NEWKEYS."); - packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS); - debug("GOT SSH2_MSG_NEWKEYS."); + debug("Wait SSH2_MSG_KEX_DH_GEX_INIT."); + packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_INIT); + + /* key, cert */ + dh_client_pub = BN_new(); + if (dh_client_pub == NULL) + fatal("dh_client_pub == NULL"); + packet_get_bignum2(dh_client_pub, &dlen); #ifdef DEBUG_KEXDH - /* send 1st encrypted/maced/compressed message */ - packet_start(SSH2_MSG_IGNORE); - packet_put_cstring("markus"); + fprintf(stderr, "\ndh_client_pub= "); + BN_print_fp(stderr, dh_client_pub); + fprintf(stderr, "\n"); + debug("bits %d", BN_num_bits(dh_client_pub)); +#endif + +#ifdef DEBUG_KEXDH + fprintf(stderr, "\np= "); + BN_print_fp(stderr, dh->p); + fprintf(stderr, "\ng= "); + bn_print(dh->g); + fprintf(stderr, "\npub= "); + BN_print_fp(stderr, dh->pub_key); + fprintf(stderr, "\n"); + DHparams_print_fp(stderr, dh); +#endif + if (!dh_pub_is_valid(dh, dh_client_pub)) + packet_disconnect("bad client public DH value"); + + klen = DH_size(dh); + kbuf = xmalloc(klen); + kout = DH_compute_key(kbuf, dh_client_pub, dh); + +#ifdef DEBUG_KEXDH + debug("shared secret: len %d/%d", klen, kout); + fprintf(stderr, "shared secret == "); + for (i = 0; i< kout; i++) + fprintf(stderr, "%02x", (kbuf[i])&0xff); + fprintf(stderr, "\n"); +#endif + shared_secret = BN_new(); + + BN_bin2bn(kbuf, kout, shared_secret); + memset(kbuf, 0, klen); + xfree(kbuf); + + /* XXX precompute? */ + dsa_make_key_blob(sensitive_data.dsa_host_key, + &server_host_key_blob, &sbloblen); + + /* calc H */ /* XXX depends on 'kex' */ + hash = kex_hash_gex( + client_version_string, + server_version_string, + buffer_ptr(client_kexinit), buffer_len(client_kexinit), + buffer_ptr(server_kexinit), buffer_len(server_kexinit), + (char *)server_host_key_blob, sbloblen, + nbits, dh->p, dh->g, + dh_client_pub, + dh->pub_key, + shared_secret + ); + buffer_free(client_kexinit); + buffer_free(server_kexinit); + xfree(client_kexinit); + xfree(server_kexinit); +#ifdef DEBUG_KEXDH + fprintf(stderr, "hash == "); + for (i = 0; i< 20; i++) + fprintf(stderr, "%02x", (hash[i])&0xff); + fprintf(stderr, "\n"); +#endif + /* save session id := H */ + /* XXX hashlen depends on KEX */ + session_id2_len = 20; + session_id2 = xmalloc(session_id2_len); + memcpy(session_id2, hash, session_id2_len); + + /* sign H */ + /* XXX hashlen depends on KEX */ + dsa_sign(sensitive_data.dsa_host_key, &signature, &slen, hash, 20); + + destroy_sensitive_data(); + + /* send server hostkey, DH pubkey 'f' and singed H */ + packet_start(SSH2_MSG_KEX_DH_GEX_REPLY); + packet_put_string((char *)server_host_key_blob, sbloblen); + packet_put_bignum2(dh->pub_key); /* f */ + packet_put_string((char *)signature, slen); packet_send(); + xfree(signature); + xfree(server_host_key_blob); packet_write_wait(); -#endif - debug("done: KEX2."); + + kex_derive_keys(kex, hash, shared_secret); + packet_set_kex(kex); + + /* have keys, free DH */ + DH_free(dh); } + -- cgit v1.2.3