/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/rdesktop.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 53 by matthewc, Tue May 28 11:48:55 2002 UTC revision 710 by jsorg71, Tue Jun 15 22:17:08 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    #ifdef WITH_OPENSSL
39    #include <openssl/md5.h>
40    #else
41    #include "crypto/md5.h"
42    #endif
43    
44    char g_title[64] = "";
45    char g_username[64];
46    char g_hostname[16];
47  char keymapname[16];  char keymapname[16];
48  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;  
49    
50    int g_width = 800;              /* width is special: If 0, the
51                                       geometry will be fetched from
52                                       _NET_WORKAREA. If negative,
53                                       absolute value specifies the
54                                       percent of the whole screen. */
55    int g_height = 600;
56    extern int g_tcp_port_rdp;
57    int g_server_bpp = 8;
58    int g_win_button_size = 0;      /* If zero, disable single app mode */
59    BOOL g_bitmap_compression = True;
60    BOOL g_sendmotion = True;
61    BOOL g_bitmap_cache = True;
62    BOOL g_encryption = True;
63    BOOL packet_encryption = True;
64    BOOL g_desktop_save = True;
65    BOOL g_fullscreen = False;
66    BOOL g_grab_keyboard = True;
67    BOOL g_hide_decorations = False;
68    BOOL g_use_rdp5 = True;
69    BOOL g_console_session = False;
70    BOOL g_numlock_sync = False;
71    BOOL g_owncolmap = False;
72    BOOL g_ownbackstore = True;     /* We can't rely on external BackingStore */
73    uint32 g_embed_wnd;
74    uint32 g_rdp5_performanceflags =
75            RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
76    
77    #ifdef WITH_RDPSND
78    BOOL g_rdpsnd = False;
79    #endif
80    
81    extern RDPDR_DEVICE g_rdpdr_device[];
82    extern uint32 g_num_devices;
83    extern char *g_rdpdr_clientname;
84    
85    #ifdef RDP2VNC
86    extern int rfb_port;
87    extern int defer_time;
88    void
89    rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
90                    char *shell, char *directory);
91    #endif
92  /* Display usage information */  /* Display usage information */
93  static void  static void
94  usage(char *program)  usage(char *program)
95  {  {
96          printf("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
97          printf("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
98          printf("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
99          printf("   -s: shell\n");  
100          printf("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
101          printf("   -p: password (autologon)\n");  #ifdef RDP2VNC
102          printf("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
103          printf("   -k: keyboard layout\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
104          printf("   -g: desktop geometry (WxH)\n");  #endif
105          printf("   -f: full-screen mode\n");          fprintf(stderr, "   -u: user name\n");
106          printf("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
107          printf("   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -s: shell\n");
108          printf("   -m: do not send motion events\n");          fprintf(stderr, "   -c: working directory\n");
109          printf("   -l: do not request licence\n\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
110            fprintf(stderr, "   -n: client hostname\n");
111            fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
112            fprintf(stderr, "   -g: desktop geometry (WxH)\n");
113            fprintf(stderr, "   -f: full-screen mode\n");
114            fprintf(stderr, "   -b: force bitmap updates\n");
115            fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");
116            fprintf(stderr, "   -e: disable encryption (French TS)\n");
117            fprintf(stderr, "   -E: disable encryption from client to server\n");
118            fprintf(stderr, "   -m: do not send motion events\n");
119            fprintf(stderr, "   -C: use private colour map\n");
120            fprintf(stderr, "   -D: hide window manager decorations\n");
121            fprintf(stderr, "   -K: keep window manager key bindings\n");
122            fprintf(stderr, "   -S: caption button size (single application mode)\n");
123            fprintf(stderr, "   -T: window title\n");
124            fprintf(stderr, "   -N: enable numlock syncronization\n");
125            fprintf(stderr, "   -X: embed into another window with a given id.\n");
126            fprintf(stderr, "   -a: connection colour depth\n");
127            fprintf(stderr,
128                    "   -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex number)\n");
129            fprintf(stderr, "   -r: enable specified device redirection (this flag can be repeated)\n");
130            fprintf(stderr,
131                    "         '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n");
132            fprintf(stderr, "             or      COM1=/dev/ttyS0,COM2=/dev/ttyS1\n");
133            fprintf(stderr,
134                    "         '-r disk:A=/mnt/floppy': enable redirection of /mnt/floppy to A:\n");
135            fprintf(stderr, "             or   A=/mnt/floppy,D=/mnt/cdrom'\n");
136            fprintf(stderr, "         '-r clientname=<client name>': Set the client name displayed\n");
137            fprintf(stderr, "             for redirected disks\n");
138            fprintf(stderr,
139                    "         '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1\n");
140            fprintf(stderr, "             or      LPT1=/dev/lp0,LPT2=/dev/lp1\n");
141            fprintf(stderr, "         '-r printer:mydeskjet': enable printer redirection\n");
142            fprintf(stderr,
143                    "             or      mydeskjet=\"HP LaserJet IIIP\" to enter server driver as well\n");
144            fprintf(stderr, "         '-r sound:[local|off|remote]': enable sound redirection\n");
145            fprintf(stderr, "                     remote would leave sound on server\n");
146            fprintf(stderr, "   -0: attach to console\n");
147            fprintf(stderr, "   -4: use RDP version 4\n");
148            fprintf(stderr, "   -5: use RDP version 5 (default)\n");
149    }
150    
151    void
152    print_disconnect_reason(uint16 reason)
153    {
154            char *text;
155    
156            switch (reason)
157            {
158                    case exDiscReasonNoInfo:
159                            text = "No information available";
160                            break;
161    
162                    case exDiscReasonAPIInitiatedDisconnect:
163                            text = "Server initiated disconnect";
164                            break;
165    
166                    case exDiscReasonAPIInitiatedLogoff:
167                            text = "Server initiated logoff";
168                            break;
169    
170                    case exDiscReasonServerIdleTimeout:
171                            text = "Server idle timeout reached";
172                            break;
173    
174                    case exDiscReasonServerLogonTimeout:
175                            text = "Server logon timeout reached";
176                            break;
177    
178                    case exDiscReasonReplacedByOtherConnection:
179                            text = "The session was replaced";
180                            break;
181    
182                    case exDiscReasonOutOfMemory:
183                            text = "The server is out of memory";
184                            break;
185    
186                    case exDiscReasonServerDeniedConnection:
187                            text = "The server denied the connection";
188                            break;
189    
190                    case exDiscReasonServerDeniedConnectionFips:
191                            text = "The server denied the connection for security reason";
192                            break;
193    
194                    case exDiscReasonLicenseInternal:
195                            text = "Internal licensing error";
196                            break;
197    
198                    case exDiscReasonLicenseNoLicenseServer:
199                            text = "No license server available";
200                            break;
201    
202                    case exDiscReasonLicenseNoLicense:
203                            text = "No valid license available";
204                            break;
205    
206                    case exDiscReasonLicenseErrClientMsg:
207                            text = "Invalid licensing message";
208                            break;
209    
210                    case exDiscReasonLicenseHwidDoesntMatchLicense:
211                            text = "Hardware id doesn't match software license";
212                            break;
213    
214                    case exDiscReasonLicenseErrClientLicense:
215                            text = "Client license error";
216                            break;
217    
218                    case exDiscReasonLicenseCantFinishProtocol:
219                            text = "Network error during licensing protocol";
220                            break;
221    
222                    case exDiscReasonLicenseClientEndedProtocol:
223                            text = "Licensing protocol was not completed";
224                            break;
225    
226                    case exDiscReasonLicenseErrClientEncryption:
227                            text = "Incorrect client license enryption";
228                            break;
229    
230                    case exDiscReasonLicenseCantUpgradeLicense:
231                            text = "Can't upgrade license";
232                            break;
233    
234                    case exDiscReasonLicenseNoRemoteConnections:
235                            text = "The server is not licensed to accept remote connections";
236                            break;
237    
238                    default:
239                            if (reason > 0x1000 && reason < 0x7fff)
240                            {
241                                    text = "Internal protocol error";
242                            }
243                            else
244                            {
245                                    text = "Unknown reason";
246                            }
247            }
248            fprintf(stderr, "disconnect: %s.\n", text);
249    }
250    
251    static BOOL
252    read_password(char *password, int size)
253    {
254            struct termios tios;
255            BOOL ret = False;
256            int istty = 0;
257            char *p;
258    
259            if (tcgetattr(STDIN_FILENO, &tios) == 0)
260            {
261                    fprintf(stderr, "Password: ");
262                    tios.c_lflag &= ~ECHO;
263                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
264                    istty = 1;
265            }
266    
267            if (fgets(password, size, stdin) != NULL)
268            {
269                    ret = True;
270    
271                    /* strip final newline */
272                    p = strchr(password, '\n');
273                    if (p != NULL)
274                            *p = 0;
275            }
276    
277            if (istty)
278            {
279                    tios.c_lflag |= ECHO;
280                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
281                    fprintf(stderr, "\n");
282            }
283    
284            return ret;
285    }
286    
287    static void
288    parse_server_and_port(char *server)
289    {
290            char *p;
291    #ifdef IPv6
292            int addr_colons;
293    #endif
294    
295    #ifdef IPv6
296            p = server;
297            addr_colons = 0;
298            while (*p)
299                    if (*p++ == ':')
300                            addr_colons++;
301            if (addr_colons >= 2)
302            {
303                    /* numeric IPv6 style address format - [1:2:3::4]:port */
304                    p = strchr(server, ']');
305                    if (*server == '[' && p != NULL)
306                    {
307                            if (*(p + 1) == ':' && *(p + 2) != '\0')
308                                    g_tcp_port_rdp = strtol(p + 2, NULL, 10);
309                            /* remove the port number and brackets from the address */
310                            *p = '\0';
311                            strncpy(server, server + 1, strlen(server));
312                    }
313            }
314            else
315            {
316                    /* dns name or IPv4 style address format - server.example.com:port or 1.2.3.4:port */
317                    p = strchr(server, ':');
318                    if (p != NULL)
319                    {
320                            g_tcp_port_rdp = strtol(p + 1, NULL, 10);
321                            *p = 0;
322                    }
323            }
324    #else /* no IPv6 support */
325            p = strchr(server, ':');
326            if (p != NULL)
327            {
328                    g_tcp_port_rdp = strtol(p + 1, NULL, 10);
329                    *p = 0;
330            }
331    #endif /* IPv6 */
332    
333  }  }
334    
335  /* Client program */  /* Client program */
336  int  int
337  main(int argc, char *argv[])  main(int argc, char *argv[])
338  {  {
339            char server[64];
340          char fullhostname[64];          char fullhostname[64];
341          char domain[16];          char domain[16];
342          char password[16];          char password[64];
343          char shell[32];          char shell[128];
344          char directory[32];          char directory[32];
345          char title[32];          BOOL prompt_password, deactivated;
346          struct passwd *pw;          struct passwd *pw;
347          char *server, *p;          uint32 flags, ext_disc_reason = 0;
348          uint32 flags;          char *p;
349          int c;          int c;
350    
351          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");  
352    
353          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
354            prompt_password = False;
355          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
356          strcpy(keymapname, "us");          strcpy(keymapname, "en-us");
357            g_embed_wnd = 0;
358    
359          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:fbemlh?")) != -1)          g_num_devices = 0;
360    
361    #ifdef RDP2VNC
362    #define VNCOPT "V:Q:"
363    #else
364    #define VNCOPT
365    #endif
366    
367            while ((c = getopt(argc, argv, VNCOPT "u:d:s:c:p:n:k:g:fbBeEmCDKS:T:NX:a:x:r: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;
476    
477                            case 'C':
478                                    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;                                  break;
488    
489                          case 'l':                          case 'S':
490                                  licence = False;                                  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 'x':
529    
530                                    if (strncmp("modem", optarg, 1) == 0)
531                                    {
532                                            g_rdp5_performanceflags =
533                                                    RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
534                                                    RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
535                                    }
536                                    else if (strncmp("broadband", optarg, 1) == 0)
537                                    {
538                                            g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
539                                    }
540                                    else if (strncmp("lan", optarg, 1) == 0)
541                                    {
542                                            g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;
543                                    }
544                                    else
545                                    {
546                                            g_rdp5_performanceflags = strtol(optarg, NULL, 16);
547                                    }
548                                    break;
549    
550                            case 'r':
551    
552                                    if (strncmp("sound", optarg, 5) == 0)
553                                    {
554                                            optarg += 5;
555    
556                                            if (*optarg == ':')
557                                            {
558                                                    *optarg++;
559                                                    while ((p = next_arg(optarg, ',')))
560                                                    {
561                                                            if (strncmp("remote", optarg, 6) == 0)
562                                                                    flags |= RDP_LOGON_LEAVE_AUDIO;
563    
564                                                            if (strncmp("local", optarg, 5) == 0)
565    #ifdef WITH_RDPSND
566                                                                    g_rdpsnd = True;
567    #else
568                                                                    warning("Not compiled with sound support");
569    #endif
570    
571                                                            if (strncmp("off", optarg, 3) == 0)
572    #ifdef WITH_RDPSND
573                                                                    g_rdpsnd = False;
574    #else
575                                                                    warning("Not compiled with sound support");
576    #endif
577    
578                                                            optarg = p;
579                                                    }
580                                            }
581                                            else
582                                            {
583    #ifdef WITH_RDPSND
584                                                    g_rdpsnd = True;
585    #else
586                                                    warning("Not compiled with sound support");
587    #endif
588                                            }
589                                    }
590                                    else if (strncmp("disk", optarg, 4) == 0)
591                                    {
592                                            /* -r disk:h:=/mnt/floppy */
593                                            disk_enum_devices(&g_num_devices, optarg + 4);
594                                    }
595                                    else if (strncmp("comport", optarg, 7) == 0)
596                                    {
597                                            serial_enum_devices(&g_num_devices, optarg + 7);
598                                    }
599                                    else if (strncmp("lptport", optarg, 7) == 0)
600                                    {
601                                            parallel_enum_devices(&g_num_devices, optarg + 7);
602                                    }
603                                    else if (strncmp("printer", optarg, 7) == 0)
604                                    {
605                                            printer_enum_devices(&g_num_devices, optarg + 7);
606                                    }
607                                    else if (strncmp("clientname", optarg, 7) == 0)
608                                    {
609                                            g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
610                                            strcpy(g_rdpdr_clientname, optarg + 11);
611                                    }
612                                    else
613                                    {
614                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound\n");
615                                    }
616                                    break;
617    
618                            case '0':
619                                    g_console_session = True;
620                                    break;
621    
622                            case '4':
623                                    g_use_rdp5 = False;
624                                    break;
625    
626                            case '5':
627                                    g_use_rdp5 = True;
628                                  break;                                  break;
629    
630                          case 'h':                          case 'h':
# Line 159  main(int argc, char *argv[]) Line 635  main(int argc, char *argv[])
635                  }                  }
636          }          }
637    
638          if (argc - optind < 1)          if (argc - optind != 1)
639          {          {
640                  usage(argv[0]);                  usage(argv[0]);
641                  return 1;                  return 1;
642          }          }
643    
644          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
645            parse_server_and_port(server);
646    
647          if (username[0] == 0)          if (!username_option)
648          {          {
649                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
650                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
# Line 176  main(int argc, char *argv[]) Line 653  main(int argc, char *argv[])
653                          return 1;                          return 1;
654                  }                  }
655    
656                  STRNCPY(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
657          }          }
658    
659          if (hostname[0] == 0)          if (g_hostname[0] == 0)
660          {          {
661                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
662                  {                  {
# Line 191  main(int argc, char *argv[]) Line 668  main(int argc, char *argv[])
668                  if (p != NULL)                  if (p != NULL)
669                          *p = 0;                          *p = 0;
670    
671                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
672          }          }
673    
674          if (!strcmp(password, "-"))          if (prompt_password && read_password(password, sizeof(password)))
675          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
676    
677          if ((width == 0) || (height == 0))          if (g_title[0] == 0)
678          {          {
679                  width = 800;                  strcpy(g_title, "rdesktop - ");
680                  height = 600;                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
681          }          }
682    
683          strcpy(title, "rdesktop - ");  #ifdef RDP2VNC
684          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          rdp2vnc_connect(server, flags, domain, password, shell, directory);
685            return 0;
686    #else
687    
688            if (!ui_init())
689                    return 1;
690    
691    #ifdef WITH_RDPSND
692            if (g_rdpsnd)
693                    rdpsnd_init();
694    #endif
695            rdpdr_init();
696    
697          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
698                  return 1;                  return 1;
699    
700          printf("Connection successful.\n");          /* By setting encryption to False here, we have an encrypted login
701               packet but unencrypted transfer of other packets */
702            if (!packet_encryption)
703                    g_encryption = False;
704    
705          if (ui_create_window(title))  
706            DEBUG(("Connection successful.\n"));
707            memset(password, 0, sizeof(password));
708    
709            if (ui_create_window())
710          {          {
711                  rdp_main_loop();                  rdp_main_loop(&deactivated, &ext_disc_reason);
712                  ui_destroy_window();                  ui_destroy_window();
713          }          }
714    
715          printf("Disconnecting...\n");          DEBUG(("Disconnecting...\n"));
716          rdp_disconnect();          rdp_disconnect();
717          return 0;          ui_deinit();
718    
719            if (ext_disc_reason >= 2)
720                    print_disconnect_reason(ext_disc_reason);
721    
722            if (deactivated)
723            {
724                    /* clean disconnect */
725                    return 0;
726            }
727            else
728            {
729                    if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
730                        || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
731                    {
732                            /* not so clean disconnect, but nothing to worry about */
733                            return 0;
734                    }
735                    else
736                    {
737                            /* return error */
738                            return 2;
739                    }
740            }
741    
742    #endif
743    
744  }  }
745    
746    #ifdef EGD_SOCKET
747    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
748    static BOOL
749    generate_random_egd(uint8 * buf)
750    {
751            struct sockaddr_un addr;
752            BOOL ret = False;
753            int fd;
754    
755            fd = socket(AF_UNIX, SOCK_STREAM, 0);
756            if (fd == -1)
757                    return False;
758    
759            addr.sun_family = AF_UNIX;
760            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
761            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
762                    goto err;
763    
764            /* PRNGD and EGD use a simple communications protocol */
765            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
766            buf[1] = 32;            /* Number of requested random bytes */
767            if (write(fd, buf, 2) != 2)
768                    goto err;
769    
770            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
771                    goto err;
772    
773            if (read(fd, buf, 32) != 32)
774                    goto err;
775    
776            ret = True;
777    
778          err:
779            close(fd);
780            return ret;
781    }
782    #endif
783    
784  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
785  void  void
786  generate_random(uint8 *random)  generate_random(uint8 * random)
787  {  {
788          struct stat st;          struct stat st;
789          struct tms tmsbuf;          struct tms tmsbuf;
790          uint32 *r = (uint32 *) random;          MD5_CTX md5;
791          int fd;          uint32 *r;
792            int fd, n;
793    
794          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
795          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
796              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
797          {          {
798                  read(fd, random, 32);                  n = read(fd, random, 32);
799                  close(fd);                  close(fd);
800                  return;                  if (n == 32)
801                            return;
802          }          }
803    
804    #ifdef EGD_SOCKET
805            /* As a second preference use an EGD */
806            if (generate_random_egd(random))
807                    return;
808    #endif
809    
810          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
811            r = (uint32 *) random;
812          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
813          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
814          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 257  generate_random(uint8 *random) Line 817  generate_random(uint8 *random)
817          r[5] = st.st_atime;          r[5] = st.st_atime;
818          r[6] = st.st_mtime;          r[6] = st.st_mtime;
819          r[7] = st.st_ctime;          r[7] = st.st_ctime;
820    
821            /* Hash both halves with MD5 to obscure possible patterns */
822            MD5_Init(&md5);
823            MD5_Update(&md5, random, 16);
824            MD5_Final(random, &md5);
825            MD5_Update(&md5, random + 16, 16);
826            MD5_Final(random + 16, &md5);
827  }  }
828    
829  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 305  error(char *format, ...) Line 872  error(char *format, ...)
872          va_end(ap);          va_end(ap);
873  }  }
874    
875    /* report a warning */
876    void
877    warning(char *format, ...)
878    {
879            va_list ap;
880    
881            fprintf(stderr, "WARNING: ");
882    
883            va_start(ap, format);
884            vfprintf(stderr, format, ap);
885            va_end(ap);
886    }
887    
888  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
889  void  void
890  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 323  void Line 903  void
903  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, unsigned int len)
904  {  {
905          unsigned char *line = p;          unsigned char *line = p;
906          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
907    
908          while (offset < len)          while (offset < len)
909          {          {
# Line 337  hexdump(unsigned char *p, unsigned int l Line 916  hexdump(unsigned char *p, unsigned int l
916                          printf("%02x ", line[i]);                          printf("%02x ", line[i]);
917    
918                  for (; i < 16; i++)                  for (; i < 16; i++)
919                                  printf("   ");                          printf("   ");
920    
921                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
922                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
923    
924                  printf("\n");                  printf("\n");
925                  offset += thisline;                  offset += thisline;
# Line 350  hexdump(unsigned char *p, unsigned int l Line 927  hexdump(unsigned char *p, unsigned int l
927          }          }
928  }  }
929    
930    /*
931      input: src is the string we look in for needle.
932             Needle may be escaped by a backslash, in
933             that case we ignore that particular needle.
934      return value: returns next src pointer, for
935            succesive executions, like in a while loop
936            if retval is 0, then there are no more args.
937      pitfalls:
938            src is modified. 0x00 chars are inserted to
939            terminate strings.
940            return val, points on the next val chr after ins
941            0x00
942    
943            example usage:
944            while( (pos = next_arg( optarg, ',')) ){
945                    printf("%s\n",optarg);
946                    optarg=pos;
947            }
948    
949    */
950    char *
951    next_arg(char *src, char needle)
952    {
953            char *nextval;
954            char *p;
955            char *mvp = 0;
956    
957            /* EOS */
958            if (*src == (char) 0x00)
959                    return 0;
960    
961            p = src;
962            /*  skip escaped needles */
963            while ((nextval = strchr(p, needle)))
964            {
965                    mvp = nextval - 1;
966                    /* found backslashed needle */
967                    if (*mvp == '\\' && (mvp > src))
968                    {
969                            /* move string one to the left */
970                            while (*(mvp + 1) != (char) 0x00)
971                            {
972                                    *mvp = *(mvp + 1);
973                                    *mvp++;
974                            }
975                            *mvp = (char) 0x00;
976                            p = nextval;
977                    }
978                    else
979                    {
980                            p = nextval + 1;
981                            break;
982                    }
983    
984            }
985    
986            /* more args available */
987            if (nextval)
988            {
989                    *nextval = (char) 0x00;
990                    return ++nextval;
991            }
992    
993            /* no more args after this, jump to EOS */
994            nextval = src + strlen(src);
995            return nextval;
996    }
997    
998    
999    void
1000    toupper_str(char *p)
1001    {
1002            while (*p)
1003            {
1004                    if ((*p >= 'a') && (*p <= 'z'))
1005                            *p = toupper((int) *p);
1006                    p++;
1007            }
1008    }
1009    
1010    
1011    /* not all clibs got ltoa */
1012    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1013    
1014    char *
1015    l_to_a(long N, int base)
1016    {
1017            static char ret[LTOA_BUFSIZE];
1018    
1019            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1020    
1021            register int divrem;
1022    
1023            if (base < 36 || 2 > base)
1024                    base = 10;
1025    
1026            if (N < 0)
1027            {
1028                    *head++ = '-';
1029                    N = -N;
1030            }
1031    
1032            tail = buf + sizeof(buf);
1033            *--tail = 0;
1034    
1035            do
1036            {
1037                    divrem = N % base;
1038                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1039                    N /= base;
1040            }
1041            while (N);
1042    
1043            strcpy(head, tail);
1044            return ret;
1045    }
1046    
1047    
1048  int  int
1049  load_licence(unsigned char **data)  load_licence(unsigned char **data)
1050  {  {
1051          char path[PATH_MAX];          char *home, *path;
         char *home;  
1052          struct stat st;          struct stat st;
1053          int fd;          int fd, length;
1054    
1055          home = getenv("HOME");          home = getenv("HOME");
1056          if (home == NULL)          if (home == NULL)
1057                  return -1;                  return -1;
1058    
1059          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1060          strncat(path, "/.rdesktop/licence", sizeof(path)-strlen(path)-1);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1061    
1062          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
1063          if (fd == -1)          if (fd == -1)
# Line 372  load_licence(unsigned char **data) Line 1066  load_licence(unsigned char **data)
1066          if (fstat(fd, &st))          if (fstat(fd, &st))
1067                  return -1;                  return -1;
1068    
1069          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
1070          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
1071            close(fd);
1072            xfree(path);
1073            return length;
1074  }  }
1075    
1076  void  void
1077  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
1078  {  {
1079          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
1080          int fd;          int fd;
1081    
1082          home = getenv("HOME");          home = getenv("HOME");
1083          if (home == NULL)          if (home == NULL)
1084                  return;                  return;
1085    
1086          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1087          strncat(path, "/.rdesktop", sizeof(path)-strlen(path)-1);  
1088          mkdir(path, 0700);          sprintf(path, "%s/.rdesktop", home);
1089            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1090            {
1091                    perror(path);
1092                    return;
1093            }
1094    
1095            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1096    
1097          strncat(path, "/licence", sizeof(path)-strlen(path)-1);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1098            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1099            strcpy(tmppath, path);
1100            strcat(tmppath, ".new");
1101    
1102          fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0600);          fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1103          if (fd == -1)          if (fd == -1)
1104          {          {
1105                  perror("open");                  perror(tmppath);
1106                  return;                  return;
1107          }          }
1108    
1109          write(fd, data, length);          if (write(fd, data, length) != length)
1110            {
1111                    perror(tmppath);
1112                    unlink(tmppath);
1113            }
1114            else if (rename(tmppath, path) == -1)
1115            {
1116                    perror(path);
1117                    unlink(tmppath);
1118            }
1119    
1120          close(fd);          close(fd);
1121            xfree(tmppath);
1122            xfree(path);
1123  }  }
   

Legend:
Removed from v.53  
changed lines
  Added in v.710

  ViewVC Help
Powered by ViewVC 1.1.26