/[rdesktop]/sourceforge.net/trunk/rdesktop/rdesktop.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/rdesktop.c

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

revision 22 by matty, Tue Oct 17 06:12:31 2000 UTC revision 628 by n-ki, Thu Mar 4 12:43:10 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 = True;  
 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    extern BOOL g_owncolmap;
72    extern BOOL g_ownbackstore;
73    
74    #ifdef WITH_RDPSND
75    BOOL g_rdpsnd = False;
76    #endif
77    
78    extern RDPDR_DEVICE g_rdpdr_device[];
79    extern uint32 g_num_devices;
80    
81    #ifdef RDP2VNC
82    extern int rfb_port;
83    extern int defer_time;
84    void
85    rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
86                    char *shell, char *directory);
87    #endif
88  /* Display usage information */  /* Display usage information */
89  static void usage(char *program)  static void
90    usage(char *program)
91    {
92            fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
93            fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
94            fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
95    
96            fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
97    #ifdef RDP2VNC
98            fprintf(stderr, "   -V: vnc port\n");
99            fprintf(stderr, "   -Q: defer time (ms)\n");
100    #endif
101            fprintf(stderr, "   -u: user name\n");
102            fprintf(stderr, "   -d: domain\n");
103            fprintf(stderr, "   -s: shell\n");
104            fprintf(stderr, "   -c: working directory\n");
105            fprintf(stderr, "   -p: password (- to prompt)\n");
106            fprintf(stderr, "   -n: client hostname\n");
107            fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
108            fprintf(stderr, "   -g: desktop geometry (WxH)\n");
109            fprintf(stderr, "   -f: full-screen mode\n");
110            fprintf(stderr, "   -b: force bitmap updates\n");
111            fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");
112            fprintf(stderr, "   -e: disable encryption (French TS)\n");
113            fprintf(stderr, "   -E: disable encryption from client to server\n");
114            fprintf(stderr, "   -m: do not send motion events\n");
115            fprintf(stderr, "   -C: use private colour map\n");
116            fprintf(stderr, "   -D: hide window manager decorations\n");
117            fprintf(stderr, "   -K: keep window manager key bindings\n");
118            fprintf(stderr, "   -S: caption button size (single application mode)\n");
119            fprintf(stderr, "   -T: window title\n");
120            fprintf(stderr, "   -N: enable numlock syncronization\n");
121            fprintf(stderr, "   -a: connection colour depth\n");
122            fprintf(stderr, "   -r: enable specified device redirection (this flag can be repeated)\n");
123            fprintf(stderr,
124                    "         '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n");
125            fprintf(stderr, "             or      COM1=/dev/ttyS0,COM2=/dev/ttyS1\n");
126            fprintf(stderr,
127                    "         '-r disk:A=/mnt/floppy': enable redirection of /mnt/floppy to A:\n");
128            fprintf(stderr, "             or   A=/mnt/floppy,D=/mnt/cdrom'\n");
129            fprintf(stderr,
130                    "         '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1\n");
131            fprintf(stderr, "             or      LPT1=/dev/lp0,LPT2=/dev/lp1\n");
132            fprintf(stderr, "         '-r printer:mydeskjet': enable printer redirection\n");
133            fprintf(stderr,
134                    "             or      mydeskjet=\"HP LaserJet IIIP\" to enter server driver as well\n");
135            fprintf(stderr, "         '-r sound:[on|off|remote]': enable sound redirection\n");
136            fprintf(stderr, "                     remote would leave sound on server\n");
137            fprintf(stderr, "   -0: attach to console\n");
138            fprintf(stderr, "   -4: use RDP version 4\n");
139            fprintf(stderr, "   -5: use RDP version 5 (default)\n");
140    }
141    
142    static BOOL
143    read_password(char *password, int size)
144  {  {
145          STATUS("Usage: %s [options] server\n", program);          struct termios tios;
146          STATUS("   -u: user name\n");          BOOL ret = False;
147          STATUS("   -d: domain\n");          int istty = 0;
148          STATUS("   -s: shell\n");          char *p;
149          STATUS("   -c: working directory\n");  
150          STATUS("   -p: password (autologon)\n");          if (tcgetattr(STDIN_FILENO, &tios) == 0)
151          STATUS("   -n: client hostname\n");          {
152          STATUS("   -w: desktop width\n");                  fprintf(stderr, "Password: ");
153          STATUS("   -h: desktop height\n");                  tios.c_lflag &= ~ECHO;
154          STATUS("   -k: keyboard layout (hex)\n");                  tcsetattr(STDIN_FILENO, TCSANOW, &tios);
155          STATUS("   -b: force bitmap updates\n");                  istty = 1;
156          STATUS("   -m: do not send motion events\n");          }
157          STATUS("   -l: do not request licence\n\n");  
158            if (fgets(password, size, stdin) != NULL)
159            {
160                    ret = True;
161    
162                    /* strip final newline */
163                    p = strchr(password, '\n');
164                    if (p != NULL)
165                            *p = 0;
166            }
167    
168            if (istty)
169            {
170                    tios.c_lflag |= ECHO;
171                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
172                    fprintf(stderr, "\n");
173            }
174    
175            return ret;
176    }
177    
178    static void
179    parse_server_and_port(char *server)
180    {
181            char *p;
182    #ifdef IPv6
183            int addr_colons;
184    #endif
185    
186    #ifdef IPv6
187            p = server;
188            addr_colons = 0;
189            while (*p)
190                    if (*p++ == ':')
191                            addr_colons++;
192            if (addr_colons >= 2)
193            {
194                    /* numeric IPv6 style address format - [1:2:3::4]:port */
195                    p = strchr(server, ']');
196                    if (*server == '[' && p != NULL)
197                    {
198                            if (*(p + 1) == ':' && *(p + 2) != '\0')
199                                    tcp_port_rdp = strtol(p + 2, NULL, 10);
200                            /* remove the port number and brackets from the address */
201                            *p = '\0';
202                            strncpy(server, server + 1, strlen(server));
203                    }
204            }
205            else
206            {
207                    /* dns name or IPv4 style address format - server.example.com:port or 1.2.3.4:port */
208                    p = strchr(server, ':');
209                    if (p != NULL)
210                    {
211                            tcp_port_rdp = strtol(p + 1, NULL, 10);
212                            *p = 0;
213                    }
214            }
215    #else /* no IPv6 support */
216            p = strchr(server, ':');
217            if (p != NULL)
218            {
219                    tcp_port_rdp = strtol(p + 1, NULL, 10);
220                    *p = 0;
221            }
222    #endif /* IPv6 */
223    
224  }  }
225    
226  /* Client program */  /* Client program */
227  int main(int argc, char *argv[])  int
228    main(int argc, char *argv[])
229  {  {
230          struct passwd *pw;          char server[64];
231          char *server;          char fullhostname[64];
         uint32 flags;  
232          char domain[16];          char domain[16];
233          char password[16];          char password[64];
234          char shell[32];          char shell[128];
235          char directory[32];          char directory[32];
236          char title[32];          BOOL prompt_password, rdp_retval = False;
237            struct passwd *pw;
238            uint32 flags;
239            char *p;
240          int c;          int c;
241    
242          STATUS("rdesktop: A Remote Desktop Protocol client.\n");          int username_option = 0;
         STATUS("Version "VERSION". Copyright (C) 1999-2000 Matt Chapman.\n");  
         STATUS("See http://www.rdesktop.org/ for more information.\n\n");  
243    
244          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
245            prompt_password = False;
246          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
247            strcpy(keymapname, "en-us");
248    
249            g_num_devices = 0;
250    
251          while ((c = getopt(argc, argv, "u:d:s:c:p:n:w:h:k:bml?")) != -1)  #ifdef RDP2VNC
252    #define VNCOPT "V:Q:"
253    #else
254    #define VNCOPT
255    #endif
256    
257            while ((c = getopt(argc, argv, VNCOPT "u:d:s:c:p:n:k:g:fbBeEmCDKS:T:Na:r:045h?")) != -1)
258          {          {
259                  switch (c)                  switch (c)
260                  {                  {
261    #ifdef RDP2VNC
262                            case 'V':
263                                    rfb_port = strtol(optarg, NULL, 10);
264                                    if (rfb_port < 100)
265                                            rfb_port += 5900;
266                                    break;
267    
268                            case 'Q':
269                                    defer_time = strtol(optarg, NULL, 10);
270                                    if (defer_time < 0)
271                                            defer_time = 0;
272                                    break;
273    #endif
274    
275                          case 'u':                          case 'u':
276                                  strncpy(username, optarg, sizeof(username));                                  STRNCPY(g_username, optarg, sizeof(g_username));
277                                    username_option = 1;
278                                  break;                                  break;
279    
280                          case 'd':                          case 'd':
281                                  strncpy(domain, optarg, sizeof(domain));                                  STRNCPY(domain, optarg, sizeof(domain));
282                                    break;
283    
284                            case 's':
285                                    STRNCPY(shell, optarg, sizeof(shell));
286                                    break;
287    
288                            case 'c':
289                                    STRNCPY(directory, optarg, sizeof(directory));
290                                  break;                                  break;
291    
292                          case 'p':                          case 'p':
293                                    if ((optarg[0] == '-') && (optarg[1] == 0))
294                                    {
295                                            prompt_password = True;
296                                            break;
297                                    }
298    
299                                    STRNCPY(password, optarg, sizeof(password));
300                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
301                                  strncpy(password, optarg, sizeof(password));  
302                                    /* try to overwrite argument so it won't appear in ps */
303                                    p = optarg;
304                                    while (*p)
305                                            *(p++) = 'X';
306                                  break;                                  break;
307    
308                          case 's':                          case 'n':
309                                  strncpy(shell, optarg, sizeof(shell));                                  STRNCPY(hostname, optarg, sizeof(hostname));
310                                  break;                                  break;
311    
312                          case 'c':                          case 'k':
313                                  strncpy(directory, optarg, sizeof(directory));                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
314                                  break;                                  break;
315    
316                          case 'n':                          case 'g':
317                                  strncpy(hostname, optarg, sizeof(hostname));                                  g_fullscreen = False;
318                                    if (!strcmp(optarg, "workarea"))
319                                    {
320                                            g_width = g_height = 0;
321                                            break;
322                                    }
323    
324                                    g_width = strtol(optarg, &p, 10);
325                                    if (g_width <= 0)
326                                    {
327                                            error("invalid geometry\n");
328                                            return 1;
329                                    }
330    
331                                    if (*p == 'x')
332                                            g_height = strtol(p + 1, NULL, 10);
333    
334                                    if (g_height <= 0)
335                                    {
336                                            error("invalid geometry\n");
337                                            return 1;
338                                    }
339    
340                                    if (*p == '%')
341                                            g_width = -g_width;
342    
343                                  break;                                  break;
344    
345                          case 'w':                          case 'f':
346                                  width = strtol(optarg, NULL, 10);                                  g_fullscreen = True;
347                                  break;                                  break;
348    
349                          case 'h':                          case 'b':
350                                  height = strtol(optarg, NULL, 10);                                  g_orders = False;
351                                  break;                                  break;
352    
353                          case 'k':                          case 'B':
354                                  keylayout = strtol(optarg, NULL, 16);                                  g_ownbackstore = False;
355                                  break;                                  break;
356    
357                            case 'e':
358                                    g_encryption = False;
359                                    break;
360                            case 'E':
361                                    packet_encryption = False;
362                                    break;
363                          case 'm':                          case 'm':
364                                  motion = False;                                  g_sendmotion = False;
365                                  break;                                  break;
366    
367                          case 'b':                          case 'C':
368                                  orders = False;                                  g_owncolmap = True;
369                                    break;
370    
371                            case 'D':
372                                    g_hide_decorations = True;
373                                    break;
374    
375                            case 'K':
376                                    g_grab_keyboard = False;
377                                    break;
378    
379                            case 'S':
380                                    if (!strcmp(optarg, "standard"))
381                                    {
382                                            g_win_button_size = 18;
383                                            break;
384                                    }
385    
386                                    g_win_button_size = strtol(optarg, &p, 10);
387    
388                                    if (*p)
389                                    {
390                                            error("invalid button size\n");
391                                            return 1;
392                                    }
393    
394                                    break;
395    
396                            case 'T':
397                                    STRNCPY(g_title, optarg, sizeof(g_title));
398                                    break;
399    
400                            case 'N':
401                                    g_numlock_sync = True;
402                                    break;
403    
404                            case 'a':
405                                    g_server_bpp = strtol(optarg, NULL, 10);
406                                    if (g_server_bpp != 8 && g_server_bpp != 16 && g_server_bpp != 15
407                                        && g_server_bpp != 24)
408                                    {
409                                            error("invalid server bpp\n");
410                                            return 1;
411                                    }
412                                    break;
413    
414                            case 'r':
415    
416                                    if (strncmp("sound", optarg, 5) == 0)
417                                    {
418                                            if (*(optarg + 6) == ':')
419                                            {
420    
421                                                    if (strncmp("remote", optarg + 7, 6) == 0)
422                                                            flags |= RDP_LOGON_LEAVE_AUDIO;
423                                                    else if (strncmp("on", optarg + 7, 2) == 0)
424                                                    {
425    #ifdef WITH_RDPSND
426                                                            g_rdpsnd = True;
427    #else
428                                                            warning("Not compiled with sound support");
429    #endif
430                                                    }
431                                            }
432                                            else
433                                            {
434    #ifdef WITH_RDPSND
435                                                    g_rdpsnd = True;
436    #else
437                                                    warning("Not compiled with sound support");
438    #endif
439                                            }
440                                    }
441                                    else if (strncmp("disk", optarg, 4) == 0)
442                                    {
443                                            /* -r disk:h:=/mnt/floppy */
444                                            disk_enum_devices(&g_num_devices, optarg + 4);
445                                    }
446                                    else if (strncmp("comport", optarg, 7) == 0)
447                                    {
448                                            serial_enum_devices(&g_num_devices, optarg + 7);
449                                    }
450                                    else if (strncmp("lptport", optarg, 7) == 0)
451                                    {
452                                            parallel_enum_devices(&g_num_devices, optarg + 7);
453                                    }
454                                    else if (strncmp("printer", optarg, 7) == 0)
455                                    {
456                                            printer_enum_devices(&g_num_devices, optarg + 7);
457                                    }
458                                    else
459                                    {
460                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound\n");
461                                    }
462                                    break;
463    
464                            case '0':
465                                    g_console_session = True;
466                                  break;                                  break;
467    
468                          case 'l':                          case '4':
469                                  licence = False;                                  g_use_rdp5 = False;
470                                  break;                                  break;
471    
472                            case '5':
473                                    g_use_rdp5 = True;
474                                    break;
475    
476                            case 'h':
477                          case '?':                          case '?':
478                          default:                          default:
479                                  usage(argv[0]);                                  usage(argv[0]);
# Line 134  int main(int argc, char *argv[]) Line 481  int main(int argc, char *argv[])
481                  }                  }
482          }          }
483    
484          if (argc - optind < 1)          if (argc - optind != 1)
485          {          {
486                  usage(argv[0]);                  usage(argv[0]);
487                  return 1;                  return 1;
488          }          }
489    
490          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
491            parse_server_and_port(server);
492    
493          if (username[0] == 0)          if (!username_option)
494          {          {
495                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
496                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
497                  {                  {
498                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
499                          return 1;                          return 1;
500                  }                  }
501    
502                  strncpy(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
503          }          }
504    
505          if (hostname[0] == 0)          if (hostname[0] == 0)
506          {          {
507                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
508                  {                  {
509                          STATUS("Could not determine host name.\n");                          error("could not determine local hostname, use -n\n");
510                          return 1;                          return 1;
511                  }                  }
512    
513                    p = strchr(fullhostname, '.');
514                    if (p != NULL)
515                            *p = 0;
516    
517                    STRNCPY(hostname, fullhostname, sizeof(hostname));
518            }
519    
520            if (prompt_password && read_password(password, sizeof(password)))
521                    flags |= RDP_LOGON_AUTO;
522    
523            if (g_title[0] == 0)
524            {
525                    strcpy(g_title, "rdesktop - ");
526                    strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
527          }          }
528    
529    #ifdef RDP2VNC
530            rdp2vnc_connect(server, flags, domain, password, shell, directory);
531            return 0;
532    #else
533    
534            if (!ui_init())
535                    return 1;
536    
537    #ifdef WITH_RDPSND
538            if (g_rdpsnd)
539                    rdpsnd_init();
540    #endif
541            rdpdr_init();
542    
543          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
544                  return 1;                  return 1;
545    
546          STATUS("Connection successful.\n");          /* By setting encryption to False here, we have an encrypted login
547               packet but unencrypted transfer of other packets */
548            if (!packet_encryption)
549                    g_encryption = False;
550    
551    
552          strcpy(title, "rdesktop - ");          DEBUG(("Connection successful.\n"));
553          strncat(title, server, sizeof(title));          memset(password, 0, sizeof(password));
554    
555          if (ui_create_window(title))          if (ui_create_window())
556          {          {
557                  rdp_main_loop();                  rdp_retval = rdp_main_loop();
558                  ui_destroy_window();                  ui_destroy_window();
559          }          }
560    
561            DEBUG(("Disconnecting...\n"));
562          rdp_disconnect();          rdp_disconnect();
563          return 0;          ui_deinit();
564    
565            if (True == rdp_retval)
566                    return 0;
567            else
568                    return 2;
569    
570    #endif
571    
572  }  }
573    
574    #ifdef EGD_SOCKET
575    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
576    static BOOL
577    generate_random_egd(uint8 * buf)
578    {
579            struct sockaddr_un addr;
580            BOOL ret = False;
581            int fd;
582    
583            fd = socket(AF_UNIX, SOCK_STREAM, 0);
584            if (fd == -1)
585                    return False;
586    
587            addr.sun_family = AF_UNIX;
588            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
589            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
590                    goto err;
591    
592            /* PRNGD and EGD use a simple communications protocol */
593            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
594            buf[1] = 32;            /* Number of requested random bytes */
595            if (write(fd, buf, 2) != 2)
596                    goto err;
597    
598            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
599                    goto err;
600    
601            if (read(fd, buf, 32) != 32)
602                    goto err;
603    
604            ret = True;
605    
606          err:
607            close(fd);
608            return ret;
609    }
610    #endif
611    
612  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
613  void generate_random(uint8 *random)  void
614    generate_random(uint8 * random)
615  {  {
616          struct stat st;          struct stat st;
617          struct tms tmsbuf;          struct tms tmsbuf;
618          uint32 *r = (uint32 *)random;          MD5_CTX md5;
619          int fd;          uint32 *r;
620            int fd, n;
621          /* If we have a kernel random device, use it. */  
622          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          /* If we have a kernel random device, try that first */
623            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
624                || ((fd = open("/dev/random", O_RDONLY)) != -1))
625          {          {
626                  read(fd, random, 32);                  n = read(fd, random, 32);
627                  close(fd);                  close(fd);
628                  return;                  if (n == 32)
629                            return;
630          }          }
631    
632    #ifdef EGD_SOCKET
633            /* As a second preference use an EGD */
634            if (generate_random_egd(random))
635                    return;
636    #endif
637    
638          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
639            r = (uint32 *) random;
640          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
641          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
642          r[2] = times(&tmsbuf); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
643          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
644          stat("/tmp", &st);          stat("/tmp", &st);
645          r[5] = st.st_atime;          r[5] = st.st_atime;
646          r[6] = st.st_mtime;          r[6] = st.st_mtime;
647          r[7] = st.st_ctime;          r[7] = st.st_ctime;
648    
649            /* Hash both halves with MD5 to obscure possible patterns */
650            MD5_Init(&md5);
651            MD5_Update(&md5, random, 16);
652            MD5_Final(random, &md5);
653            MD5_Update(&md5, random + 16, 16);
654            MD5_Final(random + 16, &md5);
655  }  }
656    
657  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
658  void *xmalloc(int size)  void *
659    xmalloc(int size)
660  {  {
661          void *mem = malloc(size);          void *mem = malloc(size);
662          if (mem == NULL)          if (mem == NULL)
663          {          {
664                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
665                  exit(1);                  exit(1);
666          }          }
667          return mem;          return mem;
668  }  }
669    
670  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
671  void *xrealloc(void *oldmem, int size)  void *
672    xrealloc(void *oldmem, int size)
673  {  {
674          void *mem = realloc(oldmem, size);          void *mem = realloc(oldmem, size);
675          if (mem == NULL)          if (mem == NULL)
676          {          {
677                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
678                  exit(1);                  exit(1);
679          }          }
680          return mem;          return mem;
681  }  }
682    
683  /* free */  /* free */
684  void xfree(void *mem)  void
685    xfree(void *mem)
686  {  {
687          free(mem);          free(mem);
688  }  }
689    
690  /* Produce a hex dump */  /* report an error */
691  void hexdump(unsigned char *p, unsigned int len)  void
692    error(char *format, ...)
693    {
694            va_list ap;
695    
696            fprintf(stderr, "ERROR: ");
697    
698            va_start(ap, format);
699            vfprintf(stderr, format, ap);
700            va_end(ap);
701    }
702    
703    /* report a warning */
704    void
705    warning(char *format, ...)
706    {
707            va_list ap;
708    
709            fprintf(stderr, "WARNING: ");
710    
711            va_start(ap, format);
712            vfprintf(stderr, format, ap);
713            va_end(ap);
714    }
715    
716    /* report an unimplemented protocol feature */
717    void
718    unimpl(char *format, ...)
719    {
720            va_list ap;
721    
722            fprintf(stderr, "NOT IMPLEMENTED: ");
723    
724            va_start(ap, format);
725            vfprintf(stderr, format, ap);
726            va_end(ap);
727    }
728    
729    /* produce a hex dump */
730    void
731    hexdump(unsigned char *p, unsigned int len)
732  {  {
733          unsigned char *line = p;          unsigned char *line = p;
734          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
735    
736          while (offset < len)          while (offset < len)
737          {          {
738                  STATUS("%04x ", offset);                  printf("%04x ", offset);
739                  thisline = len - offset;                  thisline = len - offset;
740                  if (thisline > 16)                  if (thisline > 16)
741                          thisline = 16;                          thisline = 16;
742    
743                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
744                          STATUS("%02x ", line[i])                          printf("%02x ", line[i]);
745    
746                  for (; i < 16; i++)                  for (; i < 16; i++)
747                          STATUS("   ");                          printf("   ");
748    
749                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
750                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
751    
752                  STATUS("\n");                  printf("\n");
753                  offset += thisline;                  offset += thisline;
754                  line += thisline;                  line += thisline;
755          }          }
756  }  }
757    
758    /*
759      input: src is the string we look in for needle.
760             Needle may be escaped by a backslash, in
761             that case we ignore that particular needle.
762      return value: returns next src pointer, for
763            succesive executions, like in a while loop
764            if retval is 0, then there are no more args.
765      pitfalls:
766            src is modified. 0x00 chars are inserted to
767            terminate strings.
768            return val, points on the next val chr after ins
769            0x00
770    
771            example usage:
772            while( (pos = next_arg( optarg, ',')) ){
773                    printf("%s\n",optarg);
774                    optarg=pos;
775            }
776    
777    */
778    char *
779    next_arg(char *src, char needle)
780    {
781            char *nextval;
782            char *p;
783            char *mvp = 0;
784    
785            /* EOS */
786            if (*src == (char) 0x00)
787                    return 0;
788    
789            p = src;
790            /*  skip escaped needles */
791            while ((nextval = strchr(p, needle)))
792            {
793                    mvp = nextval - 1;
794                    /* found backslashed needle */
795                    if (*mvp == '\\' && (mvp > src))
796                    {
797                            /* move string one to the left */
798                            while (*(mvp + 1) != (char) 0x00)
799                            {
800                                    *mvp = *(mvp + 1);
801                                    *mvp++;
802                            }
803                            *mvp = (char) 0x00;
804                            p = nextval;
805                    }
806                    else
807                    {
808                            p = nextval + 1;
809                            break;
810                    }
811    
812            }
813    
814            /* more args available */
815            if (nextval)
816            {
817                    *nextval = (char) 0x00;
818                    return ++nextval;
819            }
820    
821            /* no more args after this, jump to EOS */
822            nextval = src + strlen(src);
823            return nextval;
824    }
825    
826    
827    void
828    toupper_str(char *p)
829    {
830            while (*p)
831            {
832                    if ((*p >= 'a') && (*p <= 'z'))
833                            *p = toupper((int) *p);
834                    p++;
835            }
836    }
837    
838    
839    /* not all clibs got ltoa */
840    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
841    
842    char *
843    l_to_a(long N, int base)
844    {
845            static char ret[LTOA_BUFSIZE];
846    
847            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
848    
849            register int divrem;
850    
851            if (base < 36 || 2 > base)
852                    base = 10;
853    
854            if (N < 0)
855            {
856                    *head++ = '-';
857                    N = -N;
858            }
859    
860            tail = buf + sizeof(buf);
861            *--tail = 0;
862    
863            do
864            {
865                    divrem = N % base;
866                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
867                    N /= base;
868            }
869            while (N);
870    
871            strcpy(head, tail);
872            return ret;
873    }
874    
875    
876    int
877    load_licence(unsigned char **data)
878    {
879            char *home, *path;
880            struct stat st;
881            int fd, length;
882    
883            home = getenv("HOME");
884            if (home == NULL)
885                    return -1;
886    
887            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
888            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
889    
890            fd = open(path, O_RDONLY);
891            if (fd == -1)
892                    return -1;
893    
894            if (fstat(fd, &st))
895                    return -1;
896    
897            *data = (uint8 *) xmalloc(st.st_size);
898            length = read(fd, *data, st.st_size);
899            close(fd);
900            xfree(path);
901            return length;
902    }
903    
904    void
905    save_licence(unsigned char *data, int length)
906    {
907            char *home, *path, *tmppath;
908            int fd;
909    
910            home = getenv("HOME");
911            if (home == NULL)
912                    return;
913    
914            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
915    
916            sprintf(path, "%s/.rdesktop", home);
917            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
918            {
919                    perror(path);
920                    return;
921            }
922    
923            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
924    
925            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
926            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
927            strcpy(tmppath, path);
928            strcat(tmppath, ".new");
929    
930            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
931            if (fd == -1)
932            {
933                    perror(tmppath);
934                    return;
935            }
936    
937            if (write(fd, data, length) != length)
938            {
939                    perror(tmppath);
940                    unlink(tmppath);
941            }
942            else if (rename(tmppath, path) == -1)
943            {
944                    perror(path);
945                    unlink(tmppath);
946            }
947    
948            close(fd);
949            xfree(tmppath);
950            xfree(path);
951    }

Legend:
Removed from v.22  
changed lines
  Added in v.628

  ViewVC Help
Powered by ViewVC 1.1.26