summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/serve.c31
-rw-r--r--src/tls.c11
2 files changed, 41 insertions, 1 deletions
diff --git a/src/serve.c b/src/serve.c
index 4b63dde..d77c2ff 100644
--- a/src/serve.c
+++ b/src/serve.c
@@ -199,7 +199,36 @@ serve_cgi(struct gmnisrv_client *client, const char *path,
setenv("TLS_CIPHER", SSL_CIPHER_get_name(cipher), 1);
setenv("TLS_VERSION", SSL_CIPHER_get_version(cipher), 1);
- // TODO: Client certificate details
+ // barebones client cert implementation
+ // adapted from openssl(1)'s implementation
+ // TODO: support REMOTE_USER, TLS_CLIENT_NOT_{BEFORE,AFTER},
+ // TLS_CLIENT_SERIAL_NUMBER
+ X509 *client_cert = SSL_get_peer_certificate(client->ssl);
+ if (client_cert != NULL) {
+ // 32 bytes because we're always using SHA256, but
+ // possibly change to EVP_MAX_MD_SIZE to support all
+ // of openssl's hash funcs
+ unsigned char digest[32];
+
+ if (X509_digest(client_cert, EVP_sha256(), digest, NULL)) {
+ setenv("AUTH_TYPE", "CERTIFICATE", 1);
+ // 32*2 because converting to hex doubles length
+ // +7 for "SHA256:" prefix
+ // +1 for null char
+ char hex_digest[32*2 + 7 + 1];
+ strncat(hex_digest, "SHA256:", 8);
+
+ char *cur_pos = hex_digest + 7;
+ for (int i = 0; i < 32; ++i) {
+ cur_pos += sprintf(cur_pos, "%02X", digest[i]);
+ }
+ setenv("TLS_CLIENT_HASH", hex_digest, 1);
+ } else {
+ const char *error = "Out of memory";
+ client_submit_response(client,
+ GEMINI_STATUS_TEMPORARY_FAILURE, error, NULL);
+ }
+ }
execlp(path, path, NULL);
server_error("execlp: %s", strerror(errno));
diff --git a/src/tls.c b/src/tls.c
index 26785a0..284cbef 100644
--- a/src/tls.c
+++ b/src/tls.c
@@ -15,6 +15,14 @@
#include "util.h"
static int
+always_true_callback(X509_STORE_CTX *ctx, void *arg)
+{
+ (void)(ctx);
+ (void)(arg);
+ return 1;
+}
+
+static int
tls_host_gencert(struct gmnisrv_tls *tlsconf, struct gmnisrv_host *host,
const char *crtpath, const char *keypath)
{
@@ -185,6 +193,9 @@ tls_init(struct gmnisrv_config *conf)
assert(r == 1);
SSL_CTX_set_tlsext_servername_callback(conf->tls.ssl_ctx, NULL);
+ SSL_CTX_set_verify(conf->tls.ssl_ctx, SSL_VERIFY_PEER, NULL);
+ // use always_true_callback to ignore errors such as self-signed error
+ SSL_CTX_set_cert_verify_callback(conf->tls.ssl_ctx, always_true_callback, NULL);
// TLS re-negotiation is a fucking STUPID idea
// I'm gating this behind an #ifdef based on an optimistic assumption