/[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 29 by matty, Fri Sep 14 03:38:39 2001 UTC revision 263 by astrand, Mon Nov 18 18:12:49 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-2000     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    
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 <limits.h>             /* PATH_MAX */
26    #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  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 bitmap_compression = True;  BOOL bitmap_compression = True;
53  BOOL sendmotion = True;  BOOL sendmotion = True;
54  BOOL orders = True;  BOOL orders = True;
55  BOOL licence = True;  BOOL encryption = True;
 BOOL use_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    
61  /* Display usage information */  /* Display usage information */
62  static void  static void
63  usage(char *program)  usage(char *program)
64  {  {
65          STATUS("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
66          STATUS("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2002 Matt Chapman.\n");
67          STATUS("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
68          STATUS("   -s: shell\n");  
69          STATUS("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
70          STATUS("   -p: password (autologon)\n");          fprintf(stderr, "   -u: user name\n");
71          STATUS("   -n: client hostname\n");          fprintf(stderr, "   -d: domain\n");
72          STATUS("   -w: desktop width\n");          fprintf(stderr, "   -s: shell\n");
73          STATUS("   -h: desktop height\n");          fprintf(stderr, "   -c: working directory\n");
74          STATUS("   -k: keyboard layout (hex)\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
75          STATUS("   -b: force bitmap updates\n");          fprintf(stderr, "   -n: client hostname\n");
76          STATUS("   -m: do not send motion events\n");          fprintf(stderr, "   -k: keyboard layout on terminal server (us,sv,gr,etc.)\n");
77          STATUS("   -l: do not request licence\n\n");          fprintf(stderr, "   -g: desktop geometry (WxH)\n");
78            fprintf(stderr, "   -f: full-screen mode\n");
79            fprintf(stderr, "   -b: force bitmap updates\n");
80            fprintf(stderr, "   -e: disable encryption (French TS)\n");
81            fprintf(stderr, "   -m: do not send motion events\n");
82            fprintf(stderr, "   -K: keep window manager key bindings\n");
83            fprintf(stderr, "   -T: window title\n");
84            fprintf(stderr, "   -D: hide window manager decorations\n");
85    }
86    
87    static BOOL
88    read_password(char *password, int size)
89    {
90            struct termios tios;
91            BOOL ret = False;
92            int istty = 0;
93            char *p;
94    
95            if (tcgetattr(STDIN_FILENO, &tios) == 0)
96            {
97                    fprintf(stderr, "Password: ");
98                    tios.c_lflag &= ~ECHO;
99                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
100                    istty = 1;
101            }
102    
103            if (fgets(password, size, stdin) != NULL)
104            {
105                    ret = True;
106    
107                    /* strip final newline */
108                    p = strchr(password, '\n');
109                    if (p != NULL)
110                            *p = 0;
111            }
112    
113            if (istty)
114            {
115                    tios.c_lflag |= ECHO;
116                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
117                    fprintf(stderr, "\n");
118            }
119    
120            return ret;
121  }  }
122    
123  /* Client program */  /* Client program */
124  int  int
125  main(int argc, char *argv[])  main(int argc, char *argv[])
126  {  {
127          struct passwd *pw;          char server[64];
128          char *server;          char fullhostname[64];
         uint32 flags;  
129          char domain[16];          char domain[16];
130          char password[16];          char password[16];
131          char shell[32];          char shell[128];
132          char directory[32];          char directory[32];
133          char title[32];          BOOL prompt_password;
134            struct passwd *pw;
135            uint32 flags;
136            char *p;
137          int c;          int c;
138    
         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");  
   
139          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
140            prompt_password = False;
141          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
142            strcpy(keymapname, "en-us");
143    
144          while ((c = getopt(argc, argv, "u:d:s:c:p:n:g:k:mbleKFVh?")) != -1)          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:fbemKT:Dh?")) != -1)
145          {          {
146                  switch (c)                  switch (c)
147                  {                  {
148                          case 'u':                          case 'u':
149                                  strncpy(username, optarg, sizeof(username));                                  STRNCPY(username, optarg, sizeof(username));
150                                  break;                                  break;
151    
152                          case 'd':                          case 'd':
153                                  strncpy(domain, optarg, sizeof(domain));                                  STRNCPY(domain, optarg, sizeof(domain));
                                 break;  
   
                         case 'p':  
                                 flags |= RDP_LOGON_AUTO;  
                                 strncpy(password, optarg, sizeof(password));  
154                                  break;                                  break;
155    
156                          case 's':                          case 's':
157                                  strncpy(shell, optarg, sizeof(shell));                                  STRNCPY(shell, optarg, sizeof(shell));
158                                  break;                                  break;
159    
160                          case 'c':                          case 'c':
161                                  strncpy(directory, optarg, sizeof(directory));                                  STRNCPY(directory, optarg, sizeof(directory));
162                                    break;
163    
164                            case 'p':
165                                    if ((optarg[0] == '-') && (optarg[1] == 0))
166                                    {
167                                            prompt_password = True;
168                                            break;
169                                    }
170    
171                                    STRNCPY(password, optarg, sizeof(password));
172                                    flags |= RDP_LOGON_AUTO;
173    
174                                    /* try to overwrite argument so it won't appear in ps */
175                                    p = optarg;
176                                    while (*p)
177                                            *(p++) = 'X';
178                                  break;                                  break;
179    
180                          case 'n':                          case 'n':
181                                  strncpy(hostname, optarg, sizeof(hostname));                                  STRNCPY(hostname, optarg, sizeof(hostname));
182                                  break;                                  break;
183    
184                            case 'k':
185                                    STRNCPY(keymapname, optarg, sizeof(keymapname));
186                                    break;
187    
188                          case 'g':                          case 'g':
189                                    if (!strcmp(optarg, "workarea"))
190                                  {                                  {
191                                          char *tgem = 0;                                          width = height = 0;
192                                          width = strtol(optarg, NULL, 10);                                          break;
                                         tgem = strchr(optarg, 'x');  
                                         if ((tgem == 0) || (strlen(tgem) < 2))  
                                         {  
                                                 ERROR  
                                                         ("-g: invalid parameter. Syntax example: -g 1024x768\n");  
                                                 exit(1);  
                                         }  
                                         height = strtol(tgem + 1, NULL, 10);  
193                                  }                                  }
                                 break;  
194    
195                          case 'k':                                  width = strtol(optarg, &p, 10);
196                                  keylayout = strtol(optarg, NULL, 16);                                  if (*p == 'x')
197                                  /* keylayout = find_keyb_code(optarg); */                                          height = strtol(p + 1, NULL, 10);
198                                  if (keylayout == 0)  
199                                          return 0;                                  if ((width == 0) || (height == 0))
200                                    {
201                                            error("invalid geometry\n");
202                                            return 1;
203                                    }
204                                  break;                                  break;
205    
206                          case 'm':                          case 'f':
207                                  sendmotion = False;                                  fullscreen = True;
208                                  break;                                  break;
209    
210                          case 'b':                          case 'b':
211                                  orders = False;                                  orders = False;
212                                  break;                                  break;
213    
214                          case 'l':                          case 'e':
215                                  licence = False;                                  encryption = False;
216                                  break;                                  break;
217    
218                          case 'e':                          case 'm':
219                                  use_encryption = False;                                  sendmotion = False;
220                                  break;                                  break;
221    
222                          case 'F':                          case 'K':
223                                  fullscreen = True;                                  grab_keyboard = False;
224                                    break;
225    
226                            case 'T':
227                                    STRNCPY(title, optarg, sizeof(title));
228                                    break;
229    
230                            case 'D':
231                                    hide_decorations = True;
232                                  break;                                  break;
233    
234                          case 'h':                          case 'h':
# Line 165  main(int argc, char *argv[]) Line 245  main(int argc, char *argv[])
245                  return 1;                  return 1;
246          }          }
247    
248          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
249            p = strchr(server, ':');
250            if (p != NULL)
251            {
252                    tcp_port_rdp = strtol(p + 1, NULL, 10);
253                    *p = 0;
254            }
255    
256          if (username[0] == 0)          if (username[0] == 0)
257          {          {
258                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
259                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
260                  {                  {
261                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
262                          return 1;                          return 1;
263                  }                  }
264    
265                  strncpy(username, pw->pw_name, sizeof(username));                  STRNCPY(username, pw->pw_name, sizeof(username));
266          }          }
267    
268          if (hostname[0] == 0)          if (hostname[0] == 0)
269          {          {
270                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
271                  {                  {
272                          STATUS("Could not determine host name.\n");                          error("could not determine local hostname, use -n\n");
273                          return 1;                          return 1;
274                  }                  }
275    
276                    p = strchr(fullhostname, '.');
277                    if (p != NULL)
278                            *p = 0;
279    
280                    STRNCPY(hostname, fullhostname, sizeof(hostname));
281          }          }
282    
283          strcpy(title, "rdesktop - ");          if (prompt_password && read_password(password, sizeof(password)))
284          strncat(title, server, sizeof(title));                  flags |= RDP_LOGON_AUTO;
285    
286          if (ui_create_window(title))          if (title[0] == 0)
287          {          {
288                  if (!rdp_connect(server, flags, domain, password, shell,                  strcpy(title, "rdesktop - ");
289                                   directory))                  strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
290                          return 1;          }
291    
292            if (!ui_init())
293                    return 1;
294    
295            if (!rdp_connect(server, flags, domain, password, shell, directory))
296                    return 1;
297    
298                  STATUS("Connection successful.\n");          DEBUG(("Connection successful.\n"));
299            memset(password, 0, sizeof(password));
300    
301            if (ui_create_window())
302            {
303                  rdp_main_loop();                  rdp_main_loop();
304                  ui_destroy_window();                  ui_destroy_window();
305          }          }
306    
307            DEBUG(("Disconnecting...\n"));
308          rdp_disconnect();          rdp_disconnect();
309            ui_deinit();
310          return 0;          return 0;
311  }  }
312    
313    #ifdef EGD_SOCKET
314    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
315    static BOOL
316    generate_random_egd(uint8 * buf)
317    {
318            struct sockaddr_un addr;
319            BOOL ret = False;
320            int fd;
321    
322            fd = socket(AF_UNIX, SOCK_STREAM, 0);
323            if (fd == -1)
324                    return False;
325    
326            addr.sun_family = AF_UNIX;
327            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
328            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
329                    goto err;
330    
331            /* PRNGD and EGD use a simple communications protocol */
332            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
333            buf[1] = 32;            /* Number of requested random bytes */
334            if (write(fd, buf, 2) != 2)
335                    goto err;
336    
337            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
338                    goto err;
339    
340            if (read(fd, buf, 32) != 32)
341                    goto err;
342    
343            ret = True;
344    
345          err:
346            close(fd);
347            return ret;
348    }
349    #endif
350    
351  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
352  void  void
353  generate_random(uint8 *random)  generate_random(uint8 * random)
354  {  {
355          struct stat st;          struct stat st;
356          struct tms tmsbuf;          struct tms tmsbuf;
357          uint32 *r = (uint32 *) random;          MD5_CTX md5;
358          int fd;          uint32 *r;
359            int fd, n;
360          /* If we have a kernel random device, use it. */  
361          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          /* If we have a kernel random device, try that first */
362            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
363                || ((fd = open("/dev/random", O_RDONLY)) != -1))
364          {          {
365                  read(fd, random, 32);                  n = read(fd, random, 32);
366                  close(fd);                  close(fd);
367                  return;                  if (n == 32)
368                            return;
369          }          }
370    
371    #ifdef EGD_SOCKET
372            /* As a second preference use an EGD */
373            if (generate_random_egd(random))
374                    return;
375    #endif
376    
377          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
378            r = (uint32 *) random;
379          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
380          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
381          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 232  generate_random(uint8 *random) Line 384  generate_random(uint8 *random)
384          r[5] = st.st_atime;          r[5] = st.st_atime;
385          r[6] = st.st_mtime;          r[6] = st.st_mtime;
386          r[7] = st.st_ctime;          r[7] = st.st_ctime;
387    
388            /* Hash both halves with MD5 to obscure possible patterns */
389            MD5_Init(&md5);
390            MD5_Update(&md5, random, 16);
391            MD5_Final(random, &md5);
392            MD5_Update(&md5, random + 16, 16);
393            MD5_Final(random + 16, &md5);
394  }  }
395    
396  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 241  xmalloc(int size) Line 400  xmalloc(int size)
400          void *mem = malloc(size);          void *mem = malloc(size);
401          if (mem == NULL)          if (mem == NULL)
402          {          {
403                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
404                  exit(1);                  exit(1);
405          }          }
406          return mem;          return mem;
# Line 254  xrealloc(void *oldmem, int size) Line 413  xrealloc(void *oldmem, int size)
413          void *mem = realloc(oldmem, size);          void *mem = realloc(oldmem, size);
414          if (mem == NULL)          if (mem == NULL)
415          {          {
416                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
417                  exit(1);                  exit(1);
418          }          }
419          return mem;          return mem;
# Line 267  xfree(void *mem) Line 426  xfree(void *mem)
426          free(mem);          free(mem);
427  }  }
428    
429  /* Produce a hex dump */  /* report an error */
430    void
431    error(char *format, ...)
432    {
433            va_list ap;
434    
435            fprintf(stderr, "ERROR: ");
436    
437            va_start(ap, format);
438            vfprintf(stderr, format, ap);
439            va_end(ap);
440    }
441    
442    /* report an unimplemented protocol feature */
443    void
444    unimpl(char *format, ...)
445    {
446            va_list ap;
447    
448            fprintf(stderr, "NOT IMPLEMENTED: ");
449    
450            va_start(ap, format);
451            vfprintf(stderr, format, ap);
452            va_end(ap);
453    }
454    
455    /* produce a hex dump */
456  void  void
457  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, unsigned int len)
458  {  {
# Line 277  hexdump(unsigned char *p, unsigned int l Line 462  hexdump(unsigned char *p, unsigned int l
462    
463          while (offset < len)          while (offset < len)
464          {          {
465                  STATUS("%04x ", offset);                  printf("%04x ", offset);
466                  thisline = len - offset;                  thisline = len - offset;
467                  if (thisline > 16)                  if (thisline > 16)
468                          thisline = 16;                          thisline = 16;
469    
470                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
471                          STATUS("%02x ", line[i]) for (; i < 16; i++)                          printf("%02x ", line[i]);
472                                  STATUS("   ");  
473                    for (; i < 16; i++)
474                            printf("   ");
475    
476                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
477                          STATUS("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
478    
479                  STATUS("\n");                  printf("\n");
480                  offset += thisline;                  offset += thisline;
481                  line += thisline;                  line += thisline;
482          }          }
483  }  }
484    
485    #ifdef SAVE_LICENCE
486    int
487    load_licence(unsigned char **data)
488    {
489            char path[PATH_MAX];
490            char *home;
491            struct stat st;
492            int fd;
493    
494            home = getenv("HOME");
495            if (home == NULL)
496                    return -1;
497    
498            STRNCPY(path, home, sizeof(path));
499            strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);
500    
501            fd = open(path, O_RDONLY);
502            if (fd == -1)
503                    return -1;
504    
505            if (fstat(fd, &st))
506                    return -1;
507    
508            *data = xmalloc(st.st_size);
509            return read(fd, *data, st.st_size);
510    }
511    
512    void
513    save_licence(unsigned char *data, int length)
514    {
515            char path[PATH_MAX];
516            char *home;
517            int fd;
518    
519            home = getenv("HOME");
520            if (home == NULL)
521                    return;
522    
523            STRNCPY(path, home, sizeof(path));
524            strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);
525            mkdir(path, 0700);
526    
527            strncat(path, "/licence", sizeof(path) - strlen(path) - 1);
528    
529            fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
530            if (fd == -1)
531            {
532                    perror("open");
533                    return;
534            }
535    
536            write(fd, data, length);
537            close(fd);
538    }
539    #endif

Legend:
Removed from v.29  
changed lines
  Added in v.263

  ViewVC Help
Powered by ViewVC 1.1.26