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

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

  ViewVC Help
Powered by ViewVC 1.1.26