1 /* 2 rdesktop: A Remote Desktop Protocol client. 3 Parsing primitives 4 Copyright (C) Matthew Chapman 1999-2008 5 Copyright 2012-2017 Henrik Andersson <hean01@cendio.se> for Cendio AB 6 Copyright 2017 Alexander Zakharov <uglym8@gmail.com> 7 Copyright 2019 Karl Mikaelsson <derfian@cendio.se> for Cendio AB 8 9 This program is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 #ifndef _STREAM_H 24 #define _STREAM_H 25 26 /* Parser state */ 27 typedef struct stream 28 { 29 unsigned char *p; 30 unsigned char *end; 31 unsigned char *data; 32 unsigned int size; 33 34 /* Offsets of various headers */ 35 unsigned char *iso_hdr; 36 unsigned char *mcs_hdr; 37 unsigned char *sec_hdr; 38 unsigned char *rdp_hdr; 39 unsigned char *channel_hdr; 40 41 } 42 *STREAM; 43 44 /* Return a newly allocated STREAM object of the specified size */ 45 STREAM s_alloc(unsigned int size); 46 /* Wrap an existing buffer in a STREAM object, transferring ownership */ 47 STREAM s_inherit(unsigned char *data, unsigned int size); 48 /* Resize an existing STREAM object, keeping all data and offsets intact */ 49 void s_realloc(STREAM s, unsigned int size); 50 /* Free STREAM object and its associated buffer */ 51 void s_free(STREAM s); 52 /* Reset all internal offsets, but keep the allocated size */ 53 void s_reset(STREAM s); 54 55 void out_utf16s(STREAM s, const char *string); 56 void out_utf16s_padded(STREAM s, const char *string, size_t width, unsigned char pad); 57 void out_utf16s_no_eos(STREAM s, const char *string); 58 59 size_t in_ansi_string(STREAM s, char *string, size_t len); 60 61 62 /* Store current offset as header h and skip n bytes */ 63 #define s_push_layer(s,h,n) { (s)->h = (s)->p; (s)->p += n; } 64 /* Set header h as current offset */ 65 #define s_pop_layer(s,h) (s)->p = (s)->h; 66 /* Mark current offset as end of readable data */ 67 #define s_mark_end(s) (s)->end = (s)->p; 68 /* Return current read offset in the STREAM */ 69 #define s_tell(s) (size_t)((s)->p - (s)->data) 70 /* Set current read offset in the STREAM */ 71 #define s_seek(s,o) (s)->p = (s)->data; s_assert_r(s,o); (s)->p += o; 72 /* Returns number of bytes that can still be read from STREAM */ 73 #define s_remaining(s) (size_t)((s)->end - (s)->p) 74 /* True if at least n bytes can still be read */ 75 #define s_check_rem(s,n) (((s)->p <= (s)->end) && ((size_t)n <= s_remaining(s))) 76 /* True if all data has been read */ 77 #define s_check_end(s) ((s)->p == (s)->end) 78 /* Return the total number of bytes that can be read */ 79 #define s_length(s) ((s)->end - (s)->data) 80 /* Return the number of bytes that can still be written */ 81 #define s_left(s) ((s)->size - (size_t)((s)->p - (s)->data)) 82 83 /* Verify that there is enough data/space before accessing a STREAM */ 84 #define s_assert_r(s,n) { if (!s_check_rem(s, n)) rdp_protocol_error( "unexpected stream overrun", s); } 85 #define s_assert_w(s,n) { if (s_left(s) < (size_t)n) { logger(Core, Error, "%s:%d: %s(), %s", __FILE__, __LINE__, __func__, "unexpected stream overrun"); exit(0); } } 86 87 /* Read/write an unsigned integer in little-endian order */ 88 #if defined(L_ENDIAN) && !defined(NEED_ALIGN) 89 #define in_uint16_le(s,v) { s_assert_r(s, 2); v = *(uint16 *)((s)->p); (s)->p += 2; } 90 #define in_uint32_le(s,v) { s_assert_r(s, 4); v = *(uint32 *)((s)->p); (s)->p += 4; } 91 #define in_uint64_le(s,v) { s_assert_r(s, 8); v = *(uint64 *)((s)->p); (s)->p += 8; } 92 #define out_uint16_le(s,v) { s_assert_w(s, 2); *(uint16 *)((s)->p) = v; (s)->p += 2; } 93 #define out_uint32_le(s,v) { s_assert_w(s, 4); *(uint32 *)((s)->p) = v; (s)->p += 4; } 94 #define out_uint64_le(s,v) { s_assert_w(s, 8); *(uint64 *)((s)->p) = v; (s)->p += 8; } 95 #else 96 #define in_uint16_le(s,v) { s_assert_r(s, 2); v = *((s)->p++); v += *((s)->p++) << 8; } 97 #define in_uint32_le(s,v) { s_assert_r(s, 4); in_uint16_le(s,v) \ 98 v += *((s)->p++) << 16; v += *((s)->p++) << 24; } 99 #define in_uint64_le(s,v) { s_assert_r(s, 8); in_uint32_le(s,v) \ 100 v += *((s)->p++) << 32; v += *((s)->p++) << 40; \ 101 v += *((s)->p++) << 48; v += *((s)->p++) << 56; } 102 #define out_uint16_le(s,v) { s_assert_w(s, 2); *((s)->p++) = (v) & 0xff; *((s)->p++) = ((v) >> 8) & 0xff; } 103 #define out_uint32_le(s,v) { s_assert_w(s, 4); out_uint16_le(s, (v) & 0xffff); out_uint16_le(s, ((v) >> 16) & 0xffff); } 104 #define out_uint64_le(s,v) { s_assert_w(s, 8); out_uint32_le(s, (v) & 0xffffffff); out_uint32_le(s, ((v) >> 32) & 0xffffffff); } 105 #endif 106 107 108 /* Read/write an unsigned integer in big-endian order */ 109 #if defined(B_ENDIAN) && !defined(NEED_ALIGN) 110 #define in_uint16_be(s,v) { s_assert_r(s, 2); v = *(uint16 *)((s)->p); (s)->p += 2; } 111 #define in_uint32_be(s,v) { s_assert_r(s, 4); v = *(uint32 *)((s)->p); (s)->p += 4; } 112 #define in_uint64_be(s,v) { s_assert_r(s, 8); v = *(uint64 *)((s)->p); (s)->p += 8; } 113 #define out_uint16_be(s,v) { s_assert_w(s, 2); *(uint16 *)((s)->p) = v; (s)->p += 2; } 114 #define out_uint32_be(s,v) { s_assert_w(s, 4); *(uint32 *)((s)->p) = v; (s)->p += 4; } 115 #define out_uint64_be(s,v) { s_assert_w(s, 8); *(uint64 *)((s)->p) = v; (s)->p += 8; } 116 117 #define B_ENDIAN_PREFERRED 118 #define in_uint16(s,v) in_uint16_be(s,v) 119 #define in_uint32(s,v) in_uint32_be(s,v) 120 #define in_uint64(s,v) in_uint64_be(s,v) 121 122 #define out_uint16(s,v) out_uint16_be(s,v) 123 #define out_uint32(s,v) out_uint32_be(s,v) 124 #define out_uint64(s,v) out_uint64_be(s,v) 125 126 #else 127 #define in_uint16_be(s,v) { s_assert_r(s, 2); v = *((s)->p++); next_be(s,v); } 128 #define in_uint32_be(s,v) { s_assert_r(s, 4); in_uint16_be(s,v); next_be(s,v); next_be(s,v); } 129 #define in_uint64_be(s,v) { s_assert_r(s, 8); in_uint32_be(s,v); next_be(s,v); next_be(s,v); next_be(s,v); next_be(s,v); } 130 #define out_uint16_be(s,v) { s_assert_w(s, 2); *((s)->p++) = ((v) >> 8) & 0xff; *((s)->p++) = (v) & 0xff; } 131 #define out_uint32_be(s,v) { s_assert_w(s, 4); out_uint16_be(s, ((v) >> 16) & 0xffff); out_uint16_be(s, (v) & 0xffff); } 132 #define out_uint64_be(s,v) { s_assert_w(s, 8); out_uint32_be(s, ((v) >> 32) & 0xffffffff); out_uint32_be(s, (v) & 0xffffffff); } 133 #endif 134 135 #ifndef B_ENDIAN_PREFERRED 136 #define in_uint16(s,v) in_uint16_le(s,v) 137 #define in_uint32(s,v) in_uint32_le(s,v) 138 #define in_uint64(s,v) in_uint64_le(s,v) 139 #define out_uint16(s,v) out_uint16_le(s,v) 140 #define out_uint32(s,v) out_uint32_le(s,v) 141 #define out_uint64(s,v) out_uint64_le(s,v) 142 #endif 143 144 /* Read a single unsigned byte in v from STREAM s */ 145 #define in_uint8(s,v) { s_assert_r(s, 1); v = *((s)->p++); } 146 /* Return a pointer in v to manually read n bytes from STREAM s */ 147 #define in_uint8p(s,v,n) { s_assert_r(s, n); v = (s)->p; (s)->p += n; } 148 /* Copy n bytes from STREAM s in to array v */ 149 #define in_uint8a(s,v,n) { s_assert_r(s, n); memcpy(v,(s)->p,n); (s)->p += n; } 150 /* Skip reading n bytes in STREAM s */ 151 #define in_uint8s(s,n) { s_assert_r(s, n); (s)->p += n; } 152 /* Write a single unsigned byte from v to STREAM s */ 153 #define out_uint8(s,v) { s_assert_w(s, 1); *((s)->p++) = v; } 154 /* Return a pointer in v to manually fill in n bytes in STREAM s */ 155 #define out_uint8p(s,v,n) { s_assert_w(s, n); v = (s)->p; (s)->p += n; } 156 /* Copy n bytes from array v in to STREAM s */ 157 #define out_uint8a(s,v,n) { s_assert_w(s, n); memcpy((s)->p,v,n); (s)->p += n; } 158 /* Fill n bytes with 0:s in STREAM s */ 159 #define out_uint8s(s,n) { s_assert_w(s, n); memset((s)->p,0,n); (s)->p += n; } 160 161 /* Copy n bytes from STREAM s in to STREAM v */ 162 #define in_uint8stream(s,v,n) { s_assert_r(s, n); out_uint8a((v), (s)->p, n); (s)->p += n; } 163 /* Copy n bytes in to STREAM s from STREAM v */ 164 #define out_uint8stream(s,v,n) in_uint8stream(v,s,n) 165 /* Copy the entire STREAM v (ignoring offsets) in to STREAM s */ 166 #define out_stream(s, v) out_uint8a(s, (v)->data, s_length((v))) 167 168 /* Return a pointer in v to manually modify n bytes of STREAM s in place */ 169 #define inout_uint8p(s,v,n) { s_assert_r(s, n); s_assert_w(s, n); v = (s)->p; (s)->p += n; } 170 171 /* Read one more byte of an unsigned big-endian integer */ 172 #define next_be(s,v) { s_assert_r(s, 1); v = ((v) << 8) + *((s)->p++); } 173 174 175 #endif /* _STREAM_H */ 176