⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unix.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*						  Unix Randomness-Gathering Code					*
*	Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-2005		*
*																			*
****************************************************************************/

/* This module is part of the cryptlib continuously seeded pseudorandom
   number generator.  For usage conditions, see random.c */

/* Define the following to print diagnostic information on where randomness
   is coming from */

/* #define DEBUG_RANDOM	*/

/* Comment out the following to disable printed warnings about possible
   conflicts with signal handlers and other system services */

#define DEBUG_CONFLICTS

/* General includes */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "crypt.h"

/* Unix and Unix-like systems share the same makefile, make sure that the
   user isn't trying to use the Unix randomness code under a non-Unix (but
   Unix-like) system.  This would be pretty unlikely since the makefile
   automatically adjusts itself based on the environment it's running in,
   but we use the following safety check just in case.  We have to perform
   this check before we try any includes because Unix and the Unix-like
   systems don't have the same header files */

#ifdef __BEOS__
  #error For the BeOS build you need to edit $MISCOBJS in the makefile to use 'beos' and not 'unix'
#endif /* BeOS has its own randomness-gathering file */
#ifdef __ECOS__
  #error For the eCOS build you need to edit $MISCOBJS in the makefile to use 'ecos' and not 'unix'
#endif /* eCOS has its own randomness-gathering file */
#ifdef __ITRON__
  #error For the uITRON build you need to edit $MISCOBJS in the makefile to use 'itron' and not 'unix'
#endif /* uITRON has its own randomness-gathering file */
#ifdef __PALMSOURCE__
  #error For the PalmOS build you need to edit $MISCOBJS in the makefile to use 'palmos' and not 'unix'
#endif /* PalmOS has its own randomness-gathering file */
#ifdef __RTEMS__
  #error For the RTEMS build you need to edit $MISCOBJS in the makefile to use 'rtems' and not 'unix'
#endif /* RTEMS has its own randomness-gathering file */
#if defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )
  #error For the Tandem build you need to edit $MISCOBJS in the makefile to use 'tandem' and not 'unix'
#endif /* Tandem OSS has its own randomness-gathering file */
#if defined( __VXWORKS__ )
  #error For the VxWorks build you need to edit $MISCOBJS in the makefile to use 'vxworks' and not 'unix'
#endif /* VxWorks has its own randomness-gathering file */
#if defined( __XMK__ )
  #error For the Xilinx XMK build you need to edit $MISCOBJS in the makefile to use 'xmk' and not 'unix'
#endif /* XMK has its own randomness-gathering file */

/* OS-specific includes */

#if defined( __hpux ) && ( OSVERSION >= 10 )
  #define _XOPEN_SOURCE_EXTENDED
#endif /* Workaround for inconsistent PHUX networking headers */
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#if !( defined( __QNX__ ) || defined( __MVS__ ) )
  #include <sys/errno.h>
  #include <sys/ipc.h>
#endif /* !( QNX || MVS ) */
#include <sys/time.h>	/* SCO and SunOS need this before resource.h */
#ifndef __QNX__
  #if defined( _MPRAS ) && !( defined( _XOPEN_SOURCE ) && \
	  defined( __XOPEN_SOURCE_EXTENDED ) )
	/* On MP-RAS 3.02, the X/Open test macros must be set to include
	   getrusage(). */
	#define _XOPEN_SOURCE 1
	#define _XOPEN_SOURCE_EXTENDED 1
	#define MPRAS_XOPEN_DEFINES
  #endif /* MP-RAS */
  #include <sys/resource.h>
  #if defined( MPRAS_XOPEN_DEFINES )
	#undef _XOPEN_SOURCE
	#undef _XOPEN_SOURCE_EXTENDED
	#undef MPRAS_XOPEN_DEFINES
  #endif /* MP-RAS */
#endif /* QNX */
#if defined( _AIX ) || defined( __QNX__ )
  #include <sys/select.h>
#endif /* Aches || QNX */
#ifdef _AIX
  #include <sys/systemcfg.h>
