mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Give the BPP an input and output packet queue.
Now, instead of writing each packet straight on to the raw output bufchain by calling the BPP's format_packet function, the higher protocol layers will put the packets on to a queue, which will automatically trigger a callback (using the new mechanism for embedding a callback in any packet queue) to make the BPP format its queue on to the raw-output bufchain. That in turn triggers a second callback which moves the data to the socket. This means in particular that the CBC ignore-message workaround can be moved into the new BPP routine to process the output queue, which is a good place for it because then it can easily arrange to only put an ignore message at the start of any sequence of packets that are being formatted as a single output blob.
This commit is contained in:
parent
60d95b6a62
commit
6bb847738b
68
ssh.c
68
ssh.c
@ -474,8 +474,7 @@ struct ssh_tag {
|
||||
int incoming_data_seen_eof;
|
||||
char *incoming_data_eof_message;
|
||||
|
||||
PktInQueue pq_full;
|
||||
struct IdempotentCallback pq_full_consumer;
|
||||
struct IdempotentCallback incoming_pkt_consumer;
|
||||
|
||||
PktInQueue pq_ssh1_login;
|
||||
struct IdempotentCallback ssh1_login_icb;
|
||||
@ -725,22 +724,7 @@ static int s_write(Ssh ssh, const void *data, int len)
|
||||
|
||||
static void ssh_pkt_write(Ssh ssh, PktOut *pkt)
|
||||
{
|
||||
if (ssh->version == 2 && ssh->v2_cbc_ignore_workaround &&
|
||||
bufchain_size(&ssh->outgoing_data) != 0) {
|
||||
/*
|
||||
* When using a CBC-mode cipher in SSH-2, it's necessary to
|
||||
* ensure that an attacker can't provide data to be encrypted
|
||||
* using an IV that they know. We ensure this by prefixing
|
||||
* each packet that might contain user data with an
|
||||
* SSH_MSG_IGNORE.
|
||||
*/
|
||||
PktOut *ipkt = ssh_bpp_new_pktout(ssh->bpp, SSH2_MSG_IGNORE);
|
||||
put_stringz(ipkt, "");
|
||||
ssh_bpp_format_packet(ssh->bpp, ipkt);
|
||||
}
|
||||
|
||||
ssh_bpp_format_packet(ssh->bpp, pkt);
|
||||
queue_idempotent_callback(&ssh->outgoing_data_sender);
|
||||
pq_push(&ssh->bpp->out_pq, pkt);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -881,8 +865,6 @@ static void ssh2_add_sigblob(Ssh ssh, PktOut *pkt,
|
||||
|
||||
static void ssh_feed_to_bpp(Ssh ssh)
|
||||
{
|
||||
PacketQueueNode *prev_tail = ssh->pq_full.pqb.end.prev;
|
||||
|
||||
assert(ssh->bpp);
|
||||
ssh_bpp_handle_input(ssh->bpp);
|
||||
|
||||
@ -904,9 +886,6 @@ static void ssh_feed_to_bpp(Ssh ssh)
|
||||
ssh->close_expected = TRUE;
|
||||
ssh->disconnect_message_seen = TRUE;
|
||||
}
|
||||
|
||||
if (ssh->pq_full.pqb.end.prev != prev_tail)
|
||||
queue_idempotent_callback(&ssh->pq_full_consumer);
|
||||
}
|
||||
|
||||
static void ssh_got_ssh_version(struct ssh_version_receiver *rcv,
|
||||
@ -976,12 +955,14 @@ static void ssh_got_ssh_version(struct ssh_version_receiver *rcv,
|
||||
}
|
||||
|
||||
ssh->bpp->out_raw = &ssh->outgoing_data;
|
||||
ssh->bpp->out_raw->ic = &ssh->outgoing_data_sender;
|
||||
ssh->bpp->in_raw = &ssh->incoming_data;
|
||||
ssh->bpp->in_pq = &ssh->pq_full;
|
||||
ssh->bpp->in_pq.pqb.ic = &ssh->incoming_pkt_consumer;
|
||||
ssh->bpp->pls = &ssh->pls;
|
||||
ssh->bpp->logctx = ssh->logctx;
|
||||
ssh->bpp->remote_bugs = ssh->remote_bugs;
|
||||
|
||||
queue_idempotent_callback(&ssh->incoming_data_consumer);
|
||||
queue_idempotent_callback(&ssh->bpp->ic_in_raw);
|
||||
queue_idempotent_callback(&ssh->user_input_consumer);
|
||||
|
||||
update_specials_menu(ssh->frontend);
|
||||
@ -1034,12 +1015,12 @@ static void ssh_process_incoming_data(void *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void ssh_process_pq_full(void *ctx)
|
||||
static void ssh_process_incoming_pkts(void *ctx)
|
||||
{
|
||||
Ssh ssh = (Ssh)ctx;
|
||||
PktIn *pktin;
|
||||
|
||||
while ((pktin = pq_pop(&ssh->pq_full)) != NULL) {
|
||||
while ((pktin = pq_pop(&ssh->bpp->in_pq)) != NULL) {
|
||||
if (ssh->general_packet_processing)
|
||||
ssh->general_packet_processing(ssh, pktin);
|
||||
ssh->packet_dispatch[pktin->type](ssh, pktin);
|
||||
@ -1730,6 +1711,13 @@ static void do_ssh1_login(void *vctx)
|
||||
|
||||
sfree(s->rsabuf);
|
||||
|
||||
/*
|
||||
* Force the BPP to synchronously marshal all packets up to and
|
||||
* including the SESSION_KEY into wire format, before we turn on
|
||||
* crypto.
|
||||
*/
|
||||
ssh_bpp_handle_output(ssh->bpp);
|
||||
|
||||
{
|
||||
const struct ssh1_cipheralg *cipher =
|
||||
(s->cipher_type == SSH_CIPHER_BLOWFISH ? &ssh1_blowfish :
|
||||
@ -5077,6 +5065,13 @@ static void do_ssh2_transport(void *vctx)
|
||||
ssh->stats.out.running = TRUE;
|
||||
ssh->stats.out.remaining = ssh->max_data_size;
|
||||
|
||||
/*
|
||||
* Force the BPP to synchronously marshal all packets up to and
|
||||
* including that NEWKEYS into wire format, before we switch over
|
||||
* to new crypto.
|
||||
*/
|
||||
ssh_bpp_handle_output(ssh->bpp);
|
||||
|
||||
/*
|
||||
* We've sent client NEWKEYS, so create and initialise
|
||||
* client-to-server session keys.
|
||||
@ -6616,10 +6611,10 @@ static void ssh2_msg_userauth(Ssh ssh, PktIn *pktin)
|
||||
* protocol has officially started, which means we must
|
||||
* install the dispatch-table entries for all the
|
||||
* connection-layer messages. In particular, we must do this
|
||||
* _before_ we return to the loop in ssh_process_pq_full
|
||||
* _before_ we return to the loop in ssh_process_incoming_pkts
|
||||
* that's processing the currently queued packets through the
|
||||
* dispatch table, because if (say) an SSH_MSG_GLOBAL_REQUEST
|
||||
* is already pending in pq_full, we can't afford to delay
|
||||
* is already pending in in_pq, we can't afford to delay
|
||||
* installing its dispatch table entry until after that queue
|
||||
* run is done.
|
||||
*/
|
||||
@ -8331,14 +8326,15 @@ static void do_ssh2_connection(void *vctx)
|
||||
|
||||
/*
|
||||
* Put our current pending packet queue back to the front of
|
||||
* pq_full, and then schedule a callback to re-process those
|
||||
* the main pq, and then schedule a callback to re-process those
|
||||
* packets (if any). That way, anything already in our queue that
|
||||
* matches any of the table entries we've just modified will go to
|
||||
* the right handler function, and won't come here to confuse us.
|
||||
*/
|
||||
if (pq_peek(&ssh->pq_ssh2_connection)) {
|
||||
pq_concatenate(&ssh->pq_full, &ssh->pq_ssh2_connection, &ssh->pq_full);
|
||||
queue_idempotent_callback(&ssh->pq_full_consumer);
|
||||
pq_concatenate(&ssh->bpp->in_pq,
|
||||
&ssh->pq_ssh2_connection, &ssh->bpp->in_pq);
|
||||
queue_idempotent_callback(ssh->bpp->in_pq.pqb.ic);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -9005,10 +9001,9 @@ static const char *ssh_init(Frontend *frontend, Backend **backend_handle,
|
||||
ssh->incoming_data_consumer.fn = ssh_process_incoming_data;
|
||||
ssh->incoming_data_consumer.ctx = ssh;
|
||||
ssh->incoming_data_consumer.queued = FALSE;
|
||||
pq_in_init(&ssh->pq_full);
|
||||
ssh->pq_full_consumer.fn = ssh_process_pq_full;
|
||||
ssh->pq_full_consumer.ctx = ssh;
|
||||
ssh->pq_full_consumer.queued = FALSE;
|
||||
ssh->incoming_pkt_consumer.fn = ssh_process_incoming_pkts;
|
||||
ssh->incoming_pkt_consumer.ctx = ssh;
|
||||
ssh->incoming_pkt_consumer.queued = FALSE;
|
||||
pq_in_init(&ssh->pq_ssh1_login);
|
||||
ssh->ssh1_login_icb.fn = do_ssh1_login;
|
||||
ssh->ssh1_login_icb.ctx = ssh;
|
||||
@ -9191,7 +9186,6 @@ static void ssh_free(Backend *be)
|
||||
bufchain_clear(&ssh->incoming_data);
|
||||
bufchain_clear(&ssh->outgoing_data);
|
||||
sfree(ssh->incoming_data_eof_message);
|
||||
pq_in_clear(&ssh->pq_full);
|
||||
pq_in_clear(&ssh->pq_ssh1_login);
|
||||
pq_in_clear(&ssh->pq_ssh1_connection);
|
||||
pq_in_clear(&ssh->pq_ssh2_transport);
|
||||
|
23
ssh1bpp.c
23
ssh1bpp.c
@ -30,14 +30,14 @@ struct ssh1_bpp_state {
|
||||
|
||||
static void ssh1_bpp_free(BinaryPacketProtocol *bpp);
|
||||
static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp);
|
||||
static void ssh1_bpp_handle_output(BinaryPacketProtocol *bpp);
|
||||
static PktOut *ssh1_bpp_new_pktout(int type);
|
||||
static void ssh1_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt);
|
||||
|
||||
static const struct BinaryPacketProtocolVtable ssh1_bpp_vtable = {
|
||||
ssh1_bpp_free,
|
||||
ssh1_bpp_handle_input,
|
||||
ssh1_bpp_handle_output,
|
||||
ssh1_bpp_new_pktout,
|
||||
ssh1_bpp_format_packet,
|
||||
};
|
||||
|
||||
BinaryPacketProtocol *ssh1_bpp_new(void)
|
||||
@ -45,6 +45,7 @@ BinaryPacketProtocol *ssh1_bpp_new(void)
|
||||
struct ssh1_bpp_state *s = snew(struct ssh1_bpp_state);
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->bpp.vt = &ssh1_bpp_vtable;
|
||||
ssh_bpp_common_setup(&s->bpp);
|
||||
return &s->bpp;
|
||||
}
|
||||
|
||||
@ -202,7 +203,7 @@ static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
pq_push(s->bpp.in_pq, s->pktin);
|
||||
pq_push(&s->bpp.in_pq, s->pktin);
|
||||
|
||||
{
|
||||
int type = s->pktin->type;
|
||||
@ -241,9 +242,8 @@ static PktOut *ssh1_bpp_new_pktout(int pkt_type)
|
||||
return pkt;
|
||||
}
|
||||
|
||||
static void ssh1_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt)
|
||||
static void ssh1_bpp_format_packet(struct ssh1_bpp_state *s, PktOut *pkt)
|
||||
{
|
||||
struct ssh1_bpp_state *s = FROMFIELD(bpp, struct ssh1_bpp_state, bpp);
|
||||
int pad, biglen, i, pktoffs;
|
||||
unsigned long crc;
|
||||
int len;
|
||||
@ -290,6 +290,15 @@ static void ssh1_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt)
|
||||
|
||||
bufchain_add(s->bpp.out_raw, pkt->data + pktoffs,
|
||||
biglen + 4); /* len(length+padding+type+data+CRC) */
|
||||
|
||||
ssh_free_pktout(pkt);
|
||||
}
|
||||
|
||||
static void ssh1_bpp_handle_output(BinaryPacketProtocol *bpp)
|
||||
{
|
||||
struct ssh1_bpp_state *s = FROMFIELD(bpp, struct ssh1_bpp_state, bpp);
|
||||
PktOut *pkt;
|
||||
|
||||
while ((pkt = pq_pop(&s->bpp.out_pq)) != NULL) {
|
||||
ssh1_bpp_format_packet(s, pkt);
|
||||
ssh_free_pktout(pkt);
|
||||
}
|
||||
}
|
||||
|
@ -22,14 +22,14 @@ struct ssh2_bare_bpp_state {
|
||||
|
||||
static void ssh2_bare_bpp_free(BinaryPacketProtocol *bpp);
|
||||
static void ssh2_bare_bpp_handle_input(BinaryPacketProtocol *bpp);
|
||||
static void ssh2_bare_bpp_handle_output(BinaryPacketProtocol *bpp);
|
||||
static PktOut *ssh2_bare_bpp_new_pktout(int type);
|
||||
static void ssh2_bare_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *);
|
||||
|
||||
static const struct BinaryPacketProtocolVtable ssh2_bare_bpp_vtable = {
|
||||
ssh2_bare_bpp_free,
|
||||
ssh2_bare_bpp_handle_input,
|
||||
ssh2_bare_bpp_handle_output,
|
||||
ssh2_bare_bpp_new_pktout,
|
||||
ssh2_bare_bpp_format_packet,
|
||||
};
|
||||
|
||||
BinaryPacketProtocol *ssh2_bare_bpp_new(void)
|
||||
@ -37,6 +37,7 @@ BinaryPacketProtocol *ssh2_bare_bpp_new(void)
|
||||
struct ssh2_bare_bpp_state *s = snew(struct ssh2_bare_bpp_state);
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->bpp.vt = &ssh2_bare_bpp_vtable;
|
||||
ssh_bpp_common_setup(&s->bpp);
|
||||
return &s->bpp;
|
||||
}
|
||||
|
||||
@ -120,7 +121,7 @@ static void ssh2_bare_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
continue;
|
||||
}
|
||||
|
||||
pq_push(s->bpp.in_pq, s->pktin);
|
||||
pq_push(&s->bpp.in_pq, s->pktin);
|
||||
|
||||
{
|
||||
int type = s->pktin->type;
|
||||
@ -142,11 +143,9 @@ static PktOut *ssh2_bare_bpp_new_pktout(int pkt_type)
|
||||
return pkt;
|
||||
}
|
||||
|
||||
static void ssh2_bare_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt)
|
||||
static void ssh2_bare_bpp_format_packet(struct ssh2_bare_bpp_state *s,
|
||||
PktOut *pkt)
|
||||
{
|
||||
struct ssh2_bare_bpp_state *s =
|
||||
FROMFIELD(bpp, struct ssh2_bare_bpp_state, bpp);
|
||||
|
||||
if (s->bpp.logctx) {
|
||||
ptrlen pktdata = make_ptrlen(pkt->data + 5, pkt->length - 5);
|
||||
logblank_t blanks[MAX_BLANKS];
|
||||
@ -164,6 +163,16 @@ static void ssh2_bare_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt)
|
||||
|
||||
PUT_32BIT(pkt->data, pkt->length - 4);
|
||||
bufchain_add(s->bpp.out_raw, pkt->data, pkt->length);
|
||||
|
||||
ssh_free_pktout(pkt);
|
||||
}
|
||||
|
||||
static void ssh2_bare_bpp_handle_output(BinaryPacketProtocol *bpp)
|
||||
{
|
||||
struct ssh2_bare_bpp_state *s =
|
||||
FROMFIELD(bpp, struct ssh2_bare_bpp_state, bpp);
|
||||
PktOut *pkt;
|
||||
|
||||
while ((pkt = pq_pop(&s->bpp.out_pq)) != NULL) {
|
||||
ssh2_bare_bpp_format_packet(s, pkt);
|
||||
ssh_free_pktout(pkt);
|
||||
}
|
||||
}
|
||||
|
55
ssh2bpp.c
55
ssh2bpp.c
@ -25,6 +25,7 @@ struct ssh2_bpp_state {
|
||||
unsigned cipherblk;
|
||||
PktIn *pktin;
|
||||
struct DataTransferStats *stats;
|
||||
int cbc_ignore_workaround;
|
||||
|
||||
struct ssh2_bpp_direction in, out;
|
||||
/* comp and decomp logically belong in the per-direction
|
||||
@ -39,14 +40,14 @@ struct ssh2_bpp_state {
|
||||
|
||||
static void ssh2_bpp_free(BinaryPacketProtocol *bpp);
|
||||
static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp);
|
||||
static void ssh2_bpp_handle_output(BinaryPacketProtocol *bpp);
|
||||
static PktOut *ssh2_bpp_new_pktout(int type);
|
||||
static void ssh2_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt);
|
||||
|
||||
static const struct BinaryPacketProtocolVtable ssh2_bpp_vtable = {
|
||||
ssh2_bpp_free,
|
||||
ssh2_bpp_handle_input,
|
||||
ssh2_bpp_handle_output,
|
||||
ssh2_bpp_new_pktout,
|
||||
ssh2_bpp_format_packet,
|
||||
};
|
||||
|
||||
BinaryPacketProtocol *ssh2_bpp_new(struct DataTransferStats *stats)
|
||||
@ -55,6 +56,7 @@ BinaryPacketProtocol *ssh2_bpp_new(struct DataTransferStats *stats)
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->bpp.vt = &ssh2_bpp_vtable;
|
||||
s->stats = stats;
|
||||
ssh_bpp_common_setup(&s->bpp);
|
||||
return &s->bpp;
|
||||
}
|
||||
|
||||
@ -99,8 +101,13 @@ void ssh2_bpp_new_outgoing_crypto(
|
||||
s->out.cipher = ssh2_cipher_new(cipher);
|
||||
ssh2_cipher_setkey(s->out.cipher, ckey);
|
||||
ssh2_cipher_setiv(s->out.cipher, iv);
|
||||
|
||||
s->cbc_ignore_workaround = (
|
||||
(ssh2_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_IS_CBC) &&
|
||||
!(s->bpp.remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE));
|
||||
} else {
|
||||
s->out.cipher = NULL;
|
||||
s->cbc_ignore_workaround = FALSE;
|
||||
}
|
||||
s->out.etm_mode = etm_mode;
|
||||
if (mac) {
|
||||
@ -478,7 +485,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
continue;
|
||||
}
|
||||
|
||||
pq_push(s->bpp.in_pq, s->pktin);
|
||||
pq_push(&s->bpp.in_pq, s->pktin);
|
||||
|
||||
{
|
||||
int type = s->pktin->type;
|
||||
@ -611,10 +618,8 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
|
||||
|
||||
}
|
||||
|
||||
static void ssh2_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt)
|
||||
static void ssh2_bpp_format_packet(struct ssh2_bpp_state *s, PktOut *pkt)
|
||||
{
|
||||
struct ssh2_bpp_state *s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp);
|
||||
|
||||
if (pkt->minlen > 0 && !s->out_comp) {
|
||||
/*
|
||||
* If we've been told to pad the packet out to a given minimum
|
||||
@ -678,6 +683,40 @@ static void ssh2_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt)
|
||||
|
||||
ssh2_bpp_format_packet_inner(s, pkt);
|
||||
bufchain_add(s->bpp.out_raw, pkt->data, pkt->length);
|
||||
|
||||
ssh_free_pktout(pkt);
|
||||
}
|
||||
|
||||
static void ssh2_bpp_handle_output(BinaryPacketProtocol *bpp)
|
||||
{
|
||||
struct ssh2_bpp_state *s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp);
|
||||
PktOut *pkt;
|
||||
|
||||
if (s->cbc_ignore_workaround) {
|
||||
/*
|
||||
* When using a CBC-mode cipher in SSH-2, it's necessary to
|
||||
* ensure that an attacker can't provide data to be encrypted
|
||||
* using an IV that they know. We ensure this by inserting an
|
||||
* SSH_MSG_IGNORE if the last cipher block of the previous
|
||||
* packet has already been sent to the network (which we
|
||||
* approximate conservatively by checking if it's vanished
|
||||
* from out_raw).
|
||||
*/
|
||||
if (bufchain_size(s->bpp.out_raw) <
|
||||
(ssh2_cipher_alg(s->out.cipher)->blksize +
|
||||
ssh2_mac_alg(s->out.mac)->len)) {
|
||||
/*
|
||||
* There's less data in out_raw than the MAC size plus the
|
||||
* cipher block size, which means at least one byte of
|
||||
* that cipher block must already have left. Add an
|
||||
* IGNORE.
|
||||
*/
|
||||
pkt = ssh_bpp_new_pktout(&s->bpp, SSH2_MSG_IGNORE);
|
||||
put_stringz(pkt, "");
|
||||
ssh2_bpp_format_packet(s, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
while ((pkt = pq_pop(&s->bpp.out_pq)) != NULL) {
|
||||
ssh2_bpp_format_packet(s, pkt);
|
||||
ssh_free_pktout(pkt);
|
||||
}
|
||||
}
|
||||
|
30
sshbpp.h
30
sshbpp.h
@ -5,30 +5,44 @@
|
||||
#ifndef PUTTY_SSHBPP_H
|
||||
#define PUTTY_SSHBPP_H
|
||||
|
||||
typedef struct BinaryPacketProtocol BinaryPacketProtocol;
|
||||
|
||||
struct BinaryPacketProtocolVtable {
|
||||
void (*free)(BinaryPacketProtocol *);
|
||||
void (*handle_input)(BinaryPacketProtocol *);
|
||||
void (*handle_output)(BinaryPacketProtocol *);
|
||||
PktOut *(*new_pktout)(int type);
|
||||
void (*format_packet)(BinaryPacketProtocol *, PktOut *);
|
||||
};
|
||||
|
||||
struct BinaryPacketProtocol {
|
||||
const struct BinaryPacketProtocolVtable *vt;
|
||||
bufchain *in_raw, *out_raw;
|
||||
PktInQueue *in_pq;
|
||||
PktInQueue in_pq;
|
||||
PktOutQueue out_pq;
|
||||
PacketLogSettings *pls;
|
||||
LogContext *logctx;
|
||||
Ssh ssh;
|
||||
|
||||
/* ic_in_raw is filled in by the BPP (probably by calling
|
||||
* ssh_bpp_common_setup). The BPP's owner triggers it when data is
|
||||
* added to in_raw, and also when the BPP is newly created. */
|
||||
IdempotentCallback ic_in_raw;
|
||||
|
||||
/* ic_out_pq is entirely internal to the BPP itself; it's used as
|
||||
* the callback on out_pq. */
|
||||
IdempotentCallback ic_out_pq;
|
||||
|
||||
int remote_bugs;
|
||||
|
||||
int seen_disconnect;
|
||||
char *error;
|
||||
};
|
||||
|
||||
#define ssh_bpp_free(bpp) ((bpp)->vt->free(bpp))
|
||||
#define ssh_bpp_handle_input(bpp) ((bpp)->vt->handle_input(bpp))
|
||||
#define ssh_bpp_handle_output(bpp) ((bpp)->vt->handle_output(bpp))
|
||||
#define ssh_bpp_new_pktout(bpp, type) ((bpp)->vt->new_pktout(type))
|
||||
#define ssh_bpp_format_packet(bpp, pkt) ((bpp)->vt->format_packet(bpp, pkt))
|
||||
|
||||
/* ssh_bpp_free is more than just a macro wrapper on the vtable; it
|
||||
* does centralised parts of the freeing too. */
|
||||
void ssh_bpp_free(BinaryPacketProtocol *bpp);
|
||||
|
||||
BinaryPacketProtocol *ssh1_bpp_new(void);
|
||||
void ssh1_bpp_new_cipher(BinaryPacketProtocol *bpp,
|
||||
@ -40,6 +54,10 @@ void ssh1_bpp_new_cipher(BinaryPacketProtocol *bpp,
|
||||
* up zlib compression if it was SUCCESS. */
|
||||
void ssh1_bpp_requested_compression(BinaryPacketProtocol *bpp);
|
||||
|
||||
/* Helper routine which does common BPP initialisation, e.g. setting
|
||||
* up in_pq and out_pq, and initialising input_consumer. */
|
||||
void ssh_bpp_common_setup(BinaryPacketProtocol *);
|
||||
|
||||
/* Common helper function between the SSH-2 full and bare BPPs */
|
||||
int ssh2_bpp_check_unimplemented(BinaryPacketProtocol *bpp, PktIn *pktin);
|
||||
|
||||
|
35
sshcommon.c
35
sshcommon.c
@ -252,6 +252,7 @@ void ssh_free_pktout(PktOut *pkt)
|
||||
sfree(pkt->data);
|
||||
sfree(pkt);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Implement zombiechan_new() and its trivial vtable.
|
||||
*/
|
||||
@ -630,9 +631,39 @@ const char *ssh2_pkt_type(Pkt_KCtx pkt_kctx, Pkt_ACtx pkt_actx, int type)
|
||||
#undef TRANSLATE_AUTH
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Common helper function for implementations of BinaryPacketProtocol.
|
||||
* Common helper functions for clients and implementations of
|
||||
* BinaryPacketProtocol.
|
||||
*/
|
||||
|
||||
static void ssh_bpp_input_raw_data_callback(void *context)
|
||||
{
|
||||
BinaryPacketProtocol *bpp = (BinaryPacketProtocol *)context;
|
||||
ssh_bpp_handle_input(bpp);
|
||||
}
|
||||
|
||||
static void ssh_bpp_output_packet_callback(void *context)
|
||||
{
|
||||
BinaryPacketProtocol *bpp = (BinaryPacketProtocol *)context;
|
||||
ssh_bpp_handle_output(bpp);
|
||||
}
|
||||
|
||||
void ssh_bpp_common_setup(BinaryPacketProtocol *bpp)
|
||||
{
|
||||
pq_in_init(&bpp->in_pq);
|
||||
pq_out_init(&bpp->out_pq);
|
||||
bpp->ic_in_raw.fn = ssh_bpp_input_raw_data_callback;
|
||||
bpp->ic_in_raw.ctx = bpp;
|
||||
bpp->ic_out_pq.fn = ssh_bpp_output_packet_callback;
|
||||
bpp->ic_out_pq.ctx = bpp;
|
||||
bpp->out_pq.pqb.ic = &bpp->ic_out_pq;
|
||||
}
|
||||
|
||||
void ssh_bpp_free(BinaryPacketProtocol *bpp)
|
||||
{
|
||||
delete_callbacks_for_context(bpp);
|
||||
bpp->vt->free(bpp);
|
||||
}
|
||||
|
||||
#define BITMAP_UNIVERSAL(y, name, value) \
|
||||
| (value >= y && value < y+32 ? 1UL << (value-y) : 0)
|
||||
#define BITMAP_CONDITIONAL(y, name, value, ctx) \
|
||||
@ -658,7 +689,7 @@ int ssh2_bpp_check_unimplemented(BinaryPacketProtocol *bpp, PktIn *pktin)
|
||||
!((valid_bitmap[pktin->type >> 5] >> (pktin->type & 0x1F)) & 1)) {
|
||||
PktOut *pkt = ssh_bpp_new_pktout(bpp, SSH2_MSG_UNIMPLEMENTED);
|
||||
put_uint32(pkt, pktin->sequence);
|
||||
ssh_bpp_format_packet(bpp, pkt);
|
||||
pq_push(&bpp->out_pq, pkt);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -41,14 +41,14 @@ struct ssh_verstring_state {
|
||||
|
||||
static void ssh_verstring_free(BinaryPacketProtocol *bpp);
|
||||
static void ssh_verstring_handle_input(BinaryPacketProtocol *bpp);
|
||||
static void ssh_verstring_handle_output(BinaryPacketProtocol *bpp);
|
||||
static PktOut *ssh_verstring_new_pktout(int type);
|
||||
static void ssh_verstring_format_packet(BinaryPacketProtocol *bpp, PktOut *);
|
||||
|
||||
static const struct BinaryPacketProtocolVtable ssh_verstring_vtable = {
|
||||
ssh_verstring_free,
|
||||
ssh_verstring_handle_input,
|
||||
ssh_verstring_handle_output,
|
||||
ssh_verstring_new_pktout,
|
||||
ssh_verstring_format_packet,
|
||||
};
|
||||
|
||||
static void ssh_detect_bugs(struct ssh_verstring_state *s);
|
||||
@ -97,6 +97,7 @@ BinaryPacketProtocol *ssh_verstring_new(
|
||||
s->send_early = !ssh_version_includes_v1(protoversion);
|
||||
|
||||
s->bpp.vt = &ssh_verstring_vtable;
|
||||
ssh_bpp_common_setup(&s->bpp);
|
||||
return &s->bpp;
|
||||
}
|
||||
|
||||
@ -394,7 +395,7 @@ static PktOut *ssh_verstring_new_pktout(int type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ssh_verstring_format_packet(BinaryPacketProtocol *bpp, PktOut *pkg)
|
||||
static void ssh_verstring_handle_output(BinaryPacketProtocol *bpp)
|
||||
{
|
||||
assert(0 && "Should never try to send packets during SSH version "
|
||||
"string exchange");
|
||||
|
Loading…
Reference in New Issue
Block a user