]> andersk Git - gssapi-openssh.git/blobdiff - openssh/kex.c
merged OpenSSH 5.3p1 to trunk
[gssapi-openssh.git] / openssh / kex.c
index b49c610b27eb498c428961c88c586ba409667559..71ccfe2858c8edc0d221e20b939e940ba982a4c6 100644 (file)
@@ -1,3 +1,4 @@
+/* $OpenBSD: kex.c,v 1.81 2009/05/27 06:34:36 andreas Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  *
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: kex.c,v 1.64 2005/07/25 11:59:39 markus Exp $");
+
+#include <sys/param.h>
+
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 #include <openssl/crypto.h>
 
-#include "ssh2.h"
 #include "xmalloc.h"
+#include "ssh2.h"
 #include "buffer.h"
-#include "bufaux.h"
 #include "packet.h"
 #include "compat.h"
 #include "cipher.h"
-#include "kex.h"
 #include "key.h"
+#include "kex.h"
 #include "log.h"
 #include "mac.h"
 #include "match.h"
 #include "dispatch.h"
 #include "monitor.h"
+#include "canohost.h"
 
 #ifdef GSSAPI
 #include "ssh-gss.h"
 #endif
 
-#define KEX_COOKIE_LEN 16
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+# if defined(HAVE_EVP_SHA256)
+# define evp_ssh_sha256 EVP_sha256
+# else
+extern const EVP_MD *evp_ssh_sha256(void);
+# endif
+#endif
 
 /* prototype */
 static void kex_kexinit_finish(Kex *);
 static void kex_choose_conf(Kex *);
 
 /* put algorithm proposal into buffer */
+/* used in sshconnect.c as well as kex.c */
 void
 kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
 {
@@ -76,10 +91,10 @@ static char **
 kex_buf2prop(Buffer *raw, int *first_kex_follows)
 {
        Buffer b;
-       int i;
+       u_int i;
        char **proposal;
 
-       proposal = xmalloc(PROPOSAL_MAX * sizeof(char *));
+       proposal = xcalloc(PROPOSAL_MAX, sizeof(char *));
 
        buffer_init(&b);
        buffer_append(&b, buffer_ptr(raw), buffer_len(raw));
@@ -97,7 +112,7 @@ kex_buf2prop(Buffer *raw, int *first_kex_follows)
                *first_kex_follows = i;
        debug2("kex_parse_kexinit: first_kex_follows %d ", i);
        i = buffer_get_int(&b);
-       debug2("kex_parse_kexinit: reserved %d ", i);
+       debug2("kex_parse_kexinit: reserved %u ", i);
        buffer_free(&b);
        return proposal;
 }
@@ -112,6 +127,7 @@ kex_prop_free(char **proposal)
        xfree(proposal);
 }
 
+/* ARGSUSED */
 static void
 kex_protocol_error(int type, u_int32_t seq, void *ctxt)
 {
@@ -183,6 +199,7 @@ kex_send_kexinit(Kex *kex)
        kex->flags |= KEX_INIT_SENT;
 }
 
