/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/rdesktop.c

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

revision 17 by matty, Thu Sep 28 15:54:11 2000 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-2000     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    
21  #include <stdlib.h>     /* malloc realloc free */  #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 <sys/stat.h>   /* stat */  #include <termios.h>            /* tcgetattr tcsetattr */
26  #include <sys/time.h>   /* gettimeofday */  #include <sys/stat.h>           /* stat */
27  #include <sys/times.h>  /* times */  #include <sys/time.h>           /* gettimeofday */
28    #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  int width = 800;  char keymapname[16];
48  int height = 600;  int keylayout = 0x409;          /* Defaults to US keyboard layout */
 int keylayout = 0x409;  
 BOOL motion = False;  
 BOOL orders = True;  
 BOOL licence = 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 usage(char *program)  static void
94    usage(char *program)
95    {
96            fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
97            fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
98            fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
99    
100            fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
101    #ifdef RDP2VNC
102            fprintf(stderr, "   -V: vnc port\n");
103            fprintf(stderr, "   -Q: defer time (ms)\n");
104    #endif
105            fprintf(stderr, "   -u: user name\n");
106            fprintf(stderr, "   -d: domain\n");
107            fprintf(stderr, "   -s: shell\n");
108            fprintf(stderr, "   -c: working directory\n");
109            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          STATUS("Usage: %s [options] server\n", program);          char *text;
155          STATUS("   -u: user name\n");  
156          STATUS("   -n: client hostname\n");          switch (reason)
157          STATUS("   -w: desktop width\n");          {
158          STATUS("   -h: desktop height\n");                  case exDiscReasonNoInfo:
159          STATUS("   -k: keyboard layout (hex)\n");                          text = "No information available";
160          STATUS("   -m: send motion events\n");                          break;
161          STATUS("   -b: force bitmap updates\n");  
162          STATUS("   -l: do not request licence\n\n");                  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 main(int argc, char *argv[])  int
337    main(int argc, char *argv[])
338  {  {
339            char server[64];
340            char fullhostname[64];
341            char domain[16];
342            char password[64];
343            char shell[128];
344            char directory[32];
345            BOOL prompt_password, deactivated;
346          struct passwd *pw;          struct passwd *pw;
347          char *server;          uint32 flags, ext_disc_reason = 0;
348          char title[32];          char *p;
349          int c;          int c;
350    
351          STATUS("rdesktop: A Remote Desktop Protocol client.\n");          int username_option = 0;
352          STATUS("Version "VERSION". Copyright (C) 1999-2000 Matt Chapman.\n");  
353          STATUS("See http://www.rdesktop.org/ for more information.\n\n");          flags = RDP_LOGON_NORMAL;
354            prompt_password = False;
355            domain[0] = password[0] = shell[0] = directory[0] = 0;
356            strcpy(keymapname, "en-us");
357            g_embed_wnd = 0;
358    
359            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, "u:n:w:h:k:mbl?")) != -1)          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 'n':                          case 'd':
391                                  strncpy(hostname, optarg, sizeof(hostname));                                  STRNCPY(domain, optarg, sizeof(domain));
392                                  break;                                  break;
393    
394                          case 'w':                          case 's':
395                                  width = strtol(optarg, NULL, 10);                                  STRNCPY(shell, optarg, sizeof(shell));
396                                  break;                                  break;
397    
398                          case 'h':                          case 'c':
399                                  height = strtol(optarg, NULL, 10);                                  STRNCPY(directory, optarg, sizeof(directory));
400                                    break;
401    
402                            case 'p':
403                                    if ((optarg[0] == '-') && (optarg[1] == 0))
404                                    {
405                                            prompt_password = True;
406                                            break;
407                                    }
408    
409                                    STRNCPY(password, optarg, sizeof(password));
410                                    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;
417    
418                            case 'n':
419                                    STRNCPY(hostname, optarg, sizeof(hostname));
420                                  break;                                  break;
421    
422                          case 'k':                          case 'k':
423                                  keylayout = strtol(optarg, NULL, 16);                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
424                                  break;                                  break;
425    
426                          case 'm':                          case 'g':
427                                  motion = True;                                  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')
442                                            g_height = strtol(p + 1, NULL, 10);
443    
444                                    if (g_height <= 0)
445                                    {
446                                            error("invalid geometry\n");
447                                            return 1;
448                                    }
449    
450                                    if (*p == '%')
451                                            g_width = -g_width;
452    
453                                    break;
454    
455                            case 'f':
456                                    g_fullscreen = True;
457                                  break;                                  break;
458    
459                          case 'b':                          case 'b':
460                                  orders = False;                                  g_orders = False;
461                                    break;
462    
463                            case 'B':
464                                    g_ownbackstore = False;
465                                    break;
466    
467                            case 'e':
468                                    g_encryption = False;
469                                    break;
470                            case 'E':
471                                    packet_encryption = False;
472                                    break;
473                            case 'm':
474                                    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;                                  break;
484    
485                          case 'l':                          case 'K':
486                                  licence = False;                                  g_grab_keyboard = False;
487                                  break;                                  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;
625    
626                            case 'h':
627                          case '?':                          case '?':
628                          default:                          default:
629                                  usage(argv[0]);                                  usage(argv[0]);
# Line 105  int main(int argc, char *argv[]) Line 631  int 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))
647                  {                  {
648                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
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)
656          {          {
657                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
658                  {                  {
659                          STATUS("Could not determine host name.\n");                          error("could not determine local hostname, use -n\n");
660                          return 1;                          return 1;
661                  }                  }
662    
663                    p = strchr(fullhostname, '.');
664                    if (p != NULL)
665                            *p = 0;
666    
667                    STRNCPY(hostname, fullhostname, sizeof(hostname));
668          }          }
669    
670          if (!rdp_connect(server))          if (prompt_password && read_password(password, sizeof(password)))
671                    flags |= RDP_LOGON_AUTO;
672    
673            if (g_title[0] == 0)
674            {
675                    strcpy(g_title, "rdesktop - ");
676                    strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
677            }
678    
679    #ifdef RDP2VNC
680            rdp2vnc_connect(server, flags, domain, password, shell, directory);
681            return 0;
682    #else
683    
684            if (!ui_init())
685                  return 1;                  return 1;
686    
687          STATUS("Connection successful.\n");  #ifdef WITH_RDPSND
688            if (g_rdpsnd)
689                    rdpsnd_init();
690    #endif
691            rdpdr_init();
692    
693          strcpy(title, "rdesktop - ");          if (!rdp_connect(server, flags, domain, password, shell, directory))
694          strncat(title, server, sizeof(title));                  return 1;
695    
696          if (ui_create_window(title))          /* 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    
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            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  /* Generate a 32-byte random for the secure transport code. */  #ifdef EGD_SOCKET
743  void generate_random(uint8 *random)  /* 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 stat st;          struct sockaddr_un addr;
748          uint32 *r = (uint32 *)random;          BOOL ret = False;
749          int fd;          int fd;
750    
751          /* If we have a kernel random device, use it. */          fd = socket(AF_UNIX, SOCK_STREAM, 0);
752          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          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. */
781    void
782    generate_random(uint8 * random)
783    {
784            struct stat st;
785            struct tms tmsbuf;
786            MD5_CTX md5;
787            uint32 *r;
788            int fd, n;
789    
790            /* If we have a kernel random device, try that first */
791            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
792                || ((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(NULL); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
811          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
812          stat("/tmp", &st);          stat("/tmp", &st);
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 */
826  void *xmalloc(int size)  void *
827    xmalloc(int size)
828  {  {
829          void *mem = malloc(size);          void *mem = malloc(size);
830          if (mem == NULL)          if (mem == NULL)
831          {          {
832                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
833                  exit(1);                  exit(1);
834          }          }
835          return mem;          return mem;
836  }  }
837    
838  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
839  void *xrealloc(void *oldmem, int size)  void *
840    xrealloc(void *oldmem, int size)
841  {  {
842          void *mem = realloc(oldmem, size);          void *mem = realloc(oldmem, size);
843          if (mem == NULL)          if (mem == NULL)
844          {          {
845                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
846                  exit(1);                  exit(1);
847          }          }
848          return mem;          return mem;
849  }  }
850    
851  /* free */  /* free */
852  void xfree(void *mem)  void
853    xfree(void *mem)
854  {  {
855          free(mem);          free(mem);
856  }  }
857    
858  /* Produce a hex dump */  /* report an error */
859  void hexdump(unsigned char *p, unsigned int len)  void
860    error(char *format, ...)
861    {
862            va_list ap;
863    
864            fprintf(stderr, "ERROR: ");
865    
866            va_start(ap, format);
867            vfprintf(stderr, format, ap);
868            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 */
885    void
886    unimpl(char *format, ...)
887    {
888            va_list ap;
889    
890            fprintf(stderr, "NOT IMPLEMENTED: ");
891    
892            va_start(ap, format);
893            vfprintf(stderr, format, ap);
894            va_end(ap);
895    }
896    
897    /* produce a hex dump */
898    void
899    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          {          {
906                  STATUS("%04x ", offset);                  printf("%04x ", offset);
907                  thisline = len - offset;                  thisline = len - offset;
908                  if (thisline > 16)                  if (thisline > 16)
909                          thisline = 16;                          thisline = 16;
910    
911                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
912                          STATUS("%02x ", line[i])                          printf("%02x ", line[i]);
913    
914                  for (; i < 16; i++)                  for (; i < 16; i++)
915                          STATUS("   ");                          printf("   ");
916    
917                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
918                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
919    
920                  STATUS("\n");                  printf("\n");
921                  offset += thisline;                  offset += thisline;
922                  line += thisline;                  line += thisline;
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
1045    load_licence(unsigned char **data)
1046    {
1047            char *home, *path;
1048            struct stat st;
1049            int fd, length;
1050    
1051            home = getenv("HOME");
1052            if (home == NULL)
1053                    return -1;
1054    
1055            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
1056            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
1057    
1058            fd = open(path, O_RDONLY);
1059            if (fd == -1)
1060                    return -1;
1061    
1062            if (fstat(fd, &st))
1063                    return -1;
1064    
1065            *data = (uint8 *) xmalloc(st.st_size);
1066            length = read(fd, *data, st.st_size);
1067            close(fd);
1068            xfree(path);
1069            return length;
1070    }
1071    
1072    void
1073    save_licence(unsigned char *data, int length)
1074    {
1075            char *home, *path, *tmppath;
1076            int fd;
1077    
1078            home = getenv("HOME");
1079            if (home == NULL)
1080                    return;
1081    
1082            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
1083    
1084            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            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(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1099            if (fd == -1)
1100            {
1101                    perror(tmppath);
1102                    return;
1103            }
1104    
1105            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);
1117            xfree(tmppath);
1118            xfree(path);
1119    }

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

  ViewVC Help
Powered by ViewVC 1.1.26