/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 857 - (hide annotations)
Sun Mar 13 13:36:04 2005 UTC (19 years, 2 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdesktop.c
File MIME type: text/plain
File size: 26985 byte(s)
configure test for HAVE_ICONV_H, HAVE_LOCALE_H and HAVE_LANGINFO_H
still no test for HAVE_ICONV

1 forsberg 350 /* -*- c-basic-offset: 8 -*-
2 matty 10 rdesktop: A Remote Desktop Protocol client.
3     Entrypoint and utility functions
4 stargo 828 Copyright (C) Matthew Chapman 1999-2005
5 jsorg71 100
6 matty 10 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 jsorg71 100
11 matty 10 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 jsorg71 100
16 matty 10 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 matty 30 #include <stdarg.h> /* va_list va_start va_end */
22 matty 24 #include <unistd.h> /* read close getuid getgid getpid getppid gethostname */
23     #include <fcntl.h> /* open */
24     #include <pwd.h> /* getpwuid */
25 matthewc 211 #include <termios.h> /* tcgetattr tcsetattr */
26 matty 24 #include <sys/stat.h> /* stat */
27     #include <sys/time.h> /* gettimeofday */
28     #include <sys/times.h> /* times */
29 stargo 570 #include <ctype.h> /* toupper */
30 astrand 325 #include <errno.h>
31 matty 10 #include "rdesktop.h"
32    
33 stargo 855 #ifdef HAVE_ICONV
34 stargo 857 #ifdef HAVE_LOCALE_H
35 stargo 855 #include <locale.h>
36 stargo 857 #endif
37     #ifdef HAVE_LANGINFO_H
38 stargo 855 #include <langinfo.h>
39     #endif
40 stargo 857 #endif
41 stargo 855
42 matthewc 220 #ifdef EGD_SOCKET
43     #include <sys/socket.h> /* socket connect */
44     #include <sys/un.h> /* sockaddr_un */
45     #endif
46    
47     #include <openssl/md5.h>
48    
49 astrand 479 char g_title[64] = "";
50     char g_username[64];
51 jsorg71 710 char g_hostname[16];
52 matthewc 38 char keymapname[16];
53 jsorg71 710 int g_keylayout = 0x409; /* Defaults to US keyboard layout */
54 astrand 500
55     int g_width = 800; /* width is special: If 0, the
56     geometry will be fetched from
57     _NET_WORKAREA. If negative,
58     absolute value specifies the
59     percent of the whole screen. */
60 jsorg71 447 int g_height = 600;
61 stargo 800 int g_xpos = 0;
62     int g_ypos = 0;
63 jsorg71 710 extern int g_tcp_port_rdp;
64 jsorg71 438 int g_server_bpp = 8;
65 jsorg71 450 int g_win_button_size = 0; /* If zero, disable single app mode */
66 jsorg71 437 BOOL g_bitmap_compression = True;
67 jsorg71 447 BOOL g_sendmotion = True;
68 jsorg71 678 BOOL g_bitmap_cache = True;
69 jsorg71 725 BOOL g_bitmap_cache_persist_enable = False;
70     BOOL g_bitmap_cache_precache = True;
71 jsorg71 437 BOOL g_encryption = True;
72 forsberg 427 BOOL packet_encryption = True;
73 jsorg71 848 BOOL g_desktop_save = True; /* desktop save order */
74     BOOL g_polygon_ellipse_orders = True; /* polygon / ellipse orders */
75 jsorg71 447 BOOL g_fullscreen = False;
76 jsorg71 450 BOOL g_grab_keyboard = True;
77     BOOL g_hide_decorations = False;
78 astrand 458 BOOL g_use_rdp5 = True;
79 matthewc 482 BOOL g_console_session = False;
80 astrand 552 BOOL g_numlock_sync = False;
81 stargo 648 BOOL g_owncolmap = False;
82 astrand 651 BOOL g_ownbackstore = True; /* We can't rely on external BackingStore */
83 stargo 648 uint32 g_embed_wnd;
84 astrand 651 uint32 g_rdp5_performanceflags =
85     RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
86 matty 10
87 stargo 501 #ifdef WITH_RDPSND
88 matthewc 520 BOOL g_rdpsnd = False;
89 stargo 501 #endif
90    
91 stargo 855 #ifdef HAVE_ICONV
92     char g_codepage[16] = "";
93     #endif
94    
95 n-ki 569 extern RDPDR_DEVICE g_rdpdr_device[];
96     extern uint32 g_num_devices;
97 astrand 651 extern char *g_rdpdr_clientname;
98 n-ki 569
99 astrand 333 #ifdef RDP2VNC
100     extern int rfb_port;
101     extern int defer_time;
102     void
103     rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
104     char *shell, char *directory);
105     #endif
106 matty 10 /* Display usage information */
107 matty 25 static void
108     usage(char *program)
109 matty 10 {
110 matthewc 122 fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
111 stargo 828 fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
112 matthewc 122 fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
113    
114 matthewc 222 fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
115 astrand 333 #ifdef RDP2VNC
116     fprintf(stderr, " -V: vnc port\n");
117 forsberg 471 fprintf(stderr, " -Q: defer time (ms)\n");
118 astrand 333 #endif
119 astrand 111 fprintf(stderr, " -u: user name\n");
120     fprintf(stderr, " -d: domain\n");
121     fprintf(stderr, " -s: shell\n");
122     fprintf(stderr, " -c: working directory\n");
123 matthewc 211 fprintf(stderr, " -p: password (- to prompt)\n");
124 astrand 111 fprintf(stderr, " -n: client hostname\n");
125 matthewc 520 fprintf(stderr, " -k: keyboard layout on server (en-us, de, sv, etc.)\n");
126 astrand 111 fprintf(stderr, " -g: desktop geometry (WxH)\n");
127     fprintf(stderr, " -f: full-screen mode\n");
128     fprintf(stderr, " -b: force bitmap updates\n");
129 stargo 855 #ifdef HAVE_ICONV
130     fprintf(stderr, " -L: local codepage\n");
131     #endif
132 stargo 609 fprintf(stderr, " -B: use BackingStore of X-server (if available)\n");
133 astrand 111 fprintf(stderr, " -e: disable encryption (French TS)\n");
134 forsberg 471 fprintf(stderr, " -E: disable encryption from client to server\n");
135 astrand 111 fprintf(stderr, " -m: do not send motion events\n");
136 n-ki 279 fprintf(stderr, " -C: use private colour map\n");
137 matthewc 520 fprintf(stderr, " -D: hide window manager decorations\n");
138 astrand 111 fprintf(stderr, " -K: keep window manager key bindings\n");
139 matthewc 520 fprintf(stderr, " -S: caption button size (single application mode)\n");
140 matthewc 223 fprintf(stderr, " -T: window title\n");
141 n-ki 569 fprintf(stderr, " -N: enable numlock syncronization\n");
142 stargo 636 fprintf(stderr, " -X: embed into another window with a given id.\n");
143 matthewc 520 fprintf(stderr, " -a: connection colour depth\n");
144 jsorg71 773 fprintf(stderr, " -z: enable rdp compression\n");
145 jsorg71 725 fprintf(stderr, " -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex nr.)\n");
146     fprintf(stderr, " -P: use persistent bitmap caching\n");
147 n-ki 569 fprintf(stderr, " -r: enable specified device redirection (this flag can be repeated)\n");
148 astrand 608 fprintf(stderr,
149     " '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n");
150 n-ki 578 fprintf(stderr, " or COM1=/dev/ttyS0,COM2=/dev/ttyS1\n");
151 astrand 608 fprintf(stderr,
152 astrand 747 " '-r disk:floppy=/mnt/floppy': enable redirection of /mnt/floppy to 'floppy' share\n");
153     fprintf(stderr, " or 'floppy=/mnt/floppy,cdrom=/mnt/cdrom'\n");
154 forsberg 646 fprintf(stderr, " '-r clientname=<client name>': Set the client name displayed\n");
155     fprintf(stderr, " for redirected disks\n");
156 astrand 608 fprintf(stderr,
157     " '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1\n");
158 n-ki 578 fprintf(stderr, " or LPT1=/dev/lp0,LPT2=/dev/lp1\n");
159 n-ki 569 fprintf(stderr, " '-r printer:mydeskjet': enable printer redirection\n");
160 astrand 608 fprintf(stderr,
161 n-ki 628 " or mydeskjet=\"HP LaserJet IIIP\" to enter server driver as well\n");
162 n-ki 630 fprintf(stderr, " '-r sound:[local|off|remote]': enable sound redirection\n");
163 n-ki 628 fprintf(stderr, " remote would leave sound on server\n");
164 matthewc 482 fprintf(stderr, " -0: attach to console\n");
165     fprintf(stderr, " -4: use RDP version 4\n");
166     fprintf(stderr, " -5: use RDP version 5 (default)\n");
167 matty 10 }
168    
169 astrand 676 void
170     print_disconnect_reason(uint16 reason)
171     {
172     char *text;
173    
174     switch (reason)
175     {
176     case exDiscReasonNoInfo:
177     text = "No information available";
178     break;
179    
180     case exDiscReasonAPIInitiatedDisconnect:
181     text = "Server initiated disconnect";
182     break;
183    
184     case exDiscReasonAPIInitiatedLogoff:
185     text = "Server initiated logoff";
186     break;
187    
188     case exDiscReasonServerIdleTimeout:
189     text = "Server idle timeout reached";
190     break;
191    
192     case exDiscReasonServerLogonTimeout:
193     text = "Server logon timeout reached";
194     break;
195    
196     case exDiscReasonReplacedByOtherConnection:
197     text = "The session was replaced";
198     break;
199    
200     case exDiscReasonOutOfMemory:
201     text = "The server is out of memory";
202     break;
203    
204     case exDiscReasonServerDeniedConnection:
205     text = "The server denied the connection";
206     break;
207    
208     case exDiscReasonServerDeniedConnectionFips:
209     text = "The server denied the connection for security reason";
210     break;
211    
212     case exDiscReasonLicenseInternal:
213     text = "Internal licensing error";
214     break;
215    
216     case exDiscReasonLicenseNoLicenseServer:
217     text = "No license server available";
218     break;
219    
220     case exDiscReasonLicenseNoLicense:
221     text = "No valid license available";
222     break;
223    
224     case exDiscReasonLicenseErrClientMsg:
225     text = "Invalid licensing message";
226     break;
227    
228     case exDiscReasonLicenseHwidDoesntMatchLicense:
229     text = "Hardware id doesn't match software license";
230     break;
231    
232     case exDiscReasonLicenseErrClientLicense:
233     text = "Client license error";
234     break;
235    
236     case exDiscReasonLicenseCantFinishProtocol:
237     text = "Network error during licensing protocol";
238     break;
239    
240     case exDiscReasonLicenseClientEndedProtocol:
241     text = "Licensing protocol was not completed";
242     break;
243    
244     case exDiscReasonLicenseErrClientEncryption:
245     text = "Incorrect client license enryption";
246     break;
247    
248     case exDiscReasonLicenseCantUpgradeLicense:
249     text = "Can't upgrade license";
250     break;
251    
252     case exDiscReasonLicenseNoRemoteConnections:
253     text = "The server is not licensed to accept remote connections";
254     break;
255    
256     default:
257     if (reason > 0x1000 && reason < 0x7fff)
258     {
259     text = "Internal protocol error";
260     }
261     else
262     {
263     text = "Unknown reason";
264     }
265     }
266     fprintf(stderr, "disconnect: %s.\n", text);
267     }
268    
269 matthewc 211 static BOOL
270     read_password(char *password, int size)
271     {
272     struct termios tios;
273     BOOL ret = False;
274     int istty = 0;
275     char *p;
276    
277     if (tcgetattr(STDIN_FILENO, &tios) == 0)
278     {
279     fprintf(stderr, "Password: ");
280     tios.c_lflag &= ~ECHO;
281     tcsetattr(STDIN_FILENO, TCSANOW, &tios);
282     istty = 1;
283     }
284    
285     if (fgets(password, size, stdin) != NULL)
286     {
287     ret = True;
288    
289     /* strip final newline */
290     p = strchr(password, '\n');
291     if (p != NULL)
292     *p = 0;
293     }
294    
295     if (istty)
296     {
297     tios.c_lflag |= ECHO;
298     tcsetattr(STDIN_FILENO, TCSANOW, &tios);
299     fprintf(stderr, "\n");
300     }
301    
302     return ret;
303     }
304    
305 astrand 444 static void
306     parse_server_and_port(char *server)
307     {
308     char *p;
309     #ifdef IPv6
310     int addr_colons;
311     #endif
312    
313     #ifdef IPv6
314     p = server;
315     addr_colons = 0;
316     while (*p)
317     if (*p++ == ':')
318     addr_colons++;
319     if (addr_colons >= 2)
320     {
321     /* numeric IPv6 style address format - [1:2:3::4]:port */
322     p = strchr(server, ']');
323     if (*server == '[' && p != NULL)
324     {
325     if (*(p + 1) == ':' && *(p + 2) != '\0')
326 jsorg71 710 g_tcp_port_rdp = strtol(p + 2, NULL, 10);
327 astrand 444 /* remove the port number and brackets from the address */
328     *p = '\0';
329     strncpy(server, server + 1, strlen(server));
330     }
331     }
332     else
333     {
334     /* dns name or IPv4 style address format - server.example.com:port or 1.2.3.4:port */
335     p = strchr(server, ':');
336     if (p != NULL)
337     {
338 jsorg71 710 g_tcp_port_rdp = strtol(p + 1, NULL, 10);
339 astrand 444 *p = 0;
340     }
341     }
342     #else /* no IPv6 support */
343     p = strchr(server, ':');
344     if (p != NULL)
345     {
346 jsorg71 710 g_tcp_port_rdp = strtol(p + 1, NULL, 10);
347 astrand 444 *p = 0;
348     }
349     #endif /* IPv6 */
350    
351     }
352    
353 matty 10 /* Client program */
354 matty 25 int
355     main(int argc, char *argv[])
356 matty 10 {
357 matthewc 222 char server[64];
358 matty 30 char fullhostname[64];
359 matty 21 char domain[16];
360 astrand 479 char password[64];
361 astrand 238 char shell[128];
362 matty 21 char directory[32];
363 astrand 676 BOOL prompt_password, deactivated;
364 matty 30 struct passwd *pw;
365 astrand 676 uint32 flags, ext_disc_reason = 0;
366 matthewc 222 char *p;
367 matty 10 int c;
368 n-ki 569
369 astrand 289 int username_option = 0;
370 matty 10
371 matty 21 flags = RDP_LOGON_NORMAL;
372 matthewc 211 prompt_password = False;
373 matty 21 domain[0] = password[0] = shell[0] = directory[0] = 0;
374 matthewc 240 strcpy(keymapname, "en-us");
375 stargo 636 g_embed_wnd = 0;
376 matty 21
377 n-ki 569 g_num_devices = 0;
378    
379 astrand 333 #ifdef RDP2VNC
380 forsberg 471 #define VNCOPT "V:Q:"
381 astrand 333 #else
382     #define VNCOPT
383     #endif
384    
385 jsorg71 725 while ((c = getopt(argc, argv,
386 stargo 855 VNCOPT "u:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
387 matty 10 {
388     switch (c)
389     {
390 astrand 333 #ifdef RDP2VNC
391     case 'V':
392     rfb_port = strtol(optarg, NULL, 10);
393     if (rfb_port < 100)
394     rfb_port += 5900;
395     break;
396    
397 forsberg 471 case 'Q':
398 astrand 333 defer_time = strtol(optarg, NULL, 10);
399     if (defer_time < 0)
400     defer_time = 0;
401     break;
402     #endif
403    
404 matty 10 case 'u':
405 jsorg71 437 STRNCPY(g_username, optarg, sizeof(g_username));
406 astrand 289 username_option = 1;
407 matty 10 break;
408    
409 stargo 855 case 'L':
410     #ifdef HAVE_ICONV
411     STRNCPY(g_codepage, optarg, sizeof(g_codepage));
412     #else
413     error("iconv support not available\n");
414     #endif
415     break;
416    
417 matty 21 case 'd':
418 matty 30 STRNCPY(domain, optarg, sizeof(domain));
419 matty 21 break;
420    
421     case 's':
422 matty 30 STRNCPY(shell, optarg, sizeof(shell));
423 matty 21 break;
424    
425     case 'c':
426 matty 30 STRNCPY(directory, optarg, sizeof(directory));
427 matty 21 break;
428    
429 matty 30 case 'p':
430 matthewc 211 if ((optarg[0] == '-') && (optarg[1] == 0))
431     {
432     prompt_password = True;
433     break;
434     }
435    
436 matty 30 STRNCPY(password, optarg, sizeof(password));
437     flags |= RDP_LOGON_AUTO;
438 matthewc 211
439     /* try to overwrite argument so it won't appear in ps */
440 n-ki 171 p = optarg;
441     while (*p)
442     *(p++) = 'X';
443 matty 30 break;
444    
445 matty 10 case 'n':
446 jsorg71 710 STRNCPY(g_hostname, optarg, sizeof(g_hostname));
447 matty 10 break;
448    
449     case 'k':
450 astrand 82 STRNCPY(keymapname, optarg, sizeof(keymapname));
451 matty 10 break;
452    
453 matty 30 case 'g':
454 astrand 547 g_fullscreen = False;
455 astrand 263 if (!strcmp(optarg, "workarea"))
456     {
457 jsorg71 447 g_width = g_height = 0;
458 astrand 263 break;
459     }
460    
461 jsorg71 447 g_width = strtol(optarg, &p, 10);
462 astrand 500 if (g_width <= 0)
463     {
464     error("invalid geometry\n");
465     return 1;
466     }
467    
468 matty 30 if (*p == 'x')
469 stargo 800 g_height = strtol(p + 1, &p, 10);
470 matty 30
471 astrand 500 if (g_height <= 0)
472 matty 30 {
473     error("invalid geometry\n");
474     return 1;
475     }
476 astrand 500
477     if (*p == '%')
478 stargo 800 {
479 astrand 500 g_width = -g_width;
480 stargo 800 p++;
481     }
482 astrand 500
483 stargo 800 if (*p == '+' || *p == '-')
484     g_xpos = strtol(p, &p, 10);
485 astrand 801
486 stargo 800 if (*p == '+' || *p == '-')
487     g_ypos = strtol(p, NULL, 10);
488    
489 matty 10 break;
490    
491 matty 30 case 'f':
492 jsorg71 447 g_fullscreen = True;
493 matty 30 break;
494    
495 matty 10 case 'b':
496 jsorg71 678 g_bitmap_cache = False;
497 matty 10 break;
498    
499 stargo 609 case 'B':
500     g_ownbackstore = False;
501     break;
502    
503 matty 30 case 'e':
504 jsorg71 437 g_encryption = False;
505 matty 10 break;
506 astrand 435 case 'E':
507 forsberg 427 packet_encryption = False;
508     break;
509 matty 30 case 'm':
510 jsorg71 447 g_sendmotion = False;
511 matty 28 break;
512 matty 29
513 n-ki 279 case 'C':
514 jsorg71 450 g_owncolmap = True;
515 n-ki 279 break;
516    
517 matthewc 520 case 'D':
518     g_hide_decorations = True;
519     break;
520    
521 astrand 76 case 'K':
522 jsorg71 450 g_grab_keyboard = False;
523 astrand 76 break;
524    
525 matthewc 520 case 'S':
526     if (!strcmp(optarg, "standard"))
527     {
528     g_win_button_size = 18;
529     break;
530     }
531    
532     g_win_button_size = strtol(optarg, &p, 10);
533    
534     if (*p)
535     {
536     error("invalid button size\n");
537     return 1;
538     }
539    
540     break;
541    
542 matthewc 223 case 'T':
543 jsorg71 450 STRNCPY(g_title, optarg, sizeof(g_title));
544 astrand 107 break;
545    
546 astrand 552 case 'N':
547     g_numlock_sync = True;
548     break;
549    
550 stargo 636 case 'X':
551     g_embed_wnd = strtol(optarg, NULL, 10);
552     break;
553 astrand 651
554 jsorg71 309 case 'a':
555 jsorg71 438 g_server_bpp = strtol(optarg, NULL, 10);
556     if (g_server_bpp != 8 && g_server_bpp != 16 && g_server_bpp != 15
557     && g_server_bpp != 24)
558 jsorg71 309 {
559     error("invalid server bpp\n");
560     return 1;
561     }
562     break;
563    
564 jsorg71 773 case 'z':
565     DEBUG(("rdp compression enabled\n"));
566     flags |= RDP_COMPRESSION;
567     break;
568    
569 stargo 637 case 'x':
570     if (strncmp("modem", optarg, 1) == 0)
571     {
572 astrand 651 g_rdp5_performanceflags =
573     RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
574     RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
575 stargo 637 }
576     else if (strncmp("broadband", optarg, 1) == 0)
577     {
578     g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
579     }
580     else if (strncmp("lan", optarg, 1) == 0)
581     {
582     g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;
583     }
584     else
585     {
586     g_rdp5_performanceflags = strtol(optarg, NULL, 16);
587     }
588     break;
589 astrand 651
590 jsorg71 725 case 'P':
591     g_bitmap_cache_persist_enable = True;
592     break;
593    
594 matthewc 520 case 'r':
595 n-ki 569
596     if (strncmp("sound", optarg, 5) == 0)
597     {
598 n-ki 629 optarg += 5;
599    
600     if (*optarg == ':')
601 n-ki 628 {
602 n-ki 629 *optarg++;
603     while ((p = next_arg(optarg, ',')))
604     {
605     if (strncmp("remote", optarg, 6) == 0)
606     flags |= RDP_LOGON_LEAVE_AUDIO;
607 n-ki 628
608 n-ki 630 if (strncmp("local", optarg, 5) == 0)
609 stargo 501 #ifdef WITH_RDPSND
610 n-ki 629 g_rdpsnd = True;
611 matthewc 520 #else
612 stargo 739 warning("Not compiled with sound support\n");
613 matthewc 520 #endif
614 n-ki 629
615     if (strncmp("off", optarg, 3) == 0)
616 stargo 685 #ifdef WITH_RDPSND
617 n-ki 629 g_rdpsnd = False;
618 stargo 685 #else
619 stargo 739 warning("Not compiled with sound support\n");
620 stargo 685 #endif
621 n-ki 629
622     optarg = p;
623 n-ki 628 }
624     }
625     else
626     {
627     #ifdef WITH_RDPSND
628     g_rdpsnd = True;
629     #else
630 stargo 739 warning("Not compiled with sound support\n");
631 n-ki 628 #endif
632     }
633 n-ki 569 }
634     else if (strncmp("disk", optarg, 4) == 0)
635     {
636     /* -r disk:h:=/mnt/floppy */
637     disk_enum_devices(&g_num_devices, optarg + 4);
638     }
639     else if (strncmp("comport", optarg, 7) == 0)
640     {
641     serial_enum_devices(&g_num_devices, optarg + 7);
642     }
643     else if (strncmp("lptport", optarg, 7) == 0)
644     {
645     parallel_enum_devices(&g_num_devices, optarg + 7);
646     }
647     else if (strncmp("printer", optarg, 7) == 0)
648     {
649     printer_enum_devices(&g_num_devices, optarg + 7);
650     }
651 forsberg 646 else if (strncmp("clientname", optarg, 7) == 0)
652     {
653 astrand 651 g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
654 forsberg 646 strcpy(g_rdpdr_clientname, optarg + 11);
655     }
656 n-ki 569 else
657     {
658     warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound\n");
659     }
660 stargo 501 break;
661 matthewc 520
662 matthewc 482 case '0':
663     g_console_session = True;
664     break;
665    
666 astrand 458 case '4':
667     g_use_rdp5 = False;
668     break;
669    
670 forsberg 350 case '5':
671 jsorg71 438 g_use_rdp5 = True;
672 forsberg 350 break;
673 astrand 458
674 matty 28 case 'h':
675 matty 10 case '?':
676     default:
677     usage(argv[0]);
678     return 1;
679     }
680     }
681    
682 stargo 610 if (argc - optind != 1)
683 matty 10 {
684     usage(argv[0]);
685     return 1;
686     }
687    
688 matthewc 222 STRNCPY(server, argv[optind], sizeof(server));
689 astrand 444 parse_server_and_port(server);
690 matty 10
691 astrand 289 if (!username_option)
692 matty 10 {
693     pw = getpwuid(getuid());
694     if ((pw == NULL) || (pw->pw_name == NULL))
695     {
696 matty 30 error("could not determine username, use -u\n");
697 matty 10 return 1;
698     }
699    
700 jsorg71 437 STRNCPY(g_username, pw->pw_name, sizeof(g_username));
701 matty 10 }
702    
703 stargo 855 #ifdef HAVE_ICONV
704     if (g_codepage[0] == 0)
705     {
706     if (setlocale(LC_CTYPE, ""))
707     {
708     STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
709     }
710     else
711     {
712     STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
713     }
714     }
715     #endif
716    
717 jsorg71 710 if (g_hostname[0] == 0)
718 matty 10 {
719 matty 30 if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
720 matty 10 {
721 matty 30 error("could not determine local hostname, use -n\n");
722 matty 10 return 1;
723     }
724 matty 30
725     p = strchr(fullhostname, '.');
726     if (p != NULL)
727     *p = 0;
728    
729 jsorg71 710 STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
730 matty 10 }
731    
732 stargo 825 if ((flags & RDP_COMPRESSION) && (g_server_bpp > 8))
733     {
734     warning("rdp compression not supported for bpp > 8, compression disabled\n");
735     flags ^= RDP_COMPRESSION;
736     }
737    
738 matthewc 211 if (prompt_password && read_password(password, sizeof(password)))
739     flags |= RDP_LOGON_AUTO;
740 matty 30
741 jsorg71 450 if (g_title[0] == 0)
742 astrand 107 {
743 jsorg71 450 strcpy(g_title, "rdesktop - ");
744     strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
745 astrand 107 }
746 matty 12
747 astrand 333 #ifdef RDP2VNC
748     rdp2vnc_connect(server, flags, domain, password, shell, directory);
749 forsberg 424 return 0;
750 astrand 333 #else
751    
752 astrand 82 if (!ui_init())
753     return 1;
754 astrand 66
755 matthewc 474 #ifdef WITH_RDPSND
756 stargo 501 if (g_rdpsnd)
757     rdpsnd_init();
758 matthewc 474 #endif
759 n-ki 569 rdpdr_init();
760 forsberg 416
761 matthewc 53 if (!rdp_connect(server, flags, domain, password, shell, directory))
762     return 1;
763    
764 forsberg 427 /* By setting encryption to False here, we have an encrypted login
765     packet but unencrypted transfer of other packets */
766 astrand 435 if (!packet_encryption)
767 jsorg71 437 g_encryption = False;
768 forsberg 427
769    
770 matthewc 122 DEBUG(("Connection successful.\n"));
771 matthewc 211 memset(password, 0, sizeof(password));
772 matthewc 53
773 jsorg71 100 if (ui_create_window())
774 matty 10 {
775 astrand 676 rdp_main_loop(&deactivated, &ext_disc_reason);
776 matty 10 ui_destroy_window();
777     }
778    
779 matthewc 122 DEBUG(("Disconnecting...\n"));
780 jsorg71 730 rdp_disconnect();
781 jsorg71 725 cache_save_state();
782 matthewc 188 ui_deinit();
783 astrand 333
784 astrand 676 if (ext_disc_reason >= 2)
785     print_disconnect_reason(ext_disc_reason);
786    
787     if (deactivated)
788     {
789     /* clean disconnect */
790 forsberg 424 return 0;
791 astrand 676 }
792 forsberg 424 else
793 astrand 676 {
794     if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
795     || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
796     {
797     /* not so clean disconnect, but nothing to worry about */
798     return 0;
799     }
800     else
801     {
802     /* return error */
803     return 2;
804     }
805     }
806 forsberg 424
807 astrand 333 #endif
808    
809 matty 10 }
810    
811 matthewc 220 #ifdef EGD_SOCKET
812     /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
813     static BOOL
814     generate_random_egd(uint8 * buf)
815     {
816     struct sockaddr_un addr;
817     BOOL ret = False;
818     int fd;
819    
820     fd = socket(AF_UNIX, SOCK_STREAM, 0);
821     if (fd == -1)
822     return False;
823    
824     addr.sun_family = AF_UNIX;
825     memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
826 astrand 259 if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
827 matthewc 220 goto err;
828    
829     /* PRNGD and EGD use a simple communications protocol */
830 astrand 259 buf[0] = 1; /* Non-blocking (similar to /dev/urandom) */
831     buf[1] = 32; /* Number of requested random bytes */
832 matthewc 220 if (write(fd, buf, 2) != 2)
833     goto err;
834    
835 astrand 259 if ((read(fd, buf, 1) != 1) || (buf[0] == 0)) /* Available? */
836 matthewc 220 goto err;
837    
838     if (read(fd, buf, 32) != 32)
839     goto err;
840    
841     ret = True;
842    
843 astrand 259 err:
844 matthewc 220 close(fd);
845     return ret;
846     }
847     #endif
848    
849 matty 10 /* Generate a 32-byte random for the secure transport code. */
850 matty 25 void
851 astrand 64 generate_random(uint8 * random)
852 matty 10 {
853     struct stat st;
854 matty 22 struct tms tmsbuf;
855 matthewc 220 MD5_CTX md5;
856     uint32 *r;
857     int fd, n;
858 matty 10
859 matthewc 220 /* If we have a kernel random device, try that first */
860 matty 30 if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
861     || ((fd = open("/dev/random", O_RDONLY)) != -1))
862 matty 10 {
863 matthewc 220 n = read(fd, random, 32);
864 matty 10 close(fd);
865 matthewc 220 if (n == 32)
866     return;
867 matty 10 }
868    
869 matthewc 220 #ifdef EGD_SOCKET
870     /* As a second preference use an EGD */
871     if (generate_random_egd(random))
872     return;
873     #endif
874    
875 matty 10 /* Otherwise use whatever entropy we can gather - ideas welcome. */
876 astrand 259 r = (uint32 *) random;
877 matty 10 r[0] = (getpid()) | (getppid() << 16);
878     r[1] = (getuid()) | (getgid() << 16);
879 matty 24 r[2] = times(&tmsbuf); /* system uptime (clocks) */
880     gettimeofday((struct timeval *) &r[3], NULL); /* sec and usec */
881 matty 10 stat("/tmp", &st);
882     r[5] = st.st_atime;
883     r[6] = st.st_mtime;
884     r[7] = st.st_ctime;
885 matthewc 220
886     /* Hash both halves with MD5 to obscure possible patterns */
887     MD5_Init(&md5);
888 astrand 259 MD5_Update(&md5, random, 16);
889 matthewc 220 MD5_Final(random, &md5);
890 astrand 259 MD5_Update(&md5, random + 16, 16);
891     MD5_Final(random + 16, &md5);
892 matty 10 }
893    
894     /* malloc; exit if out of memory */
895 matty 25 void *
896     xmalloc(int size)
897 matty 10 {
898     void *mem = malloc(size);
899     if (mem == NULL)
900     {
901 matty 30 error("xmalloc %d\n", size);
902 matty 10 exit(1);
903     }
904     return mem;
905     }
906    
907     /* realloc; exit if out of memory */
908 matty 25 void *
909     xrealloc(void *oldmem, int size)
910 matty 10 {
911 astrand 782 void *mem;
912 jsorg71 773
913     if (size < 1)
914     size = 1;
915     mem = realloc(oldmem, size);
916 matty 10 if (mem == NULL)
917     {
918 matty 30 error("xrealloc %d\n", size);
919 matty 10 exit(1);
920     }
921     return mem;
922     }
923    
924     /* free */
925 matty 25 void
926     xfree(void *mem)
927 matty 10 {
928     free(mem);
929     }
930    
931 matty 30 /* report an error */
932 matty 25 void
933 matty 30 error(char *format, ...)
934     {
935     va_list ap;
936    
937     fprintf(stderr, "ERROR: ");
938    
939     va_start(ap, format);
940     vfprintf(stderr, format, ap);
941     va_end(ap);
942     }
943    
944 matthewc 297 /* report a warning */
945     void
946     warning(char *format, ...)
947     {
948     va_list ap;
949    
950     fprintf(stderr, "WARNING: ");
951    
952     va_start(ap, format);
953     vfprintf(stderr, format, ap);
954     va_end(ap);
955     }
956    
957 matty 30 /* report an unimplemented protocol feature */
958     void
959     unimpl(char *format, ...)
960     {
961     va_list ap;
962    
963     fprintf(stderr, "NOT IMPLEMENTED: ");
964    
965     va_start(ap, format);
966     vfprintf(stderr, format, ap);
967     va_end(ap);
968     }
969    
970     /* produce a hex dump */
971     void
972 n-ki 569 hexdump(unsigned char *p, unsigned int len)
973 matty 10 {
974     unsigned char *line = p;
975 jsorg71 376 int i, thisline, offset = 0;
976 matty 10
977     while (offset < len)
978     {
979 matthewc 169 printf("%04x ", offset);
980 matty 10 thisline = len - offset;
981     if (thisline > 16)
982     thisline = 16;
983    
984     for (i = 0; i < thisline; i++)
985 matthewc 169 printf("%02x ", line[i]);
986 matty 10
987 matty 30 for (; i < 16; i++)
988 matthewc 169 printf(" ");
989 matty 30
990 matty 10 for (i = 0; i < thisline; i++)
991 matthewc 169 printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
992 matty 10
993 matthewc 169 printf("\n");
994 matty 10 offset += thisline;
995     line += thisline;
996     }
997     }
998 astrand 325
999 n-ki 569 /*
1000 n-ki 583 input: src is the string we look in for needle.
1001     Needle may be escaped by a backslash, in
1002     that case we ignore that particular needle.
1003 n-ki 569 return value: returns next src pointer, for
1004     succesive executions, like in a while loop
1005     if retval is 0, then there are no more args.
1006     pitfalls:
1007     src is modified. 0x00 chars are inserted to
1008     terminate strings.
1009     return val, points on the next val chr after ins
1010     0x00
1011 astrand 325
1012 n-ki 569 example usage:
1013     while( (pos = next_arg( optarg, ',')) ){
1014     printf("%s\n",optarg);
1015     optarg=pos;
1016     }
1017    
1018     */
1019     char *
1020     next_arg(char *src, char needle)
1021     {
1022     char *nextval;
1023 n-ki 571 char *p;
1024 n-ki 575 char *mvp = 0;
1025 n-ki 569
1026 n-ki 575 /* EOS */
1027 n-ki 569 if (*src == (char) 0x00)
1028     return 0;
1029    
1030 n-ki 571 p = src;
1031 n-ki 575 /* skip escaped needles */
1032 astrand 580 while ((nextval = strchr(p, needle)))
1033 n-ki 571 {
1034 n-ki 575 mvp = nextval - 1;
1035     /* found backslashed needle */
1036 astrand 580 if (*mvp == '\\' && (mvp > src))
1037 n-ki 575 {
1038     /* move string one to the left */
1039 astrand 580 while (*(mvp + 1) != (char) 0x00)
1040 n-ki 575 {
1041 astrand 580 *mvp = *(mvp + 1);
1042 n-ki 575 *mvp++;
1043     }
1044 astrand 580 *mvp = (char) 0x00;
1045 n-ki 575 p = nextval;
1046     }
1047     else
1048     {
1049 astrand 580 p = nextval + 1;
1050 n-ki 571 break;
1051 n-ki 575 }
1052    
1053 n-ki 571 }
1054    
1055 n-ki 575 /* more args available */
1056 n-ki 569 if (nextval)
1057     {
1058     *nextval = (char) 0x00;
1059     return ++nextval;
1060     }
1061    
1062 n-ki 575 /* no more args after this, jump to EOS */
1063 n-ki 569 nextval = src + strlen(src);
1064     return nextval;
1065     }
1066    
1067    
1068 stargo 570 void
1069 astrand 580 toupper_str(char *p)
1070 n-ki 569 {
1071 astrand 580 while (*p)
1072     {
1073     if ((*p >= 'a') && (*p <= 'z'))
1074 stargo 570 *p = toupper((int) *p);
1075 n-ki 569 p++;
1076     }
1077     }
1078    
1079    
1080     /* not all clibs got ltoa */
1081     #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1082    
1083     char *
1084 stargo 603 l_to_a(long N, int base)
1085 n-ki 569 {
1086     static char ret[LTOA_BUFSIZE];
1087    
1088 n-ki 583 char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1089 n-ki 569
1090 n-ki 583 register int divrem;
1091    
1092     if (base < 36 || 2 > base)
1093 n-ki 569 base = 10;
1094    
1095 n-ki 583 if (N < 0)
1096 n-ki 569 {
1097     *head++ = '-';
1098 n-ki 583 N = -N;
1099 n-ki 569 }
1100    
1101 n-ki 583 tail = buf + sizeof(buf);
1102     *--tail = 0;
1103    
1104     do
1105 n-ki 569 {
1106 n-ki 583 divrem = N % base;
1107     *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1108     N /= base;
1109 n-ki 569 }
1110 n-ki 583 while (N);
1111 n-ki 569
1112 n-ki 583 strcpy(head, tail);
1113 n-ki 569 return ret;
1114     }
1115    
1116    
1117 astrand 325 int
1118     load_licence(unsigned char **data)
1119     {
1120 matthewc 367 char *home, *path;
1121 astrand 325 struct stat st;
1122 matthewc 367 int fd, length;
1123 astrand 325
1124     home = getenv("HOME");
1125     if (home == NULL)
1126     return -1;
1127    
1128 jsorg71 710 path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1129     sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1130 astrand 325
1131     fd = open(path, O_RDONLY);
1132     if (fd == -1)
1133     return -1;
1134    
1135     if (fstat(fd, &st))
1136     return -1;
1137    
1138 forsberg 416 *data = (uint8 *) xmalloc(st.st_size);
1139 matthewc 367 length = read(fd, *data, st.st_size);
1140     close(fd);
1141     xfree(path);
1142     return length;
1143 astrand 325 }
1144    
1145     void
1146     save_licence(unsigned char *data, int length)
1147     {
1148 matthewc 367 char *home, *path, *tmppath;
1149     int fd;
1150 astrand 325
1151     home = getenv("HOME");
1152     if (home == NULL)
1153     return;
1154    
1155 jsorg71 710 path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1156 astrand 325
1157 matthewc 367 sprintf(path, "%s/.rdesktop", home);
1158     if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1159 astrand 325 {
1160 matthewc 367 perror(path);
1161     return;
1162 astrand 325 }
1163    
1164 matthewc 367 /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1165 astrand 325
1166 jsorg71 710 sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1167 forsberg 416 tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1168 matthewc 367 strcpy(tmppath, path);
1169     strcat(tmppath, ".new");
1170    
1171 forsberg 416 fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1172 matthewc 367 if (fd == -1)
1173 astrand 325 {
1174 matthewc 367 perror(tmppath);
1175     return;
1176 astrand 325 }
1177    
1178 matthewc 367 if (write(fd, data, length) != length)
1179 astrand 325 {
1180 matthewc 367 perror(tmppath);
1181     unlink(tmppath);
1182 astrand 325 }
1183 matthewc 367 else if (rename(tmppath, path) == -1)
1184 astrand 325 {
1185 matthewc 367 perror(path);
1186     unlink(tmppath);
1187 astrand 325 }
1188    
1189 matthewc 367 close(fd);
1190     xfree(tmppath);
1191     xfree(path);
1192 astrand 325 }
1193 jsorg71 725
1194     /* Create the bitmap cache directory */
1195     BOOL
1196     rd_pstcache_mkdir(void)
1197     {
1198     char *home;
1199     char bmpcache_dir[256];
1200    
1201     home = getenv("HOME");
1202    
1203     if (home == NULL)
1204     return False;
1205    
1206     sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1207    
1208     if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1209     {
1210     perror(bmpcache_dir);
1211     return False;
1212     }
1213    
1214     sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1215    
1216     if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1217     {
1218     perror(bmpcache_dir);
1219     return False;
1220     }
1221    
1222     return True;
1223     }
1224    
1225     /* open a file in the .rdesktop directory */
1226     int
1227     rd_open_file(char *filename)
1228     {
1229     char *home;
1230     char fn[256];
1231 astrand 738 int fd;
1232 jsorg71 725
1233     home = getenv("HOME");
1234     if (home == NULL)
1235     return -1;
1236     sprintf(fn, "%s/.rdesktop/%s", home, filename);
1237     fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1238     if (fd == -1)
1239     perror(fn);
1240     return fd;
1241     }
1242    
1243     /* close file */
1244     void
1245     rd_close_file(int fd)
1246     {
1247 astrand 738 close(fd);
1248 jsorg71 725 }
1249    
1250     /* read from file*/
1251     int
1252     rd_read_file(int fd, void *ptr, int len)
1253     {
1254 astrand 738 return read(fd, ptr, len);
1255 jsorg71 725 }
1256    
1257     /* write to file */
1258     int
1259 astrand 738 rd_write_file(int fd, void *ptr, int len)
1260 jsorg71 725 {
1261 astrand 738 return write(fd, ptr, len);
1262 jsorg71 725 }
1263    
1264     /* move file pointer */
1265     int
1266     rd_lseek_file(int fd, int offset)
1267     {
1268 astrand 738 return lseek(fd, offset, SEEK_SET);
1269 jsorg71 725 }
1270    
1271     /* do a write lock on a file */
1272     BOOL
1273     rd_lock_file(int fd, int start, int len)
1274     {
1275     struct flock lock;
1276    
1277     lock.l_type = F_WRLCK;
1278     lock.l_whence = SEEK_SET;
1279     lock.l_start = start;
1280     lock.l_len = len;
1281     if (fcntl(fd, F_SETLK, &lock) == -1)
1282     return False;
1283     return True;
1284     }

  ViewVC Help
Powered by ViewVC 1.1.26