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

Legend:
Removed from v.21  
changed lines
  Added in v.317

  ViewVC Help
Powered by ViewVC 1.1.26