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

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

  ViewVC Help
Powered by ViewVC 1.1.26