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

Legend:
Removed from v.29  
changed lines
  Added in v.608

  ViewVC Help
Powered by ViewVC 1.1.26