1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 Parsing primitives
4 Copyright 2017 Henrik Andersson <hean01@cendio.se> for Cendio AB
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <errno.h>
21 #include <iconv.h>
22 #include <stdlib.h>
23
24 #include "rdesktop.h"
25
26 extern char g_codepage[16];
27
28 STREAM
s_alloc(unsigned int size)29 s_alloc(unsigned int size)
30 {
31 STREAM s;
32
33 s = xmalloc(sizeof(struct stream));
34 memset(s, 0, sizeof(struct stream));
35 s_realloc(s, size);
36
37 return s;
38 }
39
40 STREAM
s_inherit(unsigned char * data,unsigned int size)41 s_inherit(unsigned char *data, unsigned int size)
42 {
43 STREAM s;
44
45 s = xmalloc(sizeof(struct stream));
46 memset(s, 0, sizeof(struct stream));
47 s->p = s->data = data;
48 s->size = size;
49
50 return s;
51 }
52
53 void
s_realloc(STREAM s,unsigned int size)54 s_realloc(STREAM s, unsigned int size)
55 {
56 unsigned char *data;
57
58 if (s->size >= size)
59 return;
60
61 data = s->data;
62 s->size = size;
63 s->data = xrealloc(data, size);
64 s->p = s->data + (s->p - data);
65 s->end = s->data + (s->end - data);
66 s->iso_hdr = s->data + (s->iso_hdr - data);
67 s->mcs_hdr = s->data + (s->mcs_hdr - data);
68 s->sec_hdr = s->data + (s->sec_hdr - data);
69 s->rdp_hdr = s->data + (s->rdp_hdr - data);
70 s->channel_hdr = s->data + (s->channel_hdr - data);
71 }
72
73 void
s_reset(STREAM s)74 s_reset(STREAM s)
75 {
76 struct stream tmp;
77 tmp = *s;
78 memset(s, 0, sizeof(struct stream));
79 s->size = tmp.size;
80 s->end = s->p = s->data = tmp.data;
81 }
82
83
84 void
s_free(STREAM s)85 s_free(STREAM s)
86 {
87 if (s == NULL)
88 return;
89 free(s->data);
90 free(s);
91 }
92
93 static iconv_t
local_to_utf16()94 local_to_utf16()
95 {
96 iconv_t icv;
97 icv = iconv_open(WINDOWS_CODEPAGE, g_codepage);
98 if (icv == (iconv_t) - 1)
99 {
100 logger(Core, Error, "locale_to_utf16(), iconv_open[%s -> %s] fail %p",
101 g_codepage, WINDOWS_CODEPAGE, icv);
102 abort();
103 }
104 return icv;
105 }
106
107 /* Writes a utf16 encoded string into stream excluding null termination.
108 This function assumes that input is ASCII compatible, such as UTF-8.
109 */
110 static inline size_t
_out_utf16s(STREAM s,size_t maxlength,const char * string)111 _out_utf16s(STREAM s, size_t maxlength, const char *string)
112 {
113 static iconv_t icv_local_to_utf16;
114 size_t bl, ibl, obl;
115 const char *pin;
116 char *pout;
117
118 if (string == NULL)
119 return 0;
120
121 if (!icv_local_to_utf16)
122 {
123 icv_local_to_utf16 = local_to_utf16();
124 }
125
126 ibl = strlen(string);
127 obl = maxlength ? maxlength : (size_t) s_left(s);
128 pin = string;
129 pout = (char *) s->p;
130
131 if (iconv(icv_local_to_utf16, (char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
132 {
133 logger(Protocol, Error, "out_utf16s(), iconv(2) fail, errno %d", errno);
134 abort();
135 }
136
137 bl = (unsigned char *) pout - s->p;
138
139 s->p = (unsigned char *) pout;
140
141 return bl;
142 }
143
144 /* Writes a utf16 encoded string into stream including a null
145 termination. The length is fixed and defined by width. If result is
146 longer than specified width, the string is truncated. pad,
147 specifies a character to pad with.
148 */
149 void
out_utf16s_padded(STREAM s,const char * string,size_t length,unsigned char pad)150 out_utf16s_padded(STREAM s, const char *string, size_t length, unsigned char pad)
151 {
152 size_t i, bl;
153 bl = _out_utf16s(s, length - 2, string);
154
155 // append utf16 null termination
156 out_uint16(s, 0);
157 bl += 2;
158
159 for (i = 0; i < (length - bl); i++)
160 out_uint8(s, pad);
161 }
162
163 /* Writes a utf16 encoded string into stream including a null
164 termination.
165 */
166 void
out_utf16s(STREAM s,const char * string)167 out_utf16s(STREAM s, const char *string)
168 {
169 _out_utf16s(s, 0, string);
170
171 // append utf16 null termination
172 out_uint16(s, 0);
173 }
174
175
176 /* Writes a utf16 encoded string into stream excluding null
177 termination. */
178 void
out_utf16s_no_eos(STREAM s,const char * string)179 out_utf16s_no_eos(STREAM s, const char *string)
180 {
181 _out_utf16s(s, 0, string);
182 }
183
184 /* Read bytes from STREAM s into *string until a null terminator is
185 found, or len bytes are read from the stream. Returns the number of
186 bytes read. */
187 size_t
in_ansi_string(STREAM s,char * string,size_t len)188 in_ansi_string(STREAM s, char *string, size_t len)
189 {
190 char *ps;
191 size_t left;
192 ps = string;
193
194 left = len;
195 while (left--)
196 {
197 if (left == 0)
198 break;
199
200 in_uint8(s, *ps);
201
202 if (*ps == '\0')
203 break;
204
205 ps++;
206 }
207
208 return len - left;
209 }
210