1 /**
2 * xrdp: A Remote Desktop Protocol server.
3 *
4 * Copyright (C) Jay Sorg 2004-2012
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 /**
20 *
21 * @file libscp_v1c_mng.c
22 * @brief libscp version 1 client api code - session management
23 * @author Simone Fedele
24 *
25 */
26
27 #if defined(HAVE_CONFIG_H)
28 #include <config_ac.h>
29 #endif
30
31 #include "libscp_v1c_mng.h"
32 #include "string_calls.h"
33
34 #include <stdlib.h>
35 #include <stdio.h>
36
37 //extern struct log_config* s_log;
38
39 static enum SCP_CLIENT_STATES_E
40 _scp_v1c_mng_check_response(struct trans *t, struct SCP_SESSION *s);
41
42 /* client API */
43 /* 001 */
44 enum SCP_CLIENT_STATES_E
scp_v1c_mng_connect(struct trans * t,struct SCP_SESSION * s)45 scp_v1c_mng_connect(struct trans *t, struct SCP_SESSION *s)
46 {
47 struct stream *out_s = t->out_s;
48
49 tui8 sz;
50 int size;
51
52 size = (12 + 4 + g_strlen(s->hostname) + g_strlen(s->username) +
53 g_strlen(s->password));
54
55 if (s->addr_type == SCP_ADDRESS_TYPE_IPV4)
56 {
57 size = size + 4;
58 }
59 else
60 {
61 size = size + 16;
62 }
63
64 init_stream(out_s, size);
65
66 /* sending request */
67
68 /* header */
69 out_uint32_be(out_s, 1); /* version */
70 out_uint32_be(out_s, size);
71 out_uint16_be(out_s, SCP_COMMAND_SET_MANAGE);
72 out_uint16_be(out_s, SCP_CMD_MNG_LOGIN);
73
74 /* data */
75 sz = g_strlen(s->username);
76 out_uint8(out_s, sz);
77 out_uint8p(out_s, s->username, sz);
78 sz = g_strlen(s->password);
79 out_uint8(out_s, sz);
80 out_uint8p(out_s, s->password, sz);
81
82 /* address */
83 out_uint8(out_s, s->addr_type);
84
85 if (s->addr_type == SCP_ADDRESS_TYPE_IPV4)
86 {
87 out_uint32_be(out_s, s->ipv4addr);
88 }
89 else
90 {
91 out_uint8p(out_s, s->ipv6addr, 16);
92 }
93
94 /* hostname */
95 sz = g_strlen(s->hostname);
96 out_uint8(out_s, sz);
97 out_uint8p(out_s, s->hostname, sz);
98 s_mark_end(out_s);
99
100 if (0 != trans_force_write(t))
101 {
102 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__);
103 return SCP_CLIENT_STATE_NETWORK_ERR;
104 }
105
106 /* wait for response */
107 return _scp_v1c_mng_check_response(t, s);
108 }
109
110 /* 004 */
111 enum SCP_CLIENT_STATES_E
scp_v1c_mng_get_session_list(struct trans * t,int * scount,struct SCP_DISCONNECTED_SESSION ** s)112 scp_v1c_mng_get_session_list(struct trans *t, int *scount,
113 struct SCP_DISCONNECTED_SESSION **s)
114 {
115 struct stream *in_s = t->in_s;
116 struct stream *out_s = t->out_s;
117 tui32 version = 1;
118 int size = 12;
119 tui16 cmd = SCP_CMD_MNG_LIST_REQ; /* request session list */
120 tui32 sescnt = 0; /* total session number */
121 tui32 sestmp = 0; /* additional total session number */
122 tui8 pktcnt = 0; /* packet session count */
123 tui32 totalcnt = 0; /* session counter */
124 tui8 continued = 0; /* continue flag */
125 int firstpkt = 1; /* "first packet" flag */
126 int idx;
127 struct SCP_DISCONNECTED_SESSION *ds = 0;
128 // tui8 addr[16];
129
130 init_stream(out_s, 64);
131
132 /* we request session list */
133 out_uint32_be(out_s, version); /* version */
134 out_uint32_be(out_s, size); /* size */
135 out_uint16_be(out_s, SCP_COMMAND_SET_MANAGE); /* cmdset */
136 out_uint16_be(out_s, cmd); /* cmd */
137 s_mark_end(out_s);
138
139 if (0 != trans_force_write(t))
140 {
141 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__);
142 return SCP_CLIENT_STATE_NETWORK_ERR;
143 }
144
145 do
146 {
147 /* then we wait for server response */
148 init_stream(in_s, 8);
149
150 if (0 != trans_force_read(t, 8))
151 {
152 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__);
153 g_free(ds);
154 return SCP_CLIENT_STATE_NETWORK_ERR;
155 }
156
157 in_uint32_be(in_s, version);
158
159 if (version != 1)
160 {
161 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__);
162 g_free(ds);
163 return SCP_CLIENT_STATE_VERSION_ERR;
164 }
165
166 in_uint32_be(in_s, size);
167
168 if (size < 12)
169 {
170 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: size error", __LINE__);
171 g_free(ds);
172 return SCP_CLIENT_STATE_SIZE_ERR;
173 }
174
175 init_stream(in_s, size);
176
177 if (0 != trans_force_read(t, size - 8))
178 {
179 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__);
180 g_free(ds);
181 return SCP_CLIENT_STATE_NETWORK_ERR;
182 }
183
184 in_uint16_be(in_s, cmd);
185
186 if (cmd != SCP_COMMAND_SET_MANAGE)
187 {
188 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__);
189 g_free(ds);
190 return SCP_CLIENT_STATE_SEQUENCE_ERR;
191 }
192
193 in_uint16_be(in_s, cmd);
194
195 if (cmd != SCP_CMD_MNG_LIST) /* session list */
196 {
197 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__);
198 g_free(ds);
199 return SCP_CLIENT_STATE_SEQUENCE_ERR;
200 }
201
202 if (firstpkt)
203 {
204 firstpkt = 0;
205 in_uint32_be(in_s, sescnt);
206 sestmp = sescnt;
207
208 if (0 == sescnt)
209 {
210 /* return data... */
211 (*scount) = sescnt;
212 (*s) = NULL;
213
214 LOG_DEVEL(LOG_LEVEL_DEBUG, "[v1c_mng] end list - no session on TS");
215 return SCP_CLIENT_STATE_LIST_OK;
216 }
217
218 ds = g_new(struct SCP_DISCONNECTED_SESSION, sescnt);
219
220 if (ds == 0)
221 {
222 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: internal error", __LINE__);
223 return SCP_CLIENT_STATE_INTERNAL_ERR;
224 }
225 }
226 else
227 {
228 in_uint32_be(in_s, sestmp);
229 }
230
231 in_uint8(in_s, continued);
232 in_uint8(in_s, pktcnt);
233
234 for (idx = 0; idx < pktcnt; idx++)
235 {
236 in_uint32_be(in_s, (ds[totalcnt]).SID); /* session id */
237 in_uint8(in_s, (ds[totalcnt]).type);
238 in_uint16_be(in_s, (ds[totalcnt]).height);
239 in_uint16_be(in_s, (ds[totalcnt]).width);
240 in_uint8(in_s, (ds[totalcnt]).bpp);
241 in_uint8(in_s, (ds[totalcnt]).idle_days);
242 in_uint8(in_s, (ds[totalcnt]).idle_hours);
243 in_uint8(in_s, (ds[totalcnt]).idle_minutes);
244
245 in_uint16_be(in_s, (ds[totalcnt]).conn_year);
246 in_uint8(in_s, (ds[totalcnt]).conn_month);
247 in_uint8(in_s, (ds[totalcnt]).conn_day);
248 in_uint8(in_s, (ds[totalcnt]).conn_hour);
249 in_uint8(in_s, (ds[totalcnt]).conn_minute);
250 in_uint8(in_s, (ds[totalcnt]).addr_type);
251
252 if ((ds[totalcnt]).addr_type == SCP_ADDRESS_TYPE_IPV4)
253 {
254 in_uint32_be(in_s, (ds[totalcnt]).ipv4addr);
255 }
256
257 if ((ds[totalcnt]).addr_type == SCP_ADDRESS_TYPE_IPV6)
258 {
259 in_uint8a(in_s, (ds[totalcnt]).ipv6addr, 16);
260 }
261
262 totalcnt++;
263 }
264 }
265 while (continued);
266
267 /* return data... */
268 (*scount) = sescnt;
269 (*s) = ds;
270
271 LOG_DEVEL(LOG_LEVEL_DEBUG, "[v1c_mng] end list");
272 return SCP_CLIENT_STATE_LIST_OK;
273 }
274
275 /* 043 * /
276 enum SCP_CLIENT_STATES_E
277 scp_v1c_select_session(struct SCP_CONNECTION* c, struct SCP_SESSION* s,
278 SCP_SID sid)
279 {
280 tui32 version = 1;
281 tui32 size = 16;
282 tui16 cmd = 43;
283
284 init_stream(c->out_s, c->out_s->size);
285
286 / * sending our selection * /
287 out_uint32_be(c->out_s, version); / * version * /
288 out_uint32_be(c->out_s, size); / * size * /
289 out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); / * cmdset * /
290 out_uint16_be(c->out_s, cmd); / * cmd * /
291
292 out_uint32_be(c->out_s, sid);
293
294 if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size))
295 {
296 return SCP_CLIENT_STATE_NETWORK_ERR;
297 }
298
299 / * waiting for response.... * /
300 init_stream(c->in_s, c->in_s->size);
301 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8))
302 {
303 return SCP_CLIENT_STATE_NETWORK_ERR;
304 }
305
306 in_uint32_be(c->in_s, version);
307 if (version != 1)
308 {
309 return SCP_CLIENT_STATE_VERSION_ERR;
310 }
311
312 in_uint32_be(c->in_s, size);
313 if (size < 12)
314 {
315 return SCP_CLIENT_STATE_SIZE_ERR;
316 }
317
318 init_stream(c->in_s, c->in_s->size);
319 / * read the rest of the packet * /
320 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, size - 8))
321 {
322 return SCP_CLIENT_STATE_NETWORK_ERR;
323 }
324
325 in_uint16_be(c->in_s, cmd);
326 if (cmd != SCP_COMMAND_SET_DEFAULT)
327 {
328 return SCP_CLIENT_STATE_SEQUENCE_ERR;
329 }
330
331 in_uint16_be(c->in_s, cmd);
332 if (cmd != 46)
333 {
334 return SCP_CLIENT_STATE_SEQUENCE_ERR;
335 }
336
337 / * session display * /
338 in_uint16_be(c->in_s, (s->display));
339 / *we don't need to return any data other than the display * /
340 / *because we already sent that * /
341
342 return SCP_CLIENT_STATE_OK;
343 }*/
344
345 /* 044 * /
346 enum SCP_CLIENT_STATES_E
347 scp_v1c_select_session_cancel(struct SCP_CONNECTION* c)
348 {
349 tui32 version = 1;
350 tui32 size = 12;
351 tui16 cmd = 44;
352
353 init_stream(c->out_s, c->out_s->size);
354
355 / * sending our selection * /
356 out_uint32_be(c->out_s, version); / * version * /
357 out_uint32_be(c->out_s, size); / * size * /
358 out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); / * cmdset * /
359 out_uint16_be(c->out_s, cmd); / * cmd * /
360
361 if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size))
362 {
363 return SCP_CLIENT_STATE_NETWORK_ERR;
364 }
365
366 return SCP_CLIENT_STATE_END;
367 }*/
368
369 static enum SCP_CLIENT_STATES_E
_scp_v1c_mng_check_response(struct trans * t,struct SCP_SESSION * s)370 _scp_v1c_mng_check_response(struct trans *t, struct SCP_SESSION *s)
371 {
372 struct stream *in_s = t->in_s;
373 tui32 version;
374 int size;
375 tui16 cmd;
376 tui8 dim;
377 char buf[257];
378
379 init_stream(in_s, 8);
380
381 if (0 != trans_force_read(t, 8))
382 {
383 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__);
384 return SCP_CLIENT_STATE_NETWORK_ERR;
385 }
386
387 in_uint32_be(in_s, version);
388
389 if (version != 1)
390 {
391 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: version error", __LINE__);
392 return SCP_CLIENT_STATE_VERSION_ERR;
393 }
394
395 in_uint32_be(in_s, size);
396
397 init_stream(in_s, size - 8);
398
399 /* read the rest of the packet */
400 if (0 != trans_force_read(t, size - 8))
401 {
402 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: network error", __LINE__);
403 return SCP_CLIENT_STATE_NETWORK_ERR;
404 }
405
406 in_uint16_be(in_s, cmd);
407
408 if (cmd != SCP_COMMAND_SET_MANAGE)
409 {
410 LOG(LOG_LEVEL_WARNING, "[v1c_mng:%d] connection aborted: sequence error", __LINE__);
411 return SCP_CLIENT_STATE_SEQUENCE_ERR;
412 }
413
414 in_uint16_be(in_s, cmd);
415
416 if (cmd == SCP_CMD_MNG_LOGIN_ALLOW) /* connection ok */
417 {
418 LOG(LOG_LEVEL_INFO, "[v1c_mng:%d] connection ok", __LINE__);
419 return SCP_CLIENT_STATE_OK;
420 }
421 else if (cmd == SCP_CMD_MNG_LOGIN_DENY) /* connection denied */
422 {
423 in_uint8(in_s, dim);
424 buf[dim] = '\0';
425 in_uint8a(in_s, buf, dim);
426 scp_session_set_errstr(s, buf);
427
428 LOG(LOG_LEVEL_INFO, "[v1c_mng:%d] connection denied: %s", __LINE__, s->errstr);
429 return SCP_CLIENT_STATE_CONNECTION_DENIED;
430 }
431
432 LOG(LOG_LEVEL_WARNING, "[v1c-mng:%d] connection aborted: sequence error", __LINE__);
433 return SCP_CLIENT_STATE_SEQUENCE_ERR;
434 }
435