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

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

  ViewVC Help
Powered by ViewVC 1.1.26