#endif /* Aches */
#ifdef __CYGWIN__
  #include <signal.h>
  #include <sys/ipc.h>
  #include <sys/sem.h>
  #include <sys/shm.h>
#endif /* CYGWIN */
#if !( defined( __QNX__ ) || defined( __CYGWIN__ ) )
  #include <sys/shm.h>
#endif /* QNX || Cygwin */
#ifndef __MVS__
  #if 0		/* Deprecated - 6/4/03 */
	#include <sys/signal.h>
  #else
	#include <signal.h>
  #endif /* 0 */
#endif /* !MVS */
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>	/* Verschiedene komische Typen */
#include <sys/un.h>
#if defined( __hpux ) && ( OSVERSION == 9 )
  #include <vfork.h>
#endif /* __hpux 9.x, after that it's in unistd.h */
#include <sys/wait.h>
/* #include <kitchensink.h> */

#if defined( sun ) || defined( __ultrix__ ) || defined( __hpux )
  #define HAS_VFORK
#endif /* Unixen that have vfork() */

/* Crays and QNX 4.x don't have a rlimit/rusage so we have to fake the
   functions and structs */

#if defined( _CRAY ) || \
	( defined( __QNX__ ) && OSVERSION <= 4 )
  #define setrlimit( x, y )
  struct rlimit { int dummy1, dummy2; };
  struct rusage { int dummy; };
#endif /* Systems without rlimit/rusage */

/* If we're using threads, we have to protect the entropy gatherer with
   a mutex to prevent multiple threads from trying to initate polls at the
   same time.  Unlike the kernel mutexes, we don't have to worry about
   being called recursively, so there's no need for special-case handling
   for Posix' nasty non-reentrant mutexes */

#ifdef USE_THREADS
  #include <pthread.h>

  #define lockPollingMutex()	pthread_mutex_lock( &gathererMutex )
  #define unlockPollingMutex()	pthread_mutex_unlock( &gathererMutex )
#else
  #define lockPollingMutex()
  #define unlockPollingMutex()
#endif /* USE_THREADS */

/* The size of the intermediate buffer used to accumulate polled data */

#define RANDOM_BUFSIZE	4096

/* The structure containing information on random-data sources.  Each record
   contains the source and a relative estimate of its usefulness (weighting)
   which is used to scale the number of kB of output from the source (total =
   data_bytes / usefulness).  Usually the weighting is in the range 1-3 (or 0
   for especially useless sources), resulting in a usefulness rating of 1...3
   for each kB of source output (or 0 for the useless sources).

   If the source is constantly changing (certain types of network statistics
   have this characteristic) but the amount of output is small, the weighting
   is given as a negative value to indicate that the output should be treated
   as if a minimum of 1K of output had been obtained.  If the source produces
   a lot of output then the scale factor is fractional, resulting in a
   usefulness rating of < 1 for each kB of source output.

   In order to provide enough randomness to satisfy the requirements for a
   slow poll, we need to accumulate at least 20 points of usefulness (a
   typical system should get about 30 points).

   Some potential options are missed out because of special considerations.
   pstat -i and pstat -f can produce amazing amounts of output (the record is
   600K on an Oracle server) that floods the buffer and doesn't yield
   anything useful (apart from perhaps increasing the entropy of the vmstat
   output a bit), so we don't bother with this.  pstat in general produces
   quite a bit of output, but it doesn't change much over time, so it gets
   very low weightings.  netstat -s produces constantly-changing output but
   also produces quite a bit of it, so it only gets a weighting of 2 rather
   than 3.  The same holds for netstat -in, which gets 1 rather than 2.  In
   addition some of the lower-ranked sources are either rather heavyweight
   or of low value, and frequently duplicate information obtained by other
   means like kstat or /procfs.  To avoid waiting for a long time for them
   to produce output, we only use them if earlier, quicker sources aren't
   available.

   Some binaries are stored in different locations on different systems so
   alternative paths are given for them.  The code sorts out which one to run
   by itself, once it finds an exectable somewhere it moves on to the next
   source.  The sources are arranged roughly in their order of usefulness,
   occasionally sources that provide a tiny amount of relatively useless
   data are placed ahead of ones that provide a large amount of possibly
   useful data because another 100 bytes can't hurt, and it means the buffer
   won't be swamped by one or two high-output sources. All the high-output
   sources are clustered towards the end of the list for this reason.  Some
   binaries are checked for in a certain order, for example under Slowaris
   /usr/ucb/ps understands aux as an arg, but the others don't.  Some systems
   have conditional defines enabling alternatives to commands that don't
   understand the usual options but will provide enough output (in the form
   of error messages) to look like they're the real thing, causing
   alternative options to be skipped (we can't check the return either
   because some commands return peculiar, non-zero status even when they're
   working correctly).

   In order to maximise use of the buffer, the code performs a form of run-
   length compression on its input where a repeated sequence of bytes is
   replaced by the occurrence count mod 256.  Some commands output an awful
   lot of whitespace, this measure greatly increases the amount of data we
   can fit in the buffer.

   When we scale the weighting using the SC() macro, some preprocessors may
   give a division by zero warning for the most obvious expression 'weight ?
   1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero trap), so
   we define a value SC_0 that evaluates to zero when fed to '1024 / SC_0' */

