]> andersk Git - gssapi-openssh.git/blobdiff - openssh/packet.c
remove duplicate HPN lines
[gssapi-openssh.git] / openssh / packet.c
index 8abd43eb461946a1208b435a2abcf5c576283a43..7b77e2986f97f19ad2cc4889ece0803c3e2884a5 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.157 2008/07/10 18:08:11 markus Exp $ */
+/* $OpenBSD: packet.c,v 1.160 2009/02/13 11:50:21 markus Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -84,6 +84,8 @@
 #define DBG(x)
 #endif
 
+#define PACKET_MAX_SIZE (256 * 1024)
+
 /*
  * This variable contains the file descriptors used for communicating with
  * the other side.  connection_in is used for reading; connection_out for
@@ -160,6 +162,10 @@ static u_int ssh1_keylen;
 /* roundup current message to extra_pad bytes */
 static u_char extra_pad = 0;
 
+/* XXX discard incoming data after MAC error */
+static u_int packet_discard = 0;
+static Mac *packet_discard_mac = NULL;
+
 struct packet {
        TAILQ_ENTRY(packet) next;
        u_char type;
@@ -209,6 +215,36 @@ packet_set_timeout(int timeout, int count)
                packet_timeout_ms = timeout * count * 1000;
 }
 
+static void
+packet_stop_discard(void)
+{
+       if (packet_discard_mac) {
+               char buf[1024];
+               
+               memset(buf, 'a', sizeof(buf));
+               while (buffer_len(&incoming_packet) < PACKET_MAX_SIZE)
+                       buffer_append(&incoming_packet, buf, sizeof(buf));
+               (void) mac_compute(packet_discard_mac,
+                   p_read.seqnr,
+                   buffer_ptr(&incoming_packet),
+                   PACKET_MAX_SIZE);
+       }
+       logit("Finished discarding for %.200s", get_remote_ipaddr());
+       cleanup_exit(255);
+}
+
+static void
+packet_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard)
+{
+       if (enc == NULL || !cipher_is_cbc(enc->cipher))
+               packet_disconnect("Packet corrupt");
+       if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled)
+               packet_discard_mac = mac;
+       if (buffer_len(&input) >= discard)
+               packet_stop_discard();
+       packet_discard = discard - buffer_len(&input);
+}
+
 /* Returns 1 if remote host is connected via socket, 0 if not. */
 
 int
@@ -739,7 +775,7 @@ packet_enable_delayed_compress(void)
 /*
  * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
  */
-static void
+static int
 packet_send2_wrapped(void)
 {
        u_char type, *cp, *macbuf = NULL;
@@ -852,11 +888,13 @@ packet_send2_wrapped(void)
                set_newkeys(MODE_OUT);
        else if (type == SSH2_MSG_USERAUTH_SUCCESS && server_side)
                packet_enable_delayed_compress();
+       return(packet_length);
 }
 
-static void
+static int
 packet_send2(void)
 {
+        static int packet_length = 0;
        static int rekeying = 0;
        struct packet *p;
        u_char type, *cp;
@@ -874,7 +912,7 @@ packet_send2(void)
                        memcpy(&p->payload, &outgoing_packet, sizeof(Buffer));
                        buffer_init(&outgoing_packet);
                        TAILQ_INSERT_TAIL(&outgoing, p, next);
-                       return;
+                       return(sizeof(Buffer));
                }
        }
 
@@ -882,7 +920,7 @@ packet_send2(void)
        if (type == SSH2_MSG_KEXINIT)
                rekeying = 1;
 
-       packet_send2_wrapped();
+       packet_length = packet_send2_wrapped();
 
        /* after a NEWKEYS message we can send the complete queue */
        if (type == SSH2_MSG_NEWKEYS) {
@@ -895,19 +933,22 @@ packet_send2(void)
                            sizeof(Buffer));
                        TAILQ_REMOVE(&outgoing, p, next);
                        xfree(p);
-                       packet_send2_wrapped();
+                       packet_length += packet_send2_wrapped();
                }
        }
+       return(packet_length);
 }
 
