/[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 25 by matty, Sat Jan 6 03:47:04 2001 UTC revision 222 by matthewc, Fri Oct 11 04:00:32 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 <limits.h>             /* PATH_MAX */
26    #include <termios.h>            /* tcgetattr tcsetattr */
27  #include <sys/stat.h>           /* stat */  #include <sys/stat.h>           /* stat */
28  #include <sys/time.h>           /* gettimeofday */  #include <sys/time.h>           /* gettimeofday */
29  #include <sys/times.h>          /* times */  #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  static void
61  usage(char *program)  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[:port]\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, "   -K: keep window manager key bindings\n");
81            fprintf(stderr, "   -w: 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  int
122  main(int argc, char *argv[])  main(int argc, char *argv[])
123  {  {
124          struct passwd *pw;          char server[64];
125          char *server;          char fullhostname[64];
         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            uint32 flags;
133            char *p;
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: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 'K':
214                                  orders = False;                                  grab_keyboard = False;
215                                  break;                                  break;
216    
217                          case 'l':                          case 'w':
218                                  licence = False;                                  STRNCPY(title, optarg, sizeof(title));
219                                  break;                                  break;
220    
221                            case 'h':
222                          case '?':                          case '?':
223                          default:                          default:
224                                  usage(argv[0]);                                  usage(argv[0]);
# Line 143  main(int argc, char *argv[]) Line 232  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 (!rdp_connect(server, flags, domain, password, shell, directory))          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 (!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    #ifdef EGD_SOCKET
301    /* 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 sockaddr_un addr;
306            BOOL ret = False;
307            int fd;
308    
309            fd = socket(AF_UNIX, SOCK_STREAM, 0);
310            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. */  /* Generate a 32-byte random for the secure transport code. */
339  void  void
340  generate_random(uint8 *random)  generate_random(uint8 * random)
341  {  {
342          struct stat st;          struct stat st;
343          struct tms tmsbuf;          struct tms tmsbuf;
344          uint32 *r = (uint32 *) random;          MD5_CTX md5;
345          int fd;          uint32 *r;
346            int fd, n;
347          /* If we have a kernel random device, use it. */  
348          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          /* 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(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 210  generate_random(uint8 *random) Line 371  generate_random(uint8 *random)
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 */
# Line 219  xmalloc(int size) Line 387  xmalloc(int size)
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;
# Line 232  xrealloc(void *oldmem, int size) Line 400  xrealloc(void *oldmem, int size)
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;
# Line 245  xfree(void *mem) Line 413  xfree(void *mem)
413          free(mem);          free(mem);
414  }  }
415    
416  /* Produce a hex dump */  /* report an error */
417    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  void
444  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, unsigned int len)
445  {  {
# Line 255  hexdump(unsigned char *p, unsigned int l Line 449  hexdump(unsigned char *p, unsigned int l
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]) for (; i < 16; i++)                          printf("%02x ", line[i]);
459                                  STATUS("   ");  
460                    for (; i < 16; i++)
461                            printf("   ");
462    
463                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
464                          STATUS("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (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.25  
changed lines
  Added in v.222

  ViewVC Help
Powered by ViewVC 1.1.26