version 1.93, 2002/03/24 16:01:13 |
version 1.93.2.2, 2002/10/11 14:51:52 |
|
|
#include "log.h" |
#include "log.h" |
#include "canohost.h" |
#include "canohost.h" |
#include "misc.h" |
#include "misc.h" |
|
#include "ssh.h" |
|
|
#ifdef PACKET_DEBUG |
#ifdef PACKET_DEBUG |
#define DBG(x) x |
#define DBG(x) x |
|
|
static u_int32_t read_seqnr = 0; |
static u_int32_t read_seqnr = 0; |
static u_int32_t send_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 */ |
/* roundup current message to extra_pad bytes */ |
static u_char extra_pad = 0; |
static u_char extra_pad = 0; |
|
|
|
|
packet_set_connection(int fd_in, int fd_out) |
packet_set_connection(int fd_in, int fd_out) |
{ |
{ |
Cipher *none = cipher_by_name("none"); |
Cipher *none = cipher_by_name("none"); |
|
|
if (none == NULL) |
if (none == NULL) |
fatal("packet_set_connection: cannot load cipher 'none'"); |
fatal("packet_set_connection: cannot load cipher 'none'"); |
connection_in = fd_in; |
connection_in = fd_in; |
|
|
else if (mode == MODE_OUT) |
else if (mode == MODE_OUT) |
send_seqnr = seqnr; |
send_seqnr = seqnr; |
else |
else |
fatal("%s: bad mode %d", __FUNCTION__, mode); |
fatal("packet_set_seqnr: bad mode %d", mode); |
} |
} |
|
|
/* returns 1 if connection is via ipv4 */ |
/* returns 1 if connection is via ipv4 */ |
|
|
* key is used for both sending and reception. However, both directions are |
* key is used for both sending and reception. However, both directions are |
* encrypted independently of each other. |
* encrypted independently of each other. |
*/ |
*/ |
|
|
void |
void |
packet_set_encryption_key(const u_char *key, u_int keylen, |
packet_set_encryption_key(const u_char *key, u_int keylen, |
int number) |
int number) |
{ |
{ |
Cipher *cipher = cipher_by_number(number); |
Cipher *cipher = cipher_by_number(number); |
|
|
if (cipher == NULL) |
if (cipher == NULL) |
fatal("packet_set_encryption_key: unknown cipher number %d", number); |
fatal("packet_set_encryption_key: unknown cipher number %d", number); |
if (keylen < 20) |
if (keylen < 20) |
fatal("packet_set_encryption_key: keylen too small: %d", keylen); |
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(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); |
cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); |
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. */ |
/* Start constructing a packet to send. */ |
void |
void |
packet_start(u_char type) |
packet_start(u_char type) |
|
|
packet_put_char(int value) |
packet_put_char(int value) |
{ |
{ |
char ch = value; |
char ch = value; |
|
|
buffer_append(&outgoing_packet, &ch, 1); |
buffer_append(&outgoing_packet, &ch, 1); |
} |
} |
void |
void |
|
|
buffer_clear(&incoming_packet); |
buffer_clear(&incoming_packet); |
buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), |
buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), |
buffer_len(&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. |
* get packet type, implies consume. |
|
|
int |
int |
packet_read_poll_seqnr(u_int32_t *seqnr_p) |
packet_read_poll_seqnr(u_int32_t *seqnr_p) |
{ |
{ |
int reason, seqnr; |
u_int reason, seqnr; |
u_char type; |
u_char type; |
char *msg; |
char *msg; |
|
|
|
|
case SSH2_MSG_DISCONNECT: |
case SSH2_MSG_DISCONNECT: |
reason = packet_get_int(); |
reason = packet_get_int(); |
msg = packet_get_string(NULL); |
msg = packet_get_string(NULL); |
log("Received disconnect from %s: %d: %.400s", get_remote_ipaddr(), |
log("Received disconnect from %s: %u: %.400s", |
reason, msg); |
get_remote_ipaddr(), reason, msg); |
xfree(msg); |
xfree(msg); |
fatal_cleanup(); |
fatal_cleanup(); |
break; |
break; |
case SSH2_MSG_UNIMPLEMENTED: |
case SSH2_MSG_UNIMPLEMENTED: |
seqnr = packet_get_int(); |
seqnr = packet_get_int(); |
debug("Received SSH2_MSG_UNIMPLEMENTED for %d", seqnr); |
debug("Received SSH2_MSG_UNIMPLEMENTED for %u", |
|
seqnr); |
break; |
break; |
default: |
default: |
return type; |
return type; |
|
|
break; |
break; |
case SSH_MSG_DISCONNECT: |
case SSH_MSG_DISCONNECT: |
msg = packet_get_string(NULL); |
msg = packet_get_string(NULL); |
log("Received disconnect from %s: %.400s", get_remote_ipaddr(), |
log("Received disconnect from %s: %.400s", |
msg); |
get_remote_ipaddr(), msg); |
fatal_cleanup(); |
fatal_cleanup(); |
xfree(msg); |
xfree(msg); |
break; |
break; |
|
|
packet_get_char(void) |
packet_get_char(void) |
{ |
{ |
char ch; |
char ch; |
|
|
buffer_get(&incoming_packet, &ch, 1); |
buffer_get(&incoming_packet, &ch, 1); |
return (u_char) ch; |
return (u_char) ch; |
} |
} |
|
|
packet_get_raw(int *length_ptr) |
packet_get_raw(int *length_ptr) |
{ |
{ |
int bytes = buffer_len(&incoming_packet); |
int bytes = buffer_len(&incoming_packet); |
|
|
if (length_ptr != NULL) |
if (length_ptr != NULL) |
*length_ptr = bytes; |
*length_ptr = bytes; |
return buffer_ptr(&incoming_packet); |
return buffer_ptr(&incoming_packet); |
|
|
char buf[1024]; |
char buf[1024]; |
va_list args; |
va_list args; |
static int disconnecting = 0; |
static int disconnecting = 0; |
|
|
if (disconnecting) /* Guard against recursive invocations. */ |
if (disconnecting) /* Guard against recursive invocations. */ |
fatal("packet_disconnect called recursively."); |
fatal("packet_disconnect called recursively."); |
disconnecting = 1; |
disconnecting = 1; |
|
|
packet_write_poll(void) |
packet_write_poll(void) |
{ |
{ |
int len = buffer_len(&output); |
int len = buffer_len(&output); |
|
|
if (len > 0) { |
if (len > 0) { |
len = write(connection_out, buffer_ptr(&output), len); |
len = write(connection_out, buffer_ptr(&output), len); |
if (len <= 0) { |
if (len <= 0) { |
|
|
packet_set_maxsize(int s) |
packet_set_maxsize(int s) |
{ |
{ |
static int called = 0; |
static int called = 0; |
|
|
if (called) { |
if (called) { |
log("packet_set_maxsize: called twice: old %d new %d", |
log("packet_set_maxsize: called twice: old %d new %d", |
max_packet_size, s); |
max_packet_size, s); |