/[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 800 by stargo, Thu Nov 18 11:18:49 2004 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Entrypoint and utility functions     Entrypoint and utility functions
4     Copyright (C) Matthew Chapman 1999-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 (prompt_password && read_password(password, sizeof(password)))
694          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
695    
696          if ((width == 0) || (height == 0))          if (g_title[0] == 0)
697          {          {
698                  width = 800;                  strcpy(g_title, "rdesktop - ");
699                  height = 600;                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
700          }          }
701    
702          strcpy(title, "rdesktop - ");  #ifdef RDP2VNC
703          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          rdp2vnc_connect(server, flags, domain, password, shell, directory);
704            return 0;
705    #else
706    
707            if (!ui_init())
708                    return 1;
709    
710          xkeymap_init1();  #ifdef WITH_RDPSND
711            if (g_rdpsnd)
712                    rdpsnd_init();
713    #endif
714            rdpdr_init();
715    
716          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
717                  return 1;                  return 1;
718    
719          printf("Connection successful.\n");          /* By setting encryption to False here, we have an encrypted login
720               packet but unencrypted transfer of other packets */
721            if (!packet_encryption)
722                    g_encryption = False;
723    
724    
725            DEBUG(("Connection successful.\n"));
726            memset(password, 0, sizeof(password));
727    
728          if (ui_create_window(title))          if (ui_create_window())
729          {          {
730                  rdp_main_loop();                  rdp_main_loop(&deactivated, &ext_disc_reason);
731                  ui_destroy_window();                  ui_destroy_window();
732          }          }
733    
734          printf("Disconnecting...\n");          DEBUG(("Disconnecting...\n"));
735          rdp_disconnect();          rdp_disconnect();
736          return 0;          cache_save_state();
737            ui_deinit();
738    
739            if (ext_disc_reason >= 2)
740                    print_disconnect_reason(ext_disc_reason);
741    
742            if (deactivated)
743            {
744                    /* clean disconnect */
745                    return 0;
746            }
747            else
748            {
749                    if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
750                        || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
751                    {
752                            /* not so clean disconnect, but nothing to worry about */
753                            return 0;
754                    }
755                    else
756                    {
757                            /* return error */
758                            return 2;
759                    }
760            }
761    
762    #endif
763    
764    }
765    
766    #ifdef EGD_SOCKET
767    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
768    static BOOL
769    generate_random_egd(uint8 * buf)
770    {
771            struct sockaddr_un addr;
772            BOOL ret = False;
773            int fd;
774    
775            fd = socket(AF_UNIX, SOCK_STREAM, 0);
776            if (fd == -1)
777                    return False;
778    
779            addr.sun_family = AF_UNIX;
780            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
781            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
782                    goto err;
783    
784            /* PRNGD and EGD use a simple communications protocol */
785            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
786            buf[1] = 32;            /* Number of requested random bytes */
787            if (write(fd, buf, 2) != 2)
788                    goto err;
789    
790            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
791                    goto err;
792    
793            if (read(fd, buf, 32) != 32)
794                    goto err;
795    
796            ret = True;
797    
798          err:
799            close(fd);
800            return ret;
801  }  }
802    #endif
803    
804  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
805  void  void
# Line 252  generate_random(uint8 * random) Line 807  generate_random(uint8 * random)
807  {  {
808          struct stat st;          struct stat st;
809          struct tms tmsbuf;          struct tms tmsbuf;
810          uint32 *r = (uint32 *) random;          MD5_CTX md5;
811          int fd;          uint32 *r;
812            int fd, n;
813    
814          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
815          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
816              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
817          {          {
818                  read(fd, random, 32);                  n = read(fd, random, 32);
819                  close(fd);                  close(fd);
820                  return;                  if (n == 32)
821                            return;
822          }          }
823    
824    #ifdef EGD_SOCKET
825            /* As a second preference use an EGD */
826            if (generate_random_egd(random))
827                    return;
828    #endif
829    
830          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
831            r = (uint32 *) random;
832          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
833          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
834          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 273  generate_random(uint8 * random) Line 837  generate_random(uint8 * random)
837          r[5] = st.st_atime;          r[5] = st.st_atime;
838          r[6] = st.st_mtime;          r[6] = st.st_mtime;
839          r[7] = st.st_ctime;          r[7] = st.st_ctime;
840    
841            /* Hash both halves with MD5 to obscure possible patterns */
842            MD5_Init(&md5);
843            MD5_Update(&md5, random, 16);
844            MD5_Final(random, &md5);
845            MD5_Update(&md5, random + 16, 16);
846            MD5_Final(random + 16, &md5);
847  }  }
848    
849  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 292  xmalloc(int size) Line 863  xmalloc(int size)
863  void *  void *
864  xrealloc(void *oldmem, int size)  xrealloc(void *oldmem, int size)
865  {  {
866          void *mem = realloc(oldmem, size);          void *mem;
867    
868            if (size < 1)
869                    size = 1;
870            mem = realloc(oldmem, size);
871          if (mem == NULL)          if (mem == NULL)
872          {          {
873                  error("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
# Line 321  error(char *format, ...) Line 896  error(char *format, ...)
896          va_end(ap);          va_end(ap);
897  }  }
898    
899    /* report a warning */
900    void
901    warning(char *format, ...)
902    {
903            va_list ap;
904    
905            fprintf(stderr, "WARNING: ");
906    
907            va_start(ap, format);
908            vfprintf(stderr, format, ap);
909            va_end(ap);
910    }
911    
912  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
913  void  void
914  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 339  void Line 927  void
927  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, unsigned int len)
928  {  {
929          unsigned char *line = p;          unsigned char *line = p;
930          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
931    
932          while (offset < len)          while (offset < len)
933          {          {
# Line 356  hexdump(unsigned char *p, unsigned int l Line 943  hexdump(unsigned char *p, unsigned int l
943                          printf("   ");                          printf("   ");
944    
945                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
946                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
947    
948                  printf("\n");                  printf("\n");
949                  offset += thisline;                  offset += thisline;
# Line 366  hexdump(unsigned char *p, unsigned int l Line 951  hexdump(unsigned char *p, unsigned int l
951          }          }
952  }  }
953    
954    /*
955      input: src is the string we look in for needle.
956             Needle may be escaped by a backslash, in
957             that case we ignore that particular needle.
958      return value: returns next src pointer, for
959            succesive executions, like in a while loop
960            if retval is 0, then there are no more args.
961      pitfalls:
962            src is modified. 0x00 chars are inserted to
963            terminate strings.
964            return val, points on the next val chr after ins
965            0x00
966    
967            example usage:
968            while( (pos = next_arg( optarg, ',')) ){
969                    printf("%s\n",optarg);
970                    optarg=pos;
971            }
972    
973    */
974    char *
975    next_arg(char *src, char needle)
976    {
977            char *nextval;
978            char *p;
979            char *mvp = 0;
980    
981            /* EOS */
982            if (*src == (char) 0x00)
983                    return 0;
984    
985            p = src;
986            /*  skip escaped needles */
987            while ((nextval = strchr(p, needle)))
988            {
989                    mvp = nextval - 1;
990                    /* found backslashed needle */
991                    if (*mvp == '\\' && (mvp > src))
992                    {
993                            /* move string one to the left */
994                            while (*(mvp + 1) != (char) 0x00)
995                            {
996                                    *mvp = *(mvp + 1);
997                                    *mvp++;
998                            }
999                            *mvp = (char) 0x00;
1000                            p = nextval;
1001                    }
1002                    else
1003                    {
1004                            p = nextval + 1;
1005                            break;
1006                    }
1007    
1008            }
1009    
1010            /* more args available */
1011            if (nextval)
1012            {
1013                    *nextval = (char) 0x00;
1014                    return ++nextval;
1015            }
1016    
1017            /* no more args after this, jump to EOS */
1018            nextval = src + strlen(src);
1019            return nextval;
1020    }
1021    
1022    
1023    void
1024    toupper_str(char *p)
1025    {
1026            while (*p)
1027            {
1028                    if ((*p >= 'a') && (*p <= 'z'))
1029                            *p = toupper((int) *p);
1030                    p++;
1031            }
1032    }
1033    
1034    
1035    /* not all clibs got ltoa */
1036    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1037    
1038    char *
1039    l_to_a(long N, int base)
1040    {
1041            static char ret[LTOA_BUFSIZE];
1042    
1043            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1044    
1045            register int divrem;
1046    
1047            if (base < 36 || 2 > base)
1048                    base = 10;
1049    
1050            if (N < 0)
1051            {
1052                    *head++ = '-';
1053                    N = -N;
1054            }
1055    
1056            tail = buf + sizeof(buf);
1057            *--tail = 0;
1058    
1059            do
1060            {
1061                    divrem = N % base;
1062                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1063                    N /= base;
1064            }
1065            while (N);
1066    
1067            strcpy(head, tail);
1068            return ret;
1069    }
1070    
1071    
1072  int  int
1073  load_licence(unsigned char **data)  load_licence(unsigned char **data)
1074  {  {
1075          char path[PATH_MAX];          char *home, *path;
         char *home;  
1076          struct stat st;          struct stat st;
1077          int fd;          int fd, length;
1078    
1079          home = getenv("HOME");          home = getenv("HOME");
1080          if (home == NULL)          if (home == NULL)
1081                  return -1;                  return -1;
1082    
1083          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1084          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1085    
1086          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
1087          if (fd == -1)          if (fd == -1)
# Line 388  load_licence(unsigned char **data) Line 1090  load_licence(unsigned char **data)
1090          if (fstat(fd, &st))          if (fstat(fd, &st))
1091                  return -1;                  return -1;
1092    
1093          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
1094          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
1095            close(fd);
1096            xfree(path);
1097            return length;
1098  }  }
1099    
1100  void  void
1101  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
1102  {  {
1103          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
1104          int fd;          int fd;
1105    
1106          home = getenv("HOME");          home = getenv("HOME");
1107          if (home == NULL)          if (home == NULL)
1108                  return;                  return;
1109    
1110          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1111          strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);  
1112          mkdir(path, 0700);          sprintf(path, "%s/.rdesktop", home);
1113            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1114            {
1115                    perror(path);
1116                    return;
1117            }
1118    
1119            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1120    
1121          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1122            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1123            strcpy(tmppath, path);
1124            strcat(tmppath, ".new");
1125    
1126          fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1127          if (fd == -1)          if (fd == -1)
1128          {          {
1129                  perror("open");                  perror(tmppath);
1130                  return;                  return;
1131          }          }
1132    
1133          write(fd, data, length);          if (write(fd, data, length) != length)
1134            {
1135                    perror(tmppath);
1136                    unlink(tmppath);
1137            }
1138            else if (rename(tmppath, path) == -1)
1139            {
1140                    perror(path);
1141                    unlink(tmppath);
1142            }
1143    
1144            close(fd);
1145            xfree(tmppath);
1146            xfree(path);
1147    }
1148    
1149    /* Create the bitmap cache directory */
1150    BOOL
1151    rd_pstcache_mkdir(void)
1152    {
1153            char *home;
1154            char bmpcache_dir[256];
1155    
1156            home = getenv("HOME");
1157    
1158            if (home == NULL)
1159                    return False;
1160    
1161            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1162    
1163            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1164            {
1165                    perror(bmpcache_dir);
1166                    return False;
1167            }
1168    
1169            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1170    
1171            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1172            {
1173                    perror(bmpcache_dir);
1174                    return False;
1175            }
1176    
1177            return True;
1178    }
1179    
1180    /* open a file in the .rdesktop directory */
1181    int
1182    rd_open_file(char *filename)
1183    {
1184            char *home;
1185            char fn[256];
1186            int fd;
1187    
1188            home = getenv("HOME");
1189            if (home == NULL)
1190                    return -1;
1191            sprintf(fn, "%s/.rdesktop/%s", home, filename);
1192            fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1193            if (fd == -1)
1194                    perror(fn);
1195            return fd;
1196    }
1197    
1198    /* close file */
1199    void
1200    rd_close_file(int fd)
1201    {
1202          close(fd);          close(fd);
1203  }  }
1204    
1205    /* read from file*/
1206    int
1207    rd_read_file(int fd, void *ptr, int len)
1208    {
1209            return read(fd, ptr, len);
1210    }
1211    
1212    /* write to file */
1213    int
1214    rd_write_file(int fd, void *ptr, int len)
1215    {
1216            return write(fd, ptr, len);
1217    }
1218    
1219    /* move file pointer */
1220    int
1221    rd_lseek_file(int fd, int offset)
1222    {
1223            return lseek(fd, offset, SEEK_SET);
1224    }
1225    
1226    /* do a write lock on a file */
1227    BOOL
1228    rd_lock_file(int fd, int start, int len)
1229    {
1230            struct flock lock;
1231    
1232            lock.l_type = F_WRLCK;
1233            lock.l_whence = SEEK_SET;
1234            lock.l_start = start;
1235            lock.l_len = len;
1236            if (fcntl(fd, F_SETLK, &lock) == -1)
1237                    return False;
1238            return True;
1239    }

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

  ViewVC Help
Powered by ViewVC 1.1.26