19 #define DEBUG_CONFLICTS
23 #if defined( __GNUC__ )
40 #error For the BeOS build you need to edit $MISCOBJS in the makefile to use 'beos' and not 'unix'
43 #error For the eCOS build you need to edit $MISCOBJS in the makefile to use 'ecos' and not 'unix'
46 #error For the uITRON build you need to edit $MISCOBJS in the makefile to use 'itron' and not 'unix'
49 #error For the PalmOS build you need to edit $MISCOBJS in the makefile to use 'palmos' and not 'unix'
52 #error For the RTEMS build you need to edit $MISCOBJS in the makefile to use 'rtems' and not 'unix'
54 #if defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )
55 #error For the Tandem build you need to edit $MISCOBJS in the makefile to use 'tandem' and not 'unix'
57 #if defined( __VXWORKS__ )
58 #error For the VxWorks build you need to edit $MISCOBJS in the makefile to use 'vxworks' and not 'unix'
60 #if defined( __XMK__ )
61 #error For the Xilinx XMK build you need to edit $MISCOBJS in the makefile to use 'xmk' and not 'unix'
66 #if defined( __hpux ) && ( OSVERSION >= 10 )
67 #define _XOPEN_SOURCE_EXTENDED
73 #if !( defined( __QNX__ ) || defined( __MVS__ ) )
74 #include <sys/errno.h>
79 #if defined( _MPRAS ) && !( defined( _XOPEN_SOURCE ) && \
80 defined( __XOPEN_SOURCE_EXTENDED ) )
83 #define _XOPEN_SOURCE 1
84 #define _XOPEN_SOURCE_EXTENDED 1
85 #define MPRAS_XOPEN_DEFINES
87 #include <sys/resource.h>
88 #if defined( MPRAS_XOPEN_DEFINES )
90 #undef _XOPEN_SOURCE_EXTENDED
91 #undef MPRAS_XOPEN_DEFINES
94 #if defined( _AIX ) || defined( __QNX__ )
95 #include <sys/select.h>
98 #include <sys/systemcfg.h>
106 #if !( defined( __QNX__ ) || defined( __CYGWIN__ ) )
109 #if defined( __linux__ ) && ( defined(__i386__) || defined(__x86_64__) )
110 #include <sys/timex.h>
113 #include <sys/socket.h>
114 #include <sys/stat.h>
115 #include <sys/types.h>
117 #if defined( __hpux ) && ( OSVERSION == 9 )
120 #include <sys/wait.h>
123 #if defined( sun ) || defined( __ultrix__ ) || defined( __hpux )
130 #if defined( _CRAY ) || \
131 ( defined( __QNX__ ) && OSVERSION <= 4 )
132 #define setrlimit( x, y )
134 struct rusage {
int dummy; };
146 #define lockPollingMutex() pthread_mutex_lock( &gathererMutex )
147 #define unlockPollingMutex() pthread_mutex_unlock( &gathererMutex )
149 #define lockPollingMutex()
150 #define unlockPollingMutex()
155 #define RANDOM_BUFSIZE 4096
156 #if RANDOM_BUFSIZE > MAX_INTLENGTH_SHORT
157 #error RANDOM_BUFSIZE exceeds randomness accumulator size
163 #define ENSURES_EXIT( x ) \
164 if( !( x ) ) { assert( INTERNAL_ERROR ); exit( -1 ); }
232 #define SC( weight ) ( 1024 / weight )
248 {
"/bin/vmstat",
"-s",
SC( -3 ), NULL, 0, 0, 0,
TRUE },
249 {
"/usr/bin/vmstat",
"-s",
SC( -3 ), NULL, 0, 0, 0,
FALSE },
250 {
"/bin/vmstat",
"-c",
SC( -3 ), NULL, 0, 0, 0,
TRUE },
251 {
"/usr/bin/vmstat",
"-c",
SC( -3 ), NULL, 0, 0, 0,
FALSE },
252 #if defined( __APPLE__ )
253 {
"/usr/bin/vm_stat", NULL,
SC( -3 ), NULL, 0, 0, 0,
FALSE },
255 {
"/usr/bin/pfstat", NULL,
SC( -2 ), NULL, 0, 0, 0,
FALSE },
256 {
"/bin/vmstat",
"-i",
SC( -2 ), NULL, 0, 0, 0,
TRUE },
257 {
"/usr/bin/vmstat",
"-i",
SC( -2 ), NULL, 0, 0, 0,
FALSE },
258 #if defined( _AIX ) || defined( __SCO_VERSION__ )
259 {
"/usr/bin/vmstat",
"-f",
SC( -1 ), NULL, 0, 0, 0,
FALSE },
261 {
"/usr/ucb/netstat",
"-s",
SC( 2 ), NULL, 0, 0, 0,
TRUE },
262 {
"/usr/bin/netstat",
"-s",
SC( 2 ), NULL, 0, 0, 0,
TRUE },
263 {
"/usr/sbin/netstat",
"-s",
SC( 2 ), NULL, 0, 0, 0,
TRUE },
264 {
"/bin/netstat",
"-s",
SC( 2 ), NULL, 0, 0, 0,
TRUE },
265 {
"/usr/etc/netstat",
"-s",
SC( 2 ), NULL, 0, 0, 0,
FALSE },
266 {
"/usr/bin/nfsstat", NULL,
SC( 2 ), NULL, 0, 0, 0,
FALSE },
267 {
"/usr/ucb/netstat",
"-m",
SC( -1 ), NULL, 0, 0, 0,
TRUE },
268 {
"/usr/bin/netstat",
"-m",
SC( -1 ), NULL, 0, 0, 0,
TRUE },
269 {
"/usr/sbin/netstat",
"-m",
SC( -1 ), NULL, 0, 0, 0,
TRUE },
270 {
"/bin/netstat",
"-m",
SC( -1 ), NULL, 0, 0, 0,
TRUE },
271 {
"/usr/etc/netstat",
"-m",
SC( -1 ), NULL, 0, 0, 0,
FALSE },
272 {
"/usr/ucb/netstat",
"-in",
SC( -1 ), NULL, 0, 0, 0,
TRUE },
273 {
"/usr/bin/netstat",
"-in",
SC( -1 ), NULL, 0, 0, 0,
TRUE },
274 {
"/usr/sbin/netstat",
"-in",
SC( -1 ), NULL, 0, 0, 0,
TRUE },
275 {
"/bin/netstat",
"-in",
SC( -1 ), NULL, 0, 0, 0,
TRUE },
276 {
"/usr/etc/netstat",
"-in",
SC( -1 ), NULL, 0, 0, 0,
FALSE },
277 #ifndef __SCO_VERSION__
278 {
"/usr/sbin/snmp_request",
"localhost public get 1.3.6.1.2.1.7.1.0",
SC( -1 ), NULL, 0, 0, 0,
FALSE },
279 {
"/usr/sbin/snmp_request",
"localhost public get 1.3.6.1.2.1.7.4.0",
SC( -1 ), NULL, 0, 0, 0,
FALSE },
280 {
"/usr/sbin/snmp_request",
"localhost public get 1.3.6.1.2.1.4.3.0",
SC( -1 ), NULL, 0, 0, 0,
FALSE },
281 {
"/usr/sbin/snmp_request",
"localhost public get 1.3.6.1.2.1.6.10.0",
SC( -1 ), NULL, 0, 0, 0,
FALSE },
282 {
"/usr/sbin/snmp_request",
"localhost public get 1.3.6.1.2.1.6.11.0",
SC( -1 ), NULL, 0, 0, 0,
FALSE },
283 {
"/usr/sbin/snmp_request",
"localhost public get 1.3.6.1.2.1.6.13.0",
SC( -1 ), NULL, 0, 0, 0,
FALSE },
285 {
"/usr/sbin/snmpstat",
"-an localhost public",
SC(
SC_0 ), NULL, 0, 0, 0,
FALSE },
286 {
"/usr/sbin/snmpstat",
"-in localhost public",
SC(
SC_0 ), NULL, 0, 0, 0,
FALSE },
287 {
"/usr/sbin/snmpstat",
"-Sn localhost public",
SC(
SC_0 ), NULL, 0, 0, 0,
FALSE },
289 {
"/usr/bin/smartctl",
"-A /dev/hda" ,
SC( 1 ), NULL, 0, 0, 0,
FALSE },
290 {
"/usr/bin/smartctl",
"-A /dev/hdb" ,
SC( 1 ), NULL, 0, 0, 0,
FALSE },
291 {
"/usr/bin/mpstat", NULL,
SC( 1 ), NULL, 0, 0, 0,
FALSE },
292 {
"/usr/bin/w", NULL,
SC( 1 ), NULL, 0, 0, 0,
TRUE },
293 {
"/usr/bsd/w", NULL,
SC( 1 ), NULL, 0, 0, 0,
FALSE },
294 {
"/usr/bin/df", NULL,
SC( 1 ), NULL, 0, 0, 0,
TRUE },
295 {
"/bin/df", NULL,
SC( 1 ), NULL, 0, 0, 0,
FALSE },
296 {
"/usr/sbin/portstat", NULL,
SC( 1 ), NULL, 0, 0, 0,
FALSE },
297 {
"/usr/bin/iostat", NULL,
SC(
SC_0 ), NULL, 0, 0, 0,
FALSE },
298 {
"/usr/bin/uptime", NULL,
SC(
SC_0 ), NULL, 0, 0, 0,
TRUE },
299 {
"/usr/bsd/uptime", NULL,
SC(
SC_0 ), NULL, 0, 0, 0,
FALSE },
300 {
"/usr/bin/vmstat",
"-f",
SC(
SC_0 ), NULL, 0, 0, 0,
TRUE },
301 {
"/bin/vmstat",
"-f",
SC(
SC_0 ), NULL, 0, 0, 0,
TRUE },
302 {
"/usr/ucb/netstat",
"-n",
SC( 0.5 ), NULL, 0, 0, 0,
TRUE },
303 {
"/usr/bin/netstat",
"-n",
SC( 0.5 ), NULL, 0, 0, 0,
TRUE },
304 {
"/usr/sbin/netstat",
"-n",
SC( 0.5 ), NULL, 0, 0, 0,
TRUE },
305 {
"/bin/netstat",
"-n",
SC( 0.5 ), NULL, 0, 0, 0,
TRUE },
306 {
"/usr/etc/netstat",
"-n",
SC( 0.5 ), NULL, 0, 0, 0,
FALSE },
319 {
"/usr/sbin/ntptrace",
"-r2 -t1 -nv",
SC( -1 ), NULL, 0, 0, 0,
FALSE },
320 #if defined( __sgi ) || defined( __hpux )
321 {
"/bin/ps",
"-el",
SC( 0.3 ), NULL, 0, 0, 0,
TRUE },
323 {
"/usr/ucb/ps",
"aux",
SC( 0.3 ), NULL, 0, 0, 0,
TRUE },
324 {
"/usr/bin/ps",
"aux",
SC( 0.3 ), NULL, 0, 0, 0,
TRUE },
325 {
"/bin/ps",
"aux",
SC( 0.3 ), NULL, 0, 0, 0,
FALSE },
326 {
"/usr/bin/ipcs",
"-a",
SC( 0.5 ), NULL, 0, 0, 0,
TRUE },
327 {
"/bin/ipcs",
"-a",
SC( 0.5 ), NULL, 0, 0, 0,
FALSE },
329 {
"/etc/pstat",
"-p",
SC( 0.5 ), NULL, 0, 0, 0,
TRUE },
330 {
"/bin/pstat",
"-p",
SC( 0.5 ), NULL, 0, 0, 0,
FALSE },
331 {
"/etc/pstat",
"-S",
SC( 0.2 ), NULL, 0, 0, 0,
TRUE },
332 {
"/bin/pstat",
"-S",
SC( 0.2 ), NULL, 0, 0, 0,
FALSE },
333 {
"/etc/pstat",
"-v",
SC( 0.2 ), NULL, 0, 0, 0,
TRUE },
334 {
"/bin/pstat",
"-v",
SC( 0.2 ), NULL, 0, 0, 0,
FALSE },
335 {
"/etc/pstat",
"-x",
SC( 0.2 ), NULL, 0, 0, 0,
TRUE },
336 {
"/bin/pstat",
"-x",
SC( 0.2 ), NULL, 0, 0, 0,
FALSE },
337 {
"/etc/pstat",
"-t",
SC( 0.1 ), NULL, 0, 0, 0,
TRUE },
338 {
"/bin/pstat",
"-t",
SC( 0.1 ), NULL, 0, 0, 0,
FALSE },
340 #ifndef __SCO_VERSION__
341 {
"/usr/sbin/sar",
"-AR",
SC( 0.05 ), NULL, 0, 0, 0,
FALSE },
343 {
"/usr/bin/last",
"-n 50",
SC( 0.3 ), NULL, 0, 0, 0,
TRUE },
345 {
"/usr/bsd/last",
"-50",
SC( 0.3 ), NULL, 0, 0, 0,
FALSE },
348 {
"/etc/last",
"-50",
SC( 0.3 ), NULL, 0, 0, 0,
FALSE },
350 {
"/usr/bsd/last",
"-n 50",
SC( 0.3 ), NULL, 0, 0, 0,
FALSE },
352 {
"/usr/bin/showrev",
"-a",
SC( 0.1 ), NULL, 0, 0, 0,
FALSE },
353 {
"/usr/sbin/swap",
"-l",
SC(
SC_0 ), NULL, 0, 0, 0,
FALSE },
354 {
"/usr/sbin/prtconf",
"-v",
SC(
SC_0 ), NULL, 0, 0, 0,
FALSE },
356 {
"/usr/sbin/psrinfo", NULL,
SC(
SC_0 ), NULL, 0, 0, 0,
FALSE },
357 {
"/usr/bin/lsof",
"-blnwP",
SC( 0.3 ), NULL, 0, 0, 0,
TRUE },
358 {
"/usr/local/bin/lsof",
"-blnwP",
SC( 0.3 ), NULL, 0, 0, 0,
FALSE },
361 {
"/usr/sbin/snmp_request",
"localhost public get 1.3.6.1.2.1.5.1.0",
SC( 0.1 ), NULL, 0, 0, 0,
FALSE },
362 {
"/usr/sbin/snmp_request",
"localhost public get 1.3.6.1.2.1.5.3.0",
SC( 0.1 ), NULL, 0, 0, 0,
FALSE },
363 {
"/etc/arp",
"-a",
SC( 0.1 ), NULL, 0, 0, 0,
TRUE },
364 {
"/usr/etc/arp",
"-a",
SC( 0.1 ), NULL, 0, 0, 0,
TRUE },
365 {
"/usr/bin/arp",
"-a",
SC( 0.1 ), NULL, 0, 0, 0,
TRUE },
366 {
"/usr/sbin/arp",
"-a",
SC( 0.1 ), NULL, 0, 0, 0,
FALSE },
367 {
"/usr/sbin/ripquery",
"-nw 1 127.0.0.1",
SC( 0.1 ), NULL, 0, 0, 0,
FALSE },
368 {
"/bin/lpstat",
"-t",
SC( 0.1 ), NULL, 0, 0, 0,
TRUE },
369 {
"/usr/bin/lpstat",
"-t",
SC( 0.1 ), NULL, 0, 0, 0,
TRUE },
370 {
"/usr/ucb/lpstat",
"-t",
SC( 0.1 ), NULL, 0, 0, 0,
FALSE },
371 {
"/usr/bin/tcpdump",
"-c 5 -efvvx",
SC( 1 ), NULL, 0, 0, 0,
FALSE },
377 {
"/usr/sbin/advfsstat",
"-b usr_domain",
SC(
SC_0 ), NULL, 0, 0, 0,
FALSE },
378 {
"/usr/sbin/advfsstat",
"-l 2 usr_domain",
SC( 0.5 ), NULL, 0, 0, 0,
FALSE },
379 {
"/usr/sbin/advfsstat",
"-p usr_domain",
SC(
SC_0 ), NULL, 0, 0, 0,
FALSE },
389 {
"/usr/bin/finger",
"@ml.media.mit.edu",
SC( 0.9 ), NULL, 0, 0, 0,
FALSE },
390 {
"/usr/local/bin/wget",
"-O - http://lavarand.sgi.com/block.html",
SC( 0.9 ), NULL, 0, 0, 0,
FALSE },
391 {
"/bin/cat",
"/usr/spool/mqueue/syslog",
SC( 0.9 ), NULL, 0, 0, 0,
FALSE },
395 { NULL, NULL, 0, NULL, 0, 0, 0,
FALSE },
396 { NULL, NULL, 0, NULL, 0, 0, 0,
FALSE }
401 static pid_t gathererProcess = 0;
402 static BYTE *gathererBuffer;
403 static int gathererMemID;
404 static int gathererBufSize;
405 static struct sigaction gathererOldHandler;
407 static pthread_mutex_t gathererMutex;
424 #if defined( __hpux ) && ( OSVERSION == 9 )
431 static
int getrusage(
int who,
OUT struct rusage *rusage )
433 return( syscall( SYS_getrusage, who, rusage ) );
437 #if defined( __MVS__ ) || defined( __hpux )
444 OUT struct rusage *rusage )
446 const pid_t waitPid = waitpid( pid, status, options );
448 getrusage( RUSAGE_CHILDREN, rusage );
456 #if defined( _CRAY ) || ( defined( __QNX__ ) && OSVERSION <= 4 )
459 pid_t wait4( pid_t pid,
OUT int *status,
int options,
460 OUT struct rusage *rusage )
462 return( waitpid( pid, status, options ) );
490 int pipedes[ 2 + 8 ];
494 REQUIRES_N( STDIN_FILENO <= 1 && STDOUT_FILENO <= 1 );
498 if( pipe( pipedes ) < 0 )
528 entry->pid = vfork();
532 if( entry->pid == ( pid_t ) -1 )
535 close( pipedes[ 0 ] );
536 close( pipedes[ 1 ] );
540 if( entry->pid == ( pid_t ) 0 )
546 if( dup2( pipedes[ STDOUT_FILENO ], STDOUT_FILENO ) < 0 )
548 if( ( fd = open(
"/dev/null", O_RDWR ) ) > 0 )
550 dup2( fd, STDIN_FILENO );
551 dup2( fd, STDERR_FILENO );
568 static uid_t gathererUID = ( uid_t ) -1, gathererGID = ( uid_t ) -1;
570 if( gathererUID == ( uid_t ) -1 )
572 struct passwd *passwd;
574 passwd = getpwnam(
"nobody" );
577 gathererUID = passwd->pw_uid;
578 gathererGID = passwd->pw_gid;
585 if( gathererUID != ( uid_t ) -1 )
588 ( void ) setuid( gathererUID );
589 ( void ) seteuid( gathererUID );
590 ( void ) setgid( gathererGID );
591 ( void ) setegid( gathererGID );
593 #if( defined( __linux__ ) || ( defined( __FreeBSD__ ) && OSVERSION >= 5 ) || \
594 ( defined( __hpux ) && OSVERSION >= 11 ) )
595 ( void ) setresuid( gathererUID, gathererUID, gathererUID );
596 ( void ) setresgid( gathererGID, gathererGID, gathererGID );
598 ( void ) setreuid( gathererUID, gathererUID );
599 ( void ) setregid( gathererGID, gathererGID );
606 close( pipedes[ STDIN_FILENO ] );
607 close( pipedes[ STDOUT_FILENO ] );
610 execl( entry->path, entry->path, entry->arg, NULL );
626 close( pipedes[ STDOUT_FILENO ] );
627 fcntl( pipedes[ STDIN_FILENO ], F_SETFD, FD_CLOEXEC );
628 stream = fdopen( pipedes[ STDIN_FILENO ],
"r" );
631 int savedErrno = errno;
635 kill( entry->pid, SIGKILL );
636 close( pipedes[ STDOUT_FILENO ] );
637 waitpid( entry->pid, NULL, 0 );
648 INOUT struct rusage *rusage )
651 int iterationCount = 0, status = 0;
654 fclose( entry->pipe );
667 pid = wait4( entry->pid, NULL, 0, rusage );
669 while( pid == -1 && errno == EINTR && \
671 if( pid != entry->pid )
687 #if defined( _CRAY ) || defined( _M_XENIX )
688 #include <sys/times.h>
695 #if !( defined( _CRAY ) || defined( _M_XENIX ) )
697 #if !( defined( __QNX__ ) && OSVERSION <= 4 )
698 struct rusage rusage;
704 timebasestruct_t cpuClockInfo;
706 #if ( defined( sun ) && ( OSVERSION >= 5 ) )
709 #if ( defined( __QNX__ ) && OSVERSION >= 5 )
710 uint64_t clockCycles;
712 #if defined( _POSIX_TIMERS ) && ( _POSIX_TIMERS > 0 ) && 0
713 struct timespec timeSpec;
725 #if !( defined( _CRAY ) || defined( _M_XENIX ) )
726 gettimeofday( &tv, NULL );
733 #if !( defined( __QNX__ ) && OSVERSION <= 4 )
734 getrusage( RUSAGE_SELF, &rusage );
735 addRandomData( randomState, &rusage,
sizeof(
struct rusage ) );
742 addRandomData( randomState, &tms,
sizeof(
struct tms ) );
746 read_real_time( &cpuClockInfo,
sizeof( timebasestruct_t ) );
747 addRandomData( randomState, &cpuClockInfo,
sizeof( timebasestruct_t ) );
749 #if ( defined( sun ) && ( OSVERSION >= 5 ) )
754 hrTime = gethrtime();
755 addRandomData( randomState, &hrTime,
sizeof( hrtime_t ) );
758 if( getSysCaps() & SYSCAP_FLAG_RDTSC )
760 unsigned long tscValue;
766 #if ( defined( __QNX__ ) && OSVERSION >= 5 )
770 clockCycles = ClockCycles();
771 addRandomData( randomState, &clockCycles,
sizeof( uint64_t ) );
781 #if defined( _POSIX_TIMERS ) && ( _POSIX_TIMERS > 0 ) && 0
782 if( clock_gettime( CLOCK_REALTIME, &timeSpec ) == 0 )
783 addRandomData( randomState, &timeSpec,
sizeof(
struct timespec ) );
784 if( clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &timeSpec ) == 0 )
785 addRandomData( randomState, &timeSpec,
sizeof(
struct timespec ) );
786 if( clock_gettime( CLOCK_THREAD_CPUTIME_ID, &timeSpec ) == 0 )
787 addRandomData( randomState, &timeSpec,
sizeof(
struct timespec ) );
791 endRandomData( randomState, 0 );
808 #if ( defined( sun ) && ( OSVERSION >= 5 ) )
813 #define BIG_RANDOM_BUFSIZE ( RANDOM_BUFSIZE * 2 )
816 static
int getKstatData(
void )
822 int noEntries = 0, quality;
825 if( ( kc = kstat_open() ) == NULL )
833 for( ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next )
835 if( kstat_read( kc, ksp, NULL ) == -1 || \
836 ksp->ks_data_size <= 0 )
838 addRandomData( randomState, ksp,
sizeof( kstat_t ) );
845 &msgData, CRYPT_IATTRIBUTE_ENTROPY );
848 addRandomData( randomState, ksp->ks_data, ksp->ks_data_size );
857 quality = ( noEntries > 50 ) ? 35 : 0;
858 endRandomData( randomState, quality );
871 #if ( defined( sun ) && ( OSVERSION >= 5 ) ) || defined( __osf__ ) || \
872 defined( __alpha__ ) || defined( __linux__ )
875 #include <sys/procfs.h>
878 static
int getProcData(
void )
890 struct pracinfo pracInfo;
896 int fd, noEntries = 0, quality,
status;
902 sprintf_s( fileName, 128,
"/proc/%d", getpid() );
903 if( ( fd = open( fileName, O_RDONLY ) ) == -1 )
918 if( ioctl( fd, PIOCSTATUS, &prStatus ) != -1 )
921 printf( __FILE__
": PIOCSTATUS contributed %d bytes.\n",
922 sizeof( prstatus_t ) );
924 addRandomData( randomState, &prStatus,
sizeof( prstatus_t ) );
929 if( ioctl( fd, PIOCPSINFO, &prMisc ) != -1 )
932 printf( __FILE__
": PIOCPSINFO contributed %d bytes.\n",
933 sizeof( prpsinfo_t ) );
935 addRandomData( randomState, &prMisc,
sizeof( prpsinfo_t ) );
940 if( ioctl( fd, PIOCUSAGE, &prUsage ) != -1 )
943 printf( __FILE__
": PIOCUSAGE contributed %d bytes.\n",
944 sizeof( prusage_t ) );
946 addRandomData( randomState, &prUsage,
sizeof( prusage_t ) );
952 if( ioctl( fd, PIOCACINFO, &pracInfo ) != -1 )
955 printf( __FILE__
": PIOCACINFO contributed %d bytes.\n",
956 sizeof(
struct pracinfo ) );
958 addRandomData( randomState, &pracInfo,
sizeof(
struct pracinfo ) );
970 quality = ( noEntries > 2 ) ? 10 : 0;
971 endRandomData( randomState, quality );
983 static
int getProcFSdata(
void )
989 static const PROCSOURCE_INFO procSources[] = {
990 {
"/proc/diskstats", 2 }, {
"/proc/interrupts", 3 },
991 {
"/proc/loadavg", 2 }, {
"/proc/locks", 1 },
992 {
"/proc/meminfo", 3 }, {
"/proc/net/dev", 2 },
993 {
"/proc/net/ipx", 2 }, {
"/proc/modules", 1 },
994 {
"/proc/mounts", 1 }, {
"/proc/net/netstat", 2 },
995 {
"/proc/net/rt_cache", 1 }, {
"/proc/net/rt_cache_stat", 3 },
996 {
"/proc/net/snmp", 2 }, {
"/proc/net/softnet_stat", 2 },
997 {
"/proc/net/stat/arp_cache", 3 }, {
"/proc/net/stat/ndisc_cache", 2 },
998 {
"/proc/net/stat/rt_cache", 3 }, {
"/proc/net/tcp", 3 },
999 {
"/proc/net/udp", 2 }, {
"/proc/net/wireless", 2 },
1000 {
"/proc/slabinfo", 3 }, {
"/proc/stat", 3 },
1001 {
"/proc/sys/fs/inode-state", 1 }, {
"/proc/sys/fs/file-nr", 1 },
1002 {
"/proc/sys/fs/dentry-state", 1 }, {
"/proc/sysvipc/msg", 1 },
1003 {
"/proc/sysvipc/sem", 1 }, {
"/proc/sysvipc/shm", 1 },
1004 {
"/proc/zoneinfo", 3 },
1005 {
"/sys/devices/system/node/node0/numastat", 2 },
1006 { NULL, 0 }, { NULL, 0 }
1009 BYTE buffer[ 1024 + 8 ];
1010 int procIndex, procFD, procValue = 0, quality;
1015 procSources[ procIndex ].source != NULL && \
1025 procFD = open( procSources[ procIndex ].source, O_RDONLY );
1036 count = read( procFD, buffer, 1024 );
1040 printf( __FILE__
": %s contributed %d bytes.\n",
1041 procSources[ procIndex ].source, count );
1046 CRYPT_IATTRIBUTE_ENTROPY );
1048 procValue += procSources[ procIndex ].value;
1060 quality =
min( procValue, 50 );
1063 CRYPT_IATTRIBUTE_ENTROPY_QUALITY );
1069 #define DEVRANDOM_BYTES 128
1072 static
int getDevRandomData(
void )
1076 #if defined( __APPLE__ ) || ( defined( __FreeBSD__ ) && OSVERSION >= 5 )
1077 static const int quality = 50;
1079 static const int quality = 75;
1081 int randFD, noBytes;
1087 if( ( randFD = open(
"/dev/urandom", O_RDONLY ) ) < 0 )
1118 printf( __FILE__
": /dev/random read failed.\n" );
1123 printf( __FILE__
": /dev/random contributed %d bytes.\n", noBytes );
1127 CRYPT_IATTRIBUTE_ENTROPY );
1133 CRYPT_IATTRIBUTE_ENTROPY_QUALITY );
1140 static
int getEGDdata(
void )
1142 static const char *egdSources[] = {
1143 "/var/run/egd-pool",
"/dev/egd-pool",
"/etc/egd-pool", NULL, NULL };
1146 static const int quality = 75;
1153 sockFD = socket( AF_UNIX, SOCK_STREAM, 0 );
1156 for( egdIndex = 0; egdSources[ egdIndex ] != NULL && \
1160 struct sockaddr_un sockAddr;
1162 memset( &sockAddr, 0,
sizeof(
struct sockaddr_un ) );
1163 sockAddr.sun_family = AF_UNIX;
1164 strlcpy_s( sockAddr.sun_path,
sizeof( sockAddr.sun_path ),
1165 egdSources[ egdIndex ] );
1166 if( connect( sockFD, (
struct sockaddr * ) &sockAddr,
1167 sizeof(
struct sockaddr_un ) ) >= 0 )
1171 if( egdSources[ egdIndex ] == NULL )
1186 status = write( sockFD, buffer, 2 );
1189 status = read( sockFD, buffer, 1 );
1190 noBytes = buffer[ 0 ];
1194 status = read( sockFD, buffer, noBytes );
1197 if( ( status < 0 ) || ( status != noBytes ) )
1200 printf( __FILE__
": EGD (%s) read failed.\n", egdSources[ egdIndex ] );
1207 printf( __FILE__
": EGD (%s) contributed %d bytes.\n",
1208 egdSources[ egdIndex ], noBytes );
1212 CRYPT_IATTRIBUTE_ENTROPY );
1218 CRYPT_IATTRIBUTE_ENTROPY_QUALITY );
1230 int bufReadPos = 0, bufWritePos = 0;
1235 if( ( noBytes = fread( bufPtr, 1, bufSize, dataSource->pipe ) ) <= 0 )
1237 struct rusage rusage;
1241 if( my_pclose( dataSource, &rusage ) != 0 )
1246 if( dataSource->usefulness != 0 )
1248 if( dataSource->usefulness < 0 )
1251 total = 1025 / -dataSource->usefulness;
1256 total = dataSource->length / dataSource->usefulness;
1260 printf( __FILE__
": %s %s contributed %d bytes (compressed), "
1261 "usefulness = %d.\n", dataSource->path,
1262 ( dataSource->arg != NULL ) ? dataSource->arg :
"",
1263 dataSource->length, total );
1268 if(
sizeof(
struct rusage ) < bufSize )
1270 memcpy( bufPtr, &rusage,
sizeof(
struct rusage ) );
1271 *bufPos +=
sizeof(
struct rusage );
1278 while( bufReadPos < noBytes )
1284 if( bufReadPos >= bufSize - 1 || ch != bufPtr[ bufReadPos + 1 ] )
1286 bufPtr[ bufWritePos++ ] =
ch;
1295 while( bufReadPos < noBytes && ( ch == bufPtr[ bufReadPos ] ) )
1300 bufPtr[ bufWritePos++ ] = count;
1305 *bufPos += bufWritePos;
1306 dataSource->length += noBytes;
1313 #define SLOWPOLL_TIMEOUT 30
1315 static void childPollingProcess(
const int existingEntropy )
1321 struct rlimit rl = { 0, 0 };
1323 #if defined( __hpux )
1328 int usefulness = 0, fdIndex, bufPos, i, iterationCount,
status;
1367 setrlimit( RLIMIT_CORE, &rl );
1368 for( fdIndex = getdtablesize() - 1; fdIndex > STDOUT_FILENO; fdIndex-- )
1374 for( i = 0; dataSources[ i ].
path != NULL && \
1378 if( dataSources[ i ].
path[ 0 ] ==
'\0' )
1383 if( existingEntropy >= 50 )
1386 puts( __FILE__
": All lightweight sources polled, exiting "
1387 "without polling\nheavyweight ones." );
1399 if( access( dataSources[ i ].
path, X_OK ) )
1402 printf( __FILE__
": %s not present%s.\n", dataSources[ i ].path,
1403 dataSources[ i ].hasAlternative ? \
1404 ", has alternatives" :
"" );
1406 dataSources[ i ].
pipe = NULL;
1409 dataSources[ i ].
pipe = my_popen( &dataSources[ i ] );
1410 if( dataSources[ i ].pipe == NULL )
1412 if( fileno( dataSources[ i ].pipe ) >= FD_SETSIZE )
1419 fclose( dataSources[ i ].pipe );
1420 dataSources[ i ].
pipe = NULL;
1425 dataSources[ i ].
pipeFD = fileno( dataSources[ i ].pipe );
1426 if( dataSources[ i ].pipeFD > maxFD )
1427 maxFD = dataSources[ i ].
pipeFD;
1428 fcntl( dataSources[ i ].pipeFD, F_SETFL, O_NONBLOCK );
1429 FD_SET( dataSources[ i ].pipeFD, &fds );
1430 dataSources[ i ].
length = 0;
1435 while( dataSources[ i ].path != NULL && \
1436 dataSources[ i ].hasAlternative && \
1441 printf( __FILE__
": Skipping %s.\n", dataSources[ i + 1 ].path );
1455 for( moreSources =
TRUE, iterationCount = 0;
1456 moreSources && bufPos < gathererBufSize && \
1467 #if defined( __hpux ) && ( OSVERSION == 9 || OSVERSION == 0 )
1468 if( select( maxFD + 1, (
int * ) &fds, NULL, NULL, &tv ) == -1 )
1470 if( select( maxFD + 1, &fds, NULL, NULL, &tv ) == -1 )
1475 for( i = 0; dataSources[ i ].
path != NULL && \
1479 if( dataSources[ i ].pipe != NULL && \
1480 FD_ISSET( dataSources[ i ].pipeFD, &fds ) )
1481 usefulness += getEntropySourceData( &dataSources[ i ],
1482 gathererBuffer + bufPos,
1483 gathererBufSize - bufPos,
1489 moreSources =
FALSE;
1491 for( i = 0; dataSources[ i ].
path != NULL && \
1495 if( dataSources[ i ].pipe != NULL )
1497 FD_SET( dataSources[ i ].pipeFD, &fds );
1506 if( checkMonoTimerExpired( &timerInfo ) )
1508 for( i = 0; dataSources[ i ].
path != NULL && \
1512 if( dataSources[ i ].pipe != NULL )
1515 printf( __FILE__
": Aborting read of %s due to "
1516 "timeout.\n", dataSources[ i ].
path );
1518 fclose( dataSources[ i ].pipe );
1519 kill( dataSources[ i ].pid, SIGKILL );
1520 dataSources[ i ].
pipe = NULL;
1521 dataSources[ i ].
pid = 0;
1525 moreSources =
FALSE;
1527 puts( __FILE__
": Poll timed out, probably due to blocked data "
1532 ENSURES_EXIT( iterationCount < FAILSAFE_ITERATIONS_MAX );
1534 gathererInfo->
noBytes = bufPos;
1536 printf( __FILE__
": Got %d bytes, usefulness = %d.\n", bufPos,
1574 #define SHARED_BUFSIZE 49152
1578 const int pageSize =
getSysVar( SYSVAR_PAGESIZE );
1579 int extraEntropy = 0;
1585 if( gathererProcess != 0 )
1598 extraEntropy += getDevRandomData();
1599 if( !access(
"/proc/interrupts", R_OK ) )
1600 extraEntropy += getProcFSdata();
1601 extraEntropy += getEGDdata();
1603 extraEntropy += getKstatData();
1606 extraEntropy += getProcData();
1609 printf( __FILE__
": Got %d additional entropy from direct sources.\n",
1611 if( extraEntropy >= 100 )
1613 puts(
" (Skipping full slowpoll since sufficient entropy is "
1617 if( extraEntropy >= 100 )
1629 #if defined( __QNX__ ) && OSVERSION <= 4
1630 fprintf( stderr,
"cryptlib: QNX 4.x doesn't contain the OS mechanisms "
1631 "required to provide\n system entropy sources that "
1632 "can be used for key generation. In\n order to use "
1633 "cryptlib in this environment, you need to apply the\n"
1634 " randomness mechanisms for embedded systems "
1635 "described in the\n cryptlib manual.\n" );
1646 if( sigaction( SIGCHLD, NULL, &gathererOldHandler ) < 0 )
1651 fprintf( stderr,
"cryptlib: sigaction() failed, errno = %d, "
1652 "file " __FILE__
", line %d.\n", errno, __LINE__ );
1657 if( gathererOldHandler.sa_handler != SIG_DFL && \
1658 gathererOldHandler.sa_handler != SIG_IGN )
1660 #ifdef DEBUG_CONFLICTS
1662 fprintf( stderr,
"cryptlib: Conflicting SIGCHLD handling detected "
1663 "in randomness polling code,\nfile " __FILE__
", line %d. "
1664 "See the source code for more\ninformation.\n", __LINE__ );
1670 if( gathererOldHandler.sa_handler != SIG_DFL )
1672 struct sigaction newHandler;
1674 memset( &newHandler, 0,
sizeof( newHandler ) );
1675 newHandler.sa_handler = SIG_DFL;
1676 sigemptyset( &newHandler.sa_mask );
1677 sigaction( SIGCHLD, &newHandler, NULL );
1681 gathererBufSize = (
SHARED_BUFSIZE / pageSize ) * ( pageSize + 1 );
1682 if( ( gathererMemID = shmget( IPC_PRIVATE, gathererBufSize,
1683 IPC_CREAT | 0600 ) ) == -1 || \
1684 ( gathererBuffer = (
BYTE * ) shmat( gathererMemID,
1685 NULL, 0 ) ) == (
BYTE * ) -1 )
1690 if( errno == ENOSYS )
1694 fprintf( stderr,
"cryptlib: SYSV shared memory required for "
1695 "random number gathering isn't\n supported on this "
1696 "type of Cray hardware (ENOSYS),\n file " __FILE__
1697 ", line %d.\n", __LINE__ );
1700 #ifdef DEBUG_CONFLICTS
1701 fprintf( stderr,
"cryptlib: shmget()/shmat() failed, errno = %d, "
1702 "file " __FILE__
", line %d.\n", errno, __LINE__ );
1704 if( gathererMemID != -1 )
1705 shmctl( gathererMemID, IPC_RMID, NULL );
1706 if( gathererOldHandler.sa_handler != SIG_DFL )
1707 sigaction( SIGCHLD, &gathererOldHandler, NULL );
1717 gathererProcess = -1;
1733 if( ( gathererProcess = fork() ) != 0 )
1736 if( gathererProcess != -1 )
1741 #ifdef DEBUG_CONFLICTS
1742 fprintf( stderr,
"cryptlib: fork() failed, errno = %d, file "
1743 __FILE__
", line %d.\n", errno, __LINE__ );
1746 shmctl( gathererMemID, IPC_RMID, NULL );
1747 if( gathererOldHandler.sa_handler != SIG_DFL )
1748 sigaction( SIGCHLD, &gathererOldHandler, NULL );
1749 gathererProcess = 0;
1755 childPollingProcess( extraEntropy );
1761 #if !defined( _POSIX_PRIORITY_SCHEDULING ) || ( _POSIX_PRIORITY_SCHEDULING < 0 )
1763 #define sched_yield()
1764 #elif ( _POSIX_PRIORITY_SCHEDULING == 0 )
1766 static void my_sched_yield(
void )
1769 if( sysconf( _SC_PRIORITY_SCHEDULING ) > 0 )
1772 #define sched_yield my_sched_yield
1784 if( gathererProcess <= 0 )
1803 kill( gathererProcess, SIGTERM );
1810 if( kill( gathererProcess, 0 ) != -1 || errno != ESRCH )
1811 kill( gathererProcess, SIGKILL );
1816 if( waitpid( gathererProcess, &status, 0 ) >= 0 && WIFEXITED( status ) )
1824 if( gathererInfo->
noBytes > 0 && !force )
1830 &msgData, CRYPT_IATTRIBUTE_ENTROPY );
1839 CRYPT_IATTRIBUTE_ENTROPY_QUALITY );
1844 zeroise( gathererBuffer, gathererBufSize );
1850 #if !( defined( __QNX__ ) && OSVERSION <= 4 )
1851 shmdt( gathererBuffer );
1852 shmctl( gathererMemID, IPC_RMID, NULL );
1853 if( gathererOldHandler.sa_handler != SIG_DFL )
1855 struct sigaction oact;
1860 sigaction( SIGCHLD, NULL, &oact );
1861 if( oact.sa_handler != SIG_DFL )
1863 #ifdef DEBUG_CONFLICTS
1866 fprintf( stderr,
"cryptlib: SIGCHLD handler was replaced "
1867 "while slow poll was in progress,\nfile " __FILE__
1868 ", line %d. See the source code for more\n"
1869 "information.\n", __LINE__ );
1876 sigaction( SIGCHLD, &gathererOldHandler, NULL );
1880 gathererProcess = 0;
1902 #if defined( USE_THREADS ) && \
1903 ( defined( _AIX ) || defined( _CRAY ) || defined( __MVS__ ) || \
1904 defined( _MPRAS ) || defined( __APPLE__ ) || \
1905 ( defined( __FreeBSD__ ) && OSVERSION <= 5 ) )
1912 static pthread_mutex_t forkedMutex;
1919 pthread_mutex_lock( &forkedMutex );
1922 pthread_mutex_unlock( &forkedMutex );
1924 return( hasForked );
1927 void setForked(
void )
1930 pthread_mutex_lock( &forkedMutex );
1932 pthread_mutex_unlock( &forkedMutex );
1939 static pid_t originalPID = -1;
1942 if( originalPID == -1 )
1943 originalPID = getpid();
1947 if( getpid() != originalPID )
1949 originalPID = getpid();
1967 pthread_atfork( NULL, setForked, setForked );
1969 pthread_mutex_init( &gathererMutex, NULL );
1970 pthread_mutex_init( &forkedMutex, NULL );
1977 pthread_mutex_destroy( &forkedMutex );
1978 pthread_mutex_destroy( &gathererMutex );