+/* ARGSUSED */
 void
 kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
 {
@@ -214,8 +231,7 @@ kex_setup(char *proposal[PROPOSAL_MAX])
 {
        Kex *kex;
 
-       kex = xmalloc(sizeof(*kex));
-       memset(kex, 0, sizeof(*kex));
+       kex = xcalloc(1, sizeof(*kex));
        buffer_init(&kex->peer);
        buffer_init(&kex->my);
        kex_prop2buf(&kex->my, proposal);
@@ -248,7 +264,8 @@ choose_enc(Enc *enc, char *client, char *server)
 {
        char *name = match_list(client, server, NULL);
        if (name == NULL)
-               fatal("no matching cipher found: client %s server %s", client, server);
+               fatal("no matching cipher found: client %s server %s",
+                   client, server);
        if ((enc->cipher = cipher_by_name(name)) == NULL)
                fatal("matching cipher is not supported: %s", name);
        enc->name = name;
@@ -258,13 +275,15 @@ choose_enc(Enc *enc, char *client, char *server)
        enc->key_len = cipher_keylen(enc->cipher);
        enc->block_size = cipher_blocksize(enc->cipher);
 }
+
 static void
 choose_mac(Mac *mac, char *client, char *server)
 {
        char *name = match_list(client, server, NULL);
        if (name == NULL)
-               fatal("no matching mac found: client %s server %s", client, server);
-       if (mac_init(mac, name) < 0)
+               fatal("no matching mac found: client %s server %s",
+                   client, server);
+       if (mac_setup(mac, name) < 0)
                fatal("unsupported mac %s", name);
        /* truncate the key */
        if (datafellows & SSH_BUG_HMAC)
@@ -273,6 +292,7 @@ choose_mac(Mac *mac, char *client, char *server)
        mac->key = NULL;
        mac->enabled = 0;
 }
+
 static void
 choose_comp(Comp *comp, char *client, char *server)
 {
@@ -290,29 +310,45 @@ choose_comp(Comp *comp, char *client, char *server)
        }
        comp->name = name;
 }
+
 static void
 choose_kex(Kex *k, char *client, char *server)
 {
        k->name = match_list(client, server, NULL);
        if (k->name == NULL)
-               fatal("no kex alg");
+               fatal("Unable to negotiate a key exchange method");
        if (strcmp(k->name, KEX_DH1) == 0) {
                k->kex_type = KEX_DH_GRP1_SHA1;
+               k->evp_md = EVP_sha1();
        } else if (strcmp(k->name, KEX_DH14) == 0) {
                k->kex_type = KEX_DH_GRP14_SHA1;
-       } else if (strcmp(k->name, KEX_DHGEX) == 0) {
+               k->evp_md = EVP_sha1();
+       } else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) {
                k->kex_type = KEX_DH_GEX_SHA1;
+               k->evp_md = EVP_sha1();
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+       } else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) {
+               k->kex_type = KEX_DH_GEX_SHA256;
+               k->evp_md = evp_ssh_sha256();
+#endif
 #ifdef GSSAPI
        } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID,
-           sizeof(KEX_GSS_GEX_SHA1_ID)-1) == 0) {
+           sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) {
                k->kex_type = KEX_GSS_GEX_SHA1;
-       } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID, 
-           sizeof(KEX_GSS_GRP1_SHA1_ID)-1) == 0) {
+               k->evp_md = EVP_sha1();
+       } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID,
+           sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) {
                k->kex_type = KEX_GSS_GRP1_SHA1;
+               k->evp_md = EVP_sha1();
+       } else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID,
+           sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) {
+               k->kex_type = KEX_GSS_GRP14_SHA1;
+               k->evp_md = EVP_sha1();
 #endif
        } else
                fatal("bad kex alg %s", k->name);
 }
+
 static void
 choose_hostkeyalg(Kex *k, char *client, char *server)
 {
@@ -358,6 +394,13 @@ kex_choose_conf(Kex *kex)
        int nenc, nmac, ncomp;
        u_int mode, ctos, need;
        int first_kex_follows, type;
+       int log_flag = 0;
+
+       int auth_flag;
+
+       auth_flag = packet_authentication_state();
+
+       debug ("AUTH STATE IS %d", auth_flag);
 
        my   = kex_buf2prop(&kex->my, NULL);
        peer = kex_buf2prop(&kex->peer, &first_kex_follows);
@@ -372,21 +415,44 @@ kex_choose_conf(Kex *kex)
 
        /* Algorithm Negotiation */
        for (mode = 0; mode < MODE_MAX; mode++) {
-               newkeys = xmalloc(sizeof(*newkeys));
-               memset(newkeys, 0, sizeof(*newkeys));
+               newkeys = xcalloc(1, sizeof(*newkeys));
                kex->newkeys[mode] = newkeys;
-               ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN);
+               ctos = (!kex->server && mode == MODE_OUT) ||
+                   (kex->server && mode == MODE_IN);
                nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;
                nmac  = ctos ? PROPOSAL_MAC_ALGS_CTOS  : PROPOSAL_MAC_ALGS_STOC;
                ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
                choose_enc (&newkeys->enc,  cprop[nenc],  sprop[nenc]);
                choose_mac (&newkeys->mac,  cprop[nmac],  sprop[nmac]);
                choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
+               debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name);
+               if (strcmp(newkeys->enc.name, "none") == 0) {
+                               debug("Requesting NONE. Authflag is %d", auth_flag);                    
+                       if (auth_flag == 1) {
+                               debug("None requested post authentication.");
+                       } else {
+                               fatal("Pre-authentication none cipher requests are not allowed.");
+                       }
+               } 
                debug("kex: %s %s %s %s",
                    ctos ? "client->server" : "server->client",
                    newkeys->enc.name,
                    newkeys->mac.name,
                    newkeys->comp.name);
