Skip to content

Commit

Permalink
properly hanlde SSL shutdown for openssl 3.x, fixes #108
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabian Mauchle committed Jan 20, 2023
1 parent 6dc9d00 commit e6c7663
Showing 1 changed file with 50 additions and 41 deletions.
91 changes: 50 additions & 41 deletions tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,16 +249,16 @@ int sslreadtimeout(SSL *ssl, unsigned char *buf, int num, int timeout, pthread_m
if (ndesc < 0 || fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
if (fds[0].revents & POLLERR) {
if(!getsockopt(SSL_get_fd(ssl), SOL_SOCKET, SO_ERROR, (void *)&sockerr, &errlen))
debug(DBG_INFO, "TLS Connection lost: %s", strerror(sockerr));
debug(DBG_INFO, "sslreadtimeout: connection lost: %s", strerror(sockerr));
else
debug(DBG_INFO, "TLS Connection lost: unknown error");
debug(DBG_INFO, "sslreadtimeout: connection lost: unknown error");
} else if (fds[0].revents & POLLHUP) {
debug(DBG_INFO, "TLS Connection lost: hang up");
debug(DBG_INFO, "sslreadtimeout: connection lost: hang up");
} else if (fds[0].revents & POLLNVAL) {
debug(DBG_INFO, "TLS Connection error: fd not open");
debug(DBG_ERR, "sslreadtimeout: connection error: fd not open");
}

SSL_shutdown(ssl);
SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
pthread_mutex_unlock(lock);
return -1;
}
Expand All @@ -269,25 +269,29 @@ int sslreadtimeout(SSL *ssl, unsigned char *buf, int num, int timeout, pthread_m
switch (SSL_get_error(ssl, cnt)) {
case SSL_ERROR_WANT_WRITE:
want_write = 1;
/* fallthrough */
case SSL_ERROR_WANT_READ:
cnt = 0;
continue;
case SSL_ERROR_ZERO_RETURN:
debug(DBG_DBG, "sslreadtimeout: got ssl shutdown");
SSL_shutdown(ssl);
break;
case SSL_ERROR_SYSCALL:
debugerrno(errno, DBG_INFO, "sslreadtimeout: connection lost");
/* fallthrough */
default:
case SSL_ERROR_SSL:
while ((error = ERR_get_error()))
debug(DBG_ERR, "sslreadtimeout: SSL: %s", ERR_error_string(error, NULL));
if (cnt == 0)
debug(DBG_INFO, "sslreadtimeout: connection closed by remote host");
else {
debugerrno(errno, DBG_ERR, "sslreadtimeout: connection lost");
}
/* ensure ssl connection is shutdown */
SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
break;
default:
debug(DBG_ERR, "sslreadtimeout: uncaught SSL error");
SSL_shutdown(ssl);
pthread_mutex_unlock(lock);
return -1;
SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
}
pthread_mutex_unlock(lock);
return -1;
}
}
pthread_mutex_unlock(lock);
Expand Down Expand Up @@ -441,7 +445,7 @@ void *tlsserverwr(void *arg) {
for (;;) {
pthread_mutex_lock(&replyq->mutex);
while (!list_first(replyq->entries)) {
if (client->ssl) {
if (!SSL_get_shutdown(client->ssl)) {
debug(DBG_DBG, "tlsserverwr: waiting for signal");
pthread_cond_wait(&replyq->cond, &replyq->mutex);
debug(DBG_DBG, "tlsserverwr: got signal");
Expand All @@ -453,12 +457,11 @@ void *tlsserverwr(void *arg) {
pthread_mutex_unlock(&replyq->mutex);

pthread_mutex_lock(&client->lock);
if (!client->ssl) {
/* ssl might have changed while waiting */
if (SSL_get_shutdown(client->ssl)) {
if (reply)
freerq(reply);
pthread_mutex_unlock(&client->lock);
debug(DBG_DBG, "tlsserverwr: exiting as requested");
debug(DBG_DBG, "tlsserverwr: ssl connection shutdown; exiting as requested");
pthread_exit(NULL);
}

Expand All @@ -480,34 +483,40 @@ void tlsserverrd(struct client *client) {
debug(DBG_DBG, "tlsserverrd: starting for %s", addr2string(client->addr, tmp, sizeof(tmp)));

if (pthread_create(&tlsserverwrth, &pthread_attr, tlsserverwr, (void *)client)) {
debug(DBG_ERR, "tlsserverrd: pthread_create failed");
return;
debug(DBG_ERR, "tlsserverrd: pthread_create failed");
return;
}

for (;;) {
buf = radtlsget(client->ssl, IDLE_TIMEOUT * 3, &client->lock);
if (!buf) {
debug(DBG_ERR, "tlsserverrd: connection from %s lost", addr2string(client->addr, tmp, sizeof(tmp)));
break;
}
debug(DBG_DBG, "tlsserverrd: got Radius message from %s", addr2string(client->addr, tmp, sizeof(tmp)));
rq = newrequest();
if (!rq) {
free(buf);
continue;
}
rq->buf = buf;
rq->from = client;
if (!radsrv(rq)) {
debug(DBG_ERR, "tlsserverrd: message authentication/validation failed, closing connection from %s", addr2string(client->addr, tmp, sizeof(tmp)));
break;
}
buf = radtlsget(client->ssl, IDLE_TIMEOUT * 3, &client->lock);
if (!buf) {
pthread_mutex_lock(&client->lock);
if (SSL_get_shutdown(client->ssl))
debug(DBG_ERR, "tlsserverrd: connection from %s, client %s lost", addr2string(client->addr, tmp, sizeof(tmp)), client->conf->name);
else {
debug(DBG_WARN, "tlsserverrd: timeout from %s, client %s (no requests), closing connection", addr2string(client->addr, tmp, sizeof(tmp)), client->conf->name);
SSL_shutdown(client->ssl);
}
/* ensure shutdown state is set so tlsserverwr knows it can exit*/
SSL_set_shutdown(client->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
pthread_mutex_unlock(&client->lock);
break;
}
debug(DBG_DBG, "tlsserverrd: got Radius message from %s", addr2string(client->addr, tmp, sizeof(tmp)));
rq = newrequest();
if (!rq) {
free(buf);
continue;
}
rq->buf = buf;
rq->from = client;
if (!radsrv(rq)) {
debug(DBG_ERR, "tlsserverrd: message authentication/validation failed, closing connection from %s", addr2string(client->addr, tmp, sizeof(tmp)));
break;
}
}

/* stop writer by setting ssl to NULL and give signal in case waiting for data */
pthread_mutex_lock(&client->lock);
client->ssl = NULL;
pthread_mutex_unlock(&client->lock);
/* signal writer so it can finish (based on SSL_shutdown) */
pthread_mutex_lock(&client->replyq->mutex);
pthread_cond_signal(&client->replyq->cond);
pthread_mutex_unlock(&client->replyq->mutex);
Expand Down

0 comments on commit e6c7663

Please sign in to comment.