mirror of
https://git.sr.ht/~sircmpwn/gmnisrv
synced 2025-02-02 15:08:11 -05:00
Overhaul network I/O to be async for real
Had to totally cut off OpenSSL from the network fd because obviously OpenSSL is just going to wreck our shit
This commit is contained in:
parent
a22bec5149
commit
1fe107875b
@ -10,9 +10,11 @@
|
|||||||
|
|
||||||
struct gmnisrv_server;
|
struct gmnisrv_server;
|
||||||
|
|
||||||
enum response_state {
|
enum client_state {
|
||||||
RESPOND_HEADER,
|
CLIENT_STATE_REQUEST,
|
||||||
RESPOND_BODY,
|
CLIENT_STATE_SSL,
|
||||||
|
CLIENT_STATE_HEADER,
|
||||||
|
CLIENT_STATE_BODY,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gmnisrv_client {
|
struct gmnisrv_client {
|
||||||
@ -24,13 +26,12 @@ struct gmnisrv_client {
|
|||||||
struct pollfd *pollfd;
|
struct pollfd *pollfd;
|
||||||
|
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
BIO *bio, *sbio;
|
BIO *rbio, *wbio;
|
||||||
|
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
static_assert(GEMINI_MAX_URL + 3 < 4096, "GEMINI_MAX_URL is too high");
|
|
||||||
size_t bufix, bufln;
|
size_t bufix, bufln;
|
||||||
|
|
||||||
enum response_state state;
|
enum client_state state, next;
|
||||||
enum gemini_status status;
|
enum gemini_status status;
|
||||||
char *meta;
|
char *meta;
|
||||||
FILE *body;
|
FILE *body;
|
||||||
|
@ -5,7 +5,7 @@ struct gmnisrv_config;
|
|||||||
|
|
||||||
int tls_init(struct gmnisrv_config *conf);
|
int tls_init(struct gmnisrv_config *conf);
|
||||||
void tls_finish(struct gmnisrv_config *conf);
|
void tls_finish(struct gmnisrv_config *conf);
|
||||||
SSL *tls_get_ssl(struct gmnisrv_config *conf, int fd);
|
SSL *tls_get_ssl(struct gmnisrv_config *conf);
|
||||||
void tls_set_host(SSL *ssl, struct gmnisrv_host *host);
|
void tls_set_host(SSL *ssl, struct gmnisrv_host *host);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,6 +18,7 @@ void
|
|||||||
client_submit_response(struct gmnisrv_client *client,
|
client_submit_response(struct gmnisrv_client *client,
|
||||||
enum gemini_status status, const char *meta, FILE *body)
|
enum gemini_status status, const char *meta, FILE *body)
|
||||||
{
|
{
|
||||||
|
client->state = CLIENT_STATE_HEADER;
|
||||||
client->status = status;
|
client->status = status;
|
||||||
client->meta = strdup(meta);
|
client->meta = strdup(meta);
|
||||||
client->body = body;
|
client->body = body;
|
||||||
|
314
src/server.c
314
src/server.c
@ -186,9 +186,6 @@ disconnect_client(struct gmnisrv_server *server, struct gmnisrv_client *client)
|
|||||||
client->path ? client->path : "(none)",
|
client->path ? client->path : "(none)",
|
||||||
ms, client->bbytes, (int)client->status, client->meta);
|
ms, client->bbytes, (int)client->status, client->meta);
|
||||||
}
|
}
|
||||||
if (client->bio) {
|
|
||||||
BIO_free_all(client->bio);
|
|
||||||
}
|
|
||||||
if (client->ssl) {
|
if (client->ssl) {
|
||||||
SSL_free(client->ssl);
|
SSL_free(client->ssl);
|
||||||
}
|
}
|
||||||
@ -211,7 +208,7 @@ disconnect_client(struct gmnisrv_server *server, struct gmnisrv_client *client)
|
|||||||
static int
|
static int
|
||||||
client_init_ssl(struct gmnisrv_server *server, struct gmnisrv_client *client)
|
client_init_ssl(struct gmnisrv_server *server, struct gmnisrv_client *client)
|
||||||
{
|
{
|
||||||
client->ssl = tls_get_ssl(server->conf, client->sockfd);
|
client->ssl = tls_get_ssl(server->conf);
|
||||||
if (!client->ssl) {
|
if (!client->ssl) {
|
||||||
client_error(&client->addr,
|
client_error(&client->addr,
|
||||||
"unable to initialize SSL, disconnecting");
|
"unable to initialize SSL, disconnecting");
|
||||||
@ -219,151 +216,280 @@ client_init_ssl(struct gmnisrv_server *server, struct gmnisrv_client *client)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int r = SSL_accept(client->ssl);
|
client->rbio = BIO_new(BIO_s_mem());
|
||||||
if (r != 1) {
|
client->wbio = BIO_new(BIO_s_mem());
|
||||||
r = SSL_get_error(client->ssl, r);
|
|
||||||
if (r == SSL_ERROR_WANT_READ || r == SSL_ERROR_WANT_WRITE) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
client_error(&client->addr, "SSL accept error %s, disconnecting",
|
|
||||||
ERR_error_string(r, NULL));
|
|
||||||
disconnect_client(server, client);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
client->sbio = BIO_new(BIO_f_ssl());
|
SSL_set_accept_state(client->ssl);
|
||||||
BIO_set_ssl(client->sbio, client->ssl, 0);
|
SSL_set_bio(client->ssl, client->rbio, client->wbio);
|
||||||
client->bio = BIO_new(BIO_f_buffer());
|
|
||||||
BIO_push(client->bio, client->sbio);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum client_state {
|
enum connection_state {
|
||||||
CLIENT_CONNECTED,
|
CONNECTED,
|
||||||
CLIENT_DISCONNECTED,
|
DISCONNECTED,
|
||||||
};
|
};
|
||||||
|
|
||||||
static enum client_state
|
static enum connection_state
|
||||||
client_readable(struct gmnisrv_server *server, struct gmnisrv_client *client)
|
client_readable(struct gmnisrv_server *server, struct gmnisrv_client *client)
|
||||||
{
|
{
|
||||||
if (!client->ssl && client_init_ssl(server, client) != 0) {
|
if (!client->ssl && client_init_ssl(server, client) != 0) {
|
||||||
return CLIENT_DISCONNECTED;
|
return DISCONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
ssize_t n = read(client->sockfd, buf, sizeof(buf));
|
||||||
|
if (n <= 0) {
|
||||||
|
disconnect_client(server, client);
|
||||||
|
return DISCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t w = 0;
|
||||||
|
while (w < (size_t)n) {
|
||||||
|
int r = BIO_write(client->rbio, &buf[w], n - w);
|
||||||
|
if (r <= 0) {
|
||||||
|
client_error(&client->addr,
|
||||||
|
"Error writing to client RBIO: %s",
|
||||||
|
ERR_error_string(r, NULL));
|
||||||
|
disconnect_client(server, client);
|
||||||
|
return DISCONNECTED;
|
||||||
|
}
|
||||||
|
w += r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SSL_is_init_finished(client->ssl)) {
|
||||||
|
int r = SSL_accept(client->ssl);
|
||||||
|
switch ((r = SSL_get_error(client->ssl, r))) {
|
||||||
|
case SSL_ERROR_NONE:
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
goto queue_ssl_write;
|
||||||
|
case SSL_ERROR_SSL:
|
||||||
|
client_error(&client->addr,
|
||||||
|
"SSL accept error: %s",
|
||||||
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
disconnect_client(server, client);
|
||||||
|
return DISCONNECTED;
|
||||||
|
default:
|
||||||
|
client_error(&client->addr,
|
||||||
|
"SSL accept error: %s",
|
||||||
|
ERR_error_string(r, NULL));
|
||||||
|
disconnect_client(server, client);
|
||||||
|
return DISCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SSL_is_init_finished(client->ssl)) {
|
||||||
|
return CONNECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!client->host) {
|
if (!client->host) {
|
||||||
|
client_log(&client->addr, "missing client host");
|
||||||
const char *error = "This server requires clients to support the TLS SNI (server name identification) extension";
|
const char *error = "This server requires clients to support the TLS SNI (server name identification) extension";
|
||||||
client_submit_response(client,
|
client_submit_response(client,
|
||||||
GEMINI_STATUS_BAD_REQUEST, error, NULL);
|
GEMINI_STATUS_BAD_REQUEST, error, NULL);
|
||||||
return CLIENT_CONNECTED;
|
return CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int r = BIO_gets(client->bio, client->buf, sizeof(client->buf));
|
int r, e;
|
||||||
if (r <= 0) {
|
do {
|
||||||
r = SSL_get_error(client->ssl, r);
|
if (client->bufln >= sizeof(client->buf)) {
|
||||||
if (r == SSL_ERROR_WANT_READ) {
|
client_log(&client->addr, "overlong");
|
||||||
return CLIENT_CONNECTED;
|
const char *error = "Protocol error: malformed request";
|
||||||
|
client_submit_response(client,
|
||||||
|
GEMINI_STATUS_BAD_REQUEST, error, NULL);
|
||||||
|
return CONNECTED;
|
||||||
}
|
}
|
||||||
client_error(&client->addr, "SSL read error %s, disconnecting",
|
|
||||||
ERR_error_string(r, NULL));
|
r = SSL_read(client->ssl,
|
||||||
disconnect_client(server, client);
|
&client->buf[client->bufln],
|
||||||
return CLIENT_DISCONNECTED;
|
sizeof(client->buf) - client->bufln);
|
||||||
}
|
|
||||||
client->buf[r] = '\0';
|
switch ((e = SSL_get_error(client->ssl, r))) {
|
||||||
|
case SSL_ERROR_NONE:
|
||||||
|
client->bufln += r;
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
break;
|
||||||
|
case SSL_ERROR_SSL:
|
||||||
|
client_error(&client->addr,
|
||||||
|
"SSL read error: %s",
|
||||||
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
disconnect_client(server, client);
|
||||||
|
return DISCONNECTED;
|
||||||
|
default:
|
||||||
|
client_error(&client->addr,
|
||||||
|
"SSL read error: %s",
|
||||||
|
ERR_error_string(e, NULL));
|
||||||
|
disconnect_client(server, client);
|
||||||
|
return DISCONNECTED;
|
||||||
|
}
|
||||||
|
} while (r > 0);
|
||||||
|
|
||||||
|
client->buf[client->bufln] = '\0';
|
||||||
|
|
||||||
char *newline = strstr(client->buf, "\r\n");
|
char *newline = strstr(client->buf, "\r\n");
|
||||||
if (!newline) {
|
if (!newline) {
|
||||||
const char *error = "Protocol error: malformed request";
|
const char *error = "Protocol error: malformed request";
|
||||||
client_submit_response(client,
|
switch (e) {
|
||||||
GEMINI_STATUS_BAD_REQUEST, error, NULL);
|
case SSL_ERROR_WANT_READ:
|
||||||
return CLIENT_CONNECTED;
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
goto queue_ssl_write;
|
||||||
|
default:
|
||||||
|
client_submit_response(client,
|
||||||
|
GEMINI_STATUS_BAD_REQUEST, error, NULL);
|
||||||
|
return CONNECTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*newline = 0;
|
*newline = 0;
|
||||||
|
|
||||||
if (!request_validate(client, &client->path)) {
|
if (!request_validate(client, &client->path)) {
|
||||||
return CLIENT_CONNECTED;
|
return CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
serve_request(client);
|
serve_request(client);
|
||||||
return CLIENT_CONNECTED;
|
return CONNECTED;
|
||||||
|
|
||||||
|
queue_ssl_write:
|
||||||
|
client->bufln = 0;
|
||||||
|
client->state = CLIENT_STATE_SSL;
|
||||||
|
client->next = CLIENT_STATE_REQUEST;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
client_error(&client->addr,
|
||||||
|
"BIO read error: %s",
|
||||||
|
ERR_error_string(r, NULL));
|
||||||
|
disconnect_client(server, client);
|
||||||
|
return DISCONNECTED;
|
||||||
|
} else {
|
||||||
|
client->bufln += r;
|
||||||
|
}
|
||||||
|
} while (r > 0);
|
||||||
|
client->pollfd->events = POLLOUT;
|
||||||
|
return CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum client_state
|
static enum connection_state
|
||||||
client_writable(struct gmnisrv_server *server, struct gmnisrv_client *client)
|
client_writable(struct gmnisrv_server *server, struct gmnisrv_client *client)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
char buf[BUFSIZ];
|
||||||
switch (client->state) {
|
switch (client->state) {
|
||||||
case RESPOND_HEADER:
|
case CLIENT_STATE_REQUEST:
|
||||||
|
assert(0); // Invariant
|
||||||
|
case CLIENT_STATE_SSL:
|
||||||
|
assert(client->bufln > 0);
|
||||||
|
n = write(client->sockfd, client->buf, client->bufln);
|
||||||
|
if (n <= 0) {
|
||||||
|
client_log(&client->addr, "write error: %s",
|
||||||
|
strerror(errno));
|
||||||
|
disconnect_client(server, client);
|
||||||
|
return DISCONNECTED;
|
||||||
|
}
|
||||||
|
client->bufln -= n;
|
||||||
|
if (client->bufln == 0) {
|
||||||
|
client->state = client->next;
|
||||||
|
if (client->state == CLIENT_STATE_REQUEST) {
|
||||||
|
client->pollfd->events = POLLIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CONNECTED;
|
||||||
|
case CLIENT_STATE_HEADER:
|
||||||
if (client->bufix == 0) {
|
if (client->bufix == 0) {
|
||||||
assert(strlen(client->meta) <= 1024);
|
assert(strlen(client->meta) <= 1024);
|
||||||
n = snprintf(client->buf, sizeof(client->buf),
|
int n = snprintf(client->buf, sizeof(client->buf),
|
||||||
"%02d %s\r\n", (int)client->status,
|
"%02d %s\r\n", (int)client->status,
|
||||||
client->meta);
|
client->meta);
|
||||||
assert(n > 0);
|
assert(n > 0);
|
||||||
client->bufln = n;
|
client->bufln = n;
|
||||||
}
|
}
|
||||||
r = BIO_write(client->sbio, &client->buf[client->bufix],
|
|
||||||
client->bufln - client->bufix);
|
|
||||||
if (r <= 0) {
|
|
||||||
r = SSL_get_error(client->ssl, r);
|
|
||||||
if (r == SSL_ERROR_WANT_WRITE) {
|
|
||||||
return CLIENT_CONNECTED;
|
|
||||||
}
|
|
||||||
client->status = GEMINI_STATUS_NONE;
|
|
||||||
client_error(&client->addr,
|
|
||||||
"header write error %s, disconnecting",
|
|
||||||
ERR_error_string(r, NULL));
|
|
||||||
disconnect_client(server, client);
|
|
||||||
return CLIENT_DISCONNECTED;
|
|
||||||
}
|
|
||||||
client->bufix += r;
|
|
||||||
if (client->bufix >= client->bufln) {
|
|
||||||
if (!client->body) {
|
|
||||||
disconnect_client(server, client);
|
|
||||||
return CLIENT_DISCONNECTED;
|
|
||||||
} else {
|
|
||||||
client->state = RESPOND_BODY;
|
|
||||||
client->bufix = client->bufln = 0;
|
|
||||||
return CLIENT_CONNECTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case RESPOND_BODY:
|
case CLIENT_STATE_BODY:
|
||||||
if (client->bufix >= client->bufln) {
|
if (client->bufix >= client->bufln) {
|
||||||
n = fread(client->buf, 1, sizeof(client->buf),
|
int n = fread(client->buf, 1,
|
||||||
client->body);
|
sizeof(client->buf), client->body);
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
client_error(&client->addr,
|
client_error(&client->addr,
|
||||||
"Error reading response body: %s",
|
"Error reading response body: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
disconnect_client(server, client);
|
disconnect_client(server, client);
|
||||||
return CLIENT_DISCONNECTED;
|
return DISCONNECTED;
|
||||||
}
|
}
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
// EOF
|
// EOF
|
||||||
disconnect_client(server, client);
|
disconnect_client(server, client);
|
||||||
return CLIENT_DISCONNECTED;
|
return DISCONNECTED;
|
||||||
}
|
}
|
||||||
client->bbytes += n;
|
client->bbytes += n;
|
||||||
client->bufln = n;
|
client->bufln = n;
|
||||||
client->bufix = 0;
|
client->bufix = 0;
|
||||||
}
|
}
|
||||||
r = BIO_write(client->sbio, &client->buf[client->bufix],
|
|
||||||
client->bufln - client->bufix);
|
|
||||||
if (r <= 0) {
|
|
||||||
r = SSL_get_error(client->ssl, r);
|
|
||||||
if (r == SSL_ERROR_WANT_WRITE) {
|
|
||||||
return CLIENT_CONNECTED;
|
|
||||||
}
|
|
||||||
client->status = GEMINI_STATUS_NONE;
|
|
||||||
client_error(&client->addr, "body write error %s, disconnecting",
|
|
||||||
ERR_error_string(r, NULL));
|
|
||||||
disconnect_client(server, client);
|
|
||||||
return CLIENT_DISCONNECTED;
|
|
||||||
}
|
|
||||||
client->bufix += r;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
r = SSL_write(client->ssl, &client->buf[client->bufix],
|
||||||
|
client->bufln - client->bufix);
|
||||||
|
if (r <= 0) {
|
||||||
|
r = SSL_get_error(client->ssl, r);
|
||||||
|
assert(r == SSL_ERROR_WANT_WRITE); // Hmm?
|
||||||
|
client->status = GEMINI_STATUS_NONE;
|
||||||
|
client_error(&client->addr,
|
||||||
|
"header write error %s, disconnecting",
|
||||||
|
ERR_error_string(r, NULL));
|
||||||
|
disconnect_client(server, client);
|
||||||
|
return DISCONNECTED;
|
||||||
|
}
|
||||||
|
client->bufix += r;
|
||||||
|
|
||||||
|
while (r > 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int w = 0; w < r; ) {
|
||||||
|
int q = write(client->sockfd, &buf[w], r - w);
|
||||||
|
if (q < 0) {
|
||||||
|
assert(0); // TODO: handle write errors
|
||||||
|
}
|
||||||
|
w += q;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (client->state) {
|
||||||
|
case CLIENT_STATE_REQUEST:
|
||||||
|
case CLIENT_STATE_SSL:
|
||||||
|
assert(0); // Invariant
|
||||||
|
case CLIENT_STATE_HEADER:
|
||||||
|
if (client->bufix >= client->bufln) {
|
||||||
|
if (!client->body) {
|
||||||
|
disconnect_client(server, client);
|
||||||
|
return DISCONNECTED;
|
||||||
|
} else {
|
||||||
|
client->state = CLIENT_STATE_BODY;
|
||||||
|
client->bufix = client->bufln = 0;
|
||||||
|
return CONNECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CLIENT_STATE_BODY:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static long
|
||||||
@ -450,18 +576,18 @@ server_run(struct gmnisrv_server *server)
|
|||||||
|
|
||||||
for (size_t i = 0; i < server->nclients; ++i) {
|
for (size_t i = 0; i < server->nclients; ++i) {
|
||||||
int pi = i + server->nlisten;
|
int pi = i + server->nlisten;
|
||||||
enum client_state s = CLIENT_CONNECTED;
|
enum connection_state s = CONNECTED;
|
||||||
if ((server->fds[pi].revents & (POLLHUP | POLLERR))) {
|
if ((server->fds[pi].revents & (POLLHUP | POLLERR))) {
|
||||||
disconnect_client(server, &server->clients[i]);
|
disconnect_client(server, &server->clients[i]);
|
||||||
s = CLIENT_DISCONNECTED;
|
s = DISCONNECTED;
|
||||||
}
|
}
|
||||||
if (s == CLIENT_CONNECTED && (server->fds[pi].revents & POLLIN)) {
|
if (s == CONNECTED && (server->fds[pi].revents & POLLIN)) {
|
||||||
s = client_readable(server, &server->clients[i]);
|
s = client_readable(server, &server->clients[i]);
|
||||||
}
|
}
|
||||||
if (s == CLIENT_CONNECTED && (server->fds[pi].revents & POLLOUT)) {
|
if (s == CONNECTED && (server->fds[pi].revents & POLLOUT)) {
|
||||||
s = client_writable(server, &server->clients[i]);
|
s = client_writable(server, &server->clients[i]);
|
||||||
}
|
}
|
||||||
if (s == CLIENT_DISCONNECTED) {
|
if (s == DISCONNECTED) {
|
||||||
--i;
|
--i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
src/tls.c
33
src/tls.c
@ -161,12 +161,31 @@ tls_init(struct gmnisrv_config *conf)
|
|||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
ERR_load_crypto_strings();
|
ERR_load_crypto_strings();
|
||||||
|
|
||||||
conf->tls.ssl_ctx = SSL_CTX_new(TLS_method());
|
conf->tls.ssl_ctx = SSL_CTX_new(TLS_server_method());
|
||||||
assert(conf->tls.ssl_ctx);
|
assert(conf->tls.ssl_ctx);
|
||||||
|
|
||||||
|
int r = SSL_CTX_set_min_proto_version(conf->tls.ssl_ctx, TLS1_2_VERSION);
|
||||||
|
assert(r == 1);
|
||||||
|
|
||||||
|
r = SSL_CTX_set_cipher_list(conf->tls.ssl_ctx,
|
||||||
|
"ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:"
|
||||||
|
"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:"
|
||||||
|
"ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:"
|
||||||
|
"DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:"
|
||||||
|
"TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:"
|
||||||
|
"TLS_CHACHA20_POLY1305_SHA256");
|
||||||
|
assert(r == 1);
|
||||||
|
|
||||||
SSL_CTX_set_tlsext_servername_callback(conf->tls.ssl_ctx, NULL);
|
SSL_CTX_set_tlsext_servername_callback(conf->tls.ssl_ctx, NULL);
|
||||||
|
|
||||||
int r;
|
// TLS re-negotiation is a fucking STUPID idea
|
||||||
|
// I'm gating this behind an #ifdef based on an optimistic assumption
|
||||||
|
// that someday it will be removed from OpenSSL entirely because of how
|
||||||
|
// fucking stupid this fucking godawful idea is
|
||||||
|
#ifdef SSL_OP_NO_RENEGOTIATION
|
||||||
|
SSL_CTX_set_options(conf->tls.ssl_ctx, SSL_OP_NO_RENEGOTIATION);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (struct gmnisrv_host *host = conf->hosts; host; host = host->next) {
|
for (struct gmnisrv_host *host = conf->hosts; host; host = host->next) {
|
||||||
r = tls_host_init(&conf->tls, host);
|
r = tls_host_init(&conf->tls, host);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
@ -188,15 +207,9 @@ tls_finish(struct gmnisrv_config *conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SSL *
|
SSL *
|
||||||
tls_get_ssl(struct gmnisrv_config *conf, int fd)
|
tls_get_ssl(struct gmnisrv_config *conf)
|
||||||
{
|
{
|
||||||
SSL *ssl = SSL_new(conf->tls.ssl_ctx);
|
return SSL_new(conf->tls.ssl_ctx);
|
||||||
if (!ssl) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
int r = SSL_set_fd(ssl, fd);
|
|
||||||
assert(r == 1);
|
|
||||||
return ssl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
x
Reference in New Issue
Block a user