3 Copyright 1988, 1998 The Open Group
4 Copyright 2003-2004 Oswald Buddenhagen <ossi@kde.org>
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of a copyright holder shall
24 not be used in advertising or otherwise to promote the sale, use or
25 other dealings in this Software without prior written authorization
26 from the copyright holder.
31 * xdm - display manager daemon
32 * Author: Keith Packard, MIT X Consortium
43 /* ####################################################################### */
46 * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
47 * Copyright (c) 2001-2002 Damien Miller. All rights reserved.
49 * Redistribution and use in source and binary forms, with or without
50 * modification, are permitted provided that the following conditions
52 * 1. Redistributions of source code must retain the above copyright
53 * notice, this list of conditions and the following disclaimer.
54 * 2. Redistributions in binary form must reproduce the above copyright
55 * notice, this list of conditions and the following disclaimer in the
56 * documentation and/or other materials provided with the distribution.
58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
67 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
70 #include "dm_socket.h"
74 #ifndef INADDR_LOOPBACK
75 # define INADDR_LOOPBACK 0x7F000001U
79 getPrngdBytes( char *buf
, int len
,
80 unsigned short tcp_port
, const char *socket_path
)
82 int fd
, addr_len
, rval
, errors
;
84 struct sockaddr
*addr
;
85 struct sockaddr_in addr_in
;
86 struct sockaddr_un addr_un
;
91 memset( &addr_in
, 0, sizeof(addr_in
) );
92 af
= addr_in
.sin_family
= AF_INET
;
93 addr_in
.sin_addr
.s_addr
= htonl( INADDR_LOOPBACK
);
94 addr_in
.sin_port
= htons( tcp_port
);
95 addr_len
= sizeof(addr_in
);
96 addr
= (struct sockaddr
*)&addr_in
;
97 } else if (*socket_path
) {
98 unsigned spl
= strlen( socket_path
);
99 if (spl
>= sizeof(addr_un
.sun_path
)) {
100 logError( "get_random_prngd: "
101 "Random pool path is too long\n" );
104 af
= addr_un
.sun_family
= AF_UNIX
;
105 strncpy( addr_un
.sun_path
, socket_path
,
106 sizeof(addr_un
.sun_path
) );
107 addr_len
= offsetof(struct sockaddr_un
, sun_path
) + spl
+ 1;
108 addr
= (struct sockaddr
*)&addr_un
;
112 old_sigpipe
= Signal( SIGPIPE
, SIG_IGN
);
117 if ((fd
= socket( af
, SOCK_STREAM
, 0 )) < 0) {
118 logError( "Could not create socket: %m\n" );
122 if (connect( fd
, (struct sockaddr
*)addr
, addr_len
)) {
124 logError( "Could not connect to PRNGD port %d: %m\n",
127 logError( "Could not connect to PRNGD socket %\"s: %m\n",
132 /* Send blocking read request to PRNGD */
136 if (writer( fd
, msg
, sizeof(msg
) ) != sizeof(msg
)) {
137 if (errno
== EPIPE
&& errors
< 10) {
142 logError( "Could not write to PRNGD socket: %m\n" );
146 if (reader( fd
, buf
, len
) != len
) {
147 if (errno
== EPIPE
&& errors
< 10) {
152 logError( "Could not read from PRNGD socket: %m\n" );
158 Signal( SIGPIPE
, old_sigpipe
);
164 /* ####################################################################### */
167 * Stolen from the Linux kernel.
169 * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All
172 * Redistribution and use in source and binary forms, with or without
173 * modification, are permitted provided that the following conditions
175 * 1. Redistributions of source code must retain the above copyright
176 * notice, and the entire permission notice in its entirety,
177 * including the disclaimer of warranties.
178 * 2. Redistributions in binary form must reproduce the above copyright
179 * notice, this list of conditions and the following disclaimer in the
180 * documentation and/or other materials provided with the distribution.
181 * 3. The name of the author may not be used to endorse or promote
182 * products derived from this software without specific prior
183 * written permission.
185 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
186 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
187 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
188 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
189 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
190 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
191 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
192 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
193 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
194 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
195 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
199 static unsigned epool
[32], erotate
, eadd_ptr
;
202 addEntropy( unsigned const *in
, int nwords
)
204 static unsigned const twist_table
[8] = {
205 0, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
206 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
212 w
= (w
<<erotate
| w
>>(32-erotate
)) & 0xffffffff;
213 i
= eadd_ptr
= (eadd_ptr
- 1) & 31;
214 new_rotate
= erotate
+ 14;
216 new_rotate
= erotate
+ 7;
217 erotate
= new_rotate
& 31;
218 w
^= epool
[(i
+ 26) & 31];
219 w
^= epool
[(i
+ 20) & 31];
220 w
^= epool
[(i
+ 14) & 31];
221 w
^= epool
[(i
+ 7) & 31];
222 w
^= epool
[(i
+ 1) & 31];
224 epool
[i
] = (w
>> 3) ^ twist_table
[w
& 7];
228 /* ####################################################################### */
231 * This code implements something close to the MD5 message-digest
232 * algorithm. This code is based on code written by Colin Plumb
233 * in 1993, no copyright is claimed.
234 * This code is in the public domain; do with it what you wish.
237 /* The four core functions - F1 is optimized somewhat */
238 #define F1(x, y, z) (z ^ (x & (y ^ z)))
239 #define F2(x, y, z) F1 (z, x, y)
240 #define F3(x, y, z) (x ^ y ^ z)
241 #define F4(x, y, z) (y ^ (x | ~z))
243 /* This is the central step in the MD5 algorithm. */
244 #define pmd5_step(f, w, x, y, z, data, s) \
245 (w += (f(x, y, z) + data) & 0xffffffff, w = w<<s | w>>(32-s), w += x)
248 * The core of the MD5 algorithm, this alters an existing MD5 hash to
249 * reflect the addition of 16 longwords of new data.
252 pMD5Hash( unsigned *out
, unsigned const in
[16] )
261 pmd5_step( F1
, a
, b
, c
, d
, in
[0] + 0xd76aa478, 7 );
262 pmd5_step( F1
, d
, a
, b
, c
, in
[1] + 0xe8c7b756, 12 );
263 pmd5_step( F1
, c
, d
, a
, b
, in
[2] + 0x242070db, 17 );
264 pmd5_step( F1
, b
, c
, d
, a
, in
[3] + 0xc1bdceee, 22 );
265 pmd5_step( F1
, a
, b
, c
, d
, in
[4] + 0xf57c0faf, 7 );
266 pmd5_step( F1
, d
, a
, b
, c
, in
[5] + 0x4787c62a, 12 );
267 pmd5_step( F1
, c
, d
, a
, b
, in
[6] + 0xa8304613, 17 );
268 pmd5_step( F1
, b
, c
, d
, a
, in
[7] + 0xfd469501, 22 );
269 pmd5_step( F1
, a
, b
, c
, d
, in
[8] + 0x698098d8, 7 );
270 pmd5_step( F1
, d
, a
, b
, c
, in
[9] + 0x8b44f7af, 12 );
271 pmd5_step( F1
, c
, d
, a
, b
, in
[10] + 0xffff5bb1, 17 );
272 pmd5_step( F1
, b
, c
, d
, a
, in
[11] + 0x895cd7be, 22 );
273 pmd5_step( F1
, a
, b
, c
, d
, in
[12] + 0x6b901122, 7 );
274 pmd5_step( F1
, d
, a
, b
, c
, in
[13] + 0xfd987193, 12 );
275 pmd5_step( F1
, c
, d
, a
, b
, in
[14] + 0xa679438e, 17 );
276 pmd5_step( F1
, b
, c
, d
, a
, in
[15] + 0x49b40821, 22 );
278 pmd5_step( F2
, a
, b
, c
, d
, in
[1] + 0xf61e2562, 5 );
279 pmd5_step( F2
, d
, a
, b
, c
, in
[6] + 0xc040b340, 9 );
280 pmd5_step( F2
, c
, d
, a
, b
, in
[11] + 0x265e5a51, 14 );
281 pmd5_step( F2
, b
, c
, d
, a
, in
[0] + 0xe9b6c7aa, 20 );
282 pmd5_step( F2
, a
, b
, c
, d
, in
[5] + 0xd62f105d, 5 );
283 pmd5_step( F2
, d
, a
, b
, c
, in
[10] + 0x02441453, 9 );
284 pmd5_step( F2
, c
, d
, a
, b
, in
[15] + 0xd8a1e681, 14 );
285 pmd5_step( F2
, b
, c
, d
, a
, in
[4] + 0xe7d3fbc8, 20 );
286 pmd5_step( F2
, a
, b
, c
, d
, in
[9] + 0x21e1cde6, 5 );
287 pmd5_step( F2
, d
, a
, b
, c
, in
[14] + 0xc33707d6, 9 );
288 pmd5_step( F2
, c
, d
, a
, b
, in
[3] + 0xf4d50d87, 14 );
289 pmd5_step( F2
, b
, c
, d
, a
, in
[8] + 0x455a14ed, 20 );
290 pmd5_step( F2
, a
, b
, c
, d
, in
[13] + 0xa9e3e905, 5 );
291 pmd5_step( F2
, d
, a
, b
, c
, in
[2] + 0xfcefa3f8, 9 );
292 pmd5_step( F2
, c
, d
, a
, b
, in
[7] + 0x676f02d9, 14 );
293 pmd5_step( F2
, b
, c
, d
, a
, in
[12] + 0x8d2a4c8a, 20 );
295 pmd5_step( F3
, a
, b
, c
, d
, in
[5] + 0xfffa3942, 4 );
296 pmd5_step( F3
, d
, a
, b
, c
, in
[8] + 0x8771f681, 11 );
297 pmd5_step( F3
, c
, d
, a
, b
, in
[11] + 0x6d9d6122, 16 );
298 pmd5_step( F3
, b
, c
, d
, a
, in
[14] + 0xfde5380c, 23 );
299 pmd5_step( F3
, a
, b
, c
, d
, in
[1] + 0xa4beea44, 4 );
300 pmd5_step( F3
, d
, a
, b
, c
, in
[4] + 0x4bdecfa9, 11 );
301 pmd5_step( F3
, c
, d
, a
, b
, in
[7] + 0xf6bb4b60, 16 );
302 pmd5_step( F3
, b
, c
, d
, a
, in
[10] + 0xbebfbc70, 23 );
303 pmd5_step( F3
, a
, b
, c
, d
, in
[13] + 0x289b7ec6, 4 );
304 pmd5_step( F3
, d
, a
, b
, c
, in
[0] + 0xeaa127fa, 11 );
305 pmd5_step( F3
, c
, d
, a
, b
, in
[3] + 0xd4ef3085, 16 );
306 pmd5_step( F3
, b
, c
, d
, a
, in
[6] + 0x04881d05, 23 );
307 pmd5_step( F3
, a
, b
, c
, d
, in
[9] + 0xd9d4d039, 4 );
308 pmd5_step( F3
, d
, a
, b
, c
, in
[12] + 0xe6db99e5, 11 );
309 pmd5_step( F3
, c
, d
, a
, b
, in
[15] + 0x1fa27cf8, 16 );
310 pmd5_step( F3
, b
, c
, d
, a
, in
[2] + 0xc4ac5665, 23 );
312 pmd5_step( F4
, a
, b
, c
, d
, in
[0] + 0xf4292244, 6 );
313 pmd5_step( F4
, d
, a
, b
, c
, in
[7] + 0x432aff97, 10 );
314 pmd5_step( F4
, c
, d
, a
, b
, in
[14] + 0xab9423a7, 15 );
315 pmd5_step( F4
, b
, c
, d
, a
, in
[5] + 0xfc93a039, 21 );
316 pmd5_step( F4
, a
, b
, c
, d
, in
[12] + 0x655b59c3, 6 );
317 pmd5_step( F4
, d
, a
, b
, c
, in
[3] + 0x8f0ccc92, 10 );
318 pmd5_step( F4
, c
, d
, a
, b
, in
[10] + 0xffeff47d, 15 );
319 pmd5_step( F4
, b
, c
, d
, a
, in
[1] + 0x85845dd1, 21 );
320 pmd5_step( F4
, a
, b
, c
, d
, in
[8] + 0x6fa87e4f, 6 );
321 pmd5_step( F4
, d
, a
, b
, c
, in
[15] + 0xfe2ce6e0, 10 );
322 pmd5_step( F4
, c
, d
, a
, b
, in
[6] + 0xa3014314, 15 );
323 pmd5_step( F4
, b
, c
, d
, a
, in
[13] + 0x4e0811a1, 21 );
324 pmd5_step( F4
, a
, b
, c
, d
, in
[4] + 0xf7537e82, 6 );
325 pmd5_step( F4
, d
, a
, b
, c
, in
[11] + 0xbd3af235, 10 );
326 pmd5_step( F4
, c
, d
, a
, b
, in
[2] + 0x2ad7d2bb, 15 );
327 pmd5_step( F4
, b
, c
, d
, a
, in
[9] + 0xeb86d391, 21 );
335 /* ####################################################################### */
339 sumFile( const char *name
, int len
, int whence
, long offset
)
341 int fd
, i
, cnt
, readlen
= 0;
342 unsigned char buf
[0x1000];
344 if ((fd
= open( name
, O_RDONLY
)) < 0) {
345 debug( "cannot open entropy source %\"s: %m\n", name
);
348 lseek( fd
, offset
, whence
);
349 while (readlen
< len
) {
350 if (!(cnt
= read( fd
, buf
, sizeof(buf
) )))
354 debug( "cannot read entropy source %\"s: %m\n", name
);
358 if (sizeof(unsigned) == 4)
359 addEntropy( (unsigned *)buf
, (cnt
+ 3) / 4 );
361 unsigned buf2
[sizeof(buf
) / 4];
362 for (i
= 0; i
< cnt
; i
+= 8) {
363 buf2
[i
/ 4] = *(unsigned *)(buf
+ i
) & 0xffffffff;
364 buf2
[i
/ 4 + 1] = *(unsigned *)(buf
+ i
) >> 32;
366 addEntropy( buf2
, (cnt
+ 3) / 4 );
370 debug( "read %d bytes from entropy source %\"s\n", readlen
, name
);
375 addTimerEntropy( void )
378 gettimeofday( &now
, 0 );
379 addEntropy( (unsigned *)&now
, sizeof(now
)/sizeof(unsigned) );
385 addOtherEntropy( void )
388 /* XXX -- setup-specific ... use some common ones */
389 sumFile( "/var/log/messages", 0x1000, SEEK_END
, -0x1000 );
390 sumFile( "/var/log/syslog", 0x1000, SEEK_END
, -0x1000 );
391 sumFile( "/var/log/debug", 0x1000, SEEK_END
, -0x1000 );
392 sumFile( "/var/log/kern.log", 0x1000, SEEK_END
, -0x1000 );
393 sumFile( "/var/log/daemon.log", 0x1000, SEEK_END
, -0x1000 );
394 /* root hardly ever has an own box ... maybe pick a random mailbox instead? eek ...
395 sumFile( "/var/spool/mail/root", 0x1000, SEEK_END, -0x1000 );
400 addPreGetEntropy( void )
406 if ((readlen
= sumFile( randomFile
, BSIZ
, SEEK_SET
, offset
)) == BSIZ
) {
408 #if defined(__i386__) || defined(amiga)
409 if (!strcmp( randomFile
, "/dev/mem" )) {
410 if (offset
== 0xa0000) /* skip 640kB-1MB ROM mappings */
412 else if (offset
== 0xf00000) /* skip 15-16MB memory hole */
417 } else if (readlen
>= 0 && offset
) {
418 if ((offset
= sumFile( randomFile
, BSIZ
, SEEK_SET
, 0 )) == BSIZ
)
421 logError( "Cannot read randomFile %\"s; "
422 "X cookies may be easily guessable\n", randomFile
);
426 /* len MUST be multiple of sizeof(unsigned) and not more than 16! */
427 /* auth MUST be sizeof(unsigned)-aligned! */
429 generateAuthData( char *auth
, int len
)
431 #ifdef HAVE_ARC4RANDOM
433 unsigned *rnd
= (unsigned *)auth
;
434 if (sizeof(unsigned) == 4)
435 for (i
= 0; i
< len
; i
+= 4)
436 rnd
[i
/ 4] = arc4random();
438 for (i
= 0; i
< len
; i
+= 8)
439 rnd
[i
/ 8] = arc4random() | (arc4random() << 32);
443 const char *rd
= randomDevice
;
450 if ((fd
= open( rd
, O_RDONLY
)) >= 0) {
451 if (read( fd
, auth
, len
) == len
) {
456 logError( "Cannot read randomDevice %\"s: %m\n", rd
);
458 logError( "Cannot open randomDevice %\"s: %m\n", rd
);
464 if (!getPrngdBytes( auth
, len
, prngdPort
, prngdSocket
))
468 unsigned *rnd
= (unsigned *)auth
;
469 unsigned tmp
[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 };
471 pMD5Hash( tmp
, epool
);
472 addEntropy( tmp
, 1 );
473 pMD5Hash( tmp
, epool
+ 16 );
474 addEntropy( tmp
+ 2, 1 );
475 if (sizeof(unsigned) == 4)
476 memcpy( auth
, tmp
, len
);
479 for (i
= 0; i
< len
; i
+= 8)
480 rnd
[i
/ 8] = tmp
[i
/ 4] | (tmp
[i
/ 4 + 1] << 32);
488 #ifndef HAVE_ARC4RANDOM
493 generateAuthData( (char *)&rslt
, sizeof(int) );
494 return rslt
& 0x7fffffff;