/[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 25 by matty, Sat Jan 6 03:47:04 2001 UTC revision 333 by astrand, Thu Feb 20 12:14:13 2003 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Entrypoint and utility functions     Entrypoint and utility functions
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2003
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include <stdlib.h>             /* malloc realloc free */  #include <stdarg.h>             /* va_list va_start va_end */
22  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */
23  #include <fcntl.h>              /* open */  #include <fcntl.h>              /* open */
24  #include <pwd.h>                /* getpwuid */  #include <pwd.h>                /* getpwuid */
25    #include <termios.h>            /* tcgetattr tcsetattr */
26  #include <sys/stat.h>           /* stat */  #include <sys/stat.h>           /* stat */
27  #include <sys/time.h>           /* gettimeofday */  #include <sys/time.h>           /* gettimeofday */
28  #include <sys/times.h>          /* times */  #include <sys/times.h>          /* times */
29    #include <errno.h>
30  #include "rdesktop.h"  #include "rdesktop.h"
31    
32    #ifdef EGD_SOCKET
33    #include <sys/socket.h>         /* socket connect */
34    #include <sys/un.h>             /* sockaddr_un */
35    #endif
36    
37    #ifdef WITH_OPENSSL
38    #include <openssl/md5.h>
39    #else
40    #include "crypto/md5.h"
41    #endif
42    
43    char title[32] = "";
44  char username[16];  char username[16];
45  char hostname[16];  char hostname[16];
46  int width = 800;  char keymapname[16];
47    int keylayout = 0x409;          /* Defaults to US keyboard layout */
48    int width = 800;                /* If width or height are reset to zero, the geometry will
49                                       be fetched from _NET_WORKAREA */
50  int height = 600;  int height = 600;
51  int keylayout = 0x409;  int tcp_port_rdp = TCP_PORT_RDP;
52  BOOL motion = True;  int server_bpp = 8;
53    int win_button_size = 0;        /* If zero, disable single app mode */
54    BOOL bitmap_compression = True;
55    BOOL sendmotion = True;
56  BOOL orders = True;  BOOL orders = True;
57  BOOL licence = True;  BOOL encryption = True;
58    BOOL desktop_save = True;
59    BOOL fullscreen = False;
60    BOOL grab_keyboard = True;
61    BOOL hide_decorations = False;
62    extern BOOL owncolmap;
63    
64    #ifdef RDP2VNC
65    extern int rfb_port;
66    extern int defer_time;
67    void
68    rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
69                    char *shell, char *directory);
70    #endif
71  /* Display usage information */  /* Display usage information */
72  static void  static void
73  usage(char *program)  usage(char *program)
74  {  {
75          STATUS("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
76          STATUS("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
77          STATUS("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
78          STATUS("   -s: shell\n");  
79          STATUS("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
80          STATUS("   -p: password (autologon)\n");  #ifdef RDP2VNC
81          STATUS("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
82          STATUS("   -w: desktop width\n");          fprintf(stderr, "   -E: defer time (ms)\n");
83          STATUS("   -h: desktop height\n");  #endif
84          STATUS("   -k: keyboard layout (hex)\n");          fprintf(stderr, "   -u: user name\n");
85          STATUS("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
86          STATUS("   -m: do not send motion events\n");          fprintf(stderr, "   -s: shell\n");
87          STATUS("   -l: do not request licence\n\n");          fprintf(stderr, "   -S: caption button size (single application mode)\n");
88            fprintf(stderr, "   -c: working directory\n");
89            fprintf(stderr, "   -p: password (- to prompt)\n");
90            fprintf(stderr, "   -n: client hostname\n");
91            fprintf(stderr, "   -k: keyboard layout on terminal server (us,sv,gr,etc.)\n");
92            fprintf(stderr, "   -g: desktop geometry (WxH)\n");
93            fprintf(stderr, "   -f: full-screen mode\n");
94            fprintf(stderr, "   -b: force bitmap updates\n");
95            fprintf(stderr, "   -e: disable encryption (French TS)\n");
96            fprintf(stderr, "   -m: do not send motion events\n");
97            fprintf(stderr, "   -C: use private colour map\n");
98            fprintf(stderr, "   -K: keep window manager key bindings\n");
99            fprintf(stderr, "   -T: window title\n");
100            fprintf(stderr, "   -D: hide window manager decorations\n");
101            fprintf(stderr, "   -a: server bpp\n");
102    }
103    
104    static BOOL
105    read_password(char *password, int size)
106    {
107            struct termios tios;
108            BOOL ret = False;
109            int istty = 0;
110            char *p;
111    
112            if (tcgetattr(STDIN_FILENO, &tios) == 0)
113            {
114                    fprintf(stderr, "Password: ");
115                    tios.c_lflag &= ~ECHO;
116                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
117                    istty = 1;
118            }
119    
120            if (fgets(password, size, stdin) != NULL)
121            {
122                    ret = True;
123    
124                    /* strip final newline */
125                    p = strchr(password, '\n');
126                    if (p != NULL)
127                            *p = 0;
128            }
129    
130            if (istty)
131            {
132                    tios.c_lflag |= ECHO;
133                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
134                    fprintf(stderr, "\n");
135            }
136    
137            return ret;
138  }  }
139    
140  /* Client program */  /* Client program */
141  int  int
142  main(int argc, char *argv[])  main(int argc, char *argv[])
143  {  {
144          struct passwd *pw;          char server[64];
145          char *server;          char fullhostname[64];
         uint32 flags;  
146          char domain[16];          char domain[16];
147          char password[16];          char password[16];
148          char shell[32];          char shell[128];
149          char directory[32];          char directory[32];
150          char title[32];          BOOL prompt_password;
151            struct passwd *pw;
152            uint32 flags;
153            char *p;
154          int c;          int c;
155            int username_option = 0;
         STATUS("rdesktop: A Remote Desktop Protocol client.\n");  
         STATUS("Version " VERSION  
                ". Copyright (C) 1999-2000 Matt Chapman.\n");  
         STATUS("See http://www.rdesktop.org/ for more information.\n\n");  
156    
157          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
158            prompt_password = False;
159          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
160            strcpy(keymapname, "en-us");
161    
162          while ((c = getopt(argc, argv, "u:d:s:c:p:n:w:h:k:bml?")) != -1)  #ifdef RDP2VNC
163    #define VNCOPT "V:E:"
164    #else
165    #define VNCOPT
166    #endif
167    
168            while ((c = getopt(argc, argv, VNCOPT "u:d:s:S:c:p:n:k:g:a:fbemCKT:Dh?")) != -1)
169          {          {
170                  switch (c)                  switch (c)
171                  {                  {
172    #ifdef RDP2VNC
173                            case 'V':
174                                    rfb_port = strtol(optarg, NULL, 10);
175                                    if (rfb_port < 100)
176                                            rfb_port += 5900;
177                                    break;
178    
179                            case 'E':
180                                    defer_time = strtol(optarg, NULL, 10);
181                                    if (defer_time < 0)
182                                            defer_time = 0;
183                                    break;
184    #endif
185    
186                          case 'u':                          case 'u':
187                                  strncpy(username, optarg, sizeof(username));                                  STRNCPY(username, optarg, sizeof(username));
188                                    username_option = 1;
189                                  break;                                  break;
190    
191                          case 'd':                          case 'd':
192                                  strncpy(domain, optarg, sizeof(domain));                                  STRNCPY(domain, optarg, sizeof(domain));
193                                  break;                                  break;
194    
195                          case 'p':                          case 's':
196                                  flags |= RDP_LOGON_AUTO;                                  STRNCPY(shell, optarg, sizeof(shell));
                                 strncpy(password, optarg, sizeof(password));  
197                                  break;                                  break;
198    
199                          case 's':                          case 'S':
200                                  strncpy(shell, optarg, sizeof(shell));                                  if (!strcmp(optarg, "standard"))
201                                    {
202                                            win_button_size = 18;
203                                            break;
204                                    }
205    
206                                    win_button_size = strtol(optarg, &p, 10);
207    
208                                    if (*p)
209                                    {
210                                            error("invalid button size\n");
211                                            return 1;
212                                    }
213    
214                                  break;                                  break;
215    
216                          case 'c':                          case 'c':
217                                  strncpy(directory, optarg, sizeof(directory));                                  STRNCPY(directory, optarg, sizeof(directory));
218                                  break;                                  break;
219    
220                          case 'n':                          case 'p':
221                                  strncpy(hostname, optarg, sizeof(hostname));                                  if ((optarg[0] == '-') && (optarg[1] == 0))
222                                  break;                                  {
223                                            prompt_password = True;
224                                            break;
225                                    }
226    
227                                    STRNCPY(password, optarg, sizeof(password));
228                                    flags |= RDP_LOGON_AUTO;
229    
230                          case 'w':                                  /* try to overwrite argument so it won't appear in ps */
231                                  width = strtol(optarg, NULL, 10);                                  p = optarg;
232                                    while (*p)
233                                            *(p++) = 'X';
234                                  break;                                  break;
235    
236                          case 'h':                          case 'n':
237                                  height = strtol(optarg, NULL, 10);                                  STRNCPY(hostname, optarg, sizeof(hostname));
238                                  break;                                  break;
239    
240                          case 'k':                          case 'k':
241                                  keylayout = strtol(optarg, NULL, 16);                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
242                                  break;                                  break;
243    
244                          case 'm':                          case 'g':
245                                  motion = False;                                  if (!strcmp(optarg, "workarea"))
246                                    {
247                                            width = height = 0;
248                                            break;
249                                    }
250    
251                                    width = strtol(optarg, &p, 10);
252                                    if (*p == 'x')
253                                            height = strtol(p + 1, NULL, 10);
254    
255                                    if ((width == 0) || (height == 0))
256                                    {
257                                            error("invalid geometry\n");
258                                            return 1;
259                                    }
260                                    break;
261    
262                            case 'f':
263                                    fullscreen = True;
264                                  break;                                  break;
265    
266                          case 'b':                          case 'b':
267                                  orders = False;                                  orders = False;
268                                  break;                                  break;
269    
270                          case 'l':                          case 'e':
271                                  licence = False;                                  encryption = False;
272                                    break;
273    
274                            case 'm':
275                                    sendmotion = False;
276                                    break;
277    
278                            case 'C':
279                                    owncolmap = True;
280                                    break;
281    
282                            case 'K':
283                                    grab_keyboard = False;
284                                    break;
285    
286                            case 'T':
287                                    STRNCPY(title, optarg, sizeof(title));
288                                    break;
289    
290                            case 'D':
291                                    hide_decorations = True;
292                                    break;
293    
294                            case 'a':
295                                    server_bpp = strtol(optarg, NULL, 10);
296                                    if (server_bpp != 8 && server_bpp != 16 && server_bpp != 15
297                                        && server_bpp != 24)
298                                    {
299                                            error("invalid server bpp\n");
300                                            return 1;
301                                    }
302                                  break;                                  break;
303    
304                            case 'h':
305                          case '?':                          case '?':
306                          default:                          default:
307                                  usage(argv[0]);                                  usage(argv[0]);
# Line 143  main(int argc, char *argv[]) Line 315  main(int argc, char *argv[])
315                  return 1;                  return 1;
316          }          }
317    
318          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
319            p = strchr(server, ':');
320            if (p != NULL)
321            {
322                    tcp_port_rdp = strtol(p + 1, NULL, 10);
323                    *p = 0;
324            }
325    
326          if (username[0] == 0)          if (!username_option)
327          {          {
328                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
329                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
330                  {                  {
331                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
332                          return 1;                          return 1;
333                  }                  }
334    
335                  strncpy(username, pw->pw_name, sizeof(username));                  STRNCPY(username, pw->pw_name, sizeof(username));
336          }          }
337    
338          if (hostname[0] == 0)          if (hostname[0] == 0)
339          {          {
340                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
341                  {                  {
342                          STATUS("Could not determine host name.\n");                          error("could not determine local hostname, use -n\n");
343                          return 1;                          return 1;
344                  }                  }
345    
346                    p = strchr(fullhostname, '.');
347                    if (p != NULL)
348                            *p = 0;
349    
350                    STRNCPY(hostname, fullhostname, sizeof(hostname));
351          }          }
352    
353          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (prompt_password && read_password(password, sizeof(password)))
354                    flags |= RDP_LOGON_AUTO;
355    
356            if (title[0] == 0)
357            {
358                    strcpy(title, "rdesktop - ");
359                    strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
360            }
361    
362    #ifdef RDP2VNC
363            rdp2vnc_connect(server, flags, domain, password, shell, directory);
364    #else
365    
366            if (!ui_init())
367                  return 1;                  return 1;
368    
369          STATUS("Connection successful.\n");          if (!rdp_connect(server, flags, domain, password, shell, directory))
370                    return 1;
371    
372          strcpy(title, "rdesktop - ");          DEBUG(("Connection successful.\n"));
373          strncat(title, server, sizeof(title));          memset(password, 0, sizeof(password));
374    
375          if (ui_create_window(title))          if (ui_create_window())
376          {          {
377                  rdp_main_loop();                  rdp_main_loop();
378                  ui_destroy_window();                  ui_destroy_window();
379          }          }
380    
381            DEBUG(("Disconnecting...\n"));
382          rdp_disconnect();          rdp_disconnect();
383            ui_deinit();
384    
385    #endif
386    
387          return 0;          return 0;
388  }  }
389    
390    #ifdef EGD_SOCKET
391    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
392    static BOOL
393    generate_random_egd(uint8 * buf)
394    {
395            struct sockaddr_un addr;
396            BOOL ret = False;
397            int fd;
398    
399            fd = socket(AF_UNIX, SOCK_STREAM, 0);
400            if (fd == -1)
401                    return False;
402    
403            addr.sun_family = AF_UNIX;
404            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
405            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
406                    goto err;
407    
408            /* PRNGD and EGD use a simple communications protocol */
409            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
410            buf[1] = 32;            /* Number of requested random bytes */
411            if (write(fd, buf, 2) != 2)
412                    goto err;
413    
414            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
415                    goto err;
416    
417            if (read(fd, buf, 32) != 32)
418                    goto err;
419    
420            ret = True;
421    
422          err:
423            close(fd);
424            return ret;
425    }
426    #endif
427    
428  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
429  void  void
430  generate_random(uint8 *random)  generate_random(uint8 * random)
431  {  {
432          struct stat st;          struct stat st;
433          struct tms tmsbuf;          struct tms tmsbuf;
434          uint32 *r = (uint32 *) random;          MD5_CTX md5;
435          int fd;          uint32 *r;
436            int fd, n;
437          /* If we have a kernel random device, use it. */  
438          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          /* If we have a kernel random device, try that first */
439            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
440                || ((fd = open("/dev/random", O_RDONLY)) != -1))
441          {          {
442                  read(fd, random, 32);                  n = read(fd, random, 32);
443                  close(fd);                  close(fd);
444                  return;                  if (n == 32)
445                            return;
446          }          }
447    
448    #ifdef EGD_SOCKET
449            /* As a second preference use an EGD */
450            if (generate_random_egd(random))
451                    return;
452    #endif
453    
454          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
455            r = (uint32 *) random;
456          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
457          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
458          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 210  generate_random(uint8 *random) Line 461  generate_random(uint8 *random)
461          r[5] = st.st_atime;          r[5] = st.st_atime;
462          r[6] = st.st_mtime;          r[6] = st.st_mtime;
463          r[7] = st.st_ctime;          r[7] = st.st_ctime;
464    
465            /* Hash both halves with MD5 to obscure possible patterns */
466            MD5_Init(&md5);
467            MD5_Update(&md5, random, 16);
468            MD5_Final(random, &md5);
469            MD5_Update(&md5, random + 16, 16);
470            MD5_Final(random + 16, &md5);
471  }  }
472    
473  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 219  xmalloc(int size) Line 477  xmalloc(int size)
477          void *mem = malloc(size);          void *mem = malloc(size);
478          if (mem == NULL)          if (mem == NULL)
479          {          {
480                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
481                  exit(1);                  exit(1);
482          }          }
483          return mem;          return mem;
# Line 232  xrealloc(void *oldmem, int size) Line 490  xrealloc(void *oldmem, int size)
490          void *mem = realloc(oldmem, size);          void *mem = realloc(oldmem, size);
491          if (mem == NULL)          if (mem == NULL)
492          {          {
493                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
494                  exit(1);                  exit(1);
495          }          }
496          return mem;          return mem;
# Line 245  xfree(void *mem) Line 503  xfree(void *mem)
503          free(mem);          free(mem);
504  }  }
505    
506  /* Produce a hex dump */  /* report an error */
507    void
508    error(char *format, ...)
509    {
510            va_list ap;
511    
512            fprintf(stderr, "ERROR: ");
513    
514            va_start(ap, format);
515            vfprintf(stderr, format, ap);
516            va_end(ap);
517    }
518    
519    /* report a warning */
520    void
521    warning(char *format, ...)
522    {
523            va_list ap;
524    
525            fprintf(stderr, "WARNING: ");
526    
527            va_start(ap, format);
528            vfprintf(stderr, format, ap);
529            va_end(ap);
530    }
531    
532    /* report an unimplemented protocol feature */
533    void
534    unimpl(char *format, ...)
535    {
536            va_list ap;
537    
538            fprintf(stderr, "NOT IMPLEMENTED: ");
539    
540            va_start(ap, format);
541            vfprintf(stderr, format, ap);
542            va_end(ap);
543    }
544    
545    /* produce a hex dump */
546  void  void
547  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, unsigned int len)
548  {  {
# Line 255  hexdump(unsigned char *p, unsigned int l Line 552  hexdump(unsigned char *p, unsigned int l
552    
553          while (offset < len)          while (offset < len)
554          {          {
555                  STATUS("%04x ", offset);                  printf("%04x ", offset);
556                  thisline = len - offset;                  thisline = len - offset;
557                  if (thisline > 16)                  if (thisline > 16)
558                          thisline = 16;                          thisline = 16;
559    
560                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
561                          STATUS("%02x ", line[i]) for (; i < 16; i++)                          printf("%02x ", line[i]);
562                                  STATUS("   ");  
563                    for (; i < 16; i++)
564                            printf("   ");
565    
566                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
567                          STATUS("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
568    
569                  STATUS("\n");                  printf("\n");
570                  offset += thisline;                  offset += thisline;
571                  line += thisline;                  line += thisline;
572          }          }
573  }  }
574    
575    
576    int
577    load_licence(unsigned char **data)
578    {
579            char *path;
580            char *home;
581            struct stat st;
582            int fd;
583    
584            home = getenv("HOME");
585            if (home == NULL)
586                    return -1;
587    
588            path = xmalloc(strlen(home) + strlen(hostname) + 20);
589            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
590    
591            fd = open(path, O_RDONLY);
592            if (fd == -1)
593                    return -1;
594    
595            if (fstat(fd, &st))
596                    return -1;
597    
598            *data = xmalloc(st.st_size);
599            return read(fd, *data, st.st_size);
600    }
601    
602    void
603    save_licence(unsigned char *data, int length)
604    {
605            char *fpath;            /* file path for licence */
606            char *fname, *fnamewrk; /* file name for licence .inkl path. */
607            char *home;
608            uint32 y;
609            struct flock fnfl;
610            int fnfd, fnwrkfd, i, wlen;
611            struct stream s, *s_ptr;
612            uint32 len;
613    
614            /* Construct a stream, so that we can use macros to extract the
615             * licence.
616             */
617            s_ptr = &s;
618            s_ptr->p = data;
619            /* Skip first two bytes */
620            in_uint16(s_ptr, len);
621    
622            /* Skip three strings */
623            for (i = 0; i < 3; i++)
624            {
625                    in_uint32(s_ptr, len);
626                    s_ptr->p += len;
627                    /* Make sure that we won't be past the end of data after
628                     * reading the next length value
629                     */
630                    if ((s_ptr->p) + 4 > data + length)
631                    {
632                            printf("Error in parsing licence key.\n");
633                            printf("Strings %d end value %x > supplied length (%x)\n", i,
634                                   (unsigned int) s_ptr->p, (unsigned int) data + length);
635                            return;
636                    }
637            }
638            in_uint32(s_ptr, len);
639            if (s_ptr->p + len > data + length)
640            {
641                    printf("Error in parsing licence key.\n");
642                    printf("End of licence %x > supplied length (%x)\n",
643                           (unsigned int) s_ptr->p + len, (unsigned int) data + length);
644                    return;
645            }
646    
647            home = getenv("HOME");
648            if (home == NULL)
649                    return;
650    
651            /* set and create the directory -- if it doesn't exist. */
652            fpath = xmalloc(strlen(home) + 11);
653            STRNCPY(fpath, home, strlen(home) + 1);
654    
655            sprintf(fpath, "%s/.rdesktop", fpath);
656            if (mkdir(fpath, 0700) == -1 && errno != EEXIST)
657            {
658                    perror("mkdir");
659                    exit(1);
660            }
661    
662            /* set the real licence filename, and put a write lock on it. */
663            fname = xmalloc(strlen(fpath) + strlen(hostname) + 10);
664            sprintf(fname, "%s/licence.%s", fpath, hostname);
665            fnfd = open(fname, O_RDONLY);
666            if (fnfd != -1)
667            {
668                    fnfl.l_type = F_WRLCK;
669                    fnfl.l_whence = SEEK_SET;
670                    fnfl.l_start = 0;
671                    fnfl.l_len = 1;
672                    fcntl(fnfd, F_SETLK, &fnfl);
673            }
674    
675            /* create a temporary licence file */
676            fnamewrk = xmalloc(strlen(fname) + 12);
677            for (y = 0;; y++)
678            {
679                    sprintf(fnamewrk, "%s.%lu", fname, (long unsigned int) y);
680                    fnwrkfd = open(fnamewrk, O_WRONLY | O_CREAT | O_EXCL, 0600);
681                    if (fnwrkfd == -1)
682                    {
683                            if (errno == EINTR || errno == EEXIST)
684                                    continue;
685                            perror("create");
686                            exit(1);
687                    }
688                    break;
689            }
690            /* write to the licence file */
691            for (y = 0; y < len;)
692            {
693                    do
694                    {
695                            wlen = write(fnwrkfd, s_ptr->p + y, len - y);
696                    }
697                    while (wlen == -1 && errno == EINTR);
698                    if (wlen < 1)
699                    {
700                            perror("write");
701                            unlink(fnamewrk);
702                            exit(1);
703                    }
704                    y += wlen;
705            }
706    
707            /* close the file and rename it to fname */
708            if (close(fnwrkfd) == -1)
709            {
710                    perror("close");
711                    unlink(fnamewrk);
712                    exit(1);
713            }
714            if (rename(fnamewrk, fname) == -1)
715            {
716                    perror("rename");
717                    unlink(fnamewrk);
718                    exit(1);
719            }
720            /* close the file lock on fname */
721            if (fnfd != -1)
722            {
723                    fnfl.l_type = F_UNLCK;
724                    fnfl.l_whence = SEEK_SET;
725                    fnfl.l_start = 0;
726                    fnfl.l_len = 1;
727                    fcntl(fnfd, F_SETLK, &fnfl);
728                    close(fnfd);
729            }
730    
731    }

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

  ViewVC Help
Powered by ViewVC 1.1.26