/[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 259 by astrand, Mon Nov 18 15:30:12 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    
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[:port]\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, "   -K: keep window manager key bindings\n");
81            fprintf(stderr, "   -T: window title\n");
82    }
83    
84    static BOOL
85    read_password(char *password, int size)
86    {
87            struct termios tios;
88            BOOL ret = False;
89            int istty = 0;
90            char *p;
91    
92            if (tcgetattr(STDIN_FILENO, &tios) == 0)
93            {
94                    fprintf(stderr, "Password: ");
95                    tios.c_lflag &= ~ECHO;
96                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
97                    istty = 1;
98            }
99    
100            if (fgets(password, size, stdin) != NULL)
101            {
102                    ret = True;
103    
104                    /* strip final newline */
105                    p = strchr(password, '\n');
106                    if (p != NULL)
107                            *p = 0;
108            }
109    
110            if (istty)
111            {
112                    tios.c_lflag |= ECHO;
113                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
114                    fprintf(stderr, "\n");
115            }
116    
117            return ret;
118  }  }
119    
120  /* Client program */  /* Client program */
121  int main(int argc, char *argv[])  int
122    main(int argc, char *argv[])
123  {  {
124            char server[64];
125            char fullhostname[64];
126            char domain[16];
127            char password[16];
128            char shell[128];
129            char directory[32];
130            BOOL prompt_password;
131          struct passwd *pw;          struct passwd *pw;
132          char *server;          uint32 flags;
133          char title[32];          char *p;
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, "en-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:fbemKT: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 'K':
214                                    grab_keyboard = False;
215                                  break;                                  break;
216    
217                            case 'T':
218                                    STRNCPY(title, optarg, sizeof(title));
219                                    break;
220    
221                            case 'h':
222                          case '?':                          case '?':
223                          default:                          default:
224                                  usage(argv[0]);                                  usage(argv[0]);
# Line 110  int main(int argc, char *argv[]) Line 232  int main(int argc, char *argv[])
232                  return 1;                  return 1;
233          }          }
234    
235          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
236            p = strchr(server, ':');
237            if (p != NULL)
238            {
239                    tcp_port_rdp = strtol(p + 1, NULL, 10);
240                    *p = 0;
241            }
242    
243          if (username[0] == 0)          if (username[0] == 0)
244          {          {
245                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
246                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
247                  {                  {
248                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
249                          return 1;                          return 1;
250                  }                  }
251    
252                  strncpy(username, pw->pw_name, sizeof(username));                  STRNCPY(username, pw->pw_name, sizeof(username));
253          }          }
254    
255          if (hostname[0] == 0)          if (hostname[0] == 0)
256          {          {
257                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
258                  {                  {
259                          STATUS("Could not determine host name.\n");                          error("could not determine local hostname, use -n\n");
260                          return 1;                          return 1;
261                  }                  }
262    
263                    p = strchr(fullhostname, '.');
264                    if (p != NULL)
265                            *p = 0;
266    
267                    STRNCPY(hostname, fullhostname, sizeof(hostname));
268            }
269    
270            if (prompt_password && read_password(password, sizeof(password)))
271                    flags |= RDP_LOGON_AUTO;
272    
273            if (title[0] == 0)
274            {
275                    strcpy(title, "rdesktop - ");
276                    strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
277          }          }
278    
279          if (!rdp_connect(server))          if (!ui_init())
280                  return 1;                  return 1;
281    
282          STATUS("Connection successful.\n");          if (!rdp_connect(server, flags, domain, password, shell, directory))
283                    return 1;
284    
285          strcpy(title, "rdesktop - ");          DEBUG(("Connection successful.\n"));
286          strncat(title, server, sizeof(title));          memset(password, 0, sizeof(password));
287    
288          if (ui_create_window(title))          if (ui_create_window())
289          {          {
290                  rdp_main_loop();                  rdp_main_loop();
291                  ui_destroy_window();                  ui_destroy_window();
292          }          }
293    
294            DEBUG(("Disconnecting...\n"));
295          rdp_disconnect();          rdp_disconnect();
296            ui_deinit();
297          return 0;          return 0;
298  }  }
299    
300  /* Generate a 32-byte random for the secure transport code. */  #ifdef EGD_SOCKET
301  void generate_random(uint8 *random)  /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
302    static BOOL
303    generate_random_egd(uint8 * buf)
304  {  {
305          struct stat st;          struct sockaddr_un addr;
306          uint32 *r = (uint32 *)random;          BOOL ret = False;
307          int fd;          int fd;
308    
309          /* If we have a kernel random device, use it. */          fd = socket(AF_UNIX, SOCK_STREAM, 0);
310          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (fd == -1)
311                    return False;
312    
313            addr.sun_family = AF_UNIX;
314            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
315            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
316                    goto err;
317    
318            /* PRNGD and EGD use a simple communications protocol */
319            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
320            buf[1] = 32;            /* Number of requested random bytes */
321            if (write(fd, buf, 2) != 2)
322                    goto err;
323    
324            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
325                    goto err;
326    
327            if (read(fd, buf, 32) != 32)
328                    goto err;
329    
330            ret = True;
331    
332          err:
333            close(fd);
334            return ret;
335    }
336    #endif
337    
338    /* Generate a 32-byte random for the secure transport code. */
339    void
340    generate_random(uint8 * random)
341    {
342            struct stat st;
343            struct tms tmsbuf;
344            MD5_CTX md5;
345            uint32 *r;
346            int fd, n;
347    
348            /* If we have a kernel random device, try that first */
349            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
350                || ((fd = open("/dev/random", O_RDONLY)) != -1))
351          {          {
352                  read(fd, random, 32);                  n = read(fd, random, 32);
353                  close(fd);                  close(fd);
354                  return;                  if (n == 32)
355                            return;
356          }          }
357    
358    #ifdef EGD_SOCKET
359            /* As a second preference use an EGD */
360            if (generate_random_egd(random))
361                    return;
362    #endif
363    
364          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
365            r = (uint32 *) random;
366          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
367          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
368          r[2] = times(NULL); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
369          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
370          stat("/tmp", &st);          stat("/tmp", &st);
371          r[5] = st.st_atime;          r[5] = st.st_atime;
372          r[6] = st.st_mtime;          r[6] = st.st_mtime;
373          r[7] = st.st_ctime;          r[7] = st.st_ctime;
374    
375            /* Hash both halves with MD5 to obscure possible patterns */
376            MD5_Init(&md5);
377            MD5_Update(&md5, random, 16);
378            MD5_Final(random, &md5);
379            MD5_Update(&md5, random + 16, 16);
380            MD5_Final(random + 16, &md5);
381  }  }
382    
383  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
384  void *xmalloc(int size)  void *
385    xmalloc(int size)
386  {  {
387          void *mem = malloc(size);          void *mem = malloc(size);
388          if (mem == NULL)          if (mem == NULL)
389          {          {
390                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
391                  exit(1);                  exit(1);
392          }          }
393          return mem;          return mem;
394  }  }
395    
396  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
397  void *xrealloc(void *oldmem, int size)  void *
398    xrealloc(void *oldmem, int size)
399  {  {
400          void *mem = realloc(oldmem, size);          void *mem = realloc(oldmem, size);
401          if (mem == NULL)          if (mem == NULL)
402          {          {
403                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
404                  exit(1);                  exit(1);
405          }          }
406          return mem;          return mem;
407  }  }
408    
409  /* free */  /* free */
410  void xfree(void *mem)  void
411    xfree(void *mem)
412  {  {
413          free(mem);          free(mem);
414  }  }
415    
416  /* Produce a hex dump */  /* report an error */
417  void hexdump(unsigned char *p, unsigned int len)  void
418    error(char *format, ...)
419    {
420            va_list ap;
421    
422            fprintf(stderr, "ERROR: ");
423    
424            va_start(ap, format);
425            vfprintf(stderr, format, ap);
426            va_end(ap);
427    }
428    
429    /* report an unimplemented protocol feature */
430    void
431    unimpl(char *format, ...)
432    {
433            va_list ap;
434    
435            fprintf(stderr, "NOT IMPLEMENTED: ");
436    
437            va_start(ap, format);
438            vfprintf(stderr, format, ap);
439            va_end(ap);
440    }
441    
442    /* produce a hex dump */
443    void
444    hexdump(unsigned char *p, unsigned int len)
445  {  {
446          unsigned char *line = p;          unsigned char *line = p;
447          unsigned int thisline, offset = 0;          unsigned int thisline, offset = 0;
# Line 216  void hexdump(unsigned char *p, unsigned Line 449  void hexdump(unsigned char *p, unsigned
449    
450          while (offset < len)          while (offset < len)
451          {          {
452                  STATUS("%04x ", offset);                  printf("%04x ", offset);
453                  thisline = len - offset;                  thisline = len - offset;
454                  if (thisline > 16)                  if (thisline > 16)
455                          thisline = 16;                          thisline = 16;
456    
457                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
458                          STATUS("%02x ", line[i])                          printf("%02x ", line[i]);
459    
460                  for (; i < 16; i++)                  for (; i < 16; i++)
461                          STATUS("   ");                          printf("   ");
462    
463                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
464                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
465    
466                  STATUS("\n");                  printf("\n");
467                  offset += thisline;                  offset += thisline;
468                  line += thisline;                  line += thisline;
469          }          }
470  }  }
471    
472    #ifdef SAVE_LICENCE
473    int
474    load_licence(unsigned char **data)
475    {
476            char path[PATH_MAX];
477            char *home;
478            struct stat st;
479            int fd;
480    
481            home = getenv("HOME");
482            if (home == NULL)
483                    return -1;
484    
485            STRNCPY(path, home, sizeof(path));
486            strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);
487    
488            fd = open(path, O_RDONLY);
489            if (fd == -1)
490                    return -1;
491    
492            if (fstat(fd, &st))
493                    return -1;
494    
495            *data = xmalloc(st.st_size);
496            return read(fd, *data, st.st_size);
497    }
498    
499    void
500    save_licence(unsigned char *data, int length)
501    {
502            char path[PATH_MAX];
503            char *home;
504            int fd;
505    
506            home = getenv("HOME");
507            if (home == NULL)
508                    return;
509    
510            STRNCPY(path, home, sizeof(path));
511            strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);
512            mkdir(path, 0700);
513    
514            strncat(path, "/licence", sizeof(path) - strlen(path) - 1);
515    
516            fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
517            if (fd == -1)
518            {
519                    perror("open");
520                    return;
521            }
522    
523            write(fd, data, length);
524            close(fd);
525    }
526    #endif

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

  ViewVC Help
Powered by ViewVC 1.1.26