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

📄 unix.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
	{ "/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/bin/lsof", "-blnwP", SC( 0.3 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/local/bin/lsof", "-blnwP", SC( 0.3 ), NULL, 0, 0, 0, FALSE },
							/* Output is very system and version-dependent
							   and can also be extremely voluminous */
	{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.1.0", SC( 0.1 ), NULL, 0, 0, 0, FALSE }, /* ICMP ? */
	{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.3.0", SC( 0.1 ), NULL, 0, 0, 0, FALSE }, /* ICMP ? */
	{ "/etc/arp", "-a", SC( 0.1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/etc/arp", "-a", SC( 0.1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bin/arp", "-a", SC( 0.1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/sbin/arp", "-a", SC( 0.1 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/sbin/ripquery", "-nw 1 127.0.0.1", SC( 0.1 ), NULL, 0, 0, 0, FALSE },
	{ "/bin/lpstat", "-t", SC( 0.1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/bin/lpstat", "-t", SC( 0.1 ), NULL, 0, 0, 0, TRUE },
	{ "/usr/ucb/lpstat", "-t", SC( 0.1 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/bin/tcpdump", "-c 5 -efvvx", SC( 1 ), NULL, 0, 0, 0, FALSE },
							/* This is very environment-dependant.  If
							   network traffic is low, it'll probably time
							   out before delivering 5 packets, which is OK
							   because it'll probably be fixed stuff like ARP
							   anyway */
	{ "/usr/sbin/advfsstat", "-b usr_domain", SC( SC_0 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/sbin/advfsstat", "-l 2 usr_domain", SC( 0.5 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/sbin/advfsstat", "-p usr_domain", SC( SC_0 ), NULL, 0, 0, 0, FALSE },
							/* This is a complex and screwball program.  Some
							   systems have things like rX_dmn, x = integer,
							   for RAID systems, but the statistics are
							   pretty dodgy */
#if 0
	/* The following aren't enabled since they're somewhat slow and not very
	   unpredictable, however they give an indication of the sort of sources
	   you can use (for example the finger might be more useful on a
	   firewalled internal network) */
	{ "/usr/bin/finger", "@ml.media.mit.edu", SC( 0.9 ), NULL, 0, 0, 0, FALSE },
	{ "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html", SC( 0.9 ), NULL, 0, 0, 0, FALSE },
	{ "/bin/cat", "/usr/spool/mqueue/syslog", SC( 0.9 ), NULL, 0, 0, 0, FALSE },
#endif /* 0 */

	/* End-of-sources marker */
	{ NULL, NULL, 0, NULL, 0, 0, 0, FALSE }, 
		{ NULL, NULL, 0, NULL, 0, 0, 0, FALSE }
	};

/* Variables to manage the child process that fills the buffer */

static pid_t gathererProcess = 0;/* The child process that fills the buffer */
static BYTE *gathererBuffer;	/* Shared buffer for gathering random noise */
static int gathererMemID;		/* ID for shared memory */
static int gathererBufSize;		/* Size of the shared memory buffer */
static struct sigaction gathererOldHandler;	/* Previous signal handler */
#ifdef USE_THREADS
  static pthread_mutex_t gathererMutex;	/* Mutex to protect the polling */
#endif /* USE_THREADS */

/* The struct at the start of the shared memory buffer used to communicate
   information from the child to the parent */

typedef struct {
	int usefulness;				/* Usefulness of data in buffer */
	int noBytes;				/* No.of bytes in buffer */
	} GATHERER_INFO;

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

#if defined( __hpux ) && ( OSVERSION == 9 )

/* PHUX 9.x doesn't support getrusage in libc (wonderful...) */

#include <syscall.h>

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
static int getrusage( int who, OUT struct rusage *rusage )
	{
	return( syscall( SYS_getrusage, who, rusage ) );
	}
#endif /* __hpux */

#if defined( __MVS__ ) || defined( __hpux )

/* MVS USS and PHUX don't have wait4() so we emulate it with waitpid() and
   getrusage() */

CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \
pid_t wait4( pid_t pid, OUT int *status, int options, 
			 OUT struct rusage *rusage )
	{
	const pid_t waitPid = waitpid( pid, status, options );

	getrusage( RUSAGE_CHILDREN, rusage );
	return( waitPid );
	}
#endif /* MVS || PHUX */

/* Cray Unicos and QNX 4.x have neither wait4() nor getrusage, so we fake
   it */

#if defined( _CRAY ) || ( defined( __QNX__ ) && OSVERSION <= 4 )

CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \
pid_t wait4( pid_t pid, OUT int *status, int options, 
			 OUT struct rusage *rusage )
	{
	return( waitpid( pid, status, options ) );
	}
#endif /* Cray Unicos || QNX 4.x */

/* Under SunOS 4.x popen() doesn't record the pid of the child process.  When
   pclose() is called, instead of calling waitpid() for the correct child, it
   calls wait() repeatedly until the right child is reaped.  The problem whit
   this behaviour is that this reaps any other children that happen to have
   died at that moment, and when their pclose() comes along, the process hangs
   forever.

   This behaviour may be related to older SVR3-compatible SIGCLD handling in
   which, under the SIG_IGN disposition, the status of the child was discarded
   (i.e. no zombies were generated) so that when the parent called wait() it
   would block until all children terminated, whereupon wait() would return -1
   with errno set to ECHILD.

   The fix for this problem is to use a wrapper for popen()/pclose() that
   saves the pid in the dataSources structure (code adapted from GNU-libc's
   popen() call).  Doing our own popen() has other advantages as well, for
   example we use the more secure execl() to run the child instead of the
   dangerous system().

   Aut viam inveniam aut faciam */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static FILE *my_popen( INOUT DATA_SOURCE_INFO *entry )
	{
	int pipedes[ 2 + 8 ];
	FILE *stream;

	/* Sanity check for stdin and stdout */
	REQUIRES_N( STDIN_FILENO <= 1 && STDOUT_FILENO <= 1 );

	/* Create the pipe.  Note that under QNX the pipe resource manager
	   'pipe' must be running in order to use pipes */
	if( pipe( pipedes ) < 0 )
		return( NULL );

	/* Fork off the child ("vfork() is like an OS orgasm.  All OSes want to
	   do it, but most just end up faking it" - Chris Wedgwood).  If your OS
	   supports it, you should try and use vfork() here because it's rather
	   more efficient and has guaranteed copy-on-write semantics that prevent
	   cryptlib object data from being copied to the child.  Many modern
	   Unixen use COW for forks anyway (e.g. Linux, for which vfork() is just
	   an alias for fork()), so we get most of the benefits of vfork() with a
	   plain fork(), however there's another problem with fork that isn't
	   fixed by COW.  Any large program, when forked, requires (at least
	   temporarily) a lot of address space.  That is, when the process is
	   forked the system needs to allocate many virtual pages (backing store)
	   even if those pages are never used.  If the system doesn't have enough
	   swap space available to support this, the fork() will fail when the
	   system tries to reserver backing store for pages that are never
	   touched.  Even in non-large processes this can cause problems when (as
	   with the randomness-gatherer) many children are forked at once.

	   In the absence of threads the use of pcreate() (which only requires
	   backing store for the new processes' stack, not the entire process)
	   would do the trick, however pcreate() isn't compatible with threads,
	   which makes it of little use for the default thread-enabled cryptlib
	   build

	   Although OSF/1 has vfork(), it has nasty interactions with threading
	   and can cause other problems with handling of children, so we don't
	   use it */
#ifdef HAS_VFORK
	entry->pid = vfork();
#else
	entry->pid = fork();
#endif /* Unixen that have vfork() */
	if( entry->pid == ( pid_t ) -1 )
		{
		/* The fork failed */
		close( pipedes[ 0 ] );
		close( pipedes[ 1 ] );
		return( NULL );
		}

	if( entry->pid == ( pid_t ) 0 )
		{
		int fd;

		/* We are the child, connect the read side of the pipe to stdout and
		   unplug stdin and stderr */
		if( dup2( pipedes[ STDOUT_FILENO ], STDOUT_FILENO ) < 0 )
			exit( 127 );
		if( ( fd = open( "/dev/null", O_RDWR ) ) > 0 )
			{
			dup2( fd, STDIN_FILENO );
			dup2( fd, STDERR_FILENO );
			close( fd );
			}

		/* If we're root, give up our permissions to make sure that we don't
		   inadvertently read anything sensitive.  If the getpwnam() fails
		   (this can happen if we're chrooted with no "nobody" entry in the
		   local passwd file) we default to -1, which is usually nobody.  
		   The newer setreXid() and setresXid() calls use a parameter value 
		   of -1 to indicate "don't change this value" so this isn't 
		   possible any longer, but then there's not really much else that 
		   we can do at this point.
		   
		   We don't check whether the change succeeds since it's not a major 
		   security problem but just a precaution */
		if( geteuid() == 0 )
			{
			static uid_t gathererUID = ( uid_t ) -1, gathererGID = ( uid_t ) -1;

			if( gathererUID == ( uid_t ) -1 )
				{
				struct passwd *passwd;

				passwd = getpwnam( "nobody" );
				if( passwd != NULL )
					{
					gathererUID = passwd->pw_uid;
					gathererGID = passwd->pw_gid;
					}
				else
					{
					assert( DEBUG_WARN );
					}
				}
			if( gathererUID != ( uid_t ) -1 )
				{
#if 0			/* Not available on some OSes */
				setuid( gathererUID );
				seteuid( gathererUID );
				setgid( gathererGID );
				setegid( gathererGID );
#else
  #if( defined( __linux__ ) || ( defined( __FreeBSD__ ) && OSVERSION >= 5 ) || \
	   ( defined( __hpux ) && OSVERSION >= 11 ) )
				setresuid( gathererUID, gathererUID, gathererUID );
				setresgid( gathererGID, gathererGID, gathererGID );
  #else
				setreuid( gathererUID, gathererUID );
				setregid( gathererGID, gathererGID );
  #endif /* OSses with setresXid() */
#endif /* 0 */
				}
			}

		/* Close the pipe descriptors */
		close( pipedes[ STDIN_FILENO ] );
		close( pipedes[ STDOUT_FILENO ] );

		/* Try and exec the program */
		execl( entry->path, entry->path, entry->arg, NULL );

		/* Die if the exec failed.  Since vfork() doesn't duplicate the stdio
		   buffers (or anything else for that matter), we have to use _exit()
		   rather than exit() to ensure that the shutdown actions don't upset
		   the parent's state */
#ifdef HAS_VFORK
		_exit( 127 );
#else
		exit( 127 );
#endif /* Unixen that have vfork() */
		}

	/* We are the parent.  Close the irrelevant side of the pipe and open the
	   relevant side as a new stream.  Mark our side of the pipe to close on
	   exec, so new children won't see it */
	close( pipedes[ STDOUT_FILENO ] );
	fcntl( pipedes[ STDIN_FILENO ], F_SETFD, FD_CLOEXEC );
	stream = fdopen( pipedes[ STDIN_FILENO ], "r" );
	if( stream == NULL )
		{
		int savedErrno = errno;

		/* The stream couldn't be opened or the child structure couldn't be
		   allocated.  Kill the child and close the other side of the pipe */
		kill( entry->pid, SIGKILL );
		close( pipedes[ STDOUT_FILENO ] );
		waitpid( entry->pid, NULL, 0 );
		entry->pid = 0;
		errno = savedErrno;
		return( NULL );
		}

	return( stream );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int my_pclose( INOUT DATA_SOURCE_INFO *entry, 
					  INOUT struct rusage *rusage )
	{
	pid_t pid;
	int iterationCount = 0, status = 0;

	/* Close the pipe */
	fclose( entry->pipe );
	entry->pipe = NULL;

	/* Wait for the child to terminate, ignoring the return value from the
	   process because some programs return funny values that would result

⌨️ 快捷键说明

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