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

📄 cryptlib.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
		{
		if( initLevel >= 2 )
			{
			endTrustInfo();
			destroyObjects();
			}
		if( initLevel >= 1 )
			endInternalFunctions();
		endInitialisation( FALSE );
		return( status );
		}

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

C_RET cryptInit( void )
	{
	return( initCrypt() );
	}

C_RET cryptEnd( void )
	{
	int status;

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

	/* Signal the networking layer that we're about to shut down.  This is
	   necessary before we can close down any objects which are blocked 
	   waiting on network I/O */
	signalShutdownNetworking();

	/* Clean up all resources.  The order in which the cleanup is performed
	   is based on dependencies of one layer of services upon lower layers:

		trustInfo -> cert/context objects
		random -> device objects
		device objects -> drivers

	   and everything relies on the kernel itself which is shut down by the
	   endInternalFunctions() call */
	endTrustInfo();
	status = destroyObjects();
	unbindDrivers();
	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.  Note that in this form the library is no
	   longer thread-safe */
#if defined( __WIN32__ ) && defined( STATIC_LIB )
	/* Delete the library initialisation lock */
	deleteGlobalResourceLock( initialisation );
#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 cryptsvr.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 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 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 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 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 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 = cryptInitEx();
	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 which 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 )

⌨️ 快捷键说明

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