1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Entrypoint and utility functions
4 Copyright (C) Matthew Chapman 1999-2004
6 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
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <stdarg.h> /* va_list va_start va_end */
22 #include <unistd.h> /* read close getuid getgid getpid getppid gethostname */
23 #include <fcntl.h> /* open */
24 #include <pwd.h> /* getpwuid */
25 #include <termios.h> /* tcgetattr tcsetattr */
26 #include <sys/stat.h> /* stat */
27 #include <sys/time.h> /* gettimeofday */
28 #include <sys/times.h> /* times */
30 #include <X11/Xlib.h> /* Window */
34 #include <sys/socket.h> /* socket connect */
35 #include <sys/un.h> /* sockaddr_un */
38 #include <openssl/md5.h>
41 /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
43 generate_random_egd(uint8 * buf)
45 struct sockaddr_un addr;
49 fd = socket(AF_UNIX, SOCK_STREAM, 0);
53 addr.sun_family = AF_UNIX;
54 memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
55 if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
58 /* PRNGD and EGD use a simple communications protocol */
59 buf[0] = 1; /* Non-blocking (similar to /dev/urandom) */
60 buf[1] = 32; /* Number of requested random bytes */
61 if (write(fd, buf, 2) != 2)
64 if ((read(fd, buf, 1) != 1) || (buf[0] == 0)) /* Available? */
67 if (read(fd, buf, 32) != 32)
78 /* Generate a 32-byte random for the secure transport code. */
80 generate_random(uint8 * random)
88 /* If we have a kernel random device, try that first */
89 if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
90 || ((fd = open("/dev/random", O_RDONLY)) != -1))
92 n = read(fd, random, 32);
99 /* As a second preference use an EGD */
100 if (generate_random_egd(random))
104 /* Otherwise use whatever entropy we can gather - ideas welcome. */
105 r = (uint32 *) random;
106 r[0] = (getpid()) | (getppid() << 16);
107 r[1] = (getuid()) | (getgid() << 16);
108 r[2] = times(&tmsbuf); /* system uptime (clocks) */
109 gettimeofday((struct timeval *) &r[3], NULL); /* sec and usec */
115 /* Hash both halves with MD5 to obscure possible patterns */
117 MD5_Update(&md5, random, 16);
118 MD5_Final(random, &md5);
119 MD5_Update(&md5, random + 16, 16);
120 MD5_Final(random + 16, &md5);
123 /* malloc; exit if out of memory */
127 void *mem = malloc(size);
130 error("xmalloc %d\n", size);
136 /* realloc; exit if out of memory */
138 xrealloc(void *oldmem, int size)
140 void *mem = realloc(oldmem, size);
143 error("xrealloc %d\n", size);
156 /* report an error */
158 error(char *format, ...)
162 fprintf(stderr, "ERROR: ");
164 va_start(ap, format);
165 vfprintf(stderr, format, ap);
171 /* report a warning */
173 warning(char *format, ...)
177 fprintf(stderr, "WARNING: ");
179 va_start(ap, format);
180 vfprintf(stderr, format, ap);
184 /* report an unimplemented protocol feature */
186 unimpl(char *format, ...)
190 fprintf(stderr, "NOT IMPLEMENTED: ");
192 va_start(ap, format);
193 vfprintf(stderr, format, ap);
197 /* produce a hex dump */
199 hexdump(unsigned char *p, int len)
201 unsigned char *line = p;
202 int i, thisline, offset = 0;
206 printf("%04x ", offset);
207 thisline = len - offset;
211 for (i = 0; i < thisline; i++)
212 printf("%02x ", line[i]);
217 for (i = 0; i < thisline; i++)
218 printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');