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_v1s.c
22 * @brief libscp version 1 server api code
23 * @author Simone Fedele
24 *
25 */
26
27 #if defined(HAVE_CONFIG_H)
28 #include <config_ac.h>
29 #endif
30
31 #ifndef LIBSCP_V1S_C
32 #define LIBSCP_V1S_C
33
34 #include "libscp_v1s.h"
35 #include "string_calls.h"
36
37 //extern struct log_config* s_log;
38
39 /**
40 * Reads a uint8 followed by a string into a buffer
41 *
42 * Buffer is null-terminated on success
43 *
44 * @param s Input stream
45 * @param [out] Output buffer (must be >= 256 chars)
46 * @param param Parameter we're reading
47 * @param line Line number reference
48 * @return != 0 if string read OK
49 *
50 * @todo
51 * This needs to be merged with the func of the same name in
52 * libscp_v1s_mng.c
53 */
54 static
in_string8(struct stream * s,char str[],const char * param,int line)55 int in_string8(struct stream *s, char str[], const char *param, int line)
56 {
57 int result;
58
59 if (!s_check_rem(s, 1))
60 {
61 LOG(LOG_LEVEL_WARNING,
62 "[v1s:%d] connection aborted: %s len missing",
63 line, param);
64 result = 0;
65 }
66 else
67 {
68 unsigned int sz;
69
70 in_uint8(s, sz);
71 result = s_check_rem(s, sz);
72 if (!result)
73 {
74 LOG(LOG_LEVEL_WARNING,
75 "[v1s:%d] connection aborted: %s data missing",
76 line, param);
77 }
78 else
79 {
80 in_uint8a(s, str, sz);
81 str[sz] = '\0';
82 }
83 }
84 return result;
85 }
86 /* server API */
87
88 /**
89 * Initialises a V1 session object
90 *
91 * This is called after the V1 header, command set and command have been read
92 *
93 * @param c Connection
94 * @param [out] session pre-allocated session object
95 * @return SCP_SERVER_STATE_OK for success
96 */
97 static enum SCP_SERVER_STATES_E
scp_v1s_init_session(struct SCP_CONNECTION * c,struct SCP_SESSION * session)98 scp_v1s_init_session(struct SCP_CONNECTION *c, struct SCP_SESSION *session)
99 {
100 tui8 type;
101 tui16 height;
102 tui16 width;
103 tui8 bpp;
104 tui8 sz;
105 char buf[256];
106
107 scp_session_set_version(session, 1);
108
109 /* Check there's data for the session type, the height, the width, the
110 * bpp, the resource sharing indicator and the locale */
111 if (!s_check_rem(c->in_s, 1 + 2 + 2 + 1 + 1 + 17))
112 {
113 LOG(LOG_LEVEL_WARNING,
114 "[v1s:%d] connection aborted: short packet",
115 __LINE__);
116 return SCP_SERVER_STATE_SIZE_ERR;
117 }
118
119 in_uint8(c->in_s, type);
120
121 if ((type != SCP_SESSION_TYPE_XVNC) && (type != SCP_SESSION_TYPE_XRDP))
122 {
123 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: unknown session type", __LINE__);
124 return SCP_SERVER_STATE_SESSION_TYPE_ERR;
125 }
126
127 scp_session_set_type(session, type);
128
129 in_uint16_be(c->in_s, height);
130 scp_session_set_height(session, height);
131 in_uint16_be(c->in_s, width);
132 scp_session_set_width(session, width);
133 in_uint8(c->in_s, bpp);
134 if (0 != scp_session_set_bpp(session, bpp))
135 {
136 LOG(LOG_LEVEL_WARNING,
137 "[v1s:%d] connection aborted: unsupported bpp: %d",
138 __LINE__, bpp);
139 return SCP_SERVER_STATE_INTERNAL_ERR;
140 }
141 in_uint8(c->in_s, sz);
142 scp_session_set_rsr(session, sz);
143 in_uint8a(c->in_s, buf, 17);
144 buf[17] = '\0';
145 scp_session_set_locale(session, buf);
146
147 /* Check there's enough data left for at least an IPv4 address (+len) */
148 if (!s_check_rem(c->in_s, 1 + 4))
149 {
150 LOG(LOG_LEVEL_WARNING,
151 "[v1s:%d] connection aborted: IP addr len missing",
152 __LINE__);
153 return SCP_SERVER_STATE_SIZE_ERR;
154 }
155
156 in_uint8(c->in_s, sz);
157
158 if (sz == SCP_ADDRESS_TYPE_IPV4)
159 {
160 tui32 ipv4;
161 in_uint32_be(c->in_s, ipv4);
162 scp_session_set_addr(session, sz, &ipv4);
163 }
164 else if (sz == SCP_ADDRESS_TYPE_IPV6)
165 {
166 if (!s_check_rem(c->in_s, 16))
167 {
168 LOG(LOG_LEVEL_WARNING,
169 "[v1s:%d] connection aborted: IP addr missing",
170 __LINE__);
171 return SCP_SERVER_STATE_SIZE_ERR;
172 }
173 in_uint8a(c->in_s, buf, 16);
174 scp_session_set_addr(session, sz, buf);
175 }
176
177 /* reading hostname */
178 if (!in_string8(c->in_s, buf, "hostname", __LINE__))
179 {
180 return SCP_SERVER_STATE_SIZE_ERR;
181 }
182
183 if (0 != scp_session_set_hostname(session, buf))
184 {
185 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__);
186 return SCP_SERVER_STATE_INTERNAL_ERR;
187 }
188
189 /* reading username */
190 if (!in_string8(c->in_s, buf, "username", __LINE__))
191 {
192 return SCP_SERVER_STATE_SIZE_ERR;
193 }
194
195 if (0 != scp_session_set_username(session, buf))
196 {
197 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__);
198 return SCP_SERVER_STATE_INTERNAL_ERR;
199 }
200
201 /* reading password */
202 if (!in_string8(c->in_s, buf, "passwd", __LINE__))
203 {
204 return SCP_SERVER_STATE_SIZE_ERR;
205 }
206
207 if (0 != scp_session_set_password(session, buf))
208 {
209 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__);
210 return SCP_SERVER_STATE_INTERNAL_ERR;
211 }
212
213 return SCP_SERVER_STATE_OK;
214 }
215
216 /* server API */
scp_v1s_accept(struct SCP_CONNECTION * c,struct SCP_SESSION ** s,int skipVchk)217 enum SCP_SERVER_STATES_E scp_v1s_accept(struct SCP_CONNECTION *c, struct SCP_SESSION **s, int skipVchk)
218 {
219 enum SCP_SERVER_STATES_E result;
220 struct SCP_SESSION *session;
221 tui32 version;
222 int size;
223 tui16 cmdset;
224 tui16 cmd;
225
226 (*s) = NULL;
227
228 if (!skipVchk)
229 {
230
231 if (0 == scp_tcp_force_recv(c->in_sck, c->in_s->data, 8))
232 {
233 in_uint32_be(c->in_s, version);
234
235 if (version != 1)
236 {
237 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__);
238 return SCP_SERVER_STATE_VERSION_ERR;
239 }
240 }
241 else
242 {
243 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
244 return SCP_SERVER_STATE_NETWORK_ERR;
245 }
246 }
247
248 in_uint32_be(c->in_s, size);
249
250 /* Check the message is big enough for the header, the command set, and
251 * the command (but not too big) */
252 if (size < (8 + 2 + 2) || size > SCP_MAX_MESSAGE_SIZE)
253 {
254 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__);
255 return SCP_SERVER_STATE_SIZE_ERR;
256 }
257
258 init_stream(c->in_s, size - 8);
259
260 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, (size - 8)))
261 {
262 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
263 return SCP_SERVER_STATE_NETWORK_ERR;
264 }
265
266 c->in_s->end = c->in_s->data + (size - 8);
267
268 /* reading command set */
269 in_uint16_be(c->in_s, cmdset);
270
271 /* if we are starting a management session */
272 if (cmdset == SCP_COMMAND_SET_MANAGE)
273 {
274 LOG(LOG_LEVEL_DEBUG, "[v1s:%d] requested management connection", __LINE__);
275 /* should return SCP_SERVER_STATE_START_MANAGE */
276 return scp_v1s_mng_accept(c, s);
277 }
278
279 /* if we started with resource sharing... */
280 if (cmdset == SCP_COMMAND_SET_RSR)
281 {
282 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
283 return SCP_SERVER_STATE_SEQUENCE_ERR;
284 }
285
286 /* reading command */
287 in_uint16_be(c->in_s, cmd);
288
289 if (cmd != 1)
290 {
291 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
292 return SCP_SERVER_STATE_SEQUENCE_ERR;
293 }
294
295 session = scp_session_create();
296
297 if (NULL == session)
298 {
299 LOG(LOG_LEVEL_WARNING,
300 "[v1s:%d] connection aborted: internal error "
301 "(malloc returned NULL)", __LINE__);
302 result = SCP_SERVER_STATE_INTERNAL_ERR;
303 }
304 else
305 {
306 result = scp_v1s_init_session(c, session);
307 if (result != SCP_SERVER_STATE_OK)
308 {
309 scp_session_destroy(session);
310 session = NULL;
311 }
312 }
313
314 /* returning the struct */
315 (*s) = session;
316
317 return result;
318 }
319
320 enum SCP_SERVER_STATES_E
scp_v1s_deny_connection(struct SCP_CONNECTION * c,const char * reason)321 scp_v1s_deny_connection(struct SCP_CONNECTION *c, const char *reason)
322 {
323 int rlen;
324
325 init_stream(c->out_s, c->out_s->size);
326
327 /* forcing message not to exceed 64k */
328 rlen = g_strlen(reason);
329
330 if (rlen > 65535)
331 {
332 rlen = 65535;
333 }
334
335 out_uint32_be(c->out_s, 1);
336 /* packet size: 4 + 4 + 2 + 2 + 2 + strlen(reason)*/
337 /* version + size + cmdset + cmd + msglen + msg */
338 out_uint32_be(c->out_s, rlen + 14);
339 out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT);
340 out_uint16_be(c->out_s, 2);
341 out_uint16_be(c->out_s, rlen);
342 out_uint8p(c->out_s, reason, rlen);
343
344 if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, rlen + 14))
345 {
346 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
347 return SCP_SERVER_STATE_NETWORK_ERR;
348 }
349
350 return SCP_SERVER_STATE_END;
351 }
352
353 enum SCP_SERVER_STATES_E
scp_v1s_request_password(struct SCP_CONNECTION * c,struct SCP_SESSION * s,const char * reason)354 scp_v1s_request_password(struct SCP_CONNECTION *c, struct SCP_SESSION *s,
355 const char *reason)
356 {
357 tui32 version;
358 int size;
359 tui16 cmdset;
360 tui16 cmd;
361 int rlen;
362 char buf[256];
363
364 init_stream(c->in_s, c->in_s->size);
365 init_stream(c->out_s, c->out_s->size);
366
367 /* forcing message not to exceed 64k */
368 rlen = g_strlen(reason);
369
370 if (rlen > 65535)
371 {
372 rlen = 65535;
373 }
374
375 /* send password request */
376 version = 1;
377 cmd = 3;
378
379 out_uint32_be(c->out_s, version); /* version */
380 out_uint32_be(c->out_s, 14 + rlen); /* size */
381 out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset */
382 out_uint16_be(c->out_s, cmd); /* cmd */
383
384 out_uint16_be(c->out_s, rlen);
385 out_uint8p(c->out_s, reason, rlen);
386
387 if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, 14 + rlen))
388 {
389 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
390 return SCP_SERVER_STATE_NETWORK_ERR;
391 }
392
393 /* receive password & username */
394 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8))
395 {
396 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
397 return SCP_SERVER_STATE_NETWORK_ERR;
398 }
399
400 in_uint32_be(c->in_s, version);
401
402 if (version != 1)
403 {
404 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__);
405 return SCP_SERVER_STATE_VERSION_ERR;
406 }
407
408 in_uint32_be(c->in_s, size);
409
410 /* Check the message is big enough for the header, the command set, and
411 * the command (but not too big) */
412 if (size < (8 + 2 + 2) || size > SCP_MAX_MESSAGE_SIZE)
413 {
414 LOG(LOG_LEVEL_WARNING,
415 "[v1s:%d] connection aborted: size error",
416 __LINE__);
417 return SCP_SERVER_STATE_SIZE_ERR;
418 }
419
420 init_stream(c->in_s, size - 8);
421
422 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, (size - 8)))
423 {
424 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
425 return SCP_SERVER_STATE_NETWORK_ERR;
426 }
427
428 c->in_s->end = c->in_s->data + (size - 8);
429
430 in_uint16_be(c->in_s, cmdset);
431
432 if (cmdset != SCP_COMMAND_SET_DEFAULT)
433 {
434 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
435 return SCP_SERVER_STATE_SEQUENCE_ERR;
436 }
437
438 in_uint16_be(c->in_s, cmd);
439
440 if (cmd != 4)
441 {
442 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
443 return SCP_SERVER_STATE_SEQUENCE_ERR;
444 }
445
446 /* reading username */
447 if (!in_string8(c->in_s, buf, "username", __LINE__))
448 {
449 return SCP_SERVER_STATE_SIZE_ERR;
450 }
451
452 if (0 != scp_session_set_username(s, buf))
453 {
454 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__);
455 return SCP_SERVER_STATE_INTERNAL_ERR;
456 }
457
458 /* reading password */
459 if (!in_string8(c->in_s, buf, "passwd", __LINE__))
460 {
461 return SCP_SERVER_STATE_SIZE_ERR;
462 }
463
464 if (0 != scp_session_set_password(s, buf))
465 {
466 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__);
467 return SCP_SERVER_STATE_INTERNAL_ERR;
468 }
469
470 return SCP_SERVER_STATE_OK;
471 }
472
473 /* 020 */
474 enum SCP_SERVER_STATES_E
scp_v1s_request_pwd_change(struct SCP_CONNECTION * c,char * reason,char * npw)475 scp_v1s_request_pwd_change(struct SCP_CONNECTION *c, char *reason, char *npw)
476 {
477 return SCP_SERVER_STATE_INTERNAL_ERR;
478 }
479
480 /* 023 */
481 enum SCP_SERVER_STATES_E
scp_v1s_pwd_change_error(struct SCP_CONNECTION * c,char * error,int retry,char * npw)482 scp_v1s_pwd_change_error(struct SCP_CONNECTION *c, char *error, int retry, char *npw)
483 {
484 return SCP_SERVER_STATE_INTERNAL_ERR;
485 }
486
487 /* 030 */
488 enum SCP_SERVER_STATES_E
scp_v1s_connect_new_session(struct SCP_CONNECTION * c,SCP_DISPLAY d)489 scp_v1s_connect_new_session(struct SCP_CONNECTION *c, SCP_DISPLAY d)
490 {
491 /* send password request */
492 tui32 version = 1;
493 tui32 size = 14;
494 tui16 cmd = 30;
495
496 init_stream(c->out_s, c->out_s->size);
497
498 out_uint32_be(c->out_s, version); /* version */
499 out_uint32_be(c->out_s, size); /* size */
500 out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset */
501 out_uint16_be(c->out_s, cmd); /* cmd */
502
503 out_uint16_be(c->out_s, d); /* display */
504
505 if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, 14))
506 {
507 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
508 return SCP_SERVER_STATE_NETWORK_ERR;
509 }
510
511 return SCP_SERVER_STATE_OK;
512 }
513
514 /* 032 */
515 enum SCP_SERVER_STATES_E
scp_v1s_connection_error(struct SCP_CONNECTION * c,const char * error)516 scp_v1s_connection_error(struct SCP_CONNECTION *c, const char *error)
517 {
518 tui16 len;
519
520 len = g_strlen(error);
521 init_stream(c->out_s, c->out_s->size);
522
523 out_uint32_be(c->out_s, 1);
524 /* packet size: 4 + 4 + 2 + 2 + len */
525 /* version + size + cmdset + cmd */
526 out_uint32_be(c->out_s, (12 + len));
527 out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT);
528 out_uint16_be(c->out_s, SCP_CMD_CONN_ERROR);
529
530 if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, (12 + len)))
531 {
532 return SCP_SERVER_STATE_NETWORK_ERR;
533 }
534
535 return SCP_SERVER_STATE_END;
536 }
537
538 /* 040 */
539 enum SCP_SERVER_STATES_E
scp_v1s_list_sessions(struct SCP_CONNECTION * c,int sescnt,struct SCP_DISCONNECTED_SESSION * ds,SCP_SID * sid)540 scp_v1s_list_sessions(struct SCP_CONNECTION *c, int sescnt, struct SCP_DISCONNECTED_SESSION *ds, SCP_SID *sid)
541 {
542 tui32 version = 1;
543 int size = 12;
544 tui16 cmd = 40;
545 int pktcnt;
546 int idx;
547 int sidx;
548 int pidx;
549 struct SCP_DISCONNECTED_SESSION *cds;
550
551 /* first we send a notice that we have some disconnected sessions */
552 init_stream(c->out_s, c->out_s->size);
553
554 out_uint32_be(c->out_s, version); /* version */
555 out_uint32_be(c->out_s, size); /* size */
556 out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset */
557 out_uint16_be(c->out_s, cmd); /* cmd */
558
559 if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size))
560 {
561 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
562 return SCP_SERVER_STATE_NETWORK_ERR;
563 }
564
565 /* then we wait for client ack */
566
567 /*
568 * Maybe this message could say if the session should be resized on
569 * server side or client side.
570 */
571 init_stream(c->in_s, c->in_s->size);
572
573 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8))
574 {
575 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
576 return SCP_SERVER_STATE_NETWORK_ERR;
577 }
578
579 in_uint32_be(c->in_s, version);
580
581 if (version != 1)
582 {
583 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__);
584 return SCP_SERVER_STATE_VERSION_ERR;
585 }
586
587 in_uint32_be(c->in_s, size);
588
589 /* Check the message is big enough for the header, the command set, and
590 * the command (but not too big) */
591 if (size < (8 + 2 + 2) || size > SCP_MAX_MESSAGE_SIZE)
592 {
593 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__);
594 return SCP_SERVER_STATE_SIZE_ERR;
595 }
596
597 init_stream(c->in_s, size - 8);
598
599 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, (size - 8)))
600 {
601 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
602 return SCP_SERVER_STATE_NETWORK_ERR;
603 }
604
605 c->in_s->end = c->in_s->data + (size - 8);
606
607 in_uint16_be(c->in_s, cmd);
608
609 if (cmd != SCP_COMMAND_SET_DEFAULT)
610 {
611 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
612 return SCP_SERVER_STATE_SEQUENCE_ERR;
613 }
614
615 in_uint16_be(c->in_s, cmd);
616
617 if (cmd != 41)
618 {
619 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
620 return SCP_SERVER_STATE_SEQUENCE_ERR;
621 }
622
623 /* calculating the number of packets to send */
624 pktcnt = sescnt / SCP_SERVER_MAX_LIST_SIZE;
625
626 if ((sescnt % SCP_SERVER_MAX_LIST_SIZE) != 0)
627 {
628 pktcnt++;
629 }
630
631 for (idx = 0; idx < pktcnt; idx++)
632 {
633 /* ok, we send session session list */
634 init_stream(c->out_s, c->out_s->size);
635
636 /* size: ver+size+cmdset+cmd+sescnt+continue+count */
637 size = 4 + 4 + 2 + 2 + 4 + 1 + 1;
638
639 /* header */
640 cmd = 42;
641 s_push_layer(c->out_s, channel_hdr, 8);
642 out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT);
643 out_uint16_be(c->out_s, cmd);
644
645 /* session count */
646 out_uint32_be(c->out_s, sescnt);
647
648 /* setting the continue flag */
649 if ((idx + 1)*SCP_SERVER_MAX_LIST_SIZE >= sescnt)
650 {
651 out_uint8(c->out_s, 0);
652 /* setting session count for this packet */
653 pidx = sescnt - (idx * SCP_SERVER_MAX_LIST_SIZE);
654 out_uint8(c->out_s, pidx);
655 }
656 else
657 {
658 out_uint8(c->out_s, 1);
659 /* setting session count for this packet */
660 pidx = SCP_SERVER_MAX_LIST_SIZE;
661 out_uint8(c->out_s, pidx);
662 }
663
664 /* adding session descriptors */
665 for (sidx = 0; sidx < pidx; sidx++)
666 {
667 /* shortcut to the current session to send */
668 cds = ds + ((idx) * SCP_SERVER_MAX_LIST_SIZE) + sidx;
669
670 /* session data */
671 out_uint32_be(c->out_s, cds->SID); /* session id */
672 out_uint8(c->out_s, cds->type);
673 out_uint16_be(c->out_s, cds->height);
674 out_uint16_be(c->out_s, cds->width);
675 out_uint8(c->out_s, cds->bpp);
676 out_uint8(c->out_s, cds->idle_days);
677 out_uint8(c->out_s, cds->idle_hours);
678 out_uint8(c->out_s, cds->idle_minutes);
679 size += 13;
680
681 out_uint16_be(c->out_s, cds->conn_year);
682 out_uint8(c->out_s, cds->conn_month);
683 out_uint8(c->out_s, cds->conn_day);
684 out_uint8(c->out_s, cds->conn_hour);
685 out_uint8(c->out_s, cds->conn_minute);
686 out_uint8(c->out_s, cds->addr_type);
687 size += 7;
688
689 if (cds->addr_type == SCP_ADDRESS_TYPE_IPV4)
690 {
691 in_uint32_be(c->out_s, cds->ipv4addr);
692 size += 4;
693 }
694 else if (cds->addr_type == SCP_ADDRESS_TYPE_IPV6)
695 {
696 in_uint8a(c->out_s, cds->ipv6addr, 16);
697 size += 16;
698 }
699 }
700
701 s_pop_layer(c->out_s, channel_hdr);
702 out_uint32_be(c->out_s, version);
703 out_uint32_be(c->out_s, size);
704
705 if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size))
706 {
707 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
708 return SCP_SERVER_STATE_NETWORK_ERR;
709 }
710 }
711
712 /* we get the response */
713 init_stream(c->in_s, c->in_s->size);
714
715 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, (8)))
716 {
717 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
718 return SCP_SERVER_STATE_NETWORK_ERR;
719 }
720
721 in_uint32_be(c->in_s, version);
722
723 if (version != 1)
724 {
725 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__);
726 return SCP_SERVER_STATE_VERSION_ERR;
727 }
728
729 in_uint32_be(c->in_s, size);
730
731 /* Check the message is big enough for the header, the command set, and
732 * the command (but not too big) */
733 if (size < (8 + 2 + 2) || size > SCP_MAX_MESSAGE_SIZE)
734 {
735 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__);
736 return SCP_SERVER_STATE_SIZE_ERR;
737 }
738
739 /* rest of the packet */
740 init_stream(c->in_s, size - 8);
741
742 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, (size - 8)))
743 {
744 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
745 return SCP_SERVER_STATE_NETWORK_ERR;
746 }
747
748 c->in_s->end = c->in_s->data + (size - 8);
749
750 in_uint16_be(c->in_s, cmd);
751
752 if (cmd != SCP_COMMAND_SET_DEFAULT)
753 {
754 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
755 return SCP_SERVER_STATE_SEQUENCE_ERR;
756 }
757
758 in_uint16_be(c->in_s, cmd);
759
760 if (cmd == 43)
761 {
762 if (!s_check_rem(c->in_s, 4))
763 {
764 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: missing session", __LINE__);
765 return SCP_SERVER_STATE_SIZE_ERR;
766 }
767 /* select session */
768 in_uint32_be(c->in_s, (*sid));
769
770 /* checking sid value */
771 for (idx = 0; idx < sescnt; idx++)
772 {
773 /* the sid is valid */
774 if (ds[idx].SID == (*sid))
775 {
776 /* ok, session selected */
777 return SCP_SERVER_STATE_OK;
778 }
779 }
780
781 /* if we got here, the requested sid wasn't one from the list we sent */
782 /* we should kill the connection */
783 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error (no such session in list)", __LINE__);
784 return SCP_SERVER_STATE_INTERNAL_ERR;
785 }
786 else if (cmd == 44)
787 {
788 /* cancel connection */
789 return SCP_SERVER_STATE_SELECTION_CANCEL;
790 }
791 // else if (cmd == 45)
792 // {
793 // /* force new connection */
794 // return SCP_SERVER_STATE_FORCE_NEW;
795 // }
796 else
797 {
798 /* wrong response */
799 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
800 return SCP_SERVER_STATE_SEQUENCE_ERR;
801 }
802
803 return SCP_SERVER_STATE_OK;
804 }
805
806 /* 046 was: 031 struct SCP_DISCONNECTED_SESSION* ds, */
807 enum SCP_SERVER_STATES_E
scp_v1s_reconnect_session(struct SCP_CONNECTION * c,SCP_DISPLAY d)808 scp_v1s_reconnect_session(struct SCP_CONNECTION *c, SCP_DISPLAY d)
809 {
810 tui32 version = 1;
811 tui32 size = 14;
812 tui16 cmd = 46;
813
814 /* ok, we send session data and display */
815 init_stream(c->out_s, c->out_s->size);
816
817 /* header */
818 out_uint32_be(c->out_s, version);
819 out_uint32_be(c->out_s, size);
820 out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT);
821 out_uint16_be(c->out_s, cmd);
822
823 /* session data */
824 out_uint16_be(c->out_s, d); /* session display */
825 /*out_uint8(c->out_s, ds->type);
826 out_uint16_be(c->out_s, ds->height);
827 out_uint16_be(c->out_s, ds->width);
828 out_uint8(c->out_s, ds->bpp);
829 out_uint8(c->out_s, ds->idle_days);
830 out_uint8(c->out_s, ds->idle_hours);
831 out_uint8(c->out_s, ds->idle_minutes);*/
832 /* these last three are not really needed... */
833
834 if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size))
835 {
836 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
837 return SCP_SERVER_STATE_NETWORK_ERR;
838 }
839
840 return SCP_SERVER_STATE_OK;
841 }
842
843 #endif
844