source: trunk/src/sh_entropy.c @ 132

Last change on this file since 132 was 132, checked in by rainer, 12 years ago

Make utility functions thread-safe.

File size: 20.7 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
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.                           */
15/*                                                                         */
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.              */
19
20
21#include "config_xor.h"
22
23#include <stdio.h>
24#include <string.h>
25
26#include <sys/types.h>
27
28#ifdef HAVE_MEMORY_H
29#include <memory.h>
30#endif
31
32#if TIME_WITH_SYS_TIME
33#include <sys/time.h>
34#include <time.h>
35#else
36#if HAVE_SYS_TIME_H
37#include <sys/time.h>
38#else
39#include <time.h>
40#endif
41#endif
42
43
44#include <stdlib.h>
45#include <pwd.h>
46#include <unistd.h>
47#include <fcntl.h>
48#include <signal.h>
49#include <sys/stat.h>
50#include <errno.h>
51#include <sys/wait.h>
52
53
54#ifdef HAVE_SYS_SELECT_H
55#include <sys/select.h>
56#endif
57#include <sys/types.h>
58
59
60
61#include "samhain.h"
62#include "sh_utils.h"
63#include "sh_unix.h"
64#include "sh_tiger.h"
65#include "sh_calls.h"
66
67#undef  FIL__
68#define FIL__  _("sh_entropy.c")
69
70#if defined (HAVE_EGD_RANDOM)
71/* rndegd.c  -  interface to the EGD
72 *      Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
73 */
74#include <stddef.h>
75#include <sys/socket.h>
76#include <sys/un.h>
77
78static int
79do_write( int fd, void *buf, size_t nbytes )
80{
81    size_t nleft = nbytes;
82    int nwritten;
83
84    while( nleft > 0 ) {
85        nwritten = write( fd, buf, nleft);
86        if( nwritten < 0 ) {
87            if( errno == EINTR )
88                continue;
89            return -1;
90        }
91        nleft -= nwritten;
92        buf = (char*)buf + nwritten;
93    }
94    return 0;
95}
96
97static int
98do_read( int fd, void *buf, int nbytes )
99{
100    int n, nread = 0;
101
102    if (nbytes < 0)
103      return 0;
104
105    do {
106        do {
107            n = read(fd, (char*)buf + nread, nbytes );
108        } while( n == -1 && errno == EINTR );
109        if( n == -1 )
110            return -1;
111        nread += n;
112    } while( nread < nbytes );
113    return nbytes;
114}
115
116
117int sh_entropy(int getbytes, char * nbuf)
118{
119    static int fd = -1;
120    int n;
121    byte buffer[256+2];
122    int nbytes;
123    int do_restart = 0;
124    int myerror = 0;
125    int length;
126    char * p = nbuf;
127    int i;
128
129    SL_ENTER(_("sh_entropy"));
130
131    if( getbytes <= 0)
132        SL_RETURN( -1, _("sh_entropy"));
133    if (getbytes > KEY_BYT)
134      getbytes = KEY_BYT;
135    length = getbytes;
136
137  restart:
138    if( do_restart ) {
139        if( fd != -1 ) {
140            close( fd );
141            fd = -1;
142        }
143    }
144    if( fd == -1 ) {
145        const char *bname = NULL;
146        char *name;
147        struct sockaddr_un addr;
148        int addr_len;
149
150      #ifdef EGD_SOCKET_NAME
151        bname = EGD_SOCKET_NAME;
152      #endif
153        if ( !bname || !*bname )
154            bname = _("=entropy");
155
156        if ( *bname == '=' && bname[1] )
157            name = sh_util_strconcat ( DEFAULT_DATAROOT, "/", bname+1 , NULL );
158        else
159            name = sh_util_strconcat ( bname , NULL );
160
161        if ( strlen(name)+1 >= sizeof(addr.sun_path) )
162          {
163            sh_error_handle ((-1), FIL__, __LINE__, ENAMETOOLONG, MSG_E_SUBGEN,
164                             _("EGD socketname is too long"),
165                             _("sh_entropy") ); 
166            SH_FREE(name);
167            SL_RETURN( -1, _("sh_entropy") );
168          }
169
170        memset( &addr, 0, sizeof(addr) );
171        addr.sun_family = AF_UNIX;
172        sl_strlcpy( addr.sun_path, name, sizeof(addr.sun_path) );
173        addr_len = offsetof( struct sockaddr_un, sun_path )
174                   + strlen( addr.sun_path );
175
176        fd = socket(AF_UNIX, SOCK_STREAM, 0);
177        if( fd == -1 )
178          {
179            myerror = errno;
180            sh_error_handle ((-1), FIL__, __LINE__, myerror, MSG_E_SUBGEN,
181                             _("cannot create unix domain socket"),
182                             _("sh_entropy") ); 
183            SH_FREE(name);
184            SL_RETURN( -1, _("sh_entropy") );
185          }
186        if( connect( fd, (struct sockaddr*)&addr, addr_len) == -1 )
187          {
188            myerror = errno;
189            sh_error_handle ((-1), FIL__, __LINE__, myerror, MSG_E_SUBGEN,
190                             _("cannot connect to unix domain socket"),
191                             _("sh_entropy") ); 
192            SH_FREE(name);
193            SL_RETURN( -1, _("sh_entropy") );
194          }
195        SH_FREE(name);
196    }
197    do_restart = 0;
198
199    nbytes = length < 255? length : 255;
200    /* first time we do it with a non blocking request */
201    buffer[0] = 1; /* non blocking */
202    buffer[1] = nbytes;
203    if( do_write( fd, buffer, 2 ) == -1 )
204          {
205            myerror = errno;
206            sh_error_handle ((-1), FIL__, __LINE__, myerror, MSG_E_SUBGEN,
207                             _("cannot write to EGD"),
208                             _("sh_entropy") ); 
209            SL_RETURN( -1, _("sh_entropy") );
210          }
211    n = do_read( fd, buffer, 1 );
212    if( n == -1 ) {
213        myerror = errno;
214        sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, myerror, MSG_E_SUBGEN,
215                         _("read error on EGD"),
216                         _("sh_entropy") ); 
217        do_restart = 1;
218        goto restart;
219    }
220    n = buffer[0];
221    if( n ) {
222        n = do_read( fd, buffer, n );
223        if( n == -1 ) {
224            myerror = errno;
225            sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, myerror,MSG_E_SUBGEN,
226                             _("read error on EGD"),
227                             _("sh_entropy") ); 
228            do_restart = 1;
229            goto restart;
230        }
231        for (i = 0; i < n; ++i)
232          {
233            if (getbytes >= 0)
234              { *p = buffer[i]; ++p; --getbytes; }
235          }
236        length -= n;
237    }
238
239    while( length ) {
240        nbytes = length < 255? length : 255;
241
242        buffer[0] = 2; /* blocking */
243        buffer[1] = nbytes;
244        if( do_write( fd, buffer, 2 ) == -1 )
245          {
246            myerror = errno;
247            sh_error_handle ((-1), FIL__, __LINE__, myerror, MSG_E_SUBGEN,
248                             _("cannot write to EGD"),
249                             _("sh_entropy") ); 
250            SL_RETURN( -1, _("sh_entropy") );
251          }
252        n = do_read( fd, buffer, nbytes );
253        if( n == -1 ) {
254            myerror = errno;
255            sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, myerror,MSG_E_SUBGEN,
256                             _("read error on EGD"),
257                             _("sh_entropy") ); 
258            do_restart = 1;
259            goto restart;
260        }
261        for (i = 0; i < n; ++i)
262          {
263            if (getbytes >= 0)
264              { *p = buffer[i]; ++p; --getbytes; }
265          }
266        length -= n;
267    }
268    memset(buffer, 0, sizeof(buffer) );
269
270    SL_RETURN( 0, _("sh_entropy") ); /* success */
271}
272
273/* HAVE_EGD_RANDOM */
274#endif
275
276#if defined (HAVE_URANDOM)
277
278int read_mbytes(int timeout_val, char * path, char * nbuf, int nbytes)
279{
280  int m_count;
281  int fd2;
282
283  SL_ENTER(_("read_mbytes"));
284
285  if ((fd2 = aud_open (FIL__, __LINE__, SL_NOPRIV, path, O_RDONLY, 0)) >= 0) 
286    {
287      /* Test whether file is a character device, and is
288       * readable.
289       */
290      if (0 == sh_unix_device_readable(fd2)) 
291        {
292          m_count = sl_read_timeout_fd(fd2, &nbuf, nbytes, 
293                                       timeout_val, SL_FALSE);
294          if (m_count < 0)
295            m_count = 0;
296        }
297      else
298        m_count = 0;
299    }
300  else
301    m_count = 0;
302
303  close(fd2);
304
305  TPT((0, FIL__, __LINE__, _("msg=<read_mbytes: OK>\n"))); 
306  SL_RETURN(m_count, _("read_mbytes"));
307}
308
309/* Read nbytes bytes from /dev/random, mix them with
310 * previous reads using a hash function, and give out
311 * nbytes bytes from the result.
312 */
313int sh_entropy(int nbytes, char * nbuf)
314{
315  int    i, m_count = 0;
316  char * keybuf;
317  char   addbuf[2 * KEY_BYT];
318
319  SL_ENTER(_("sh_entropy"));
320
321  ASSERT((nbytes <= KEY_BYT), _("nbytes <= KEY_BYT"))
322
323  if (nbytes > KEY_BYT)
324    nbytes = KEY_BYT;
325
326  memset(nbuf, '\0', nbytes);
327
328#ifdef NAME_OF_DEV_URANDOM
329  m_count = read_mbytes (30, NAME_OF_DEV_RANDOM, nbuf, nbytes);
330#else
331  m_count = read_mbytes (300, NAME_OF_DEV_RANDOM, nbuf, nbytes);
332#endif
333
334  if (m_count == 0)
335    {
336#ifdef NAME_OF_DEV_URANDOM
337      sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__, EIO, MSG_NODEV, 
338                       (long) sh.real.uid, NAME_OF_DEV_RANDOM);
339#else
340      sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_NODEV, 
341                       (long) sh.real.uid, NAME_OF_DEV_RANDOM);
342#endif
343    }
344
345#ifdef NAME_OF_DEV_URANDOM
346  if (m_count < nbytes)
347    {
348      i = read_mbytes(30, NAME_OF_DEV_URANDOM, &nbuf[m_count], nbytes-m_count);
349      if (i == 0)
350        sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_NODEV, 
351                         (long) sh.real.uid, NAME_OF_DEV_URANDOM);
352      else
353        m_count += i;
354    }
355#endif
356
357
358  if (m_count > 0)
359    {
360      /* -- Add previous entropy into the new pool. --
361       */
362      memset(addbuf, '\0', sizeof(addbuf));
363      for (i = 0; i < m_count; ++i)
364        addbuf[i]         = nbuf[i];
365      for (i = 0; i < KEY_BYT; ++i)
366        addbuf[i+KEY_BYT] = skey->poolv[i];
367      keybuf = (char *) sh_tiger_hash_uint32 (addbuf, 
368                                              TIGER_DATA, 2 * KEY_BYT);
369      memset(addbuf, '\0', sizeof(addbuf));
370     
371      /* -- Give out nbytes bytes from the new pool. --
372       */
373      for (i = 0; i < KEY_BYT; ++i)
374        {
375          skey->poolv[i] = keybuf[i];
376          if (i < nbytes) 
377            nbuf[i] = keybuf[i];
378        }
379      memset (keybuf, '\0', KEY_BYT);
380     
381      SL_RETURN(0, _("sh_entropy"));
382    }
383  else
384    {
385      SL_RETURN((-1), _("sh_entropy"));
386    }
387}
388
389/* HAVE_URANDOM */
390#endif
391
392#ifdef HAVE_UNIX_RANDOM
393
394#ifndef FD_SET
395#define NFDBITS         32
396#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
397#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
398#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
399#endif /* !FD_SET */
400#ifndef FD_SETSIZE
401#define FD_SETSIZE      32
402#endif
403#ifndef FD_ZERO
404#define FD_ZERO(p)      memset((char *)(p), '\0', sizeof(*(p)))
405#endif
406
407#include "sh_static.h"
408
409static
410char   * com_path[] = {
411  N_("/usr/bin/xpg4/"),
412  N_("/usr/ucb/"),
413  N_("/bin/"),
414  N_("/sbin/"),
415  N_("/usr/bin/"),
416  N_("/usr/sbin/"),
417  N_("/usr/local/bin/"),
418  NULL
419};
420
421
422typedef struct {
423  char   * command;
424  char   * arg;
425  int      pipeFD;
426  pid_t    pid;
427  int      isset;
428  FILE   * pipe;
429} sourcetable_t;
430
431static
432sourcetable_t source[] = {
433  { N_("w"),
434    N_("w"),
435    0,
436    0,
437    0,
438    NULL },
439  { N_("netstat"),
440    N_("netstat -n"),
441    0,
442    0,
443    0,
444    NULL },
445  { N_("ps"),
446    N_("ps -ef"),
447    0,
448    0,
449    0,
450    NULL },
451  { N_("arp"),
452    N_("arp -a"),
453    0,
454    0,
455    0,
456    NULL },
457  { N_("free"),
458    N_("free"),
459    0,
460    0,
461    0,
462    NULL },
463  { N_("uptime"),
464    N_("uptime"),
465    0,
466    0,
467    0,
468    NULL },
469  { N_("procinfo"),
470    N_("procinfo -a"),
471    0,
472    0,
473    0,
474    NULL },
475  { N_("vmstat"),
476    N_("vmstat"),
477    0,
478    0,
479    0,
480    NULL },
481  { N_("w"), /* Play it again, Sam. */
482    N_("w"),
483    0,
484    0,
485    0,
486    NULL },
487  { NULL,
488    NULL,
489    0,
490    0,
491    0,
492    NULL }
493};
494
495
496static FILE * sh_popen (sourcetable_t  *source, char * command)
497{
498  int i;
499  int pipedes[2];
500  FILE *outf = NULL;
501  char * arg[4];
502  char * envp[2];
503  size_t len;
504  char   arg0[80];
505  char   arg1[80];
506
507  SL_ENTER(_("sh_popen"));
508
509  strncpy (arg0, _("/bin/sh"), sizeof(arg0));
510  arg[0] = arg0;
511  strncpy (arg1, _("-c"), sizeof(arg1));
512  arg[1] = arg1;
513  arg[2] = command;
514  arg[3] = NULL;
515
516  if (sh.timezone != NULL)
517    {
518      len = sl_strlen(sh.timezone) + 4;
519      envp[0] = malloc (len);     /* free() ok     */
520      if (envp[0] != NULL)
521        sl_snprintf (envp[0], len, "TZ=%s", sh.timezone);
522      else
523        envp[0] = NULL;
524      envp[1] = NULL;
525    }
526  else
527    {
528      envp[0] = NULL;
529    }
530
531 
532  /* Create the pipe
533   */
534  if (aud_pipe(FIL__, __LINE__, pipedes) < 0) {
535    if (envp[0] != NULL) free(envp[0]);
536    SL_RETURN(NULL, _("sh_popen"));
537  }
538 
539  fflush (NULL);
540
541  source->pid = aud_fork(FIL__, __LINE__);
542 
543  /* Failure
544   */
545  if (source->pid == (pid_t) - 1) {
546    close(pipedes[0]);
547    close(pipedes[1]);
548    if (envp[0] != NULL) free(envp[0]);
549    SL_RETURN(NULL, _("sh_popen"));
550  }
551
552  if (source->pid == (pid_t) 0) 
553    {
554
555      /* child - make read side of the pipe stdout
556       */
557      if (retry_aud_dup2(FIL__, __LINE__, 
558                         pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
559        aud__exit(FIL__, __LINE__, EXIT_FAILURE);
560     
561      /* close the pipe descriptors
562       */
563      close   (pipedes[STDIN_FILENO]);
564      close   (pipedes[STDOUT_FILENO]);
565
566      /* don't leak file descriptors
567       */
568      sh_unix_closeall (3, -1); /* in child process */
569
570      /* zero priv info
571       */
572      memset(skey, 0, sizeof(sh_key_t));
573
574      /* drop root privileges
575       */
576      i = 0; 
577      if (0 == geteuid()) 
578        {
579#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
580          struct passwd    pwd;
581          char             buffer[SH_PWBUF_SIZE];
582          struct passwd *  tempres;
583          sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, sizeof(buffer), &tempres);
584#else
585          struct passwd * tempres = sh_getpwnam(DEFAULT_IDENT);
586#endif
587 
588          if (NULL != tempres) {
589            i = aud_setgid(FIL__, __LINE__, tempres->pw_gid); 
590            if (i == 0)
591              i = sh_unix_initgroups(DEFAULT_IDENT ,tempres->pw_gid);
592            if (i == 0) 
593              i = aud_setuid(FIL__, __LINE__, tempres->pw_uid);
594            /* make sure we cannot get root again
595             */
596            if ((tempres->pw_uid != 0) && (aud_setuid(FIL__, __LINE__, 0) >= 0))
597              i = -1;
598          } else {
599            i = -1;
600          }
601        }
602     
603      /* some problem ...
604       */
605      if (i == -1) {
606        aud__exit(FIL__, __LINE__, EXIT_FAILURE);
607      }
608     
609      freopen (_("/dev/null"), "r+", stderr);
610     
611      /* exec the program */
612      retry_aud_execve (FIL__, __LINE__, _("/bin/sh"), arg, envp);
613     
614      /* failed
615       */
616      aud__exit(FIL__, __LINE__, EXIT_FAILURE);
617    }
618
619    /* parent
620     */
621    if (envp[0] != NULL) 
622      free(envp[0]);
623
624    close (pipedes[STDOUT_FILENO]);
625    retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
626
627    outf = fdopen (pipedes[STDIN_FILENO], "r");
628
629    if (outf == NULL) 
630      {
631        aud_kill (FIL__, __LINE__, source->pid, SIGKILL);
632        close (pipedes[STDOUT_FILENO]);
633        waitpid (source->pid, NULL, 0);
634        source->pid = 0;
635        SL_RETURN(NULL, _("sh_popen"));
636      }
637
638    SL_RETURN(outf, _("sh_popen"));
639}
640
641
642static int sh_pclose (sourcetable_t *source)
643{
644    int status = 0;
645    int retval;
646    char msg[128];
647    char errbuf[SH_ERRBUF_SIZE];
648
649    SL_ENTER(_("sh_pclose"));
650
651    retval = fclose(source->pipe);
652    if (retval)
653      {
654        sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, retval, 
655                         MSG_E_SUBGEN,
656                         sh_error_message(retval, errbuf, sizeof(errbuf)),
657                         _("sh_pclose"));
658        SL_RETURN((-1), _("sh_pclose"));
659      }
660
661    retval = waitpid(source->pid, &status, 0);
662    if (retval != source->pid)
663      {
664        sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, retval, 
665                         MSG_E_SUBGEN,
666                         sh_error_message(retval, errbuf, sizeof(errbuf)),
667                         _("sh_pclose"));
668
669        status = -1;
670      }
671    else if (WIFSIGNALED(status))
672      {
673        sl_snprintf(msg, sizeof(msg), _("Subprocess terminated by signal %d"),
674                    WTERMSIG(status));
675        sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, retval, 
676                         MSG_E_SUBGEN,
677                         msg,
678                         _("sh_pclose"));
679        status = -1;
680      }
681
682    source->pipe = NULL;
683    source->pid = 0;
684    SL_RETURN(status, _("sh_pclose"));
685}
686
687#define BUF_ENT 32766
688
689/* Poll the system for randomness, mix results with
690 * previous reads using a hash function, and give out
691 * nbytes bytes from the result.
692 */
693int sh_entropy(int nbytes, char * nbuf)
694{
695  int    caperr;
696  char   combuf[80];
697  char * buffer;
698  int    i, j, icount;
699  int    bufcount = 0;
700  int    count;
701
702  char * keybuf;
703  char   addbuf[2 * KEY_BYT];
704
705  struct timeval tv;
706  fd_set fds;
707  unsigned long select_now = 0;
708  int    maxFD = 0;
709  int    imax, selcount;
710  char errbuf[SH_ERRBUF_SIZE];
711 
712  SL_ENTER(_("sh_entropy"));
713
714  ASSERT((nbytes <= KEY_BYT), _("nbytes <= KEY_BYT"))
715
716  if (nbytes > KEY_BYT)
717    nbytes = KEY_BYT;
718
719
720  /* --- If there is entropy in the pool, return it. ---
721   */
722  if (skey->poolc >= nbytes)
723    {
724      j = KEY_BYT - skey->poolc;
725      for (i = 0; i < nbytes; ++i)
726        {
727          nbuf[i] = skey->poolv[i+j];
728          --skey->poolc;
729        }
730      SL_RETURN(0, _("sh_entropy"));
731    }
732
733
734  FD_ZERO(&fds);   
735
736  i = 0; icount = 0;
737  buffer = SH_ALLOC(BUF_ENT+2);
738
739  if (0 != (caperr = sl_get_cap_sub()))
740    {
741      sh_error_handle((-1), FIL__, __LINE__, caperr, MSG_E_SUBGEN,
742                      sh_error_message (caperr, errbuf, sizeof(errbuf)), 
743                      _("sl_get_cap_sub"));
744    }
745
746  while (source[i].command != NULL) {
747
748    j = 0;
749    while (com_path[j] != NULL)
750      {
751        sl_strlcpy(combuf, _(com_path[j]),       80);
752        sl_strlcat(combuf, _(source[i].command), 80);
753
754        /* flawfinder: ignore */
755        if ( access (combuf, X_OK) == 0) 
756          {
757            sl_strlcpy(combuf, _(com_path[j]),       80);
758            sl_strlcat(combuf, _(source[i].arg),     80);
759            sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_ENSTART,
760                             combuf);
761            break;
762          }
763        ++j;
764      }
765
766    /* Not found, try next command.
767     */
768    if (com_path[j] == NULL) 
769      { 
770        ++i;
771        continue;
772      }
773
774    /* Source exists
775     */
776    source[i].pipe   = sh_popen  ( &source[i], combuf );
777    if (NULL != source[i].pipe)
778      { 
779        source[i].pipeFD = fileno ( source[i].pipe    );
780        sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_ENEXEC,
781                         combuf, (long) source[i].pipeFD);
782
783        maxFD = (source[i].pipeFD > maxFD) ? source[i].pipeFD : maxFD;
784        retry_fcntl( FIL__, __LINE__, source[i].pipeFD, F_SETFL, O_NONBLOCK);
785        FD_SET( source[i].pipeFD, &fds );
786        source[i].isset = 1;
787        ++icount;
788      }
789    else
790      {
791        sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_ENFAIL,
792                         combuf);
793      }
794
795    ++i;
796  }
797
798  imax       = i;
799  tv.tv_sec  = 1;
800  tv.tv_usec = 0;
801  bufcount   = 0;
802
803  while ( (icount > 0) && (bufcount < BUF_ENT) ) {
804
805    if ( (selcount = select (maxFD+1, &fds, NULL, NULL, &tv)) == -1) 
806      break;
807
808    /* reset timeout for select()
809     */
810    tv.tv_sec  = 1;
811    tv.tv_usec = 0;
812
813    /* timeout - let's not hang on forever
814     */
815    if (selcount == 0) 
816      {
817        ++select_now;
818        sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_ENTOUT,
819                         (unsigned long) select_now);
820        if ( select_now > 9 ) 
821          break;
822      }
823   
824    for (i = 0; i < imax; ++i) {
825
826      if ( FD_ISSET (source[i].pipeFD, &fds) ) {
827        count = fread (&buffer[bufcount], 
828                       1, 
829                       BUF_ENT-bufcount, 
830                       source[i].pipe );
831        if (count == 0) 
832          {
833            if (0 != feof(source[i].pipe))
834              sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_ENCLOS,
835                               (long) source[i].pipeFD);
836            else
837              sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_ENCLOS1,
838                               (long) source[i].pipeFD);
839            source[i].isset = 0;
840            sh_pclose ( &source[i] );
841            --icount;
842          }
843        else
844          {
845            sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_ENREAD,
846                             (long) source[i].pipeFD, (long) count);
847          }
848        bufcount += count;
849
850      } 
851    }
852
853    maxFD = 0;
854    FD_ZERO(&fds);   
855   
856    for (i = 0; i < imax; ++i)
857      {
858        if (source[i].isset == 1)
859          { 
860            FD_SET( source[i].pipeFD, &fds );
861            maxFD = (source[i].pipeFD > maxFD) ? source[i].pipeFD : maxFD;
862          }
863      }
864  }
865
866  for (i = 0; i < imax; ++i) 
867    {
868      if (source[i].isset == 1)
869        {
870          sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_ENCLOS1,
871                             (long) source[i].pipeFD);
872          sh_pclose ( &source[i] );
873        }
874    }
875  buffer[bufcount] = '\0';
876
877  if (0 != (caperr = sl_drop_cap_sub()))
878    {
879      sh_error_handle((-1), FIL__, __LINE__, caperr, MSG_E_SUBGEN,
880                      sh_error_message (caperr, errbuf, sizeof(errbuf)), 
881                      _("sl_drop_cap_sub"));
882    }
883
884  if (bufcount > 0) 
885    {
886      keybuf = (char *) sh_tiger_hash_uint32 (buffer, 
887                                              TIGER_DATA, sl_strlen(buffer));
888
889      /* add previous entropy into the new pool
890       */
891      memset(addbuf, '\0', sizeof(addbuf));
892      for (i = 0; i < KEY_BYT; ++i)
893        {
894          addbuf[i]         = keybuf[i];
895          addbuf[i+KEY_BYT] = skey->poolv[i];
896        }
897      keybuf = (char *) sh_tiger_hash_uint32 (addbuf, 
898                                              TIGER_DATA, sizeof(addbuf));
899      memset(addbuf, '\0', sizeof(addbuf));
900     
901      /* store in system pool
902       */
903      for (i = 0; i < KEY_BYT; ++i)
904        skey->poolv[i] = keybuf[i];
905      skey->poolc = KEY_BYT;
906      memset (buffer, '\0', BUF_ENT+2);
907      memset (keybuf, '\0', KEY_BYT);
908      SH_FREE(buffer);
909    } 
910  else 
911    {
912      SH_FREE(buffer);
913      SL_RETURN((-1), _("sh_entropy"));
914    }
915
916  /* give out nbytes Bytes from the entropy pool
917   */
918  for (i = 0; i < nbytes; ++i)
919    {
920      nbuf[i] = skey->poolv[i];
921      --skey->poolc;
922    }
923
924  SL_RETURN(0, _("sh_entropy"));
925}
926
927/* HAVE_UNIX_RANDOM */
928#endif
929
930
931
932
933
934
935
Note: See TracBrowser for help on using the repository browser.