/[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 17 by matty, Thu Sep 28 15:54:11 2000 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 <sys/stat.h>   /* stat */  #include <limits.h>             /* PATH_MAX */
26  #include <sys/time.h>   /* gettimeofday */  #include <termios.h>            /* tcgetattr tcsetattr */
27  #include <sys/times.h>  /* times */  #include <sys/stat.h>           /* stat */
28    #include <sys/time.h>           /* gettimeofday */
29    #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 motion = False;  BOOL bitmap_compression = True;
53    BOOL sendmotion = True;
54  BOOL orders = True;  BOOL orders = True;
55  BOOL licence = True;  BOOL encryption = True;
56    BOOL desktop_save = True;
57    BOOL fullscreen = False;
58    BOOL grab_keyboard = True;
59    BOOL hide_decorations = False;
60    
61  /* Display usage information */  /* Display usage information */
62  static void usage(char *program)  static void
63    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("   -n: client hostname\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
68          STATUS("   -w: desktop width\n");  
69          STATUS("   -h: desktop height\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
70          STATUS("   -k: keyboard layout (hex)\n");          fprintf(stderr, "   -u: user name\n");
71          STATUS("   -m: send motion events\n");          fprintf(stderr, "   -d: domain\n");
72          STATUS("   -b: force bitmap updates\n");          fprintf(stderr, "   -s: shell\n");
73          STATUS("   -l: do not request licence\n\n");          fprintf(stderr, "   -c: working directory\n");
74            fprintf(stderr, "   -p: password (- to prompt)\n");
75            fprintf(stderr, "   -n: client hostname\n");
76            fprintf(stderr, "   -k: keyboard layout on terminal server (us,sv,gr,etc.)\n");
77            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 main(int argc, char *argv[])  int
125    main(int argc, char *argv[])
126  {  {
127            char server[64];
128            char fullhostname[64];
129            char domain[16];
130            char password[16];
131            char shell[128];
132            char directory[32];
133            BOOL prompt_password;
134          struct passwd *pw;          struct passwd *pw;
135          char *server;          uint32 flags;
136          char title[32];          char *p;
137          int c;          int c;
138    
139          STATUS("rdesktop: A Remote Desktop Protocol client.\n");          flags = RDP_LOGON_NORMAL;
140          STATUS("Version "VERSION". Copyright (C) 1999-2000 Matt Chapman.\n");          prompt_password = False;
141          STATUS("See http://www.rdesktop.org/ for more information.\n\n");          domain[0] = password[0] = shell[0] = directory[0] = 0;
142            strcpy(keymapname, "en-us");
143    
144          while ((c = getopt(argc, argv, "u:n:w:h:k:mbl?")) != -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 'n':                          case 'd':
153                                  strncpy(hostname, optarg, sizeof(hostname));                                  STRNCPY(domain, optarg, sizeof(domain));
154                                  break;                                  break;
155    
156                          case 'w':                          case 's':
157                                  width = strtol(optarg, NULL, 10);                                  STRNCPY(shell, optarg, sizeof(shell));
158                                  break;                                  break;
159    
160                          case 'h':                          case 'c':
161                                  height = strtol(optarg, NULL, 10);                                  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;
179    
180                            case 'n':
181                                    STRNCPY(hostname, optarg, sizeof(hostname));
182                                  break;                                  break;
183    
184                          case 'k':                          case 'k':
185                                  keylayout = strtol(optarg, NULL, 16);                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
186                                  break;                                  break;
187    
188                          case 'm':                          case 'g':
189                                  motion = True;                                  if (!strcmp(optarg, "workarea"))
190                                    {
191                                            width = height = 0;
192                                            break;
193                                    }
194    
195                                    width = strtol(optarg, &p, 10);
196                                    if (*p == 'x')
197                                            height = strtol(p + 1, NULL, 10);
198    
199                                    if ((width == 0) || (height == 0))
200                                    {
201                                            error("invalid geometry\n");
202                                            return 1;
203                                    }
204                                    break;
205    
206                            case 'f':
207                                    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;
217    
218                            case 'm':
219                                    sendmotion = False;
220                                    break;
221    
222                            case 'K':
223                                    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':
235                          case '?':                          case '?':
236                          default:                          default:
237                                  usage(argv[0]);                                  usage(argv[0]);
# Line 111  int main(int argc, char *argv[]) Line 245  int 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          if (!rdp_connect(server))          if (prompt_password && read_password(password, sizeof(password)))
284                    flags |= RDP_LOGON_AUTO;
285    
286            if (title[0] == 0)
287            {
288                    strcpy(title, "rdesktop - ");
289                    strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
290            }
291    
292            if (!ui_init())
293                  return 1;                  return 1;
294    
295          STATUS("Connection successful.\n");          if (!rdp_connect(server, flags, domain, password, shell, directory))
296                    return 1;
297    
298          strcpy(title, "rdesktop - ");          DEBUG(("Connection successful.\n"));
299          strncat(title, server, sizeof(title));          memset(password, 0, sizeof(password));
300    
301          if (ui_create_window(title))          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  /* Generate a 32-byte random for the secure transport code. */  #ifdef EGD_SOCKET
314  void generate_random(uint8 *random)  /* 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 stat st;          struct sockaddr_un addr;
319          uint32 *r = (uint32 *)random;          BOOL ret = False;
320          int fd;          int fd;
321    
322          /* If we have a kernel random device, use it. */          fd = socket(AF_UNIX, SOCK_STREAM, 0);
323          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          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. */
352    void
353    generate_random(uint8 * random)
354    {
355            struct stat st;
356            struct tms tmsbuf;
357            MD5_CTX md5;
358            uint32 *r;
359            int fd, n;
360    
361            /* 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(NULL); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
382          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
383          stat("/tmp", &st);          stat("/tmp", &st);
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 */
397  void *xmalloc(int size)  void *
398    xmalloc(int size)
399  {  {
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;
407  }  }
408    
409  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
410  void *xrealloc(void *oldmem, int size)  void *
411    xrealloc(void *oldmem, int size)
412  {  {
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;
420  }  }
421    
422  /* free */  /* free */
423  void xfree(void *mem)  void
424    xfree(void *mem)
425  {  {
426          free(mem);          free(mem);
427  }  }
428    
429  /* Produce a hex dump */  /* report an error */
430  void hexdump(unsigned char *p, unsigned int len)  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
457    hexdump(unsigned char *p, unsigned int len)
458  {  {
459          unsigned char *line = p;          unsigned char *line = p;
460          unsigned int thisline, offset = 0;          unsigned int thisline, offset = 0;
# Line 217  void hexdump(unsigned char *p, unsigned Line 462  void hexdump(unsigned char *p, unsigned
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])                          printf("%02x ", line[i]);
472    
473                  for (; i < 16; i++)                  for (; i < 16; i++)
474                          STATUS("   ");                          printf("   ");
475    
476                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
477                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (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.17  
changed lines
  Added in v.263

  ViewVC Help
Powered by ViewVC 1.1.26