| #ifndef __ENABLE_MOCANA_SSL_SERVER__  | 
 |  | 
 | #include	"wsIntrn.h" | 
 | #include	"webs.h" | 
 | #include	"websSSL.h" | 
 | #include	"ref_nv_def.h" | 
 |  | 
 |  | 
 | #define DEFAULT_KEY_FILE	"/etc_ro/certs/cakey.pem" | 
 | #define DEFAULT_CA_FILE		"/etc_ro/certs/cacert.pem" | 
 | #define DEFAULT_PWD_FILE	"/etc_ro/certs/password" | 
 | #define SSL_PORT			443 | 
 |  | 
 | #define DEFAULT_KEY_MASK	0x60 | 
 | typedef struct websSSLKey { | 
 | 	char pwd[17]; | 
 | 	unsigned char procType; | 
 | 	unsigned short dekType; | 
 | 	unsigned char dekInfo[16]; | 
 | 	unsigned char privateKey[624]; | 
 | 	unsigned short certLen; | 
 | } websSSLKey; | 
 |  | 
 |  | 
 |  | 
 | #ifdef SIGPIPE | 
 | #define do_pipe_sig()	signal(SIGPIPE,SIG_IGN) | 
 | #else | 
 | #define do_pipe_sig() | 
 | #endif | 
 |  | 
 |  | 
 | #  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 | 
 |  | 
 |  | 
 | #ifdef OPENSSL | 
 | #ifndef SSLeay_add_all_algorithms | 
 | #define SSLeay_add_all_algorithms() OpenSSL_add_all_algorithms() | 
 | #endif | 
 |  | 
 | #define SSLC_add_all_algorithms()	SSLeay_add_all_algorithms() | 
 | #else | 
 | extern void SSLC_add_all_algorithms(void); | 
 | #endif | 
 |  | 
 |  | 
 | 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); | 
 | static int		websSSLSetCertStuff(SSL_CTX *ctx, char *cert_file, char *key_file); | 
 |  | 
 |  | 
 | static int		sslListenSock = -1;			 | 
 | static SSL_CTX	*sslctx = NULL; | 
 | static char		*sslpwd = NULL; | 
 | static websSSLKey sslkey = {0}; | 
 | static unsigned char *sslcert = NULL; | 
 |  | 
 |  | 
 | static int getFileSize(char *lpath) | 
 | { | 
 | 	gstat_t s; | 
 | 	 | 
 | 	if (lpath && stat(lpath, &s) == 0) { | 
 | 		return s.st_size; | 
 | 	} | 
 | 	return 0; | 
 | } | 
 |  | 
 |  | 
 | int websSSLOpen() | 
 | { | 
 | 	SSL_METHOD	*meth; | 
 |  | 
 | 	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 | 
 |  | 
 |  | 
 | #ifdef WEBINSPECT_FIX  | 
 | 	meth = TLSv1_2_server_method(); | 
 | #else  | 
 | 	meth = SSLv23_server_method(); | 
 | #endif	 | 
 | 	sslctx = SSL_CTX_new(meth); | 
 |  | 
 | 	a_assert(sslctx); | 
 |  | 
 | 	if (sslctx == NULL) { | 
 | 		trace(2, T("SSL: Unable to create SSL context!\n"));  | 
 | 		return -1; | 
 | 	} | 
 |  | 
 |  | 
 | 	SSL_CTX_set_quiet_shutdown(sslctx, 1); | 
 | 	SSL_CTX_set_options(sslctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); | 
 | 	SSL_CTX_sess_set_cache_size(sslctx, 128); | 
 | 	 | 
 | 	EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); | 
 | 	if (ecdh){ | 
 | 		long eret = SSL_CTX_set_tmp_ecdh (sslctx, ecdh); | 
 | 		trace(2, T("SSL: ecdh:%x ret=%d\n"), ecdh, eret);  | 
 | 		EC_KEY_free(ecdh); | 
 | 		ecdh = NULL; | 
 | 	} | 
 |  | 
 |  | 
 | #ifdef WEBINSPECT_FIX	 | 
 | 	if(!SSL_CTX_set_cipher_list(sslctx,"ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:!NULL:!RC4:!RC2:!DES:!3DES:!SHA:!SHA256:!SHA384:!MD5+HIGH:+MEDIUM")) | 
 | 		trace(2, T("SSL: Unable to set !DES:!RC4:!SHA1\n"));  | 
 | #endif		 | 
 |  | 
 | 	unsigned char webkey_flag = 0; | 
 | 	int retCode = cpnv_NvItemRead(ZPS_REF_MSINFO_WEBKEY_FLAG_BASE_ADDR, &webkey_flag, sizeof(webkey_flag)); | 
 | 	if (retCode == CPNV_ERROR) | 
 | 	{ | 
 | 		trace(2, T("SSL: read cpnv keyflag error\n")); | 
 | 		websSSLClose(); | 
 | 		return -1; | 
 | 	} | 
 | 	trace(2, T("SSL: webkey_flag=%d\n"),webkey_flag); | 
 | 	if (webkey_flag != 1) | 
 | 	{ | 
 | 		ssize_t read_len = 0; | 
 | 		char *pwdFile = DEFAULT_PWD_FILE; | 
 | 		int pwdSize = getFileSize(pwdFile); | 
 | 		if(pwdSize > 0) | 
 | 		{ | 
 | 			int fd = open(pwdFile, SOCKET_RDONLY | SOCKET_BINARY, 0666); | 
 | 			if(fd >= 0)  | 
 | 			{ | 
 | 				sslpwd = balloc(B_L,pwdSize + 1); | 
 | 				if(sslpwd != NULL) | 
 | 				{ | 
 | 					memset(sslpwd, 0, pwdSize + 1); | 
 | 					read_len = read(fd, sslpwd, pwdSize); | 
 | 					if(read_len < 0) | 
 | 					{ | 
 | 						trace(2, T("read len:%d ; errno: %s\n"), read_len, strerror(errno));  | 
 | 					} | 
 | 					trace(2, T("SSL: pwd:%s\n"), sslpwd);  | 
 | 					SSL_CTX_set_default_passwd_cb_userdata(sslctx, (void *)sslpwd); | 
 | 				} | 
 | 				close(fd); | 
 | 			} | 
 | 		} | 
 | 			 | 
 | 		//char *certFile = DEFAULT_CA_FILE; | 
 | 		//char *keyFile = DEFAULT_KEY_FILE;// kw OVERWRITE_CONST_CHAR | 
 | 		if (websSSLSetCertStuff(sslctx, DEFAULT_CA_FILE, DEFAULT_KEY_FILE) != 0) { | 
 | 			websSSLClose(); | 
 | 			return -1; | 
 | 		} | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		retCode = cpnv_NvItemRead(ZPS_REF_MSINFO_WEBKEY_DATA_BASE_ADDR, (unsigned char *)&sslkey, sizeof(sslkey)); | 
 | 		char i = 0; | 
 | 		if (retCode == CPNV_ERROR) | 
 | 		{ | 
 | 			trace(2, T("SSL: read cpnv key error\n")); | 
 | 			websSSLClose(); | 
 | 			return -1; | 
 | 		} | 
 | 		trace(2, T("SSL: key procType=%d dekType=%d certLen=%d\n"),sslkey.procType,sslkey.dekType,sslkey.certLen); | 
 | 		sslcert = balloc(B_L, sslkey.certLen); | 
 | 		if(sslcert == NULL) | 
 | 		{ | 
 | 			trace(2, T("SSL: alloc cpnv cert fail\n")); | 
 | 			websSSLClose(); | 
 | 			return -1; | 
 | 		} | 
 | 		retCode = cpnv_NvItemRead(ZPS_REF_MSINFO_WEBKEY_DATA_BASE_ADDR+sizeof(sslkey), sslcert, sslkey.certLen); | 
 | 		if (retCode == CPNV_ERROR) | 
 | 		{ | 
 | 			trace(2, T("SSL: read cpnv cert error\n")); | 
 | 			websSSLClose(); | 
 | 			return -1; | 
 | 		} | 
 | 		for(i=0; i < sizeof(sslkey.pwd); i++) | 
 | 		{ | 
 | 			if(sslkey.pwd[i] != 0) | 
 | 			{ | 
 | 				sslkey.pwd[i] = sslkey.pwd[i] - DEFAULT_KEY_MASK; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				break; | 
 | 			} | 
 | 		} | 
 | 		SSL_CTX_set_default_passwd_cb_userdata(sslctx, (void *)sslkey.pwd); | 
 | 		retCode = websSSLSetCertificate(sslctx, sslcert, sslkey.certLen); | 
 | 		if (retCode <= 0) | 
 | 		{ | 
 | 			trace(2, T("SSL: websSSLSetCertificate fail ret=%d\n"),retCode); | 
 | 			websSSLClose(); | 
 | 			return -1; | 
 | 		} | 
 | 		retCode = websSSLSetPrivateKey(sslctx, &sslkey); | 
 | 		if (retCode <= 0) | 
 | 		{ | 
 | 			trace(2, T("SSL: websSSLSetPrivateKey fail ret=%d\n"),retCode); | 
 | 			websSSLClose(); | 
 | 			return -1; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	SSL_CTX_set_tmp_rsa_callback(sslctx, websSSLTempRSACallback); | 
 |  | 
 |  | 
 | 	SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, websSSLVerifyCallback); | 
 |  | 
 |  | 
 | 	sslListenSock = socketOpenConnection6(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; | 
 | } | 
 |  | 
 |  | 
 |  | 
 | int websSSLIsOpen() | 
 | { | 
 | 	return (sslListenSock != -1); | 
 | } | 
 |  | 
 |  | 
 |  | 
 | 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); | 
 |  | 
 |  | 
 | 	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)); | 
 |  | 
 |  | 
 | 	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; | 
 | 	} | 
 |  | 
 | 	wp->flags |= WEBS_SECURE; | 
 |  | 
 |  | 
 | 	socketCreateHandler(sid, SOCKET_READABLE, websSSLSocketEvent, (int) wp); | 
 |  | 
 | 	wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout, (void *) wp); | 
 | 	//trace(8, T("webs: accept request\n")); | 
 | 	return 0; | 
 | } | 
 |  | 
 | 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; | 
 | 	} | 
 |  | 
 | 	if(sslpwd != NULL) { | 
 | 		bfree(B_L, sslpwd); | 
 | 		sslpwd = NULL; | 
 | 	} | 
 |  | 
 | #ifdef SSLC | 
 | 	SSL_library_cleanup(); | 
 | #endif | 
 | } | 
 |  | 
 |  | 
 | 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); | 
 | 	if(sptr == NULL) | 
 | 		return -1; | 
 | 	sock = sptr->sock; | 
 |  | 
 | 	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 | 
 |  | 
 | #ifdef WEBS_SSL_SUPPORT | 
 | 	websSSLFree(wp->wsp); | 
 | 	wp->wsp = balloc(B_L, sizeof(websSSL_t)); | 
 | 	a_assert (wp->wsp); | 
 | 	if(wp->wsp == NULL) | 
 | 		return -1; | 
 | 	(wp->wsp)->bio = bio; | 
 | 	(wp->wsp)->ssl = ssl; | 
 | #endif | 
 |  | 
 | 	websReadEvent(wp); | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | 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 (websValid(wp) && wp->writeSocket) {//cov | 
 | 			(*wp->writeSocket)(wp); | 
 | 		} | 
 | 	}  | 
 | } | 
 |  | 
 | 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); | 
 | 		X509_NAME_oneline(X509_get_issuer_name(X509_STORE_CTX_get_current_cert(ctx)), 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; | 
 | } | 
 |  | 
 | int websSSLSetCertificate(SSL_CTX *ctx, const unsigned char *data, int len) | 
 | { | 
 | 	BIO *in; | 
 | 	int ret = 0; | 
 | 	X509 *x = NULL; | 
 | 	 | 
 | 	in = BIO_new(BIO_s_mem()); | 
 | 	if (in == NULL) { | 
 | 		trace(2, T("SSL: cert BIO_new NULL\n")); | 
 | 		goto end; | 
 | 	} | 
 |  | 
 | 	ret = PEM_write_bio(in, PEM_STRING_X509, "", data, len); | 
 | 	if (ret <= 0){ | 
 | 		trace(2, T("SSL: cert PEM_write_bio fail ret=%d\n"),ret); | 
 | 		goto end; | 
 | 	} | 
 | 	x = PEM_read_bio_X509(in, NULL, | 
 | 			SSL_CTX_get_default_passwd_cb(ctx),//ctx->default_passwd_callback, | 
 | 			SSL_CTX_get_default_passwd_cb_userdata(ctx));//ctx->default_passwd_callback_userdata); | 
 |  | 
 | 	if (x == NULL) { | 
 | 		trace(2, T("SSL: cert PEM_read_bio_X509 NULL\n")); | 
 | 		goto end; | 
 | 	} | 
 |  | 
 | 	ret = SSL_CTX_use_certificate(ctx, x); | 
 | 	X509_free(x); | 
 |  | 
 |  end: | 
 | 	if (in != NULL) | 
 | 		BIO_free(in); | 
 | 	return (ret); | 
 | } | 
 |  | 
 | int websSSLSetPrivateKey(SSL_CTX *ctx, websSSLKey *key) | 
 | { | 
 | 	int ret = 0; | 
 | 	BIO *in; | 
 | 	EVP_PKEY *pkey = NULL; | 
 | 	const char *objstr = NULL; | 
 | 	char buf[PEM_BUFSIZE] = {0}; | 
 | 	 | 
 | 	in = BIO_new(BIO_s_mem()); | 
 | 	if (in == NULL) { | 
 | 		trace(2, T("SSL: key BIO_new NULL\n")); | 
 | 		goto end; | 
 | 	} | 
 |  | 
 | 	objstr = OBJ_nid2sn(key->dekType); | 
 | 	if (objstr == NULL) { | 
 | 		trace(2, T("SSL: key OBJ_nid2sn NULL type = %d\n"),key->dekType); | 
 | 		goto end; | 
 | 	} | 
 | 	PEM_proc_type(buf, key->procType); | 
 | 	PEM_dek_info(buf, objstr, sizeof(key->dekInfo), (char *)key->dekInfo); | 
 |  | 
 | 	ret = PEM_write_bio(in, PEM_STRING_RSA, buf, key->privateKey, sizeof(key->privateKey)); | 
 | 	if (ret <= 0){ | 
 | 		trace(2, T("SSL: key PEM_write_bio fail ret=%d\n"),ret); | 
 | 		goto end; | 
 | 	} | 
 | 	pkey = PEM_read_bio_PrivateKey(in, NULL, | 
 | 			SSL_CTX_get_default_passwd_cb(ctx),//ctx->default_passwd_callback, | 
 | 			SSL_CTX_get_default_passwd_cb_userdata(ctx));//ctx->default_passwd_callback_userdata); | 
 | 	if (pkey == NULL) { | 
 | 		trace(2, T("SSL: key PEM_read_bio_PrivateKey NULL\n")); | 
 | 		goto end; | 
 | 	} | 
 | 	ret = SSL_CTX_use_PrivateKey(ctx, pkey); | 
 | 	EVP_PKEY_free(pkey); | 
 | 	 | 
 |  end: | 
 | 	if (in != NULL) | 
 | 		BIO_free(in); | 
 | 	return (ret); | 
 | } | 
 |  | 
 |  | 
 | 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; | 
 | 		} | 
 |  | 
 |  | 
 | 		if (!SSL_CTX_check_private_key(ctx)) { | 
 | 			trace(2, T("SSL: Check of private key file <%s> FAILED!\n"), | 
 | 				keyFile);  | 
 | 			return -1; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 |  | 
 | 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; | 
 | 	} | 
 |  | 
 | 	if (!SSL_CTX_check_private_key(sslctx)) { | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 |  | 
 | 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; | 
 | 	} | 
 |  | 
 | 	if (!SSL_CTX_check_private_key(sslctx)) { | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | #ifdef SSLC | 
 | extern RSA *RSA_new(void); | 
 | #endif | 
 |  | 
 | int websSSLEof(websSSL_t *wsp) | 
 | { | 
 | 	a_assert(wsp); | 
 |  | 
 | 	if ((wsp == NULL) || (wsp->bio == NULL)) { | 
 | 		return -1; | 
 | 	}  | 
 |  | 
 | 	return BIO_eof(wsp->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); | 
 | } | 
 |  | 
 | 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; | 
 | } | 
 |  | 
 |  | 
 | int websSSLFree(websSSL_t *wsp) | 
 | { | 
 | 	if (wsp == NULL) { | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	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; | 
 | } | 
 |  | 
 |  | 
 |  | 
 |  | 
 | #define BUF_BLOCK 256 | 
 |  | 
 | int 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 (len < 1536) { | 
 |  | 
 | 		if ((rc = BIO_read(wsp->bio, &c, 1)) < 0) { | 
 | 			return rc; | 
 | 		} | 
 | 		 | 
 | 		if (rc == 0) { | 
 |  | 
 | 			if (len > 0 && BIO_eof(wsp->bio)) { | 
 | 				c = '\n'; | 
 | 			} else { | 
 | 				return -1; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		if (c == '\n') { | 
 | 			if ((len > 0) && (len < lenBuf)) { | 
 | 				(*buf)[len] = 0; | 
 | 			} | 
 | 			return len; | 
 | 		} else if (c == '\r') { | 
 | 			continue; | 
 | 		}  | 
 |  | 
 | 		if (lenBuf == 0 || len >= lenBuf - 1) { | 
 | 			lenBuf += BUF_BLOCK; | 
 | 			*buf = brealloc(B_L, *buf, lenBuf); | 
 | 		} | 
 |  | 
 | 		a_assert(*buf); | 
 | 		if(*buf == NULL) | 
 | 			return -1; | 
 | 		(*buf)[len] = c; | 
 | 		len++; | 
 | 	} | 
 | 	bfreeSafe(B_L,*buf); | 
 | 	*buf = NULL; | 
 | 	return -1; | 
 | } | 
 |  | 
 |  | 
 | 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); | 
 | } | 
 |  | 
 |  | 
 | int websSSLFlush(websSSL_t *wsp) | 
 | { | 
 | 	a_assert(wsp); | 
 |  | 
 | 	if ((wsp == NULL) || (wsp->bio == NULL)) { | 
 | 		return -1; | 
 | 	}  | 
 |  | 
 | 	return BIO_flush(wsp->bio); | 
 | } | 
 |  | 
 | #endif |