From dc15ee1f1ca3363390eb7ea3f54eaeae6122ce08 Mon Sep 17 00:00:00 2001
From: deuce <>
Date: Sat, 10 Mar 2018 01:53:39 +0000
Subject: [PATCH] More betterer crypt logging... Things return allocated
 pointers with errors in them now. FTP server updated, the rest to follow
 "soon".

---
 src/sbbs3/ftpsrvr.c   |  77 +++++++++++-----------
 src/sbbs3/js_socket.c |   3 +-
 src/sbbs3/mailsrvr.c  |  12 ++--
 src/sbbs3/services.c  |   8 +--
 src/sbbs3/ssl.c       | 145 ++++++++++++++++++++++++++----------------
 src/sbbs3/ssl.h       |   5 +-
 src/sbbs3/websrvr.c   |  12 ++--
 7 files changed, 151 insertions(+), 111 deletions(-)

diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index 06db06fa7e..fc52abcf67 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -293,6 +293,16 @@ static int ftp_close_socket(SOCKET* sock, CRYPT_SESSION *sess, int line)
 	return(result);
 }
 
+#define GCES(status, sock, session, estr, action) do {                      \
+	int GCES_level;                                                     \
+	get_crypt_error_string(status, session, &estr, action, &GCES_level);\
+	if (estr) {                                                         \
+		lprintf(GCES_level, "%04d %s", sock, estr);                 \
+		free(estr);                                                 \
+	}                                                                   \
+} while (0)
+
+
 static int sockprintf(SOCKET sock, CRYPT_SESSION sess, char *fmt, ...)
 {
 	int		len;
@@ -302,7 +312,7 @@ static int sockprintf(SOCKET sock, CRYPT_SESSION sess, char *fmt, ...)
 	char	sbuf[1024];
 	fd_set	socket_set;
 	struct timeval tv;
-	char	estr[SSL_ESTR_LEN];
+	char	*estr;
 
     va_start(argptr,fmt);
     len=vsnprintf(sbuf,maxlen=sizeof(sbuf)-2,fmt,argptr);
@@ -345,15 +355,13 @@ static int sockprintf(SOCKET sock, CRYPT_SESSION sess, char *fmt, ...)
 			if (result == CRYPT_OK)
 				sent += tls_sent;
 			else {
-				get_crypt_error_string(result, sess, estr, "sending data");
-				lprintf(crypt_ll(result), "%04d !ERROR %s", sock, estr);
+				GCES(result, sock, sess, estr, "sending data");
 				if (result != CRYPT_ERROR_TIMEOUT)
 					return 0;
 			}
 			result = cryptFlushData(sess);
 			if (result != CRYPT_OK) {
-				get_crypt_error_string(result, sess, estr, "flushing data");
-				lprintf(crypt_ll(result), "%04d error %s", sock, estr);
+				GCES(result, sock, sess, estr, "flushing data");
 				return 0;
 			}
 		}