-void
+int
 packet_send(void)
 {
+  int packet_len = 0;
        if (compat20)
-               packet_send2();
+               packet_len = packet_send2();
        else
                packet_send1();
        DBG(debug("packet_send done"));
+       return(packet_len);
 }
 
 /*
@@ -1127,6 +1168,9 @@ packet_read_poll2(u_int32_t *seqnr_p)
        Mac *mac   = NULL;
        Comp *comp = NULL;
 
+       if (packet_discard)
+               return SSH_MSG_NONE;
+
        if (newkeys[MODE_IN] != NULL) {
                enc  = &newkeys[MODE_IN]->enc;
                mac  = &newkeys[MODE_IN]->mac;
@@ -1148,11 +1192,14 @@ packet_read_poll2(u_int32_t *seqnr_p)
                    block_size);
                cp = buffer_ptr(&incoming_packet);
                packet_length = get_u32(cp);
-               if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
+               if (packet_length < 1 + 4 || packet_length > PACKET_MAX_SIZE) {
 #ifdef PACKET_DEBUG
                        buffer_dump(&incoming_packet);
 #endif
-                       packet_disconnect("Bad packet length %u.", packet_length);
+                       logit("Bad packet length %u.", packet_length);
+                       packet_start_discard(enc, mac, packet_length,
+                           PACKET_MAX_SIZE);
+                       return SSH_MSG_NONE;
                }
                DBG(debug("input: packet len %u", packet_length+4));
                buffer_consume(&input, block_size);
@@ -1161,9 +1208,13 @@ packet_read_poll2(u_int32_t *seqnr_p)
        need = 4 + packet_length - block_size;
        DBG(debug("partial packet %d, need %d, maclen %d", block_size,
            need, maclen));
-       if (need % block_size != 0)
-               fatal("padding error: need %d block %d mod %d",
+       if (need % block_size != 0) {
+               logit("padding error: need %d block %d mod %d",
                    need, block_size, need % block_size);
+               packet_start_discard(enc, mac, packet_length,
+                   PACKET_MAX_SIZE - block_size);
+               return SSH_MSG_NONE;
+       }
        /*
         * check if the entire packet has been received and
         * decrypt into incoming_packet
@@ -1185,11 +1236,19 @@ packet_read_poll2(u_int32_t *seqnr_p)
                macbuf = mac_compute(mac, p_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.");
+               if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) {
+                       logit("Corrupted MAC on input.");
+                       if (need > PACKET_MAX_SIZE)
+                               fatal("internal error need %d", need);
+                       packet_start_discard(enc, mac, packet_length,
+                           PACKET_MAX_SIZE - need);
+                       return SSH_MSG_NONE;
+               }
+                               
                DBG(debug("MAC #%d ok", p_read.seqnr));
                buffer_consume(&input, mac->mac_len);
        }
+       /* XXX now it's safe to use fatal/packet_disconnect */
        if (seqnr_p != NULL)
                *seqnr_p = p_read.seqnr;
        if (++p_read.seqnr == 0)
@@ -1322,6 +1381,13 @@ packet_read_poll(void)
 void
 packet_process_incoming(const char *buf, u_int len)
 {
+       if (packet_discard) {
+               keep_alive_timeouts = 0; /* ?? */
+               if (len >= packet_discard)
+                       packet_stop_discard();
+               packet_discard -= len;
+               return;
+       }
        buffer_append(&input, buf, len);
 }
 
@@ -1483,23 +1549,25 @@ packet_disconnect(const char *fmt,...)
 
 /* Checks if there is any buffered output, and tries to write some of the output. */
 
-void
+int
 packet_write_poll(void)
 {
-       int len = buffer_len(&output);
+       int len = 0;
+       len = buffer_len(&output);
 
        if (len > 0) {
                len = write(connection_out, buffer_ptr(&output), len);
                if (len == -1) {
                        if (errno == EINTR || errno == EAGAIN ||
                            errno == EWOULDBLOCK)
-                               return;
+                               return (0);
                        fatal("Write failed: %.100s", strerror(errno));
                }
                if (len == 0)
                        fatal("Write connection closed");
                buffer_consume(&output, len);
        }
+       return(len);
 }
 
 
@@ -1508,16 +1576,17 @@ packet_write_poll(void)
  * written.
  */
 
-void
+int
 packet_write_wait(void)
 {
        fd_set *setp;
        int ret, ms_remain;
        struct timeval start, timeout, *timeoutp = NULL;
+       u_int bytes_sent = 0;
 
        setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS),
            sizeof(fd_mask));
-       packet_write_poll();
+       bytes_sent += packet_write_poll();
        while (packet_have_data_to_write()) {
                memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
                    sizeof(fd_mask));
@@ -1551,9 +1620,10 @@ packet_write_wait(void)
                            "waiting to write", get_remote_ipaddr());
                        cleanup_exit(255);
                }
-               packet_write_poll();
+               bytes_sent += packet_write_poll();
        }
        xfree(setp);
+       return (bytes_sent);
 }
 
 /* Returns true if there is buffered data to write to the connection. */
@@ -1675,12 +1745,24 @@ packet_send_ignore(int nbytes)
        }
 }
 
+int rekey_requested = 0;
+void
+packet_request_rekeying(void)
+{
+       rekey_requested = 1;
+}
+
 #define MAX_PACKETS    (1U<<31)
 int
 packet_need_rekeying(void)
 {
        if (datafellows & SSH_BUG_NOREKEY)
                return 0;
+       if (rekey_requested == 1)
+       {
+               rekey_requested = 0;
+               return 1;
+       }
        return
            (p_send.packets > MAX_PACKETS) ||
            (p_read.packets > MAX_PACKETS) ||
@@ -1705,3 +1787,9 @@ packet_set_authenticated(void)
 {
        after_authentication = 1;
 }
+
+int
+packet_authentication_state(void)
+{
+       return(after_authentication);
+}
This page took 0.046427 seconds and 4 git commands to generate.