]> andersk Git - openssh.git/blobdiff - packet.c
- stevesk@cvs.openbsd.org 2002/12/04 04:36:47
[openssh.git] / packet.c
index 045d5a10556d7a8b8f840482f8800849c6bf5cab..0a8baa5b208555430c639970ed59c236bece060b 100644 (file)
--- a/packet.c
+++ b/packet.c
@@ -37,7 +37,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: packet.c,v 1.90 2002/02/27 21:23:13 stevesk Exp $");
+RCSID("$OpenBSD: packet.c,v 1.100 2002/11/21 22:45:31 markus Exp $");
 
 #include "xmalloc.h"
 #include "buffer.h"
@@ -60,6 +60,7 @@ RCSID("$OpenBSD: packet.c,v 1.90 2002/02/27 21:23:13 stevesk Exp $");
 #include "log.h"
 #include "canohost.h"
 #include "misc.h"
+#include "ssh.h"
 
 #ifdef PACKET_DEBUG
 #define DBG(x) x
@@ -86,10 +87,10 @@ static CipherContext receive_context;
 static CipherContext send_context;
 
 /* Buffer for raw input data from the socket. */
-static Buffer input;
+Buffer input;
 
 /* Buffer for raw output data going to the socket. */
-static Buffer output;
+Buffer output;
 
 /* Buffer for the partial outgoing packet being constructed. */
 static Buffer outgoing_packet;
@@ -115,6 +116,12 @@ static int interactive_mode = 0;
 
 /* Session key information for Encryption and MAC */
 Newkeys *newkeys[MODE_MAX];
+static u_int32_t read_seqnr = 0;
+static u_int32_t send_seqnr = 0;
+
+/* Session key for protocol v1 */
+static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
+static u_int ssh1_keylen;
 
 /* roundup current message to extra_pad bytes */
 static u_char extra_pad = 0;
@@ -127,6 +134,7 @@ void
 packet_set_connection(int fd_in, int fd_out)
 {
        Cipher *none = cipher_by_name("none");
+
        if (none == NULL)
                fatal("packet_set_connection: cannot load cipher 'none'");
        connection_in = fd_in;
@@ -171,6 +179,99 @@ packet_connection_is_on_socket(void)
        return 1;
 }
 
+/*
+ * Exports an IV from the CipherContext required to export the key
+ * state back from the unprivileged child to the privileged parent
+ * process.
+ */
+
+void
+packet_get_keyiv(int mode, u_char *iv, u_int len)
+{
+       CipherContext *cc;
+
+       if (mode == MODE_OUT)
+               cc = &send_context;
+       else
+               cc = &receive_context;
+
+       cipher_get_keyiv(cc, iv, len);
+}
+
+int
+packet_get_keycontext(int mode, u_char *dat)
+{
+       CipherContext *cc;
+
+       if (mode == MODE_OUT)
+               cc = &send_context;
+       else
+               cc = &receive_context;
+
+       return (cipher_get_keycontext(cc, dat));
+}
+
+void
+packet_set_keycontext(int mode, u_char *dat)
+{
+       CipherContext *cc;
+
+       if (mode == MODE_OUT)
+               cc = &send_context;
+       else
+               cc = &receive_context;
+
+       cipher_set_keycontext(cc, dat);
+}
+
+int
+packet_get_keyiv_len(int mode)
+{
+       CipherContext *cc;
+
+       if (mode == MODE_OUT)
+               cc = &send_context;
+       else
+               cc = &receive_context;
+
+       return (cipher_get_keyiv_len(cc));
+}
+void
+packet_set_iv(int mode, u_char *dat)
+{
+       CipherContext *cc;
+
+       if (mode == MODE_OUT)
+               cc = &send_context;
+       else
+               cc = &receive_context;
+
+       cipher_set_keyiv(cc, dat);
+}
+int
+packet_get_ssh1_cipher()
+{
+       return (cipher_get_number(receive_context.cipher));
+}
+
+
+u_int32_t
+packet_get_seqnr(int mode)
+{
+       return (mode == MODE_IN ? read_seqnr : send_seqnr);
+}
+
+void
+packet_set_seqnr(int mode, u_int32_t seqnr)
+{
+       if (mode == MODE_IN)
+               read_seqnr = seqnr;
+       else if (mode == MODE_OUT)
+               send_seqnr = seqnr;
+       else
+               fatal("packet_set_seqnr: bad mode %d", mode);
+}
+
 /* returns 1 if connection is via ipv4 */
 
 int
@@ -182,9 +283,14 @@ packet_connection_is_ipv4(void)
        memset(&to, 0, sizeof(to));
        if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)
                return 0;
-       if (to.ss_family != AF_INET)
-               return 0;
-       return 1;
+       if (to.ss_family == AF_INET)
+               return 1;
+#ifdef IPV4_IN_IPV6
+       if (to.ss_family == AF_INET6 && 
+           IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
+               return 1;
+#endif
+       return 0;
 }
 
 /* Sets the connection into non-blocking mode. */
@@ -291,19 +397,34 @@ packet_start_compression(int level)
  * key is used for both sending and reception.  However, both directions are
  * encrypted independently of each other.
  */
