/[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 66 by astrand, Thu Jul 18 18:28:12 2002 UTC revision 289 by astrand, Thu Jan 16 13:48:02 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-2001     Copyright (C) Matthew Chapman 1999-2002
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
 #include <stdlib.h>             /* malloc realloc free */  
21  #include <stdarg.h>             /* va_list va_start va_end */  #include <stdarg.h>             /* va_list va_start va_end */
22  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */
23  #include <fcntl.h>              /* open */  #include <fcntl.h>              /* open */
24    #include <errno.h>              /* save licence uses it. */
25  #include <pwd.h>                /* getpwuid */  #include <pwd.h>                /* getpwuid */
26  #include <limits.h>             /* PATH_MAX */  #include <termios.h>            /* tcgetattr tcsetattr */
27  #include <sys/stat.h>           /* stat */  #include <sys/stat.h>           /* stat */
28  #include <sys/time.h>           /* gettimeofday */  #include <sys/time.h>           /* gettimeofday */
29  #include <sys/times.h>          /* times */  #include <sys/times.h>          /* times */
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  char keymapname[16];  char keymapname[16];
47  int keylayout = 0x409;          /* Defaults to US keyboard layout */  int keylayout = 0x409;          /* Defaults to US keyboard layout */
48  int width;  int width = 800;                /* If width or height are reset to zero, the geometry will
49  int height;                                     be fetched from _NET_WORKAREA */
50    int height = 600;
51  int tcp_port_rdp = TCP_PORT_RDP;  int tcp_port_rdp = TCP_PORT_RDP;
52  BOOL bitmap_compression = True;  BOOL bitmap_compression = True;
53  BOOL sendmotion = True;  BOOL sendmotion = True;
54  BOOL orders = True;  BOOL orders = True;
 BOOL licence = True;  
55  BOOL encryption = True;  BOOL encryption = True;
56  BOOL desktop_save = True;  BOOL desktop_save = True;
57  BOOL fullscreen = False;  BOOL fullscreen = False;
58    BOOL grab_keyboard = True;
59    BOOL hide_decorations = False;
60    extern BOOL owncolmap;
61    
62  /* Display usage information */  /* Display usage information */
63  static void  static void
64  usage(char *program)  usage(char *program)
65  {  {
66          printf("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
67          printf("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2002 Matt Chapman.\n");
68          printf("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
69          printf("   -s: shell\n");  
70          printf("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
71          printf("   -p: password (autologon)\n");          fprintf(stderr, "   -u: user name\n");
72          printf("   -n: client hostname\n");          fprintf(stderr, "   -d: domain\n");
73          printf("   -k: keyboard layout on terminal server (us,sv,gr etc.)\n");          fprintf(stderr, "   -s: shell\n");
74          printf("   -g: desktop geometry (WxH)\n");          fprintf(stderr, "   -c: working directory\n");
75          printf("   -f: full-screen mode\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
76          printf("   -b: force bitmap updates\n");          fprintf(stderr, "   -n: client hostname\n");
77          printf("   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -k: keyboard layout on terminal server (us,sv,gr,etc.)\n");
78          printf("   -m: do not send motion events\n");          fprintf(stderr, "   -g: desktop geometry (WxH)\n");
79          printf("   -l: do not request licence\n");          fprintf(stderr, "   -f: full-screen mode\n");
80          printf("   -t: rdp tcp port\n\n");          fprintf(stderr, "   -b: force bitmap updates\n");
81            fprintf(stderr, "   -e: disable encryption (French TS)\n");
82            fprintf(stderr, "   -m: do not send motion events\n");
83            fprintf(stderr, "   -C: use private colour map\n");
84            fprintf(stderr, "   -K: keep window manager key bindings\n");
85            fprintf(stderr, "   -T: window title\n");
86            fprintf(stderr, "   -D: hide window manager decorations\n");
87    }
88    
89    static BOOL
90    read_password(char *password, int size)
91    {
92            struct termios tios;
93            BOOL ret = False;
94            int istty = 0;
95            char *p;
96    
97            if (tcgetattr(STDIN_FILENO, &tios) == 0)
98            {
99                    fprintf(stderr, "Password: ");
100                    tios.c_lflag &= ~ECHO;
101                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
102                    istty = 1;
103            }
104    
105            if (fgets(password, size, stdin) != NULL)
106            {
107                    ret = True;
108    
109                    /* strip final newline */
110                    p = strchr(password, '\n');
111                    if (p != NULL)
112                            *p = 0;
113            }
114    
115            if (istty)
116            {
117                    tios.c_lflag |= ECHO;
118                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
119                    fprintf(stderr, "\n");
120            }
121    
122            return ret;
123  }  }
124    
125  /* Client program */  /* Client program */
126  int  int
127  main(int argc, char *argv[])  main(int argc, char *argv[])
128  {  {
129            char server[64];
130          char fullhostname[64];          char fullhostname[64];
131          char domain[16];          char domain[16];
132          char password[16];          char password[16];
133          char shell[32];          char shell[128];
134          char directory[32];          char directory[32];
135          char title[32];          BOOL prompt_password;
136          struct passwd *pw;          struct passwd *pw;
         char *server, *p;  
137          uint32 flags;          uint32 flags;
138            char *p;
139          int c;          int c;
140            int username_option = 0;
         printf("rdesktop: A Remote Desktop Protocol client.\n");  
         printf("Version " VERSION  
                ". Copyright (C) 1999-2001 Matt Chapman.\n");  
         printf("See http://www.rdesktop.org/ for more information.\n\n");  
141    
142          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
143            prompt_password = False;
144          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
145          strcpy(keymapname, "us");          strcpy(keymapname, "en-us");
146    
147          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:t:fbemlh?")) != -1)          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:fbemCKT:Dh?")) != -1)
148          {          {
149                  switch (c)                  switch (c)
150                  {                  {
151                          case 'u':                          case 'u':
152                                  STRNCPY(username, optarg, sizeof(username));                                  STRNCPY(username, optarg, sizeof(username));
153                                    username_option = 1;
154                                  break;                                  break;
155    
156                          case 'd':                          case 'd':
# Line 110  main(int argc, char *argv[]) Line 166  main(int argc, char *argv[])
166                                  break;                                  break;
167    
168                          case 'p':                          case 'p':
169                                    if ((optarg[0] == '-') && (optarg[1] == 0))
170                                    {
171                                            prompt_password = True;
172                                            break;
173                                    }
174    
175                                  STRNCPY(password, optarg, sizeof(password));                                  STRNCPY(password, optarg, sizeof(password));
176                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
177    
178                                    /* try to overwrite argument so it won't appear in ps */
179                                    p = optarg;
180                                    while (*p)
181                                            *(p++) = 'X';
182                                  break;                                  break;
183    
184                          case 'n':                          case 'n':
# Line 119  main(int argc, char *argv[]) Line 186  main(int argc, char *argv[])
186                                  break;                                  break;
187    
188                          case 'k':                          case 'k':
189                                  STRNCPY(keymapname, optarg,                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
                                         sizeof(keymapname));  
190                                  break;                                  break;
191    
192                          case 'g':                          case 'g':
193                                    if (!strcmp(optarg, "workarea"))
194                                    {
195                                            width = height = 0;
196                                            break;
197                                    }
198    
199                                  width = strtol(optarg, &p, 10);                                  width = strtol(optarg, &p, 10);
200                                  if (*p == 'x')                                  if (*p == 'x')
201                                          height = strtol(p + 1, NULL, 10);                                          height = strtol(p + 1, NULL, 10);
# Line 151  main(int argc, char *argv[]) Line 223  main(int argc, char *argv[])
223                                  sendmotion = False;                                  sendmotion = False;
224                                  break;                                  break;
225    
226                          case 'l':                          case 'C':
227                                  licence = False;                                  owncolmap = True;
228                                    break;
229    
230                            case 'K':
231                                    grab_keyboard = False;
232                                    break;
233    
234                            case 'T':
235                                    STRNCPY(title, optarg, sizeof(title));
236                                  break;                                  break;
237    
238                          case 't':                          case 'D':
239                                  tcp_port_rdp = strtol(optarg, NULL, 10);                                  hide_decorations = True;
240                                  break;                                  break;
241    
242                          case 'h':                          case 'h':
# Line 173  main(int argc, char *argv[]) Line 253  main(int argc, char *argv[])
253                  return 1;                  return 1;
254          }          }
255    
256          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
257            p = strchr(server, ':');
258            if (p != NULL)
259            {
260                    tcp_port_rdp = strtol(p + 1, NULL, 10);
261                    *p = 0;
262            }
263    
264          if (username[0] == 0)          if (!username_option)
265          {          {
266                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
267                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
# Line 202  main(int argc, char *argv[]) Line 288  main(int argc, char *argv[])
288                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(hostname, fullhostname, sizeof(hostname));
289          }          }
290    
291          if (!strcmp(password, "-"))          if (prompt_password && read_password(password, sizeof(password)))
292          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
293    
294          if ((width == 0) || (height == 0))          if (title[0] == 0)
295          {          {
296                  width = 800;                  strcpy(title, "rdesktop - ");
297                  height = 600;                  strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
298          }          }
299    
300          strcpy(title, "rdesktop - ");          if (!ui_init())
301          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));                  return 1;
   
         xkeymap_init1();  
302    
303          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
304                  return 1;                  return 1;
305    
306          printf("Connection successful.\n");          DEBUG(("Connection successful.\n"));
307            memset(password, 0, sizeof(password));
308    
309          if (ui_create_window(title))          if (ui_create_window())
310          {          {
311                  rdp_main_loop();                  rdp_main_loop();
312                  ui_destroy_window();                  ui_destroy_window();
313          }          }
314    
315          printf("Disconnecting...\n");          DEBUG(("Disconnecting...\n"));
316          rdp_disconnect();          rdp_disconnect();
317            ui_deinit();
318          return 0;          return 0;
319  }  }
320    
321    #ifdef EGD_SOCKET
322    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
323    static BOOL
324    generate_random_egd(uint8 * buf)
325    {
326            struct sockaddr_un addr;
327            BOOL ret = False;
328            int fd;
329    
330            fd = socket(AF_UNIX, SOCK_STREAM, 0);
331            if (fd == -1)
332                    return False;
333    
334            addr.sun_family = AF_UNIX;
335            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
336            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
337                    goto err;
338    
339            /* PRNGD and EGD use a simple communications protocol */
340            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
341            buf[1] = 32;            /* Number of requested random bytes */
342            if (write(fd, buf, 2) != 2)
343                    goto err;
344    
345            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
346                    goto err;
347    
348            if (read(fd, buf, 32) != 32)
349                    goto err;
350    
351            ret = True;
352    
353          err:
354            close(fd);
355            return ret;
356    }
357    #endif
358    
359  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
360  void  void
361  generate_random(uint8 * random)  generate_random(uint8 * random)
362  {  {
363          struct stat st;          struct stat st;
364          struct tms tmsbuf;          struct tms tmsbuf;
365          uint32 *r = (uint32 *) random;          MD5_CTX md5;
366          int fd;          uint32 *r;
367            int fd, n;
368    
369          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
370          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
371              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
372          {          {
373                  read(fd, random, 32);                  n = read(fd, random, 32);
374                  close(fd);                  close(fd);
375                  return;                  if (n == 32)
376                            return;
377          }          }
378    
379    #ifdef EGD_SOCKET
380            /* As a second preference use an EGD */
381            if (generate_random_egd(random))
382                    return;
383    #endif
384    
385          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
386            r = (uint32 *) random;
387          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
388          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
389          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 267  generate_random(uint8 * random) Line 392  generate_random(uint8 * random)
392          r[5] = st.st_atime;          r[5] = st.st_atime;
393          r[6] = st.st_mtime;          r[6] = st.st_mtime;
394          r[7] = st.st_ctime;          r[7] = st.st_ctime;
395    
396            /* Hash both halves with MD5 to obscure possible patterns */
397            MD5_Init(&md5);
398            MD5_Update(&md5, random, 16);
399            MD5_Final(random, &md5);
400            MD5_Update(&md5, random + 16, 16);
401            MD5_Final(random + 16, &md5);
402  }  }
403    
404  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 350  hexdump(unsigned char *p, unsigned int l Line 482  hexdump(unsigned char *p, unsigned int l
482                          printf("   ");                          printf("   ");
483    
484                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
485                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
486    
487                  printf("\n");                  printf("\n");
488                  offset += thisline;                  offset += thisline;
# Line 360  hexdump(unsigned char *p, unsigned int l Line 490  hexdump(unsigned char *p, unsigned int l
490          }          }
491  }  }
492    
493    #ifdef SAVE_LICENCE
494  int  int
495  load_licence(unsigned char **data)  load_licence(unsigned char **data)
496  {  {
497          char path[PATH_MAX];          char *path;
498          char *home;          char *home;
499          struct stat st;          struct stat st;
500          int fd;          int fd;
# Line 372  load_licence(unsigned char **data) Line 503  load_licence(unsigned char **data)
503          if (home == NULL)          if (home == NULL)
504                  return -1;                  return -1;
505    
506          STRNCPY(path, home, sizeof(path));          path = xmalloc(strlen(home) + strlen(hostname) + 20);
507          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
508    
509          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
510          if (fd == -1)          if (fd == -1)
# Line 389  load_licence(unsigned char **data) Line 520  load_licence(unsigned char **data)
520  void  void
521  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
522  {  {
523          char path[PATH_MAX];          char *fpath;            /* file path for licence */
524            char *fname, *fnamewrk; /* file name for licence .inkl path. */
525          char *home;          char *home;
526          int fd;          uint32 y;
527            struct flock fnfl;
528            int fnfd, fnwrkfd, i, wlen;
529            struct stream s, *s_ptr;
530            uint32 len;
531    
532            /* Construct a stream, so that we can use macros to extract the
533             * licence.
534             */
535            s_ptr = &s;
536            s_ptr->p = data;
537            /* Skip first two bytes */
538            in_uint16(s_ptr, len);
539    
540            /* Skip three strings */
541            for (i = 0; i < 3; i++)
542            {
543                    in_uint32(s_ptr, len);
544                    s_ptr->p += len;
545                    /* Make sure that we won't be past the end of data after
546                     * reading the next length value
547                     */
548                    if ((s_ptr->p) + 4 > data + length)
549                    {
550                            printf("Error in parsing licence key.\n");
551                            printf("Strings %d end value %x > supplied length (%x)\n",
552                                   i, s_ptr->p, data + length);
553                            return;
554                    }
555            }
556            in_uint32(s_ptr, len);
557            if (s_ptr->p + len > data + length)
558            {
559                    printf("Error in parsing licence key.\n");
560                    printf("End of licence %x > supplied length (%x)\n", s_ptr->p + len, data + length);
561                    return;
562            }
563    
564          home = getenv("HOME");          home = getenv("HOME");
565          if (home == NULL)          if (home == NULL)
566                  return;                  return;
567    
568          STRNCPY(path, home, sizeof(path));          /* set and create the directory -- if it doesn't exist. */
569          strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);          fpath = xmalloc(strlen(home) + 11);
570          mkdir(path, 0700);          STRNCPY(fpath, home, strlen(home) + 1);
571    
572          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          sprintf(fpath, "%s/.rdesktop", fpath);
573            if (mkdir(fpath, 0700) == -1 && errno != EEXIST)
574            {
575                    perror("mkdir");
576                    exit(1);
577            }
578    
579          fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          /* set the real licence filename, and put a write lock on it. */
580          if (fd == -1)          fname = xmalloc(strlen(fpath) + strlen(hostname) + 10);
581            sprintf(fname, "%s/licence.%s", fpath, hostname);
582            fnfd = open(fname, O_RDONLY);
583            if (fnfd != -1)
584            {
585                    fnfl.l_type = F_WRLCK;
586                    fnfl.l_whence = SEEK_SET;
587                    fnfl.l_start = 0;
588                    fnfl.l_len = 1;
589                    fcntl(fnfd, F_SETLK, &fnfl);
590            }
591    
592            /* create a temporary licence file */
593            fnamewrk = xmalloc(strlen(fname) + 12);
594            for (y = 0;; y++)
595            {
596                    sprintf(fnamewrk, "%s.%lu", fname, y);
597                    fnwrkfd = open(fnamewrk, O_WRONLY | O_CREAT | O_EXCL, 0600);
598                    if (fnwrkfd == -1)
599                    {
600                            if (errno == EINTR || errno == EEXIST)
601                                    continue;
602                            perror("create");
603                            exit(1);
604                    }
605                    break;
606            }
607            /* write to the licence file */
608            for (y = 0; y < len;)
609          {          {
610                  perror("open");                  do
611                  return;                  {
612                            wlen = write(fnwrkfd, s_ptr->p + y, len - y);
613                    }
614                    while (wlen == -1 && errno == EINTR);
615                    if (wlen < 1)
616                    {
617                            perror("write");
618                            unlink(fnamewrk);
619                            exit(1);
620                    }
621                    y += wlen;
622            }
623    
624            /* close the file and rename it to fname */
625            if (close(fnwrkfd) == -1)
626            {
627                    perror("close");
628                    unlink(fnamewrk);
629                    exit(1);
630            }
631            if (rename(fnamewrk, fname) == -1)
632            {
633                    perror("rename");
634                    unlink(fnamewrk);
635                    exit(1);
636            }
637            /* close the file lock on fname */
638            if (fnfd != -1)
639            {
640                    fnfl.l_type = F_UNLCK;
641                    fnfl.l_whence = SEEK_SET;
642                    fnfl.l_start = 0;
643                    fnfl.l_len = 1;
644                    fcntl(fnfd, F_SETLK, &fnfl);
645                    close(fnfd);
646          }          }
647    
         write(fd, data, length);  
         close(fd);  
648  }  }
649    #endif

Legend:
Removed from v.66  
changed lines
  Added in v.289

  ViewVC Help
Powered by ViewVC 1.1.26