From 25b84123336bec6e85cb0b7d61c6fb902ae44825 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 9 Apr 2019 13:35:46 +0200 Subject: [PATCH] Avoid poking around in STREAM internals It's easy to make mistakes this way, and bypassed the normal bounds checking. So make sure we always use macros or functions. --- channels.c | 17 ++---- cliprdr.c | 9 +-- cssp.c | 87 ++++++++++++-------------- licence.c | 10 ++- lspci.c | 3 +- mcs.c | 9 +-- orders.c | 12 ++-- printercache.c | 16 +++-- rdp.c | 73 +++++++++++++--------- rdp5.c | 30 ++++----- rdpdr.c | 119 +++++++++++++++++++----------------- rdpsnd.c | 58 +++++++++--------- rdpsnd_alsa.c | 16 ++++- rdpsnd_libao.c | 7 ++- rdpsnd_oss.c | 14 +++-- rdpsnd_pulse.c | 11 ++-- rdpsnd_sgi.c | 7 ++- rdpsnd_sun.c | 16 +++-- scard.c | 162 +++++++++++++++++++++++++++++-------------------- seamless.c | 3 +- secure.c | 91 +++++++++++++++++---------- stream.h | 3 + tcp.c | 55 +++++++++-------- 23 files changed, 469 insertions(+), 359 deletions(-) diff --git a/channels.c b/channels.c index b5ea690..e51f1cc 100644 --- a/channels.c +++ b/channels.c @@ -186,7 +186,6 @@ void channel_process(STREAM s, uint16 mcs_channel) { uint32 length, flags; - uint32 thislength; VCHANNEL *channel = NULL; unsigned int i; STREAM in; @@ -214,22 +213,16 @@ channel_process(STREAM s, uint16 mcs_channel) in = &channel->in; if (flags & CHANNEL_FLAG_FIRST) { - if (length > in->size) - { - in->data = (uint8 *) xrealloc(in->data, length); - in->size = length; - } - in->p = in->data; + s_realloc(in, length); + s_reset(in); } - thislength = MIN(s_remaining(s), in->data + in->size - in->p); - memcpy(in->p, s->p, thislength); - in->p += thislength; + out_uint8stream(in, s, s_remaining(s)); if (flags & CHANNEL_FLAG_LAST) { - in->end = in->p; - in->p = in->data; + s_mark_end(in); + s_seek(in, 0); channel->process(in); } } diff --git a/cliprdr.c b/cliprdr.c index c05e281..a7d41b2 100644 --- a/cliprdr.c +++ b/cliprdr.c @@ -119,21 +119,14 @@ cliprdr_process(STREAM s) uint16 type, status; uint32 length, format; uint8 *data; - struct stream packet = *s; in_uint16_le(s, type); in_uint16_le(s, status); in_uint32_le(s, length); - data = s->p; logger(Clipboard, Debug, "cliprdr_process(), type=%d, status=%d, length=%d", type, status, length); - if (!s_check_rem(s, length)) - { - rdp_protocol_error("consume of packet from stream would overrun", &packet); - } - if (status == CLIPRDR_ERROR) { switch (type) @@ -161,6 +154,7 @@ cliprdr_process(STREAM s) ui_clip_sync(); break; case CLIPRDR_FORMAT_ANNOUNCE: + in_uint8p(s, data, length); ui_clip_format_announce(data, length); cliprdr_send_packet(CLIPRDR_FORMAT_ACK, CLIPRDR_RESPONSE, NULL, 0); return; @@ -171,6 +165,7 @@ cliprdr_process(STREAM s) ui_clip_request_data(format); break; case CLIPRDR_DATA_RESPONSE: + in_uint8p(s, data, length); ui_clip_handle_data(data, length); break; case 7: /* TODO: W2K3 SP1 sends this on connect with a value of 1 */ diff --git a/cssp.c b/cssp.c index c599791..c7b015c 100644 --- a/cssp.c +++ b/cssp.c @@ -38,7 +38,7 @@ ber_wrap_hdr_data(int tagval, STREAM in) out = s_alloc(size); ber_out_header(out, tagval, s_length(in)); - out_uint8a(out, in->data, s_length(in)); + out_stream(out, in); s_mark_end(out); return out; @@ -148,8 +148,10 @@ cssp_gss_wrap(gss_ctx_id_t ctx, STREAM in) gss_buffer_desc inbuf, outbuf; STREAM out; - inbuf.value = in->data; + s_seek(in, 0); inbuf.length = s_length(in); + in_uint8p(in, inbuf.value, s_length(in)); + s_seek(in, 0); major_status = gss_wrap(&minor_status, ctx, True, GSS_C_QOP_DEFAULT, &inbuf, &conf_state, &outbuf); @@ -189,8 +191,10 @@ cssp_gss_unwrap(gss_ctx_id_t ctx, STREAM in) int conf_state; STREAM out; - inbuf.value = in->data; + s_seek(in, 0); inbuf.length = s_length(in); + in_uint8p(in, inbuf.value, s_length(in)); + s_seek(in, 0); major_status = gss_unwrap(&minor_status, ctx, &inbuf, &outbuf, &conf_state, &qop_state); @@ -231,7 +235,7 @@ cssp_encode_tspasswordcreds(char *username, char *password, char *domain) h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -244,7 +248,7 @@ cssp_encode_tspasswordcreds(char *username, char *password, char *domain) h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -256,7 +260,7 @@ cssp_encode_tspasswordcreds(char *username, char *password, char *domain) h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -292,7 +296,7 @@ cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, cha h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -306,7 +310,7 @@ cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, cha h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -321,7 +325,7 @@ cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, cha h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -336,7 +340,7 @@ cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, cha h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -351,7 +355,7 @@ cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, cha h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 4, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -384,7 +388,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain) h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -394,7 +398,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain) g_sc_container_name, g_sc_csp_name); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -408,7 +412,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain) h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -423,7 +427,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain) h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -464,7 +468,7 @@ cssp_encode_tscredentials(char *username, char *password, char *domain) h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -482,7 +486,7 @@ cssp_encode_tscredentials(char *username, char *password, char *domain) h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, h3); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h3); s_free(h2); @@ -518,7 +522,7 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey) h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -532,7 +536,7 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey) h2 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, h3); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h5); s_free(h4); @@ -548,7 +552,7 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey) h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_free(h2); s_free(h1); @@ -561,7 +565,7 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey) h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2); s_realloc(&message, s_length(&message) + s_length(h1)); - out_uint8a(&message, h1->data, s_length(h1)); + out_stream(&message, h1); s_mark_end(&message); s_free(h2); s_free(h1); @@ -572,7 +576,7 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey) // Todo: can h1 be send directly instead of tcp_init() approach h1 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message); s = tcp_init(s_length(h1)); - out_uint8a(s, h1->data, s_length(h1)); + out_stream(s, h1); s_mark_end(s); s_free(h1); @@ -600,34 +604,21 @@ cssp_read_tsrequest(RD_BOOL pubkey) if (s == NULL) return NULL; - // verify ASN.1 header - if (s->p[0] != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED)) - { - logger(Protocol, Error, - "cssp_read_tsrequest(), expected BER_TAG_SEQUENCE|BER_TAG_CONSTRUCTED, got %x", - s->p[0]); - return NULL; - } - - // peek at first 4 bytes to get full message length - if (s->p[1] < 0x80) - length = s->p[1] - 2; - else if (s->p[1] == 0x81) - length = s->p[2] - 1; - else if (s->p[1] == 0x82) - length = (s->p[2] << 8) | s->p[3]; - else - return NULL; - - // receive the remainings of message - s = tcp_recv(s, length); - packet = *s; - - // parse the response and into nego token + // get and verify the header if (!ber_in_header(s, &tagval, &length) || tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED)) return NULL; + // We've already read 4 bytes, but the header might have been + // less than that, so we need to adjust the length + length -= s_remaining(s); + + // receive the remainings of message + s = tcp_recv(s, length); + if (s == NULL) + return NULL; + packet = *s; + // version [0] if (!ber_in_header(s, &tagval, &length) || tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0)) @@ -666,7 +657,7 @@ cssp_read_tsrequest(RD_BOOL pubkey) } out = s_alloc(length); - out_uint8a(out, s->p, length); + out_uint8stream(out, s, length); s_mark_end(out); s_seek(out, 0); } @@ -681,7 +672,7 @@ cssp_read_tsrequest(RD_BOOL pubkey) return NULL; out = s_alloc(length); - out_uint8a(out, s->p, length); + out_uint8stream(out, s, length); s_mark_end(out); s_seek(out, 0); } diff --git a/licence.c b/licence.c index 2125254..4acac8d 100644 --- a/licence.c +++ b/licence.c @@ -277,6 +277,7 @@ licence_process_platform_challenge(STREAM s) static void licence_process_new_license(STREAM s) { + unsigned char *data; RDSSL_RC4 crypt_key; uint32 length; int i; @@ -286,8 +287,12 @@ licence_process_new_license(STREAM s) if (!s_check_rem(s, length)) return; + inout_uint8p(s, data, length); + rdssl_rc4_set_key(&crypt_key, g_licence_key, 16); - rdssl_rc4_crypt(&crypt_key, s->p, s->p, length); + rdssl_rc4_crypt(&crypt_key, data, data, length); + + s_seek(s, s_tell(s) - length); /* Parse NEW_LICENSE_INFO block */ in_uint8s(s, 4); // skip dwVersion @@ -304,7 +309,8 @@ licence_process_new_license(STREAM s) } g_licence_issued = True; - save_licence(s->p, length); + in_uint8p(s, data, length); + save_licence(data, length); } /* process a licence error alert packet */ diff --git a/lspci.c b/lspci.c index 73b974d..1a79131 100644 --- a/lspci.c +++ b/lspci.c @@ -139,7 +139,8 @@ lspci_process(STREAM s) pkglen = s_remaining(s); /* str_handle_lines requires null terminated strings */ buf = xmalloc(pkglen + 1); - STRNCPY(buf, (char *) s->p, pkglen + 1); + in_uint8a(s, buf, pkglen); + buf[pkglen] = '\0'; str_handle_lines(buf, &rest, lspci_process_line, NULL); xfree(buf); } diff --git a/mcs.c b/mcs.c index a13092b..62d18d8 100644 --- a/mcs.c +++ b/mcs.c @@ -62,7 +62,7 @@ mcs_parse_domain_params(STREAM s) static void mcs_send_connect_initial(STREAM mcs_data) { - int datalen = mcs_data->end - mcs_data->data; + int datalen = s_length(mcs_data); int length = 9 + 3 * 34 + 4 + datalen; STREAM s; logger(Protocol, Debug, "%s()", __func__); @@ -139,9 +139,10 @@ mcs_recv_connect_response(STREAM mcs_data) length = mcs_data->size; } - in_uint8a(s, mcs_data->data, length); - mcs_data->p = mcs_data->data; - mcs_data->end = mcs_data->data + length; + s_reset(mcs_data); + in_uint8stream(s, mcs_data, length); + s_mark_end(mcs_data); + s_seek(mcs_data, 0); */ return s_check_end(s); } diff --git a/orders.c b/orders.c index 44e5034..e463fed 100644 --- a/orders.c +++ b/orders.c @@ -20,7 +20,7 @@ #include "rdesktop.h" #include "orders.h" -extern uint8 *g_next_packet; +extern size_t g_next_packet; static RDP_ORDER_STATE g_order_state; extern RDP_VERSION g_rdp_version; @@ -1252,7 +1252,7 @@ process_secondary_order(STREAM s) sint16 length; uint16 flags; uint8 type; - uint8 *next_order; + size_t next_order; struct stream packet = *s; in_uint16_le(s, length); @@ -1269,7 +1269,7 @@ process_secondary_order(STREAM s) rdp_protocol_error("next order pointer would overrun stream", &packet); } - next_order = s->p + length; + next_order = s_tell(s) + length; switch (type) { @@ -1306,7 +1306,7 @@ process_secondary_order(STREAM s) "process_secondary_order(), unhandled secondary order %d", type); } - s->p = next_order; + s_seek(s, next_order); } /* Process an order PDU */ @@ -1448,9 +1448,9 @@ process_orders(STREAM s, uint16 num_orders) } #if 0 /* not true when RDP_COMPRESSION is set */ - if (s->p != g_next_packet) + if (s_tell(s) != g_next_packet) logger(Graphics, Error, "process_orders(), %d bytes remaining", - (int) (g_next_packet - s->p)); + (int) (g_next_packet - s_tell(s))); #endif } diff --git a/printercache.c b/printercache.c index e0a449c..86973bc 100644 --- a/printercache.c +++ b/printercache.c @@ -238,6 +238,8 @@ printercache_process(STREAM s) { uint32 type, printer_length, driver_length, printer_unicode_length, blob_length; char device_name[9], *printer, *driver; + size_t blob_start; + unsigned char *blob; printer = driver = NULL; @@ -279,8 +281,10 @@ printercache_process(STREAM s) { rdp_in_unistr(s, printer_unicode_length, &printer, &printer_unicode_length); - if (printer) - printercache_save_blob(printer, s->p, blob_length); + if (printer) { + in_uint8p(s, blob, blob_length); + printercache_save_blob(printer, blob, blob_length); + } free(printer); } break; @@ -289,6 +293,7 @@ printercache_process(STREAM s) in_uint8a(s, device_name, 5); /* get LPTx/COMx name */ /* need to fetch this data so that we can get the length of the packet to store. */ + blob_start = s_tell(s); in_uint8s(s, 0x2); /* ??? */ in_uint8s(s, 0x2) /* pad?? */ in_uint32_be(s, driver_length); @@ -302,10 +307,11 @@ printercache_process(STREAM s) /* rewind stream so that we can save this blob */ /* length is driver_length + printer_length + 19 */ /* rewind stream */ - s->p = s->p - 19; + s_seek(s, blob_start); - printercache_save_blob(device_name, s->p, - driver_length + printer_length + 19); + blob_length = driver_length + printer_length + 19; + in_uint8p(s, blob, blob_length); + printercache_save_blob(device_name, blob, blob_length); break; default: logger(Protocol, Warning, diff --git a/rdp.c b/rdp.c index ffc8920..b938c2f 100644 --- a/rdp.c +++ b/rdp.c @@ -59,7 +59,7 @@ extern RD_BOOL g_dynamic_session_resize; RD_BOOL g_exit_mainloop = False; -uint8 *g_next_packet; +size_t g_next_packet; uint32 g_rdp_shareid; extern RDPCOMP g_mppc_dict; @@ -128,6 +128,9 @@ rdp_ts_in_share_control_header(STREAM s, uint8 * type, uint16 * length) *type = pdu_type & 0xf; + /* Give just the size of the data */ + *length -= 6; + return True; } @@ -142,7 +145,7 @@ rdp_recv(uint8 * type) while (1) { /* fill stream with data if needed for parsing a new packet */ - if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL)) + if (g_next_packet == 0) { rdp_s = sec_recv(&is_fastpath); if (rdp_s == NULL) @@ -155,11 +158,16 @@ rdp_recv(uint8 * type) continue; } - g_next_packet = rdp_s->p; + g_next_packet = s_tell(rdp_s); } else { - rdp_s->p = g_next_packet; + s_seek(rdp_s, g_next_packet); + if (s_check_end(rdp_s)) + { + g_next_packet = 0; + continue; + } } /* parse a TS_SHARECONTROLHEADER */ @@ -171,7 +179,13 @@ rdp_recv(uint8 * type) logger(Protocol, Debug, "rdp_recv(), RDP packet #%d, type 0x%x", ++g_packetno, *type); - g_next_packet += length; + if (!s_check_rem(rdp_s, length)) + { + rdp_protocol_error("not enough data for PDU", rdp_s); + } + + g_next_packet = s_tell(rdp_s) + length; + return rdp_s; } @@ -241,7 +255,8 @@ rdp_out_unistr(STREAM s, char *string, int len) */ static iconv_t icv_local_to_utf16; size_t ibl, obl; - char *pin, *pout; + char *pin; + unsigned char *pout; if (string == NULL || len == 0) @@ -263,18 +278,16 @@ rdp_out_unistr(STREAM s, char *string, int len) ibl = strlen(string); obl = len + 2; pin = string; - pout = (char *) s->p; + out_uint8p(s, pout, len + 2); - memset(pout, 0, len + 4); + memset(pout, 0, len + 2); - if (iconv(icv_local_to_utf16, (char **) &pin, &ibl, &pout, &obl) == (size_t) - 1) + if (iconv(icv_local_to_utf16, (char **) &pin, &ibl, (char **)&pout, &obl) == (size_t) - 1) { logger(Protocol, Error, "rdp_out_unistr(), iconv(2) fail, errno %d", errno); abort(); } - - s->p += len + 2; } /* Input a string in Unicode @@ -286,7 +299,8 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size) { static iconv_t icv_utf16_to_local; size_t ibl, obl; - char *pin, *pout; + unsigned char *pin; + char *pout; struct stream packet = *s; @@ -323,7 +337,7 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size) ibl = in_len; obl = *str_size - 1; - pin = (char *) s->p; + in_uint8p(s, pin, in_len); pout = *string; if (iconv(icv_utf16_to_local, (char **) &pin, &ibl, &pout, &obl) == (size_t) - 1) @@ -344,9 +358,6 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size) abort(); } - /* we must update the location of the current STREAM for future reads of s->p */ - s->p += in_len; - *pout = 0; if (*string) @@ -1219,25 +1230,25 @@ static void rdp_process_server_caps(STREAM s, uint16 length) { int n; - uint8 *next, *start; + size_t next, start; uint16 ncapsets, capset_type, capset_length; logger(Protocol, Debug, "%s()", __func__); - start = s->p; + start = s_tell(s); in_uint16_le(s, ncapsets); in_uint8s(s, 2); /* pad */ for (n = 0; n < ncapsets; n++) { - if (s->p > start + length) + if (s_tell(s) > start + length) return; in_uint16_le(s, capset_type); in_uint16_le(s, capset_length); - next = s->p + capset_length - 4; + next = s_tell(s) + capset_length - 4; switch (capset_type) { @@ -1256,7 +1267,7 @@ rdp_process_server_caps(STREAM s, uint16 length) break; } - s->p = next; + s_seek(s, next); } } @@ -1726,6 +1737,7 @@ process_data_pdu(STREAM s, uint32 * ext_disc_reason) uint16 clen; uint32 len; + uint8 *buf; uint32 roff, rlen; struct stream *ns = &(g_mppc_dict.ns); @@ -1742,21 +1754,22 @@ process_data_pdu(STREAM s, uint32 * ext_disc_reason) if (len > RDP_MPPC_DICT_SIZE) logger(Protocol, Error, "process_data_pdu(), error decompressed packet size exceeds max"); - if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1) + in_uint8p(s, buf, clen); + if (mppc_expand(buf, clen, ctype, &roff, &rlen) == -1) logger(Protocol, Error, "process_data_pdu(), error while decompressing packet"); /* len -= 18; */ /* allocate memory and copy the uncompressed data into the temporary stream */ - ns->data = (uint8 *) xrealloc(ns->data, rlen); + s_realloc(ns, rlen); + s_reset(ns); - memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen); + out_uint8a(ns, (unsigned char *) (g_mppc_dict.hist + roff), rlen); - ns->size = rlen; - ns->end = (ns->data + ns->size); - ns->p = ns->data; - ns->rdp_hdr = ns->p; + s_mark_end(ns); + s_seek(ns, 0); + s_push_layer(ns, rdp_hdr, 0); s = ns; } @@ -2056,7 +2069,7 @@ rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason) logger(Protocol, Warning, "rdp_loop(), unhandled PDU type %d received", type); } - cont = g_next_packet < s->end; + cont = g_next_packet < s_length(s); } return True; } @@ -2094,7 +2107,7 @@ void rdp_reset_state(void) { logger(Protocol, Debug, "%s()", __func__); - g_next_packet = NULL; /* reset the packet information */ + g_next_packet = 0; /* reset the packet information */ g_rdp_shareid = 0; g_exit_mainloop = False; g_first_bitmap_caps = True; diff --git a/rdp5.c b/rdp5.c index 5a8de96..6b7ab05 100644 --- a/rdp5.c +++ b/rdp5.c @@ -21,7 +21,7 @@ #include "rdesktop.h" -extern uint8 *g_next_packet; +extern size_t g_next_packet; extern RDPCOMP g_mppc_dict; @@ -78,8 +78,9 @@ process_ts_fp_updates(STREAM s) { uint16 length; uint8 hdr, code, frag, comp, ctype = 0; - uint8 *next; + size_t next; + uint8 *buf; uint32 roff, rlen; struct stream *ns = &(g_mppc_dict.ns); struct stream *ts; @@ -87,7 +88,7 @@ process_ts_fp_updates(STREAM s) static STREAM assembled[16] = { 0 }; ui_begin_update(); - while (s->p < s->end) + while (!s_check_end(s)) { /* Reading a number of TS_FP_UPDATE structures from the stream here.. */ in_uint8(s, hdr); /* updateHeader */ @@ -100,23 +101,24 @@ process_ts_fp_updates(STREAM s) in_uint16_le(s, length); /* length */ - g_next_packet = next = s->p + length; + g_next_packet = next = s_tell(s) + length; if (ctype & RDP_MPPC_COMPRESSED) { - if (mppc_expand(s->p, length, ctype, &roff, &rlen) == -1) + in_uint8p(s, buf, length); + if (mppc_expand(buf, length, ctype, &roff, &rlen) == -1) logger(Protocol, Error, "process_ts_fp_update_pdu(), error while decompressing packet"); /* allocate memory and copy the uncompressed data into the temporary stream */ - ns->data = (uint8 *) xrealloc(ns->data, rlen); + s_realloc(ns, rlen); + s_reset(ns); - memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen); + out_uint8a(ns, (unsigned char *) (g_mppc_dict.hist + roff), rlen); - ns->size = rlen; - ns->end = (ns->data + ns->size); - ns->p = ns->data; - ns->rdp_hdr = ns->p; + s_mark_end(ns); + s_seek(ns, 0); + s_push_layer(ns, rdp_hdr, 0); length = rlen; ts = ns; @@ -140,17 +142,17 @@ process_ts_fp_updates(STREAM s) s_reset(assembled[code]); } - out_uint8a(assembled[code], ts->p, length); + out_uint8stream(assembled[code], ts, length); if (frag == FASTPATH_FRAGMENT_LAST) { s_mark_end(assembled[code]); - assembled[code]->p = assembled[code]->data; + s_seek(assembled[code], 0); process_ts_fp_update_by_code(assembled[code], code); } } - s->p = next; + s_seek(s, next); } ui_end_update(); } diff --git a/rdpdr.c b/rdpdr.c index 0221366..333f6d1 100644 --- a/rdpdr.c +++ b/rdpdr.c @@ -411,7 +411,6 @@ rdpdr_process_irp(STREAM s) request, file, info_level, - buffer_len, id, major, minor, @@ -424,8 +423,8 @@ rdpdr_process_irp(STREAM s) char *filename; uint32 filename_len; - uint8 *buffer, *pst_buf; - struct stream out; + uint8 *pst_buf; + STREAM out; DEVICE_FNS *fns; RD_BOOL rw_blocking = True; RD_NTSTATUS status = RD_STATUS_INVALID_DEVICE_REQUEST; @@ -438,16 +437,13 @@ rdpdr_process_irp(STREAM s) filename = NULL; - buffer_len = 0; - buffer = (uint8 *) xmalloc(1024); - buffer[0] = 0; + out = NULL; if (device >= RDPDR_MAX_DEVICES) { logger(Protocol, Error, "rdpdr_process_irp(), invalid irp device=0x%lx, file=0x%lx, id=0x%lx, major=0x%lx, minor=0x%lx", device, file, id, major, minor); - xfree(buffer); return; } @@ -486,7 +482,6 @@ rdpdr_process_irp(STREAM s) logger(Protocol, Error, "rdpdr_process_irp(), received IRP for unknown device type %ld", device); - xfree(buffer); return; } @@ -520,7 +515,9 @@ rdpdr_process_irp(STREAM s) flags_and_attributes, filename, &result); free(filename); - buffer_len = 1; + out = s_alloc(1); + out_uint8(out, 0); + s_mark_end(out); break; case IRP_MJ_CLOSE: @@ -557,14 +554,14 @@ rdpdr_process_irp(STREAM s) if (rw_blocking) /* Complete read immediately */ { - buffer = (uint8 *) xrealloc((void *) buffer, length); - if (!buffer) - { - status = RD_STATUS_CANCELLED; - break; - } + uint8* buffer; + out = s_alloc(length); + out_uint8p(out, buffer, length); status = fns->read(file, buffer, length, offset, &result); - buffer_len = result; + /* Might have read less */ + s_mark_end(out); + s_seek(out, result); + s_mark_end(out); break; } @@ -588,7 +585,9 @@ rdpdr_process_irp(STREAM s) break; case IRP_MJ_WRITE: - buffer_len = 1; + out = s_alloc(1); + out_uint8(out, 0); + s_mark_end(out); if (!fns->write) { @@ -612,7 +611,9 @@ rdpdr_process_irp(STREAM s) if (rw_blocking) /* Complete immediately */ { - status = fns->write(file, s->p, length, offset, &result); + unsigned char *data; + in_uint8p(s, data, length); + status = fns->write(file, data, length, offset, &result); break; } @@ -645,10 +646,10 @@ rdpdr_process_irp(STREAM s) } in_uint32_le(s, info_level); - out.data = out.p = buffer; - out.size = sizeof(buffer); - status = disk_query_information(file, info_level, &out); - result = buffer_len = out.p - out.data; + out = s_alloc(1024); + status = disk_query_information(file, info_level, out); + s_mark_end(out); + result = s_length(out); break; @@ -662,10 +663,10 @@ rdpdr_process_irp(STREAM s) in_uint32_le(s, info_level); - out.data = out.p = buffer; - out.size = sizeof(buffer); - status = disk_set_information(file, info_level, s, &out); - result = buffer_len = out.p - out.data; + out = s_alloc(1024); + status = disk_set_information(file, info_level, s, out); + s_mark_end(out); + result = s_length(out); break; case IRP_MJ_QUERY_VOLUME_INFORMATION: @@ -678,10 +679,10 @@ rdpdr_process_irp(STREAM s) in_uint32_le(s, info_level); - out.data = out.p = buffer; - out.size = sizeof(buffer); - status = disk_query_volume_information(file, info_level, &out); - result = buffer_len = out.p - out.data; + out = s_alloc(1024); + status = disk_query_volume_information(file, info_level, out); + s_mark_end(out); + result = s_length(out); break; case IRP_MJ_DIRECTORY_CONTROL: @@ -707,13 +708,16 @@ rdpdr_process_irp(STREAM s) convert_to_unix_filename(filename); } - out.data = out.p = buffer; - out.size = sizeof(buffer); + out = s_alloc(1024); status = disk_query_directory(file, info_level, filename, - &out); - result = buffer_len = out.p - out.data; - if (!buffer_len) - buffer_len++; + out); + s_mark_end(out); + if (!s_length(out)) + { + out_uint8(out, 0); + s_mark_end(out); + } + result = s_length(out); free(filename); break; @@ -760,23 +764,14 @@ rdpdr_process_irp(STREAM s) in_uint8s(s, 0x14); /* TODO: Why do we need to increase length by padlen? Or is it hdr len? */ - buffer = (uint8 *) xrealloc((void *) buffer, bytes_out + 0x14); - if (!buffer) - { - status = RD_STATUS_CANCELLED; - break; - } - - out.data = out.p = buffer; - /* Guess, just a simple mistype. Check others */ - //out.size = sizeof(buffer); - out.size = bytes_out + 0x14; + out = s_alloc(bytes_out + 0x14); #ifdef WITH_SCARD scardSetInfo(g_epoch, device, id, bytes_out + 0x14); #endif - status = fns->device_control(file, request, s, &out); - result = buffer_len = out.p - out.data; + status = fns->device_control(file, request, s, out); + s_mark_end(out); + result = s_length(out); /* Serial SERIAL_WAIT_ON_MASK */ if (status == RD_STATUS_PENDING) @@ -805,12 +800,12 @@ rdpdr_process_irp(STREAM s) in_uint32_le(s, info_level); - out.data = out.p = buffer; - out.size = sizeof(buffer); + out = s_alloc(1024); /* FIXME: Perhaps consider actually *do* something here :-) */ status = RD_STATUS_SUCCESS; - result = buffer_len = out.p - out.data; + s_mark_end(out); + result = s_length(out); break; default: @@ -822,11 +817,25 @@ rdpdr_process_irp(STREAM s) if (status != RD_STATUS_PENDING) { + size_t buffer_len; + uint8 *buffer; + + if (out != NULL) + { + buffer_len = s_length(out); + s_seek(out, 0); + in_uint8p(out, buffer, buffer_len); + } + else + { + buffer_len = 0; + buffer = NULL; + } + rdpdr_send_completion(device, id, status, result, buffer, buffer_len); } - if (buffer) - xfree(buffer); - buffer = NULL; + if (out) + s_free(out); } static void diff --git a/rdpsnd.c b/rdpsnd.c index 8bb2dbb..7bbb9b6 100644 --- a/rdpsnd.c +++ b/rdpsnd.c @@ -64,6 +64,7 @@ unsigned int queue_hi, queue_lo, queue_pending; struct audio_packet packet_queue[MAX_QUEUE]; static uint8 packet_opcode; +static size_t packet_len; static struct stream packet; void (*wave_out_play) (void); @@ -295,8 +296,11 @@ static void rdpsnd_process_packet(uint8 opcode, STREAM s) { uint16 vol_left, vol_right; - static uint16 tick, format; - static uint8 packet_index; + + uint16 tick, format; + uint8 packet_index; + unsigned int size; + unsigned char *data; switch (opcode) { @@ -345,9 +349,12 @@ rdpsnd_process_packet(uint8 opcode, STREAM s) current_format = format; } - rdpsnd_queue_write(rdpsnd_dsp_process - (s->p, s_remaining(s), current_driver, - &formats[current_format]), tick, packet_index); + size = s_remaining(s); + in_uint8p(s, data, size); + rdpsnd_queue_write(rdpsnd_dsp_process(data, size, + current_driver, + &formats[current_format]), + tick, packet_index); return; break; case SNDC_CLOSE: @@ -382,12 +389,10 @@ rdpsnd_process_packet(uint8 opcode, STREAM s) static void rdpsnd_process(STREAM s) { - uint16 len; - while (!s_check_end(s)) { /* New packet */ - if (packet.size == 0) + if (packet_len == 0) { if (!s_check_rem(s, 4)) { @@ -397,25 +402,23 @@ rdpsnd_process(STREAM s) } in_uint8(s, packet_opcode); in_uint8s(s, 1); /* Padding */ - in_uint16_le(s, len); + in_uint16_le(s, packet_len); logger(Sound, Debug, "rdpsnd_process(), Opcode = 0x%x Length= %d", - (int) packet_opcode, (int) len); - - packet.p = packet.data; - packet.end = packet.data + len; - packet.size = len; + (int) packet_opcode, (int) packet_len); } else { - len = MIN(s_remaining(s), s_remaining(&packet)); + uint16 len; + + len = MIN(s_remaining(s), packet_len - s_length(&packet)); /* Microsoft's server is so broken it's not even funny... */ if (packet_opcode == SNDC_WAVE) { - if ((packet.p - packet.data) < 12) - len = MIN(len, 12 - (packet.p - packet.data)); - else if ((packet.p - packet.data) == 12) + if (s_length(&packet) < 12) + len = MIN(len, 12 - s_length(&packet)); + else if (s_length(&packet) == 12) { logger(Sound, Debug, "rdpsnd_process(), eating 4 bytes of %d bytes...", @@ -425,16 +428,18 @@ rdpsnd_process(STREAM s) } } - in_uint8a(s, packet.p, len); - packet.p += len; + in_uint8stream(s, &packet, len); + /* Always end it so s_length() works */ + s_mark_end(&packet); } /* Packet fully assembled */ - if (packet.p == packet.end) + if (s_length(&packet) == packet_len) { - packet.p = packet.data; + s_seek(&packet, 0); rdpsnd_process_packet(packet_opcode, &packet); - packet.size = 0; + packet_len = 0; + s_reset(&packet); } } } @@ -457,7 +462,8 @@ rdpsnddbg_process(STREAM s) pkglen = s_remaining(s); /* str_handle_lines requires null terminated strings */ buf = (char *) xmalloc(pkglen + 1); - STRNCPY(buf, (char *) s->p, pkglen + 1); + in_uint8a(s, buf, pkglen); + buf[pkglen] = '\0'; str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL); @@ -513,9 +519,7 @@ rdpsnd_init(char *optarg) drivers = NULL; - packet.data = (uint8 *) xmalloc(65536); - packet.p = packet.end = packet.data; - packet.size = 0; + s_realloc(&packet, 65536); rdpsnd_channel = channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, diff --git a/rdpsnd_alsa.c b/rdpsnd_alsa.c index 25fbc31..0a71597 100644 --- a/rdpsnd_alsa.c +++ b/rdpsnd_alsa.c @@ -358,6 +358,8 @@ alsa_play(void) struct audio_packet *packet; STREAM out; int len; + const unsigned char *data; + size_t before; static long prev_s, prev_us; int duration; struct timeval tv; @@ -380,13 +382,21 @@ alsa_play(void) next_tick = rdpsnd_queue_next_tick(); + before = s_tell(out); + len = s_remaining(out) / (samplewidth_out * audiochannels_out); - if ((len = snd_pcm_writei(out_handle, out->p, ((MAX_FRAMES < len) ? MAX_FRAMES : len))) < 0) + len = MIN(len, MAX_FRAMES); + in_uint8p(out, data, len); + + len = snd_pcm_writei(out_handle, data, len); + if (len < 0) { snd_pcm_prepare(out_handle); len = 0; } - out->p += (len * samplewidth_out * audiochannels_out); + + /* We might not have written everything */ + s_seek(out, before + len * samplewidth_out * audiochannels_out); gettimeofday(&tv, NULL); @@ -395,7 +405,7 @@ alsa_play(void) if (packet->tick > next_tick) next_tick += 65536; - if ((out->p == out->end) || duration > next_tick - packet->tick + 500) + if (s_check_end(out) || duration > next_tick - packet->tick + 500) { snd_pcm_sframes_t delay_frames; unsigned long delay_us; diff --git a/rdpsnd_libao.c b/rdpsnd_libao.c index 3a59788..b116742 100644 --- a/rdpsnd_libao.c +++ b/rdpsnd_libao.c @@ -148,6 +148,7 @@ libao_play(void) { struct audio_packet *packet; STREAM out; + unsigned char *data; int len; static long prev_s, prev_us; int duration; @@ -172,8 +173,8 @@ libao_play(void) next_tick = rdpsnd_queue_next_tick(); len = MIN(WAVEOUTLEN, s_remaining(out)); - ao_play(o_device, (char *) out->p, len); - out->p += len; + in_uint8p(out, data, len); + ao_play(o_device, (char *) data, len); gettimeofday(&tv, NULL); @@ -182,7 +183,7 @@ libao_play(void) if (packet->tick > next_tick) next_tick += 65536; - if ((out->p == out->end) || duration > next_tick - packet->tick + 500) + if (s_check_end(out) || duration > next_tick - packet->tick + 500) { unsigned int delay_us; diff --git a/rdpsnd_oss.c b/rdpsnd_oss.c index 0705236..561e78c 100644 --- a/rdpsnd_oss.c +++ b/rdpsnd_oss.c @@ -402,6 +402,8 @@ oss_play(void) struct audio_packet *packet; ssize_t len; STREAM out; + size_t before; + const unsigned char *data; assert(dsp_fd != -1); @@ -412,9 +414,12 @@ oss_play(void) packet = rdpsnd_queue_current_packet(); out = packet->s; - len = s_remaining(out); + before = s_tell(out); - len = write(dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len); + len = MIN(s_remaining(out), MAX_LEN); + in_uint8p(out, data, len); + + len = write(dsp_fd, data, len); if (len == -1) { if (errno != EWOULDBLOCK) @@ -429,9 +434,10 @@ oss_play(void) dsp_broken = False; - out->p += len; + /* We might not have written everything */ + s_seek(out, before + len); - if (out->p == out->end) + if (s_check_end(out)) { int delay_bytes; unsigned long delay_us; diff --git a/rdpsnd_pulse.c b/rdpsnd_pulse.c index a763541..6fde46f 100644 --- a/rdpsnd_pulse.c +++ b/rdpsnd_pulse.c @@ -1195,8 +1195,11 @@ pulse_play(void) audio_size = MIN(s_remaining(out), avail_space); if (audio_size) { + unsigned char *data; + + in_uint8p(out, data, audio_size); if (pa_stream_write - (playback_stream, out->p, audio_size, NULL, 0, playback_seek) != 0) + (playback_stream, data, audio_size, NULL, 0, playback_seek) != 0) { err = pa_context_errno(context); logger(Sound, Error, "pulse_play(), pa_stream_write: %s", @@ -1207,9 +1210,7 @@ pulse_play(void) playback_seek = PA_SEEK_RELATIVE; } - out->p += audio_size; - - if (out->p == out->end) + if (s_check_end(out)) { ret = pa_stream_get_latency(playback_stream, &delay, NULL); if (ret != 0 && (err = pa_context_errno(context)) == PA_ERR_NODATA) @@ -1251,7 +1252,7 @@ pulse_play(void) pa_threaded_mainloop_unlock(mainloop); - if (out->p == out->end) + if (s_check_end(out)) rdpsnd_queue_next(delay); return result; diff --git a/rdpsnd_sgi.c b/rdpsnd_sgi.c index d62f12c..d1dce66 100644 --- a/rdpsnd_sgi.c +++ b/rdpsnd_sgi.c @@ -246,6 +246,7 @@ sgi_play(void) struct audio_packet *packet; ssize_t len; STREAM out; + unsigned char *data; int gf; while (1) @@ -257,11 +258,11 @@ sgi_play(void) out = packet->s; len = s_remaining(out); + in_uint8p(out, data, len); - alWriteFrames(output_port, out->p, len / combinedFrameSize); + alWriteFrames(output_port, data, len / combinedFrameSize); - out->p += len; - if (out->p == out->end) + if (s_check_end(out)) { gf = alGetFilled(output_port); if (gf < (4 * maxFillable / 10)) diff --git a/rdpsnd_sun.c b/rdpsnd_sun.c index 50a8fb2..b682ca5 100644 --- a/rdpsnd_sun.c +++ b/rdpsnd_sun.c @@ -411,17 +411,22 @@ sun_play(void) struct audio_packet *packet; ssize_t len; STREAM out; + size_t before; + const unsigned char *data; /* We shouldn't be called if the queue is empty, but still */ if (rdpsnd_queue_empty()) return; packet = rdpsnd_queue_current_packet(); - out = &packet->s; + out = packet->s; - len = s_remaining(out); + before = s_tell(out); - len = write(dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len); + len = MIN(s_remaining(out), MAX_LEN); + in_uint8p(out, data, len); + + len = write(dsp_fd, data, len); if (len == -1) { if (errno != EWOULDBLOCK) @@ -439,9 +444,10 @@ sun_play(void) dsp_broken = False; - out->p += len; + /* We might not have written everything */ + s_seek(out, before + len); - if (out->p == out->end) + if (s_check_end(out)) { audio_info_t info; uint_t delay_samples; diff --git a/scard.c b/scard.c index 9e4e807..92b984a 100644 --- a/scard.c +++ b/scard.c @@ -562,7 +562,7 @@ outBufferFinish(STREAM out, char *buffer, unsigned int length) static void outForceAlignment(STREAM out, unsigned int seed) { - SERVER_DWORD add = (seed - (out->p - out->data) % seed) % seed; + SERVER_DWORD add = (seed - s_tell(out) % seed) % seed; if (add > 0) out_uint8s(out, add); } @@ -639,7 +639,7 @@ static void inReaderName(PMEM_HANDLE * handle, STREAM in, char **destination, RD_BOOL wide) { SERVER_DWORD dataLength; - in->p += 0x08; + in_uint8s(in, 0x08); in_uint32_le(in, dataLength); inRepos(in, inString(handle, in, destination, dataLength, wide)); } @@ -717,6 +717,7 @@ TS_SCardEstablishContext(STREAM in, STREAM out) out_uint32_le(out, 0x00000004); out_uint32_le(out, hContext); outForceAlignment(out, 8); + s_mark_end(out); return rv; } @@ -727,7 +728,7 @@ TS_SCardReleaseContext(STREAM in, STREAM out) MYPCSC_SCARDCONTEXT myHContext; SERVER_SCARDCONTEXT hContext; - in->p += 0x1C; + in_uint8s(in, 0x1C); in_uint32_le(in, hContext); myHContext = _scard_handle_list_get_pcsc_handle(hContext); @@ -752,6 +753,7 @@ TS_SCardReleaseContext(STREAM in, STREAM out) } outForceAlignment(out, 8); + s_mark_end(out); return rv; } @@ -762,7 +764,7 @@ TS_SCardIsValidContext(STREAM in, STREAM out) SERVER_SCARDCONTEXT hContext; MYPCSC_SCARDCONTEXT myHContext; - in->p += 0x1C; + in_uint8s(in, 0x1C); in_uint32_le(in, hContext); myHContext = _scard_handle_list_get_pcsc_handle(hContext); @@ -786,6 +788,7 @@ TS_SCardIsValidContext(STREAM in, STREAM out) } outForceAlignment(out, 8); + s_mark_end(out); return rv; } @@ -799,21 +802,21 @@ TS_SCardListReaders(STREAM in, STREAM out, RD_BOOL wide) MYPCSC_SCARDCONTEXT myHContext; SERVER_DWORD dataLength; MYPCSC_DWORD cchReaders = readerArraySize; - unsigned char *plen1, *plen2, *pend; + size_t plen1, plen2, pend; char *readers, *cur; PMEM_HANDLE lcHandle = NULL; - in->p += 0x2C; + in_uint8s(in, 0x2C); in_uint32_le(in, hContext); myHContext = _scard_handle_list_get_pcsc_handle(hContext); logger(SmartCard, Debug, "TS_SCardListReaders(), context: 0x%08x [0x%lx])", (unsigned) hContext, myHContext); - plen1 = out->p; + plen1 = s_tell(out); out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */ out_uint32_le(out, 0x01760650); - plen2 = out->p; + plen2 = s_tell(out); out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */ dataLength = 0; @@ -863,14 +866,17 @@ TS_SCardListReaders(STREAM in, STREAM out, RD_BOOL wide) dataLength += outString(out, "\0", wide); outRepos(out, dataLength); - pend = out->p; - out->p = plen1; + s_mark_end(out); + + pend = s_tell(out); + s_seek(out, plen1); out_uint32_le(out, dataLength); - out->p = plen2; + s_seek(out, plen2); out_uint32_le(out, dataLength); - out->p = pend; + s_seek(out, pend); outForceAlignment(out, 8); + s_mark_end(out); SC_xfreeallmemory(&lcHandle); return rv; } @@ -891,11 +897,11 @@ TS_SCardConnect(STREAM in, STREAM out, RD_BOOL wide) MYPCSC_DWORD dwActiveProtocol; PMEM_HANDLE lcHandle = NULL; - in->p += 0x1C; + in_uint8s(in, 0x1C); in_uint32_le(in, dwShareMode); in_uint32_le(in, dwPreferredProtocol); inReaderName(&lcHandle, in, &szReader, wide); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, hContext); myHContext = _scard_handle_list_get_pcsc_handle(hContext); @@ -966,6 +972,7 @@ TS_SCardConnect(STREAM in, STREAM out, RD_BOOL wide) out_uint32_le(out, hCard); outForceAlignment(out, 8); + s_mark_end(out); SC_xfreeallmemory(&lcHandle); return rv; } @@ -982,13 +989,13 @@ TS_SCardReconnect(STREAM in, STREAM out) SERVER_DWORD dwInitialization; MYPCSC_DWORD dwActiveProtocol; - in->p += 0x20; + in_uint8s(in, 0x20); in_uint32_le(in, dwShareMode); in_uint32_le(in, dwPreferredProtocol); in_uint32_le(in, dwInitialization); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, hContext); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, hCard); @@ -1014,6 +1021,7 @@ TS_SCardReconnect(STREAM in, STREAM out) out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol); outForceAlignment(out, 8); + s_mark_end(out); return rv; } @@ -1027,11 +1035,11 @@ TS_SCardDisconnect(STREAM in, STREAM out) MYPCSC_SCARDHANDLE myHCard; SERVER_DWORD dwDisposition; - in->p += 0x20; + in_uint8s(in, 0x20); in_uint32_le(in, dwDisposition); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, hContext); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, hCard); myHContext = _scard_handle_list_get_pcsc_handle(hContext); @@ -1076,6 +1084,7 @@ TS_SCardDisconnect(STREAM in, STREAM out) } outForceAlignment(out, 8); + s_mark_end(out); return rv; } @@ -1162,12 +1171,12 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide) long i; PMEM_HANDLE lcHandle = NULL; - in->p += 0x18; + in_uint8s(in, 0x18); in_uint32_le(in, dwTimeout); in_uint32_le(in, dwCount); - in->p += 0x08; + in_uint8s(in, 0x08); in_uint32_le(in, hContext); - in->p += 0x04; + in_uint8s(in, 0x04); myHContext = _scard_handle_list_get_pcsc_handle(hContext); @@ -1197,7 +1206,7 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide) { SERVER_DWORD dataLength; - in->p += 0x08; + in_uint8s(in, 0x08); in_uint32_le(in, dataLength); inRepos(in, inString(&lcHandle, in, (char **) &(cur->szReader), @@ -1259,6 +1268,7 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide) sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *)); } outForceAlignment(out, 8); + s_mark_end(out); SC_xfreeallmemory(&lcHandle); return rv; } @@ -1270,7 +1280,7 @@ TS_SCardCancel(STREAM in, STREAM out) SERVER_SCARDCONTEXT hContext; MYPCSC_SCARDCONTEXT myHContext; - in->p += 0x1C; + in_uint8s(in, 0x1C); in_uint32_le(in, hContext); myHContext = _scard_handle_list_get_pcsc_handle(hContext); @@ -1289,6 +1299,7 @@ TS_SCardCancel(STREAM in, STREAM out) logger(SmartCard, Debug, "TS_SCardCancel(), success"); } outForceAlignment(out, 8); + s_mark_end(out); return rv; } @@ -1309,7 +1320,7 @@ TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide) MYPCSC_LPSCARD_READERSTATE_A myRsArray; PMEM_HANDLE lcHandle = NULL; - in->p += 0x2C; + in_uint8s(in, 0x2C); in_uint32_le(in, hContext); in_uint32_le(in, atrMaskCount); pAtrMasks = SC_xmalloc(&lcHandle, atrMaskCount * sizeof(SCARD_ATRMASK_L)); @@ -1424,6 +1435,7 @@ TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide) } outForceAlignment(out, 8); + s_mark_end(out); SC_xfreeallmemory(&lcHandle); return rv; } @@ -1435,7 +1447,7 @@ TS_SCardBeginTransaction(STREAM in, STREAM out) SERVER_SCARDCONTEXT hCard; MYPCSC_SCARDCONTEXT myHCard; - in->p += 0x30; + in_uint8s(in, 0x30); in_uint32_le(in, hCard); myHCard = _scard_handle_list_get_pcsc_handle(hCard); logger(SmartCard, Debug, "TS_SCardBeginTransaction(), hcard: 0x%08x [0x%lx])", @@ -1451,6 +1463,7 @@ TS_SCardBeginTransaction(STREAM in, STREAM out) logger(SmartCard, Debug, "TS_SCardBeginTransaction(), success"); } outForceAlignment(out, 8); + s_mark_end(out); return rv; } @@ -1462,9 +1475,9 @@ TS_SCardEndTransaction(STREAM in, STREAM out) MYPCSC_SCARDCONTEXT myHCard; SERVER_DWORD dwDisposition = 0; - in->p += 0x20; + in_uint8s(in, 0x20); in_uint32_le(in, dwDisposition); - in->p += 0x0C; + in_uint8s(in, 0x0C); in_uint32_le(in, hCard); myHCard = _scard_handle_list_get_pcsc_handle(hCard); @@ -1483,6 +1496,7 @@ TS_SCardEndTransaction(STREAM in, STREAM out) logger(SmartCard, Debug, "TS_SCardEndTransaction(), success"); } outForceAlignment(out, 8); + s_mark_end(out); return rv; } @@ -1531,9 +1545,9 @@ TS_SCardTransmit(STREAM in, STREAM out, uint32 srv_buf_len) PMEM_HANDLE lcHandle = NULL; - in->p += 0x14; + in_uint8s(in, 0x14); in_uint32_le(in, map[0]); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, map[1]); pioSendPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST)); if (!pioSendPci) @@ -1551,7 +1565,7 @@ TS_SCardTransmit(STREAM in, STREAM out, uint32 srv_buf_len) if (srv_buf_len <= cbRecvLength) cbRecvLength = srv_buf_len; - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, hCard); myHCard = _scard_handle_list_get_pcsc_handle(hCard); @@ -1695,6 +1709,7 @@ TS_SCardTransmit(STREAM in, STREAM out, uint32 srv_buf_len) outBufferFinish(out, (char *) recvBuf, cbRecvLength); } outForceAlignment(out, 8); + s_mark_end(out); SC_xfreeallmemory(&lcHandle); return rv; } @@ -1712,12 +1727,12 @@ TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide) char *readerName; unsigned char *atr; - in->p += 0x24; + in_uint8s(in, 0x24); in_uint32_le(in, dwReaderLen); in_uint32_le(in, dwAtrLen); - in->p += 0x0C; + in_uint8s(in, 0x0C); in_uint32_le(in, hCard); - in->p += 0x04; + in_uint8s(in, 0x04); myHCard = _scard_handle_list_get_pcsc_handle(hCard); logger(SmartCard, Debug, "TS_SCardStatus(), hcard: 0x%08x [0x%08lx], reader len: %d bytes, atr len: %d bytes", @@ -1790,7 +1805,7 @@ TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide) else dwState = 0x00000000; - void *p_len1 = out->p; + size_t p_len1 = s_tell(out); out_uint32_le(out, dwReaderLen); out_uint32_le(out, 0x00020000); out_uint32_le(out, dwState); @@ -1802,19 +1817,21 @@ TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide) } out_uint32_le(out, dwAtrLen); - void *p_len2 = out->p; + size_t p_len2 = s_tell(out); out_uint32_le(out, dwReaderLen); dataLength = outString(out, readerName, wide); dataLength += outString(out, "\0", wide); outRepos(out, dataLength); - void *psave = out->p; - out->p = p_len1; + s_mark_end(out); + size_t psave = s_tell(out); + s_seek(out, p_len1); out_uint32_le(out, dataLength); - out->p = p_len2; + s_seek(out, p_len2); out_uint32_le(out, dataLength); - out->p = psave; + s_seek(out, psave); } outForceAlignment(out, 8); + s_mark_end(out); SC_xfreeallmemory(&lcHandle); return rv; } @@ -1831,11 +1848,11 @@ TS_SCardState(STREAM in, STREAM out) char *readerName; unsigned char *atr; - in->p += 0x24; + in_uint8s(in, 0x24); in_uint32_le(in, dwAtrLen); - in->p += 0x0C; + in_uint8s(in, 0x0C); in_uint32_le(in, hCard); - in->p += 0x04; + in_uint8s(in, 0x04); myHCard = _scard_handle_list_get_pcsc_handle(hCard); logger(SmartCard, Debug, "TS_SCardState(), hcard: 0x%08x [0x%08lx], atrlen: %d bytes", @@ -1905,6 +1922,7 @@ TS_SCardState(STREAM in, STREAM out) outRepos(out, dwAtrLen); } outForceAlignment(out, 8); + s_mark_end(out); SC_xfreeallmemory(&lcHandle); return rv; } @@ -1926,9 +1944,9 @@ TS_SCardListReaderGroups(STREAM in, STREAM out) char *szGroups; PMEM_HANDLE lcHandle = NULL; - in->p += 0x20; + in_uint8s(in, 0x20); in_uint32_le(in, dwGroups); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, hContext); myHContext = _scard_handle_list_get_pcsc_handle(hContext); @@ -1974,6 +1992,7 @@ TS_SCardListReaderGroups(STREAM in, STREAM out) out_uint32_le(out, 0x00000000); outForceAlignment(out, 8); + s_mark_end(out); SC_xfreeallmemory(&lcHandle); return rv; } @@ -1990,11 +2009,11 @@ TS_SCardGetAttrib(STREAM in, STREAM out) unsigned char *pbAttr; PMEM_HANDLE lcHandle = NULL; - in->p += 0x20; + in_uint8s(in, 0x20); in_uint32_le(in, dwAttrId); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, dwAttrLen); - in->p += 0x0C; + in_uint8s(in, 0x0C); in_uint32_le(in, hCard); myHCard = _scard_handle_list_get_pcsc_handle(hCard); @@ -2044,6 +2063,7 @@ TS_SCardGetAttrib(STREAM in, STREAM out) out_uint32_le(out, 0x00000000); } outForceAlignment(out, 8); + s_mark_end(out); return rv; } @@ -2060,11 +2080,11 @@ TS_SCardSetAttrib(STREAM in, STREAM out) unsigned char *pbAttr; PMEM_HANDLE lcHandle = NULL; - in->p += 0x20; + in_uint8s(in, 0x20); in_uint32_le(in, dwAttrId); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, dwAttrLen); - in->p += 0x0C; + in_uint8s(in, 0x0C); in_uint32_le(in, hCard); myHCard = scHandleToMyPCSC(hCard); @@ -2098,6 +2118,7 @@ TS_SCardSetAttrib(STREAM in, STREAM out) out_uint32_le(out, 0x00000000); out_uint32_le(out, 0x00000000); outForceAlignment(out, 8); + s_mark_end(out); SC_xfreeallmemory(&lcHandle); return rv; } @@ -2123,18 +2144,18 @@ TS_SCardControl(STREAM in, STREAM out) pInBuffer = NULL; pOutBuffer = NULL; - in->p += 0x14; + in_uint8s(in, 0x14); in_uint32_le(in, map[0]); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, map[1]); in_uint32_le(in, dwControlCode); in_uint32_le(in, nInBufferSize); in_uint32_le(in, map[2]); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, nOutBufferSize); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, hContext); - in->p += 0x04; + in_uint8s(in, 0x04); in_uint32_le(in, hCard); if (map[2] & INPUT_LINKED) { @@ -2241,6 +2262,7 @@ TS_SCardControl(STREAM in, STREAM out) } outForceAlignment(out, 8); + s_mark_end(out); SC_xfreeallmemory(&lcHandle); return rv; } @@ -2260,7 +2282,7 @@ scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out, { UNUSED(handle); SERVER_DWORD Result = 0x00000000; - unsigned char *psize, *pend, *pStatusCode; + size_t psize, pend, pStatusCode; SERVER_DWORD addToEnd = 0; /* Processing request */ @@ -2270,11 +2292,11 @@ scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out, /* Set CommonTypeHeader (MS-RPCE 2.2.6.1) */ out_uint32_le(out, 0x00081001); /* Header lines */ out_uint32_le(out, 0xCCCCCCCC); - psize = out->p; + psize = s_tell(out); /* Set PrivateTypeHeader (MS-RPCE 2.2.6.2) */ out_uint32_le(out, 0x00000000); /* Size of data portion */ out_uint32_le(out, 0x00000000); /* Zero bytes (may be useful) */ - pStatusCode = out->p; + pStatusCode = s_tell(out); out_uint32_le(out, 0x00000000); /* Status Code */ switch (request) @@ -2410,22 +2432,25 @@ scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out, #if 0 out_uint32_le(out, 0x00000000); #endif + s_mark_end(out); + /* Setting modified variables */ - pend = out->p; + pend = s_tell(out); /* setting data size */ - out->p = psize; + s_seek(out, psize); out_uint32_le(out, pend - psize - 16); /* setting status code */ - out->p = pStatusCode; + s_seek(out, pStatusCode); out_uint32_le(out, Result); /* finish */ - out->p = pend; + s_seek(out, pend); /* TODO: Check MS-RPCE 2.2.6.2 for alignment requirements (IIRC length must be integral multiple of 8) */ addToEnd = (pend - pStatusCode) % 16; if (addToEnd < 16 && addToEnd > 0) { out_uint8s(out, addToEnd); + s_mark_end(out); } if (Result == SCARD_E_INSUFFICIENT_BUFFER) return RD_STATUS_BUFFER_TOO_SMALL; @@ -2574,13 +2599,18 @@ SC_deviceControl(PSCThreadData data) RD_NTSTATUS status; size_t buffer_len = 0; status = scard_device_control(data->handle, data->request, data->in, data->out, data->srv_buf_len); - buffer_len = (size_t) data->out->p - (size_t) data->out->data; + buffer_len = s_tell(data->out); /* if iorequest belongs to another epoch, don't send response back to server due to it's considered as abandoned. */ if (data->epoch == curEpoch) - rdpdr_send_completion(data->device, data->id, status, buffer_len, data->out->data, buffer_len); + { + uint8 *buf; + s_seek(data->out, 0); + in_uint8p(data->out, buf, buffer_len); + rdpdr_send_completion(data->device, data->id, status, buffer_len, buf, buffer_len); + } SC_destroyThreadData(data); } diff --git a/seamless.c b/seamless.c index f5cc7a4..289b30a 100644 --- a/seamless.c +++ b/seamless.c @@ -380,7 +380,8 @@ seamless_process(STREAM s) pkglen = s_remaining(s); /* str_handle_lines requires null terminated strings */ buf = xmalloc(pkglen + 1); - STRNCPY(buf, (char *) s->p, pkglen + 1); + in_uint8a(s, buf, pkglen); + buf[pkglen] = '\0'; str_handle_lines(buf, &seamless_rest, seamless_line_handler, NULL); xfree(buf); diff --git a/secure.c b/secure.c index 8c5dd42..eb7c129 100644 --- a/secure.c +++ b/secure.c @@ -351,10 +351,12 @@ sec_send_to_channel(STREAM s, uint32 flags, uint16 channel) if (flags & SEC_ENCRYPT) { + unsigned char *data; flags &= ~SEC_ENCRYPT; datalen = s_remaining(s) - 8; - sec_sign(s->p, 8, g_sec_sign_key, g_rc4_key_len, s->p + 8, datalen); - sec_encrypt(s->p + 8, datalen); + inout_uint8p(s, data, datalen + 8); + sec_sign(data, 8, g_sec_sign_key, g_rc4_key_len, data + 8, datalen); + sec_encrypt(data + 8, datalen); } mcs_send_to_channel(s, channel); @@ -587,7 +589,7 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size, RDSSL_CERT *cacert, *server_cert; RDSSL_RKEY *server_public_key; uint16 tag, length; - uint8 *next_tag, *end; + size_t next_tag; logger(Protocol, Debug, "%s()", __func__); @@ -613,10 +615,9 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size, in_uint8p(s, *server_random, random_len); /* RSA info */ - end = s->p + rsa_info_len; - if (end > s->end) + if (!s_check_rem(s, rsa_info_len)) { - logger(Protocol, Error, "sec_parse_crypt_info(), end > s->end"); + logger(Protocol, Error, "sec_parse_crypt_info(), !s_check_rem(s, rsa_info_len)"); return False; } @@ -627,12 +628,12 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size, "sec_parse_crypt_info(), We're going for the RDP4-style encryption"); in_uint8s(s, 8); /* unknown */ - while (s->p < end) + while (!s_check_end(s)) { in_uint16_le(s, tag); in_uint16_le(s, length); - next_tag = s->p + length; + next_tag = s_tell(s) + length; switch (tag) { @@ -663,12 +664,13 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size, tag); } - s->p = next_tag; + s_seek(s, next_tag); } } else { uint32 certcount; + unsigned char *certdata; logger(Protocol, Debug, "sec_parse_crypt_info(), We're going for the RDP5-style encryption"); @@ -683,10 +685,11 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size, { /* ignore all the certificates between the root and the signing CA */ uint32 ignorelen; RDSSL_CERT *ignorecert; + unsigned char *ignoredata; in_uint32_le(s, ignorelen); - ignorecert = rdssl_cert_read(s->p, ignorelen); - in_uint8s(s, ignorelen); + in_uint8p(s, ignoredata, ignorelen); + ignorecert = rdssl_cert_read(ignoredata, ignorelen); if (ignorecert == NULL) { /* XXX: error out? */ logger(Protocol, Error, @@ -706,10 +709,10 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size, http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt */ in_uint32_le(s, cacert_len); + in_uint8p(s, certdata, cacert_len); logger(Protocol, Debug, "sec_parse_crypt_info(), server CA Certificate length is %d", cacert_len); - cacert = rdssl_cert_read(s->p, cacert_len); - in_uint8s(s, cacert_len); + cacert = rdssl_cert_read(certdata, cacert_len); if (NULL == cacert) { logger(Protocol, Error, @@ -717,10 +720,10 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size, return False; } in_uint32_le(s, cert_len); + in_uint8p(s, certdata, cert_len); logger(Protocol, Debug, "sec_parse_crypt_info(), certificate length is %d", cert_len); - server_cert = rdssl_cert_read(s->p, cert_len); - in_uint8s(s, cert_len); + server_cert = rdssl_cert_read(certdata, cert_len); if (NULL == server_cert) { rdssl_cert_free(cacert); @@ -814,7 +817,7 @@ void sec_process_mcs_data(STREAM s) { uint16 tag, length; - uint8 *next_tag; + size_t next_tag; uint8 len; in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */ @@ -823,7 +826,7 @@ sec_process_mcs_data(STREAM s) in_uint8(s, len); logger(Protocol, Debug, "%s()", __func__); - while (s->p < s->end) + while (!s_check_end(s)) { in_uint16_le(s, tag); in_uint16_le(s, length); @@ -831,7 +834,7 @@ sec_process_mcs_data(STREAM s) if (length <= 4) return; - next_tag = s->p + length - 4; + next_tag = s_tell(s) + length - 4; switch (tag) { @@ -856,7 +859,7 @@ sec_process_mcs_data(STREAM s) logger(Protocol, Warning, "Unhandled response tag 0x%x", tag); } - s->p = next_tag; + s_seek(s, next_tag); } } @@ -869,6 +872,8 @@ sec_recv(RD_BOOL * is_fastpath) uint16 channel; STREAM s; struct stream packet; + size_t data_offset; + unsigned char *data; while ((s = mcs_recv(&channel, is_fastpath, &fastpath_hdr)) != NULL) { @@ -886,19 +891,29 @@ sec_recv(RD_BOOL * is_fastpath) } in_uint8s(s, 8); /* signature */ - sec_decrypt(s->p, s_remaining(s)); + + data_offset = s_tell(s); + + inout_uint8p(s, data, s_remaining(s)); + sec_decrypt(data, s_remaining(s)); + + s_seek(s, data_offset); } return s; } if (g_encryption || (!g_licence_issued && !g_licence_error_result)) { + data_offset = s_tell(s); + /* TS_SECURITY_HEADER */ in_uint16_le(s, sec_flags); in_uint8s(s, 2); /* skip sec_flags_hi */ if (g_encryption) { + data_offset = s_tell(s); + if (sec_flags & SEC_ENCRYPT) { if (!s_check_rem(s, 8)) { @@ -906,11 +921,16 @@ sec_recv(RD_BOOL * is_fastpath) } in_uint8s(s, 8); /* signature */ - sec_decrypt(s->p, s_remaining(s)); + + data_offset = s_tell(s); + + inout_uint8p(s, data, s_remaining(s)); + sec_decrypt(data, s_remaining(s)); } if (sec_flags & SEC_LICENSE_PKT) { + s_seek(s, data_offset); licence_process(s); continue; } @@ -924,10 +944,14 @@ sec_recv(RD_BOOL * is_fastpath) } in_uint8s(s, 8); /* signature */ - sec_decrypt(s->p, s_remaining(s)); + + data_offset = s_tell(s); + + inout_uint8p(s, data, s_remaining(s)); + sec_decrypt(data, s_remaining(s)); /* Check for a redirect packet, starts with 00 04 */ - if (s->p[0] == 0 && s->p[1] == 4) + if (data[0] == 0 && data[1] == 4) { /* for some reason the PDU and the length seem to be swapped. This isn't good, but we're going to do a byte for byte @@ -935,17 +959,17 @@ sec_recv(RD_BOOL * is_fastpath) where XX YY is the little endian length. We're going to use 04 00 as the PDU type, so after our swap this will look like: XX YY 04 00 */ - swapbyte = s->p[0]; - s->p[0] = s->p[2]; - s->p[2] = swapbyte; + swapbyte = data[0]; + data[0] = data[2]; + data[2] = swapbyte; - swapbyte = s->p[1]; - s->p[1] = s->p[3]; - s->p[3] = swapbyte; + swapbyte = data[1]; + data[1] = data[3]; + data[3] = swapbyte; - swapbyte = s->p[2]; - s->p[2] = s->p[3]; - s->p[3] = swapbyte; + swapbyte = data[2]; + data[2] = data[3]; + data[3] = swapbyte; } } } @@ -956,8 +980,9 @@ sec_recv(RD_BOOL * is_fastpath) licence_process(s); continue; } - s->p -= 4; } + + s_seek(s, data_offset); } if (channel != MCS_GLOBAL_CHANNEL) diff --git a/stream.h b/stream.h index 5e7464b..b2400c5 100644 --- a/stream.h +++ b/stream.h @@ -152,6 +152,9 @@ size_t in_ansi_string(STREAM s, char *string, size_t len); /* Copy the entire STREAM v (ignoring offsets) in to STREAM s */ #define out_stream(s, v) out_uint8a(s, (v)->data, s_length((v))) +/* Return a pointer in v to manually modify n bytes of STREAM s in place */ +#define inout_uint8p(s,v,n) { s_assert_r(s, n); s_assert_w(s, n); v = (s)->p; (s)->p += n; } + #define next_be(s,v) { s_assert_r(s, 1); v = ((v) << 8) + *((s)->p++); } diff --git a/tcp.c b/tcp.c index 8634631..3f8b112 100644 --- a/tcp.c +++ b/tcp.c @@ -109,8 +109,9 @@ tcp_init(uint32 maxlen) void tcp_send(STREAM s) { - int length = s->end - s->data; - int sent, total = 0; + size_t before; + int length, sent; + unsigned char *data; if (g_network_error == True) return; @@ -119,10 +120,16 @@ tcp_send(STREAM s) scard_lock(SCARD_LOCK_TCP); #endif - while (total < length) + s_seek(s, 0); + + while (!s_check_end(s)) { + before = s_tell(s); + length = s_remaining(s); + in_uint8p(s, data, length); + if (g_ssl_initialized) { - sent = gnutls_record_send(g_tls_session, s->data + total, length - total); + sent = gnutls_record_send(g_tls_session, data, length); if (sent <= 0) { if (gnutls_error_is_fatal(sent)) { #ifdef WITH_SCARD @@ -139,7 +146,7 @@ tcp_send(STREAM s) } else { - sent = send(g_sock, s->data + total, length - total, 0); + sent = send(g_sock, data, length, 0); if (sent <= 0) { if (sent == -1 && TCP_BLOCKS) @@ -159,7 +166,9 @@ tcp_send(STREAM s) } } } - total += sent; + + /* Everything might not have been sent */ + s_seek(s, before + sent); } #ifdef WITH_SCARD scard_unlock(SCARD_LOCK_TCP); @@ -170,7 +179,8 @@ tcp_send(STREAM s) STREAM tcp_recv(STREAM s, uint32 length) { - uint32 new_length, end_offset, p_offset; + size_t before; + unsigned char *data; int rcvd = 0; if (g_network_error == True) @@ -179,27 +189,14 @@ tcp_recv(STREAM s, uint32 length) if (s == NULL) { /* read into "new" stream */ - if (length > g_in.size) - { - g_in.data = (uint8 *) xrealloc(g_in.data, length); - g_in.size = length; - } - g_in.end = g_in.p = g_in.data; + s_realloc(&g_in, length); + s_reset(&g_in); s = &g_in; } else { /* append to existing stream */ - new_length = (s->end - s->data) + length; - if (new_length > s->size) - { - p_offset = s->p - s->data; - end_offset = s->end - s->data; - s->data = (uint8 *) xrealloc(s->data, new_length); - s->size = new_length; - s->p = s->data + p_offset; - s->end = s->data + end_offset; - } + s_realloc(s, s_length(s) + length); } while (length > 0) @@ -215,8 +212,15 @@ tcp_recv(STREAM s, uint32 length) return NULL; } + before = s_tell(s); + s_seek(s, s_length(s)); + + out_uint8p(s, data, length); + + s_seek(s, before); + if (g_ssl_initialized) { - rcvd = gnutls_record_recv(g_tls_session, s->end, length); + rcvd = gnutls_record_recv(g_tls_session, data, length); if (rcvd < 0) { if (gnutls_error_is_fatal(rcvd)) { @@ -231,7 +235,7 @@ tcp_recv(STREAM s, uint32 length) } else { - rcvd = recv(g_sock, s->end, length, 0); + rcvd = recv(g_sock, data, length, 0); if (rcvd < 0) { if (rcvd == -1 && TCP_BLOCKS) @@ -253,6 +257,7 @@ tcp_recv(STREAM s, uint32 length) } } + // FIXME: Should probably have a macro for this s->end += rcvd; length -= rcvd; }