+               /* client starts withctos = 0 && log flag = 0 and no log*/
+               /* 2nd client pass ctos=1 and flag = 1 so no log*/
+               /* server starts with ctos =1 && log_flag = 0 so log */
+               /* 2nd sever pass ctos = 1 && log flag = 1 so no log*/
+               /* -cjr*/
+               if (ctos && !log_flag) {
+                       logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s",
+                             get_remote_ipaddr(),
+                             get_remote_port(),
+                             newkeys->enc.name,
+                             newkeys->mac.name,
+                             newkeys->comp.name);
+               }
+               log_flag = 1;
        }
        choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
        choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
@@ -416,28 +482,28 @@ kex_choose_conf(Kex *kex)
 }
 
 static u_char *
-derive_key(Kex *kex, int id, u_int need, u_char *hash, BIGNUM *shared_secret)
+derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen,
+    BIGNUM *shared_secret)
 {
        Buffer b;
-       const EVP_MD *evp_md = EVP_sha1();
        EVP_MD_CTX md;
        char c = id;
        u_int have;
-       int mdsz = EVP_MD_size(evp_md);
+       int mdsz;
        u_char *digest;
 
-       if (mdsz < 0)
-               fatal("derive_key: mdsz < 0");
+       if ((mdsz = EVP_MD_size(kex->evp_md)) <= 0)
+               fatal("bad kex md size %d", mdsz);
        digest = xmalloc(roundup(need, mdsz));
 
        buffer_init(&b);
        buffer_put_bignum2(&b, shared_secret);
 
        /* K1 = HASH(K || H || "A" || session_id) */
-       EVP_DigestInit(&md, evp_md);
+       EVP_DigestInit(&md, kex->evp_md);
        if (!(datafellows & SSH_BUG_DERIVEKEY))
                EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
-       EVP_DigestUpdate(&md, hash, mdsz);
+       EVP_DigestUpdate(&md, hash, hashlen);
        EVP_DigestUpdate(&md, &c, 1);
        EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len);
        EVP_DigestFinal(&md, digest, NULL);
@@ -448,10 +514,10 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, BIGNUM *shared_secret)
         * Key = K1 || K2 || ... || Kn
         */
        for (have = mdsz; need > have; have += mdsz) {
-               EVP_DigestInit(&md, evp_md);
+               EVP_DigestInit(&md, kex->evp_md);
                if (!(datafellows & SSH_BUG_DERIVEKEY))
                        EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
-               EVP_DigestUpdate(&md, hash, mdsz);
+               EVP_DigestUpdate(&md, hash, hashlen);
                EVP_DigestUpdate(&md, digest, have);
                EVP_DigestFinal(&md, digest + have, NULL);
        }
@@ -467,19 +533,22 @@ Newkeys *current_keys[MODE_MAX];
 
 #define NKEYS  6
 void
-kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret)
+kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, BIGNUM *shared_secret)
 {
        u_char *keys[NKEYS];
        u_int i, mode, ctos;
 
-       for (i = 0; i < NKEYS; i++)
-               keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret);
+       for (i = 0; i < NKEYS; i++) {
+               keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen,
+                   shared_secret);
+       }
 
        debug2("kex_derive_keys");
        for (mode = 0; mode < MODE_MAX; mode++) {
                current_keys[mode] = kex->newkeys[mode];
                kex->newkeys[mode] = NULL;
-               ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN);
+               ctos = (!kex->server && mode == MODE_OUT) ||
+                   (kex->server && mode == MODE_IN);
                current_keys[mode]->enc.iv  = keys[ctos ? 0 : 1];
                current_keys[mode]->enc.key = keys[ctos ? 2 : 3];
                current_keys[mode]->mac.key = keys[ctos ? 4 : 5];
@@ -536,7 +605,7 @@ dump_digest(char *msg, u_char *digest, int len)
        u_int i;
 
        fprintf(stderr, "%s\n", msg);
-       for (i = 0; i< len; i++) {
+       for (i = 0; i < len; i++) {
                fprintf(stderr, "%02x", digest[i]);
                if (i%32 == 31)
                        fprintf(stderr, "\n");
This page took 0.12953 seconds and 4 git commands to generate.