/[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 685 by stargo, Thu Apr 29 19:40:40 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_bitmap_cache = True;
62    BOOL g_encryption = True;
63    BOOL packet_encryption = True;
64    BOOL g_desktop_save = True;
65    BOOL g_fullscreen = False;
66    BOOL g_grab_keyboard = True;
67    BOOL g_hide_decorations = False;
68    BOOL g_use_rdp5 = True;
69    BOOL g_console_session = False;
70    BOOL g_numlock_sync = False;
71    BOOL g_owncolmap = False;
72    BOOL g_ownbackstore = True;     /* We can't rely on external BackingStore */
73    uint32 g_embed_wnd;
74    uint32 g_rdp5_performanceflags =
75            RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
76    
77    #ifdef WITH_RDPSND
78    BOOL g_rdpsnd = False;
79    #endif
80    
81    extern RDPDR_DEVICE g_rdpdr_device[];
82    extern uint32 g_num_devices;
83    extern char *g_rdpdr_clientname;
84    
85    #ifdef RDP2VNC
86    extern int rfb_port;
87    extern int defer_time;
88    void
89    rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
90                    char *shell, char *directory);
91    #endif
92  /* Display usage information */  /* Display usage information */
93  static void 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_bitmap_cache = 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    #ifdef WITH_RDPSND
573                                                                    g_rdpsnd = False;
574    #else
575                                                                    warning("Not compiled with sound support");
576    #endif
577    
578                                                            optarg = p;
579                                                    }
580                                            }
581                                            else
582                                            {
583    #ifdef WITH_RDPSND
584                                                    g_rdpsnd = True;
585    #else
586                                                    warning("Not compiled with sound support");
587    #endif
588                                            }
589                                    }
590                                    else if (strncmp("disk", optarg, 4) == 0)
591                                    {
592                                            /* -r disk:h:=/mnt/floppy */
593                                            disk_enum_devices(&g_num_devices, optarg + 4);
594                                    }
595                                    else if (strncmp("comport", optarg, 7) == 0)
596                                    {
597                                            serial_enum_devices(&g_num_devices, optarg + 7);
598                                    }
599                                    else if (strncmp("lptport", optarg, 7) == 0)
600                                    {
601                                            parallel_enum_devices(&g_num_devices, optarg + 7);
602                                    }
603                                    else if (strncmp("printer", optarg, 7) == 0)
604                                    {
605                                            printer_enum_devices(&g_num_devices, optarg + 7);
606                                    }
607                                    else if (strncmp("clientname", optarg, 7) == 0)
608                                    {
609                                            g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
610                                            strcpy(g_rdpdr_clientname, optarg + 11);
611                                    }
612                                    else
613                                    {
614                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound\n");
615                                    }
616                                    break;
617    
618                            case '0':
619                                    g_console_session = True;
620                                    break;
621    
622                            case '4':
623                                    g_use_rdp5 = False;
624                                    break;
625    
626                            case '5':
627                                    g_use_rdp5 = True;
628                                    break;
629    
630                            case 'h':
631                          case '?':                          case '?':
632                          default:                          default:
633                                  usage(argv[0]);                                  usage(argv[0]);
# Line 105  int main(int argc, char *argv[]) Line 635  int main(int argc, char *argv[])
635                  }                  }
636          }          }
637    
638          if (argc - optind < 1)          if (argc - optind != 1)
639          {          {
640                  usage(argv[0]);                  usage(argv[0]);
641                  return 1;                  return 1;
642          }          }
643    
644          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
645            parse_server_and_port(server);
646    
647          if (username[0] == 0)          if (!username_option)
648          {          {
649                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
650                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
651                  {                  {
652                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
653                          return 1;                          return 1;
654                  }                  }
655    
656                  strncpy(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
657          }          }
658    
659          if (hostname[0] == 0)          if (hostname[0] == 0)
660          {          {
661                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
662                  {                  {
663                          STATUS("Could not determine host name.\n");                          error("could not determine local hostname, use -n\n");
664                          return 1;                          return 1;
665                  }                  }
666    
667                    p = strchr(fullhostname, '.');
668                    if (p != NULL)
669                            *p = 0;
670    
671                    STRNCPY(hostname, fullhostname, sizeof(hostname));
672          }          }
673    
674          if (!rdp_connect(server))          if (prompt_password && read_password(password, sizeof(password)))
675                    flags |= RDP_LOGON_AUTO;
676    
677            if (g_title[0] == 0)
678            {
679                    strcpy(g_title, "rdesktop - ");
680                    strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
681            }
682    
683    #ifdef RDP2VNC
684            rdp2vnc_connect(server, flags, domain, password, shell, directory);
685            return 0;
686    #else
687    
688            if (!ui_init())
689                  return 1;                  return 1;
690    
691          STATUS("Connection successful.\n");  #ifdef WITH_RDPSND
692            if (g_rdpsnd)
693                    rdpsnd_init();
694    #endif
695            rdpdr_init();
696    
697          strcpy(title, "rdesktop - ");          if (!rdp_connect(server, flags, domain, password, shell, directory))
698          strncat(title, server, sizeof(title));                  return 1;
699    
700          if (ui_create_window(title))          /* By setting encryption to False here, we have an encrypted login
701               packet but unencrypted transfer of other packets */
702            if (!packet_encryption)
703                    g_encryption = False;
704    
705    
706            DEBUG(("Connection successful.\n"));
707            memset(password, 0, sizeof(password));
708    
709            if (ui_create_window())
710          {          {
711                  rdp_main_loop();                  rdp_main_loop(&deactivated, &ext_disc_reason);
712                  ui_destroy_window();                  ui_destroy_window();
713          }          }
714    
715            DEBUG(("Disconnecting...\n"));
716          rdp_disconnect();          rdp_disconnect();
717          return 0;          ui_deinit();
718    
719            if (ext_disc_reason >= 2)
720                    print_disconnect_reason(ext_disc_reason);
721    
722            if (deactivated)
723            {
724                    /* clean disconnect */
725                    return 0;
726            }
727            else
728            {
729                    if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
730                        || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
731                    {
732                            /* not so clean disconnect, but nothing to worry about */
733                            return 0;
734                    }
735                    else
736                    {
737                            /* return error */
738                            return 2;
739                    }
740            }
741    
742    #endif
743    
744  }  }
745    
746  /* Generate a 32-byte random for the secure transport code. */  #ifdef EGD_SOCKET
747  void generate_random(uint8 *random)  /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
748    static BOOL
749    generate_random_egd(uint8 * buf)
750  {  {
751          struct stat st;          struct sockaddr_un addr;
752          uint32 *r = (uint32 *)random;          BOOL ret = False;
753          int fd;          int fd;
754    
755          /* If we have a kernel random device, use it. */          fd = socket(AF_UNIX, SOCK_STREAM, 0);
756          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (fd == -1)
757                    return False;
758    
759            addr.sun_family = AF_UNIX;
760            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
761            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
762                    goto err;
763    
764            /* PRNGD and EGD use a simple communications protocol */
765            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
766            buf[1] = 32;            /* Number of requested random bytes */
767            if (write(fd, buf, 2) != 2)
768                    goto err;
769    
770            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
771                    goto err;
772    
773            if (read(fd, buf, 32) != 32)
774                    goto err;
775    
776            ret = True;
777    
778          err:
779            close(fd);
780            return ret;
781    }
782    #endif
783    
784    /* Generate a 32-byte random for the secure transport code. */
785    void
786    generate_random(uint8 * random)
787    {
788            struct stat st;
789            struct tms tmsbuf;
790            MD5_CTX md5;
791            uint32 *r;
792            int fd, n;
793    
794            /* If we have a kernel random device, try that first */
795            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
796                || ((fd = open("/dev/random", O_RDONLY)) != -1))
797          {          {
798                  read(fd, random, 32);                  n = read(fd, random, 32);
799                  close(fd);                  close(fd);
800                  return;                  if (n == 32)
801                            return;
802          }          }
803    
804    #ifdef EGD_SOCKET
805            /* As a second preference use an EGD */
806            if (generate_random_egd(random))
807                    return;
808    #endif
809    
810          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
811            r = (uint32 *) random;
812          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
813          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
814          r[2] = times(NULL); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
815          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
816          stat("/tmp", &st);          stat("/tmp", &st);
817          r[5] = st.st_atime;          r[5] = st.st_atime;
818          r[6] = st.st_mtime;          r[6] = st.st_mtime;
819          r[7] = st.st_ctime;          r[7] = st.st_ctime;
820    
821            /* Hash both halves with MD5 to obscure possible patterns */
822            MD5_Init(&md5);
823            MD5_Update(&md5, random, 16);
824            MD5_Final(random, &md5);
825            MD5_Update(&md5, random + 16, 16);
826            MD5_Final(random + 16, &md5);
827  }  }
828    
829  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
830  void *xmalloc(int size)  void *
831    xmalloc(int size)
832  {  {
833          void *mem = malloc(size);          void *mem = malloc(size);
834          if (mem == NULL)          if (mem == NULL)
835          {          {
836                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
837                  exit(1);                  exit(1);
838          }          }
839          return mem;          return mem;
840  }  }
841    
842  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
843  void *xrealloc(void *oldmem, int size)  void *
844    xrealloc(void *oldmem, int size)
845  {  {
846          void *mem = realloc(oldmem, size);          void *mem = realloc(oldmem, size);
847          if (mem == NULL)          if (mem == NULL)
848          {          {
849                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
850                  exit(1);                  exit(1);
851          }          }
852          return mem;          return mem;
853  }  }
854    
855  /* free */  /* free */
856  void xfree(void *mem)  void
857    xfree(void *mem)
858  {  {
859          free(mem);          free(mem);
860  }  }
861    
862  /* Produce a hex dump */  /* report an error */
863  void hexdump(unsigned char *p, unsigned int len)  void
864    error(char *format, ...)
865    {
866            va_list ap;
867    
868            fprintf(stderr, "ERROR: ");
869    
870            va_start(ap, format);
871            vfprintf(stderr, format, ap);
872            va_end(ap);
873    }
874    
875    /* report a warning */
876    void
877    warning(char *format, ...)
878    {
879            va_list ap;
880    
881            fprintf(stderr, "WARNING: ");
882    
883            va_start(ap, format);
884            vfprintf(stderr, format, ap);
885            va_end(ap);
886    }
887    
888    /* report an unimplemented protocol feature */
889    void
890    unimpl(char *format, ...)
891    {
892            va_list ap;
893    
894            fprintf(stderr, "NOT IMPLEMENTED: ");
895    
896            va_start(ap, format);
897            vfprintf(stderr, format, ap);
898            va_end(ap);
899    }
900    
901    /* produce a hex dump */
902    void
903    hexdump(unsigned char *p, unsigned int len)
904  {  {
905          unsigned char *line = p;          unsigned char *line = p;
906          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
907    
908          while (offset < len)          while (offset < len)
909          {          {
910                  STATUS("%04x ", offset);                  printf("%04x ", offset);
911                  thisline = len - offset;                  thisline = len - offset;
912                  if (thisline > 16)                  if (thisline > 16)
913                          thisline = 16;                          thisline = 16;
914    
915                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
916                          STATUS("%02x ", line[i])                          printf("%02x ", line[i]);
917    
918                  for (; i < 16; i++)                  for (; i < 16; i++)
919                          STATUS("   ");                          printf("   ");
920    
921                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
922                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
923    
924                  STATUS("\n");                  printf("\n");
925                  offset += thisline;                  offset += thisline;
926                  line += thisline;                  line += thisline;
927          }          }
928  }  }
929    
930    /*
931      input: src is the string we look in for needle.
932             Needle may be escaped by a backslash, in
933             that case we ignore that particular needle.
934      return value: returns next src pointer, for
935            succesive executions, like in a while loop
936            if retval is 0, then there are no more args.
937      pitfalls:
938            src is modified. 0x00 chars are inserted to
939            terminate strings.
940            return val, points on the next val chr after ins
941            0x00
942    
943            example usage:
944            while( (pos = next_arg( optarg, ',')) ){
945                    printf("%s\n",optarg);
946                    optarg=pos;
947            }
948    
949    */
950    char *
951    next_arg(char *src, char needle)
952    {
953            char *nextval;
954            char *p;
955            char *mvp = 0;
956    
957            /* EOS */
958            if (*src == (char) 0x00)
959                    return 0;
960    
961            p = src;
962            /*  skip escaped needles */
963            while ((nextval = strchr(p, needle)))
964            {
965                    mvp = nextval - 1;
966                    /* found backslashed needle */
967                    if (*mvp == '\\' && (mvp > src))
968                    {
969                            /* move string one to the left */
970                            while (*(mvp + 1) != (char) 0x00)
971                            {
972                                    *mvp = *(mvp + 1);
973                                    *mvp++;
974                            }
975                            *mvp = (char) 0x00;
976                            p = nextval;
977                    }
978                    else
979                    {
980                            p = nextval + 1;
981                            break;
982                    }
983    
984            }
985    
986            /* more args available */
987            if (nextval)
988            {
989                    *nextval = (char) 0x00;
990                    return ++nextval;
991            }
992    
993            /* no more args after this, jump to EOS */
994            nextval = src + strlen(src);
995            return nextval;
996    }
997    
998    
999    void
1000    toupper_str(char *p)
1001    {
1002            while (*p)
1003            {
1004                    if ((*p >= 'a') && (*p <= 'z'))
1005                            *p = toupper((int) *p);
1006                    p++;
1007            }
1008    }
1009    
1010    
1011    /* not all clibs got ltoa */
1012    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1013    
1014    char *
1015    l_to_a(long N, int base)
1016    {
1017            static char ret[LTOA_BUFSIZE];
1018    
1019            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1020    
1021            register int divrem;
1022    
1023            if (base < 36 || 2 > base)
1024                    base = 10;
1025    
1026            if (N < 0)
1027            {
1028                    *head++ = '-';
1029                    N = -N;
1030            }
1031    
1032            tail = buf + sizeof(buf);
1033            *--tail = 0;
1034    
1035            do
1036            {
1037                    divrem = N % base;
1038                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1039                    N /= base;
1040            }
1041            while (N);
1042    
1043            strcpy(head, tail);
1044            return ret;
1045    }
1046    
1047    
1048    int
1049    load_licence(unsigned char **data)
1050    {
1051            char *home, *path;
1052            struct stat st;
1053            int fd, length;
1054    
1055            home = getenv("HOME");
1056            if (home == NULL)
1057                    return -1;
1058    
1059            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
1060            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
1061    
1062            fd = open(path, O_RDONLY);
1063            if (fd == -1)
1064                    return -1;
1065    
1066            if (fstat(fd, &st))
1067                    return -1;
1068    
1069            *data = (uint8 *) xmalloc(st.st_size);
1070            length = read(fd, *data, st.st_size);
1071            close(fd);
1072            xfree(path);
1073            return length;
1074    }
1075    
1076    void
1077    save_licence(unsigned char *data, int length)
1078    {
1079            char *home, *path, *tmppath;
1080            int fd;
1081    
1082            home = getenv("HOME");
1083            if (home == NULL)
1084                    return;
1085    
1086            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
1087    
1088            sprintf(path, "%s/.rdesktop", home);
1089            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1090            {
1091                    perror(path);
1092                    return;
1093            }
1094    
1095            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1096    
1097            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
1098            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1099            strcpy(tmppath, path);
1100            strcat(tmppath, ".new");
1101    
1102            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1103            if (fd == -1)
1104            {
1105                    perror(tmppath);
1106                    return;
1107            }
1108    
1109            if (write(fd, data, length) != length)
1110            {
1111                    perror(tmppath);
1112                    unlink(tmppath);
1113            }
1114            else if (rename(tmppath, path) == -1)
1115            {
1116                    perror(path);
1117                    unlink(tmppath);
1118            }
1119    
1120            close(fd);
1121            xfree(tmppath);
1122            xfree(path);
1123    }

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

  ViewVC Help
Powered by ViewVC 1.1.26