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

Legend:
Removed from v.39  
changed lines
  Added in v.782

  ViewVC Help
Powered by ViewVC 1.1.26