/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/rdesktop.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.10  
changed lines
  Added in v.220

  ViewVC Help
Powered by ViewVC 1.1.26