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

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

  ViewVC Help
Powered by ViewVC 1.1.26