1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

Rewrite packet parsing in sshshare.c using BinarySource.

Another set of localised decoding routines get thrown away here. Also,
I've changed the APIs of a couple of helper functions in x11fwd.c to
take ptrlens in place of zero-terminated C strings, because that's the
format in which they come back from the decode, and it saves mallocing
a zero-terminated version of each one just to pass to those helpers.
This commit is contained in:
Simon Tatham 2018-05-29 19:11:22 +01:00
parent 28c086ca9a
commit 5be57af173
3 changed files with 100 additions and 175 deletions

4
ssh.h
View File

@ -657,8 +657,8 @@ char *platform_get_x_display(void);
*/ */
void x11_get_auth_from_authfile(struct X11Display *display, void x11_get_auth_from_authfile(struct X11Display *display,
const char *authfilename); const char *authfilename);
int x11_identify_auth_proto(const char *proto); int x11_identify_auth_proto(ptrlen protoname);
void *x11_dehexify(const char *hex, int *outlen); void *x11_dehexify(ptrlen hex, int *outlen);
Bignum copybn(Bignum b); Bignum copybn(Bignum b);
Bignum bn_power_2(int n); Bignum bn_power_2(int n);

View File

@ -728,30 +728,30 @@ static void send_packet_to_downstream(struct ssh_sharing_connstate *cs,
* If that happens, we just chop up the packet into pieces and * If that happens, we just chop up the packet into pieces and
* send them as separate CHANNEL_DATA packets. * send them as separate CHANNEL_DATA packets.
*/ */
const char *upkt = (const char *)pkt; BinarySource src[1];
unsigned channel;
ptrlen data;
int len = toint(GET_32BIT(upkt + 4)); BinarySource_BARE_INIT(src, pkt, pktlen);
upkt += 8; /* skip channel id + length field */ channel = get_uint32(src);
data = get_string(src);
if (len < 0 || len > pktlen - 8)
len = pktlen - 8;
do { do {
int this_len = (len > chan->downstream_maxpkt ? int this_len = (data.len > chan->downstream_maxpkt ?
chan->downstream_maxpkt : len); chan->downstream_maxpkt : data.len);
packet = strbuf_new(); packet = strbuf_new();
put_uint32(packet, 0); /* placeholder for length field */ put_uint32(packet, 0); /* placeholder for length field */
put_byte(packet, type); put_byte(packet, type);
put_uint32(packet, chan->downstream_id); put_uint32(packet, channel);
put_uint32(packet, this_len); put_uint32(packet, this_len);
put_data(packet, upkt, this_len); put_data(packet, data.ptr, this_len);
len -= this_len; data.ptr = (const char *)data.ptr + this_len;
upkt += this_len; data.len -= this_len;
PUT_32BIT(packet->s, packet->len-4); PUT_32BIT(packet->s, packet->len-4);
sk_write(cs->sock, packet->s, packet->len); sk_write(cs->sock, packet->s, packet->len);
strbuf_free(packet); strbuf_free(packet);
} while (len > 0); } while (data.len > 0);
} else { } else {
/* /*
* Just do the obvious thing. * Just do the obvious thing.
@ -924,44 +924,6 @@ static void share_closing(Plug plug, const char *error_msg, int error_code,
share_begin_cleanup(cs); share_begin_cleanup(cs);
} }
static int getstring_inner(const void *vdata, int datalen,
char **out, int *outlen)
{
const unsigned char *data = (const unsigned char *)vdata;
int len;
if (datalen < 4)
return FALSE;
len = toint(GET_32BIT(data));
if (len < 0 || len > datalen - 4)
return FALSE;
if (outlen)
*outlen = len + 4; /* total size including length field */
if (out)
*out = dupprintf("%.*s", len, (char *)data + 4);
return TRUE;
}
static char *getstring(const void *data, int datalen)
{
char *ret;
if (getstring_inner(data, datalen, &ret, NULL))
return ret;
else
return NULL;
}
static int getstring_size(const void *data, int datalen)
{
int ret;
if (getstring_inner(data, datalen, NULL, &ret))
return ret;
else
return -1;
}
/* /*
* Append a message to the end of an xchannel's queue. * Append a message to the end of an xchannel's queue.
*/ */
@ -1011,9 +973,11 @@ void share_dead_xchannel_respond(struct ssh_sharing_connstate *cs,
* A CHANNEL_REQUEST is responded to by sending * A CHANNEL_REQUEST is responded to by sending
* CHANNEL_FAILURE, if it has want_reply set. * CHANNEL_FAILURE, if it has want_reply set.
*/ */
int wantreplypos = getstring_size(msg->data, msg->datalen); BinarySource src[1];
if (wantreplypos > 0 && wantreplypos < msg->datalen && BinarySource_BARE_INIT(src, msg->data, msg->datalen);
msg->data[wantreplypos] != 0) { get_uint32(src); /* skip channel id */
get_string(src); /* skip request type */
if (get_bool(src)) {
strbuf *packet = strbuf_new(); strbuf *packet = strbuf_new();
put_uint32(packet, xc->server_id); put_uint32(packet, xc->server_id);
ssh_send_packet_from_downstream ssh_send_packet_from_downstream
@ -1170,10 +1134,13 @@ void share_got_pkt_from_server(void *csv, int type,
{ {
struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)csv; struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)csv;
struct share_globreq *globreq; struct share_globreq *globreq;
int id_pos; size_t id_pos;
unsigned upstream_id, server_id; unsigned upstream_id, server_id;
struct share_channel *chan; struct share_channel *chan;
struct share_xchannel *xc; struct share_xchannel *xc;
BinarySource src[1];
BinarySource_BARE_INIT(src, pkt, pktlen);
switch (type) { switch (type) {
case SSH2_MSG_REQUEST_SUCCESS: case SSH2_MSG_REQUEST_SUCCESS:
@ -1207,9 +1174,9 @@ void share_got_pkt_from_server(void *csv, int type,
break; break;
case SSH2_MSG_CHANNEL_OPEN: case SSH2_MSG_CHANNEL_OPEN:
id_pos = getstring_size(pkt, pktlen); get_string(src);
assert(id_pos >= 0); server_id = get_uint32(src);
server_id = GET_32BIT(pkt + id_pos); assert(!get_err(src));
share_add_halfchannel(cs, server_id); share_add_halfchannel(cs, server_id);
send_packet_to_downstream(cs, type, pkt, pktlen, NULL); send_packet_to_downstream(cs, type, pkt, pktlen, NULL);
@ -1230,13 +1197,13 @@ void share_got_pkt_from_server(void *csv, int type,
* first uint32 field in the packet. Substitute the downstream * first uint32 field in the packet. Substitute the downstream
* channel id for our one and pass the packet downstream. * channel id for our one and pass the packet downstream.
*/ */
assert(pktlen >= 4); id_pos = src->pos;
upstream_id = GET_32BIT(pkt); upstream_id = get_uint32(src);
if ((chan = share_find_channel_by_upstream(cs, upstream_id)) != NULL) { if ((chan = share_find_channel_by_upstream(cs, upstream_id)) != NULL) {
/* /*
* The normal case: this id refers to an open channel. * The normal case: this id refers to an open channel.
*/ */
PUT_32BIT(pkt, chan->downstream_id); PUT_32BIT(pkt + id_pos, chan->downstream_id);
send_packet_to_downstream(cs, type, pkt, pktlen, chan); send_packet_to_downstream(cs, type, pkt, pktlen, chan);
/* /*
@ -1296,9 +1263,10 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
int type, int type,
unsigned char *pkt, int pktlen) unsigned char *pkt, int pktlen)
{ {
char *request_name; ptrlen request_name;
struct share_forwarding *fwd; struct share_forwarding *fwd;
int id_pos; size_t id_pos;
unsigned maxpkt;
unsigned old_id, new_id, server_id; unsigned old_id, new_id, server_id;
struct share_globreq *globreq; struct share_globreq *globreq;
struct share_channel *chan; struct share_channel *chan;
@ -1306,6 +1274,11 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
struct share_xchannel *xc; struct share_xchannel *xc;
strbuf *packet; strbuf *packet;
char *err = NULL; char *err = NULL;
BinarySource src[1];
size_t wantreplypos;
int orig_wantreply;
BinarySource_BARE_INIT(src, pkt, pktlen);
switch (type) { switch (type) {
case SSH2_MSG_DISCONNECT: case SSH2_MSG_DISCONNECT:
@ -1326,39 +1299,26 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
* will probably require that too, and so we don't forward on * will probably require that too, and so we don't forward on
* any request we don't understand. * any request we don't understand.
*/ */
request_name = getstring(pkt, pktlen); request_name = get_string(src);
if (request_name == NULL) { wantreplypos = src->pos;
err = dupprintf("Truncated GLOBAL_REQUEST packet"); orig_wantreply = get_bool(src);
goto confused;
}
if (!strcmp(request_name, "tcpip-forward")) { if (ptrlen_eq_string(request_name, "tcpip-forward")) {
int wantreplypos, orig_wantreply, port, ret; ptrlen hostpl;
char *host; char *host;
int port, ret;
sfree(request_name);
/* /*
* Pick the packet apart to find the want_reply field and * Pick the packet apart to find the want_reply field and
* the host/port we're going to ask to listen on. * the host/port we're going to ask to listen on.
*/ */
wantreplypos = getstring_size(pkt, pktlen); hostpl = get_string(src);
if (wantreplypos < 0 || wantreplypos >= pktlen) { port = toint(get_uint32(src));
if (get_err(src)) {
err = dupprintf("Truncated GLOBAL_REQUEST packet"); err = dupprintf("Truncated GLOBAL_REQUEST packet");
goto confused; goto confused;
} }
orig_wantreply = pkt[wantreplypos]; host = mkstr(hostpl);
port = getstring_size(pkt + (wantreplypos + 1),
pktlen - (wantreplypos + 1));
port += (wantreplypos + 1);
if (port < 0 || port > pktlen - 4) {
err = dupprintf("Truncated GLOBAL_REQUEST packet");
goto confused;
}
host = getstring(pkt + (wantreplypos + 1),
pktlen - (wantreplypos + 1));
assert(host != NULL);
port = GET_32BIT(pkt + port);
/* /*
* See if we can allocate space in ssh.c's tree of remote * See if we can allocate space in ssh.c's tree of remote
@ -1382,11 +1342,10 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
* that we know whether this forwarding needs to be * that we know whether this forwarding needs to be
* cleaned up if downstream goes away. * cleaned up if downstream goes away.
*/ */
int old_wantreply = pkt[wantreplypos];
pkt[wantreplypos] = 1; pkt[wantreplypos] = 1;
ssh_send_packet_from_downstream ssh_send_packet_from_downstream
(cs->parent->ssh, cs->id, type, pkt, pktlen, (cs->parent->ssh, cs->id, type, pkt, pktlen,
old_wantreply ? NULL : "upstream added want_reply flag"); orig_wantreply ? NULL : "upstream added want_reply flag");
fwd = share_add_forwarding(cs, host, port); fwd = share_add_forwarding(cs, host, port);
ssh_sharing_queue_global_request(cs->parent->ssh, cs); ssh_sharing_queue_global_request(cs->parent->ssh, cs);
@ -1404,34 +1363,23 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
} }
sfree(host); sfree(host);
} else if (!strcmp(request_name, "cancel-tcpip-forward")) { } else if (ptrlen_eq_string(request_name, "cancel-tcpip-forward")) {
int wantreplypos, orig_wantreply, port; ptrlen hostpl;
char *host; char *host;
int port;
struct share_forwarding *fwd; struct share_forwarding *fwd;
sfree(request_name);
/* /*
* Pick the packet apart to find the want_reply field and * Pick the packet apart to find the want_reply field and
* the host/port we're going to ask to listen on. * the host/port we're going to ask to listen on.
*/ */
wantreplypos = getstring_size(pkt, pktlen); hostpl = get_string(src);
if (wantreplypos < 0 || wantreplypos >= pktlen) { port = toint(get_uint32(src));
if (get_err(src)) {
err = dupprintf("Truncated GLOBAL_REQUEST packet"); err = dupprintf("Truncated GLOBAL_REQUEST packet");
goto confused; goto confused;
} }
orig_wantreply = pkt[wantreplypos]; host = mkstr(hostpl);
port = getstring_size(pkt + (wantreplypos + 1),
pktlen - (wantreplypos + 1));
port += (wantreplypos + 1);
if (port < 0 || port > pktlen - 4) {
err = dupprintf("Truncated GLOBAL_REQUEST packet");
goto confused;
}
host = getstring(pkt + (wantreplypos + 1),
pktlen - (wantreplypos + 1));
assert(host != NULL);
port = GET_32BIT(pkt + port);
/* /*
* Look up the existing forwarding with these details. * Look up the existing forwarding with these details.
@ -1449,11 +1397,10 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
* that _we_ know whether the forwarding has been * that _we_ know whether the forwarding has been
* deleted even if downstream doesn't want to know. * deleted even if downstream doesn't want to know.
*/ */
int old_wantreply = pkt[wantreplypos];
pkt[wantreplypos] = 1; pkt[wantreplypos] = 1;
ssh_send_packet_from_downstream ssh_send_packet_from_downstream
(cs->parent->ssh, cs->id, type, pkt, pktlen, (cs->parent->ssh, cs->id, type, pkt, pktlen,
old_wantreply ? NULL : "upstream added want_reply flag"); orig_wantreply ? NULL : "upstream added want_reply flag");
ssh_sharing_queue_global_request(cs->parent->ssh, cs); ssh_sharing_queue_global_request(cs->parent->ssh, cs);
} }
@ -1463,16 +1410,7 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
* Request we don't understand. Manufacture a failure * Request we don't understand. Manufacture a failure
* message if an answer was required. * message if an answer was required.
*/ */
int wantreplypos; if (orig_wantreply)
sfree(request_name);
wantreplypos = getstring_size(pkt, pktlen);
if (wantreplypos < 0 || wantreplypos >= pktlen) {
err = dupprintf("Truncated GLOBAL_REQUEST packet");
goto confused;
}
if (pkt[wantreplypos])
send_packet_to_downstream(cs, SSH2_MSG_REQUEST_FAILURE, send_packet_to_downstream(cs, SSH2_MSG_REQUEST_FAILURE,
"", 0, NULL); "", 0, NULL);
} }
@ -1480,16 +1418,17 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
case SSH2_MSG_CHANNEL_OPEN: case SSH2_MSG_CHANNEL_OPEN:
/* Sender channel id comes after the channel type string */ /* Sender channel id comes after the channel type string */
id_pos = getstring_size(pkt, pktlen); get_string(src);
if (id_pos < 0 || id_pos > pktlen - 12) { id_pos = src->pos;
old_id = get_uint32(src);
new_id = ssh_alloc_sharing_channel(cs->parent->ssh, cs);
get_uint32(src); /* skip initial window size */
maxpkt = get_uint32(src);
if (get_err(src)) {
err = dupprintf("Truncated CHANNEL_OPEN packet"); err = dupprintf("Truncated CHANNEL_OPEN packet");
goto confused; goto confused;
} }
share_add_channel(cs, old_id, new_id, 0, UNACKNOWLEDGED, maxpkt);
old_id = GET_32BIT(pkt + id_pos);
new_id = ssh_alloc_sharing_channel(cs->parent->ssh, cs);
share_add_channel(cs, old_id, new_id, 0, UNACKNOWLEDGED,
GET_32BIT(pkt + id_pos + 8));
PUT_32BIT(pkt + id_pos, new_id); PUT_32BIT(pkt + id_pos, new_id);
ssh_send_packet_from_downstream(cs->parent->ssh, cs->id, ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
type, pkt, pktlen, NULL); type, pkt, pktlen, NULL);
@ -1501,10 +1440,16 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
goto confused; goto confused;
} }
id_pos = 4; /* sender channel id is 2nd uint32 field in packet */ server_id = get_uint32(src);
old_id = GET_32BIT(pkt + id_pos); id_pos = src->pos;
old_id = get_uint32(src);
get_uint32(src); /* skip initial window size */
maxpkt = get_uint32(src);
if (get_err(src)) {
err = dupprintf("Truncated CHANNEL_OPEN_CONFIRMATION packet");
goto confused;
}
server_id = GET_32BIT(pkt);
/* This server id may refer to either a halfchannel or an xchannel. */ /* This server id may refer to either a halfchannel or an xchannel. */
hc = NULL, xc = NULL; /* placate optimiser */ hc = NULL, xc = NULL; /* placate optimiser */
if ((hc = share_find_halfchannel(cs, server_id)) != NULL) { if ((hc = share_find_halfchannel(cs, server_id)) != NULL) {
@ -1519,8 +1464,7 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
PUT_32BIT(pkt + id_pos, new_id); PUT_32BIT(pkt + id_pos, new_id);
chan = share_add_channel(cs, old_id, new_id, server_id, OPEN, chan = share_add_channel(cs, old_id, new_id, server_id, OPEN, maxpkt);
GET_32BIT(pkt + 12));
if (hc) { if (hc) {
ssh_send_packet_from_downstream(cs->parent->ssh, cs->id, ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
@ -1539,12 +1483,12 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
break; break;
case SSH2_MSG_CHANNEL_OPEN_FAILURE: case SSH2_MSG_CHANNEL_OPEN_FAILURE:
if (pktlen < 4) { server_id = get_uint32(src);
if (get_err(src)) {
err = dupprintf("Truncated CHANNEL_OPEN_FAILURE packet"); err = dupprintf("Truncated CHANNEL_OPEN_FAILURE packet");
goto confused; goto confused;
} }
server_id = GET_32BIT(pkt);
/* This server id may refer to either a halfchannel or an xchannel. */ /* This server id may refer to either a halfchannel or an xchannel. */
if ((hc = share_find_halfchannel(cs, server_id)) != NULL) { if ((hc = share_find_halfchannel(cs, server_id)) != NULL) {
ssh_send_packet_from_downstream(cs->parent->ssh, cs->id, ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
@ -1570,8 +1514,11 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
case SSH2_MSG_CHANNEL_FAILURE: case SSH2_MSG_CHANNEL_FAILURE:
case SSH2_MSG_IGNORE: case SSH2_MSG_IGNORE:
case SSH2_MSG_DEBUG: case SSH2_MSG_DEBUG:
if (type == SSH2_MSG_CHANNEL_REQUEST && server_id = get_uint32(src);
(request_name = getstring(pkt + 4, pktlen - 4)) != NULL) {
if (type == SSH2_MSG_CHANNEL_REQUEST) {
request_name = get_string(src);
/* /*
* Agent forwarding requests from downstream are treated * Agent forwarding requests from downstream are treated
* specially. Because OpenSSHD doesn't let us enable agent * specially. Because OpenSSHD doesn't let us enable agent
@ -1597,11 +1544,8 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
* subsequent CHANNEL_OPENs still can't be associated with * subsequent CHANNEL_OPENs still can't be associated with
* a parent session channel.) * a parent session channel.)
*/ */
if (!strcmp(request_name, "auth-agent-req@openssh.com") && if (ptrlen_eq_string(request_name, "auth-agent-req@openssh.com") &&
!ssh_agent_forwarding_permitted(cs->parent->ssh)) { !ssh_agent_forwarding_permitted(cs->parent->ssh)) {
unsigned server_id = GET_32BIT(pkt);
sfree(request_name);
chan = share_find_channel_by_server(cs, server_id); chan = share_find_channel_by_server(cs, server_id);
if (chan) { if (chan) {
@ -1630,14 +1574,10 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
* whether it's one to handle locally or one to pass on to * whether it's one to handle locally or one to pass on to
* a downstream, and if the latter, which one. * a downstream, and if the latter, which one.
*/ */
if (!strcmp(request_name, "x11-req")) { if (ptrlen_eq_string(request_name, "x11-req")) {
unsigned server_id = GET_32BIT(pkt);
int want_reply, single_connection, screen; int want_reply, single_connection, screen;
char *auth_proto_str, *auth_data; ptrlen auth_data;
int auth_proto; int auth_proto;
int pos;
sfree(request_name);
chan = share_find_channel_by_server(cs, server_id); chan = share_find_channel_by_server(cs, server_id);
if (!chan) { if (!chan) {
@ -1652,26 +1592,16 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
* Pick apart the whole message to find the downstream * Pick apart the whole message to find the downstream
* auth details. * auth details.
*/ */
/* we have already seen: 4 bytes channel id, 4+7 request name */ want_reply = get_bool(src);
if (pktlen < 17) { single_connection = get_bool(src);
err = dupprintf("Truncated CHANNEL_REQUEST(\"x11\") packet"); auth_proto = x11_identify_auth_proto(get_string(src));
auth_data = get_string(src);
screen = toint(get_uint32(src));
if (get_err(src)) {
err = dupprintf("Truncated CHANNEL_REQUEST(\"x11-req\")"
" packet");
goto confused; goto confused;
} }
want_reply = pkt[15] != 0;
single_connection = pkt[16] != 0;
auth_proto_str = getstring(pkt+17, pktlen-17);
auth_proto = x11_identify_auth_proto(auth_proto_str);
sfree(auth_proto_str);
pos = 17 + getstring_size(pkt+17, pktlen-17);
auth_data = getstring(pkt+pos, pktlen-pos);
pos += getstring_size(pkt+pos, pktlen-pos);
if (pktlen < pos+4) {
err = dupprintf("Truncated CHANNEL_REQUEST(\"x11\") packet");
sfree(auth_data);
goto confused;
}
screen = GET_32BIT(pkt+pos);
if (auth_proto < 0) { if (auth_proto < 0) {
/* Reject due to not understanding downstream's /* Reject due to not understanding downstream's
@ -1682,14 +1612,12 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
cs, SSH2_MSG_CHANNEL_FAILURE, cs, SSH2_MSG_CHANNEL_FAILURE,
packet->s, packet->len, NULL); packet->s, packet->len, NULL);
strbuf_free(packet); strbuf_free(packet);
sfree(auth_data);
break; break;
} }
chan->x11_auth_proto = auth_proto; chan->x11_auth_proto = auth_proto;
chan->x11_auth_data = x11_dehexify(auth_data, chan->x11_auth_data = x11_dehexify(auth_data,
&chan->x11_auth_datalen); &chan->x11_auth_datalen);
sfree(auth_data);
chan->x11_auth_upstream = chan->x11_auth_upstream =
ssh_sharing_add_x11_display(cs->parent->ssh, auth_proto, ssh_sharing_add_x11_display(cs->parent->ssh, auth_proto,
cs, chan); cs, chan);
@ -1715,14 +1643,11 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
break; break;
} }
sfree(request_name);
} }
ssh_send_packet_from_downstream(cs->parent->ssh, cs->id, ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
type, pkt, pktlen, NULL); type, pkt, pktlen, NULL);
if (type == SSH2_MSG_CHANNEL_CLOSE && pktlen >= 4) { if (type == SSH2_MSG_CHANNEL_CLOSE && pktlen >= 4) {
server_id = GET_32BIT(pkt);
chan = share_find_channel_by_server(cs, server_id); chan = share_find_channel_by_server(cs, server_id);
if (chan) { if (chan) {
if (chan->state == RCVD_CLOSE) { if (chan->state == RCVD_CLOSE) {

View File

@ -974,29 +974,29 @@ void x11_send_eof(struct X11Connection *xconn)
* representations of an X11 auth protocol name + hex cookie into our * representations of an X11 auth protocol name + hex cookie into our
* usual integer protocol id and binary auth data. * usual integer protocol id and binary auth data.
*/ */
int x11_identify_auth_proto(const char *protoname) int x11_identify_auth_proto(ptrlen protoname)
{ {
int protocol; int protocol;
for (protocol = 1; protocol < lenof(x11_authnames); protocol++) for (protocol = 1; protocol < lenof(x11_authnames); protocol++)
if (!strcmp(protoname, x11_authnames[protocol])) if (ptrlen_eq_string(protoname, x11_authnames[protocol]))
return protocol; return protocol;
return -1; return -1;
} }
void *x11_dehexify(const char *hex, int *outlen) void *x11_dehexify(ptrlen hexpl, int *outlen)
{ {
int len, i; int len, i;
unsigned char *ret; unsigned char *ret;
len = strlen(hex) / 2; len = hexpl.len / 2;
ret = snewn(len, unsigned char); ret = snewn(len, unsigned char);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
char bytestr[3]; char bytestr[3];
unsigned val = 0; unsigned val = 0;
bytestr[0] = hex[2*i]; bytestr[0] = ((const char *)hexpl.ptr)[2*i];
bytestr[1] = hex[2*i+1]; bytestr[1] = ((const char *)hexpl.ptr)[2*i+1];
bytestr[2] = '\0'; bytestr[2] = '\0';
sscanf(bytestr, "%x", &val); sscanf(bytestr, "%x", &val);
ret[i] = val; ret[i] = val;