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