dtlogin: Two additional coverity fixes
[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 __FreeBSD__
124 #   define USE_CRYPT
125 #  endif
126 #  ifdef __OpenBSD__
127 #   define DONT_USE_DES
128 #  endif
129 #  ifdef sun
130 #   define USE_CRYPT
131 #   if (OSMAJORVERSION >= 4)
132      /* avoid strange sun crypt hackery */
133 #    define crypt _crypt
134 #   endif
135 #  endif
136 # endif
137 #endif
138
139 #if !defined (DONT_USE_DES) && !defined (USE_CRYPT)
140 # define USE_ENCRYPT
141 #endif
142
143 #ifdef HASXDMAUTH
144 static unsigned char    key[8];
145 #else
146 static long             key[2];
147 #endif
148
149 static sumFile (char *name, long sum[2]);
150
151 #ifdef HASXDMAUTH
152
153 typedef unsigned char auth_cblock[8];   /* block size */
154
155 typedef struct auth_ks_struct { auth_cblock _; } auth_wrapper_schedule[16];
156
157 extern void _XdmcpWrapperToOddParity();
158
159 static void
160 longtochars (long l, unsigned char *c)
161 {
162     c[0] = (l >> 24) & 0xff;
163     c[1] = (l >> 16) & 0xff;
164     c[2] = (l >> 8) & 0xff;
165     c[3] = l & 0xff;
166 }
167
168 static void
169 InitXdmcpWrapper (void)
170 {
171     long            sum[2];
172     unsigned char   tmpkey[8];
173 /*
174  * randomFile is and xdm resource not defined in dtlogin.
175  *
176  *   if (!sumFile (randomFile, sum)) {
177  */
178     if (!sumFile ("/dev/mem", sum)) {
179         sum[0] = time ((Time_t *) 0);
180         sum[1] = time ((Time_t *) 0);
181     }
182     longtochars (sum[0], tmpkey+0);
183     longtochars (sum[1], tmpkey+4);
184     tmpkey[0] = 0;
185     _XdmcpWrapperToOddParity (tmpkey, key);
186 }
187
188 #endif /* HASXDMAUTH */
189
190 #ifndef HASXDMAUTH
191 /* A random number generator that is more unpredictable
192    than that shipped with some systems.
193    This code is taken from the C standard. */
194
195 static unsigned long int next = 1;
196
197 static int
198 xdm_rand(void)
199 {
200     next = next * 1103515245 + 12345;
201     return (unsigned int)(next/65536) % 32768;
202 }
203
204 static void
205 xdm_srand(unsigned int seed)
206 {
207     next = seed;
208 }
209 #endif /* no HASXDMAUTH */
210
211 #ifdef USE_ENCRYPT
212 static void
213 bitsToBytes (unsigned long bits[2], char bytes[64])
214 {
215     int bit, byte;
216     int i;
217
218     i = 0;
219     for (byte = 0; byte < 2; byte++)
220         for (bit = 0; bit < 32; bit++)
221             bytes[i++] = ((bits[byte] & (1 << bit)) != 0);
222 }
223 #endif /* USE_ENCRYPT */
224
225 # define FILE_LIMIT     1024    /* no more than this many buffers */
226
227 /* for linux/csrg we use a simpler method to get 2 random longs from
228  *  the OS's random number device.
229  */
230
231 #if defined(linux) || defined(CSRG_BASED) || defined(sun)
232 #define READ_LIMIT (sizeof (long) * 2)
233
234 static int
235 sumFile (char *name, long sum[2])
236 {
237   long    buf[2];
238   int     fd;
239   int     ret_status = 0;
240
241   if ( (fd = open (name, 0)) < 0 )
242     {
243       LogError((unsigned char *) "Cannot open randomFile \"%s\", errno = %d\n",
244                name, errno);
245       return 0;
246     }
247
248   sum[0] = 0;
249   sum[1] = 0;
250
251   if (read(fd, (char *)buf, READ_LIMIT) != READ_LIMIT)
252     {
253       LogError((unsigned char *) "Could not read %d bytes from '%s'\n",
254                READ_LIMIT, name);
255       /* cheap fallback */
256       sum[0] = (long)time((Time_t *) 0);
257       sum[1] = sum[0];
258     }
259   else
260     {
261       sum[0] = buf[0];
262       sum[1] = buf[1];
263       ret_status = 1;
264     }
265
266   close(fd);
267   return ret_status;
268 }
269
270 #undef READ_LIMIT
271
272 #else /* linux || CSRG_BASED */
273
274 static int
275 sumFile (char *name, 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 void
312 GenerateAuthData (char *auth, int len)
313 {
314     long            ldata[2];
315
316 #ifdef ITIMER_REAL
317     {
318         struct timeval  now;
319
320         X_GETTIMEOFDAY (&now);
321         ldata[0] = now.tv_sec;
322         ldata[1] = now.tv_usec;
323     }
324 #else
325     {
326         long    time ();
327
328         ldata[0] = time ((long *) 0);
329         ldata[1] = getpid ();
330     }
331 #endif /* ITIMER_REAL */
332
333 #ifdef HASXDMAUTH
334     {
335         int                 bit;
336         int                 i;
337         auth_wrapper_schedule    schedule;
338         unsigned char       tdata[8];
339         static int          xdmcpAuthInited;
340     
341         longtochars (ldata[0], tdata+0);
342         longtochars (ldata[1], tdata+4);
343         if (!xdmcpAuthInited)
344         {
345             InitXdmcpWrapper ();
346             xdmcpAuthInited = 1;
347         }
348         _XdmcpAuthSetup (key, schedule);
349         for (i = 0; i < len; i++) {
350             auth[i] = 0;
351             for (bit = 1; bit < 256; bit <<= 1) {
352                 _XdmcpAuthDoIt (tdata, tdata, schedule, 1);
353                 if (tdata[0] + tdata[1] & 0x4)
354                     auth[i] |= bit;
355             }
356         }
357     }
358 #else
359
360     InitCryptoKey ();
361
362 #if defined(USE_CRYPT)
363     {
364         int         i, j, k;
365         char    *result, *crypt ();
366         char    cdata[9];
367         long    sdata;
368     
369         for (j = 0; j < 2; j++)
370         {
371             sdata = ldata[j];
372             for (i = 0; i < 4; i++)
373             {
374                 k = j * 4 + i;
375                 cdata[k] = sdata & 0xff;
376                 if (cdata[k] == 0)
377                     cdata[k] = 1;
378                 sdata >>= 8;
379             }
380         }
381         cdata[8] = '\0';
382         for (i = 0; i < len; i += 4)
383         {
384             result = crypt (cdata, (const char *) key);
385             k = 4;
386             if (i + k > len)
387                 k = len - i;
388             for (j = 0; j < k; j++)
389                 auth[i + j] = result[2 + j];
390             for (j = 0; j < 8; j++)
391                 cdata[j] = result[2 + j];
392         }
393     }
394 #elif defined(USE_ENCRYPT)
395     {
396         char    key_bits[64];
397         char    data_bits[64];
398         int         bit;
399         int         i;
400     
401         bitsToBytes (key, key_bits);
402         bitsToBytes (ldata, data_bits);
403         setkey (key_bits);
404         for (i = 0; i < len; i++) {
405             auth[i] = 0;
406             for (bit = 1; bit < 256; bit <<= 1) {
407                 encrypt (data_bits, 0);
408                 if (data_bits[bit])
409                     auth[i] |= bit;
410             }
411         }
412     }
413 #else
414     {
415         int         seed;
416         int         value;
417         int         i;
418     
419         seed = (ldata[0] + key[0]) +
420               ((ldata[1] + key[1]) << 16);
421         xdm_srand (seed);
422         for (i = 0; i < len; i++)
423         {
424             value = xdm_rand ();
425             auth[i] = (value & 0xff00)  >> 8;
426         }
427         value = len;
428         if (value > sizeof (key))
429             value = sizeof (key);
430         memmove( (char *) key, auth, value);
431     }
432 #endif
433 #endif
434 }
435
436 #ifndef HASXDMAUTH
437
438 static int  cryptoInited = 0;
439
440 int 
441 InitCryptoKey( void )
442 {
443 #if defined(linux) 
444     /* non-blocking */
445     char    *key_file = "/dev/urandom";
446 #elif defined(CSRG_BASED) || defined(sun)
447     /* non-blocking */
448     char    *key_file = "/dev/random";
449 #else
450 # warning "Using /dev/mem for random bits."
451     /* JET - this seems like a really bad idea. */
452     char    *key_file = "/dev/mem";
453 #endif    
454     if (cryptoInited)
455         return 0;
456
457     /*
458      *  If the sumFile fails to produce a result
459      *  use the time of day.
460      */
461     if (!sumFile (key_file, key)) {
462
463 #ifdef ITIMER_REAL
464       {
465         struct timeval  now;
466         struct timezone zone;
467         gettimeofday (&now, &zone);
468         key[0] = now.tv_sec;
469         key[1] = now.tv_usec;
470       }
471 #else
472       {
473         long    time ();
474         
475         key[0] = time ((long *) 0);
476         key[1] = getpid ();
477       }
478 #endif
479
480     }
481     cryptoInited = 1;
482
483     return 1;
484 }
485
486 #endif /* HASXDMAUTH */