*/
#include "includes.h"
-RCSID("$OpenBSD: packet.c,v 1.93 2002/03/24 16:01:13 markus Exp $");
+RCSID("$OpenBSD: packet.c,v 1.100 2002/11/21 22:45:31 markus Exp $");
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#include "canohost.h"
#include "misc.h"
+#include "ssh.h"
#ifdef PACKET_DEBUG
#define DBG(x) x
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;
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;
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 */
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. */
* 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)
packet_put_char(int value)
{
char ch = value;
+
buffer_append(&outgoing_packet, &ch, 1);
}
void
CipherContext *cc;
int encrypt;
- debug("newkeys: mode %d", mode);
+ debug2("set_newkeys: mode %d", mode);
if (mode == MODE_OUT) {
cc = &send_context;
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;
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. */
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 */
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.
int
packet_read_poll_seqnr(u_int32_t *seqnr_p)
{
- int reason, seqnr;
+ u_int reason, seqnr;
u_char type;
char *msg;
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;
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;
packet_get_char(void)
{
char ch;
+
buffer_get(&incoming_packet, &ch, 1);
return (u_char) ch;
}
packet_get_raw(int *length_ptr)
{
int bytes = buffer_len(&incoming_packet);
+
if (length_ptr != NULL)
*length_ptr = bytes;
return buffer_ptr(&incoming_packet);
char buf[1024];
va_list args;
static int disconnecting = 0;
+
if (disconnecting) /* Guard against recursive invocations. */
fatal("packet_disconnect called recursively.");
disconnecting = 1;
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);
/* Close the connection. */
packet_close();
- /* Display the error locally and exit. */
- log("Disconnecting: %.100s", buf);
fatal_cleanup();
}
packet_write_poll(void)
{
int len = buffer_len(&output);
+
if (len > 0) {
len = write(connection_out, buffer_ptr(&output), len);
if (len <= 0) {
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);