/[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 676 by astrand, Tue Apr 20 07:01:21 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    #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 hostname[16];  char hostname[16];
47  char keymapname[16];  char keymapname[16];
48  int keylayout = 0x409;          /* Defaults to US keyboard layout */  int 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;  
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    int tcp_port_rdp = 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_orders = True;
62    BOOL g_encryption = True;
63    BOOL packet_encryption = True;
64    BOOL g_desktop_save = True;
65    BOOL g_fullscreen = False;
66    BOOL g_grab_keyboard = True;
67    BOOL g_hide_decorations = False;
68    BOOL g_use_rdp5 = True;
69    BOOL g_console_session = False;
70    BOOL g_numlock_sync = False;
71    BOOL g_owncolmap = False;
72    BOOL g_ownbackstore = True;     /* We can't rely on external BackingStore */
73    uint32 g_embed_wnd;
74    uint32 g_rdp5_performanceflags =
75            RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
76    
77    #ifdef WITH_RDPSND
78    BOOL g_rdpsnd = False;
79    #endif
80    
81    extern RDPDR_DEVICE g_rdpdr_device[];
82    extern uint32 g_num_devices;
83    extern char *g_rdpdr_clientname;
84    
85    #ifdef RDP2VNC
86    extern int rfb_port;
87    extern int defer_time;
88    void
89    rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
90                    char *shell, char *directory);
91    #endif
92  /* Display usage information */  /* Display usage information */
93  static void  static void
94  usage(char *program)  usage(char *program)
95  {  {
96          printf("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
97          printf("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
98          printf("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
99          printf("   -s: shell\n");  
100          printf("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
101          printf("   -p: password (autologon)\n");  #ifdef RDP2VNC
102          printf("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
103          printf("   -k: keyboard layout on terminal server (us,sv,gr etc.)\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
104          printf("   -g: desktop geometry (WxH)\n");  #endif
105          printf("   -f: full-screen mode\n");          fprintf(stderr, "   -u: user name\n");
106          printf("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
107          printf("   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -s: shell\n");
108          printf("   -m: do not send motion events\n");          fprintf(stderr, "   -c: working directory\n");
109          printf("   -l: do not request licence\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
110          printf("   -t: rdp tcp port\n");          fprintf(stderr, "   -n: client hostname\n");
111          printf("   -K: keep window manager key bindings\n");          fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
112            fprintf(stderr, "   -g: desktop geometry (WxH)\n");
113            fprintf(stderr, "   -f: full-screen mode\n");
114            fprintf(stderr, "   -b: force bitmap updates\n");
115            fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");
116            fprintf(stderr, "   -e: disable encryption (French TS)\n");
117            fprintf(stderr, "   -E: disable encryption from client to server\n");
118            fprintf(stderr, "   -m: do not send motion events\n");
119            fprintf(stderr, "   -C: use private colour map\n");
120            fprintf(stderr, "   -D: hide window manager decorations\n");
121            fprintf(stderr, "   -K: keep window manager key bindings\n");
122            fprintf(stderr, "   -S: caption button size (single application mode)\n");
123            fprintf(stderr, "   -T: window title\n");
124            fprintf(stderr, "   -N: enable numlock syncronization\n");
125            fprintf(stderr, "   -X: embed into another window with a given id.\n");
126            fprintf(stderr, "   -a: connection colour depth\n");
127            fprintf(stderr,
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                                    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                            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                    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            g_num_devices = 0;
360    
361          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:t:fbemlKh?")) != -1)  #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 112  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':
# Line 121  main(int argc, char *argv[]) Line 420  main(int argc, char *argv[])
420                                  break;                                  break;
421    
422                          case 'k':                          case 'k':
423                                  STRNCPY(keymapname, optarg,                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
                                         sizeof(keymapname));  
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_orders = False;
461                                  break;                                  break;
462    
463                          case 'e':                          case 'B':
464                                  encryption = False;                                  g_ownbackstore = False;
465                                  break;                                  break;
466    
467                            case 'e':
468                                    g_encryption = False;
469                                    break;
470                            case 'E':
471                                    packet_encryption = False;
472                                    break;
473                          case 'm':                          case 'm':
474                                  sendmotion = False;                                  g_sendmotion = False;
475                                  break;                                  break;
476    
477                          case 'l':                          case 'C':
478                                  licence = False;                                  g_owncolmap = True;
479                                  break;                                  break;
480    
481                          case 't':                          case 'D':
482                                  tcp_port_rdp = strtol(optarg, NULL, 10);                                  g_hide_decorations = True;
483                                  break;                                  break;
484    
485                          case 'K':                          case 'K':
486                                  grab_keyboard = False;                                  g_grab_keyboard = False;
487                                    break;
488    
489                            case 'S':
490                                    if (!strcmp(optarg, "standard"))
491                                    {
492                                            g_win_button_size = 18;
493                                            break;
494                                    }
495    
496                                    g_win_button_size = strtol(optarg, &p, 10);
497    
498                                    if (*p)
499                                    {
500                                            error("invalid button size\n");
501                                            return 1;
502                                    }
503    
504                                    break;
505    
506                            case 'T':
507                                    STRNCPY(g_title, optarg, sizeof(g_title));
508                                    break;
509    
510                            case 'N':
511                                    g_numlock_sync = True;
512                                    break;
513    
514                            case 'X':
515                                    g_embed_wnd = strtol(optarg, NULL, 10);
516                                    break;
517    
518                            case 'a':
519                                    g_server_bpp = strtol(optarg, NULL, 10);
520                                    if (g_server_bpp != 8 && g_server_bpp != 16 && g_server_bpp != 15
521                                        && g_server_bpp != 24)
522                                    {
523                                            error("invalid server bpp\n");
524                                            return 1;
525                                    }
526                                    break;
527    
528                            case '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                                                                    g_rdpsnd = False;
573    
574                                                            optarg = p;
575                                                    }
576                                            }
577                                            else
578                                            {
579    #ifdef WITH_RDPSND
580                                                    g_rdpsnd = True;
581    #else
582                                                    warning("Not compiled with sound support");
583    #endif
584                                            }
585                                    }
586                                    else if (strncmp("disk", optarg, 4) == 0)
587                                    {
588                                            /* -r disk:h:=/mnt/floppy */
589                                            disk_enum_devices(&g_num_devices, optarg + 4);
590                                    }
591                                    else if (strncmp("comport", optarg, 7) == 0)
592                                    {
593                                            serial_enum_devices(&g_num_devices, optarg + 7);
594                                    }
595                                    else if (strncmp("lptport", optarg, 7) == 0)
596                                    {
597                                            parallel_enum_devices(&g_num_devices, optarg + 7);
598                                    }
599                                    else if (strncmp("printer", optarg, 7) == 0)
600                                    {
601                                            printer_enum_devices(&g_num_devices, optarg + 7);
602                                    }
603                                    else if (strncmp("clientname", optarg, 7) == 0)
604                                    {
605                                            g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
606                                            strcpy(g_rdpdr_clientname, optarg + 11);
607                                    }
608                                    else
609                                    {
610                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound\n");
611                                    }
612                                    break;
613    
614                            case '0':
615                                    g_console_session = True;
616                                    break;
617    
618                            case '4':
619                                    g_use_rdp5 = False;
620                                    break;
621    
622                            case '5':
623                                    g_use_rdp5 = True;
624                                  break;                                  break;
625    
626                          case 'h':                          case 'h':
# Line 173  main(int argc, char *argv[]) Line 631  main(int argc, char *argv[])
631                  }                  }
632          }          }
633    
634          if (argc - optind < 1)          if (argc - optind != 1)
635          {          {
636                  usage(argv[0]);                  usage(argv[0]);
637                  return 1;                  return 1;
638          }          }
639    
640          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
641            parse_server_and_port(server);
642    
643          if (username[0] == 0)          if (!username_option)
644          {          {
645                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
646                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
# Line 190  main(int argc, char *argv[]) Line 649  main(int argc, char *argv[])
649                          return 1;                          return 1;
650                  }                  }
651    
652                  STRNCPY(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
653          }          }
654    
655          if (hostname[0] == 0)          if (hostname[0] == 0)
# Line 208  main(int argc, char *argv[]) Line 667  main(int argc, char *argv[])
667                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(hostname, fullhostname, sizeof(hostname));
668          }          }
669    
670          if (!strcmp(password, "-"))          if (prompt_password && read_password(password, sizeof(password)))
671          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
672    
673          if ((width == 0) || (height == 0))          if (g_title[0] == 0)
674          {          {
675                  width = 800;                  strcpy(g_title, "rdesktop - ");
676                  height = 600;                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
677          }          }
678    
679          strcpy(title, "rdesktop - ");  #ifdef RDP2VNC
680          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          rdp2vnc_connect(server, flags, domain, password, shell, directory);
681            return 0;
682    #else
683    
684            if (!ui_init())
685                    return 1;
686    
687          xkeymap_init1();  #ifdef WITH_RDPSND
688            if (g_rdpsnd)
689                    rdpsnd_init();
690    #endif
691            rdpdr_init();
692    
693          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
694                  return 1;                  return 1;
695    
696          printf("Connection successful.\n");          /* By setting encryption to False here, we have an encrypted login
697               packet but unencrypted transfer of other packets */
698            if (!packet_encryption)
699                    g_encryption = False;
700    
701          if (ui_create_window(title))  
702            DEBUG(("Connection successful.\n"));
703            memset(password, 0, sizeof(password));
704    
705            if (ui_create_window())
706          {          {
707                  rdp_main_loop();                  rdp_main_loop(&deactivated, &ext_disc_reason);
708                  ui_destroy_window();                  ui_destroy_window();
709          }          }
710    
711          printf("Disconnecting...\n");          DEBUG(("Disconnecting...\n"));
712          rdp_disconnect();          rdp_disconnect();
713          return 0;          ui_deinit();
714    
715            if (ext_disc_reason >= 2)
716                    print_disconnect_reason(ext_disc_reason);
717    
718            if (deactivated)
719            {
720                    /* clean disconnect */
721                    return 0;
722            }
723            else
724            {
725                    if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
726                        || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
727                    {
728                            /* not so clean disconnect, but nothing to worry about */
729                            return 0;
730                    }
731                    else
732                    {
733                            /* return error */
734                            return 2;
735                    }
736            }
737    
738    #endif
739    
740  }  }
741    
742    #ifdef EGD_SOCKET
743    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
744    static BOOL
745    generate_random_egd(uint8 * buf)
746    {
747            struct sockaddr_un addr;
748            BOOL ret = False;
749            int fd;
750    
751            fd = socket(AF_UNIX, SOCK_STREAM, 0);
752            if (fd == -1)
753                    return False;
754    
755            addr.sun_family = AF_UNIX;
756            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
757            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
758                    goto err;
759    
760            /* PRNGD and EGD use a simple communications protocol */
761            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
762            buf[1] = 32;            /* Number of requested random bytes */
763            if (write(fd, buf, 2) != 2)
764                    goto err;
765    
766            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
767                    goto err;
768    
769            if (read(fd, buf, 32) != 32)
770                    goto err;
771    
772            ret = True;
773    
774          err:
775            close(fd);
776            return ret;
777    }
778    #endif
779    
780  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
781  void  void
782  generate_random(uint8 * random)  generate_random(uint8 * random)
783  {  {
784          struct stat st;          struct stat st;
785          struct tms tmsbuf;          struct tms tmsbuf;
786          uint32 *r = (uint32 *) random;          MD5_CTX md5;
787          int fd;          uint32 *r;
788            int fd, n;
789    
790          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
791          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
792              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
793          {          {
794                  read(fd, random, 32);                  n = read(fd, random, 32);
795                  close(fd);                  close(fd);
796                  return;                  if (n == 32)
797                            return;
798          }          }
799    
800    #ifdef EGD_SOCKET
801            /* As a second preference use an EGD */
802            if (generate_random_egd(random))
803                    return;
804    #endif
805    
806          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
807            r = (uint32 *) random;
808          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
809          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
810          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 273  generate_random(uint8 * random) Line 813  generate_random(uint8 * random)
813          r[5] = st.st_atime;          r[5] = st.st_atime;
814          r[6] = st.st_mtime;          r[6] = st.st_mtime;
815          r[7] = st.st_ctime;          r[7] = st.st_ctime;
816    
817            /* Hash both halves with MD5 to obscure possible patterns */
818            MD5_Init(&md5);
819            MD5_Update(&md5, random, 16);
820            MD5_Final(random, &md5);
821            MD5_Update(&md5, random + 16, 16);
822            MD5_Final(random + 16, &md5);
823  }  }
824    
825  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 321  error(char *format, ...) Line 868  error(char *format, ...)
868          va_end(ap);          va_end(ap);
869  }  }
870    
871    /* report a warning */
872    void
873    warning(char *format, ...)
874    {
875            va_list ap;
876    
877            fprintf(stderr, "WARNING: ");
878    
879            va_start(ap, format);
880            vfprintf(stderr, format, ap);
881            va_end(ap);
882    }
883    
884  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
885  void  void
886  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 339  void Line 899  void
899  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, unsigned int len)
900  {  {
901          unsigned char *line = p;          unsigned char *line = p;
902          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
903    
904          while (offset < len)          while (offset < len)
905          {          {
# Line 356  hexdump(unsigned char *p, unsigned int l Line 915  hexdump(unsigned char *p, unsigned int l
915                          printf("   ");                          printf("   ");
916    
917                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
918                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
919    
920                  printf("\n");                  printf("\n");
921                  offset += thisline;                  offset += thisline;
# Line 366  hexdump(unsigned char *p, unsigned int l Line 923  hexdump(unsigned char *p, unsigned int l
923          }          }
924  }  }
925    
926    /*
927      input: src is the string we look in for needle.
928             Needle may be escaped by a backslash, in
929             that case we ignore that particular needle.
930      return value: returns next src pointer, for
931            succesive executions, like in a while loop
932            if retval is 0, then there are no more args.
933      pitfalls:
934            src is modified. 0x00 chars are inserted to
935            terminate strings.
936            return val, points on the next val chr after ins
937            0x00
938    
939            example usage:
940            while( (pos = next_arg( optarg, ',')) ){
941                    printf("%s\n",optarg);
942                    optarg=pos;
943            }
944    
945    */
946    char *
947    next_arg(char *src, char needle)
948    {
949            char *nextval;
950            char *p;
951            char *mvp = 0;
952    
953            /* EOS */
954            if (*src == (char) 0x00)
955                    return 0;
956    
957            p = src;
958            /*  skip escaped needles */
959            while ((nextval = strchr(p, needle)))
960            {
961                    mvp = nextval - 1;
962                    /* found backslashed needle */
963                    if (*mvp == '\\' && (mvp > src))
964                    {
965                            /* move string one to the left */
966                            while (*(mvp + 1) != (char) 0x00)
967                            {
968                                    *mvp = *(mvp + 1);
969                                    *mvp++;
970                            }
971                            *mvp = (char) 0x00;
972                            p = nextval;
973                    }
974                    else
975                    {
976                            p = nextval + 1;
977                            break;
978                    }
979    
980            }
981    
982            /* more args available */
983            if (nextval)
984            {
985                    *nextval = (char) 0x00;
986                    return ++nextval;
987            }
988    
989            /* no more args after this, jump to EOS */
990            nextval = src + strlen(src);
991            return nextval;
992    }
993    
994    
995    void
996    toupper_str(char *p)
997    {
998            while (*p)
999            {
1000                    if ((*p >= 'a') && (*p <= 'z'))
1001                            *p = toupper((int) *p);
1002                    p++;
1003            }
1004    }
1005    
1006    
1007    /* not all clibs got ltoa */
1008    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1009    
1010    char *
1011    l_to_a(long N, int base)
1012    {
1013            static char ret[LTOA_BUFSIZE];
1014    
1015            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1016    
1017            register int divrem;
1018    
1019            if (base < 36 || 2 > base)
1020                    base = 10;
1021    
1022            if (N < 0)
1023            {
1024                    *head++ = '-';
1025                    N = -N;
1026            }
1027    
1028            tail = buf + sizeof(buf);
1029            *--tail = 0;
1030    
1031            do
1032            {
1033                    divrem = N % base;
1034                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1035                    N /= base;
1036            }
1037            while (N);
1038    
1039            strcpy(head, tail);
1040            return ret;
1041    }
1042    
1043    
1044  int  int
1045  load_licence(unsigned char **data)  load_licence(unsigned char **data)
1046  {  {
1047          char path[PATH_MAX];          char *home, *path;
         char *home;  
1048          struct stat st;          struct stat st;
1049          int fd;          int fd, length;
1050    
1051          home = getenv("HOME");          home = getenv("HOME");
1052          if (home == NULL)          if (home == NULL)
1053                  return -1;                  return -1;
1054    
1055          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
1056          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
1057    
1058          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
1059          if (fd == -1)          if (fd == -1)
# Line 388  load_licence(unsigned char **data) Line 1062  load_licence(unsigned char **data)
1062          if (fstat(fd, &st))          if (fstat(fd, &st))
1063                  return -1;                  return -1;
1064    
1065          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
1066          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
1067            close(fd);
1068            xfree(path);
1069            return length;
1070  }  }
1071    
1072  void  void
1073  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
1074  {  {
1075          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
1076          int fd;          int fd;
1077    
1078          home = getenv("HOME");          home = getenv("HOME");
1079          if (home == NULL)          if (home == NULL)
1080                  return;                  return;
1081    
1082          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
1083          strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);  
1084          mkdir(path, 0700);          sprintf(path, "%s/.rdesktop", home);
1085            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1086            {
1087                    perror(path);
1088                    return;
1089            }
1090    
1091            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1092    
1093          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
1094            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1095            strcpy(tmppath, path);
1096            strcat(tmppath, ".new");
1097    
1098          fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1099          if (fd == -1)          if (fd == -1)
1100          {          {
1101                  perror("open");                  perror(tmppath);
1102                  return;                  return;
1103          }          }
1104    
1105          write(fd, data, length);          if (write(fd, data, length) != length)
1106            {
1107                    perror(tmppath);
1108                    unlink(tmppath);
1109            }
1110            else if (rename(tmppath, path) == -1)
1111            {
1112                    perror(path);
1113                    unlink(tmppath);
1114            }
1115    
1116          close(fd);          close(fd);
1117            xfree(tmppath);
1118            xfree(path);
1119  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26