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

Legend:
Removed from v.12  
changed lines
  Added in v.262

  ViewVC Help
Powered by ViewVC 1.1.26