/[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 21 by matty, Mon Oct 16 08:44:48 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 <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 = True;  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("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
66          STATUS("   -s: shell\n");  
67          STATUS("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server\n", program);
68          STATUS("   -p: password (autologon)\n");          fprintf(stderr, "   -u: user name\n");
69          STATUS("   -n: client hostname\n");          fprintf(stderr, "   -d: domain\n");
70          STATUS("   -w: desktop width\n");          fprintf(stderr, "   -s: shell\n");
71          STATUS("   -h: desktop height\n");          fprintf(stderr, "   -c: working directory\n");
72          STATUS("   -k: keyboard layout (hex)\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
73          STATUS("   -b: force bitmap updates\n");          fprintf(stderr, "   -n: client hostname\n");
74          STATUS("   -m: do not send motion events\n");          fprintf(stderr, "   -k: keyboard layout on terminal server (us,sv,gr etc.)\n");
75          STATUS("   -l: do not request licence\n\n");          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          struct passwd *pw;          char fullhostname[64];
         char *server;  
         uint32 flags;  
126          char domain[16];          char domain[16];
127          char password[16];          char password[16];
128          char shell[32];          char shell[32];
129          char directory[32];          char directory[32];
130          char title[32];          BOOL prompt_password;
131            struct passwd *pw;
132            char *server, *p;
133            uint32 flags;
134          int c;          int c;
135    
         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");  
   
136          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
137            prompt_password = False;
138          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
139            strcpy(keymapname, "us");
140    
141          while ((c = getopt(argc, argv, "u:d:s:c:p:n:w:h:k:bml?")) != -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 'd':                          case 'd':
150                                  strncpy(domain, optarg, sizeof(domain));                                  STRNCPY(domain, optarg, sizeof(domain));
151                                    break;
152    
153                            case 's':
154                                    STRNCPY(shell, optarg, sizeof(shell));
155                                    break;
156    
157                            case 'c':
158                                    STRNCPY(directory, optarg, sizeof(directory));
159                                  break;                                  break;
160    
161                          case 'p':                          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;                                  flags |= RDP_LOGON_AUTO;
170                                  strncpy(password, optarg, sizeof(password));  
171                                    /* try to overwrite argument so it won't appear in ps */
172                                    p = optarg;
173                                    while (*p)
174                                            *(p++) = 'X';
175                                  break;                                  break;
176    
177                          case 's':                          case 'n':
178                                  strncpy(shell, optarg, sizeof(shell));                                  STRNCPY(hostname, optarg, sizeof(hostname));
179                                  break;                                  break;
180    
181                          case 'c':                          case 'k':
182                                  strncpy(directory, optarg, sizeof(directory));                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
183                                  break;                                  break;
184    
185                          case 'n':                          case 'g':
186                                  strncpy(hostname, optarg, sizeof(hostname));                                  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;                                  break;
196    
197                          case 'w':                          case 'f':
198                                  width = strtol(optarg, NULL, 10);                                  fullscreen = True;
199                                  break;                                  break;
200    
201                          case 'h':                          case 'b':
202                                  height = strtol(optarg, NULL, 10);                                  orders = False;
203                                  break;                                  break;
204    
205                          case 'k':                          case 'e':
206                                  keylayout = strtol(optarg, NULL, 16);                                  encryption = False;
207                                  break;                                  break;
208    
209                          case 'm':                          case 'm':
210                                  motion = False;                                  sendmotion = False;
211                                  break;                                  break;
212    
213                          case 'b':                          case 't':
214                                  orders = False;                                  tcp_port_rdp = strtol(optarg, NULL, 10);
215                                  break;                                  break;
216    
217                          case 'l':                          case 'K':
218                                  licence = False;                                  grab_keyboard = False;
219                                  break;                                  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 147  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 (!rdp_connect(server, flags, domain, password, shell, directory))          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 (!ui_init())
278                  return 1;                  return 1;
279    
280          STATUS("Connection successful.\n");          if (!rdp_connect(server, flags, domain, password, shell, directory))
281                    return 1;
282    
283          strcpy(title, "rdesktop - ");          DEBUG(("Connection successful.\n"));
284          strncat(title, server, sizeof(title));          memset(password, 0, sizeof(password));
285    
286          if (ui_create_window(title))          if (ui_create_window())
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 246  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.21  
changed lines
  Added in v.220

  ViewVC Help
Powered by ViewVC 1.1.26