+
 void
 packet_set_encryption_key(const u_char *key, u_int keylen,
     int number)
 {
        Cipher *cipher = cipher_by_number(number);
+
        if (cipher == NULL)
                fatal("packet_set_encryption_key: unknown cipher number %d", number);
        if (keylen < 20)
                fatal("packet_set_encryption_key: keylen too small: %d", keylen);
+       if (keylen > SSH_SESSION_KEY_LENGTH)
+               fatal("packet_set_encryption_key: keylen too big: %d", keylen);
+       memcpy(ssh1_key, key, keylen);
+       ssh1_keylen = keylen;
        cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);
        cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);
 }
 
+u_int
+packet_get_encryption_key(u_char *key)
+{
+       if (key == NULL)
+               return (ssh1_keylen);
+       memcpy(key, ssh1_key, ssh1_keylen);
+       return (ssh1_keylen);
+}
+
 /* Start constructing a packet to send. */
 void
 packet_start(u_char type)
@@ -324,6 +445,7 @@ void
 packet_put_char(int value)
 {
        char ch = value;
+
        buffer_append(&outgoing_packet, &ch, 1);
 }
 void
@@ -433,7 +555,7 @@ packet_send1(void)
         */
 }
 
-static void
+void
 set_newkeys(int mode)
 {
        Enc *enc;
@@ -442,7 +564,7 @@ set_newkeys(int mode)
        CipherContext *cc;
        int encrypt;
 
-       debug("newkeys: mode %d", mode);
+       debug2("set_newkeys: mode %d", mode);
 
        if (mode == MODE_OUT) {
                cc = &send_context;
@@ -452,7 +574,7 @@ set_newkeys(int mode)
                encrypt = CIPHER_DECRYPT;
        }
        if (newkeys[mode] != NULL) {
-               debug("newkeys: rekeying");
+               debug("set_newkeys: rekeying");
                cipher_cleanup(cc);
                enc  = &newkeys[mode]->enc;
                mac  = &newkeys[mode]->mac;
@@ -477,8 +599,9 @@ set_newkeys(int mode)
        DBG(debug("cipher_init_context: %d", mode));
        cipher_init(cc, enc->cipher, enc->key, enc->key_len,
            enc->iv, enc->block_size, encrypt);
-       memset(enc->iv,  0, enc->block_size);
-       memset(enc->key, 0, enc->key_len);
+       /* Deleting the keys does not gain extra security */
+       /* memset(enc->iv,  0, enc->block_size);
+          memset(enc->key, 0, enc->key_len); */
        if (comp->type != 0 && comp->enabled == 0) {
                packet_init_compression();
                if (mode == MODE_OUT)
@@ -495,7 +618,6 @@ set_newkeys(int mode)
 static void
 packet_send2(void)
 {
-       static u_int32_t seqnr = 0;
        u_char type, *cp, *macbuf = NULL;
        u_char padlen, pad;
        u_int packet_length = 0;
@@ -549,7 +671,7 @@ packet_send2(void)
                /* will wrap if extra_pad+padlen > 255 */
                extra_pad  = roundup(extra_pad, block_size);
                pad = extra_pad - ((len + padlen) % extra_pad);
-               debug("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
+               debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
                    pad, len, padlen, extra_pad);
                padlen += pad;
                extra_pad = 0;
@@ -576,10 +698,10 @@ packet_send2(void)
 
        /* compute MAC over seqnr and packet(length fields, payload, padding) */
        if (mac && mac->enabled) {
-               macbuf = mac_compute(mac, seqnr,
+               macbuf = mac_compute(mac, send_seqnr,
                    buffer_ptr(&outgoing_packet),
                    buffer_len(&outgoing_packet));
-               DBG(debug("done calc MAC out #%d", seqnr));
+               DBG(debug("done calc MAC out #%d", send_seqnr));
        }
        /* encrypt packet and append to output buffer. */
        cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
@@ -593,7 +715,7 @@ packet_send2(void)
        buffer_dump(&output);
 #endif
        /* increment sequence number for outgoing packets */
-       if (++seqnr == 0)
+       if (++send_seqnr == 0)
                log("outgoing seqnr wraps around");
        buffer_clear(&outgoing_packet);
 
@@ -718,7 +840,7 @@ packet_read_poll1(void)
        cp = buffer_ptr(&input);
        len = GET_32BIT(cp);
        if (len < 1 + 2 + 2 || len > 256 * 1024)
-               packet_disconnect("Bad packet length %d.", len);
+               packet_disconnect("Bad packet length %u.", len);
        padded_len = (len + 8) & ~7;
 
        /* Check if the packet has been entirely received. */
@@ -783,7 +905,6 @@ packet_read_poll1(void)
 static int
 packet_read_poll2(u_int32_t *seqnr_p)
 {
-       static u_int32_t seqnr = 0;
        static u_int packet_length = 0;
        u_int padlen, need;
        u_char *macbuf, *cp, type;
@@ -815,9 +936,9 @@ packet_read_poll2(u_int32_t *seqnr_p)
                packet_length = GET_32BIT(cp);
                if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
                        buffer_dump(&incoming_packet);
-                       packet_disconnect("Bad packet length %d.", packet_length);
+                       packet_disconnect("Bad packet length %u.", packet_length);
                }
-               DBG(debug("input: packet len %d", packet_length+4));
+               DBG(debug("input: packet len %u", packet_length+4));
                buffer_consume(&input, block_size);
        }
        /* we have a partial packet of block_size bytes */
@@ -845,17 +966,17 @@ packet_read_poll2(u_int32_t *seqnr_p)
         * increment sequence number for incoming packet
         */
        if (mac && mac->enabled) {
-               macbuf = mac_compute(mac, seqnr,
+               macbuf = mac_compute(mac, read_seqnr,
                    buffer_ptr(&incoming_packet),
                    buffer_len(&incoming_packet));
                if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
                        packet_disconnect("Corrupted MAC on input.");
-               DBG(debug("MAC #%d ok", seqnr));
+               DBG(debug("MAC #%d ok", read_seqnr));
                buffer_consume(&input, mac->mac_len);
        }
        if (seqnr_p != NULL)
-               *seqnr_p = seqnr;
-       if (++seqnr == 0)
+               *seqnr_p = read_seqnr;
+       if (++read_seqnr == 0)
                log("incoming seqnr wraps around");
 
        /* get padlen */
@@ -876,7 +997,8 @@ packet_read_poll2(u_int32_t *seqnr_p)
                buffer_clear(&incoming_packet);
                buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
                    buffer_len(&compression_buffer));
-               DBG(debug("input: len after de-compress %d", buffer_len(&incoming_packet)));
+               DBG(debug("input: len after de-compress %d",
+                   buffer_len(&incoming_packet)));
        }
        /*
         * get packet type, implies consume.
@@ -897,7 +1019,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
 int
 packet_read_poll_seqnr(u_int32_t *seqnr_p)
 {
-       int reason, seqnr;
+       u_int reason, seqnr;
        u_char type;
        char *msg;
 
@@ -920,14 +1042,15 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p)
                        case SSH2_MSG_DISCONNECT:
                                reason = packet_get_int();
                                msg = packet_get_string(NULL);
-                               log("Received disconnect from %s: %d: %.400s", get_remote_ipaddr(),
-                                       reason, msg);
+                               log("Received disconnect from %s: %u: %.400s",
+                                   get_remote_ipaddr(), reason, msg);
                                xfree(msg);
                                fatal_cleanup();
                                break;
                        case SSH2_MSG_UNIMPLEMENTED:
                                seqnr = packet_get_int();
-                               debug("Received SSH2_MSG_UNIMPLEMENTED for %d", seqnr);
+                               debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
+                                   seqnr);
                                break;
                        default:
                                return type;
@@ -945,8 +1068,8 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p)
                                break;
                        case SSH_MSG_DISCONNECT:
                                msg = packet_get_string(NULL);
-                               log("Received disconnect from %s: %.400s", get_remote_ipaddr(),
-                                       msg);
+                               log("Received disconnect from %s: %.400s",
+                                   get_remote_ipaddr(), msg);
                                fatal_cleanup();
                                xfree(msg);
                                break;
@@ -983,6 +1106,7 @@ u_int
 packet_get_char(void)
 {
        char ch;
+
        buffer_get(&incoming_packet, &ch, 1);
        return (u_char) ch;
 }
@@ -1016,6 +1140,7 @@ void *
 packet_get_raw(int *length_ptr)
 {
        int bytes = buffer_len(&incoming_packet);
+
        if (length_ptr != NULL)
                *length_ptr = bytes;
        return buffer_ptr(&incoming_packet);
@@ -1088,6 +1213,7 @@ packet_disconnect(const char *fmt,...)
        char buf[1024];
        va_list args;
        static int disconnecting = 0;
+
        if (disconnecting)      /* Guard against recursive invocations. */
                fatal("packet_disconnect called recursively.");
        disconnecting = 1;
@@ -1100,6 +1226,9 @@ packet_disconnect(const char *fmt,...)
        vsnprintf(buf, sizeof(buf), fmt, args);
        va_end(args);
 
+       /* Display the error locally */
+       log("Disconnecting: %.100s", buf);
+
        /* Send the disconnect message to the other side, and wait for it to get sent. */
        if (compat20) {
                packet_start(SSH2_MSG_DISCONNECT);
@@ -1119,8 +1248,6 @@ packet_disconnect(const char *fmt,...)
        /* Close the connection. */
        packet_close();
 
-       /* Display the error locally and exit. */
-       log("Disconnecting: %.100s", buf);
        fatal_cleanup();
 }
 
@@ -1130,6 +1257,7 @@ void
 packet_write_poll(void)
 {
        int len = buffer_len(&output);
+
        if (len > 0) {
                len = write(connection_out, buffer_ptr(&output), len);
                if (len <= 0) {
@@ -1249,6 +1377,7 @@ int
 packet_set_maxsize(int s)
 {
        static int called = 0;
+
        if (called) {
                log("packet_set_maxsize: called twice: old %d new %d",
                    max_packet_size, s);
This page took 0.058643 seconds and 4 git commands to generate.