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