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

Diff of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/rdesktop.c

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

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

Legend:
Removed from v.25  
changed lines
  Added in v.609

  ViewVC Help
Powered by ViewVC 1.1.26