/[rdesktop]/sourceforge.net/trunk/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

Diff of /sourceforge.net/trunk/rdesktop/rdesktop.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.29  
changed lines
  Added in v.747

  ViewVC Help
Powered by ViewVC 1.1.26