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

Legend:
Removed from v.79  
changed lines
  Added in v.825

  ViewVC Help
Powered by ViewVC 1.1.26