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

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

  ViewVC Help
Powered by ViewVC 1.1.26