Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

Commit 211a2a1a authored by deuce's avatar deuce

There appears to be data corruption in cryptlib if a private key is added

to a second thread before the first has the session set active.  Add calls
to lock/unlock the certificate to prevent this.

The better options is likely to have a function that adds the key and socket
and sets the session active in one call and handles the locking internally.

But I'm lazy, so we get the lock functions.
parent cb205ec3
......@@ -2000,7 +2000,9 @@ static BOOL start_tls(SOCKET *sock, CRYPT_SESSION *sess, BOOL resp)
sockprintf(*sock, *sess, "431 TLS not available");
return FALSE;
}
lock_ssl_cert();
if ((status=cryptSetAttribute(*sess, CRYPT_SESSINFO_PRIVATEKEY, scfg.tls_certificate)) != CRYPT_OK) {
unlock_ssl_cert();
GCES(status, *sock, *sess, estr, "setting private key");
cryptDestroySession(*sess);
*sess = -1;
......@@ -2013,6 +2015,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) {
unlock_ssl_cert();
GCES(status, *sock, *sess, estr, "setting network socket");
cryptDestroySession(*sess);
*sess = -1;
......@@ -2023,9 +2026,11 @@ 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) {
unlock_ssl_cert();
GCES(status, *sock, *sess, estr, "setting session active");
return TRUE;
}
unlock_ssl_cert();
if (startup->max_inactivity) {
if ((status = cryptSetAttribute(*sess, CRYPT_OPTION_NET_READTIMEOUT, startup->max_inactivity)) != CRYPT_OK) {
GCES(status, *sock, *sess, estr, "setting read timeout");
......
......@@ -1866,15 +1866,20 @@ static JSBool js_socket_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict
if (scfg->tls_certificate == -1)
ret = CRYPT_ERROR_NOTAVAIL;
else {
lock_ssl_cert();
ret = cryptSetAttribute(p->session, CRYPT_SESSINFO_PRIVATEKEY, scfg->tls_certificate);
if (ret != CRYPT_OK)
if (ret != CRYPT_OK) {
unlock_ssl_cert();
GCES(ret, p, estr, "setting private key");
}
}
}
}
if(ret==CRYPT_OK) {
if((ret=do_cryptAttribute(p->session, CRYPT_SESSINFO_ACTIVE, 1))!=CRYPT_OK)
GCES(ret, p, estr, "setting session active");
if (tiny == SOCK_PROP_SSL_SERVER)
unlock_ssl_cert();
}
}
}
......
......@@ -1027,7 +1027,9 @@ static void pop3_thread(void* arg)
thread_down();
return;
}
lock_ssl_cert();
if ((stat=cryptSetAttribute(session, CRYPT_SESSINFO_PRIVATEKEY, scfg.tls_certificate)) != CRYPT_OK) {
unlock_ssl_cert();
GCESH(stat, client.protocol, socket, host_ip, session, "setting private key");
mail_close_socket(&socket, &session);
thread_down();
......@@ -1038,17 +1040,20 @@ static void pop3_thread(void* arg)
nb=0;
ioctlsocket(socket,FIONBIO,&nb);
if ((stat = cryptSetAttribute(session, CRYPT_SESSINFO_NETWORKSOCKET, socket)) != CRYPT_OK) {
unlock_ssl_cert();
GCESH(stat, client.protocol, socket, host_ip, session, "setting session socket");
mail_close_socket(&socket, &session);
thread_down();
return;
}
if ((stat = cryptSetAttribute(session, CRYPT_SESSINFO_ACTIVE, 1)) != CRYPT_OK) {
unlock_ssl_cert();
GCESH(stat, client.protocol, socket, host_ip, session, "setting session active");
mail_close_socket(&socket, &session);
thread_down();
return;
}
unlock_ssl_cert();
if (startup->max_inactivity) {
if (cryptSetAttribute(session, CRYPT_OPTION_NET_READTIMEOUT, startup->max_inactivity) != CRYPT_OK) {
GCESH(stat, client.protocol, socket, host_ip, session, "setting read timeout");
......@@ -1157,7 +1162,9 @@ static void pop3_thread(void* arg)
buf[0] = 0;
break;
}
lock_ssl_cert();
if ((stat=cryptSetAttribute(session, CRYPT_SESSINFO_PRIVATEKEY, scfg.tls_certificate)) != CRYPT_OK) {
unlock_ssl_cert();
GCESH(stat, client.protocol, socket, host_ip, session, "setting private key");
buf[0] = 0;
break;
......@@ -1167,15 +1174,18 @@ static void pop3_thread(void* arg)
nb=0;
ioctlsocket(socket,FIONBIO,&nb);
if ((stat = cryptSetAttribute(session, CRYPT_SESSINFO_NETWORKSOCKET, socket)) != CRYPT_OK) {
unlock_ssl_cert();
GCESH(stat, client.protocol, socket, host_ip, session, "setting network socket");
buf[0] = 0;
break;
}
if ((stat=cryptSetAttribute(session, CRYPT_SESSINFO_ACTIVE, 1)) != CRYPT_OK) {
unlock_ssl_cert();
GCESH(stat, client.protocol, socket, host_ip, session, "setting session active");
buf[0] = 0;
break;
}
unlock_ssl_cert();
if (startup->max_inactivity) {
if ((stat=cryptSetAttribute(session, CRYPT_OPTION_NET_READTIMEOUT, startup->max_inactivity)) != CRYPT_OK) {
GCESH(stat, client.protocol, socket, host_ip, session, "setting read timeout");
......@@ -2830,7 +2840,9 @@ static void smtp_thread(void* arg)
thread_down();
return;
}
lock_ssl_cert();
if ((cstat = cryptSetAttribute(session, CRYPT_SESSINFO_PRIVATEKEY, scfg.tls_certificate)) != CRYPT_OK) {
unlock_ssl_cert();
GCES(cstat, client.protocol, socket, CRYPT_UNUSED, "setting private key");
mail_close_socket(&socket, &session);
thread_down();
......@@ -2841,17 +2853,20 @@ static void smtp_thread(void* arg)
nb=0;
ioctlsocket(socket,FIONBIO,&nb);
if ((cstat = cryptSetAttribute(session, CRYPT_SESSINFO_NETWORKSOCKET, socket)) != CRYPT_OK) {
unlock_ssl_cert();
GCES(cstat, client.protocol, socket, CRYPT_UNUSED, "setting network socket");
mail_close_socket(&socket, &session);
thread_down();
return;
}
if ((cstat = cryptSetAttribute(session, CRYPT_SESSINFO_ACTIVE, 1)) != CRYPT_OK) {
unlock_ssl_cert();
GCES(cstat, client.protocol, socket, CRYPT_UNUSED, "setting session active");
mail_close_socket(&socket, &session);
thread_down();
return;
}
unlock_ssl_cert();
if (startup->max_inactivity) {
if ((cstat = cryptSetAttribute(session, CRYPT_OPTION_NET_READTIMEOUT, startup->max_inactivity)) != CRYPT_OK) {
GCES(cstat, client.protocol, socket, CRYPT_UNUSED, "setting read timeout");
......@@ -4724,7 +4739,9 @@ static void smtp_thread(void* arg)
sockprintf(socket, client.protocol, session, "454 TLS not available");
continue;
}
lock_ssl_cert();
if ((cstat=cryptSetAttribute(session, CRYPT_SESSINFO_PRIVATEKEY, scfg.tls_certificate)) != CRYPT_OK) {
unlock_ssl_cert();
GCES(cstat, "SMTPS", socket, session, "setting private key");
lprintf(LOG_ERR, "%04d !SMTP Unable to set private key", socket);
cryptDestroySession(session);
......@@ -4737,6 +4754,7 @@ static void smtp_thread(void* arg)
nb=0;
ioctlsocket(socket,FIONBIO,&nb);
if ((cstat = cryptSetAttribute(session, CRYPT_SESSINFO_NETWORKSOCKET, socket)) != CRYPT_OK) {
unlock_ssl_cert();
GCES(cstat, "SMTPS", socket, session, "setting network socket");
cryptDestroySession(session);
session = -1;
......@@ -4745,9 +4763,11 @@ static void smtp_thread(void* arg)
}
sockprintf(socket, client.protocol, -1, "220 Ready to start TLS");
if ((cstat=cryptSetAttribute(session, CRYPT_SESSINFO_ACTIVE, 1)) != CRYPT_OK) {
unlock_ssl_cert();
GCES(cstat, "SMTPS", socket, session, "setting session active");
break;
}
unlock_ssl_cert();
if (startup->max_inactivity) {
if ((cstat=cryptSetAttribute(session, CRYPT_OPTION_NET_READTIMEOUT, startup->max_inactivity)) != CRYPT_OK) {
GCES(cstat, "SMTPS", socket, session, "setting read timeout");
......@@ -5126,7 +5146,9 @@ static SOCKET sendmail_negotiate(CRYPT_SESSION *session, smb_t *smb, smbmsg_t *m
GCESH(status, prot, sock, server, *session, "setting certificate compliance level");
continue;
}
lock_ssl_cert();
if ((status=cryptSetAttribute(*session, CRYPT_SESSINFO_PRIVATEKEY, scfg.tls_certificate)) != CRYPT_OK) {
unlock_ssl_cert();
GCESH(status, prot, sock, server, *session, "setting private key");
continue;
}
......@@ -5135,13 +5157,16 @@ static SOCKET sendmail_negotiate(CRYPT_SESSION *session, smb_t *smb, smbmsg_t *m
nb=0;
ioctlsocket(sock,FIONBIO,&nb);
if ((status=cryptSetAttribute(*session, CRYPT_SESSINFO_NETWORKSOCKET, sock)) != CRYPT_OK) {
unlock_ssl_cert();
GCESH(status, prot, sock, server, *session, "setting network socket");
continue;
}
if ((status=cryptSetAttribute(*session, CRYPT_SESSINFO_ACTIVE, 1)) != CRYPT_OK) {
unlock_ssl_cert();
GCESH(status, prot, sock, server, *session, "setting session active");
continue;
}
unlock_ssl_cert();
if (startup->max_inactivity) {
if ((status=cryptSetAttribute(*session, CRYPT_OPTION_NET_READTIMEOUT, startup->max_inactivity)) != CRYPT_OK) {
GCESH(status, prot, sock, server, *session, "setting read timeout");
......
......@@ -1043,6 +1043,7 @@ static void js_service_thread(void* arg)
}
}
#endif
lock_ssl_cert();
if (scfg.tls_certificate != -1) {
HANDLE_CRYPT_CALL(cryptSetAttribute(service_client.tls_sess, CRYPT_SESSINFO_PRIVATEKEY, scfg.tls_certificate), &service_client, "setting private key");
}
......@@ -1051,11 +1052,13 @@ static void js_service_thread(void* arg)
HANDLE_CRYPT_CALL(cryptSetAttribute(service_client.tls_sess, CRYPT_SESSINFO_NETWORKSOCKET, socket), &service_client, "setting network socket");
if (!HANDLE_CRYPT_CALL(cryptSetAttribute(service_client.tls_sess, CRYPT_SESSINFO_ACTIVE, 1), &service_client, "setting session active")) {
unlock_ssl_cert();
if (service_client.tls_sess != -1)
cryptDestroySession(service_client.tls_sess);
js_service_failure_cleanup(service, socket);
return;
}
unlock_ssl_cert();
}
#if 0 /* Need to export from SBBS.DLL */
......
......@@ -264,6 +264,16 @@ bool DLLCALL is_crypt_initialized(void)
return cryptlib_initialized;
}
void lock_ssl_cert(void)
{
pthread_mutex_lock(&ssl_cert_mutex);
}
void unlock_ssl_cert(void)
{
pthread_mutex_unlock(&ssl_cert_mutex);
}
#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, int *level)
......
......@@ -41,6 +41,8 @@ DLLEXPORT CRYPT_CONTEXT DLLCALL get_ssl_cert(scfg_t *cfg, char **estr, int *leve
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, const char *action, int *level);
DLLEXPORT void lock_ssl_cert(void);
DLLEXPORT void unlock_ssl_cert(void);
#if defined(__cplusplus)
}
......
......@@ -6248,6 +6248,7 @@ void http_session_thread(void* arg)
}
}
#endif
lock_ssl_cert();
if (scfg.tls_certificate != -1) {
HANDLE_CRYPT_CALL(cryptSetAttribute(session.tls_sess, CRYPT_SESSINFO_SSL_OPTIONS, CRYPT_SSLOPTION_DISABLE_CERTVERIFY), &session, "disabling certificate verification");
HANDLE_CRYPT_CALL(cryptSetAttribute(session.tls_sess, CRYPT_SESSINFO_PRIVATEKEY, scfg.tls_certificate), &session, "setting private key");
......@@ -6257,10 +6258,12 @@ void http_session_thread(void* arg)
HANDLE_CRYPT_CALL(cryptSetAttribute(session.tls_sess, CRYPT_SESSINFO_NETWORKSOCKET, session.socket), &session, "setting network socket");
if (!HANDLE_CRYPT_CALL(cryptSetAttribute(session.tls_sess, CRYPT_SESSINFO_ACTIVE, 1), &session, "setting session active")) {
unlock_ssl_cert();
close_session_no_rb(&session);
thread_down();
return;
}
unlock_ssl_cert();
HANDLE_CRYPT_CALL(cryptSetAttribute(session.tls_sess, CRYPT_OPTION_NET_READTIMEOUT, 0), &session, "setting read timeout");
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment