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

📄 cryptlib.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* If anything failed, shut down the internal functions and services
	   before we exit */
	if( !cryptStatusOK( status ) )
		{
		if( initLevel >= 3 )
			{
			/* Shut down any external interfaces after making sure that the
			   initalisation ran to completion */
			waitSemaphore( SEMAPHORE_DRIVERBIND );
			dispatchManagementAction( preShutdownFunctions, 
									  MANAGEMENT_ACTION_PRE_SHUTDOWN );
			dispatchManagementAction( shutdownFunctions, 
									  MANAGEMENT_ACTION_SHUTDOWN );
			}
		if( initLevel >= 2 )
			destroyObjects();
		if( initLevel >= 1 )
			endInternalFunctions();
		endInitialisation( FALSE );
		return( status );
		}

	/* Unlock the initialisation state */
	endInitialisation( TRUE );
	return( CRYPT_OK );
	}

int endCryptlib( void )
	{
	int status;

	/* If we've already been shut down, don't do anything */
	if( !beginInitialisation( FALSE ) )
		return( CRYPT_OK );

	/* Reverse the process carried out in the multi-phase bootstrap */
	waitSemaphore( SEMAPHORE_DRIVERBIND );
	dispatchManagementAction( preShutdownFunctions, 
							  MANAGEMENT_ACTION_PRE_SHUTDOWN );
	status = destroyObjects();
	dispatchManagementAction( shutdownFunctions, 
							  MANAGEMENT_ACTION_SHUTDOWN );
	endInternalFunctions();

	/* Unlock the initialisation state */
	endInitialisation( FALSE );

	/* If the Win32 version is being compiled as a static .lib, we need to
	   perform the cleanup here */
#if defined( __WIN32__ ) && defined( STATIC_LIB )
	/* Delete the initialisation lock in the kernel */
	postShutdown();
#endif /* __WIN32__ && STATIC_LIB */

	return( status );
	}

/****************************************************************************
*																			*
*						Client/Server Interface Routines					*
*																			*
****************************************************************************/

/* If we're running in our own address space (either in another VM or on
   separate hardware), we need to have some sort of client/server mechanism
   to communicate with processes running in the applications address space.
   The following section implements the server-side interface for various
   environments */

#ifdef USE_CLIENT_SERVER

/* Prototypes for functions in cryptapi.c.  Currently this is all done 
   locally (cryptsvr_client calls cryptsvr_server directly), someone else 
   can fight with these daemons... */

#if defined( __UNIX__ )

#include <sys/un.h>

#define DAEMON_NAME			"cryptd"
#define DAEMON_SOCKET_NAME	"/dev/crypt"
#define DAEMON_NO_THREADS	10

/* Per-thread main function */

static MUTEX acceptMutex;			/* Mutex for accept() */
static int sockfd;					/* Socket for accept() */
static BOOLEAN doShutdown = FALSE;	/* Signal for threads to shut down */
static int activeThreads = 0;		/* No.of currently active threads */

THREADFUNC_DEFINE( threadedMain, dummy )
	{
	while( TRUE )
		{
		int connfd;

		/* Some implementations don't handle threads blocking in accept() too
		   well, and in any case managing the thundering herd in user space
		   is a lot more efficient than doing it in the kernel, so we
		   explicitly manage locking ourselves with a mutex.

		   If we've been told to shut down, we don't try the accept() but
		   just drop through to the shutdown check afterwards.  This
		   decrements the activeThreads counter, the last thread out turns
		   off the lights.  The way the shutdown works is that the accept()
		   fails (due to the socket being closed) and the thread falls out of
		   the accept lock/unlock, at which point either it passes into the
		   shutdown lock/unlock and exits or (rarely) it gets preempted and
		   the next thread passes through the accept lock/unlock.  In the
		   most extreme case the accept mutex pileup moves down to the exit
		   mutex, but in either case all threads eventually terminate.  The
		   only time the daemon might shut down improperly is if a thread is
		   in the middle of a long-running keygen and keeps everything else
		   active.  There isn't really any clean way to handle this, and in
		   any case if the system is about to shut down there probably won't
		   be anything left running to pick up the pieces */
		MUTEX_LOCK( &acceptMutex );
		if( !doShutdown )
			connfd = accept( sockfd, NULL, 0 );
		MUTEX_UNLOCK( &acceptMutex );
		if( doShutdown )
			{
			MUTEX_LOCK( &acceptMutex );
			activeThreads--;
			if( !activeThreads )
				cryptEnd();
			MUTEX_UNLOCK( &acceptMutex );
			THREAD_EXIT();
			}

		if( connfd == -1 )
			{
			/* If we got zapped by a signal, continue where we left off */
			if( errno == EINTR )
				continue;

			/* If we got caught by a RST for an established connection before
			   accept() got called, the connection will be aborted, in which
			   case we just continue */
			if( errno == ECONNABORTED )
				continue;

			/* ... */
			}

		/* Get the request type and make sure that it's valid */
		/* ... */

		/* Dispatch the request */
		status = dispatchRequest( request.UserDefined, request.RequestID );

		/* Clean up */
		close( connfd );
		}
	}

/* Set up the daemon and fire up the thread pool */

void sigTermFunction( int dummy )
	{
	/* Signal all active threads to die and close the socket, which forces
	   accept() to fail, guaranteeing that a thread doesn't remain blocked
	   in the call */
	doShutdown = TRUE;
	close( socket );
	}

int main( int argc, char *argv[] )
	{
	THREAD threadPool[ DAEMON_NO_THREADS ];
	const struct rlimit rl = { 0, 0 };
	struct sockaddr_un sockAddr;
	struct timeval tv;
	char *socketName, *errorString = NULL;
	int fd, status;

	/* Start logging our status */
	openlog( DAEMON_NAME, 0, LOG_DAEMON );
	syslog( LOG_INFO, DAEMON_NAME "started" );

	/* Check that everything is OK */
	if( argc > 2 )
		errorString = "usage: " DAEMON_NAME " <server socket pathname>";
	else
		{
		socketName = ( argc == 2 ) ? argv[ 1 ] : DAEMON_SOCKET_NAME;
		if( strlen( socketName > 100 )
			errorString = DAEMON_NAME ": Socket pathname too long";
		else
			if( access( socketName, F_OK )
				errorString = DAEMON_NAME ": Socket already exists";
		}
	if( errorString != NULL )
		{
		syslog( LOG_ERR, errorString );
		closelog();
		exit( EXIT_FAILURE );
		}

	/* Turn ourselves into a daemon by forking a new process and killing its
	   parent.  After this sequence of operations, we're a daemon owned by
	   init */
	if( ( status = fork() ) < 0 )
		{
		syslog( LOG_ERR, "%m" );
		closelog();
		exit( EXIT_FAILURE );
		}
	if( status )
		exit( EXIT_SUCCESS ); /* Exit if we're the parent */

#if 1
	/* Create a new session with ourselves as the session leader and no
	   controlling TTY, ignore SIGHUP, and fork again.  This is necessary
	   because when a session leader without a controlling terminal opens a
	   terminal device, it gets assigned as its controlling TTY.  By forking
	   a second time, we make sure that the child is no longer a session 
	   leader.  The reason we need to ignore SIGHUP is because when the 
	   first-level child (the session leader) exits, the second-level child 
	   (just another process in the session) will be SIGHUP'd */
	setsid();
	signal( SIGHUP, SIG_IGN );
	if( ( status = fork() ) != 0 )
		exit( EXIT_SUCCESS );
#else
	/* Detach ourselves from the controlling TTY to avoid interruptions and
	   move into our own process group to avoid mass murders */
	fd = open( "/dev/tty", O_RDWR );
	ioctl( fd, TIOCNOTTY, 0 );
	close( fd );
	setpgrp( 0, getpid() );
#endif /* 1 */

	/* Close all inherited file descriptors */
	for( fd = getdtablesize() - 1; fd >= 0; fd-- )
		close( fd );

	/* Move to a (safe) standard directory, set our umask to make sure that 
	   our files are kept private (although the cryptlib streams module does 
	   this anyway), and point the stdin, stdout, and stderr streams to the 
	   null device in case library routines try and do any I/O */
	chdir( "/tmp" );
	umask( 0177 );      /* Owner RW access only */
	fd = open( "/dev/null", O_RDWR );   /* stdin = 0 */
	dup( fd );                          /* stdout = 1 */
	dup( fd );                          /* stderr = 2 */

	/* Make sure that we can never dump core (we really, *really* don't want 
	   to do this) */
	setrlimit( RLIMIT_CORE, &rl );

	/* Go catatonic */
	signal( SIG_IGN, SIGHUP );

	/* Create a domain socket and wait for connections */
	memset( sockAddr, 0, sizeof( struct sockaddr_un ) );
	strcpy( sockAddr.sun_path, socketName );
	status = sockfd = socket( AF_LOCAL, SOCK_STREAM, 0 );
	if( status != -1 )
		status = bind( sockfd, ( SA * ) &sockAddr, SUN_LEN( &sockAddr ) );
	if( status != -1 )
		status = listen( sockfd, 5 );
	if( status == -1 )
		{
		syslog( LOG_ERR, "%m" );
		closelog();
		exit( EXIT_FAILURE );
		}

	/* Set the socket timeout to 5 seconds to make sure that we don't block
	   forever if a client hangs */
	tv.tv_sec = 5;
	tv.tv_usec = 0;
	setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv,
				sizeof( struct timeval ) );
	setsockopt( sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv,
				sizeof( struct timeval ) );

	/* Initialise the crypto code */
	status = cryptInit();
	if( cryptStatusError( status ) )
		{
		syslog( LOG_ERR, "Crypto initialisation failed" );
		closelog();
		exit( EXIT_FAILURE );
		}

	/* Make sure that if we get killed by init, we shut down cleanly */
	signal( sigTermFunction, SIGTERM );

	/* Start up the thread pool.  We hold the accept() mutex while we're
	   doing this to ensure that it's an all-or-nothing start, in other
	   words that there are no threads accepting commands while there's
	   still a chance that the init could be aborted */
	MUTEX_INIT( &acceptMutex );
	MUTEX_LOCK( &acceptMutex );
	for( i = 0; i < DAEMON_NO_THREADS; i++ )
		{
		status = THREAD_CREATE( &threadMain, NULL );
		if( THREAD_STATUS( status ) != CRYPT_OK )
			break;
		activeThreads++;
		}
	if( cryptStatusError( status ) )
		{
		/* Signal any threads that got started to terminate immediately */
		doShutdown = TRUE;
		close( socket );
		MUTEX_UNLOCK( &acceptMutex );

		syslog( LOG_ERR, "Thread pool initialisation failed" );
		closelog();
		exit( EXIT_FAILURE );
		}
	MUTEX_UNLOCK( &acceptMutex );

	/* We're ready to talk, make the socket path accessible to others (the
	   umask will have made it inaccessible, which is fine since we don't
	   want anyone poking messages at us while we're initialising) */
	chmod( socketName, 0666 );

	/* Everything is done by the threads, so we just twiddle our thumbs */
	while( TRUE )
		pause();

	/* Clean up */
	MUTEX_DESTROY( &acceptMutex );
	exit( EXIT_SUCCESS );
	}

#elif defined( __WINDOWS__ )

#define SERVICE_NAME			"cryptd"
#define SERVICE_DISPLAY_NAME	"cryptlib Server"
#define SERVICE_PATH			"%SystemRoot%\\System32\\cryptd.exe"

SERVICE_STATUS serviceStatus;
SERVICE_STATUS_HANDLE hServiceStatus;

/* Service control handler */

void WINAPI Handler( DWORD fdwControl )
	{
	switch( fdwControl )
		{
		case SERVICE_CONTROL_STOP:
			serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
			break;

		case SERVICE_CONTROL_SHUTDOWN:
			break;

		case SERVICE_CONTROL_INTERROGATE:
			; /* Fall through */
		}

⌨️ 快捷键说明

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