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