forked from mirrors/kore
more progress
This commit is contained in:
parent
bfcc4afe48
commit
1a9197ffeb
|
@ -119,6 +119,9 @@ extern int daemon(int, int);
|
||||||
|
|
||||||
#define X509_CN_LENGTH (ub_common_name + 1)
|
#define X509_CN_LENGTH (ub_common_name + 1)
|
||||||
|
|
||||||
|
#define KORE_PEM_CERT_CHAIN 1
|
||||||
|
#define KORE_DER_CERT_DATA 2
|
||||||
|
|
||||||
/* XXX hackish. */
|
/* XXX hackish. */
|
||||||
#if !defined(KORE_NO_HTTP)
|
#if !defined(KORE_NO_HTTP)
|
||||||
struct http_request;
|
struct http_request;
|
||||||
|
@ -636,15 +639,13 @@ struct kore_msg {
|
||||||
|
|
||||||
struct kore_keyreq {
|
struct kore_keyreq {
|
||||||
int padding;
|
int padding;
|
||||||
char domain[KORE_DOMAINNAME_LEN];
|
char domain[KORE_DOMAINNAME_LEN + 1];
|
||||||
u_int16_t domain_len;
|
|
||||||
u_int16_t data_len;
|
u_int16_t data_len;
|
||||||
u_int8_t data[];
|
u_int8_t data[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kore_x509_msg {
|
struct kore_x509_msg {
|
||||||
char domain[KORE_DOMAINNAME_LEN];
|
char domain[KORE_DOMAINNAME_LEN + 1];
|
||||||
u_int16_t domain_len;
|
|
||||||
size_t data_len;
|
size_t data_len;
|
||||||
u_int8_t data[];
|
u_int8_t data[];
|
||||||
};
|
};
|
||||||
|
@ -898,7 +899,8 @@ void kore_domain_load_crl(void);
|
||||||
void kore_domain_keymgr_init(void);
|
void kore_domain_keymgr_init(void);
|
||||||
void kore_domain_callback(void (*cb)(struct kore_domain *));
|
void kore_domain_callback(void (*cb)(struct kore_domain *));
|
||||||
int kore_domain_attach(struct kore_domain *, struct kore_server *);
|
int kore_domain_attach(struct kore_domain *, struct kore_server *);
|
||||||
void kore_domain_tlsinit(struct kore_domain *, const void *, size_t);
|
void kore_domain_tlsinit(struct kore_domain *, int,
|
||||||
|
const void *, size_t);
|
||||||
void kore_domain_crl_add(struct kore_domain *, const void *, size_t);
|
void kore_domain_crl_add(struct kore_domain *, const void *, size_t);
|
||||||
#if !defined(KORE_NO_HTTP)
|
#if !defined(KORE_NO_HTTP)
|
||||||
int kore_module_handler_new(struct kore_domain *, const char *,
|
int kore_module_handler_new(struct kore_domain *, const char *,
|
||||||
|
|
61
src/acme.c
61
src/acme.c
|
@ -21,6 +21,8 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -129,6 +131,7 @@ static void acme_request_json(struct kore_buf *, const char *,
|
||||||
const char *, const char *);
|
const char *, const char *);
|
||||||
|
|
||||||
static char *acme_nonce_fetch(void);
|
static char *acme_nonce_fetch(void);
|
||||||
|
static char *acme_thumbprint_component(void);
|
||||||
static char *acme_protected_component(const char *, const char *);
|
static char *acme_protected_component(const char *, const char *);
|
||||||
|
|
||||||
static void acme_parse_directory(void);
|
static void acme_parse_directory(void);
|
||||||
|
@ -290,7 +293,7 @@ kore_acme_tls_alpn(SSL *ssl, const unsigned char **out, unsigned char *outlen,
|
||||||
*out = in;
|
*out = in;
|
||||||
*outlen = inlen;
|
*outlen = inlen;
|
||||||
|
|
||||||
printf("tls-alpn-01 selected\n");
|
kore_acme_tls_challenge_use_cert(ssl, dom);
|
||||||
|
|
||||||
return (SSL_TLSEXT_ERR_OK);
|
return (SSL_TLSEXT_ERR_OK);
|
||||||
}
|
}
|
||||||
|
@ -1064,9 +1067,11 @@ static void
|
||||||
acme_challenge_tls_alpn_01_create(struct acme_order *order,
|
acme_challenge_tls_alpn_01_create(struct acme_order *order,
|
||||||
struct acme_challenge *challenge)
|
struct acme_challenge *challenge)
|
||||||
{
|
{
|
||||||
struct kore_buf buf;
|
|
||||||
struct kore_keyreq kreq;
|
struct kore_keyreq kreq;
|
||||||
|
char *thumb;
|
||||||
|
struct kore_buf buf, auth;
|
||||||
size_t len, token_len;
|
size_t len, token_len;
|
||||||
|
u_int8_t digest[SHA256_DIGEST_LENGTH];
|
||||||
|
|
||||||
if (challenge->flags & ACME_FLAG_CHALLENGE_CREATED) {
|
if (challenge->flags & ACME_FLAG_CHALLENGE_CREATED) {
|
||||||
kore_log(LOG_NOTICE,
|
kore_log(LOG_NOTICE,
|
||||||
|
@ -1089,21 +1094,31 @@ acme_challenge_tls_alpn_01_create(struct acme_order *order,
|
||||||
if (token_len > ACME_CHALLENGE_TOKEN_MAXLEN)
|
if (token_len > ACME_CHALLENGE_TOKEN_MAXLEN)
|
||||||
fatal("token exceeds length limit");
|
fatal("token exceeds length limit");
|
||||||
|
|
||||||
kore_buf_init(&buf, sizeof(kreq) + len);
|
thumb = acme_thumbprint_component();
|
||||||
|
|
||||||
|
kore_buf_init(&auth, 128);
|
||||||
|
kore_buf_appendf(&auth, "%s.%s", challenge->token, thumb);
|
||||||
|
(void)SHA256(auth.data, auth.offset, digest);
|
||||||
|
|
||||||
|
kore_buf_init(&buf, sizeof(kreq) + sizeof(digest));
|
||||||
|
|
||||||
memset(&kreq, 0, sizeof(kreq));
|
memset(&kreq, 0, sizeof(kreq));
|
||||||
kreq.domain_len = len;
|
kreq.data_len = sizeof(digest);
|
||||||
kreq.data_len = token_len;
|
|
||||||
memcpy(kreq.domain, order->domain, kreq.domain_len);
|
if (kore_strlcpy(kreq.domain, order->domain, sizeof(kreq.domain)) >=
|
||||||
|
sizeof(kreq.domain))
|
||||||
|
fatal("%s: domain truncated", __func__);
|
||||||
|
|
||||||
kore_buf_append(&buf, &kreq, sizeof(kreq));
|
kore_buf_append(&buf, &kreq, sizeof(kreq));
|
||||||
kore_buf_append(&buf, challenge->token, token_len);
|
kore_buf_append(&buf, digest, sizeof(digest));
|
||||||
|
|
||||||
kore_msg_send(KORE_WORKER_KEYMGR, KORE_ACME_CHALLENGE_CERT,
|
kore_msg_send(KORE_WORKER_KEYMGR, KORE_ACME_CHALLENGE_CERT,
|
||||||
buf.data, buf.offset);
|
buf.data, buf.offset);
|
||||||
acme_challenge_respond(order, challenge->url, "tls-alpn-01");
|
acme_challenge_respond(order, challenge->url, "tls-alpn-01");
|
||||||
|
|
||||||
|
kore_buf_cleanup(&auth);
|
||||||
kore_buf_cleanup(&buf);
|
kore_buf_cleanup(&buf);
|
||||||
|
kore_free(thumb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1348,7 +1363,7 @@ acme_protected_component(const char *nonce, const char *url)
|
||||||
struct kore_buf payload;
|
struct kore_buf payload;
|
||||||
struct kore_json_item *root, *jwk;
|
struct kore_json_item *root, *jwk;
|
||||||
|
|
||||||
root = kore_json_create_item(NULL, NULL, KORE_JSON_TYPE_OBJECT);
|
root = kore_json_create_object(NULL, NULL);
|
||||||
|
|
||||||
kore_json_create_string(root, "url", url);
|
kore_json_create_string(root, "url", url);
|
||||||
kore_json_create_string(root, "alg", "RS256");
|
kore_json_create_string(root, "alg", "RS256");
|
||||||
|
@ -1376,6 +1391,36 @@ acme_protected_component(const char *nonce, const char *url)
|
||||||
return (b64);
|
return (b64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
acme_thumbprint_component(void)
|
||||||
|
{
|
||||||
|
char *b64;
|
||||||
|
struct kore_json_item *json;
|
||||||
|
struct kore_buf payload;
|
||||||
|
u_int8_t digest[SHA256_DIGEST_LENGTH];
|
||||||
|
|
||||||
|
json = kore_json_create_object(NULL, NULL);
|
||||||
|
|
||||||
|
/* Order matters here, see RFC7638. */
|
||||||
|
kore_json_create_string(json, "e", rsakey_e);
|
||||||
|
kore_json_create_string(json, "kty", "RSA");
|
||||||
|
kore_json_create_string(json, "n", rsakey_n);
|
||||||
|
|
||||||
|
kore_buf_init(&payload, 128);
|
||||||
|
kore_json_item_tobuf(json, &payload);
|
||||||
|
|
||||||
|
(void)SHA256(payload.data, payload.offset, digest);
|
||||||
|
|
||||||
|
kore_json_item_free(json);
|
||||||
|
kore_buf_cleanup(&payload);
|
||||||
|
|
||||||
|
if (!kore_base64url_encode(digest,
|
||||||
|
sizeof(digest), &b64, KORE_BASE64_RAW))
|
||||||
|
fatal("failed to convert thumbprint JSON to b64");
|
||||||
|
|
||||||
|
return (b64);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
acme_status_type(const char *status)
|
acme_status_type(const char *status)
|
||||||
{
|
{
|
||||||
|
|
12
src/config.c
12
src/config.c
|
@ -869,11 +869,7 @@ configure_certfile(char *path)
|
||||||
return (KORE_RESULT_ERROR);
|
return (KORE_RESULT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_domain->certfile != NULL) {
|
kore_free(current_domain->certfile);
|
||||||
printf("certfile already set for %s\n", current_domain->domain);
|
|
||||||
return (KORE_RESULT_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
current_domain->certfile = kore_strdup(path);
|
current_domain->certfile = kore_strdup(path);
|
||||||
return (KORE_RESULT_OK);
|
return (KORE_RESULT_OK);
|
||||||
}
|
}
|
||||||
|
@ -886,11 +882,7 @@ configure_certkey(char *path)
|
||||||
return (KORE_RESULT_ERROR);
|
return (KORE_RESULT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_domain->certkey != NULL) {
|
kore_free(current_domain->certkey);
|
||||||
printf("certkey already set for %s\n", current_domain->domain);
|
|
||||||
return (KORE_RESULT_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
current_domain->certkey = kore_strdup(path);
|
current_domain->certkey = kore_strdup(path);
|
||||||
return (KORE_RESULT_OK);
|
return (KORE_RESULT_OK);
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,8 +271,12 @@ kore_connection_handle(struct connection *c)
|
||||||
|
|
||||||
SSL_set_fd(c->ssl, c->fd);
|
SSL_set_fd(c->ssl, c->fd);
|
||||||
SSL_set_accept_state(c->ssl);
|
SSL_set_accept_state(c->ssl);
|
||||||
SSL_set_app_data(c->ssl, c);
|
|
||||||
SSL_set_ex_data(c->ssl, 0, c);
|
if (!SSL_set_ex_data(c->ssl, 0, c)) {
|
||||||
|
kore_debug("SSL_set_ex_data(): %s",
|
||||||
|
ssl_errno_s);
|
||||||
|
return (KORE_RESULT_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
46
src/domain.c
46
src/domain.c
|
@ -263,8 +263,10 @@ kore_domain_free(struct kore_domain *dom)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
kore_domain_tlsinit(struct kore_domain *dom, const void *pem, size_t pemlen)
|
kore_domain_tlsinit(struct kore_domain *dom, int type,
|
||||||
|
const void *data, size_t datalen)
|
||||||
{
|
{
|
||||||
|
const u_int8_t *ptr;
|
||||||
RSA *rsa;
|
RSA *rsa;
|
||||||
X509 *x509;
|
X509 *x509;
|
||||||
EVP_PKEY *pkey;
|
EVP_PKEY *pkey;
|
||||||
|
@ -336,7 +338,22 @@ kore_domain_tlsinit(struct kore_domain *dom, const void *pem, size_t pemlen)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
x509 = domain_load_certificate_chain(dom->ssl_ctx, pem, pemlen);
|
switch (type) {
|
||||||
|
case KORE_PEM_CERT_CHAIN:
|
||||||
|
x509 = domain_load_certificate_chain(dom->ssl_ctx,
|
||||||
|
data, datalen);
|
||||||
|
break;
|
||||||
|
case KORE_DER_CERT_DATA:
|
||||||
|
ptr = data;
|
||||||
|
if ((x509 = d2i_X509(NULL, &ptr, datalen)) == NULL)
|
||||||
|
fatalx("d2i_X509: %s", ssl_errno_s);
|
||||||
|
if (SSL_CTX_use_certificate(dom->ssl_ctx, x509) == 0)
|
||||||
|
fatalx("SSL_CTX_use_certificate: %s", ssl_errno_s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatalx("%s: unknown type %d", __func__, type);
|
||||||
|
}
|
||||||
|
|
||||||
if ((pkey = X509_get_pubkey(x509)) == NULL)
|
if ((pkey = X509_get_pubkey(x509)) == NULL)
|
||||||
fatalx("certificate has no public key");
|
fatalx("certificate has no public key");
|
||||||
|
|
||||||
|
@ -369,8 +386,10 @@ kore_domain_tlsinit(struct kore_domain *dom, const void *pem, size_t pemlen)
|
||||||
if (!SSL_CTX_use_PrivateKey(dom->ssl_ctx, pkey))
|
if (!SSL_CTX_use_PrivateKey(dom->ssl_ctx, pkey))
|
||||||
fatalx("SSL_CTX_use_PrivateKey(): %s", ssl_errno_s);
|
fatalx("SSL_CTX_use_PrivateKey(): %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!SSL_CTX_check_private_key(dom->ssl_ctx))
|
if (!SSL_CTX_check_private_key(dom->ssl_ctx)) {
|
||||||
fatalx("Public/Private key for %s do not match", dom->domain);
|
fatalx("Public/Private key for %s do not match (%s)",
|
||||||
|
dom->domain, ssl_errno_s);
|
||||||
|
}
|
||||||
|
|
||||||
if (tls_dhparam == NULL)
|
if (tls_dhparam == NULL)
|
||||||
fatalx("No DH parameters given");
|
fatalx("No DH parameters given");
|
||||||
|
@ -610,18 +629,18 @@ keymgr_rsa_privenc(int flen, const unsigned char *from, unsigned char *to,
|
||||||
|
|
||||||
if ((dom = RSA_get_app_data(rsa)) == NULL)
|
if ((dom = RSA_get_app_data(rsa)) == NULL)
|
||||||
fatal("RSA key has no domain attached");
|
fatal("RSA key has no domain attached");
|
||||||
if (strlen(dom->domain) >= KORE_DOMAINNAME_LEN - 1)
|
|
||||||
fatal("domain name too long");
|
|
||||||
|
|
||||||
memset(keymgr_buf, 0, sizeof(keymgr_buf));
|
memset(keymgr_buf, 0, sizeof(keymgr_buf));
|
||||||
|
|
||||||
req = (struct kore_keyreq *)keymgr_buf;
|
req = (struct kore_keyreq *)keymgr_buf;
|
||||||
|
|
||||||
|
if (kore_strlcpy(req->domain, dom->domain, sizeof(req->domain)) >=
|
||||||
|
sizeof(req->domain))
|
||||||
|
fatal("%s: domain truncated", __func__);
|
||||||
|
|
||||||
req->data_len = flen;
|
req->data_len = flen;
|
||||||
req->padding = padding;
|
req->padding = padding;
|
||||||
req->domain_len = strlen(dom->domain);
|
|
||||||
|
|
||||||
memcpy(&req->data[0], from, req->data_len);
|
memcpy(&req->data[0], from, req->data_len);
|
||||||
memcpy(req->domain, dom->domain, req->domain_len);
|
|
||||||
|
|
||||||
kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
|
kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
|
||||||
keymgr_await_data();
|
keymgr_await_data();
|
||||||
|
@ -674,13 +693,14 @@ keymgr_ecdsa_sign(const unsigned char *dgst, int dgst_len,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(keymgr_buf, 0, sizeof(keymgr_buf));
|
memset(keymgr_buf, 0, sizeof(keymgr_buf));
|
||||||
|
|
||||||
req = (struct kore_keyreq *)keymgr_buf;
|
req = (struct kore_keyreq *)keymgr_buf;
|
||||||
req->data_len = dgst_len;
|
|
||||||
req->domain_len = strlen(dom->domain);
|
|
||||||
|
|
||||||
|
if (kore_strlcpy(req->domain, dom->domain, sizeof(req->domain)) >=
|
||||||
|
sizeof(req->domain))
|
||||||
|
fatal("%s: domain truncated", __func__);
|
||||||
|
|
||||||
|
req->data_len = dgst_len;
|
||||||
memcpy(&req->data[0], dgst, req->data_len);
|
memcpy(&req->data[0], dgst, req->data_len);
|
||||||
memcpy(req->domain, dom->domain, req->domain_len);
|
|
||||||
|
|
||||||
kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
|
kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
|
||||||
keymgr_await_data();
|
keymgr_await_data();
|
||||||
|
|
215
src/keymgr.c
215
src/keymgr.c
|
@ -42,6 +42,7 @@
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include <openssl/x509v3.h>
|
#include <openssl/x509v3.h>
|
||||||
|
|
||||||
|
@ -62,6 +63,11 @@
|
||||||
#define RAND_POLL_INTERVAL (1800 * 1000)
|
#define RAND_POLL_INTERVAL (1800 * 1000)
|
||||||
#define RAND_FILE_SIZE 1024
|
#define RAND_FILE_SIZE 1024
|
||||||
|
|
||||||
|
#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x3000000fL
|
||||||
|
#undef OPENSSL_VERSION_NUMBER
|
||||||
|
#define OPENSSL_VERSION_NUMBER 0x10100000L
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#include "seccomp.h"
|
#include "seccomp.h"
|
||||||
|
|
||||||
|
@ -146,6 +152,7 @@ static void keymgr_acme_domainkey(struct kore_domain *, struct key *);
|
||||||
static void keymgr_acme_order_create(const char *);
|
static void keymgr_acme_order_create(const char *);
|
||||||
static void keymgr_acme_order_status(void *, u_int64_t);
|
static void keymgr_acme_order_status(void *, u_int64_t);
|
||||||
|
|
||||||
|
static void keymgr_x509_ext(X509 *, int, const char *, ...);
|
||||||
static void keymgr_acme_challenge_cert(const void *, size_t, struct key *);
|
static void keymgr_acme_challenge_cert(const void *, size_t, struct key *);
|
||||||
|
|
||||||
#endif /* KORE_USE_ACME */
|
#endif /* KORE_USE_ACME */
|
||||||
|
@ -180,7 +187,7 @@ kore_keymgr_run(void)
|
||||||
u_int64_t now, netwait, last_seed;
|
u_int64_t now, netwait, last_seed;
|
||||||
|
|
||||||
if (keymgr_active == 0)
|
if (keymgr_active == 0)
|
||||||
fatal("%s: called with keymgr_active == 0", __func__);
|
fatalx("%s: called with keymgr_active == 0", __func__);
|
||||||
|
|
||||||
quit = 0;
|
quit = 0;
|
||||||
|
|
||||||
|
@ -226,7 +233,7 @@ kore_keymgr_run(void)
|
||||||
|
|
||||||
#if defined(__OpenBSD__)
|
#if defined(__OpenBSD__)
|
||||||
if (pledge("stdio rpath", NULL) == -1)
|
if (pledge("stdio rpath", NULL) == -1)
|
||||||
fatal("failed to pledge keymgr process");
|
fatalx("failed to pledge keymgr process");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (quit != 1) {
|
while (quit != 1) {
|
||||||
|
@ -326,14 +333,13 @@ keymgr_submit_certificates(struct kore_domain *dom, u_int16_t dst)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
fatal("cannot read '%s' for %s: %s",
|
fatalx("cannot read '%s' for %s: %s",
|
||||||
dom->certfile, dom->domain, errno_s);
|
dom->certfile, dom->domain, errno_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dom->certfile != NULL) {
|
keymgr_acme_order_create(dom->domain);
|
||||||
keymgr_submit_file(KORE_MSG_CERTIFICATE,
|
printf("sending %s\n", dom->certfile);
|
||||||
dom, dom->certfile, dst, 0);
|
keymgr_submit_file(KORE_MSG_CERTIFICATE, dom, dom->certfile, dst, 0);
|
||||||
}
|
|
||||||
|
|
||||||
if (dom->crlfile != NULL)
|
if (dom->crlfile != NULL)
|
||||||
keymgr_submit_file(KORE_MSG_CRL, dom, dom->crlfile, dst, 1);
|
keymgr_submit_file(KORE_MSG_CRL, dom, dom->crlfile, dst, 1);
|
||||||
|
@ -353,17 +359,17 @@ keymgr_submit_file(u_int8_t id, struct kore_domain *dom,
|
||||||
if ((fd = open(file, O_RDONLY)) == -1) {
|
if ((fd = open(file, O_RDONLY)) == -1) {
|
||||||
if (errno == ENOENT && can_fail)
|
if (errno == ENOENT && can_fail)
|
||||||
return;
|
return;
|
||||||
fatal("open(%s): %s", file, errno_s);
|
fatalx("open(%s): %s", file, errno_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fstat(fd, &st) == -1)
|
if (fstat(fd, &st) == -1)
|
||||||
fatal("stat(%s): %s", file, errno_s);
|
fatalx("stat(%s): %s", file, errno_s);
|
||||||
|
|
||||||
if (!S_ISREG(st.st_mode))
|
if (!S_ISREG(st.st_mode))
|
||||||
fatal("%s is not a file", file);
|
fatalx("%s is not a file", file);
|
||||||
|
|
||||||
if (st.st_size <= 0 || st.st_size > (1024 * 1024 * 10)) {
|
if (st.st_size <= 0 || st.st_size > (1024 * 1024 * 10)) {
|
||||||
fatal("%s length is not valid (%jd)", file,
|
fatalx("%s length is not valid (%jd)", file,
|
||||||
(intmax_t)st.st_size);
|
(intmax_t)st.st_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,20 +377,20 @@ keymgr_submit_file(u_int8_t id, struct kore_domain *dom,
|
||||||
payload = kore_calloc(1, len);
|
payload = kore_calloc(1, len);
|
||||||
|
|
||||||
msg = (struct kore_x509_msg *)payload;
|
msg = (struct kore_x509_msg *)payload;
|
||||||
msg->domain_len = strlen(dom->domain);
|
|
||||||
if (msg->domain_len > sizeof(msg->domain))
|
if (kore_strlcpy(msg->domain, dom->domain, sizeof(msg->domain)) >=
|
||||||
fatal("domain name '%s' too long", dom->domain);
|
sizeof(msg->domain))
|
||||||
memcpy(msg->domain, dom->domain, msg->domain_len);
|
fatalx("%s: domain truncated", __func__);
|
||||||
|
|
||||||
msg->data_len = st.st_size;
|
msg->data_len = st.st_size;
|
||||||
ret = read(fd, &msg->data[0], msg->data_len);
|
ret = read(fd, &msg->data[0], msg->data_len);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
fatal("failed to read from %s: %s", file, errno_s);
|
fatalx("failed to read from %s: %s", file, errno_s);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
fatal("eof while reading %s", file);
|
fatalx("eof while reading %s", file);
|
||||||
|
|
||||||
if ((size_t)ret != msg->data_len) {
|
if ((size_t)ret != msg->data_len) {
|
||||||
fatal("bad read on %s: expected %zu, got %zd",
|
fatalx("bad read on %s: expected %zu, got %zd",
|
||||||
file, msg->data_len, ret);
|
file, msg->data_len, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,26 +412,26 @@ keymgr_load_randfile(void)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((fd = open(rand_file, O_RDONLY)) == -1)
|
if ((fd = open(rand_file, O_RDONLY)) == -1)
|
||||||
fatal("open(%s): %s", rand_file, errno_s);
|
fatalx("open(%s): %s", rand_file, errno_s);
|
||||||
|
|
||||||
if (fstat(fd, &st) == -1)
|
if (fstat(fd, &st) == -1)
|
||||||
fatal("stat(%s): %s", rand_file, errno_s);
|
fatalx("stat(%s): %s", rand_file, errno_s);
|
||||||
if (!S_ISREG(st.st_mode))
|
if (!S_ISREG(st.st_mode))
|
||||||
fatal("%s is not a file", rand_file);
|
fatalx("%s is not a file", rand_file);
|
||||||
if (st.st_size != RAND_FILE_SIZE)
|
if (st.st_size != RAND_FILE_SIZE)
|
||||||
fatal("%s has an invalid size", rand_file);
|
fatalx("%s has an invalid size", rand_file);
|
||||||
|
|
||||||
total = 0;
|
total = 0;
|
||||||
|
|
||||||
while (total != RAND_FILE_SIZE) {
|
while (total != RAND_FILE_SIZE) {
|
||||||
ret = read(fd, buf, sizeof(buf));
|
ret = read(fd, buf, sizeof(buf));
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
fatal("EOF on %s", rand_file);
|
fatalx("EOF on %s", rand_file);
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
fatal("read(%s): %s", rand_file, errno_s);
|
fatalx("read(%s): %s", rand_file, errno_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
total += (size_t)ret;
|
total += (size_t)ret;
|
||||||
|
@ -507,7 +513,7 @@ keymgr_load_domain_privatekey(struct kore_domain *dom)
|
||||||
keymgr_acme_domainkey(dom, key);
|
keymgr_acme_domainkey(dom, key);
|
||||||
#endif
|
#endif
|
||||||
if (key->pkey == NULL) {
|
if (key->pkey == NULL) {
|
||||||
fatal("failed to load private key for '%s' (%s)",
|
fatalx("failed to load private key for '%s' (%s)",
|
||||||
dom->domain, errno_s);
|
dom->domain, errno_s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -575,14 +581,15 @@ keymgr_msg_recv(struct kore_msg *msg, const void *data)
|
||||||
|
|
||||||
if (msg->length != (sizeof(*req) + req->data_len))
|
if (msg->length != (sizeof(*req) + req->data_len))
|
||||||
return;
|
return;
|
||||||
if (req->domain_len > KORE_DOMAINNAME_LEN)
|
|
||||||
|
if (req->domain[KORE_DOMAINNAME_LEN] != '\0')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
key = NULL;
|
key = NULL;
|
||||||
TAILQ_FOREACH(key, &keys, list) {
|
TAILQ_FOREACH(key, &keys, list) {
|
||||||
if (key->dom == NULL)
|
if (key->dom == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (!strncmp(key->dom->domain, req->domain, req->domain_len))
|
if (!strcmp(key->dom->domain, req->domain))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,7 +628,7 @@ keymgr_rsa_encrypt(struct kore_msg *msg, const void *data, struct key *key)
|
||||||
|
|
||||||
req = (const struct kore_keyreq *)data;
|
req = (const struct kore_keyreq *)data;
|
||||||
|
|
||||||
#if !defined(LIBRESSL_VERSION_TEXT) && OPENSSL_VERSION_NUMBER >= 0x10100000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
rsa = EVP_PKEY_get0_RSA(key->pkey);
|
rsa = EVP_PKEY_get0_RSA(key->pkey);
|
||||||
#else
|
#else
|
||||||
rsa = key->pkey->pkey.rsa;
|
rsa = key->pkey->pkey.rsa;
|
||||||
|
@ -648,7 +655,7 @@ keymgr_ecdsa_sign(struct kore_msg *msg, const void *data, struct key *key)
|
||||||
u_int8_t sig[1024];
|
u_int8_t sig[1024];
|
||||||
|
|
||||||
req = (const struct kore_keyreq *)data;
|
req = (const struct kore_keyreq *)data;
|
||||||
#if !defined(LIBRESSL_VERSION_TEXT) && OPENSSL_VERSION_NUMBER >= 0x10100000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
ec = EVP_PKEY_get0_EC_KEY(key->pkey);
|
ec = EVP_PKEY_get0_EC_KEY(key->pkey);
|
||||||
#else
|
#else
|
||||||
ec = key->pkey->pkey.ec;
|
ec = key->pkey->pkey.ec;
|
||||||
|
@ -680,7 +687,7 @@ keymgr_acme_init(void)
|
||||||
|
|
||||||
if (mkdir(KORE_ACME_CERTDIR, 0700) == -1) {
|
if (mkdir(KORE_ACME_CERTDIR, 0700) == -1) {
|
||||||
if (errno != EEXIST)
|
if (errno != EEXIST)
|
||||||
fatal("mkdir(%s): %s", KORE_ACME_CERTDIR, errno_s);
|
fatalx("mkdir(%s): %s", KORE_ACME_CERTDIR, errno_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
umask(S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
|
umask(S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
|
||||||
|
@ -727,13 +734,13 @@ keymgr_acme_domainkey(struct kore_domain *dom, struct key *key)
|
||||||
kore_log(LOG_NOTICE, "generated new domain key for %s", dom->domain);
|
kore_log(LOG_NOTICE, "generated new domain key for %s", dom->domain);
|
||||||
|
|
||||||
if ((p = strrchr(dom->certkey, '/')) == NULL)
|
if ((p = strrchr(dom->certkey, '/')) == NULL)
|
||||||
fatal("invalid certkey path '%s'", dom->certkey);
|
fatalx("invalid certkey path '%s'", dom->certkey);
|
||||||
|
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
if (mkdir(dom->certkey, 0700) == -1) {
|
if (mkdir(dom->certkey, 0700) == -1) {
|
||||||
if (errno != EEXIST)
|
if (errno != EEXIST)
|
||||||
fatal("mkdir(%s): %s", dom->certkey, errno_s);
|
fatalx("mkdir(%s): %s", dom->certkey, errno_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
*p = '/';
|
*p = '/';
|
||||||
|
@ -802,10 +809,10 @@ keymgr_acme_sign(struct kore_msg *msg, const void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
fatal("%s: missing key", __func__);
|
fatalx("%s: missing key", __func__);
|
||||||
|
|
||||||
if (msg->length < sizeof(id))
|
if (msg->length < sizeof(id))
|
||||||
fatal("%s: invalid length (%zu)", __func__, msg->length);
|
fatalx("%s: invalid length (%zu)", __func__, msg->length);
|
||||||
|
|
||||||
ptr = data;
|
ptr = data;
|
||||||
memcpy(&id, ptr, sizeof(id));
|
memcpy(&id, ptr, sizeof(id));
|
||||||
|
@ -816,19 +823,19 @@ keymgr_acme_sign(struct kore_msg *msg, const void *data)
|
||||||
sig = kore_calloc(1, EVP_PKEY_size(key->pkey));
|
sig = kore_calloc(1, EVP_PKEY_size(key->pkey));
|
||||||
|
|
||||||
if ((ctx = EVP_MD_CTX_create()) == NULL)
|
if ((ctx = EVP_MD_CTX_create()) == NULL)
|
||||||
fatal("EVP_MD_CTX_create: %s", ssl_errno_s);
|
fatalx("EVP_MD_CTX_create: %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!EVP_SignInit_ex(ctx, EVP_sha256(), NULL))
|
if (!EVP_SignInit_ex(ctx, EVP_sha256(), NULL))
|
||||||
fatal("EVP_SignInit_ex: %s", ssl_errno_s);
|
fatalx("EVP_SignInit_ex: %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!EVP_SignUpdate(ctx, ptr, msg->length))
|
if (!EVP_SignUpdate(ctx, ptr, msg->length))
|
||||||
fatal("EVP_SignUpdate: %s", ssl_errno_s);
|
fatalx("EVP_SignUpdate: %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!EVP_SignFinal(ctx, sig, &siglen, key->pkey))
|
if (!EVP_SignFinal(ctx, sig, &siglen, key->pkey))
|
||||||
fatal("EVP_SignFinal: %s", ssl_errno_s);
|
fatalx("EVP_SignFinal: %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!kore_base64url_encode(sig, siglen, &b64, KORE_BASE64_RAW))
|
if (!kore_base64url_encode(sig, siglen, &b64, KORE_BASE64_RAW))
|
||||||
fatal("%s: failed to b64url encode signed data", __func__);
|
fatalx("%s: failed to b64url encode signed data", __func__);
|
||||||
|
|
||||||
kore_buf_init(&buf, siglen + sizeof(id));
|
kore_buf_init(&buf, siglen + sizeof(id));
|
||||||
kore_buf_append(&buf, &id, sizeof(id));
|
kore_buf_append(&buf, &id, sizeof(id));
|
||||||
|
@ -845,87 +852,123 @@ keymgr_acme_sign(struct kore_msg *msg, const void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
keymgr_acme_challenge_cert(const void *token, size_t len, struct key *key)
|
keymgr_acme_challenge_cert(const void *data, size_t len, struct key *key)
|
||||||
{
|
{
|
||||||
int nid;
|
size_t idx;
|
||||||
FILE *fp;
|
struct kore_x509_msg hdr;
|
||||||
struct kore_buf buf;
|
struct kore_buf buf;
|
||||||
time_t now;
|
time_t now;
|
||||||
X509_EXTENSION *ext;
|
|
||||||
X509_NAME *name;
|
X509_NAME *name;
|
||||||
X509 *x509;
|
X509 *x509;
|
||||||
char *altname;
|
const u_int8_t *digest;
|
||||||
|
int slen, acme;
|
||||||
|
u_int8_t *cert, *uptr;
|
||||||
|
char hex[(SHA256_DIGEST_LENGTH * 2) + 1];
|
||||||
|
|
||||||
kore_log(LOG_INFO, "[%s] generating tls-alpn-01 challenge cert",
|
kore_log(LOG_INFO, "[%s] generating tls-alpn-01 challenge cert",
|
||||||
key->dom->domain);
|
key->dom->domain);
|
||||||
|
|
||||||
|
if (len != SHA256_DIGEST_LENGTH)
|
||||||
|
fatalx("invalid digest length of %zu bytes", len);
|
||||||
|
|
||||||
|
digest = data;
|
||||||
|
for (idx = 0; idx < len; idx++) {
|
||||||
|
slen = snprintf(hex + (idx * 2), sizeof(hex) - (idx * 2),
|
||||||
|
"%02x", digest[idx]);
|
||||||
|
if (slen == -1 || (size_t)slen >= sizeof(hex))
|
||||||
|
fatalx("faild to convert digest to hex");
|
||||||
|
}
|
||||||
|
|
||||||
if ((x509 = X509_new()) == NULL)
|
if ((x509 = X509_new()) == NULL)
|
||||||
fatal("X509_new(): %s", ssl_errno_s);
|
fatalx("X509_new(): %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!X509_set_version(x509, 2))
|
if (!X509_set_version(x509, 2))
|
||||||
fatal("X509_set_version(): %s", ssl_errno_s);
|
fatalx("X509_set_version(): %s", ssl_errno_s);
|
||||||
|
|
||||||
time(&now);
|
time(&now);
|
||||||
if (!ASN1_INTEGER_set(X509_get_serialNumber(x509), now))
|
if (!ASN1_INTEGER_set(X509_get_serialNumber(x509), now))
|
||||||
fatal("ASN1_INTEGER_set(): %s", ssl_errno_s);
|
fatalx("ASN1_INTEGER_set(): %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!X509_gmtime_adj(X509_get_notBefore(x509), 0))
|
if (!X509_gmtime_adj(X509_get_notBefore(x509), 0))
|
||||||
fatal("X509_gmtime_adj(): %s", ssl_errno_s);
|
fatalx("X509_gmtime_adj(): %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!X509_gmtime_adj(X509_get_notAfter(x509), ACME_X509_EXPIRATION))
|
if (!X509_gmtime_adj(X509_get_notAfter(x509), ACME_X509_EXPIRATION))
|
||||||
fatal("X509_gmtime_adj(): %s", ssl_errno_s);
|
fatalx("X509_gmtime_adj(): %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!X509_set_pubkey(x509, key->pkey))
|
if (!X509_set_pubkey(x509, key->pkey))
|
||||||
fatal("X509_set_pubkey(): %s", ssl_errno_s);
|
fatalx("X509_set_pubkey(): %s", ssl_errno_s);
|
||||||
|
|
||||||
if ((name = X509_get_subject_name(x509)) == NULL)
|
if ((name = X509_get_subject_name(x509)) == NULL)
|
||||||
fatal("X509_get_subject_name(): %s", ssl_errno_s);
|
fatalx("X509_get_subject_name(): %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!X509_NAME_add_entry_by_txt(name, "CN",
|
if (!X509_NAME_add_entry_by_txt(name, "CN",
|
||||||
MBSTRING_ASC, (const unsigned char *)key->dom->domain, -1, -1, 0))
|
MBSTRING_ASC, (const unsigned char *)key->dom->domain, -1, -1, 0))
|
||||||
fatal("X509_NAME_add_entry_by_txt(): CN %s", ssl_errno_s);
|
fatalx("X509_NAME_add_entry_by_txt(): CN %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!X509_set_issuer_name(x509, name))
|
if (!X509_set_issuer_name(x509, name))
|
||||||
fatal("X509_set_issuer_name(): %s", ssl_errno_s);
|
fatalx("X509_set_issuer_name(): %s", ssl_errno_s);
|
||||||
|
|
||||||
kore_buf_init(&buf, 128);
|
acme = OBJ_create(ACME_TLS_ALPN_01_OID, "acme", "acmeIdentifier");
|
||||||
kore_buf_appendf(&buf, "DNS:%s", key->dom->domain);
|
X509V3_EXT_add_alias(acme, NID_subject_key_identifier);
|
||||||
altname = kore_buf_stringify(&buf, NULL);
|
|
||||||
|
|
||||||
ext = X509V3_EXT_conf_nid(NULL, NULL, NID_subject_alt_name, altname);
|
keymgr_x509_ext(x509, acme, "critical,%s", hex);
|
||||||
if (ext == NULL)
|
keymgr_x509_ext(x509, NID_subject_alt_name, "DNS:%s", key->dom->domain);
|
||||||
fatal("X509V3_EXT_conf_nid: %s", ssl_errno_s);
|
|
||||||
|
|
||||||
if (!X509_add_ext(x509, ext, -1))
|
|
||||||
fatal("X509_add_ext: %s", ssl_errno_s);
|
|
||||||
|
|
||||||
X509_EXTENSION_free(ext);
|
|
||||||
kore_buf_cleanup(&buf);
|
|
||||||
|
|
||||||
nid = OBJ_create(ACME_TLS_ALPN_01_OID, "acme", "acmeIdentifier");
|
|
||||||
X509V3_EXT_add_alias(nid, NID_subject_key_identifier);
|
|
||||||
|
|
||||||
/* XXX - add SHA256 digest over key authoritization. */
|
|
||||||
ext = X509V3_EXT_conf_nid(NULL, NULL, nid, "critical,62636465");
|
|
||||||
if (ext == NULL)
|
|
||||||
fatal("X509V3_EXT_conf_nid: %s", ssl_errno_s);
|
|
||||||
|
|
||||||
if (!X509_add_ext(x509, ext, -1))
|
|
||||||
fatal("X509_add_ext: %s", ssl_errno_s);
|
|
||||||
|
|
||||||
X509_EXTENSION_free(ext);
|
|
||||||
|
|
||||||
if (!X509_sign(x509, key->pkey, EVP_sha256()))
|
if (!X509_sign(x509, key->pkey, EVP_sha256()))
|
||||||
fatal("X509_sign(): %s", ssl_errno_s);
|
fatalx("X509_sign(): %s", ssl_errno_s);
|
||||||
|
|
||||||
if ((fp = fopen("foobar.pem", "w")) == NULL)
|
if ((slen = i2d_X509(x509, NULL)) <= 0)
|
||||||
fatal("fopen(cert/server.pem): %s", errno_s);
|
fatalx("i2d_X509: %s", ssl_errno_s);
|
||||||
if (!PEM_write_X509(fp, x509))
|
|
||||||
fatal("PEM_write_X509(%s)", errno_s);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
|
cert = kore_calloc(1, slen);
|
||||||
|
uptr = cert;
|
||||||
|
|
||||||
|
if (i2d_X509(x509, &uptr) <= 0)
|
||||||
|
fatalx("i2d_X509: %s", ssl_errno_s);
|
||||||
|
|
||||||
|
memset(&hdr, 0, sizeof(hdr));
|
||||||
|
hdr.data_len = slen;
|
||||||
|
|
||||||
|
if (kore_strlcpy(hdr.domain, key->dom->domain, sizeof(hdr.domain)) >=
|
||||||
|
sizeof(hdr.domain))
|
||||||
|
fatalx("%s: domain truncated", __func__);
|
||||||
|
|
||||||
|
kore_buf_init(&buf, sizeof(hdr) + slen);
|
||||||
|
kore_buf_append(&buf, &hdr, sizeof(hdr));
|
||||||
|
kore_buf_append(&buf, cert, slen);
|
||||||
|
|
||||||
|
kore_msg_send(KORE_MSG_WORKER_ALL, KORE_ACME_CHALLENGE_SET_CERT,
|
||||||
|
buf.data, buf.offset);
|
||||||
|
|
||||||
|
kore_buf_cleanup(&buf);
|
||||||
|
kore_free(cert);
|
||||||
X509_free(x509);
|
X509_free(x509);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keymgr_x509_ext(X509 *x509, int extnid, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
X509_EXTENSION *ext;
|
||||||
|
va_list args;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
len = vsnprintf(buf, sizeof(buf), fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (len == -1 || (size_t)len >= sizeof(buf))
|
||||||
|
fatalx("failed to create buffer for extension %d", extnid);
|
||||||
|
|
||||||
|
if ((ext = X509V3_EXT_conf_nid(NULL, NULL, extnid, buf)) == NULL)
|
||||||
|
fatalx("X509V3_EXT_conf_nid: %s", ssl_errno_s);
|
||||||
|
|
||||||
|
if (!X509_add_ext(x509, ext, -1))
|
||||||
|
fatalx("X509_add_ext: %s", ssl_errno_s);
|
||||||
|
|
||||||
|
X509_EXTENSION_free(ext);
|
||||||
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
keymgr_bignum_base64(BIGNUM *bn)
|
keymgr_bignum_base64(BIGNUM *bn)
|
||||||
{
|
{
|
||||||
|
@ -937,10 +980,10 @@ keymgr_bignum_base64(BIGNUM *bn)
|
||||||
buf = kore_calloc(1, len);
|
buf = kore_calloc(1, len);
|
||||||
|
|
||||||
if (BN_bn2bin(bn, buf) != len)
|
if (BN_bn2bin(bn, buf) != len)
|
||||||
fatal("BN_bn2bin: %s", ssl_errno_s);
|
fatalx("BN_bn2bin: %s", ssl_errno_s);
|
||||||
|
|
||||||
if (!kore_base64url_encode(buf, len, &encoded, KORE_BASE64_RAW))
|
if (!kore_base64url_encode(buf, len, &encoded, KORE_BASE64_RAW))
|
||||||
fatal("failed to base64 encode BIGNUM");
|
fatalx("failed to base64 encode BIGNUM");
|
||||||
|
|
||||||
return (encoded);
|
return (encoded);
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,6 +348,8 @@ kore_tls_sni_cb(SSL *ssl, int *ad, void *arg)
|
||||||
struct kore_domain *dom;
|
struct kore_domain *dom;
|
||||||
const char *sname;
|
const char *sname;
|
||||||
|
|
||||||
|
printf("%s\n", __func__);
|
||||||
|
|
||||||
if ((c = SSL_get_ex_data(ssl, 0)) == NULL)
|
if ((c = SSL_get_ex_data(ssl, 0)) == NULL)
|
||||||
fatal("no connection data in %s", __func__);
|
fatal("no connection data in %s", __func__);
|
||||||
|
|
||||||
|
@ -366,6 +368,11 @@ kore_tls_sni_cb(SSL *ssl, int *ad, void *arg)
|
||||||
kore_debug("kore_ssl_sni_cb(): Using %s CTX", sname);
|
kore_debug("kore_ssl_sni_cb(): Using %s CTX", sname);
|
||||||
SSL_set_SSL_CTX(ssl, dom->ssl_ctx);
|
SSL_set_SSL_CTX(ssl, dom->ssl_ctx);
|
||||||
|
|
||||||
|
if (!SSL_set_ex_data(ssl, 1, dom)) {
|
||||||
|
kore_debug("SSL_set_ex_data(): %s", ssl_errno_s);
|
||||||
|
return (KORE_RESULT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(KORE_USE_ACME)
|
#if defined(KORE_USE_ACME)
|
||||||
if (kore_acme_tls_challenge_selected(ssl, dom)) {
|
if (kore_acme_tls_challenge_selected(ssl, dom)) {
|
||||||
kore_acme_tls_challenge_use_cert(ssl, dom);
|
kore_acme_tls_challenge_use_cert(ssl, dom);
|
||||||
|
|
32
src/worker.c
32
src/worker.c
|
@ -402,6 +402,12 @@ kore_worker_entry(struct kore_worker *kw)
|
||||||
kore_msg_send(KORE_WORKER_KEYMGR,
|
kore_msg_send(KORE_WORKER_KEYMGR,
|
||||||
KORE_MSG_CERTIFICATE_REQ, NULL, 0);
|
KORE_MSG_CERTIFICATE_REQ, NULL, 0);
|
||||||
}
|
}
|
||||||
|
#if defined(KORE_USE_ACME)
|
||||||
|
kore_msg_register(KORE_ACME_CHALLENGE_SET_CERT,
|
||||||
|
worker_keymgr_response);
|
||||||
|
kore_msg_register(KORE_ACME_CHALLENGE_CLEAR_CERT,
|
||||||
|
worker_keymgr_response);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
kore_msg_register(KORE_MSG_ACCEPT_AVAILABLE, worker_accept_avail);
|
kore_msg_register(KORE_MSG_ACCEPT_AVAILABLE, worker_accept_avail);
|
||||||
|
@ -770,18 +776,33 @@ worker_keymgr_response(struct kore_msg *msg, const void *data)
|
||||||
|
|
||||||
switch (msg->id) {
|
switch (msg->id) {
|
||||||
case KORE_MSG_CERTIFICATE:
|
case KORE_MSG_CERTIFICATE:
|
||||||
kore_domain_tlsinit(dom, req->data, req->data_len);
|
kore_domain_tlsinit(dom, KORE_PEM_CERT_CHAIN,
|
||||||
|
req->data, req->data_len);
|
||||||
break;
|
break;
|
||||||
case KORE_MSG_CRL:
|
case KORE_MSG_CRL:
|
||||||
kore_domain_crl_add(dom, req->data, req->data_len);
|
kore_domain_crl_add(dom, req->data, req->data_len);
|
||||||
break;
|
break;
|
||||||
#if defined(KORE_USE_ACME)
|
#if defined(KORE_USE_ACME)
|
||||||
case KORE_ACME_CHALLENGE_SET_CERT:
|
case KORE_ACME_CHALLENGE_SET_CERT:
|
||||||
|
if (dom->ssl_ctx != NULL) {
|
||||||
|
kore_free(dom->acme_cert);
|
||||||
|
dom->acme_cert_len = req->data_len;
|
||||||
|
dom->acme_cert = kore_calloc(1, req->data_len);
|
||||||
|
memcpy(dom->acme_cert, req->data, req->data_len);
|
||||||
|
} else {
|
||||||
|
kore_domain_tlsinit(dom, KORE_DER_CERT_DATA,
|
||||||
|
req->data, req->data_len);
|
||||||
|
}
|
||||||
|
kore_log(LOG_NOTICE, "[%s] tls-alpn-01 challenge active",
|
||||||
|
dom->domain);
|
||||||
|
dom->acme_challenge = 1;
|
||||||
break;
|
break;
|
||||||
case KORE_ACME_CHALLENGE_CLEAR_CERT:
|
case KORE_ACME_CHALLENGE_CLEAR_CERT:
|
||||||
dom->acme_cert_len = 0;
|
dom->acme_cert_len = 0;
|
||||||
dom->acme_challenge = 0;
|
dom->acme_challenge = 0;
|
||||||
kore_free(dom->acme_cert);
|
kore_free(dom->acme_cert);
|
||||||
|
kore_log(LOG_NOTICE, "[%s] tls-alpn-01 challenge disabled",
|
||||||
|
dom->domain);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
@ -811,11 +832,10 @@ worker_keymgr_response_verify(struct kore_msg *msg, const void *data,
|
||||||
return (KORE_RESULT_ERROR);
|
return (KORE_RESULT_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->domain_len > KORE_DOMAINNAME_LEN) {
|
if (req->domain[KORE_DOMAINNAME_LEN] != '\0') {
|
||||||
kore_log(LOG_WARNING,
|
kore_log(LOG_WARNING, "domain not NUL-terminated");
|
||||||
"invalid keymgr domain (%u)",
|
|
||||||
req->domain_len);
|
|
||||||
return (KORE_RESULT_ERROR);
|
return (KORE_RESULT_ERROR);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_FOREACH(srv, &kore_servers, list) {
|
LIST_FOREACH(srv, &kore_servers, list) {
|
||||||
|
@ -825,7 +845,7 @@ worker_keymgr_response_verify(struct kore_msg *msg, const void *data,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TAILQ_FOREACH(dom, &srv->domains, list) {
|
TAILQ_FOREACH(dom, &srv->domains, list) {
|
||||||
if (!strncmp(dom->domain, req->domain, req->domain_len))
|
if (!strcmp(dom->domain, req->domain))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue