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

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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26