/[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 53 by matthewc, Tue May 28 11:48:55 2002 UTC revision 297 by matthewc, Tue Jan 28 12:27:28 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;  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;
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\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\n");          fprintf(stderr, "   -f: full-screen mode\n");
80            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: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 107  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 120  main(int argc, char *argv[]) Line 190  main(int argc, char *argv[])
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);
202    
203                                  if ((width == 0) || (height == 0))                                  if ((width == 0) || (height == 0))
204                                  {                                  {
# Line 147  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;
237    
238                            case 'D':
239                                    hide_decorations = True;
240                                  break;                                  break;
241    
242                          case 'h':                          case 'h':
# Line 165  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 194  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;
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 257  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 305  error(char *format, ...) Line 447  error(char *format, ...)
447          va_end(ap);          va_end(ap);
448  }  }
449    
450    /* report a warning */
451    void
452    warning(char *format, ...)
453    {
454            va_list ap;
455    
456            fprintf(stderr, "WARNING: ");
457    
458            va_start(ap, format);
459            vfprintf(stderr, format, ap);
460            va_end(ap);
461    }
462    
463  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
464  void  void
465  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 337  hexdump(unsigned char *p, unsigned int l Line 492  hexdump(unsigned char *p, unsigned int l
492                          printf("%02x ", line[i]);                          printf("%02x ", line[i]);
493    
494                  for (; i < 16; i++)                  for (; i < 16; i++)
495                                  printf("   ");                          printf("   ");
496    
497                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
498                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
499    
500                  printf("\n");                  printf("\n");
501                  offset += thisline;                  offset += thisline;
# Line 350  hexdump(unsigned char *p, unsigned int l Line 503  hexdump(unsigned char *p, unsigned int l
503          }          }
504  }  }
505    
506    #ifdef SAVE_LICENCE
507  int  int
508  load_licence(unsigned char **data)  load_licence(unsigned char **data)
509  {  {
510          char path[PATH_MAX];          char *path;
511          char *home;          char *home;
512          struct stat st;          struct stat st;
513          int fd;          int fd;
# Line 362  load_licence(unsigned char **data) Line 516  load_licence(unsigned char **data)
516          if (home == NULL)          if (home == NULL)
517                  return -1;                  return -1;
518    
519          STRNCPY(path, home, sizeof(path));          path = xmalloc(strlen(home) + strlen(hostname) + 20);
520          strncat(path, "/.rdesktop/licence", sizeof(path)-strlen(path)-1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
521    
522          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
523          if (fd == -1)          if (fd == -1)
# Line 379  load_licence(unsigned char **data) Line 533  load_licence(unsigned char **data)
533  void  void
534  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
535  {  {
536          char path[PATH_MAX];          char *fpath;            /* file path for licence */
537            char *fname, *fnamewrk; /* file name for licence .inkl path. */
538          char *home;          char *home;
539          int fd;          uint32 y;
540            struct flock fnfl;
541            int fnfd, fnwrkfd, i, wlen;
542            struct stream s, *s_ptr;
543            uint32 len;
544    
545            /* Construct a stream, so that we can use macros to extract the
546             * licence.
547             */
548            s_ptr = &s;
549            s_ptr->p = data;
550            /* Skip first two bytes */
551            in_uint16(s_ptr, len);
552    
553            /* Skip three strings */
554            for (i = 0; i < 3; i++)
555            {
556                    in_uint32(s_ptr, len);
557                    s_ptr->p += len;
558                    /* Make sure that we won't be past the end of data after
559                     * reading the next length value
560                     */
561                    if ((s_ptr->p) + 4 > data + length)
562                    {
563                            printf("Error in parsing licence key.\n");
564                            printf("Strings %d end value %x > supplied length (%x)\n",
565                                   i, s_ptr->p, data + length);
566                            return;
567                    }
568            }
569            in_uint32(s_ptr, len);
570            if (s_ptr->p + len > data + length)
571            {
572                    printf("Error in parsing licence key.\n");
573                    printf("End of licence %x > supplied length (%x)\n", s_ptr->p + len, data + length);
574                    return;
575            }
576    
577          home = getenv("HOME");          home = getenv("HOME");
578          if (home == NULL)          if (home == NULL)
579                  return;                  return;
580    
581          STRNCPY(path, home, sizeof(path));          /* set and create the directory -- if it doesn't exist. */
582          strncat(path, "/.rdesktop", sizeof(path)-strlen(path)-1);          fpath = xmalloc(strlen(home) + 11);
583          mkdir(path, 0700);          STRNCPY(fpath, home, strlen(home) + 1);
584    
585          strncat(path, "/licence", sizeof(path)-strlen(path)-1);          sprintf(fpath, "%s/.rdesktop", fpath);
586            if (mkdir(fpath, 0700) == -1 && errno != EEXIST)
587            {
588                    perror("mkdir");
589                    exit(1);
590            }
591    
592          fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0600);          /* set the real licence filename, and put a write lock on it. */
593          if (fd == -1)          fname = xmalloc(strlen(fpath) + strlen(hostname) + 10);
594            sprintf(fname, "%s/licence.%s", fpath, hostname);
595            fnfd = open(fname, O_RDONLY);
596            if (fnfd != -1)
597            {
598                    fnfl.l_type = F_WRLCK;
599                    fnfl.l_whence = SEEK_SET;
600                    fnfl.l_start = 0;
601                    fnfl.l_len = 1;
602                    fcntl(fnfd, F_SETLK, &fnfl);
603            }
604    
605            /* create a temporary licence file */
606            fnamewrk = xmalloc(strlen(fname) + 12);
607            for (y = 0;; y++)
608            {
609                    sprintf(fnamewrk, "%s.%lu", fname, y);
610                    fnwrkfd = open(fnamewrk, O_WRONLY | O_CREAT | O_EXCL, 0600);
611                    if (fnwrkfd == -1)
612                    {
613                            if (errno == EINTR || errno == EEXIST)
614                                    continue;
615                            perror("create");
616                            exit(1);
617                    }
618                    break;
619            }
620            /* write to the licence file */
621            for (y = 0; y < len;)
622          {          {
623                  perror("open");                  do
624                  return;                  {
625                            wlen = write(fnwrkfd, s_ptr->p + y, len - y);
626                    }
627                    while (wlen == -1 && errno == EINTR);
628                    if (wlen < 1)
629                    {
630                            perror("write");
631                            unlink(fnamewrk);
632                            exit(1);
633                    }
634                    y += wlen;
635          }          }
636    
637          write(fd, data, length);          /* close the file and rename it to fname */
638          close(fd);          if (close(fnwrkfd) == -1)
639  }          {
640                    perror("close");
641                    unlink(fnamewrk);
642                    exit(1);
643            }
644            if (rename(fnamewrk, fname) == -1)
645            {
646                    perror("rename");
647                    unlink(fnamewrk);
648                    exit(1);
649            }
650            /* close the file lock on fname */
651            if (fnfd != -1)
652            {
653                    fnfl.l_type = F_UNLCK;
654                    fnfl.l_whence = SEEK_SET;
655                    fnfl.l_start = 0;
656                    fnfl.l_len = 1;
657                    fcntl(fnfd, F_SETLK, &fnfl);
658                    close(fnfd);
659            }
660    
661    }
662    #endif

Legend:
Removed from v.53  
changed lines
  Added in v.297

  ViewVC Help
Powered by ViewVC 1.1.26