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

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

  ViewVC Help
Powered by ViewVC 1.1.26