diff options
| author | Gab Virebent <gab@virebent.art> | 2026-06-26 19:20:00 +0200 |
|---|---|---|
| committer | Gab Virebent <gab@virebent.art> | 2026-06-26 19:20:00 +0200 |
| commit | fb48d1308d2f63f8e9b23c5d1d921783fa0dacbe (patch) | |
| tree | ceecce2f057cd4ea1e6724305fcd52915939c419 /src/server.c | |
| parent | 41c4bfecc770ea7c914e845e4ac3792cb4a473d3 (diff) | |
| download | gmnisrv-main.tar.gz gmnisrv-main.tar.xz gmnisrv-main.zip | |
- tls.c/config.h: read full PEM chain into STACK_OF(X509), send via SSL_set1_chain
- tls.c: minimum protocol TLS 1.2 -> TLS 1.3
- server.c: drain handshake output via local buffer loop instead of staging
into the fixed 4 KB client buffer (a full CA chain overflowed it -> assert)
- FORK.md: describe the fork
Diffstat (limited to 'src/server.c')
| -rw-r--r-- | src/server.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/src/server.c b/src/server.c index 359300a..022aa3d 100644 --- a/src/server.c +++ b/src/server.c @@ -376,28 +376,34 @@ client_readable(struct gmnisrv_server *server, struct gmnisrv_client *client) return CONNECTED; queue_ssl_write: - client->bufln = 0; - client->state = CLIENT_STATE_SSL; - client->next = CLIENT_STATE_REQUEST; + // Flush all pending TLS output (e.g. the ServerHello/Certificate + // handshake flight) directly to the socket, draining the write BIO via + // a local buffer in a loop. A full CA certificate chain can exceed + // sizeof(client->buf), so it must not be staged into the fixed-size + // client buffer (that overflowed and aborted on assert). do { - assert(client->bufln < sizeof(client->buf)); - r = BIO_read(client->wbio, - &client->buf[client->bufln], - sizeof(client->buf) - client->bufln); - if (r <= 0) { - if (BIO_should_retry(client->wbio)) { - continue; - } + r = BIO_read(client->wbio, buf, sizeof(buf)); + if (r < 0 && !BIO_should_retry(client->wbio)) { client_error(&client->addr, "BIO read error: %s", ERR_error_string(r, NULL)); disconnect_client(server, client); return DISCONNECTED; - } else { - client->bufln += r; - client->pollfd->events = POLLOUT; + } + for (int ww = 0; ww < r; ) { + int q = write(client->sockfd, &buf[ww], r - ww); + if (q < 0) { + client_error(&client->addr, + "client write: %s", + strerror(errno)); + disconnect_client(server, client); + return DISCONNECTED; + } + ww += q; } } while (r > 0); + client->state = CLIENT_STATE_REQUEST; + client->pollfd->events = POLLIN; return CONNECTED; } |
