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

📄 ssl.c

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 C
📖 第 1 页 / 共 4 页
字号:
				iTmp = SSL_VERIFY_NONE; break;

			case 1:
				iTmp = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; break;

			case 2:
				iTmp = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; break;

			default:
				PILog_addMessage(
					PIObject_getDB( pObject ),
					PIObject_getConfigurationDB( pObject ),
					PILOG_ERROR, "%sSSL: Bad SSL verification code %d. \
Accepted verification codes are 0, 1, 2 or 3.", pWhere, iTmp );
				return 0;
			};
		pConf->iVerify = iTmp;
		}
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_VERIFYDEPTH ) )
		{ pConf->iVerifyDepth = atoi( pVal ); }
	else if ( !PIUtil_stricmp( KEY_CONF_TYPE, pVar ) )
		{ pConf->iServer = PIUtil_stricmp( pVal, VALUE_PASSIVE ) ? 0 : 1; }
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_PRIVATEKEYFILE ) )
		{ pConf->pKeyF = PIUtil_strdup( pVal );	}
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_CACERTIFICATEPATH ) )
		{ pConf->pCACertP = PIUtil_strdup( pVal ); }
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_CACERTIFICATEFILE ) )
		{ pConf->pCACertF = PIUtil_strdup( pVal ); }
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_CERTIFICATEFILE ) )
		{ pConf->pCertF = PIUtil_strdup( pVal ); }
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_DEBUGFILE ) )
		{ pConf->pDebugFile = PIUtil_strdup( pVal ); }
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_CIPHERLIST ) )
		{ pConf->pCipherList = PIUtil_strdup( pVal ); }
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_RANDOMSEEDFILE ) )
		{ pConf->pRandomSeedFile = PIUtil_strdup( pVal ); }
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_RANDOMSEEDSIZE ) )
		{ pConf->iRandomSize = atoi( pVal ); }
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_PASSPHRASE ) )
		{ pConf->pPassPhrase = PIUtil_strdup( pVal ); }
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_FLAG ) )
		{
		if ( !PIUtil_stricmp( pVal, VALUE_BUGS ) )
			{ pConf->iBugs = 1; }
		else if ( !PIUtil_stricmp( pVal, VALUE_HACK ) )
			{ pConf->iHack = 1; }
		else if ( !PIUtil_stricmp( pVal, VALUE_DISABLE ) )
			{ pConf->iDisable = 1; }
		else
			{
			PILog_addMessage(
				PIObject_getDB( pObject ),
				PIObject_getConfigurationDB( pObject ),
				PILOG_ERROR, "%sSSL: Unknown flag '%s'.", pWhere, pVal );
			return 0;
			};
		}
	else if ( !PIUtil_stricmp( pVar, KEY_CONF_IOOBJECT ) )
		{
		/* 
		Load the prototype for the transport IO object. The function
		PIObject_loadFromLine() will log the appropriate error messages
		if it fails
		*/
		pSSL->pIOObject = PIObject_loadFromLine( 
			PIObject_getDB( pObject ),
			PIObject_getConfigurationDB( pObject ),
			pVal );
		if ( !pSSL->pIOObject )
			{ return 0; };
		}
	else
		{
		/* ---
		Configuration error
		--- */
		PILog_addMessage(
			PIObject_getDB( pObject ),
			PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "%sSSL: Unknown directive '%s'.", pWhere, pVar );
		return 0;
		};
	return 1;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
	Return non-zero on success, zero  on failure.
