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
87 /**
88 * Initialises a V1 session object
89 *
90 * This is called after the V1 header, command set and command have been read
91 *
92 * @param c Connection
93 * @param [out] session pre-allocated session object
94 * @return SCP_SERVER_STATE_OK for success
95 */
96 static enum SCP_SERVER_STATES_E
scp_v1s_init_session(struct trans * t,struct SCP_SESSION * session)97 scp_v1s_init_session(struct trans *t, struct SCP_SESSION *session)
98 {
99 tui8 type;
100 tui16 height;
101 tui16 width;
102 tui8 bpp;
103 tui8 sz;
104 char buf[256];
105 struct stream *in_s = t->in_s;
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(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(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(in_s, height);
130 scp_session_set_height(session, height);
131 in_uint16_be(in_s, width);
132 scp_session_set_width(session, width);
133 in_uint8(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(in_s, sz);
142 scp_session_set_rsr(session, sz);
143 in_uint8a(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(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(in_s, sz);
157
158 if (sz == SCP_ADDRESS_TYPE_IPV4)
159 {
160 tui32 ipv4;
161 in_uint32_be(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(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(in_s, buf, 16);
174 scp_session_set_addr(session, sz, buf);
175 }
176
177 /* reading hostname */
178 if (!in_string8(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(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(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 */
217 enum SCP_SERVER_STATES_E
scp_v1s_accept(struct trans * t,struct SCP_SESSION * s)218 scp_v1s_accept(struct trans *t, struct SCP_SESSION *s)
219 {
220 tui32 size;
221 tui16 cmdset;
222 tui16 cmd;
223 struct stream *in_s = t->in_s;
224 enum SCP_SERVER_STATES_E result;
225
226 in_uint32_be(in_s, size);
227
228 /* Check the message is big enough for the header, the command set, and
229 * the command (but not too big) */
230 if (size < (8 + 2 + 2) || size > SCP_MAX_MESSAGE_SIZE)
231 {
232 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__);
233 return SCP_SERVER_STATE_SIZE_ERR;
234 }
235
236 /* reading command set */
237 in_uint16_be(in_s, cmdset);
238
239 /* if we are starting a management session */
240 if (cmdset == SCP_COMMAND_SET_MANAGE)
241 {
242 LOG(LOG_LEVEL_DEBUG, "[v1s:%d] requested management connection", __LINE__);
243 /* should return SCP_SERVER_STATE_START_MANAGE */
244 return scp_v1s_mng_accept(t, s);
245 }
246
247 /* if we started with resource sharing... */
248 if (cmdset == SCP_COMMAND_SET_RSR)
249 {
250 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
251 return SCP_SERVER_STATE_SEQUENCE_ERR;
252 }
253
254 /* reading command */
255 in_uint16_be(in_s, cmd);
256
257 switch (cmd)
258 {
259 case SCP_CMD_LOGIN:
260 s->current_cmd = cmd;
261 result = scp_v1s_init_session(t, s);
262 break;
263
264 case SCP_CMD_RESEND_CREDS:
265 result = scp_v1s_accept_password_reply(t, s);
266 s->current_cmd = SCP_CMD_LOGIN; /* Caller re-parses credentials */
267 break;
268
269 default:
270 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence "
271 "error. Unrecognised cmd %d", __LINE__, cmd);
272 result = SCP_SERVER_STATE_SEQUENCE_ERR;
273 }
274
275 return result;
276 }
277
278 enum SCP_SERVER_STATES_E
scp_v1s_deny_connection(struct trans * t,const char * reason)279 scp_v1s_deny_connection(struct trans *t, const char *reason)
280 {
281 struct stream *out_s;
282 int rlen;
283
284 /* forcing message not to exceed 64k */
285 rlen = g_strlen(reason);
286 if (rlen > 65535)
287 {
288 rlen = 65535;
289 }
290 out_s = trans_get_out_s(t, rlen + 14);
291 out_uint32_be(out_s, 1); /* version */
292 /* packet size: 4 + 4 + 2 + 2 + 2 + strlen(reason) */
293 /* version + size + cmdset + cmd + msglen + msg */
294 out_uint32_be(out_s, rlen + 14);
295 out_uint16_be(out_s, SCP_COMMAND_SET_DEFAULT);
296 out_uint16_be(out_s, SCP_REPLY_LOGIN_DENIED);
297 out_uint16_be(out_s, rlen);
298 out_uint8p(out_s, reason, rlen);
299 s_mark_end(out_s);
300 if (0 != trans_force_write(t))
301 {
302 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
303 return SCP_SERVER_STATE_NETWORK_ERR;
304 }
305 return SCP_SERVER_STATE_END;
306 }
307
308 enum SCP_SERVER_STATES_E
scp_v1s_request_password(struct trans * t,struct SCP_SESSION * s,const char * reason)309 scp_v1s_request_password(struct trans *t, struct SCP_SESSION *s,
310 const char *reason)
311 {
312 struct stream *out_s;
313 int rlen;
314
315 /* forcing message not to exceed 64k */
316 rlen = g_strlen(reason);
317 if (rlen > 65535)
318 {
319 rlen = 65535;
320 }
321 out_s = trans_get_out_s(t, rlen + 14);
322 out_uint32_be(out_s, 1); /* version */
323 /* packet size: 4 + 4 + 2 + 2 + 2 + strlen(reason) */
324 /* version + size + cmdset + cmd + msglen + msg */
325 out_uint32_be(out_s, rlen + 14);
326 out_uint16_be(out_s, SCP_COMMAND_SET_DEFAULT);
327 out_uint16_be(out_s, SCP_REPLY_REREQUEST_CREDS);
328 out_uint16_be(out_s, rlen);
329 out_uint8p(out_s, reason, rlen);
330 s_mark_end(out_s);
331 if (0 != trans_force_write(t))
332 {
333 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
334 return SCP_SERVER_STATE_NETWORK_ERR;
335 }
336
337 return SCP_SERVER_STATE_OK;
338 }
339
340 enum SCP_SERVER_STATES_E
scp_v1s_accept_password_reply(struct trans * t,struct SCP_SESSION * s)341 scp_v1s_accept_password_reply(struct trans *t, struct SCP_SESSION *s)
342 {
343 struct stream *in_s;
344 char buf[257];
345
346 in_s = t->in_s;
347 buf[256] = '\0';
348
349 /* reading username */
350 if (!in_string8(in_s, buf, "username", __LINE__))
351 {
352 return SCP_SERVER_STATE_SIZE_ERR;
353 }
354 if (0 != scp_session_set_username(s, buf))
355 {
356 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error",
357 __LINE__);
358 return SCP_SERVER_STATE_INTERNAL_ERR;
359 }
360
361 /* reading password */
362 if (!in_string8(in_s, buf, "passwd", __LINE__))
363 {
364 return SCP_SERVER_STATE_SIZE_ERR;
365 }
366
367 if (0 != scp_session_set_password(s, buf))
368 {
369 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error",
370 __LINE__);
371 return SCP_SERVER_STATE_INTERNAL_ERR;
372 }
373
374 return SCP_SERVER_STATE_OK;
375 }
376
377 enum SCP_SERVER_STATES_E
scp_v1s_request_pwd_change(struct trans * t,char * reason,char * npw)378 scp_v1s_request_pwd_change(struct trans *t, char *reason, char *npw)
379 {
380 return SCP_SERVER_STATE_INTERNAL_ERR;
381 }
382
383 enum SCP_SERVER_STATES_E
scp_v1s_pwd_change_error(struct trans * t,char * error,int retry,char * npw)384 scp_v1s_pwd_change_error(struct trans *t, char *error, int retry, char *npw)
385 {
386 return SCP_SERVER_STATE_INTERNAL_ERR;
387 }
388
389 enum SCP_SERVER_STATES_E
scp_v1s_connect_new_session(struct trans * t,SCP_DISPLAY d)390 scp_v1s_connect_new_session(struct trans *t, SCP_DISPLAY d)
391 {
392 struct stream *out_s;
393
394 out_s = trans_get_out_s(t, 14);
395 out_uint32_be(out_s, 1); /* version */
396 /* packet size: 4 + 4 + 2 + 2 + 2 */
397 /* version + size + cmdset + cmd + msglen + msg */
398 out_uint32_be(out_s, 14);
399 out_uint16_be(out_s, SCP_COMMAND_SET_DEFAULT);
400 out_uint16_be(out_s, SCP_REPLY_NEW_SESSION);
401 out_uint16_be(out_s, d);
402 s_mark_end(out_s);
403 if (0 != trans_force_write(t))
404 {
405 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
406 return SCP_SERVER_STATE_NETWORK_ERR;
407 }
408 return SCP_SERVER_STATE_OK;
409 }
410
411 enum SCP_SERVER_STATES_E
scp_v1s_connection_error(struct trans * t,const char * error)412 scp_v1s_connection_error(struct trans *t, const char *error)
413 {
414 struct stream *out_s;
415 tui16 len;
416
417 len = g_strlen(error);
418 if (len > 8192 - 12)
419 {
420 len = 8192 - 12;
421 }
422 out_s = trans_get_out_s(t, 12 + len);
423 out_uint32_be(out_s, 1); /* version */
424 /* packet size: 4 + 4 + 2 + 2 + len */
425 /* version + size + cmdset + cmd */
426 out_uint32_be(out_s, 12 + len);
427 out_uint16_be(out_s, SCP_COMMAND_SET_DEFAULT);
428 out_uint16_be(out_s, SCP_REPLY_CMD_CONN_ERROR);
429 out_uint8a(out_s, error, len);
430 s_mark_end(out_s);
431 if (0 != trans_force_write(t))
432 {
433 return SCP_SERVER_STATE_NETWORK_ERR;
434 }
435 return SCP_SERVER_STATE_END;
436 }
437
438 #if 0
439 enum SCP_SERVER_STATES_E
440 scp_v1s_list_sessions(struct SCP_CONNECTION *c, int sescnt, struct SCP_DISCONNECTED_SESSION *ds, SCP_SID *sid)
441 {
442 tui32 version = 1;
443 int size = 12;
444 tui16 cmd = 40;
445 int pktcnt;
446 int idx;
447 int sidx;
448 int pidx;
449 struct SCP_DISCONNECTED_SESSION *cds;
450
451 /* first we send a notice that we have some disconnected sessions */
452 init_stream(c->out_s, c->out_s->size);
453
454 out_uint32_be(c->out_s, version); /* version */
455 out_uint32_be(c->out_s, size); /* size */
456 out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset */
457 out_uint16_be(c->out_s, cmd); /* cmd */
458
459 if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size))
460 {
461 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
462 return SCP_SERVER_STATE_NETWORK_ERR;
463 }
464
465 /* then we wait for client ack */
466
467 /*
468 * Maybe this message could say if the session should be resized on
469 * server side or client side.
470 */
471 init_stream(c->in_s, c->in_s->size);
472
473 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, 8))
474 {
475 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
476 return SCP_SERVER_STATE_NETWORK_ERR;
477 }
478
479 in_uint32_be(c->in_s, version);
480
481 if (version != 1)
482 {
483 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__);
484 return SCP_SERVER_STATE_VERSION_ERR;
485 }
486
487 in_uint32_be(c->in_s, size);
488
489 /* Check the message is big enough for the header, the command set, and
490 * the command (but not too big) */
491 if (size < (8 + 2 + 2) || size > SCP_MAX_MESSAGE_SIZE)
492 {
493 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__);
494 return SCP_SERVER_STATE_SIZE_ERR;
495 }
496
497 init_stream(c->in_s, size - 8);
498
499 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, (size - 8)))
500 {
501 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
502 return SCP_SERVER_STATE_NETWORK_ERR;
503 }
504
505 c->in_s->end = c->in_s->data + (size - 8);
506
507 in_uint16_be(c->in_s, cmd);
508
509 if (cmd != SCP_COMMAND_SET_DEFAULT)
510 {
511 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
512 return SCP_SERVER_STATE_SEQUENCE_ERR;
513 }
514
515 in_uint16_be(c->in_s, cmd);
516
517 if (cmd != 41)
518 {
519 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
520 return SCP_SERVER_STATE_SEQUENCE_ERR;
521 }
522
523 /* calculating the number of packets to send */
524 pktcnt = sescnt / SCP_SERVER_MAX_LIST_SIZE;
525
526 if ((sescnt % SCP_SERVER_MAX_LIST_SIZE) != 0)
527 {
528 pktcnt++;
529 }
530
531 for (idx = 0; idx < pktcnt; idx++)
532 {
533 /* ok, we send session session list */
534 init_stream(c->out_s, c->out_s->size);
535
536 /* size: ver+size+cmdset+cmd+sescnt+continue+count */
537 size = 4 + 4 + 2 + 2 + 4 + 1 + 1;
538
539 /* header */
540 cmd = 42;
541 s_push_layer(c->out_s, channel_hdr, 8);
542 out_uint16_be(c->out_s, SCP_COMMAND_SET_DEFAULT);
543 out_uint16_be(c->out_s, cmd);
544
545 /* session count */
546 out_uint32_be(c->out_s, sescnt);
547
548 /* setting the continue flag */
549 if ((idx + 1)*SCP_SERVER_MAX_LIST_SIZE >= sescnt)
550 {
551 out_uint8(c->out_s, 0);
552 /* setting session count for this packet */
553 pidx = sescnt - (idx * SCP_SERVER_MAX_LIST_SIZE);
554 out_uint8(c->out_s, pidx);
555 }
556 else
557 {
558 out_uint8(c->out_s, 1);
559 /* setting session count for this packet */
560 pidx = SCP_SERVER_MAX_LIST_SIZE;
561 out_uint8(c->out_s, pidx);
562 }
563
564 /* adding session descriptors */
565 for (sidx = 0; sidx < pidx; sidx++)
566 {
567 /* shortcut to the current session to send */
568 cds = ds + ((idx) * SCP_SERVER_MAX_LIST_SIZE) + sidx;
569
570 /* session data */
571 out_uint32_be(c->out_s, cds->SID); /* session id */
572 out_uint8(c->out_s, cds->type);
573 out_uint16_be(c->out_s, cds->height);
574 out_uint16_be(c->out_s, cds->width);
575 out_uint8(c->out_s, cds->bpp);
576 out_uint8(c->out_s, cds->idle_days);
577 out_uint8(c->out_s, cds->idle_hours);
578 out_uint8(c->out_s, cds->idle_minutes);
579 size += 13;
580
581 out_uint16_be(c->out_s, cds->conn_year);
582 out_uint8(c->out_s, cds->conn_month);
583 out_uint8(c->out_s, cds->conn_day);
584 out_uint8(c->out_s, cds->conn_hour);
585 out_uint8(c->out_s, cds->conn_minute);
586 out_uint8(c->out_s, cds->addr_type);
587 size += 7;
588
589 if (cds->addr_type == SCP_ADDRESS_TYPE_IPV4)
590 {
591 in_uint32_be(c->out_s, cds->ipv4addr);
592 size += 4;
593 }
594 else if (cds->addr_type == SCP_ADDRESS_TYPE_IPV6)
595 {
596 in_uint8a(c->out_s, cds->ipv6addr, 16);
597 size += 16;
598 }
599 }
600
601 s_pop_layer(c->out_s, channel_hdr);
602 out_uint32_be(c->out_s, version);
603 out_uint32_be(c->out_s, size);
604
605 if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, size))
606 {
607 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
608 return SCP_SERVER_STATE_NETWORK_ERR;
609 }
610 }
611
612 /* we get the response */
613 init_stream(c->in_s, c->in_s->size);
614
615 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, (8)))
616 {
617 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
618 return SCP_SERVER_STATE_NETWORK_ERR;
619 }
620
621 in_uint32_be(c->in_s, version);
622
623 if (version != 1)
624 {
625 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: version error", __LINE__);
626 return SCP_SERVER_STATE_VERSION_ERR;
627 }
628
629 in_uint32_be(c->in_s, size);
630
631 /* Check the message is big enough for the header, the command set, and
632 * the command (but not too big) */
633 if (size < (8 + 2 + 2) || size > SCP_MAX_MESSAGE_SIZE)
634 {
635 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: size error", __LINE__);
636 return SCP_SERVER_STATE_SIZE_ERR;
637 }
638
639 /* rest of the packet */
640 init_stream(c->in_s, size - 8);
641
642 if (0 != scp_tcp_force_recv(c->in_sck, c->in_s->data, (size - 8)))
643 {
644 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
645 return SCP_SERVER_STATE_NETWORK_ERR;
646 }
647
648 c->in_s->end = c->in_s->data + (size - 8);
649
650 in_uint16_be(c->in_s, cmd);
651
652 if (cmd != SCP_COMMAND_SET_DEFAULT)
653 {
654 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
655 return SCP_SERVER_STATE_SEQUENCE_ERR;
656 }
657
658 in_uint16_be(c->in_s, cmd);
659
660 if (cmd == 43)
661 {
662 if (!s_check_rem(c->in_s, 4))
663 {
664 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: missing session", __LINE__);
665 return SCP_SERVER_STATE_SIZE_ERR;
666 }
667 /* select session */
668 in_uint32_be(c->in_s, (*sid));
669
670 /* checking sid value */
671 for (idx = 0; idx < sescnt; idx++)
672 {
673 /* the sid is valid */
674 if (ds[idx].SID == (*sid))
675 {
676 /* ok, session selected */
677 return SCP_SERVER_STATE_OK;
678 }
679 }
680
681 /* if we got here, the requested sid wasn't one from the list we sent */
682 /* we should kill the connection */
683 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error (no such session in list)", __LINE__);
684 return SCP_SERVER_STATE_INTERNAL_ERR;
685 }
686 else if (cmd == 44)
687 {
688 /* cancel connection */
689 return SCP_SERVER_STATE_SELECTION_CANCEL;
690 }
691 // else if (cmd == 45)
692 // {
693 // /* force new connection */
694 // return SCP_SERVER_STATE_FORCE_NEW;
695 // }
696 else
697 {
698 /* wrong response */
699 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: sequence error", __LINE__);
700 return SCP_SERVER_STATE_SEQUENCE_ERR;
701 }
702
703 return SCP_SERVER_STATE_OK;
704 }
705 #endif
706
707 enum SCP_SERVER_STATES_E
scp_v1s_list_sessions40(struct trans * t)708 scp_v1s_list_sessions40(struct trans *t)
709 {
710 struct stream *out_s;
711
712 out_s = trans_get_out_s(t, 12);
713 /* send a notice that we have some disconnected sessions */
714 out_uint32_be(out_s, 1); /* version */
715 out_uint32_be(out_s, 12); /* size */
716 out_uint16_be(out_s, SCP_COMMAND_SET_DEFAULT); /* cmdset */
717 out_uint16_be(out_s, SCP_REPLY_USER_SESSIONS_EXIST);/* cmd */
718 s_mark_end(out_s);
719 if (0 != trans_force_write(t))
720 {
721 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
722 return SCP_SERVER_STATE_NETWORK_ERR;
723 }
724 return SCP_SERVER_STATE_OK;
725 }
726
727 enum SCP_SERVER_STATES_E
scp_v1s_list_sessions42(struct trans * t,int sescnt,struct SCP_DISCONNECTED_SESSION * ds)728 scp_v1s_list_sessions42(struct trans *t, int sescnt, struct SCP_DISCONNECTED_SESSION *ds)
729 {
730 int pktcnt;
731 int idx;
732 int sidx;
733 int pidx;
734 int size;
735 struct stream *out_s;
736 struct SCP_DISCONNECTED_SESSION *cds;
737
738 /* calculating the number of packets to send */
739 pktcnt = sescnt / SCP_SERVER_MAX_LIST_SIZE;
740 if ((sescnt % SCP_SERVER_MAX_LIST_SIZE) != 0)
741 {
742 pktcnt++;
743 }
744
745 for (idx = 0; idx < pktcnt; idx++)
746 {
747 out_s = trans_get_out_s(t, 8192);
748
749 /* size: ver+size+cmdset+cmd+sescnt+continue+count */
750 size = 4 + 4 + 2 + 2 + 4 + 1 + 1;
751
752 /* header */
753 s_push_layer(out_s, channel_hdr, 8);
754 out_uint16_be(out_s, SCP_COMMAND_SET_DEFAULT);
755 out_uint16_be(out_s, SCP_REPLY_SESSIONS_INFO);
756
757 /* session count */
758 out_uint32_be(out_s, sescnt);
759
760 /* setting the continue flag */
761 if ((idx + 1) * SCP_SERVER_MAX_LIST_SIZE >= sescnt)
762 {
763 out_uint8(out_s, 0);
764 /* setting session count for this packet */
765 pidx = sescnt - (idx * SCP_SERVER_MAX_LIST_SIZE);
766 out_uint8(out_s, pidx);
767 }
768 else
769 {
770 out_uint8(out_s, 1);
771 /* setting session count for this packet */
772 pidx = SCP_SERVER_MAX_LIST_SIZE;
773 out_uint8(out_s, pidx);
774 }
775
776 /* adding session descriptors */
777 for (sidx = 0; sidx < pidx; sidx++)
778 {
779 /* shortcut to the current session to send */
780 cds = ds + (idx * SCP_SERVER_MAX_LIST_SIZE) + sidx;
781
782 /* session data */
783 out_uint32_be(out_s, cds->SID); /* session id */
784 out_uint8(out_s, cds->type);
785 out_uint16_be(out_s, cds->height);
786 out_uint16_be(out_s, cds->width);
787 out_uint8(out_s, cds->bpp);
788 out_uint8(out_s, cds->idle_days);
789 out_uint8(out_s, cds->idle_hours);
790 out_uint8(out_s, cds->idle_minutes);
791 size += 13;
792
793 out_uint16_be(out_s, cds->conn_year);
794 out_uint8(out_s, cds->conn_month);
795 out_uint8(out_s, cds->conn_day);
796 out_uint8(out_s, cds->conn_hour);
797 out_uint8(out_s, cds->conn_minute);
798 out_uint8(out_s, cds->addr_type);
799 size += 7;
800
801 if (cds->addr_type == SCP_ADDRESS_TYPE_IPV4)
802 {
803 in_uint32_be(out_s, cds->ipv4addr);
804 size += 4;
805 }
806 else if (cds->addr_type == SCP_ADDRESS_TYPE_IPV6)
807 {
808 in_uint8a(out_s, cds->ipv6addr, 16);
809 size += 16;
810 }
811 }
812 s_mark_end(out_s);
813 s_pop_layer(out_s, channel_hdr);
814 out_uint32_be(out_s, 1); /* version */
815 out_uint32_be(out_s, size);
816
817 if (0 != trans_force_write(t))
818 {
819 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
820 return SCP_SERVER_STATE_NETWORK_ERR;
821 }
822 }
823 return SCP_SERVER_STATE_OK;
824 }
825
826 // TODO
827 enum SCP_SERVER_STATES_E
scp_v1s_accept_list_sessions_reply(int cmd,struct trans * t)828 scp_v1s_accept_list_sessions_reply(int cmd, struct trans *t)
829 {
830 struct SCP_SESSION *s;
831 struct stream *in_s;
832
833 s = (struct SCP_SESSION *) (t->callback_data);
834 if (s == NULL)
835 {
836 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: internal error", __LINE__);
837 return SCP_SERVER_STATE_INTERNAL_ERR;
838 }
839 s->current_cmd = cmd;
840 in_s = t->in_s;
841 switch (cmd)
842 {
843 case SCP_CMD_GET_SESSION_LIST:
844 break;
845 case SCP_CMD_SELECT_SESSION:
846 in_uint32_be(in_s, s->return_sid);
847 break;
848 case SCP_CMD_SELECT_SESSION_CANCEL:
849 break;
850 case SCP_CMD_FORCE_NEW_CONN:
851 break;
852 default:
853 break;
854 }
855 return SCP_SERVER_STATE_OK;
856 }
857
858 enum SCP_SERVER_STATES_E
scp_v1s_reconnect_session(struct trans * t,SCP_DISPLAY d)859 scp_v1s_reconnect_session(struct trans *t, SCP_DISPLAY d)
860 {
861 struct stream *out_s;
862
863 /* ok, we send session data and display */
864 out_s = trans_get_out_s(t, 14);
865 /* header */
866 out_uint32_be(out_s, 1); /* version */
867 out_uint32_be(out_s, 14); /* size */
868 out_uint16_be(out_s, SCP_COMMAND_SET_DEFAULT);
869 out_uint16_be(out_s, SCP_REPLY_SESSION_RECONNECTED); /* cmd */
870 /* session data */
871 out_uint16_be(out_s, d); /* session display */
872 s_mark_end(out_s);
873
874 /*out_uint8(c->out_s, ds->type);
875 out_uint16_be(c->out_s, ds->height);
876 out_uint16_be(c->out_s, ds->width);
877 out_uint8(c->out_s, ds->bpp);
878 out_uint8(c->out_s, ds->idle_days);
879 out_uint8(c->out_s, ds->idle_hours);
880 out_uint8(c->out_s, ds->idle_minutes);*/
881 /* these last three are not really needed... */
882
883 if (0 != trans_force_write(t))
884 {
885 LOG(LOG_LEVEL_WARNING, "[v1s:%d] connection aborted: network error", __LINE__);
886 return SCP_SERVER_STATE_NETWORK_ERR;
887 }
888
889 return SCP_SERVER_STATE_OK;
890 }
891
892 #endif
893