#define SC( weight )	( 1024 / weight )	/* Scale factor */
#define SC_0			16384				/* SC( SC_0 ) evalutes to 0 */

static struct RI {
	const char *path;		/* Path to check for existence of source */
	const char *arg;		/* Args for source */
	const int usefulness;	/* Usefulness of source */
	FILE *pipe;				/* Pipe to source as FILE * */
	int pipeFD;				/* Pipe to source as FD */
	pid_t pid;				/* pid of child for waitpid() */
	int length;				/* Quantity of output produced */
	const BOOLEAN hasAlternative;	/* Whether source has alt.location */
	} dataSources[] = {
	/* Sources that are always polled */
	{ "/bin/vmstat", "-s", SC( -3 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bin/vmstat", "-s", SC( -3 ), NULL, 0, 0, 0, FALSE },
	{ "/bin/vmstat", "-c", SC( -3 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bin/vmstat", "-c", SC( -3 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/bin/pfstat", NULL, SC( -2 ), NULL, 0, 0, 0, FALSE },
	{ "/bin/vmstat", "-i", SC( -2 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bin/vmstat", "-i", SC( -2 ), NULL, 0, 0, 0, FALSE },
#if defined( _AIX ) || defined( __SCO_VERSION__ )
	{ "/usr/bin/vmstat", "-f", SC( -1 ), NULL, 0, 0, 0, FALSE },
#endif /* OS-specific extensions to vmstat */
	{ "/usr/ucb/netstat", "-s", SC( 2 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bin/netstat", "-s", SC( 2 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/sbin/netstat", "-s", SC( 2 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/netstat", "-s", SC( 2 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/etc/netstat", "-s", SC( 2 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/bin/nfsstat", NULL, SC( 2 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/ucb/netstat", "-m", SC( -1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bin/netstat", "-m", SC( -1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/sbin/netstat", "-m", SC( -1 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/netstat", "-m", SC( -1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/etc/netstat", "-m", SC( -1 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/ucb/netstat", "-in", SC( -1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bin/netstat", "-in", SC( -1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/sbin/netstat", "-in", SC( -1 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/netstat", "-in", SC( -1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/etc/netstat", "-in", SC( -1 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/sbin/ntptrace", "-r2 -t1 -nv", SC( -1 ), NULL, 0, 0, 0, FALSE },
#ifndef __SCO_VERSION__
	{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* UDP in */
	{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* UDP out */
	{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* IP ? */
	{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.0", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* TCP ? */
	{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.11.0", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* TCP ? */
	{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* TCP ? */
#else
	{ "/usr/sbin/snmpstat", "-an localhost public", SC( SC_0 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/sbin/snmpstat", "-in localhost public", SC( SC_0 ), NULL, 0, 0, 0, FALSE }, /* Subset of netstat info */
	{ "/usr/sbin/snmpstat", "-Sn localhost public", SC( SC_0 ), NULL, 0, 0, 0, FALSE },
#endif /* SCO/UnixWare vs.everything else */
	{ "/usr/bin/mpstat", NULL, SC( 1 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/bin/w", NULL, SC( 1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bsd/w", NULL, SC( 1 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/bin/df", NULL, SC( 1 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/df", NULL, SC( 1 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/sbin/portstat", NULL, SC( 1 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/bin/iostat", NULL, SC( SC_0 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/bin/uptime", NULL, SC( SC_0 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bsd/uptime", NULL, SC( SC_0 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/bin/vmstat", "-f", SC( SC_0 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/vmstat", "-f", SC( SC_0 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/ucb/netstat", "-n", SC( 0.5 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bin/netstat", "-n", SC( 0.5 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/sbin/netstat", "-n", SC( 0.5 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/netstat", "-n", SC( 0.5 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/etc/netstat", "-n", SC( 0.5 ), NULL, 0, 0, 0, FALSE },

	/* End-of-lightweight-sources section marker */
	{ "", NULL, SC( SC_0 ), NULL, 0, 0, 0, FALSE },

	/* Potentially heavyweight or low-value sources that are only polled if
	   alternative sources aren't available */
#if defined( __sgi ) || defined( __hpux )
	{ "/bin/ps", "-el", SC( 0.3 ), NULL, 0, 0, 0, TRUE },
#endif /* SGI || PHUX */
	{ "/usr/ucb/ps", "aux", SC( 0.3 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bin/ps", "aux", SC( 0.3 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/ps", "aux", SC( 0.3 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/bin/ipcs", "-a", SC( 0.5 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/ipcs", "-a", SC( 0.5 ), NULL, 0, 0, 0, FALSE },
							/* Unreliable source, depends on system usage */
	{ "/etc/pstat", "-p", SC( 0.5 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/pstat", "-p", SC( 0.5 ), NULL, 0, 0, 0, FALSE },
	{ "/etc/pstat", "-S", SC( 0.2 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/pstat", "-S", SC( 0.2 ), NULL, 0, 0, 0, FALSE },
	{ "/etc/pstat", "-v", SC( 0.2 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/pstat", "-v", SC( 0.2 ), NULL, 0, 0, 0, FALSE },
	{ "/etc/pstat", "-x", SC( 0.2 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/pstat", "-x", SC( 0.2 ), NULL, 0, 0, 0, FALSE },
	{ "/etc/pstat", "-t", SC( 0.1 ), NULL, 0, 0, 0, TRUE },
	{ "/bin/pstat", "-t", SC( 0.1 ), NULL, 0, 0, 0, FALSE },
							/* pstat is your friend */
#ifndef __SCO_VERSION__
	{ "/usr/sbin/sar", "-AR", SC( 0.05 ), NULL, 0, 0, 0, FALSE }, /* Only updated hourly */
#endif /* SCO/UnixWare */
	{ "/usr/bin/last", "-n 50", SC( 0.3 ), NULL, 0, 0, 0, TRUE },
#ifdef __sgi
	{ "/usr/bsd/last", "-50", SC( 0.3 ), NULL, 0, 0, 0, FALSE },
#endif /* SGI */
#ifdef __hpux
	{ "/etc/last", "-50", SC( 0.3 ), NULL, 0, 0, 0, FALSE },
#endif /* PHUX */
	{ "/usr/bsd/last", "-n 50", SC( 0.3 ), NULL, 0, 0, 0, FALSE },
#ifdef sun
	{ "/usr/bin/showrev", "-a", SC( 0.1 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/sbin/swap", "-l", SC( SC_0 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/sbin/prtconf", "-v", SC( SC_0 ), NULL, 0, 0, 0, FALSE },
#endif /* SunOS/Slowaris */
	{ "/usr/sbin/psrinfo", NULL, SC( SC_0 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/local/bin/lsof", "-lnwP", SC( 0.3 ), NULL, 0, 0, 0, FALSE },
							/* Output is very system and version-dependent */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -