/[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 24 by matty, Sat Jan 6 03:12:10 2001 UTC revision 279 by n-ki, Tue Nov 26 10:09:14 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  int width = 800;  char keymapname[16];
47    int keylayout = 0x409;          /* Defaults to US keyboard layout */
48    int width = 800;                /* If width or height are reset to zero, the geometry will
49                                       be fetched from _NET_WORKAREA */
50  int height = 600;  int height = 600;
51  int keylayout = 0x409;  int tcp_port_rdp = TCP_PORT_RDP;
52  BOOL motion = True;  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-2002 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    }
88    
89    static BOOL
90    read_password(char *password, int size)
91  {  {
92          STATUS("Usage: %s [options] server\n", program);          struct termios tios;
93          STATUS("   -u: user name\n");          BOOL ret = False;
94          STATUS("   -d: domain\n");          int istty = 0;
95          STATUS("   -s: shell\n");          char *p;
96          STATUS("   -c: working directory\n");  
97          STATUS("   -p: password (autologon)\n");          if (tcgetattr(STDIN_FILENO, &tios) == 0)
98          STATUS("   -n: client hostname\n");          {
99          STATUS("   -w: desktop width\n");                  fprintf(stderr, "Password: ");
100          STATUS("   -h: desktop height\n");                  tios.c_lflag &= ~ECHO;
101          STATUS("   -k: keyboard layout (hex)\n");                  tcsetattr(STDIN_FILENO, TCSANOW, &tios);
102          STATUS("   -b: force bitmap updates\n");                  istty = 1;
103          STATUS("   -m: do not send motion events\n");          }
104          STATUS("   -l: do not request licence\n\n");  
105            if (fgets(password, size, stdin) != NULL)
106            {
107                    ret = True;
108    
109                    /* strip final newline */
110                    p = strchr(password, '\n');
111                    if (p != NULL)
112                            *p = 0;
113            }
114    
115            if (istty)
116            {
117                    tios.c_lflag |= ECHO;
118                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
119                    fprintf(stderr, "\n");
120            }
121    
122            return ret;
123  }  }
124    
125  /* Client program */  /* Client program */
126  int main(int argc, char *argv[])  int
127    main(int argc, char *argv[])
128  {  {
129          struct passwd *pw;          char server[64];
130          char *server;          char fullhostname[64];
         uint32 flags;  
131          char domain[16];          char domain[16];
132          char password[16];          char password[16];
133          char shell[32];          char shell[128];
134          char directory[32];          char directory[32];
135          char title[32];          BOOL prompt_password;
136            struct passwd *pw;
137            uint32 flags;
138            char *p;
139          int c;          int c;
140    
         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");  
   
141          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
142            prompt_password = False;
143          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
144            strcpy(keymapname, "en-us");
145    
146          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:fbemCKT:Dh?")) != -1)
147          {          {
148                  switch (c)                  switch (c)
149                  {                  {
150                          case 'u':                          case 'u':
151                                  strncpy(username, optarg, sizeof(username));                                  STRNCPY(username, optarg, sizeof(username));
152                                  break;                                  break;
153    
154                          case 'd':                          case 'd':
155                                  strncpy(domain, optarg, sizeof(domain));                                  STRNCPY(domain, optarg, sizeof(domain));
156                                    break;
157    
158                            case 's':
159                                    STRNCPY(shell, optarg, sizeof(shell));
160                                    break;
161    
162                            case 'c':
163                                    STRNCPY(directory, optarg, sizeof(directory));
164                                  break;                                  break;
165    
166                          case 'p':                          case 'p':
167                                    if ((optarg[0] == '-') && (optarg[1] == 0))
168                                    {
169                                            prompt_password = True;
170                                            break;
171                                    }
172    
173                                    STRNCPY(password, optarg, sizeof(password));
174                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
175                                  strncpy(password, optarg, sizeof(password));  
176                                    /* try to overwrite argument so it won't appear in ps */
177                                    p = optarg;
178                                    while (*p)
179                                            *(p++) = 'X';
180                                  break;                                  break;
181    
182                          case 's':                          case 'n':
183                                  strncpy(shell, optarg, sizeof(shell));                                  STRNCPY(hostname, optarg, sizeof(hostname));
184                                  break;                                  break;
185    
186                          case 'c':                          case 'k':
187                                  strncpy(directory, optarg, sizeof(directory));                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
188                                  break;                                  break;
189    
190                          case 'n':                          case 'g':
191                                  strncpy(hostname, optarg, sizeof(hostname));                                  if (!strcmp(optarg, "workarea"))
192                                    {
193                                            width = height = 0;
194                                            break;
195                                    }
196    
197                                    width = strtol(optarg, &p, 10);
198                                    if (*p == 'x')
199                                            height = strtol(p + 1, NULL, 10);
200    
201                                    if ((width == 0) || (height == 0))
202                                    {
203                                            error("invalid geometry\n");
204                                            return 1;
205                                    }
206                                  break;                                  break;
207    
208                          case 'w':                          case 'f':
209                                  width = strtol(optarg, NULL, 10);                                  fullscreen = True;
210                                  break;                                  break;
211    
212                          case 'h':                          case 'b':
213                                  height = strtol(optarg, NULL, 10);                                  orders = False;
214                                  break;                                  break;
215    
216                          case 'k':                          case 'e':
217                                  keylayout = strtol(optarg, NULL, 16);                                  encryption = False;
218                                  break;                                  break;
219    
220                          case 'm':                          case 'm':
221                                  motion = False;                                  sendmotion = False;
222                                  break;                                  break;
223    
224                          case 'b':                          case 'C':
225                                  orders = False;                                  owncolmap = True;
226                                    break;
227    
228                            case 'K':
229                                    grab_keyboard = False;
230                                  break;                                  break;
231    
232                          case 'l':                          case 'T':
233                                  licence = False;                                  STRNCPY(title, optarg, sizeof(title));
234                                  break;                                  break;
235    
236                            case 'D':
237                                    hide_decorations = True;
238                                    break;
239    
240                            case 'h':
241                          case '?':                          case '?':
242                          default:                          default:
243                                  usage(argv[0]);                                  usage(argv[0]);
# Line 141  int main(int argc, char *argv[]) Line 251  int main(int argc, char *argv[])
251                  return 1;                  return 1;
252          }          }
253    
254          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
255            p = strchr(server, ':');
256            if (p != NULL)
257            {
258                    tcp_port_rdp = strtol(p + 1, NULL, 10);
259                    *p = 0;
260            }
261    
262          if (username[0] == 0)          if (username[0] == 0)
263          {          {
264                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
265                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
266                  {                  {
267                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
268                          return 1;                          return 1;
269                  }                  }
270    
271                  strncpy(username, pw->pw_name, sizeof(username));                  STRNCPY(username, pw->pw_name, sizeof(username));
272          }          }
273    
274          if (hostname[0] == 0)          if (hostname[0] == 0)
275          {          {
276                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
277                  {                  {
278                          STATUS("Could not determine host name.\n");                          error("could not determine local hostname, use -n\n");
279                          return 1;                          return 1;
280                  }                  }
281    
282                    p = strchr(fullhostname, '.');
283                    if (p != NULL)
284                            *p = 0;
285    
286                    STRNCPY(hostname, fullhostname, sizeof(hostname));
287          }          }
288    
289          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (prompt_password && read_password(password, sizeof(password)))
290                    flags |= RDP_LOGON_AUTO;
291    
292            if (title[0] == 0)
293            {
294                    strcpy(title, "rdesktop - ");
295                    strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
296            }
297    
298            if (!ui_init())
299                  return 1;                  return 1;
300    
301          STATUS("Connection successful.\n");          if (!rdp_connect(server, flags, domain, password, shell, directory))
302                    return 1;
303    
304          strcpy(title, "rdesktop - ");          DEBUG(("Connection successful.\n"));
305          strncat(title, server, sizeof(title));          memset(password, 0, sizeof(password));
306    
307          if (ui_create_window(title))          if (ui_create_window())
308          {          {
309                  rdp_main_loop();                  rdp_main_loop();
310                  ui_destroy_window();                  ui_destroy_window();
311          }          }
312    
313            DEBUG(("Disconnecting...\n"));
314          rdp_disconnect();          rdp_disconnect();
315            ui_deinit();
316          return 0;          return 0;
317  }  }
318    
319    #ifdef EGD_SOCKET
320    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
321    static BOOL
322    generate_random_egd(uint8 * buf)
323    {
324            struct sockaddr_un addr;
325            BOOL ret = False;
326            int fd;
327    
328            fd = socket(AF_UNIX, SOCK_STREAM, 0);
329            if (fd == -1)
330                    return False;
331    
332            addr.sun_family = AF_UNIX;
333            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
334            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
335                    goto err;
336    
337            /* PRNGD and EGD use a simple communications protocol */
338            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
339            buf[1] = 32;            /* Number of requested random bytes */
340            if (write(fd, buf, 2) != 2)
341                    goto err;
342    
343            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
344                    goto err;
345    
346            if (read(fd, buf, 32) != 32)
347                    goto err;
348    
349            ret = True;
350    
351          err:
352            close(fd);
353            return ret;
354    }
355    #endif
356    
357  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
358  void generate_random(uint8 *random)  void
359    generate_random(uint8 * random)
360  {  {
361          struct stat st;          struct stat st;
362          struct tms tmsbuf;          struct tms tmsbuf;
363          uint32 *r = (uint32 *) random;          MD5_CTX md5;
364          int fd;          uint32 *r;
365            int fd, n;
366          /* If we have a kernel random device, use it. */  
367          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          /* If we have a kernel random device, try that first */
368            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
369                || ((fd = open("/dev/random", O_RDONLY)) != -1))
370          {          {
371                  read(fd, random, 32);                  n = read(fd, random, 32);
372                  close(fd);                  close(fd);
373                  return;                  if (n == 32)
374                            return;
375          }          }
376    
377    #ifdef EGD_SOCKET
378            /* As a second preference use an EGD */
379            if (generate_random_egd(random))
380                    return;
381    #endif
382    
383          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
384            r = (uint32 *) random;
385          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
386          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
387          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 207  void generate_random(uint8 *random) Line 390  void generate_random(uint8 *random)
390          r[5] = st.st_atime;          r[5] = st.st_atime;
391          r[6] = st.st_mtime;          r[6] = st.st_mtime;
392          r[7] = st.st_ctime;          r[7] = st.st_ctime;
393    
394            /* Hash both halves with MD5 to obscure possible patterns */
395            MD5_Init(&md5);
396            MD5_Update(&md5, random, 16);
397            MD5_Final(random, &md5);
398            MD5_Update(&md5, random + 16, 16);
399            MD5_Final(random + 16, &md5);
400  }  }
401    
402  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
403  void *xmalloc(int size)  void *
404    xmalloc(int size)
405  {  {
406          void *mem = malloc(size);          void *mem = malloc(size);
407          if (mem == NULL)          if (mem == NULL)
408          {          {
409                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
410                  exit(1);                  exit(1);
411          }          }
412          return mem;          return mem;
413  }  }
414    
415  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
416  void *xrealloc(void *oldmem, int size)  void *
417    xrealloc(void *oldmem, int size)
418  {  {
419          void *mem = realloc(oldmem, size);          void *mem = realloc(oldmem, size);
420          if (mem == NULL)          if (mem == NULL)
421          {          {
422                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
423                  exit(1);                  exit(1);
424          }          }
425          return mem;          return mem;
426  }  }
427    
428  /* free */  /* free */
429  void xfree(void *mem)  void
430    xfree(void *mem)
431  {  {
432          free(mem);          free(mem);
433  }  }
434    
435  /* Produce a hex dump */  /* report an error */
436  void hexdump(unsigned char *p, unsigned int len)  void
437    error(char *format, ...)
438    {
439            va_list ap;
440    
441            fprintf(stderr, "ERROR: ");
442    
443            va_start(ap, format);
444            vfprintf(stderr, format, ap);
445            va_end(ap);
446    }
447    
448    /* report an unimplemented protocol feature */
449    void
450    unimpl(char *format, ...)
451    {
452            va_list ap;
453    
454            fprintf(stderr, "NOT IMPLEMENTED: ");
455    
456            va_start(ap, format);
457            vfprintf(stderr, format, ap);
458            va_end(ap);
459    }
460    
461    /* produce a hex dump */
462    void
463    hexdump(unsigned char *p, unsigned int len)
464  {  {
465          unsigned char *line = p;          unsigned char *line = p;
466          unsigned int thisline, offset = 0;          unsigned int thisline, offset = 0;
# Line 248  void hexdump(unsigned char *p, unsigned Line 468  void hexdump(unsigned char *p, unsigned
468    
469          while (offset < len)          while (offset < len)
470          {          {
471                  STATUS("%04x ", offset);                  printf("%04x ", offset);
472                  thisline = len - offset;                  thisline = len - offset;
473                  if (thisline > 16)                  if (thisline > 16)
474                          thisline = 16;                          thisline = 16;
475    
476                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
477                          STATUS("%02x ", line[i]) for (; i < 16; i++)                          printf("%02x ", line[i]);
478                                  STATUS("   ");  
479                    for (; i < 16; i++)
480                            printf("   ");
481    
482                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
483                          STATUS("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
484    
485                  STATUS("\n");                  printf("\n");
486                  offset += thisline;                  offset += thisline;
487                  line += thisline;                  line += thisline;
488          }          }
489  }  }
490    
491    #ifdef SAVE_LICENCE
492    int
493    load_licence(unsigned char **data)
494    {
495            char path[PATH_MAX];
496            char *home;
497            struct stat st;
498            int fd;
499    
500            home = getenv("HOME");
501            if (home == NULL)
502                    return -1;
503    
504            STRNCPY(path, home, sizeof(path));
505            strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);
506    
507            fd = open(path, O_RDONLY);
508            if (fd == -1)
509                    return -1;
510    
511            if (fstat(fd, &st))
512                    return -1;
513    
514            *data = xmalloc(st.st_size);
515            return read(fd, *data, st.st_size);
516    }
517    
518    void
519    save_licence(unsigned char *data, int length)
520    {
521            char path[PATH_MAX];
522            char *home;
523            int fd;
524    
525            home = getenv("HOME");
526            if (home == NULL)
527                    return;
528    
529            STRNCPY(path, home, sizeof(path));
530            strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);
531            mkdir(path, 0700);
532    
533            strncat(path, "/licence", sizeof(path) - strlen(path) - 1);
534    
535            fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
536            if (fd == -1)
537            {
538                    perror("open");
539                    return;
540            }
541    
542            write(fd, data, length);
543            close(fd);
544    }
545    #endif

Legend:
Removed from v.24  
changed lines
  Added in v.279

  ViewVC Help
Powered by ViewVC 1.1.26