@@ -1166,7 +1174,7 @@ static int sock_recvbyte(SOCKET sock, CRYPT_SESSION sess, char *buf, time_t *las
 	struct	timeval	tv;
 	int ret;
 	int i;
-	char estr[SSL_ESTR_LEN];
+	char *estr;
 
 	if(ftp_set==NULL || terminate_server) {
 		sockprintf(sock,sess,"421 Server downed, aborting.");
@@ -1175,10 +1183,8 @@ static int sock_recvbyte(SOCKET sock, CRYPT_SESSION sess, char *buf, time_t *las
 	}
 	if (sess > -1) {
 		/* Try a read with no timeout first. */
-		if ((ret = cryptSetAttribute(sess, CRYPT_OPTION_NET_READTIMEOUT, 0)) != CRYPT_OK) {
-				get_crypt_error_string(ret, sess, estr, "setting read timeout");
-				lprintf(crypt_ll(ret), "%04d !ERROR %s", sock, estr);
-		}
+		if ((ret = cryptSetAttribute(sess, CRYPT_OPTION_NET_READTIMEOUT, 0)) != CRYPT_OK)
+			GCES(ret, sock, sess, estr, "setting read timeout");
 		while (1) {
 			ret = cryptPopData(sess, buf, 1, &len);
 			/* Successive reads will be with the full timeout after a select() */
@@ -1187,14 +1193,12 @@ static int sock_recvbyte(SOCKET sock, CRYPT_SESSION sess, char *buf, time_t *las
 				case CRYPT_OK:
 					break;
 				case CRYPT_ERROR_TIMEOUT:
-					get_crypt_error_string(ret, sess, estr, "popping data");
-					lprintf(crypt_ll(ret), "%04d !TIMEOUT %s (%u seconds)", sock, estr, startup->max_inactivity);
+					GCES(ret, sock, sess, estr, "popping data");
 					return -1;
 				case CRYPT_ERROR_COMPLETE:
 					return 0;
 				default:
-					get_crypt_error_string(ret, sess, estr, "popping data");
-					lprintf(crypt_ll(ret), "%04d !ERROR %s", sock, estr);
+					GCES(ret, sock, sess, estr, "popping data");
 					if (ret < -1)
 						return ret;
 					return -2;
@@ -1366,7 +1370,7 @@ static void send_thread(void* arg)
 	socklen_t	addr_len;
 	fd_set		socket_set;
 	struct timeval tv;
-	char		estr[SSL_ESTR_LEN];
+	char		*estr;
 
 	xfer=*(xfer_t*)arg;
 	free(arg);
@@ -1459,15 +1463,13 @@ static void send_thread(void* arg)
 		if (*xfer.data_sess != -1) {
 			int status = cryptPushData(*xfer.data_sess, buf, rd, &wr);
 			if (status != CRYPT_OK) {
-				get_crypt_error_string(status, *xfer.data_sess, estr, "pushing data");
-				lprintf(crypt_ll(status), "%04d !ERROR %s", *xfer.data_sock, estr);
+				GCES(status, *xfer.data_sock, *xfer.data_sess, estr, "pushing data");
 				wr = -1;
 			}
 			else {
 				status = cryptFlushData(*xfer.data_sess);
 				if (status != CRYPT_OK) {
-					get_crypt_error_string(status, *xfer.data_sess, estr, "flushing data");
-					lprintf(crypt_ll(status), "%04d !ERROR %s", *xfer.data_sock, estr);
+					GCES(status, *xfer.data_sock, *xfer.data_sess, estr, "flushing data");
 					wr = -1;
 				}
 			}
@@ -1645,7 +1647,7 @@ static void receive_thread(void* arg)
 	fd_set		socket_set;
 	struct timeval tv;
 	CRYPT_SESSION	sess = -1;
-	char		estr[SSL_ESTR_LEN];
+	char		*estr;
 
 	xfer=*(xfer_t*)arg;
 	free(arg);
@@ -1735,8 +1737,7 @@ static void receive_thread(void* arg)
 		if (*xfer.data_sess != -1) {
 			int status = cryptPopData(*xfer.data_sess, buf, sizeof(buf), &rd);
 			if (status != CRYPT_OK) {
-				get_crypt_error_string(status, *xfer.data_sess, estr, "flushing data");
-				lprintf(crypt_ll(status), "%04d !ERROR %s", *xfer.data_sock, estr);
+				GCES(status, *xfer.data_sock, *xfer.data_sess, estr, "flushing data");
 				rd = -1;
 			}
 		}
@@ -1928,24 +1929,30 @@ static BOOL start_tls(SOCKET *sock, CRYPT_SESSION *sess, BOOL resp)
 	BOOL nodelay;
 	ulong nb;
 	int status;
-	char estr[SSL_ESTR_LEN];
+	char *estr;
+	int level;
 
-	if (get_ssl_cert(&scfg, estr) == -1) {
-		lprintf(LOG_ERR, "Unable to get certificate %s", estr);
+	if (get_ssl_cert(&scfg, &estr, &level) == -1) {
+		if (estr) {
+			lprintf(level, "%04d FTP %s", estr);
+			free(estr);
+		}
 		if (resp)
 			sockprintf(*sock, *sess, "431 TLS not available");
 		return FALSE;
 	}
 	if ((status = cryptCreateSession(sess, CRYPT_UNUSED, CRYPT_SESSION_SSL_SERVER)) != CRYPT_OK) {
-		get_crypt_error_string(status, CRYPT_UNUSED, estr, "creating session");
-		lprintf(crypt_ll(status), "%04d FTP ERROR %s", *sock, estr);
+		GCES(status, *sock, CRYPT_UNUSED, estr, "creating session");
+		if (estr) {
+			lprintf(level, "%04d FTP %s", *sock, estr);
+			free(estr);
+		}
 		if (resp)
 			sockprintf(*sock, *sess, "431 TLS not available");
 		return FALSE;
 	}
 	if ((status = cryptSetAttribute(*sess, CRYPT_SESSINFO_SSL_OPTIONS, CRYPT_SSLOPTION_DISABLE_CERTVERIFY)) != CRYPT_OK) {
-		get_crypt_error_string(status, *sess, estr, "disabling certificate verification");
-		lprintf(crypt_ll(status), "%04d FTP ERROR %s", *sock, estr);
+		GCES(status, *sock, *sess, estr, "disabling certificate verification");
 		cryptDestroySession(*sess);
 		*sess = -1;
 		if(resp)
@@ -1953,8 +1960,7 @@ static BOOL start_tls(SOCKET *sock, CRYPT_SESSION *sess, BOOL resp)
 		return FALSE;
 	}
 	if ((status=cryptSetAttribute(*sess, CRYPT_SESSINFO_PRIVATEKEY, scfg.tls_certificate)) != CRYPT_OK) {
-		get_crypt_error_string(status, *sess, estr, "setting private key");
-		lprintf(crypt_ll(status), "%04d FTP ERROR %s", *sock, estr);
+		GCES(status, *sock, *sess, estr, "setting private key");
 		cryptDestroySession(*sess);
 		*sess = -1;
 		if (resp)
@@ -1966,8 +1972,7 @@ static BOOL start_tls(SOCKET *sock, CRYPT_SESSION *sess, BOOL resp)
 	nb=0;
 	ioctlsocket(*sock,FIONBIO,&nb);
 	if ((status = cryptSetAttribute(*sess, CRYPT_SESSINFO_NETWORKSOCKET, *sock)) != CRYPT_OK) {
-		get_crypt_error_string(status, *sess, estr, "setting network socket");
-		lprintf(crypt_ll(status), "%04d FTP ERROR %s", *sock, estr);
+		GCES(status, *sock, *sess, estr, "setting network socket");
 		cryptDestroySession(*sess);
 		*sess = -1;
 		if (resp)
@@ -1977,14 +1982,12 @@ static BOOL start_tls(SOCKET *sock, CRYPT_SESSION *sess, BOOL resp)
 	if (resp)
 		sockprintf(*sock, -1, "234 Ready to start TLS");
 	if ((status = cryptSetAttribute(*sess, CRYPT_SESSINFO_ACTIVE, 1)) != CRYPT_OK) {
-		get_crypt_error_string(status, *sess, estr, "setting session active");
-		lprintf(crypt_ll(status), "%04d FTP ERROR %s", *sock, estr);
+		GCES(status, *sock, *sess, estr, "setting session active");
 		return TRUE;
 	}
 	if (startup->max_inactivity) {
 		if ((status = cryptSetAttribute(*sess, CRYPT_OPTION_NET_READTIMEOUT, startup->max_inactivity)) != CRYPT_OK) {
-			get_crypt_error_string(status, *sess, estr, "setting read timeout");
-			lprintf(crypt_ll(status), "%04d FTP ERROR %s", *sock, estr);
+			GCES(status, *sock, *sess, estr, "setting read timeout");
 			return TRUE;
 		}
 	}
diff --git a/src/sbbs3/js_socket.c b/src/sbbs3/js_socket.c
index 636658c1ca..f95b20505d 100644
--- a/src/sbbs3/js_socket.c
+++ b/src/sbbs3/js_socket.c
@@ -1667,7 +1667,6 @@ static JSBool js_socket_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict
 	jsrefcount	rc;
 	BOOL		b;
 	int32		i;
-	char ssl_estr[SSL_ESTR_LEN];
 	scfg_t *scfg;
 
 	if((p=(js_socket_private_t*)JS_GetPrivate(cx,obj))==NULL) {
@@ -1741,7 +1740,7 @@ static JSBool js_socket_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict
 										ret = CRYPT_ERROR_NOTAVAIL;
 									}
 									else {
-										get_ssl_cert(scfg, ssl_estr);
+										get_ssl_cert(scfg, NULL, NULL);
 										if (scfg->tls_certificate == -1)
 											ret = CRYPT_ERROR_NOTAVAIL;
 										else {
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index 3846877e9b..e37cbb7ed8 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -964,7 +964,7 @@ static void pop3_thread(void* arg)
 		lprintf(LOG_INFO,"%04d POP3 Hostname: %s", socket, host_name);
 
 	if (pop3.tls_port) {
-		if (get_ssl_cert(&scfg, NULL) == -1) {
+		if (get_ssl_cert(&scfg, NULL, NULL) == -1) {
 			lprintf(LOG_ERR, "%04d !POP3 [%s] Unable to get TLS certificate", socket, host_ip);
 			mail_close_socket(socket);
 			thread_down();
@@ -1094,11 +1094,11 @@ static void pop3_thread(void* arg)
 			else if (!stricmp(buf, "CAPA")) {
 				// Capabilities
 				sockprintf(socket,session, "+OK Capability list follows");
-				sockprintf(socket,session, "TOP\r\nUSER\r\nPIPELINING\r\nUIDL\r\nIMPLEMENTATION Synchronet POP3 Server %s-%s\r\n%s.", revision, PLATFORM_DESC, (session != -1 || get_ssl_cert(&scfg, NULL) == -1) ? "" : "STLS\r\n");
+				sockprintf(socket,session, "TOP\r\nUSER\r\nPIPELINING\r\nUIDL\r\nIMPLEMENTATION Synchronet POP3 Server %s-%s\r\n%s.", revision, PLATFORM_DESC, (session != -1 || get_ssl_cert(&scfg, NULL, NULL) == -1) ? "" : "STLS\r\n");
 				i++;
 			}
 			else if (!stricmp(buf, "STLS")) {
-				if (get_ssl_cert(&scfg, NULL) == -1) {
+				if (get_ssl_cert(&scfg, NULL, NULL) == -1) {
 					sockprintf(socket,session,"-ERR STLS command not supported");
 					continue;
 				}
@@ -2759,7 +2759,7 @@ static void smtp_thread(void* arg)
 	addr_len=sizeof(server_addr);
 
 	if(smtp.tls_port) {
-		if (get_ssl_cert(&scfg, NULL) == -1) {
+		if (get_ssl_cert(&scfg, NULL, NULL) == -1) {
 			lprintf(LOG_ERR, "%04d !SMTP Unable to get certificate", socket);
 			mail_close_socket(socket);
 			thread_down();
@@ -4657,7 +4657,7 @@ static void smtp_thread(void* arg)
 			continue;
 		}
 		if(session == -1 && !stricmp(buf,"STARTTLS")) {
-			if (get_ssl_cert(&scfg, NULL) == -1) {
+			if (get_ssl_cert(&scfg, NULL, NULL) == -1) {
 				lprintf(LOG_ERR, "%04d !SMTP Unable to get certificate", socket);
 				sockprintf(socket, session, "454 TLS not available");
 				continue;
@@ -5057,7 +5057,7 @@ static SOCKET sendmail_negotiate(CRYPT_SESSION *session, smb_t *smb, smbmsg_t *m
 			case 0:
 				return sock;
 			case 1:
-				if ((!tls_retry) && get_ssl_cert(&scfg, NULL) != -1) {
+				if ((!tls_retry) && get_ssl_cert(&scfg, NULL, NULL) != -1) {
 					sockprintf(sock, *session, "STARTTLS");
 					if (sockgetrsp(sock, *session, "220", buf, sizeof(buf))) {
 						if ((status=cryptCreateSession(session, CRYPT_UNUSED, CRYPT_SESSION_SSL)) != CRYPT_OK) {
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index 7c05cdd8ec..21faaf4cfc 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -1706,7 +1706,8 @@ void DLLCALL services_thread(void* arg)
 	ulong			total_sockets;
 	struct timeval	tv;
 	service_client_t* client;
-	char			ssl_estr[SSL_ESTR_LEN];
+	char			*ssl_estr;
+	int			level;
 	BOOL			need_cert = FALSE;
 
 	services_ver();
@@ -1909,9 +1910,8 @@ void DLLCALL services_thread(void* arg)
     		startup->started(startup->cbdata);
 
 		if (need_cert) {
-			get_ssl_cert(&scfg, ssl_estr);
-			if (scfg.tls_certificate == -1)
-				lprintf(LOG_ERR, "Error creating TLS certificate: %s", ssl_estr);
+			if (get_ssl_cert(&scfg, &ssl_estr, &level) == -1)
+				lprintf(level, "No TLS certificiate %s", ssl_estr);
 		}
 
 		lprintf(LOG_INFO,"0000 Services thread started (%u service sockets bound)", total_sockets);
diff --git a/src/sbbs3/ssl.c b/src/sbbs3/ssl.c
index 903e7d2e72..a3319ef2ba 100644
--- a/src/sbbs3/ssl.c
+++ b/src/sbbs3/ssl.c
@@ -19,7 +19,10 @@ char* DLLCALL get_crypt_attribute(CRYPT_HANDLE sess, C_IN CRYPT_ATTRIBUTE_TYPE a
 	if (cryptStatusOK(cryptGetAttributeString(sess, attr, NULL, &len))) {
 		estr = malloc(len + 1);
 		if (estr) {
-			cryptGetAttributeString(sess, attr, estr, &len);
+			if (cryptStatusError(cryptGetAttributeString(sess, attr, estr, &len))) {
+				free(estr);
+				return NULL;
+			}
 			estr[len] = 0;
 			return estr;
 		}
@@ -32,156 +35,188 @@ char* DLLCALL get_crypt_error(CRYPT_HANDLE sess)
 	return get_crypt_attribute(sess, CRYPT_ATTRIBUTE_ERRORMESSAGE);
 }
 
-bool DLLCALL get_crypt_error_string(int status, CRYPT_HANDLE sess, char estr[SSL_ESTR_LEN], const char *action)
+static int DLLCALL crypt_ll(int error)
+{
+	switch(error) {
+		case CRYPT_ERROR_INCOMPLETE:
+			return LOG_WARNING;
+		case CRYPT_ERROR_COMPLETE:
+		case CRYPT_ERROR_READ:
+		case CRYPT_ERROR_WRITE:
+			return LOG_DEBUG;
+		case CRYPT_ERROR_TIMEOUT:
+			return LOG_INFO;
+	}
+	return LOG_ERR;
+}
+
+static const char *crypt_lstr(int level)
+{
+	switch(level) {
+		case LOG_EMERG:
+			return "!ERROR";
+		case LOG_ALERT:
+			return "!ERROR";
+		case LOG_CRIT:
+			return "!ERROR";
+		case LOG_ERR:
+			return "ERROR";
+		case LOG_WARNING:
+			return "WARNING";
+		case LOG_NOTICE:
+			return "note";
+		case LOG_INFO:
+			return "info";
+		case LOG_DEBUG:
+			return "dbg";
+	}
+	return "!!!!!!!!";
+}
+
+bool DLLCALL get_crypt_error_string(int status, CRYPT_HANDLE sess, char **estr, const char *action, int *lvl)
 {
 	char	*emsg = NULL;
+	bool	allocated = false;
+	int	level;
 
 	if (cryptStatusOK(status))
 		return true;
 
+	level = crypt_ll(status);
+	if (lvl)
+		*lvl = level;
+
 	if (estr) {
 		if (sess != CRYPT_UNUSED)
 			emsg = get_crypt_error(sess);
+		if (emsg != NULL)
+			allocated = true;
 		if (emsg == NULL) {
 			switch(status) {
 				case CRYPT_ERROR_PARAM1:
-					emsg = strdup("Bad argument, parameter 1");
+					emsg = "Bad argument, parameter 1";
 					break;
 				case CRYPT_ERROR_PARAM2:
-					emsg = strdup("Bad argument, parameter 2");
+					emsg = "Bad argument, parameter 2";
 					break;
 				case CRYPT_ERROR_PARAM3:
-					emsg = strdup("Bad argument, parameter 3");
+					emsg = "Bad argument, parameter 3";
 					break;
 				case CRYPT_ERROR_PARAM4:
-					emsg = strdup("Bad argument, parameter 4");
+					emsg = "Bad argument, parameter 4";
 					break;
 				case CRYPT_ERROR_PARAM5:
-					emsg = strdup("Bad argument, parameter 5");
+					emsg = "Bad argument, parameter 5";
 					break;
 				case CRYPT_ERROR_PARAM6:
-					emsg = strdup("Bad argument, parameter 6");
+					emsg = "Bad argument, parameter 6";
 					break;
 				case CRYPT_ERROR_PARAM7:
-					emsg = strdup("Bad argument, parameter 7");
+					emsg = "Bad argument, parameter 7";
 					break;
 
 				/* Errors due to insufficient resources */
 
 				case CRYPT_ERROR_MEMORY:
-					emsg = strdup("Out of memory");
+					emsg = "Out of memory";
 					break;
 				case CRYPT_ERROR_NOTINITED:
-					emsg = strdup("Data has not been initialised");
+					emsg = "Data has not been initialised";
 					break;
 				case CRYPT_ERROR_INITED:
-					emsg = strdup("Data has already been init'd");
+					emsg = "Data has already been init'd";
 					break;
 				case CRYPT_ERROR_NOSECURE:
-					emsg = strdup("Opn.not avail.at requested sec.level");
+					emsg = "Opn.not avail.at requested sec.level";
 					break;
 				case CRYPT_ERROR_RANDOM:
-					emsg = strdup("No reliable random data available");
+					emsg = "No reliable random data available";
 					break;
 				case CRYPT_ERROR_FAILED:
-					emsg = strdup("Operation failed");
+					emsg = "Operation failed";
 					break;
 				case CRYPT_ERROR_INTERNAL:
-					emsg = strdup("Internal consistency check failed");
+					emsg = "Internal consistency check failed";
 					break;
 
 				/* Security violations */
 
 				case CRYPT_ERROR_NOTAVAIL:
-					emsg = strdup("This type of opn.not available");
+					emsg = "This type of opn.not available";
 					break;
 				case CRYPT_ERROR_PERMISSION:
-					emsg = strdup("No permiss.to perform this operation");
+					emsg = "No permiss.to perform this operation";
 					break;
 				case CRYPT_ERROR_WRONGKEY:
-					emsg = strdup("Incorrect key used to decrypt data");
+					emsg = "Incorrect key used to decrypt data";
 					break;
 				case CRYPT_ERROR_INCOMPLETE:
-					emsg = strdup("Operation incomplete/still in progress");
+					emsg = "Operation incomplete/still in progress";
 					break;
 				case CRYPT_ERROR_COMPLETE:
-					emsg = strdup("Operation complete/can't continue");
+					emsg = "Operation complete/can't continue";
 					break;
 				case CRYPT_ERROR_TIMEOUT:
-					emsg = strdup("Operation timed out before completion");
+					emsg = "Operation timed out before completion";
 					break;
 				case CRYPT_ERROR_INVALID:
-					emsg = strdup("Invalid/inconsistent information");
+					emsg = "Invalid/inconsistent information";
 					break;
 				case CRYPT_ERROR_SIGNALLED:
-					emsg = strdup("Resource destroyed by extnl.event");
+					emsg = "Resource destroyed by extnl.event";
 					break;
 
 				/* High-level function errors */
 
 				case CRYPT_ERROR_OVERFLOW:
-					emsg = strdup("Resources/space exhausted");
+					emsg = "Resources/space exhausted";
 					break;
 				case CRYPT_ERROR_UNDERFLOW:
-					emsg = strdup("Not enough data available");
+					emsg = "Not enough data available";
 					break;
 				case CRYPT_ERROR_BADDATA:
-					emsg = strdup("Bad/unrecognised data format");
+					emsg = "Bad/unrecognised data format";
 					break;
 				case CRYPT_ERROR_SIGNATURE:
-					emsg = strdup("Signature/integrity check failed");
+					emsg = "Signature/integrity check failed";
 					break;
 
 				/* Data access function errors */
 
 				case CRYPT_ERROR_OPEN:
-					emsg = strdup("Cannot open object");
+					emsg = "Cannot open object";
 					break;
 				case CRYPT_ERROR_READ:
-					emsg = strdup("Cannot read item from object");
+					emsg = "Cannot read item from object";
 					break;
 				case CRYPT_ERROR_WRITE:
-					emsg = strdup("Cannot write item to object");
+					emsg = "Cannot write item to object";
 					break;
 				case CRYPT_ERROR_NOTFOUND:
-					emsg = strdup("Requested item not found in object");
+					emsg = "Requested item not found in object";
 					break;
 				case CRYPT_ERROR_DUPLICATE:
-					emsg = strdup("Item already present in object");
+					emsg = "Item already present in object";
 					break;
 
 				/* Data enveloping errors */
 
 				case CRYPT_ENVELOPE_RESOURCE:
-					emsg = strdup("Need resource to proceed");
+					emsg = "Need resource to proceed";
 					break;
 			}
 		}
 		if (emsg) {
-			safe_snprintf(estr, SSL_ESTR_LEN, "'%s' (%d) %s", emsg, status, action);
-			free_crypt_attrstr(emsg);
+			asprintf(estr, "%s '%s' (%d) %s", crypt_lstr(level), emsg, status, action);
+			if (allocated)
+				free_crypt_attrstr(emsg);
 		}
 		else
-			safe_snprintf(estr, SSL_ESTR_LEN, "(%d) %s", status, action);
+			asprintf(estr, "%s (%d) %s", crypt_lstr(level), status, action);
 	}
 	return false;
 }
 
-int DLLCALL crypt_ll(int error)
-{
-	switch(error) {
-		case CRYPT_ERROR_INCOMPLETE:
-			return LOG_WARNING;
-		case CRYPT_ERROR_COMPLETE:
-		case CRYPT_ERROR_READ:
-		case CRYPT_ERROR_WRITE:
-			return LOG_DEBUG;
-		case CRYPT_ERROR_TIMEOUT:
-			return LOG_INFO;
-	}
-	return LOG_ERR;
-}
-
 static pthread_once_t crypt_init_once = PTHREAD_ONCE_INIT;
 static pthread_mutex_t ssl_cert_mutex;
 static bool cryptlib_initialized;
@@ -219,16 +254,16 @@ bool DLLCALL is_crypt_initialized(void)
 	return cryptlib_initialized;
 }
 
-#define DO(action, handle, x)	get_crypt_error_string(x, handle, estr, action)
+#define DO(action, handle, x)	get_crypt_error_string(x, handle, estr, action, level)
 
-CRYPT_CONTEXT DLLCALL get_ssl_cert(scfg_t *cfg, char estr[SSL_ESTR_LEN])
+CRYPT_CONTEXT DLLCALL get_ssl_cert(scfg_t *cfg, char **estr, int *level)
 {
 	CRYPT_KEYSET		ssl_keyset;
 	CRYPT_CONTEXT		ssl_context = -1;	// MSVC requires this to be initialized
 	CRYPT_CERTIFICATE	ssl_cert;
 	int					i;
 	char				sysop_email[sizeof(cfg->sys_inetaddr)+6];
-    char				str[MAX_PATH+1];
+	char				str[MAX_PATH+1];
 
 	if(!do_cryptInit())
 		return -1;
diff --git a/src/sbbs3/ssl.h b/src/sbbs3/ssl.h
index 344a779221..6e75dece29 100644
--- a/src/sbbs3/ssl.h
+++ b/src/sbbs3/ssl.h
@@ -37,11 +37,10 @@ extern "C" {
 DLLEXPORT void DLLCALL free_crypt_attrstr(char *attr);
 DLLEXPORT char* DLLCALL get_crypt_attribute(CRYPT_HANDLE sess, C_IN CRYPT_ATTRIBUTE_TYPE attr);
 DLLEXPORT char* DLLCALL get_crypt_error(CRYPT_HANDLE sess);
-DLLEXPORT CRYPT_CONTEXT DLLCALL get_ssl_cert(scfg_t *cfg, char estr[SSL_ESTR_LEN]);
+DLLEXPORT CRYPT_CONTEXT DLLCALL get_ssl_cert(scfg_t *cfg, char **estr, int *level);
 DLLEXPORT int DLLCALL do_cryptInit(void);
 DLLEXPORT bool DLLCALL is_crypt_initialized(void);
-DLLEXPORT bool DLLCALL get_crypt_error_string(int status, CRYPT_HANDLE sess, char estr[SSL_ESTR_LEN], const char *action);
-DLLEXPORT int DLLCALL crypt_ll(int error);
+DLLEXPORT bool DLLCALL get_crypt_error_string(int status, CRYPT_HANDLE sess, char **estr, const char *action, int *level);
 
 #if defined(__cplusplus)
 }
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 1baedc476b..af2e27c038 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -6654,7 +6654,8 @@ void DLLCALL web_server(void* arg)
 	char			compiler[32];
 	http_session_t *	session=NULL;
 	void			*acc_type;
-	char			ssl_estr[SSL_ESTR_LEN];
+	char			*ssl_estr;
+	int			level;
 
 	startup=(web_startup_t*)arg;
 
@@ -6787,9 +6788,12 @@ void DLLCALL web_server(void* arg)
 
 		if(startup->options&WEB_OPT_ALLOW_TLS) {
 			lprintf(LOG_DEBUG,"Loading/Creating TLS certificate");
-			get_ssl_cert(&scfg, ssl_estr);
-			if (scfg.tls_certificate == -1)
-				lprintf(LOG_ERR, "Error creating TLS certificate: %s", ssl_estr);
+			if (get_ssl_cert(&scfg, &ssl_estr, &level) == -1) {
+				if (ssl_estr) {
+					lprintf(level, "%s", ssl_estr);
+					free(ssl_estr);
+				}
+			}
 		}
 
 		iniFileName(mime_types_ini,sizeof(mime_types_ini),scfg.ctrl_dir,"mime_types.ini");
-- 
GitLab