/[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 58 by jsorg71, Sun Jul 14 00:34:21 2002 UTC revision 280 by n-ki, Tue Nov 26 14:39:50 2002 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;  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");          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    
         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          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
142            prompt_password = False;
143          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
144          strcpy(keymapname, "us");          strcpy(keymapname, "en-us");
145    
146          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)
147          {          {
148                  switch (c)                  switch (c)
149                  {                  {
# Line 109  main(int argc, char *argv[]) Line 164  main(int argc, char *argv[])
164                                  break;                                  break;
165    
166                          case 'p':                          case 'p':
167                                    if ((optarg[0] == '-') && (optarg[1] == 0))
168                                    {
169                                            prompt_password = True;
170                                            break;
171                                    }
172    
173                                  STRNCPY(password, optarg, sizeof(password));                                  STRNCPY(password, optarg, sizeof(password));
174                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
175    
176                                    /* try to overwrite argument so it won't appear in ps */
177                                    p = optarg;
178                                    while (*p)
179                                            *(p++) = 'X';
180                                  break;                                  break;
181    
182                          case 'n':                          case 'n':
# Line 122  main(int argc, char *argv[]) Line 188  main(int argc, char *argv[])
188                                  break;                                  break;
189    
190                          case 'g':                          case 'g':
191                                    if (!strcmp(optarg, "workarea"))
192                                    {
193                                            width = height = 0;
194                                            break;
195                                    }
196    
197                                  width = strtol(optarg, &p, 10);                                  width = strtol(optarg, &p, 10);
198                                  if (*p == 'x')                                  if (*p == 'x')
199                                          height = strtol(p+1, NULL, 10);                                          height = strtol(p + 1, NULL, 10);
200    
201                                  if ((width == 0) || (height == 0))                                  if ((width == 0) || (height == 0))
202                                  {                                  {
# Line 149  main(int argc, char *argv[]) Line 221  main(int argc, char *argv[])
221                                  sendmotion = False;                                  sendmotion = False;
222                                  break;                                  break;
223    
224                          case 'l':                          case 'C':
225                                  licence = False;                                  owncolmap = True;
226                                    break;
227    
228                            case 'K':
229                                    grab_keyboard = False;
230                                    break;
231    
232                            case 'T':
233                                    STRNCPY(title, optarg, sizeof(title));
234                                  break;                                  break;
235    
236                          case 't':                          case 'D':
237                                  tcp_port_rdp = strtol(optarg, NULL, 10);                                  hide_decorations = True;
238                                  break;                                  break;
239    
240                          case 'h':                          case 'h':
# Line 171  main(int argc, char *argv[]) Line 251  main(int argc, char *argv[])
251                  return 1;                  return 1;
252          }          }
253    
254          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
255            p = strchr(server, ':');
256            if (p != NULL)
257            {
258                    tcp_port_rdp = strtol(p + 1, NULL, 10);
259                    *p = 0;
260            }
261    
262          if (username[0] == 0)          if (username[0] == 0)
263          {          {
# Line 200  main(int argc, char *argv[]) Line 286  main(int argc, char *argv[])
286                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(hostname, fullhostname, sizeof(hostname));
287          }          }
288    
289          if (!strcmp(password, "-"))          if (prompt_password && read_password(password, sizeof(password)))
290          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
291    
292          if ((width == 0) || (height == 0))          if (title[0] == 0)
293          {          {
294                  width = 800;                  strcpy(title, "rdesktop - ");
295                  height = 600;                  strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
296          }          }
297    
298          strcpy(title, "rdesktop - ");          if (!ui_init())
299          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));                  return 1;
300    
301          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
302                  return 1;                  return 1;
303    
304          printf("Connection successful.\n");          DEBUG(("Connection successful.\n"));
305            memset(password, 0, sizeof(password));
306    
307          if (ui_create_window(title))          if (ui_create_window())
308          {          {
309                  rdp_main_loop();                  rdp_main_loop();
310                  ui_destroy_window();                  ui_destroy_window();
311          }          }
312    
313          printf("Disconnecting...\n");          DEBUG(("Disconnecting...\n"));
314          rdp_disconnect();          rdp_disconnect();
315            ui_deinit();
316          return 0;          return 0;
317  }  }
318    
319    #ifdef EGD_SOCKET
320    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
321    static BOOL
322    generate_random_egd(uint8 * buf)
323    {
324            struct sockaddr_un addr;
325            BOOL ret = False;
326            int fd;
327    
328            fd = socket(AF_UNIX, SOCK_STREAM, 0);
329            if (fd == -1)
330                    return False;
331    
332            addr.sun_family = AF_UNIX;
333            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
334            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
335                    goto err;
336    
337            /* PRNGD and EGD use a simple communications protocol */
338            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
339            buf[1] = 32;            /* Number of requested random bytes */
340            if (write(fd, buf, 2) != 2)
341                    goto err;
342    
343            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
344                    goto err;
345    
346            if (read(fd, buf, 32) != 32)
347                    goto err;
348    
349            ret = True;
350    
351          err:
352            close(fd);
353            return ret;
354    }
355    #endif
356    
357  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
358  void  void
359  generate_random(uint8 *random)  generate_random(uint8 * random)
360  {  {
361          struct stat st;          struct stat st;
362          struct tms tmsbuf;          struct tms tmsbuf;
363          uint32 *r = (uint32 *) random;          MD5_CTX md5;
364          int fd;          uint32 *r;
365            int fd, n;
366    
367          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
368          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
369              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
370          {          {
371                  read(fd, random, 32);                  n = read(fd, random, 32);
372                  close(fd);                  close(fd);
373                  return;                  if (n == 32)
374                            return;
375          }          }
376    
377    #ifdef EGD_SOCKET
378            /* As a second preference use an EGD */
379            if (generate_random_egd(random))
380                    return;
381    #endif
382    
383          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
384            r = (uint32 *) random;
385          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
386          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
387          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 263  generate_random(uint8 *random) Line 390  generate_random(uint8 *random)
390          r[5] = st.st_atime;          r[5] = st.st_atime;
391          r[6] = st.st_mtime;          r[6] = st.st_mtime;
392          r[7] = st.st_ctime;          r[7] = st.st_ctime;
393    
394            /* Hash both halves with MD5 to obscure possible patterns */
395            MD5_Init(&md5);
396            MD5_Update(&md5, random, 16);
397            MD5_Final(random, &md5);
398            MD5_Update(&md5, random + 16, 16);
399            MD5_Final(random + 16, &md5);
400  }  }
401    
402  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 343  hexdump(unsigned char *p, unsigned int l Line 477  hexdump(unsigned char *p, unsigned int l
477                          printf("%02x ", line[i]);                          printf("%02x ", line[i]);
478    
479                  for (; i < 16; i++)                  for (; i < 16; i++)
480                                  printf("   ");                          printf("   ");
481    
482                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
483                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
484    
485                  printf("\n");                  printf("\n");
486                  offset += thisline;                  offset += thisline;
# Line 356  hexdump(unsigned char *p, unsigned int l Line 488  hexdump(unsigned char *p, unsigned int l
488          }          }
489  }  }
490    
491    #ifdef SAVE_LICENCE
492  int  int
493  load_licence(unsigned char **data)  load_licence(unsigned char **data)
494  {  {
495          char path[PATH_MAX];          char *path;
496          char *home;          char *home;
497          struct stat st;          struct stat st;
498          int fd;          int fd;
# Line 368  load_licence(unsigned char **data) Line 501  load_licence(unsigned char **data)
501          if (home == NULL)          if (home == NULL)
502                  return -1;                  return -1;
503    
504          STRNCPY(path, home, sizeof(path));          path = xmalloc(strlen(home) + strlen(hostname) + 20);
505          strncat(path, "/.rdesktop/licence", sizeof(path)-strlen(path)-1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
506    
507          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
508          if (fd == -1)          if (fd == -1)
# Line 385  load_licence(unsigned char **data) Line 518  load_licence(unsigned char **data)
518  void  void
519  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
520  {  {
521          char path[PATH_MAX];          char *fpath;            /* file path for licence */
522            char *fname, *fnamewrk; /* file name for licence .inkl path. */
523          char *home;          char *home;
524          int fd;          uint32 y;
525            struct flock fnfl;
526            int fnfd, fnwrkfd, i, wlen;
527            struct stream s, *s_ptr;
528            uint32 len;
529    
530            /* Construct a stream, so that we can use macros to extract the
531             * licence.
532             */
533            s_ptr = &s;
534            s_ptr->p = data;
535            /* Skip first two bytes */
536            in_uint16(s_ptr, len);
537    
538            /* Skip three strings */
539            for (i = 0; i < 3; i++)
540            {
541                    in_uint32(s_ptr, len);
542                    s_ptr->p += len;
543                    /* Make sure that we won't be past the end of data after
544                     * reading the next length value
545                     */
546                    if ((s_ptr->p) + 4 > data + length)
547                    {
548                            printf("Error in parsing licence key.\n");
549                            printf("Strings %d end value %x > supplied length (%x)\n",
550                                   i, s_ptr->p, data + length);
551                            return;
552                    }
553            }
554            in_uint32(s_ptr, len);
555            if (s_ptr->p + len > data + length)
556            {
557                    printf("Error in parsing licence key.\n");
558                    printf("End of licence %x > supplied length (%x)\n", s_ptr->p + len, data + length);
559                    return;
560            }
561    
562          home = getenv("HOME");          home = getenv("HOME");
563          if (home == NULL)          if (home == NULL)
564                  return;                  return;
565    
566          STRNCPY(path, home, sizeof(path));          /* set and create the directory -- if it doesn't exist. */
567          strncat(path, "/.rdesktop", sizeof(path)-strlen(path)-1);          fpath = xmalloc(strlen(home) + 11);
568          mkdir(path, 0700);          STRNCPY(fpath, home, strlen(home) + 1);
569    
570          strncat(path, "/licence", sizeof(path)-strlen(path)-1);          sprintf(fpath, "%s/.rdesktop", fpath);
571            if (mkdir(fpath, 0700) == -1 && errno != EEXIST)
572            {
573                    perror("mkdir");
574                    exit(1);
575            }
576    
577          fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0600);          /* set the real licence filename, and put a write lock on it. */
578          if (fd == -1)          fname = xmalloc(strlen(fpath) + strlen(hostname) + 10);
579            sprintf(fname, "%s/licence.%s", fpath, hostname);
580            fnfd = open(fname, O_RDONLY);
581            if (fnfd != -1)
582            {
583                    fnfl.l_type = F_WRLCK;
584                    fnfl.l_whence = SEEK_SET;
585                    fnfl.l_start = 0;
586                    fnfl.l_len = 1;
587                    fcntl(fnfd, F_SETLK, &fnfl);
588            }
589    
590            /* create a temporary licence file */
591            fnamewrk = xmalloc(strlen(fname) + 12);
592            for (y = 0;; y++)
593            {
594                    sprintf(fnamewrk, "%s.%lu", fname, y);
595                    fnwrkfd = open(fnamewrk, O_WRONLY | O_CREAT | O_EXCL, 0600);
596                    if (fnwrkfd == -1)
597                    {
598                            if (errno == EINTR || errno == EEXIST)
599                                    continue;
600                            perror("create");
601                            exit(1);
602                    }
603                    break;
604            }
605            /* write to the licence file */
606            for (y = 0; y < len;)
607          {          {
608                  perror("open");                  do
609                  return;                  {
610                            wlen = write(fnwrkfd, s_ptr->p + y, len - y);
611                    }
612                    while (wlen == -1 && errno == EINTR);
613                    if (wlen < 1)
614                    {
615                            perror("write");
616                            unlink(fnamewrk);
617                            exit(1);
618                    }
619                    y += wlen;
620          }          }
621    
622          write(fd, data, length);          /* close the file and rename it to fname */
623          close(fd);          if (close(fnwrkfd) == -1)
624  }          {
625                    perror("close");
626                    unlink(fnamewrk);
627                    exit(1);
628            }
629            if (rename(fnamewrk, fname) == -1)
630            {
631                    perror("rename");
632                    unlink(fnamewrk);
633                    exit(1);
634            }
635            /* close the file lock on fname */
636            if (fnfd != -1)
637            {
638                    fnfl.l_type = F_UNLCK;
639                    fnfl.l_whence = SEEK_SET;
640                    fnfl.l_start = 0;
641                    fnfl.l_len = 1;
642                    fcntl(fnfd, F_SETLK, &fnfl);
643                    close(fnfd);
644            }
645    
646    }
647    #endif

Legend:
Removed from v.58  
changed lines
  Added in v.280

  ViewVC Help
Powered by ViewVC 1.1.26