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

📄 websssl.c

📁 一个典型的用于嵌入式Linux环境的Webserver
💻 C
字号:
/* * websSSL.c -- SSL envrionment creation * * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved. * * See the file "license.txt" for usage and redistribution license requirements * * $Id: websSSL.c,v 1.3 2003/09/29 20:30:48 bporter Exp $ *//******************************** Description *********************************//* *	This module implements a patch into SSL implementations for the webs *	module. */#ifndef __ENABLE_MOCANA_SSL_SERVER__ /********************************* Includes ***********************************/#include	"wsIntrn.h"#include	"webs.h"#include	"websSSL.h"/******************************* Definitions **********************************/#define DEFAULT_CERT_FILE	"./server.pem"#define DEFAULT_KEY_FILE	"./certs/cakey.pem"#define DEFAULT_CA_FILE		"./certs/cacert.pem"#define DEFAULT_CA_PATH		"./certs/"#define SSL_PORT			443/* *	Define the components of the apps_startup() macro */#ifdef SIGPIPE#define do_pipe_sig()	signal(SIGPIPE,SIG_IGN)#else#define do_pipe_sig()#endif#ifdef OPENSSL#define SSLC_add_all_algorithms()	SSLeay_add_all_algorithms()#elseextern void SSLC_add_all_algorithms(void);#endif/* *	Define the apps_startup() macro */#  if defined(MSDOS) || defined(WIN16) || defined(WIN32)#    ifdef _O_BINARY#      define apps_startup() \		_fmode=_O_BINARY; do_pipe_sig(); CRYPTO_malloc_init(); \		SSLC_add_all_algorithms()#    else#      define apps_startup() \		_fmode=O_BINARY; do_pipe_sig(); CRYPTO_malloc_init(); \		SSLC_add_all_algorithms()#    endif#  else#    define apps_startup()	do_pipe_sig(); SSLC_add_all_algorithms();#  endif/*************************** Forward Declarations *****************************/static int		websSSLSetCertStuff(SSL_CTX *ctx, 									char *cert_file, 									char *key_file);static int		websSSLVerifyCallback(int ok, X509_STORE_CTX *ctx);static RSA		*websSSLTempRSACallback(SSL *s, int is_export, int keylength);static int		websSSLReadEvent (webs_t wp);static int		websSSLAccept(int sid, char *ipaddr, int port, int listenSid);static void		websSSLSocketEvent(int sid, int mask, int data);/*********************************** Locals ***********************************/static int		sslListenSock = -1;			/* Listen socket */static SSL_CTX	*sslctx = NULL;/******************************************************************************//* *	Start up the SSL Context for the application, and start a listen on the *	SSL port (usually 443, and defined by SSL_PORT) *	Return 0 on success, -1 on failure. */int websSSLOpen(){	char		*certFile, *keyFile, *CApath, *CAfile;	SSL_METHOD	*meth;	/* *	Install and initialize the SSL library */	apps_startup();	trace(7, T("SSL: Initializing SSL\n")); #ifdef SSLC	SSL_library_init();#endif	SSL_load_error_strings();#ifdef OPENSSL	SSLeay_add_ssl_algorithms();#endif/* *	Important!  Enable both SSL versions 2 and 3 */	meth = SSLv23_server_method();	sslctx = SSL_CTX_new(meth);	a_assert(sslctx);	if (sslctx == NULL) {		trace(2, T("SSL: Unable to create SSL context!\n")); 		return -1;	}/* *	Adjust some SSL Context variables */	SSL_CTX_set_quiet_shutdown(sslctx, 1);	SSL_CTX_set_options(sslctx, 0);	SSL_CTX_sess_set_cache_size(sslctx, 128);/* *	Set the certificate verification locations */	CApath = DEFAULT_CA_PATH;	CAfile = DEFAULT_CA_FILE;	if ((!SSL_CTX_load_verify_locations(sslctx, CAfile, CApath)) ||		(!SSL_CTX_set_default_verify_paths(sslctx))) {		trace(2, T("SSL: Unable to set cert verification locations!\n")); 		websSSLClose();		return -1;	}/* *	Set the certificate and key files for the SSL context */	certFile = DEFAULT_CERT_FILE;	keyFile = NULL;	if (websSSLSetCertStuff(sslctx, certFile, keyFile) != 0) {		websSSLClose();		return -1;	}/* *	Set the RSA callback for the SSL context */	SSL_CTX_set_tmp_rsa_callback(sslctx, websSSLTempRSACallback);/* *	Set the verification callback for the SSL context */	SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, websSSLVerifyCallback);/* *	Set the certificate authority list for the client */	SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(CAfile));/* *	Open the socket */	sslListenSock = socketOpenConnection(NULL, SSL_PORT, 		websSSLAccept, SOCKET_BLOCK);	if (sslListenSock < 0) {		trace(2, T("SSL: Unable to open SSL socket on port <%d>!\n"), 			SSL_PORT);		return -1;	}	return 0;}/******************************************************************************//* *	Return TRUE if websSSL has been opened */int websSSLIsOpen(){	return (sslListenSock != -1);}/******************************************************************************//* *	Stops the SSL */void websSSLClose(){	trace(7, T("SSL: Closing SSL\n")); 	if (sslctx != NULL) {		SSL_CTX_free(sslctx);		sslctx = NULL;	}	if (sslListenSock != -1) {		socketCloseConnection(sslListenSock);		sslListenSock = -1;	}#ifdef SSLC	SSL_library_cleanup();#endif}/******************************************************************************//* *	Accept a connection */int websSSLAccept(int sid, char *ipaddr, int port, int listenSid){	webs_t	wp;	int		wid;	a_assert(ipaddr && *ipaddr);	a_assert(sid >= 0);	a_assert(port >= 0);/* *	Allocate a new handle for this accepted connection. This will allocate *	a webs_t structure in the webs[] list */	if ((wid = websAlloc(sid)) < 0) {		return -1;	}	wp = webs[wid];	a_assert(wp);	wp->listenSid = listenSid;	ascToUni(wp->ipaddr, ipaddr, min(sizeof(wp->ipaddr), strlen(ipaddr)+1));/* *	Check if this is a request from a browser on this system. This is useful *	to know for permitting administrative operations only for local access */	if (gstrcmp(wp->ipaddr, T("127.0.0.1")) == 0 || 			gstrcmp(wp->ipaddr, websIpaddr) == 0 || 			gstrcmp(wp->ipaddr, websHost) == 0) {		wp->flags |= WEBS_LOCAL_REQUEST;	}/* *	Since the acceptance came in on this channel, it must be secure */	wp->flags |= WEBS_SECURE;/* *	Arrange for websSocketEvent to be called when read data is available */	socketCreateHandler(sid, SOCKET_READABLE, websSSLSocketEvent, (int) wp);/* *	Arrange for a timeout to kill hung requests */	wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout, (void *) wp);	trace(8, T("webs: accept request\n"));	return 0;}/******************************************************************************//* *	The webs socket handler.  Called in response to I/O. We just pass control *	to the relevant read or write handler. A pointer to the webs structure *	is passed as an (int) in iwp. */static void websSSLSocketEvent(int sid, int mask, int iwp){	webs_t	wp;	wp = (webs_t) iwp;	a_assert(wp);	if (! websValid(wp)) {		return;	}	if (mask & SOCKET_READABLE) {		websSSLReadEvent(wp);	} 	if (mask & SOCKET_WRITABLE) {		if (wp->writeSocket) {			(*wp->writeSocket)(wp);		}	} }/******************************************************************************//* *	Handler for SSL Read Events */static int websSSLReadEvent (webs_t wp){	int			ret, sock;	socket_t	*sptr;	SSL			*ssl;	BIO			*bio, *bioSSL, *bioSock;#ifdef DEV	const char	*ciphers;#endif	a_assert (wp);	a_assert(websValid(wp));	sptr = socketPtr(wp->sid);	a_assert(sptr);	sock = sptr->sock;/* *	Create a new BIO and SSL session for this web request */	bio = BIO_new(BIO_f_buffer());	a_assert(bio);	if (!BIO_set_write_buffer_size(bio, 128)) {		return -1;	}	ssl = (SSL *) SSL_new(sslctx);	a_assert(ssl);	if (ssl == NULL) {		return -1;	}	SSL_set_session(ssl, NULL);	bioSSL =  BIO_new(BIO_f_ssl());	a_assert(bioSSL);	bioSock = BIO_new_socket(sock, BIO_NOCLOSE);	a_assert(bioSock);	SSL_set_bio(ssl, bioSock, bioSock);	SSL_set_accept_state(ssl);	ret = BIO_set_ssl(bioSSL, ssl, BIO_CLOSE);	BIO_push(bio, bioSSL);#ifdef DEV	ciphers = SSL_get_cipher_list(ssl, 10);#endif/* *	Create the SSL data structure in the wp. */#ifdef WEBS_SSL_SUPPORT	wp->wsp = balloc(B_L, sizeof(websSSL_t));	a_assert (wp->wsp);	(wp->wsp)->bio = bio;	(wp->wsp)->ssl = ssl;#endif/* *	Call the default Read Event */	websReadEvent(wp);	return ret;}/******************************************************************************//* *	SSL Verification Callback */static int sslVerifyDepth = 0;static int sslVerifyError = X509_V_OK;int websSSLVerifyCallback(int ok, X509_STORE_CTX *ctx){	char	buf[256];	X509	*errCert;	int		err;	int		depth;	errCert =	X509_STORE_CTX_get_current_cert(ctx);	err =		X509_STORE_CTX_get_error(ctx);	depth =		X509_STORE_CTX_get_error_depth(ctx);	X509_NAME_oneline(X509_get_subject_name(errCert), buf, 256);	if (!ok) {		if (sslVerifyDepth >= depth)	{			ok = 1;			sslVerifyError = X509_V_OK;		} else {			ok=0;			sslVerifyError = X509_V_ERR_CERT_CHAIN_TOO_LONG;		}	}	switch (err)	{	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:#ifdef OPENSSL		X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);#endif		break;	case X509_V_ERR_CERT_NOT_YET_VALID:	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:	case X509_V_ERR_CERT_HAS_EXPIRED:	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:		break;	}	return ok;}/******************************************************************************//* *	Set the SSL certificate and key for the SSL context */int websSSLSetCertStuff(SSL_CTX *ctx, char *certFile, char *keyFile){	a_assert (ctx);	a_assert (certFile);	if (certFile != NULL) {		if (SSL_CTX_use_certificate_file(ctx, certFile, 			SSL_FILETYPE_PEM) <= 0) {			trace(2, T("SSL: Unable to set certificate file <%s>\n"),				certFile); 			return -1;		}		if (keyFile == NULL) {			keyFile = certFile;		}		if (SSL_CTX_use_PrivateKey_file(ctx, keyFile, SSL_FILETYPE_PEM) <= 0) {			trace(2, T("SSL: Unable to set private key file <%s>\n"),				keyFile); 			return -1;		}/*		 *		Now we know that a key and cert have been set against *		the SSL context  */		if (!SSL_CTX_check_private_key(ctx)) {			trace(2, T("SSL: Check of private key file <%s> FAILED!\n"),				keyFile); 			return -1;		}	}	return 0;}/******************************************************************************//* *	Set certificate file for SSL context */int websSSLSetCertFile(char_t *certFile){	a_assert (sslctx);	a_assert (certFile);	if (sslctx == NULL) {		return -1;	}	if (SSL_CTX_use_certificate_file(sslctx, certFile, 		SSL_FILETYPE_PEM) <= 0) {		return -1;	}/*		 *	Confirm that the certificate and the private key jive. */	if (!SSL_CTX_check_private_key(sslctx)) {		return -1;	}	return 0;}/******************************************************************************//* *	Set key file for SSL context */int websSSLSetKeyFile(char_t *keyFile){	a_assert (sslctx);	a_assert (keyFile);	if (sslctx == NULL) {		return -1;	}	if (SSL_CTX_use_PrivateKey_file(sslctx, keyFile, SSL_FILETYPE_PEM) <= 0) {		return -1;	}/*		 *	Confirm that the certificate and the private key jive. */	if (!SSL_CTX_check_private_key(sslctx)) {		return -1;	}	return 0;}#ifdef SSLCextern RSA *RSA_new(void);#endif/******************************************************************************//* *	the Temporary RSA callback */static RSA *websSSLTempRSACallback(SSL *ssl, int isExport, int keyLength){	static RSA *rsaTemp = NULL;	if (rsaTemp == NULL) {#ifdef OPENSSL		rsaTemp = RSA_generate_key(keyLength, RSA_F4, NULL, NULL);#endif#ifdef SSLC		rsaTemp = RSA_new();#endif	}	return rsaTemp;}/******************************************************************************//* *	Free SSL resources  */int websSSLFree(websSSL_t *wsp){	if (wsp == NULL) {		return -1;	}/*  *	Make sure we re-use sessions */	if (wsp->ssl != NULL) {		SSL_set_shutdown(wsp->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);	}	if (wsp->bio != NULL) {		BIO_free_all(wsp->bio);	}	bfree(B_L, wsp);	return 0;}/******************************************************************************//* *	Return Eof for the SSL BIO */int websSSLEof(websSSL_t *wsp){	a_assert(wsp);	if ((wsp == NULL) || (wsp->bio == NULL)) {		return -1;	} 	return BIO_eof(wsp->bio);}/******************************************************************************//* *	Perform a read of the SSL BIO */int websSSLRead(websSSL_t *wsp, char_t *buf, int len){	a_assert(wsp);	a_assert(buf);	if ((wsp == NULL) || (wsp->bio == NULL)) {		return -1;	} 	return BIO_read(wsp->bio, buf, len);}/******************************************************************************//* *	Perform a gets of the SSL BIO, returning an balloc'ed string */#define BUF_BLOCK 256int websSSLGets(websSSL_t *wsp, char_t **buf){	int		rc,	len, lenBuf;	char	c;	a_assert(wsp);	a_assert(buf);	lenBuf = 0;	len = 0;	if ((wsp == NULL) || (wsp->bio == NULL)) {		return -1;	} 	while (1) {		if ((rc = BIO_read(wsp->bio, &c, 1)) < 0) {			return rc;		}				if (rc == 0) {/* *			If there is a partial line and we are at EOF, pretend we saw a '\n' */			if (len > 0 && BIO_eof(wsp->bio)) {				c = '\n';			} else {				return -1;			}		}/* *		If a newline is seen, return the data excluding the new line to the *		caller. If carriage return is seen, just eat it. */		if (c == '\n') {			if ((len > 0) && (len < lenBuf)) {				(*buf)[len] = 0;			}			return len;		} else if (c == '\r') {			continue;		} /* *		Append character to buf */		if (len >= lenBuf) {			lenBuf += BUF_BLOCK;			*buf = brealloc(B_L, *buf, lenBuf);		}		a_assert(*buf);		(*buf)[len] = c;		len++;	}}/******************************************************************************//* *	Perform a write to the SSL BIO */int websSSLWrite(websSSL_t *wsp, char_t *buf, int len){	a_assert(wsp);	a_assert(buf);	if ((wsp == NULL) || (wsp->bio == NULL)) {		return -1;	} 	return BIO_write(wsp->bio, buf, len);}/******************************************************************************//* *	Perform a flush of the SSL BIO */int websSSLFlush(websSSL_t *wsp){	a_assert(wsp);	if ((wsp == NULL) || (wsp->bio == NULL)) {		return -1;	} 	return BIO_flush(wsp->bio);}/******************************************************************************/#endif

⌨️ 快捷键说明

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