]> andersk Git - openssh.git/blobdiff - packet.c
- (djm) Bug #461: ssh-copy-id fails with no arguments. Patch from
[openssh.git] / packet.c
index 1c80af128ec863de0821d1caac1f1c985f06dbfa..3e2d1249d22b1e618c51fe91e9743bebbf91fcfd 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.102 2002/12/10 19:47:14 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;
@@ -118,6 +119,10 @@ 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;
 
@@ -129,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;
@@ -173,7 +179,7 @@ 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.
@@ -195,47 +201,59 @@ packet_get_keyiv(int mode, u_char *iv, u_int len)
 int
 packet_get_keycontext(int mode, u_char *dat)
 {
-       int plen;
        CipherContext *cc;
-       
+
        if (mode == MODE_OUT)
                cc = &send_context;
        else
                cc = &receive_context;
 
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
-       plen = sizeof(cc->evp.c);
-#else
-       plen = cc->evp.cipher->ctx_size;
-#endif
+       return (cipher_get_keycontext(cc, dat));
+}
 
-       if (dat == NULL)
-               return (plen);
+void
+packet_set_keycontext(int mode, u_char *dat)
+{
+       CipherContext *cc;
 
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
-       memcpy(dat, &cc->evp.c, sizeof(cc->evp.c));
-#else
-       memcpy(dat, &cc->evp.cipher_data, plen);
-#endif
-       return (plen);
+       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_keycontext(int mode, u_char *dat)
+packet_set_iv(int mode, u_char *dat)
 {
        CipherContext *cc;
-       
+
        if (mode == MODE_OUT)
                cc = &send_context;
        else
                cc = &receive_context;
 
-#if OPENSSL_VERSION_NUMBER < 0x00907000L
-       memcpy(&cc->evp.c, dat, sizeof(cc->evp.c));
-#else
-       memcpy(&cc->evp.cipher_data, dat, cc->evp.cipher->ctx_size);
-#endif
+       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)
@@ -251,7 +269,7 @@ packet_set_seqnr(int mode, u_int32_t seqnr)
        else if (mode == MODE_OUT)
                send_seqnr = seqnr;
        else
-               fatal("%s: bad mode %d", __FUNCTION__, mode);
+               fatal("packet_set_seqnr: bad mode %d", mode);
 }
 
 /* returns 1 if connection is via ipv4 */
@@ -265,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. */
@@ -374,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)
@@ -407,6 +445,7 @@ void
 packet_put_char(int value)
 {
        char ch = value;
+
        buffer_append(&outgoing_packet, &ch, 1);
 }
 void
@@ -525,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;
@@ -535,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;
@@ -632,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;
@@ -801,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. */
@@ -897,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 */
@@ -958,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.
@@ -979,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;
 
@@ -1002,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;
@@ -1027,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;
@@ -1065,6 +1106,7 @@ u_int
 packet_get_char(void)
 {
        char ch;
+
        buffer_get(&incoming_packet, &ch, 1);
        return (u_char) ch;
 }
@@ -1098,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);
@@ -1170,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;
@@ -1182,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);
@@ -1201,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();
 }
 
@@ -1212,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) {
@@ -1268,16 +1314,26 @@ packet_not_very_much_data_to_write(void)
                return buffer_len(&output) < 128 * 1024;
 }
 
+static void
+packet_set_tos(int interactive)
+{
+       int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT;
+
+       if (!packet_connection_is_on_socket() ||
+           !packet_connection_is_ipv4())
+               return;
+       if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos,
+           sizeof(tos)) < 0)
+               error("setsockopt IP_TOS %d: %.100s:",
+                   tos, strerror(errno));
+}
+
 /* Informs that the current session is interactive.  Sets IP flags for that. */
 
 void
 packet_set_interactive(int interactive)
 {
        static int called = 0;
-#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
-       int lowdelay = IPTOS_LOWDELAY;
-       int throughput = IPTOS_THROUGHPUT;
-#endif
 
        if (called)
                return;
@@ -1288,35 +1344,12 @@ packet_set_interactive(int interactive)
 
        /* Only set socket options if using a socket.  */
        if (!packet_connection_is_on_socket())
-               return;
-       /*
-        * IPTOS_LOWDELAY and IPTOS_THROUGHPUT are IPv4 only
-        */
-       if (interactive) {
-               /*
-                * Set IP options for an interactive connection.  Use
-                * IPTOS_LOWDELAY and TCP_NODELAY.
-                */
-#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
-               if (packet_connection_is_ipv4()) {
-                       if (setsockopt(connection_in, IPPROTO_IP, IP_TOS,
-                           &lowdelay, sizeof(lowdelay)) < 0)
-                               error("setsockopt IPTOS_LOWDELAY: %.100s",
-                                   strerror(errno));
-               }
-#endif
+       if (interactive)
                set_nodelay(connection_in);
-       } else if (packet_connection_is_ipv4()) {
-               /*
-                * Set IP options for a non-interactive connection.  Use
-                * IPTOS_THROUGHPUT.
-                */
 #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
-               if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput,
-                   sizeof(throughput)) < 0)
-                       error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
+       packet_set_tos(interactive);
 #endif
-       }
+
 }
 
 /* Returns true if the current connection is interactive. */
@@ -1331,6 +1364,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.746274 seconds and 4 git commands to generate.