/[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 29 by matty, Fri Sep 14 03:38:39 2001 UTC revision 318 by astrand, Mon Feb 10 12:58:51 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 <termios.h>            /* tcgetattr tcsetattr */
26  #include <sys/stat.h>           /* stat */  #include <sys/stat.h>           /* stat */
27  #include <sys/time.h>           /* gettimeofday */  #include <sys/time.h>           /* gettimeofday */
28  #include <sys/times.h>          /* times */  #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    int server_bpp = 8;
52  BOOL bitmap_compression = True;  BOOL bitmap_compression = True;
53  BOOL sendmotion = True;  BOOL sendmotion = True;
54  BOOL orders = True;  BOOL orders = True;
55  BOOL licence = True;  BOOL encryption = True;
 BOOL use_encryption = True;  
56  BOOL desktop_save = True;  BOOL desktop_save = True;
57  BOOL fullscreen = False;  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  static void
64  usage(char *program)  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  int
128  main(int argc, char *argv[])  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:g:k:mbleKFVh?")) != -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));
                                 break;  
   
                         case 'p':  
                                 flags |= RDP_LOGON_AUTO;  
                                 strncpy(password, optarg, sizeof(password));  
159                                  break;                                  break;
160    
161                          case 's':                          case 's':
162                                  strncpy(shell, optarg, sizeof(shell));                                  STRNCPY(shell, optarg, sizeof(shell));
163                                  break;                                  break;
164    
165                          case 'c':                          case 'c':
166                                  strncpy(directory, optarg, sizeof(directory));                                  STRNCPY(directory, optarg, sizeof(directory));
167                                    break;
168    
169                            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;
178    
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 'n':                          case 'n':
186                                  strncpy(hostname, optarg, sizeof(hostname));                                  STRNCPY(hostname, optarg, sizeof(hostname));
187                                    break;
188    
189                            case 'k':
190                                    STRNCPY(keymapname, optarg, sizeof(keymapname));
191                                  break;                                  break;
192    
193                          case 'g':                          case 'g':
194                                    if (!strcmp(optarg, "workarea"))
195                                  {                                  {
196                                          char *tgem = 0;                                          width = height = 0;
197                                          width = strtol(optarg, NULL, 10);                                          break;
198                                          tgem = strchr(optarg, 'x');                                  }
199                                          if ((tgem == 0) || (strlen(tgem) < 2))  
200                                          {                                  width = strtol(optarg, &p, 10);
201                                                  ERROR                                  if (*p == 'x')
202                                                          ("-g: invalid parameter. Syntax example: -g 1024x768\n");                                          height = strtol(p + 1, NULL, 10);
203                                                  exit(1);  
204                                          }                                  if ((width == 0) || (height == 0))
205                                          height = strtol(tgem + 1, NULL, 10);                                  {
206                                            error("invalid geometry\n");
207                                            return 1;
208                                  }                                  }
209                                  break;                                  break;
210    
211                          case 'k':                          case 'f':
212                                  keylayout = strtol(optarg, NULL, 16);                                  fullscreen = True;
213                                  /* keylayout = find_keyb_code(optarg); */                                  break;
214                                  if (keylayout == 0)  
215                                          return 0;                          case 'b':
216                                    orders = False;
217                                    break;
218    
219                            case 'e':
220                                    encryption = False;
221                                  break;                                  break;
222    
223                          case 'm':                          case 'm':
224                                  sendmotion = 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 'e':                          case 'T':
236                                  use_encryption = False;                                  STRNCPY(title, optarg, sizeof(title));
237                                  break;                                  break;
238    
239                          case 'F':                          case 'D':
240                                  fullscreen = True;                                  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
246                                        && server_bpp != 24)
247                                    {
248                                            error("invalid server bpp\n");
249                                            return 1;
250                                    }
251                                  break;                                  break;
252    
253                          case 'h':                          case 'h':
# Line 165  main(int argc, char *argv[]) Line 264  main(int argc, char *argv[])
264                  return 1;                  return 1;
265          }          }
266    
267          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
268            p = strchr(server, ':');
269            if (p != NULL)
270            {
271                    tcp_port_rdp = strtol(p + 1, NULL, 10);
272                    *p = 0;
273            }
274    
275          if (username[0] == 0)          if (!username_option)
276          {          {
277                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
278                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
279                  {                  {
280                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
281                          return 1;                          return 1;
282                  }                  }
283    
284                  strncpy(username, pw->pw_name, sizeof(username));                  STRNCPY(username, pw->pw_name, sizeof(username));
285          }          }
286    
287          if (hostname[0] == 0)          if (hostname[0] == 0)
288          {          {
289                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
290                  {                  {
291                          STATUS("Could not determine host name.\n");                          error("could not determine local hostname, use -n\n");
292                          return 1;                          return 1;
293                  }                  }
294    
295                    p = strchr(fullhostname, '.');
296                    if (p != NULL)
297                            *p = 0;
298    
299                    STRNCPY(hostname, fullhostname, sizeof(hostname));
300          }          }
301    
302          strcpy(title, "rdesktop - ");          if (prompt_password && read_password(password, sizeof(password)))
303          strncat(title, server, sizeof(title));                  flags |= RDP_LOGON_AUTO;
304    
305          if (ui_create_window(title))          if (title[0] == 0)
306          {          {
307                  if (!rdp_connect(server, flags, domain, password, shell,                  strcpy(title, "rdesktop - ");
308                                   directory))                  strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
309                          return 1;          }
310    
311            if (!ui_init())
312                    return 1;
313    
314            if (!rdp_connect(server, flags, domain, password, shell, directory))
315                    return 1;
316    
317            DEBUG(("Connection successful.\n"));
318            memset(password, 0, sizeof(password));
319    
320                  STATUS("Connection successful.\n");          if (ui_create_window())
321            {
322                  rdp_main_loop();                  rdp_main_loop();
323                  ui_destroy_window();                  ui_destroy_window();
324          }          }
325    
326            DEBUG(("Disconnecting...\n"));
327          rdp_disconnect();          rdp_disconnect();
328            ui_deinit();
329          return 0;          return 0;
330  }  }
331    
332    #ifdef EGD_SOCKET
333    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
334    static BOOL
335    generate_random_egd(uint8 * buf)
336    {
337            struct sockaddr_un addr;
338            BOOL ret = False;
339            int fd;
340    
341            fd = socket(AF_UNIX, SOCK_STREAM, 0);
342            if (fd == -1)
343                    return False;
344    
345            addr.sun_family = AF_UNIX;
346            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
347            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
348                    goto err;
349    
350            /* PRNGD and EGD use a simple communications protocol */
351            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
352            buf[1] = 32;            /* Number of requested random bytes */
353            if (write(fd, buf, 2) != 2)
354                    goto err;
355    
356            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
357                    goto err;
358    
359            if (read(fd, buf, 32) != 32)
360                    goto err;
361    
362            ret = True;
363    
364          err:
365            close(fd);
366            return ret;
367    }
368    #endif
369    
370  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
371  void  void
372  generate_random(uint8 *random)  generate_random(uint8 * random)
373  {  {
374          struct stat st;          struct stat st;
375          struct tms tmsbuf;          struct tms tmsbuf;
376          uint32 *r = (uint32 *) random;          MD5_CTX md5;
377          int fd;          uint32 *r;
378            int fd, n;
379          /* If we have a kernel random device, use it. */  
380          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          /* If we have a kernel random device, try that first */
381            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
382                || ((fd = open("/dev/random", O_RDONLY)) != -1))
383          {          {
384                  read(fd, random, 32);                  n = read(fd, random, 32);
385                  close(fd);                  close(fd);
386                  return;                  if (n == 32)
387                            return;
388          }          }
389    
390    #ifdef EGD_SOCKET
391            /* As a second preference use an EGD */
392            if (generate_random_egd(random))
393                    return;
394    #endif
395    
396          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
397            r = (uint32 *) random;
398          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
399          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
400          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 232  generate_random(uint8 *random) Line 403  generate_random(uint8 *random)
403          r[5] = st.st_atime;          r[5] = st.st_atime;
404          r[6] = st.st_mtime;          r[6] = st.st_mtime;
405          r[7] = st.st_ctime;          r[7] = st.st_ctime;
406    
407            /* Hash both halves with MD5 to obscure possible patterns */
408            MD5_Init(&md5);
409            MD5_Update(&md5, random, 16);
410            MD5_Final(random, &md5);
411            MD5_Update(&md5, random + 16, 16);
412            MD5_Final(random + 16, &md5);
413  }  }
414    
415  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 241  xmalloc(int size) Line 419  xmalloc(int size)
419          void *mem = malloc(size);          void *mem = malloc(size);
420          if (mem == NULL)          if (mem == NULL)
421          {          {
422                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
423                  exit(1);                  exit(1);
424          }          }
425          return mem;          return mem;
# Line 254  xrealloc(void *oldmem, int size) Line 432  xrealloc(void *oldmem, int size)
432          void *mem = realloc(oldmem, size);          void *mem = realloc(oldmem, size);
433          if (mem == NULL)          if (mem == NULL)
434          {          {
435                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
436                  exit(1);                  exit(1);
437          }          }
438          return mem;          return mem;
# Line 267  xfree(void *mem) Line 445  xfree(void *mem)
445          free(mem);          free(mem);
446  }  }
447    
448  /* Produce a hex dump */  /* report an error */
449    void
450    error(char *format, ...)
451    {
452            va_list ap;
453    
454            fprintf(stderr, "ERROR: ");
455    
456            va_start(ap, format);
457            vfprintf(stderr, format, ap);
458            va_end(ap);
459    }
460    
461    /* report a warning */
462    void
463    warning(char *format, ...)
464    {
465            va_list ap;
466    
467            fprintf(stderr, "WARNING: ");
468    
469            va_start(ap, format);
470            vfprintf(stderr, format, ap);
471            va_end(ap);
472    }
473    
474    /* report an unimplemented protocol feature */
475    void
476    unimpl(char *format, ...)
477    {
478            va_list ap;
479    
480            fprintf(stderr, "NOT IMPLEMENTED: ");
481    
482            va_start(ap, format);
483            vfprintf(stderr, format, ap);
484            va_end(ap);
485    }
486    
487    /* produce a hex dump */
488  void  void
489  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, unsigned int len)
490  {  {
# Line 277  hexdump(unsigned char *p, unsigned int l Line 494  hexdump(unsigned char *p, unsigned int l
494    
495          while (offset < len)          while (offset < len)
496          {          {
497                  STATUS("%04x ", offset);                  printf("%04x ", offset);
498                  thisline = len - offset;                  thisline = len - offset;
499                  if (thisline > 16)                  if (thisline > 16)
500                          thisline = 16;                          thisline = 16;
501    
502                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
503                          STATUS("%02x ", line[i]) for (; i < 16; i++)                          printf("%02x ", line[i]);
504                                  STATUS("   ");  
505                    for (; i < 16; i++)
506                            printf("   ");
507    
508                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
509                          STATUS("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
510    
511                  STATUS("\n");                  printf("\n");
512                  offset += thisline;                  offset += thisline;
513                  line += thisline;                  line += thisline;
514          }          }

Legend:
Removed from v.29  
changed lines
  Added in v.318

  ViewVC Help
Powered by ViewVC 1.1.26