/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/rdesktop.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/rdesktop.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 427 - (show annotations)
Thu Jun 19 11:51:18 2003 UTC (20 years, 11 months ago) by forsberg
Original Path: sourceforge.net/trunk/rdesktop/rdesktop.c
File MIME type: text/plain
File size: 14110 byte(s)
Make it possible to disable encryption for all packets except the
packets exchanged in the setup phase.

Seems to work with all encryption levels on my W2003 Server (Beta).

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Entrypoint and utility functions
4 Copyright (C) Matthew Chapman 1999-2003
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <stdarg.h> /* va_list va_start va_end */
22 #include <unistd.h> /* read close getuid getgid getpid getppid gethostname */
23 #include <fcntl.h> /* open */
24 #include <pwd.h> /* getpwuid */
25 #include <termios.h> /* tcgetattr tcsetattr */
26 #include <sys/stat.h> /* stat */
27 #include <sys/time.h> /* gettimeofday */
28 #include <sys/times.h> /* times */
29 #include <errno.h>
30 #include "rdesktop.h"
31
32 #ifdef EGD_SOCKET
33 #include <sys/socket.h> /* socket connect */
34 #include <sys/un.h> /* sockaddr_un */
35 #endif
36
37 #ifdef WITH_OPENSSL
38 #include <openssl/md5.h>
39 #else
40 #include "crypto/md5.h"
41 #endif
42
43 char title[32] = "";
44 char username[16];
45 char hostname[16];
46 char keymapname[16];
47 int keylayout = 0x409; /* Defaults to US keyboard layout */
48 int width = 800; /* If width or height are reset to zero, the geometry will
49 be fetched from _NET_WORKAREA */
50 int height = 600;
51 int tcp_port_rdp = TCP_PORT_RDP;
52 int server_bpp = 8;
53 int win_button_size = 0; /* If zero, disable single app mode */
54 BOOL bitmap_compression = True;
55 BOOL sendmotion = True;
56 BOOL orders = True;
57 BOOL encryption = True;
58 BOOL packet_encryption = True;
59 BOOL desktop_save = True;
60 BOOL fullscreen = False;
61 BOOL grab_keyboard = True;
62 BOOL hide_decorations = False;
63 BOOL use_rdp5 = False;
64 extern BOOL owncolmap;
65
66 #ifdef RDP2VNC
67 extern int rfb_port;
68 extern int defer_time;
69 void
70 rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
71 char *shell, char *directory);
72 #endif
73 /* Display usage information */
74 static void
75 usage(char *program)
76 {
77 fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
78 fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
79 fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
80
81 fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
82 #ifdef RDP2VNC
83 fprintf(stderr, " -V: vnc port\n");
84 fprintf(stderr, " -E: defer time (ms)\n");
85 #endif
86 fprintf(stderr, " -u: user name\n");
87 fprintf(stderr, " -d: domain\n");
88 fprintf(stderr, " -s: shell\n");
89 fprintf(stderr, " -S: caption button size (single application mode)\n");
90 fprintf(stderr, " -c: working directory\n");
91 fprintf(stderr, " -p: password (- to prompt)\n");
92 fprintf(stderr, " -n: client hostname\n");
93 fprintf(stderr, " -k: keyboard layout on terminal server (us,sv,gr,etc.)\n");
94 fprintf(stderr, " -g: desktop geometry (WxH)\n");
95 fprintf(stderr, " -f: full-screen mode\n");
96 fprintf(stderr, " -b: force bitmap updates\n");
97 fprintf(stderr, " -e: disable encryption (French TS)\n");
98 fprintf(stderr, " -E: disable encryption of everything but the logon packet\n");
99 fprintf(stderr, " -m: do not send motion events\n");
100 fprintf(stderr, " -C: use private colour map\n");
101 fprintf(stderr, " -K: keep window manager key bindings\n");
102 fprintf(stderr, " -T: window title\n");
103 fprintf(stderr, " -D: hide window manager decorations\n");
104 fprintf(stderr, " -a: server bpp\n");
105 fprintf(stderr, " -5: Use RDP5 (EXPERIMENTAL!)\n");
106 }
107
108 static BOOL
109 read_password(char *password, int size)
110 {
111 struct termios tios;
112 BOOL ret = False;
113 int istty = 0;
114 char *p;
115
116 if (tcgetattr(STDIN_FILENO, &tios) == 0)
117 {
118 fprintf(stderr, "Password: ");
119 tios.c_lflag &= ~ECHO;
120 tcsetattr(STDIN_FILENO, TCSANOW, &tios);
121 istty = 1;
122 }
123
124 if (fgets(password, size, stdin) != NULL)
125 {
126 ret = True;
127
128 /* strip final newline */
129 p = strchr(password, '\n');
130 if (p != NULL)
131 *p = 0;
132 }
133
134 if (istty)
135 {
136 tios.c_lflag |= ECHO;
137 tcsetattr(STDIN_FILENO, TCSANOW, &tios);
138 fprintf(stderr, "\n");
139 }
140
141 return ret;
142 }
143
144 /* Client program */
145 int
146 main(int argc, char *argv[])
147 {
148 char server[64];
149 char fullhostname[64];
150 char domain[16];
151 char password[16];
152 char shell[128];
153 char directory[32];
154 BOOL prompt_password, rdp_retval = False;
155 struct passwd *pw;
156 uint32 flags;
157 char *p;
158 int c;
159 int username_option = 0;
160
161 flags = RDP_LOGON_NORMAL;
162 prompt_password = False;
163 domain[0] = password[0] = shell[0] = directory[0] = 0;
164 strcpy(keymapname, "en-us");
165
166 #ifdef RDP2VNC
167 #define VNCOPT "V:E:"
168 #else
169 #define VNCOPT
170 #endif
171
172 while ((c = getopt(argc, argv, VNCOPT "u:d:s:S:c:p:n:k:g:a:fbeEmCKT:Dh?54")) != -1)
173 {
174 switch (c)
175 {
176 #ifdef RDP2VNC
177 case 'V':
178 rfb_port = strtol(optarg, NULL, 10);
179 if (rfb_port < 100)
180 rfb_port += 5900;
181 break;
182
183 case 'E':
184 defer_time = strtol(optarg, NULL, 10);
185 if (defer_time < 0)
186 defer_time = 0;
187 break;
188 #endif
189
190 case 'u':
191 STRNCPY(username, optarg, sizeof(username));
192 username_option = 1;
193 break;
194
195 case 'd':
196 STRNCPY(domain, optarg, sizeof(domain));
197 break;
198
199 case 's':
200 STRNCPY(shell, optarg, sizeof(shell));
201 break;
202
203 case 'S':
204 if (!strcmp(optarg, "standard"))
205 {
206 win_button_size = 18;
207 break;
208 }
209
210 win_button_size = strtol(optarg, &p, 10);
211
212 if (*p)
213 {
214 error("invalid button size\n");
215 return 1;
216 }
217
218 break;
219
220 case 'c':
221 STRNCPY(directory, optarg, sizeof(directory));
222 break;
223
224 case 'p':
225 if ((optarg[0] == '-') && (optarg[1] == 0))
226 {
227 prompt_password = True;
228 break;
229 }
230
231 STRNCPY(password, optarg, sizeof(password));
232 flags |= RDP_LOGON_AUTO;
233
234 /* try to overwrite argument so it won't appear in ps */
235 p = optarg;
236 while (*p)
237 *(p++) = 'X';
238 break;
239
240 case 'n':
241 STRNCPY(hostname, optarg, sizeof(hostname));
242 break;
243
244 case 'k':
245 STRNCPY(keymapname, optarg, sizeof(keymapname));
246 break;
247
248 case 'g':
249 if (!strcmp(optarg, "workarea"))
250 {
251 width = height = 0;
252 break;
253 }
254
255 width = strtol(optarg, &p, 10);
256 if (*p == 'x')
257 height = strtol(p + 1, NULL, 10);
258
259 if ((width == 0) || (height == 0))
260 {
261 error("invalid geometry\n");
262 return 1;
263 }
264 break;
265
266 case 'f':
267 fullscreen = True;
268 break;
269
270 case 'b':
271 orders = False;
272 break;
273
274 case 'e':
275 encryption = False;
276 break;
277 case 'E':
278 packet_encryption = False;
279 break;
280 case 'm':
281 sendmotion = False;
282 break;
283
284 case 'C':
285 owncolmap = True;
286 break;
287
288 case 'K':
289 grab_keyboard = False;
290 break;
291
292 case 'T':
293 STRNCPY(title, optarg, sizeof(title));
294 break;
295
296 case 'D':
297 hide_decorations = True;
298 break;
299
300 case 'a':
301 server_bpp = strtol(optarg, NULL, 10);
302 if (server_bpp != 8 && server_bpp != 16 && server_bpp != 15
303 && server_bpp != 24)
304 {
305 error("invalid server bpp\n");
306 return 1;
307 }
308 break;
309
310 case '5':
311 use_rdp5 = True;
312 break;
313 case 'h':
314 case '?':
315 default:
316 usage(argv[0]);
317 return 1;
318 }
319 }
320
321 if (argc - optind < 1)
322 {
323 usage(argv[0]);
324 return 1;
325 }
326
327 STRNCPY(server, argv[optind], sizeof(server));
328 p = strchr(server, ':');
329 if (p != NULL)
330 {
331 tcp_port_rdp = strtol(p + 1, NULL, 10);
332 *p = 0;
333 }
334
335 if (!username_option)
336 {
337 pw = getpwuid(getuid());
338 if ((pw == NULL) || (pw->pw_name == NULL))
339 {
340 error("could not determine username, use -u\n");
341 return 1;
342 }
343
344 STRNCPY(username, pw->pw_name, sizeof(username));
345 }
346
347 if (hostname[0] == 0)
348 {
349 if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
350 {
351 error("could not determine local hostname, use -n\n");
352 return 1;
353 }
354
355 p = strchr(fullhostname, '.');
356 if (p != NULL)
357 *p = 0;
358
359 STRNCPY(hostname, fullhostname, sizeof(hostname));
360 }
361
362 if (prompt_password && read_password(password, sizeof(password)))
363 flags |= RDP_LOGON_AUTO;
364
365 if (title[0] == 0)
366 {
367 strcpy(title, "rdesktop - ");
368 strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
369 }
370
371 #ifdef RDP2VNC
372 rdp2vnc_connect(server, flags, domain, password, shell, directory);
373 return 0;
374 #else
375
376 if (!ui_init())
377 return 1;
378
379 ipc_init(); // Must be run after ui_init, we need X to be setup.
380
381 if (use_rdp5)
382 cliprdr_init(); // FIXME: Should perhaps be integrated into the channel management code?
383
384 if (!rdp_connect(server, flags, domain, password, shell, directory))
385 return 1;
386
387 /* By setting encryption to False here, we have an encrypted login
388 packet but unencrypted transfer of other packets */
389 if (!packet_encryption)
390 encryption = False;
391
392
393 DEBUG(("Connection successful.\n"));
394 memset(password, 0, sizeof(password));
395
396 if (ui_create_window())
397 {
398 rdp_retval = rdp_main_loop();
399 ui_destroy_window();
400 }
401
402 DEBUG(("Disconnecting...\n"));
403 rdp_disconnect();
404 ui_deinit();
405
406 if (True == rdp_retval)
407 return 0;
408 else
409 return 2;
410
411 #endif
412
413 }
414
415 #ifdef EGD_SOCKET
416 /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
417 static BOOL
418 generate_random_egd(uint8 * buf)
419 {
420 struct sockaddr_un addr;
421 BOOL ret = False;
422 int fd;
423
424 fd = socket(AF_UNIX, SOCK_STREAM, 0);
425 if (fd == -1)
426 return False;
427
428 addr.sun_family = AF_UNIX;
429 memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
430 if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
431 goto err;
432
433 /* PRNGD and EGD use a simple communications protocol */
434 buf[0] = 1; /* Non-blocking (similar to /dev/urandom) */
435 buf[1] = 32; /* Number of requested random bytes */
436 if (write(fd, buf, 2) != 2)
437 goto err;
438
439 if ((read(fd, buf, 1) != 1) || (buf[0] == 0)) /* Available? */
440 goto err;
441
442 if (read(fd, buf, 32) != 32)
443 goto err;
444
445 ret = True;
446
447 err:
448 close(fd);
449 return ret;
450 }
451 #endif
452
453 /* Generate a 32-byte random for the secure transport code. */
454 void
455 generate_random(uint8 * random)
456 {
457 struct stat st;
458 struct tms tmsbuf;
459 MD5_CTX md5;
460 uint32 *r;
461 int fd, n;
462
463 /* If we have a kernel random device, try that first */
464 if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
465 || ((fd = open("/dev/random", O_RDONLY)) != -1))
466 {
467 n = read(fd, random, 32);
468 close(fd);
469 if (n == 32)
470 return;
471 }
472
473 #ifdef EGD_SOCKET
474 /* As a second preference use an EGD */
475 if (generate_random_egd(random))
476 return;
477 #endif
478
479 /* Otherwise use whatever entropy we can gather - ideas welcome. */
480 r = (uint32 *) random;
481 r[0] = (getpid()) | (getppid() << 16);
482 r[1] = (getuid()) | (getgid() << 16);
483 r[2] = times(&tmsbuf); /* system uptime (clocks) */
484 gettimeofday((struct timeval *) &r[3], NULL); /* sec and usec */
485 stat("/tmp", &st);
486 r[5] = st.st_atime;
487 r[6] = st.st_mtime;
488 r[7] = st.st_ctime;
489
490 /* Hash both halves with MD5 to obscure possible patterns */
491 MD5_Init(&md5);
492 MD5_Update(&md5, random, 16);
493 MD5_Final(random, &md5);
494 MD5_Update(&md5, random + 16, 16);
495 MD5_Final(random + 16, &md5);
496 }
497
498 /* malloc; exit if out of memory */
499 void *
500 xmalloc(int size)
501 {
502 void *mem = malloc(size);
503 if (mem == NULL)
504 {
505 error("xmalloc %d\n", size);
506 exit(1);
507 }
508 return mem;
509 }
510
511 /* realloc; exit if out of memory */
512 void *
513 xrealloc(void *oldmem, int size)
514 {
515 void *mem = realloc(oldmem, size);
516 if (mem == NULL)
517 {
518 error("xrealloc %d\n", size);
519 exit(1);
520 }
521 return mem;
522 }
523
524 /* free */
525 void
526 xfree(void *mem)
527 {
528 free(mem);
529 }
530
531 /* report an error */
532 void
533 error(char *format, ...)
534 {
535 va_list ap;
536
537 fprintf(stderr, "ERROR: ");
538
539 va_start(ap, format);
540 vfprintf(stderr, format, ap);
541 va_end(ap);
542 }
543
544 /* report a warning */
545 void
546 warning(char *format, ...)
547 {
548 va_list ap;
549
550 fprintf(stderr, "WARNING: ");
551
552 va_start(ap, format);
553 vfprintf(stderr, format, ap);
554 va_end(ap);
555 }
556
557 /* report an unimplemented protocol feature */
558 void
559 unimpl(char *format, ...)
560 {
561 va_list ap;
562
563 fprintf(stderr, "NOT IMPLEMENTED: ");
564
565 va_start(ap, format);
566 vfprintf(stderr, format, ap);
567 va_end(ap);
568 }
569
570 /* produce a hex dump */
571 void
572 hexdump(unsigned char *p, int len)
573 {
574 unsigned char *line = p;
575 int i, thisline, offset = 0;
576
577 while (offset < len)
578 {
579 printf("%04x ", offset);
580 thisline = len - offset;
581 if (thisline > 16)
582 thisline = 16;
583
584 for (i = 0; i < thisline; i++)
585 printf("%02x ", line[i]);
586
587 for (; i < 16; i++)
588 printf(" ");
589
590 for (i = 0; i < thisline; i++)
591 printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
592
593 printf("\n");
594 offset += thisline;
595 line += thisline;
596 }
597 }
598
599
600 int
601 load_licence(unsigned char **data)
602 {
603 char *home, *path;
604 struct stat st;
605 int fd, length;
606
607 home = getenv("HOME");
608 if (home == NULL)
609 return -1;
610
611 path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
612 sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
613
614 fd = open(path, O_RDONLY);
615 if (fd == -1)
616 return -1;
617
618 if (fstat(fd, &st))
619 return -1;
620
621 *data = (uint8 *) xmalloc(st.st_size);
622 length = read(fd, *data, st.st_size);
623 close(fd);
624 xfree(path);
625 return length;
626 }
627
628 void
629 save_licence(unsigned char *data, int length)
630 {
631 char *home, *path, *tmppath;
632 int fd;
633
634 home = getenv("HOME");
635 if (home == NULL)
636 return;
637
638 path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
639
640 sprintf(path, "%s/.rdesktop", home);
641 if ((mkdir(path, 0700) == -1) && errno != EEXIST)
642 {
643 perror(path);
644 return;
645 }
646
647 /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
648
649 sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
650 tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
651 strcpy(tmppath, path);
652 strcat(tmppath, ".new");
653
654 fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
655 if (fd == -1)
656 {
657 perror(tmppath);
658 return;
659 }
660
661 if (write(fd, data, length) != length)
662 {
663 perror(tmppath);
664 unlink(tmppath);
665 }
666 else if (rename(tmppath, path) == -1)
667 {
668 perror(path);
669 unlink(tmppath);
670 }
671
672 close(fd);
673 xfree(tmppath);
674 xfree(path);
675 }

  ViewVC Help
Powered by ViewVC 1.1.26