not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kdm / backend / genauth.c
blob7fb286c4669bc939403356c6a8d0f1cac4911b42
1 /*
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
10 documentation.
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
35 #include "dm.h"
36 #include "dm_auth.h"
37 #include "dm_error.h"
39 #ifdef NEED_ENTROPY
41 # include <signal.h>
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
51 * are met:
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"
72 #include <string.h>
74 #ifndef INADDR_LOOPBACK
75 # define INADDR_LOOPBACK 0x7F000001U
76 #endif
78 static int
79 getPrngdBytes( char *buf, int len,
80 unsigned short tcp_port, const char *socket_path )
82 int fd, addr_len, rval, errors;
83 char msg[2];
84 struct sockaddr *addr;
85 struct sockaddr_in addr_in;
86 struct sockaddr_un addr_un;
87 int af;
88 SIGFUNC old_sigpipe;
90 if (tcp_port) {
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" );
102 return -1;
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;
109 } else
110 return -1;
112 old_sigpipe = Signal( SIGPIPE, SIG_IGN );
114 errors = 0;
115 rval = -1;
116 reopen:
117 if ((fd = socket( af, SOCK_STREAM, 0 )) < 0) {
118 logError( "Could not create socket: %m\n" );
119 goto done;
122 if (connect( fd, (struct sockaddr *)addr, addr_len )) {
123 if (af == AF_INET)
124 logError( "Could not connect to PRNGD port %d: %m\n",
125 tcp_port );
126 else
127 logError( "Could not connect to PRNGD socket %\"s: %m\n",
128 socket_path );
129 goto done;
132 /* Send blocking read request to PRNGD */
133 msg[0] = 0x02;
134 msg[1] = len;
136 if (writer( fd, msg, sizeof(msg) ) != sizeof(msg)) {
137 if (errno == EPIPE && errors < 10) {
138 close( fd );
139 errors++;
140 goto reopen;
142 logError( "Could not write to PRNGD socket: %m\n" );
143 goto done;
146 if (reader( fd, buf, len ) != len) {
147 if (errno == EPIPE && errors < 10) {
148 close( fd );
149 errors++;
150 goto reopen;
152 logError( "Could not read from PRNGD socket: %m\n" );
153 goto done;
156 rval = 0;
157 done:
158 Signal( SIGPIPE, old_sigpipe );
159 if (fd != -1)
160 close( fd );
161 return rval;
164 /* ####################################################################### */
167 * Stolen from the Linux kernel.
169 * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All
170 * rights reserved.
172 * Redistribution and use in source and binary forms, with or without
173 * modification, are permitted provided that the following conditions
174 * are met:
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
196 * DAMAGE.
199 static unsigned epool[32], erotate, eadd_ptr;
201 static void
202 addEntropy( unsigned const *in, int nwords )
204 static unsigned const twist_table[8] = {
205 0, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
206 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
207 unsigned i, w;
208 int new_rotate;
210 while (nwords--) {
211 w = *in++;
212 w = (w<<erotate | w>>(32-erotate)) & 0xffffffff;
213 i = eadd_ptr = (eadd_ptr - 1) & 31;
214 new_rotate = erotate + 14;
215 if (i)
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];
223 w ^= epool[i];
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.
251 static void
252 pMD5Hash( unsigned *out, unsigned const in[16] )
254 unsigned a, b, c, d;
256 a = out[0];
257 b = out[1];
258 c = out[2];
259 d = out[3];
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 );
329 out[0] += a;
330 out[1] += b;
331 out[2] += c;
332 out[3] += d;
335 /* ####################################################################### */
338 static int
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 );
346 return -1;
348 lseek( fd, offset, whence );
349 while (readlen < len) {
350 if (!(cnt = read( fd, buf, sizeof(buf) )))
351 break;
352 if (cnt < 0) {
353 close( fd );
354 debug( "cannot read entropy source %\"s: %m\n", name );
355 return -1;
357 readlen += cnt;
358 if (sizeof(unsigned) == 4)
359 addEntropy( (unsigned *)buf, (cnt + 3) / 4 );
360 else {
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 );
369 close( fd );
370 debug( "read %d bytes from entropy source %\"s\n", readlen, name );
371 return readlen;
374 void
375 addTimerEntropy( void )
377 struct timeval now;
378 gettimeofday( &now, 0 );
379 addEntropy( (unsigned *)&now, sizeof(now)/sizeof(unsigned) );
382 #define BSIZ 0x10000
384 void
385 addOtherEntropy( void )
387 addTimerEntropy();
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 );
399 void
400 addPreGetEntropy( void )
402 static long offset;
403 int readlen;
405 addTimerEntropy();
406 if ((readlen = sumFile( randomFile, BSIZ, SEEK_SET, offset )) == BSIZ) {
407 offset += readlen;
408 #if defined(__i386__) || defined(amiga)
409 if (!strcmp( randomFile, "/dev/mem" )) {
410 if (offset == 0xa0000) /* skip 640kB-1MB ROM mappings */
411 offset = 0x100000;
412 else if (offset == 0xf00000) /* skip 15-16MB memory hole */
413 offset = 0x1000000;
415 #endif
416 return;
417 } else if (readlen >= 0 && offset) {
418 if ((offset = sumFile( randomFile, BSIZ, SEEK_SET, 0 )) == BSIZ)
419 return;
421 logError( "Cannot read randomFile %\"s; "
422 "X cookies may be easily guessable\n", randomFile );
424 #endif
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
432 int i;
433 unsigned *rnd = (unsigned *)auth;
434 if (sizeof(unsigned) == 4)
435 for (i = 0; i < len; i += 4)
436 rnd[i / 4] = arc4random();
437 else
438 for (i = 0; i < len; i += 8)
439 rnd[i / 8] = arc4random() | (arc4random() << 32);
440 return True;
441 #else
442 int fd;
443 const char *rd = randomDevice;
444 # ifdef DEV_RANDOM
445 if (!*rd)
446 rd = DEV_RANDOM;
447 # else
448 if (*rd) {
449 # endif
450 if ((fd = open( rd, O_RDONLY )) >= 0) {
451 if (read( fd, auth, len ) == len) {
452 close( fd );
453 return True;
455 close( fd );
456 logError( "Cannot read randomDevice %\"s: %m\n", rd );
457 } else
458 logError( "Cannot open randomDevice %\"s: %m\n", rd );
459 # ifdef DEV_RANDOM
460 return False;
461 # else
464 if (!getPrngdBytes( auth, len, prngdPort, prngdSocket ))
465 return True;
468 unsigned *rnd = (unsigned *)auth;
469 unsigned tmp[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 };
470 addPreGetEntropy();
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 );
477 else {
478 int i;
479 for (i = 0; i < len; i += 8)
480 rnd[i / 8] = tmp[i / 4] | (tmp[i / 4 + 1] << 32);
483 return True;
484 # endif
485 #endif
488 #ifndef HAVE_ARC4RANDOM
490 secureRandom( void )
492 int rslt;
493 generateAuthData( (char *)&rslt, sizeof(int) );
494 return rslt & 0x7fffffff;
496 #endif