/[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 10 by matty, Tue Aug 15 10:23:24 2000 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 <getopt.h>     /* getopt */  #include <pwd.h>                /* getpwuid */
25  #include <pwd.h>        /* getpwuid */  #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  BOOL motion = False;  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            fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
67            fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
68            fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
69    
70            fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
71            fprintf(stderr, "   -u: user name\n");
72            fprintf(stderr, "   -d: domain\n");
73            fprintf(stderr, "   -s: shell\n");
74            fprintf(stderr, "   -c: working directory\n");
75            fprintf(stderr, "   -p: password (- to prompt)\n");
76            fprintf(stderr, "   -n: client hostname\n");
77            fprintf(stderr, "   -k: keyboard layout on terminal server (us,sv,gr,etc.)\n");
78            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          STATUS("Usage: %s [options] server\n", program);          struct termios tios;
94          STATUS("   -u: user name\n");          BOOL ret = False;
95          STATUS("   -n: client hostname\n");          int istty = 0;
96          STATUS("   -w: desktop width\n");          char *p;
97          STATUS("   -h: desktop height\n");  
98          STATUS("   -k: keyboard layout (hex)\n");          if (tcgetattr(STDIN_FILENO, &tios) == 0)
99          STATUS("   -m: send motion events\n");          {
100          STATUS("   -b: force bitmap updates\n");                  fprintf(stderr, "Password: ");
101          STATUS("   -l: do not request licence\n\n");                  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            char server[64];
131            char fullhostname[64];
132            char domain[16];
133            char password[16];
134            char shell[128];
135            char directory[32];
136            BOOL prompt_password;
137          struct passwd *pw;          struct passwd *pw;
138          char *server;          uint32 flags;
139          char title[32];          char *p;
140          int c;          int c;
141            int username_option = 0;
142    
143          STATUS("rdesktop: A Remote Desktop Protocol client.\n");          flags = RDP_LOGON_NORMAL;
144          STATUS("Version "VERSION". Copyright (C) 1999-2000 Matt Chapman.\n\n");          prompt_password = False;
145            domain[0] = password[0] = shell[0] = directory[0] = 0;
146            strcpy(keymapname, "en-us");
147    
148          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: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 'n':                          case 'd':
158                                  strncpy(hostname, optarg, sizeof(hostname));                                  STRNCPY(domain, optarg, sizeof(domain));
159                                  break;                                  break;
160    
161                          case 'w':                          case 's':
162                                  width = strtol(optarg, NULL, 10);                                  STRNCPY(shell, optarg, sizeof(shell));
163                                  break;                                  break;
164    
165                          case 'h':                          case 'c':
166                                  height = strtol(optarg, NULL, 10);                                  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;
184    
185                            case 'n':
186                                    STRNCPY(hostname, optarg, sizeof(hostname));
187                                  break;                                  break;
188    
189                          case 'k':                          case 'k':
190                                  keylayout = strtol(optarg, NULL, 16);                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
191                                  break;                                  break;
192    
193                          case 'm':                          case 'g':
194                                  motion = True;                                  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;
210    
211                            case 'f':
212                                    fullscreen = True;
213                                  break;                                  break;
214    
215                          case 'b':                          case 'b':
216                                  orders = False;                                  orders = False;
217                                  break;                                  break;
218    
219                          case 'l':                          case 'e':
220                                  licence = False;                                  encryption = False;
221                                    break;
222    
223                            case 'm':
224                                    sendmotion = False;
225                                    break;
226    
227                            case 'C':
228                                    owncolmap = True;
229                                    break;
230    
231                            case 'K':
232                                    grab_keyboard = False;
233                                    break;
234    
235                            case 'T':
236                                    STRNCPY(title, optarg, sizeof(title));
237                                    break;
238    
239                            case 'D':
240                                    hide_decorations = True;
241                                  break;                                  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;
252    
253                            case 'h':
254                          case '?':                          case '?':
255                          default:                          default:
256                                  usage(argv[0]);                                  usage(argv[0]);
# Line 111  int main(int argc, char *argv[]) Line 264  int 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            if (prompt_password && read_password(password, sizeof(password)))
303                    flags |= RDP_LOGON_AUTO;
304    
305            if (title[0] == 0)
306            {
307                    strcpy(title, "rdesktop - ");
308                    strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
309          }          }
310    
311          if (!rdp_connect(server))          if (!ui_init())
312                    return 1;
313    
314            if (!rdp_connect(server, flags, domain, password, shell, directory))
315                  return 1;                  return 1;
316    
317          STATUS("Connection successful.\n");          DEBUG(("Connection successful.\n"));
318            memset(password, 0, sizeof(password));
319    
320          snprintf(title, sizeof(title), "rdesktop - %s", server);          if (ui_create_window())
         if (ui_create_window(title))  
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  /* Generate a 32-byte random for the secure transport code. */  #ifdef EGD_SOCKET
333  void generate_random(uint8 *random)  /* 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 stat st;          struct sockaddr_un addr;
338          uint32 *r = (uint32 *)random;          BOOL ret = False;
339          int fd;          int fd;
340    
341          /* If we have a kernel random device, use it. */          fd = socket(AF_UNIX, SOCK_STREAM, 0);
342          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          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. */
371    void
372    generate_random(uint8 * random)
373    {
374            struct stat st;
375            struct tms tmsbuf;
376            MD5_CTX md5;
377            uint32 *r;
378            int fd, n;
379    
380            /* 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(NULL); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
401          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
402          stat("/tmp", &st);          stat("/tmp", &st);
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 */
416  void *xmalloc(int size)  void *
417    xmalloc(int size)
418  {  {
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;
426  }  }
427    
428  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
429  void *xrealloc(void *oldmem, int size)  void *
430    xrealloc(void *oldmem, int size)
431  {  {
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;
439  }  }
440    
441  /* free */  /* free */
442  void xfree(void *mem)  void
443    xfree(void *mem)
444  {  {
445          free(mem);          free(mem);
446  }  }
447    
448  /* Produce a hex dump */  /* report an error */
449  void hexdump(unsigned char *p, unsigned int len)  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
489    hexdump(unsigned char *p, unsigned int len)
490  {  {
491          unsigned char *line = p;          unsigned char *line = p;
492          unsigned int thisline, offset = 0;          unsigned int thisline, offset = 0;
# Line 215  void hexdump(unsigned char *p, unsigned Line 494  void hexdump(unsigned char *p, unsigned
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])                          printf("%02x ", line[i]);
504    
505                  for (; i < 16; i++)                  for (; i < 16; i++)
506                          STATUS("   ");                          printf("   ");
507    
508                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
509                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (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.10  
changed lines
  Added in v.318

  ViewVC Help
Powered by ViewVC 1.1.26