summaryrefslogtreecommitdiff
path: root/sshd.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-10-14 16:23:11 +1100
committerDamien Miller <djm@mindrot.org>2000-10-14 16:23:11 +1100
commit874d77bb134a21a5cf625956b60173376a993ba8 (patch)
tree93dd73b2ff1fbf0ad5f3978a2c4e0d8438a0bf7c /sshd.c
parent89d9796fbedef4eed6956a2c095c7cc25330c28d (diff)
- (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 <res@shore.net> - 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
Diffstat (limited to 'sshd.c')
-rw-r--r--sshd.c225
1 files changed, 197 insertions, 28 deletions
diff --git a/sshd.c b/sshd.c
index ae22cd95..e5c2508a 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 <openssl/rsa.h>
#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);
}
+