=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/packet.c,v retrieving revision 1.93 retrieving revision 1.93.2.3 diff -u -r1.93 -r1.93.2.3 --- src/usr.bin/ssh/packet.c 2002/03/24 16:01:13 1.93 +++ src/usr.bin/ssh/packet.c 2003/04/03 22:35:17 1.93.2.3 @@ -37,7 +37,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: packet.c,v 1.93 2002/03/24 16:01:13 markus Exp $"); +RCSID("$OpenBSD: packet.c,v 1.93.2.3 2003/04/03 22:35:17 miod Exp $"); #include "xmalloc.h" #include "buffer.h" @@ -60,6 +60,7 @@ #include "log.h" #include "canohost.h" #include "misc.h" +#include "ssh.h" #ifdef PACKET_DEBUG #define DBG(x) x @@ -118,6 +119,10 @@ 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 @@ 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; @@ -263,7 +269,7 @@ 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 */ @@ -386,19 +392,34 @@ * 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) @@ -419,6 +440,7 @@ packet_put_char(int value) { char ch = value; + buffer_append(&outgoing_packet, &ch, 1); } void @@ -537,7 +559,7 @@ CipherContext *cc; int encrypt; - debug("newkeys: mode %d", mode); + debug2("set_newkeys: mode %d", mode); if (mode == MODE_OUT) { cc = &send_context; @@ -547,7 +569,7 @@ 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; @@ -813,7 +835,7 @@ 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. */ @@ -909,9 +931,9 @@ 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 */ @@ -970,7 +992,8 @@ 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. @@ -991,7 +1014,7 @@ int packet_read_poll_seqnr(u_int32_t *seqnr_p) { - int reason, seqnr; + u_int reason, seqnr; u_char type; char *msg; @@ -1014,14 +1037,15 @@ 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; @@ -1039,8 +1063,8 @@ 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; @@ -1077,6 +1101,7 @@ packet_get_char(void) { char ch; + buffer_get(&incoming_packet, &ch, 1); return (u_char) ch; } @@ -1110,6 +1135,7 @@ packet_get_raw(int *length_ptr) { int bytes = buffer_len(&incoming_packet); + if (length_ptr != NULL) *length_ptr = bytes; return buffer_ptr(&incoming_packet); @@ -1182,6 +1208,7 @@ char buf[1024]; va_list args; static int disconnecting = 0; + if (disconnecting) /* Guard against recursive invocations. */ fatal("packet_disconnect called recursively."); disconnecting = 1; @@ -1194,6 +1221,9 @@ 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); @@ -1213,8 +1243,6 @@ /* Close the connection. */ packet_close(); - /* Display the error locally and exit. */ - log("Disconnecting: %.100s", buf); fatal_cleanup(); } @@ -1224,6 +1252,7 @@ packet_write_poll(void) { int len = buffer_len(&output); + if (len > 0) { len = write(connection_out, buffer_ptr(&output), len); if (len <= 0) { @@ -1280,14 +1309,26 @@ 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; - int lowdelay = IPTOS_LOWDELAY; - int throughput = IPTOS_THROUGHPUT; if (called) return; @@ -1299,30 +1340,9 @@ /* 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 (packet_connection_is_ipv4()) { - if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, - &lowdelay, sizeof(lowdelay)) < 0) - error("setsockopt IPTOS_LOWDELAY: %.100s", - strerror(errno)); - } + if (interactive) set_nodelay(connection_in); - } else if (packet_connection_is_ipv4()) { - /* - * Set IP options for a non-interactive connection. Use - * IPTOS_THROUGHPUT. - */ - if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput, - sizeof(throughput)) < 0) - error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno)); - } + packet_set_tos(interactive); } /* Returns true if the current connection is interactive. */ @@ -1337,6 +1357,7 @@ 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);