dtlogin: don't try to use /dev/mem to get random data on linux/bsd
[oweals/cde.git] / cde / programs / dtlogin / genauth.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: genauth.c /main/6 1997/03/25 12:33:13 barstow $ */
24 /* (c) Copyright 1997, The Open Group */
25 /*                                                                      *
26  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
27  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
28  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
29  * (c) Copyright 1993, 1994 Novell, Inc.                                *
30  */
31
32 /*
33  * @DEC_COPYRIGHT@
34  */
35 /*
36  * HISTORY
37  * $Log$
38  * Revision 1.1.2.2  1995/04/21  13:05:23  Peter_Derr
39  *      dtlogin auth key fixes from deltacde
40  *      [1995/04/14  18:03:41  Peter_Derr]
41  *
42  *      R6 xdm code used in dtlogin.
43  *      [1995/04/10  16:52:31  Peter_Derr]
44  *
45  * Revision 1.1.3.3  1995/02/20  21:03:19  Peter_Derr
46  *      merge XC fix-11
47  *      [1995/02/20  20:13:02  Peter_Derr]
48  * 
49  * Revision 1.1.3.2  1994/07/13  19:26:25  Peter_Derr
50  *      Include Wrap.h to get definitions for XDM-AUTHENTICATION-1
51  *      authorization mechanism.
52  *      [1994/07/13  12:15:59  Peter_Derr]
53  * 
54  * $EndLog$
55  */
56 #ifndef lint
57 static char *rcsid = "@(#)$RCSfile: genauth.c $ $Revision: /main/6 $ (DEC) $Date: 1997/03/25 12:33:13 $";
58 #endif
59 /*
60
61 Copyright (c) 1988  X Consortium
62
63 Permission is hereby granted, free of charge, to any person obtaining
64 a copy of this software and associated documentation files (the
65 "Software"), to deal in the Software without restriction, including
66 without limitation the rights to use, copy, modify, merge, publish,
67 distribute, sublicense, and/or sell copies of the Software, and to
68 permit persons to whom the Software is furnished to do so, subject to
69 the following conditions:
70
71 The above copyright notice and this permission notice shall be included
72 in all copies or substantial portions of the Software.
73
74 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
75 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
76 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
77 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
78 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
79 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
80 OTHER DEALINGS IN THE SOFTWARE.
81
82 Except as contained in this notice, the name of the X Consortium shall
83 not be used in advertising or otherwise to promote the sale, use or
84 other dealings in this Software without prior written authorization
85 from the X Consortium.
86
87 */
88
89 /*
90  * xdm - display manager daemon
91  * Author:  Keith Packard, MIT X Consortium
92  */
93
94 # include   <X11/Xauth.h>
95 # include   <X11/Xos.h>
96 # include   "dm.h"
97
98 #include <errno.h>
99
100 #ifdef X_NOT_STDC_ENV
101 #define Time_t long
102 extern Time_t time ();
103 extern int errno;
104 #else
105 #include <time.h>
106 #define Time_t time_t
107 #endif
108
109 #ifndef DONT_USE_DES
110 # ifndef USE_CRYPT
111 #  ifdef AIXV3
112 #   define USE_CRYPT
113 #  endif
114 #  ifdef ultrix
115 #   define USE_CRYPT
116 #  endif
117 #  ifdef hpux
118 #   define USE_CRYPT
119 #  endif
120 #  ifdef macII
121 #   define USE_CRYPT
122 #  endif
123 #  ifdef sun
124 #   define USE_CRYPT
125 #   if (OSMAJORVERSION >= 4)
126      /* avoid strange sun crypt hackery */
127 #    define crypt _crypt
128 #   endif
129 #  endif
130 # endif
131 #endif
132
133 #if !defined (DONT_USE_DES) && !defined (USE_CRYPT)
134 # define USE_ENCRYPT
135 #endif
136
137 #ifdef HASXDMAUTH
138 static unsigned char    key[8];
139 #else
140 static long             key[2];
141 #endif
142
143 static sumFile (char *name, long sum[2]);
144
145 #ifdef HASXDMAUTH
146
147 typedef unsigned char auth_cblock[8];   /* block size */
148
149 typedef struct auth_ks_struct { auth_cblock _; } auth_wrapper_schedule[16];
150
151 extern void _XdmcpWrapperToOddParity();
152
153 static
154 longtochars (l, c)
155     long            l;
156     unsigned char    *c;
157 {
158     c[0] = (l >> 24) & 0xff;
159     c[1] = (l >> 16) & 0xff;
160     c[2] = (l >> 8) & 0xff;
161     c[3] = l & 0xff;
162 }
163
164 static
165 InitXdmcpWrapper ()
166 {
167     long            sum[2];
168     unsigned char   tmpkey[8];
169 /*
170  * randomFile is and xdm resource not defined in dtlogin.
171  *
172  *   if (!sumFile (randomFile, sum)) {
173  */
174     if (!sumFile ("/dev/mem", sum)) {
175         sum[0] = time ((Time_t *) 0);
176         sum[1] = time ((Time_t *) 0);
177     }
178     longtochars (sum[0], tmpkey+0);
179     longtochars (sum[1], tmpkey+4);
180     tmpkey[0] = 0;
181     _XdmcpWrapperToOddParity (tmpkey, key);
182 }
183
184 #endif /* HASXDMAUTH */
185
186 #ifndef HASXDMAUTH
187 /* A random number generator that is more unpredictable
188    than that shipped with some systems.
189    This code is taken from the C standard. */
190
191 static unsigned long int next = 1;
192
193 static int
194 xdm_rand()
195 {
196     next = next * 1103515245 + 12345;
197     return (unsigned int)(next/65536) % 32768;
198 }
199
200 static void
201 xdm_srand(seed)
202     unsigned int seed;
203 {
204     next = seed;
205 }
206 #endif /* no HASXDMAUTH */
207
208 #ifdef USE_ENCRYPT
209 static
210 bitsToBytes (bits, bytes)
211 unsigned long   bits[2];
212 char    bytes[64];
213 {
214     int bit, byte;
215     int i;
216
217     i = 0;
218     for (byte = 0; byte < 2; byte++)
219         for (bit = 0; bit < 32; bit++)
220             bytes[i++] = ((bits[byte] & (1 << bit)) != 0);
221 }
222 #endif /* USE_ENCRYPT */
223
224 # define FILE_LIMIT     1024    /* no more than this many buffers */
225
226 /* for linux/csrg we use a simpler method to get 2 random longs from
227  *  the OS's random number device.
228  */
229
230 #if defined(linux) || defined(CSRG_BASED)
231 #define READ_LIMIT (sizeof (long) * 2)
232
233 static sumFile (char *name, long sum[2])
234 {
235   long    buf[2];
236   int     fd;
237   int     ret_status = 0;
238
239   if ( (fd = open (name, 0)) < 0 )
240     {
241       LogError((unsigned char *) "Cannot open randomFile \"%s\", errno = %d\n",
242                name, errno);
243       return 0;
244     }
245
246   sum[0] = 0;
247   sum[1] = 0;
248
249   if (read(fd, (char *)buf, READ_LIMIT) != READ_LIMIT)
250     {
251       LogError((unsigned char *) "Could not read %d bytes from '%s'\n",
252                READ_LIMIT, name);
253       /* cheap fallback */
254       sum[0] = (long)time((Time_t *) 0);
255       sum[1] = sum[0];
256     }
257   else
258     {
259       sum[0] = buf[0];
260       sum[1] = buf[1];
261       ret_status = 1;
262     }
263
264   close(fd);
265   return ret_status;
266 }
267
268 #undef READ_LIMIT
269
270 #else /* linux || CSRG_BASED */
271
272 static
273 sumFile (name, sum)
274 char    *name;
275 long    sum[2];
276 {
277     long    buf[1024*2];
278     int     cnt;
279     int     fd;
280     int     loops;
281     int     reads;
282     int     i;
283     int     ret_status = 0;
284
285     fd = open (name, 0);
286     if (fd < 0) {
287         LogError((unsigned char *) "Cannot open randomFile \"%s\", errno = %d\n", name, errno);
288         return 0;
289     }
290 #ifdef FRAGILE_DEV_MEM
291     if (strcmp(name, "/dev/mem") == 0) lseek (fd, (off_t) 0x100000, SEEK_SET);
292 #endif
293     reads = FILE_LIMIT;
294     sum[0] = 0;
295     sum[1] = 0;
296     while ((cnt = read (fd, (char *) buf, sizeof (buf))) > 0 && --reads > 0) {
297         loops = cnt / (2 * sizeof (long));
298         for (i = 0; i < loops; i+= 2) {
299             sum[0] += buf[i];
300             sum[1] += buf[i+1];
301             ret_status = 1;
302         }
303     }
304     if (cnt < 0)
305         LogError((unsigned char *) "Cannot read randomFile \"%s\", errno = %d\n", name, errno);
306     close (fd);
307     return ret_status;
308 }
309 #endif /* linux || CSRG_BASED */
310
311 GenerateAuthData (auth, len)
312 char    *auth;
313 int     len;
314 {
315     long            ldata[2];
316
317 #ifdef ITIMER_REAL
318     {
319         struct timeval  now;
320
321         X_GETTIMEOFDAY (&now);
322         ldata[0] = now.tv_sec;
323         ldata[1] = now.tv_usec;
324     }
325 #else
326     {
327         long    time ();
328
329         ldata[0] = time ((long *) 0);
330         ldata[1] = getpid ();
331     }
332 #endif /* ITIMER_REAL */
333
334 #ifdef HASXDMAUTH
335     {
336         int                 bit;
337         int                 i;
338         auth_wrapper_schedule    schedule;
339         unsigned char       tdata[8];
340         static int          xdmcpAuthInited;
341     
342         longtochars (ldata[0], tdata+0);
343         longtochars (ldata[1], tdata+4);
344         if (!xdmcpAuthInited)
345         {
346             InitXdmcpWrapper ();
347             xdmcpAuthInited = 1;
348         }
349         _XdmcpAuthSetup (key, schedule);
350         for (i = 0; i < len; i++) {
351             auth[i] = 0;
352             for (bit = 1; bit < 256; bit <<= 1) {
353                 _XdmcpAuthDoIt (tdata, tdata, schedule, 1);
354                 if (tdata[0] + tdata[1] & 0x4)
355                     auth[i] |= bit;
356             }
357         }
358     }
359 #else
360
361     InitCryptoKey ();
362
363 #if defined(USE_CRYPT)
364     {
365         int         i, j, k;
366         char    *result, *crypt ();
367         char    cdata[9];
368         long    sdata;
369     
370         for (j = 0; j < 2; j++)
371         {
372             sdata = ldata[j];
373             for (i = 0; i < 4; i++)
374             {
375                 k = j * 4 + i;
376                 cdata[k] = sdata & 0xff;
377                 if (cdata[k] == 0)
378                     cdata[k] = 1;
379                 sdata >>= 8;
380             }
381         }
382         cdata[8] = '\0';
383         for (i = 0; i < len; i += 4)
384         {
385             result = crypt (cdata, (const char *) key);
386             k = 4;
387             if (i + k > len)
388                 k = len - i;
389             for (j = 0; j < k; j++)
390                 auth[i + j] = result[2 + j];
391             for (j = 0; j < 8; j++)
392                 cdata[j] = result[2 + j];
393         }
394     }
395 #elif defined(USE_ENCRYPT)
396     {
397         char    key_bits[64];
398         char    data_bits[64];
399         int         bit;
400         int         i;
401     
402         bitsToBytes (key, key_bits);
403         bitsToBytes (ldata, data_bits);
404         setkey (key_bits);
405         for (i = 0; i < len; i++) {
406             auth[i] = 0;
407             for (bit = 1; bit < 256; bit <<= 1) {
408                 encrypt (data_bits, 0);
409                 if (data_bits[bit])
410                     auth[i] |= bit;
411             }
412         }
413     }
414 #else
415     {
416         int         seed;
417         int         value;
418         int         i;
419     
420         seed = (ldata[0] + key[0]) +
421               ((ldata[1] + key[1]) << 16);
422         xdm_srand (seed);
423         for (i = 0; i < len; i++)
424         {
425             value = xdm_rand ();
426             auth[i] = (value & 0xff00)  >> 8;
427         }
428         value = len;
429         if (value > sizeof (key))
430             value = sizeof (key);
431         memmove( (char *) key, auth, value);
432     }
433 #endif
434 #endif
435 }
436
437 #ifndef HASXDMAUTH
438
439 static int  cryptoInited = 0;
440
441 int 
442 InitCryptoKey( void )
443 {
444 #if defined(linux) 
445     /* non-blocking */
446     char    *key_file = "/dev/urandom";
447 #elif defined(CSRG_BASED)
448     /* non-blocking */
449     char    *key_file = "/dev/random";
450 #else
451 # warning "Using /dev/mem for random bits."
452     /* JET - this seems like a really bad idea. */
453     char    *key_file = "/dev/mem";
454 #endif    
455     if (cryptoInited)
456         return;
457
458     /*
459      *  If the sumFile fails to produce a result
460      *  use the time of day.
461      */
462     if (!sumFile (key_file, key)) {
463
464 #ifdef ITIMER_REAL
465       {
466         struct timeval  now;
467         struct timezone zone;
468         gettimeofday (&now, &zone);
469         key[0] = now.tv_sec;
470         key[1] = now.tv_usec;
471       }
472 #else
473       {
474         long    time ();
475         
476         key[0] = time ((long *) 0);
477         key[1] = getpid ();
478       }
479 #endif
480
481     }
482     cryptoInited = 1;
483 }
484
485 #endif /* HASXDMAUTH */