]> andersk Git - openssh.git/blobdiff - sshd.c
- (djm) Big OpenBSD sync:
[openssh.git] / sshd.c
diff --git a/sshd.c b/sshd.c
index ae22cd9530caa18e02bdb4b203656d410d74b79a..e5c2508a10e47d86ea8c12b56950744892194bbb 100644 (file)
--- a/sshd.c
+++ b/sshd.c
  */
 
 #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);
 }
+
This page took 0.043259 seconds and 4 git commands to generate.