\*____________________________________________________________________________*/
int SSL_init( PIObject *pObject, int iArgc, const char *ppArgv[] )
{
	PISSL *pPrototype;
	SSLConf *pConf;
	int iRet;
	SSL_METHOD *pSSLMethod = 0;
	SSL *pSSL;
	X509 *pX509;
	PIFInfo *pFInfo;
	PIPLATFORM_FD tFD;
	void *pBuf;
    EVP_PKEY *pKey;
	FILE *fp;
	static const char rnd_seed[] = "string to make the random number generator think it has entropy";

	pPrototype = PIObject_getUserData( pObject );
	pConf = pPrototype->pConf;
	iRet = PIObject_readParameters( pObject, iArgc, ppArgv,
		SSL_fnParameter, pObject );

	if ( !iRet )
		{ 
		goto init_error;
		};

	/* ---
	Initialize the random number generator
	or OAEP may fail
	--- */
	if ( pConf->pRandomSeedFile && !pConf->iDisable )
		{
		/* --- get file info --- */
		pFInfo = PIFInfo_new( pConf->pRandomSeedFile );

		if ( !pFInfo || !PIFInfo_exists( pFInfo ) || PIFInfo_isDirectory( pFInfo )
			|| !PIFInfo_isReadable( pFInfo))
			{
			PIFInfo_delete( pFInfo );
			PILog_addMessage(
				PIObject_getDB( pObject ),
				PIObject_getConfigurationDB( pObject ),
				PILOG_ERROR, "SSL: random seed file '%s' \
doesn't exist or isn't readable.",
				pConf->pRandomSeedFile );
			goto init_error;
			};

		PIFInfo_delete( pFInfo );

		/* --- open file handle --- */
		if ((tFD = PIFile_open( pConf->pRandomSeedFile, "r" )) == PIPLATFORM_FD_INVALID)
			{
			/* --- handle error --- */
			int iErrorCode = PIPlatform_getLastError();
			PILog_addMessage(
				PIObject_getDB( pObject ),
				PIObject_getConfigurationDB( pObject ),
				PILOG_ERROR, "SSL: Error on open random seed file '%s'. \
The system error code is %d.",
				pConf->pRandomSeedFile, iErrorCode );
			goto init_error;
			};

		pBuf = PIUtil_malloc( pConf->iRandomSize );
		if ( !pBuf )
			{
			/* --- handle error --- */
			int iErrorCode = PIPlatform_getLastError();
			PILog_addMessage(
				PIObject_getDB( pObject ),
				PIObject_getConfigurationDB( pObject ),
				PILOG_ERROR, "SSL: Error on allocate random seed buffer. \
The system error code is %d.", iErrorCode );
			goto init_error;
			};

		PIFile_read( tFD, pConf->iRandomSize, pBuf );
		PIFile_close( tFD );

		RAND_seed( pBuf, pConf->iRandomSize );
		PIUtil_free( pBuf );
		}
	else
		{
		RAND_seed(rnd_seed, sizeof rnd_seed);
		};

	/*
	** Open a debug file ?
	*/
	if ( pConf->pDebugFile )
		{
		if ( !strcmp( pConf->pDebugFile, "STDERR" ) )
			{
			pConf->pBIODebug = BIO_new_fp(stderr,BIO_NOCLOSE);
			}
		else if ( !strcmp( pConf->pDebugFile, "STDOUT" ) )
			{
			pConf->pBIODebug = BIO_new_fp(stdout,BIO_NOCLOSE);
			}
		else
			{
			pConf->pStdioDebug = fopen( pConf->pDebugFile, "w" );
			if ( !pConf->pStdioDebug )
				{
				PILog_addMessage(
					PIObject_getDB( pObject ),
					PIObject_getConfigurationDB( pObject ),
					PILOG_ERROR, "SSL: Failed to open debug file '%s'.",
					pConf->pDebugFile );
				goto init_error;
				};
			pConf->pBIODebug = BIO_new_fp( pConf->pStdioDebug, BIO_NOCLOSE );
			};
		}

	/* ---
	Check values were set
	--- */
	if ( !pPrototype->pIOObject )
		{
		PILog_addMessage(
			PIObject_getDB( pObject ), PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "SSL: 'IOObject' not defined." );
		goto init_error;
		};

	if ( !pConf->iServer && !pConf->pKeyF )
		{
		PILog_addMessage(
			PIObject_getDB( pObject ),
			PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "SSL: 'PrivateKeyFile' must be defined \
for server connection." );
		goto init_error;
		};

		/* --- get file info --- */
		pFInfo = PIFInfo_new( pConf->pKeyF );

		if ( !pFInfo || !PIFInfo_exists( pFInfo ) || PIFInfo_isDirectory( pFInfo )
			|| !PIFInfo_isReadable( pFInfo))
			{
			PIFInfo_delete( pFInfo );
			PILog_addMessage(
				PIObject_getDB( pObject ),
				PIObject_getConfigurationDB( pObject ),
				PILOG_ERROR, "SSL: private key file '%s' \
doesn't exist or isn't readable.",
				pConf->pKeyF );
			goto init_error;
			};
		PIFInfo_delete( pFInfo );

	if ( !pConf->iServer && !pConf->pCertF )
		{
		PILog_addMessage(
			PIObject_getDB( pObject ),
			PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "SSL: 'CertificateFile' must be defined \
for server connection." );
		goto init_error;
		};

		/* --- get file info --- */
		pFInfo = PIFInfo_new( pConf->pCertF );

		if ( !pFInfo || !PIFInfo_exists( pFInfo ) || PIFInfo_isDirectory( pFInfo )
			|| !PIFInfo_isReadable( pFInfo))
			{
			PIFInfo_delete( pFInfo );
			PILog_addMessage(
				PIObject_getDB( pObject ),
				PIObject_getConfigurationDB( pObject ),
				PILOG_ERROR, "SSL: certificate file '%s' \
doesn't exist or isn't readable.",
				pConf->pCertF );
			goto init_error;
			};
		PIFInfo_delete( pFInfo );

	/*
	** Funny little piece of code
	*/
	switch( pConf->iVersion * ( 1 + pConf->iServer ) )
		{
		case 10: pSSLMethod = TLSv1_client_method(); break;
		case 23: pSSLMethod = SSLv23_client_method(); break;
		case 2: pSSLMethod = SSLv2_client_method(); break;
		case 3: pSSLMethod = SSLv3_client_method(); break;

		case 20: pSSLMethod = TLSv1_server_method(); break;
		case 46: pSSLMethod = SSLv23_server_method(); break;
		case 4: pSSLMethod = SSLv2_server_method(); break;
		case 6: pSSLMethod = SSLv3_server_method(); break;

		default:
			assert( 0 );
		};
	pConf->pCtx = SSL_CTX_new( pSSLMethod );
	if ( !pConf->pCtx )
		{
		PILog_addMessage(
			PIObject_getDB( pObject ), PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "SSL: 'SSL_CTX_new()' failed." );
		INIT_ERR( pConf->pBIODebug );
		goto init_error;
		};
 
#if ( PISSL_DEBUG )
	SSL_CTX_set_info_callback( pConf->pCtx, fnSSLInfo );
#endif

	/*
	** Set list of allowed ciphers
	*/
	if (	pConf->pCipherList &&
			!SSL_CTX_set_cipher_list( pConf->pCtx, pConf->pCipherList ) )
		{
		/*
		** Cipher list was specified, but failed to set it
		*/
		PILog_addMessage(
			PIObject_getDB( pObject ), PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "SSL: 'SSL_set_cipher_list()' failed \
for cipher list '%s'.", pConf->pCipherList );
		INIT_ERR( pConf->pBIODebug );
		goto init_error;
		};

	/*
	** What are these for??
	*/
	if ( pConf->iBugs )
		{ SSL_CTX_set_options( pConf->pCtx, SSL_OP_ALL); };

	if ( pConf->iHack )
		{
		SSL_CTX_set_options( pConf->pCtx,
			SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
//		SSL_CTX_set_options( pConf->pCtx, SSL_OP_NON_EXPORT_FIRST);
		};

	if ( (!SSL_CTX_load_verify_locations( pConf->pCtx, pConf->pCACertF,
			pConf->pCACertP ) ) &&
		 (!SSL_CTX_set_default_verify_paths( pConf->pCtx ) ) )
		{
		PILog_addMessage(
			PIObject_getDB( pObject ), PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "SSL: 'SSL_CTX_load_verify_locations()' failed." );
		INIT_ERR( pConf->pBIODebug );
		goto init_error;
		}

	/*
	** Set SSL verification callback
	*/
	SSL_CTX_set_verify( pConf->pCtx, pConf->iVerify, fnVerify );

	if ( SSL_CTX_use_certificate_file(pConf->pCtx, pConf->pCertF,
		SSL_FILETYPE_PEM) ==-1 )
		{
		PILog_addMessage(
			PIObject_getDB( pObject ), PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "SSL: 'SSL_CTX_use_certificate_file()' failed." );
		INIT_ERR( pConf->pBIODebug );
		goto init_error;
		};

	/* --- open file handle --- */
	fp = fopen( pConf->pKeyF, "r" );
	if ( !fp )
		{
		PILog_addMessage(
			PIObject_getDB( pObject ),
			PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "SSL: Failed to open private key file '%s'.",
			pConf->pKeyF );
		goto init_error;
		};

	/* --- for passphrase callback --- */
	if ( (pKey = PEM_read_PrivateKey( fp, NULL, &fnPassPhrase, pConf )) == NULL )
		{
		PILog_addMessage(
			PIObject_getDB( pObject ), PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "SSL: 'PEM_read_PrivateKey()' failed. \n\
Check, if you entered the correct pass phrase for the used private key!" );
		fclose( fp );
//		INIT_ERR;
		goto init_error;
		};

	fclose( fp );

	/* old
	if ( SSL_CTX_use_PrivateKey_file(pConf->pCtx, pConf->pKeyF,
		SSL_FILETYPE_PEM) ==-1 )
	*/

	if ( SSL_CTX_use_PrivateKey( pConf->pCtx, pKey ) == -1 )
		{
		PILog_addMessage(
			PIObject_getDB( pObject ), PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "SSL: 'SSL_CTX_use_PrivateKey()' failed." );
		INIT_ERR( pConf->pBIODebug );
		goto init_error;
		};

	SSL_CTX_set_tmp_rsa_callback( pConf->pCtx, fnTmpRSA );

	/*
	** If we are using DSA, we can copy the parameters from
	** the private key
	*/
	pSSL=SSL_new( pConf->pCtx );
	assert( pSSL );
	CRYPTO_set_ex_data(&pSSL->ex_data, 0, (char *)pPrototype );
	pX509=SSL_get_certificate( pSSL );
	if ( pX509 )
		{
		EVP_PKEY_copy_parameters(
			X509_get_pubkey( pX509 ), SSL_get_privatekey( pSSL ) );
		};
	SSL_free( pSSL );

	/*
	** Now we know that a key and cert have been set against
	** the SSL context
	*/
	if ( !SSL_CTX_check_private_key( pConf->pCtx ) )
		{
		PILog_addMessage(
			PIObject_getDB( pObject ), PIObject_getConfigurationDB( pObject ),
			PILOG_ERROR, "SSL: Private key does not match the \
certificate public key." );
		INIT_ERR( pConf->pBIODebug );
		goto init_error;
		}

	return iRet;

init_error:
	return 0;
}


static PISync **SSL_sync;

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
void locking_callback(int mode, int type, const char *file, int line)
{
	mode & CRYPTO_LOCK ? PISync_lock(SSL_sync[type]) : PISync_unlock(SSL_sync[type]);
}


/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:

⌨️ 快捷键说明

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