/[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 79 by astrand, Mon Jul 29 20:35:13 2002 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-2001     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    
 #include <stdlib.h>             /* malloc realloc free */  
21  #include <stdarg.h>             /* va_list va_start va_end */  #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 <limits.h>             /* PATH_MAX */  #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  char keymapname[16];  char keymapname[16];
48  int keylayout = 0x409;          /* Defaults to US keyboard layout */  int keylayout = 0x409;          /* Defaults to US keyboard layout */
 int width;  
 int height;  
 int tcp_port_rdp = TCP_PORT_RDP;  
 BOOL bitmap_compression = True;  
 BOOL sendmotion = True;  
 BOOL orders = True;  
 BOOL licence = True;  
 BOOL encryption = True;  
 BOOL desktop_save = True;  
 BOOL fullscreen = False;  
 BOOL grab_keyboard = 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          printf("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
93          printf("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
94          printf("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
95          printf("   -s: shell\n");  
96          printf("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
97          printf("   -p: password (autologon)\n");  #ifdef RDP2VNC
98          printf("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
99          printf("   -k: keyboard layout on terminal server (us,sv,gr etc.)\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
100          printf("   -g: desktop geometry (WxH)\n");  #endif
101          printf("   -f: full-screen mode\n");          fprintf(stderr, "   -u: user name\n");
102          printf("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
103          printf("   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -s: shell\n");
104          printf("   -m: do not send motion events\n");          fprintf(stderr, "   -c: working directory\n");
105          printf("   -l: do not request licence\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
106          printf("   -t: rdp tcp port\n");          fprintf(stderr, "   -n: client hostname\n");
107          printf("   -K: keep window manager key bindings\n");          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            char server[64];
230          char fullhostname[64];          char fullhostname[64];
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;          struct passwd *pw;
         char *server, *p;  
237          uint32 flags;          uint32 flags;
238            char *p;
239          int c;          int c;
240    
241          printf("rdesktop: A Remote Desktop Protocol client.\n");          int username_option = 0;
         printf("Version " VERSION  
                ". Copyright (C) 1999-2001 Matt Chapman.\n");  
         printf("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, "us");          strcpy(keymapname, "en-us");
247    
248            g_num_devices = 0;
249    
250    #ifdef RDP2VNC
251    #define VNCOPT "V:Q:"
252    #else
253    #define VNCOPT
254    #endif
255    
256          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:t:fbemlKh?")) != -1)          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':
# Line 112  main(int argc, char *argv[]) Line 289  main(int argc, char *argv[])
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));                                  STRNCPY(password, optarg, sizeof(password));
299                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
300    
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 'n':                          case 'n':
# Line 121  main(int argc, char *argv[]) Line 309  main(int argc, char *argv[])
309                                  break;                                  break;
310    
311                          case 'k':                          case 'k':
312                                  STRNCPY(keymapname, optarg,                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
                                         sizeof(keymapname));  
313                                  break;                                  break;
314    
315                          case 'g':                          case 'g':
316                                  width = strtol(optarg, &p, 10);                                  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')                                  if (*p == 'x')
331                                          height = strtol(p + 1, NULL, 10);                                          g_height = strtol(p + 1, NULL, 10);
332    
333                                  if ((width == 0) || (height == 0))                                  if (g_height <= 0)
334                                  {                                  {
335                                          error("invalid geometry\n");                                          error("invalid geometry\n");
336                                          return 1;                                          return 1;
337                                  }                                  }
338    
339                                    if (*p == '%')
340                                            g_width = -g_width;
341    
342                                  break;                                  break;
343    
344                          case 'f':                          case 'f':
345                                  fullscreen = True;                                  g_fullscreen = True;
346                                  break;                                  break;
347    
348                          case 'b':                          case 'b':
349                                  orders = False;                                  g_orders = False;
350                                  break;                                  break;
351    
352                          case 'e':                          case 'B':
353                                  encryption = False;                                  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                                  sendmotion = False;                                  g_sendmotion = False;
364                                  break;                                  break;
365    
366                          case 'l':                          case 'C':
367                                  licence = False;                                  g_owncolmap = True;
368                                  break;                                  break;
369    
370                          case 't':                          case 'D':
371                                  tcp_port_rdp = strtol(optarg, NULL, 10);                                  g_hide_decorations = True;
372                                  break;                                  break;
373    
374                          case 'K':                          case 'K':
375                                  grab_keyboard = False;                                  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;
402    
403                            case 'a':
404                                    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;
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;                                  break;
457    
458                          case 'h':                          case 'h':
# Line 179  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))
# Line 190  main(int argc, char *argv[]) Line 481  main(int argc, char *argv[])
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)
# Line 208  main(int argc, char *argv[]) Line 499  main(int argc, char *argv[])
499                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(hostname, fullhostname, sizeof(hostname));
500          }          }
501    
502          if (!strcmp(password, "-"))          if (prompt_password && read_password(password, sizeof(password)))
503          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
504    
505          if ((width == 0) || (height == 0))          if (g_title[0] == 0)
506          {          {
507                  width = 800;                  strcpy(g_title, "rdesktop - ");
508                  height = 600;                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
509          }          }
510    
511          strcpy(title, "rdesktop - ");  #ifdef RDP2VNC
512          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          rdp2vnc_connect(server, flags, domain, password, shell, directory);
513            return 0;
514    #else
515    
516            if (!ui_init())
517                    return 1;
518    
519          xkeymap_init1();  #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          printf("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          if (ui_create_window(title))  
534            DEBUG(("Connection successful.\n"));
535            memset(password, 0, sizeof(password));
536    
537            if (ui_create_window())
538          {          {
539                  rdp_main_loop();                  rdp_retval = rdp_main_loop();
540                  ui_destroy_window();                  ui_destroy_window();
541          }          }
542    
543          printf("Disconnecting...\n");          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
# Line 252  generate_random(uint8 * random) Line 597  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    
604          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
605          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
606              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((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 273  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 321  error(char *format, ...) Line 682  error(char *format, ...)
682          va_end(ap);          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 */  /* report an unimplemented protocol feature */
699  void  void
700  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 339  void Line 713  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          {          {
# Line 356  hexdump(unsigned char *p, unsigned int l Line 729  hexdump(unsigned char *p, unsigned int l
729                          printf("   ");                          printf("   ");
730    
731                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
732                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
733    
734                  printf("\n");                  printf("\n");
735                  offset += thisline;                  offset += thisline;
# Line 366  hexdump(unsigned char *p, unsigned int l Line 737  hexdump(unsigned char *p, unsigned int l
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  int
859  load_licence(unsigned char **data)  load_licence(unsigned char **data)
860  {  {
861          char path[PATH_MAX];          char *home, *path;
         char *home;  
862          struct stat st;          struct stat st;
863          int fd;          int fd, length;
864    
865          home = getenv("HOME");          home = getenv("HOME");
866          if (home == NULL)          if (home == NULL)
867                  return -1;                  return -1;
868    
869          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
870          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
871    
872          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
873          if (fd == -1)          if (fd == -1)
# Line 388  load_licence(unsigned char **data) Line 876  load_licence(unsigned char **data)
876          if (fstat(fd, &st))          if (fstat(fd, &st))
877                  return -1;                  return -1;
878    
879          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
880          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
881            close(fd);
882            xfree(path);
883            return length;
884  }  }
885    
886  void  void
887  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
888  {  {
889          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
890          int fd;          int fd;
891    
892          home = getenv("HOME");          home = getenv("HOME");
893          if (home == NULL)          if (home == NULL)
894                  return;                  return;
895    
896          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
897          strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);  
898          mkdir(path, 0700);          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          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          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(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
913          if (fd == -1)          if (fd == -1)
914          {          {
915                  perror("open");                  perror(tmppath);
916                  return;                  return;
917          }          }
918    
919          write(fd, data, length);          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);          close(fd);
931            xfree(tmppath);
932            xfree(path);
933  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26