*/
#include "includes.h"
-RCSID("$OpenBSD: packet.c,v 1.48 2001/02/04 15:32:24 stevesk Exp $");
+RCSID("$OpenBSD: packet.c,v 1.56 2001/03/03 21:41:07 millert Exp $");
#include "xmalloc.h"
#include "buffer.h"
#include "ssh1.h"
#include "ssh2.h"
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/hmac.h>
#include "cipher.h"
#include "kex.h"
-#include "hmac.h"
+#include "mac.h"
#include "log.h"
#include "canohost.h"
void
packet_start(int type)
{
- DBG(debug("packet_start[%d]",type));
+ DBG(debug("packet_start[%d]", type));
if (use_ssh2_packet_format)
packet_start2(type);
else
*/
void
-packet_send1()
+packet_send1(void)
{
char buf[8], *cp;
int i, padding, len;
* Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
*/
void
-packet_send2()
+packet_send2(void)
{
+ static u_int32_t seqnr = 0;
u_char *macbuf = NULL;
char *cp;
u_int packet_length = 0;
u_int i, padlen, len;
u_int32_t rand = 0;
- static u_int seqnr = 0;
int type;
Enc *enc = NULL;
Mac *mac = NULL;
if (i % 4 == 0)
rand = arc4random();
cp[i] = rand & 0xff;
- rand <<= 8;
+ rand >>= 8;
}
} else {
/* clear padding */
/* compute MAC over seqnr and packet(length fields, payload, padding) */
if (mac && mac->enabled) {
- macbuf = hmac( mac->md, seqnr,
+ macbuf = mac_compute(mac, seqnr,
(u_char *) buffer_ptr(&outgoing_packet),
- buffer_len(&outgoing_packet),
- mac->key, mac->key_len
- );
+ buffer_len(&outgoing_packet));
DBG(debug("done calc MAC out #%d", seqnr));
}
/* encrypt packet and append to output buffer. */
packet_read(int *payload_len_ptr)
{
int type, len;
- fd_set set;
+ fd_set *setp;
char buf[8192];
DBG(debug("packet_read()"));
+ setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) *
+ sizeof(fd_mask));
+
/* Since we are blocking, ensure that all written packets have been sent. */
packet_write_wait();
|| type == SSH_CMSG_EXIT_CONFIRMATION))
packet_integrity_check(*payload_len_ptr, 0, type);
/* If we got a packet, return it. */
- if (type != SSH_MSG_NONE)
+ if (type != SSH_MSG_NONE) {
+ xfree(setp);
return type;
+ }
/*
* Otherwise, wait for some data to arrive, add it to the
* buffer, and try again.
*/
- FD_ZERO(&set);
- FD_SET(connection_in, &set);
+ memset(setp, 0, howmany(connection_in + 1, NFDBITS) *
+ sizeof(fd_mask));
+ FD_SET(connection_in, setp);
/* Wait for some data to arrive. */
- select(connection_in + 1, &set, NULL, NULL, NULL);
+ while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 &&
+ (errno == EAGAIN || errno == EINTR))
+ ;
/* Read data from the socket. */
len = read(connection_in, buf, sizeof(buf));
int
packet_read_poll2(int *payload_len_ptr)
{
+ static u_int32_t seqnr = 0;
+ static u_int packet_length = 0;
u_int padlen, need;
u_char buf[8], *macbuf;
u_char *ucp;
char *cp;
- static u_int packet_length = 0;
- static u_int seqnr = 0;
int type;
int maclen, block_size;
Enc *enc = NULL;
* increment sequence number for incoming packet
*/
if (mac && mac->enabled) {
- macbuf = hmac( mac->md, seqnr,
+ macbuf = mac_compute(mac, seqnr,
(u_char *) buffer_ptr(&incoming_packet),
- buffer_len(&incoming_packet),
- mac->key, mac->key_len
- );
+ buffer_len(&incoming_packet));
if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
packet_disconnect("Corrupted MAC on input.");
DBG(debug("MAC #%d ok", seqnr));
}
#ifdef PACKET_DEBUG
- fprintf(stderr, "read/plain[%d]:\r\n",type);
+ fprintf(stderr, "read/plain[%d]:\r\n", type);
buffer_dump(&incoming_packet);
#endif
return (u_char)type;
void
packet_write_wait()
{
+ fd_set *setp;
+
+ setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) *
+ sizeof(fd_mask));
packet_write_poll();
while (packet_have_data_to_write()) {
- fd_set set;
- FD_ZERO(&set);
- FD_SET(connection_out, &set);
- select(connection_out + 1, NULL, &set, NULL, NULL);
+ memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
+ sizeof(fd_mask));
+ FD_SET(connection_out, setp);
+ while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 &&
+ (errno == EAGAIN || errno == EINTR))
+ ;
packet_write_poll();
}
+ xfree(setp);
}
/* Returns true if there is buffered data to write to the connection. */
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
int on = 1;
if (called)
max_packet_size = s;
return s;
}
+
+/*
+ * 9.2. Ignored Data Message
+ *
+ * byte SSH_MSG_IGNORE
+ * string data
+ *
+ * All implementations MUST understand (and ignore) this message at any
+ * time (after receiving the protocol version). No implementation is
+ * required to send them. This message can be used as an additional
+ * protection measure against advanced traffic analysis techniques.
+ */
+/* size of current + ignore message should be n*sumlen bytes (w/o mac) */
+void
+packet_inject_ignore(int sumlen)
+{
+ int blocksize, padlen, have, need, nb, mini, nbytes;
+ Enc *enc = NULL;
+
+ if (use_ssh2_packet_format == 0)
+ return;
+
+ have = buffer_len(&outgoing_packet);
+ debug2("packet_inject_ignore: current %d", have);
+ if (kex != NULL)
+ enc = &kex->enc[MODE_OUT];
+ blocksize = enc ? enc->cipher->block_size : 8;
+ padlen = blocksize - (have % blocksize);
+ if (padlen < 4)
+ padlen += blocksize;
+ have += padlen;
+ have /= blocksize; /* # of blocks for current message */
+
+ nb = roundup(sumlen, blocksize) / blocksize; /* blocks for both */
+ mini = roundup(5+1+4+4, blocksize) / blocksize; /* minsize ignore msg */
+ need = nb - (have % nb); /* blocks for ignore */
+ if (need <= mini)
+ need += nb;
+ nbytes = (need - mini) * blocksize; /* size of ignore payload */
+ debug2("packet_inject_ignore: block %d have %d nb %d mini %d need %d",
+ blocksize, have, nb, mini, need);
+
+ /* enqueue current message and append a ignore message */
+ packet_send();
+ packet_send_ignore(nbytes);
+}
+
+void
+packet_send_ignore(int nbytes)
+{
+ u_int32_t rand = 0;
+ int i;
+
+ packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE);
+ packet_put_int(nbytes);
+ for(i = 0; i < nbytes; i++) {
+ if (i % 4 == 0)
+ rand = arc4random();
+ packet_put_char(rand & 0xff);
+ rand >>= 8;
+ }
+}