kore/src/acme.c

1759 lines
43 KiB
C
Raw Normal View History

Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
/*
2022-01-31 22:02:06 +01:00
* Copyright (c) 2019-2022 Joris Vink <joris@coders.se>
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* ACMEv2 protocol implementation.
*
* The acme process is responsible for talking to the acme servers, parsing
* their JSON responses and requesting signed data / a csr from the keymgr
* process.
*
* The acme process does not hold your account or domain keys, so anything
* that needs to be signed is sent to the keymgr process instead.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <openssl/sha.h>
#include <stdio.h>
#include <stdlib.h>
#include "kore.h"
#include "acme.h"
#include "curl.h"
#define ACME_CREATE_ACCOUNT 0
#define ACME_RESOLVE_ACCOUNT 1
#define ACME_STATUS_PENDING 1
#define ACME_STATUS_PROCESSING 2
#define ACME_STATUS_VALID 3
#define ACME_STATUS_INVALID 4
#define ACME_STATUS_READY 5
#define ACME_STATUS_EXPIRED 6
#define ACME_STATUS_REVOKED 7
/*
* The default provider is letsencrypt, can be overwritten via the config
* file its acme_provider setting.
*/
#define ACME_DEFAULT_PROVIDER "https://acme-v02.api.letsencrypt.org/directory"
#if defined(__linux__)
#include "seccomp.h"
/*
* The syscalls our acme worker is allowed to perform, only.
*
* Since we drop all previously loaded seccomp rules to apply our own
* we will have to reinclude the ones curl does.
*/
static struct sock_filter filter_acme[] = {
2020-07-14 15:47:58 +02:00
KORE_SYSCALL_ALLOW(prctl),
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#if defined(SYS_poll)
KORE_SYSCALL_ALLOW(poll),
#endif
KORE_SYSCALL_ALLOW(ppoll),
KORE_SYSCALL_ALLOW(sendto),
KORE_SYSCALL_ALLOW(recvfrom),
#if defined(SYS_epoll_wait)
KORE_SYSCALL_ALLOW(epoll_wait),
#endif
KORE_SYSCALL_ALLOW(epoll_pwait),
KORE_SYSCALL_ALLOW(recvmsg),
2020-07-14 15:47:58 +02:00
KORE_SYSCALL_ALLOW(sendmsg),
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
KORE_SYSCALL_ALLOW(sendmmsg),
KORE_SYSCALL_ALLOW(getpeername),
2020-07-14 15:47:58 +02:00
KORE_SYSCALL_ALLOW(gettid),
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
KORE_SYSCALL_ALLOW(exit),
KORE_SYSCALL_ALLOW(brk),
#if defined(SYS_mmap)
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
KORE_SYSCALL_ALLOW(mmap),
#endif
#if defined(SYS_mmap2)
KORE_SYSCALL_ALLOW(mmap2),
#endif
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
KORE_SYSCALL_ALLOW(ioctl),
KORE_SYSCALL_ALLOW(uname),
KORE_SYSCALL_ALLOW(munmap),
KORE_SYSCALL_ALLOW(madvise),
KORE_SYSCALL_ALLOW(faccessat),
KORE_SYSCALL_ALLOW(newfstatat),
KORE_SYSCALL_ALLOW(clock_gettime),
KORE_SYSCALL_ALLOW(bind),
KORE_SYSCALL_ALLOW(ioctl),
KORE_SYSCALL_ALLOW(connect),
KORE_SYSCALL_ALLOW(getsockopt),
KORE_SYSCALL_ALLOW(socketpair),
KORE_SYSCALL_ALLOW(getsockname),
KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET),
KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET6),
KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_UNIX),
KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_NETLINK),
KORE_SYSCALL_ALLOW(clone),
KORE_SYSCALL_ALLOW(membarrier),
KORE_SYSCALL_ALLOW(set_robust_list),
#if defined(SYS_clone3)
KORE_SYSCALL_ALLOW(clone3),
#endif
#if defined(SYS_rseq)
KORE_SYSCALL_ALLOW(rseq),
#endif
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
};
#endif
struct acme_request {
struct kore_curl curl;
};
struct acme_sign_op {
u_int32_t id;
struct kore_timer *t;
void *udata;
char *nonce;
char *payload;
char *protected;
void (*cb)(struct acme_sign_op *,
struct kore_buf *);
LIST_ENTRY(acme_sign_op) list;
};
#define ACME_AUTH_STATE_DOWNLOAD 1
#define ACME_AUTH_STATE_CHALLENGE 2
struct acme_auth {
char *url;
struct acme_order *order;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
int status;
struct acme_challenge *challenge;
LIST_ENTRY(acme_auth) list;
};
#define ACME_ORDER_STATE_RUNNING 1
#define ACME_ORDER_STATE_ERROR 2
#define ACME_ORDER_STATE_CANCELLED 3
#define ACME_ORDER_STATE_UPDATE 4
#define ACME_ORDER_STATE_UPDATE_AUTH 5
#define ACME_ORDER_STATE_WAITING 6
#define ACME_ORDER_STATE_FETCH_CERT 7
#define ACME_ORDER_STATE_COMPLETE 8
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#define ACME_ORDER_TICK 1000
#define ACME_ORDER_TIMEOUT 240000
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#define ACME_ORDER_CSR_REQUESTED 0x1000
struct acme_order {
int state;
int status;
int flags;
int auths;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
u_int64_t start;
char *id;
char *final;
char *domain;
char *certloc;
struct acme_auth *curauth;
LIST_HEAD(, acme_auth) auth;
LIST_ENTRY(acme_order) list;
};
static LIST_HEAD(, acme_order) orders;
#define ACME_FLAG_CHALLENGE_CREATED 0x0001
#define ACME_CHALLENGE_TOKEN_MAXLEN 64
struct acme_challenge {
int status;
int flags;
char *url;
char *type;
char *token;
char *error_type;
char *error_detail;
int (*process)(struct acme_order *,
struct acme_challenge *);
};
static LIST_HEAD(, acme_sign_op) signops;
static int acme_status_type(const char *);
static int acme_request_run(struct acme_request *);
static void acme_request_cleanup(struct acme_request *);
static void acme_request_prepare(struct acme_request *,
2020-10-28 15:44:18 +01:00
int, const char *, const void *, size_t);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
static void acme_request_json(struct kore_buf *, const char *,
const char *, const char *);
static char *acme_nonce_fetch(void);
static char *acme_thumbprint_component(void);
static char *acme_base64url(const void *, size_t);
static char *acme_protected_component(const char *, const char *);
static void acme_keymgr_key_req(const char *, const void *, size_t, int);
static void acme_parse_directory(void);
static void acme_directory_set(struct kore_json *, const char *, char **);
static void acme_sign_expire(void *, u_int64_t);
static void acme_sign_result(struct kore_msg *, const void *);
static void acme_sign_submit(struct kore_json_item *, const char *, void *,
void (*cb)(struct acme_sign_op *, struct kore_buf *));
static void acme_rsakey_exp(struct kore_msg *, const void *);
static void acme_rsakey_mod(struct kore_msg *, const void *);
static void acme_account_reg(int);
static void acme_account_create(struct kore_msg *, const void *);
static void acme_account_resolve(struct kore_msg *, const void *);
static void acme_generic_submit(struct acme_sign_op *, struct kore_buf *);
static void acme_account_reg_submit(struct acme_sign_op *,
struct kore_buf *);
static void acme_order_retry(const char *);
static void acme_order_process(void *, u_int64_t);
static void acme_order_update(struct acme_order *);
static void acme_order_update_submit(struct acme_sign_op *,
struct kore_buf *);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
static void acme_order_request_csr(struct acme_order *);
static void acme_order_fetch_certificate(struct acme_order *);
static void acme_order_fetch_certificate_submit(struct acme_sign_op *,
struct kore_buf *);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
static void acme_order_create(struct kore_msg *, const void *);
static void acme_order_remove(struct acme_order *, const char *);
static void acme_order_csr_response(struct kore_msg *, const void *);
static void acme_order_create_submit(struct acme_sign_op *,
struct kore_buf *);
static void acme_order_auth_log_error(struct acme_order *);
static void acme_order_auth_deactivate(struct acme_order *);
static int acme_order_auth_process(struct acme_order *,
struct acme_auth *);
static void acme_order_auth_update(struct acme_order *,
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
struct acme_auth *);
static void acme_order_auth_update_submit(struct acme_sign_op *,
struct kore_buf *);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
static int acme_challenge_tls_alpn_01(struct acme_order *,
struct acme_challenge *);
static void acme_challenge_tls_alpn_01_create(struct acme_order *,
struct acme_challenge *);
static void acme_challenge_respond(struct acme_order *,
const char *, const char *);
static int signop_id = 0;
static char *rsakey_n = NULL;
static char *rsakey_e = NULL;
static char *nonce_url = NULL;
static char *order_url = NULL;
static char *revoke_url = NULL;
static char *account_id = NULL;
static char *account_url = NULL;
struct kore_privsep acme_privsep;
int acme_domains = 0;
char *acme_email = NULL;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
char *acme_provider = NULL;
u_int32_t acme_request_timeout = 8;
void
kore_acme_init(void)
{
acme_provider = kore_strdup(ACME_DEFAULT_PROVIDER);
}
void
kore_acme_run(void)
{
int quit;
u_int64_t now, netwait;
quit = 0;
kore_server_closeall();
kore_module_cleanup();
net_init();
kore_timer_init();
kore_connection_init();
kore_platform_event_init();
kore_msg_worker_init();
kore_msg_register(KORE_ACME_RSAKEY_E, acme_rsakey_exp);
kore_msg_register(KORE_ACME_RSAKEY_N, acme_rsakey_mod);
kore_msg_register(KORE_ACME_SIGN_RESULT, acme_sign_result);
kore_msg_register(KORE_ACME_ORDER_CREATE, acme_order_create);
kore_msg_register(KORE_ACME_ACCOUNT_CREATE, acme_account_create);
kore_msg_register(KORE_ACME_ACCOUNT_RESOLVE, acme_account_resolve);
kore_msg_register(KORE_ACME_CSR_RESPONSE, acme_order_csr_response);
#if defined(__linux__)
/* Drop all enabled seccomp filters, and add only ours. */
kore_seccomp_drop();
kore_seccomp_filter("acme", filter_acme, KORE_FILTER_LEN(filter_acme));
#endif
#if defined(KORE_USE_PYTHON)
kore_msg_unregister(KORE_PYTHON_SEND_OBJ);
#endif
kore_worker_privsep();
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
#if defined(__OpenBSD__)
if (unveil("/etc/ssl/", "r") == -1)
fatal("unveil: %s", errno_s);
if (pledge("stdio inet dns rpath", NULL) == -1)
fatal("pledge acme process: %s", errno_s);
#endif
http_init();
LIST_INIT(&orders);
LIST_INIT(&signops);
kore_worker_started();
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
acme_parse_directory();
while (quit != 1) {
now = kore_time_ms();
netwait = kore_timer_next_run(now);
kore_platform_event_wait(netwait);
if (sig_recv != 0) {
switch (sig_recv) {
case SIGQUIT:
case SIGINT:
case SIGTERM:
quit = 1;
break;
default:
break;
}
sig_recv = 0;
}
if (quit)
break;
now = kore_time_ms();
kore_timer_run(now);
kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
}
kore_platform_event_cleanup();
kore_connection_cleanup();
net_cleanup();
}
2019-11-13 23:01:24 +01:00
void
kore_acme_get_paths(const char *domain, char **key, char **cert)
{
int len;
char path[MAXPATHLEN];
len = snprintf(path, sizeof(path), "%s/%s/fullchain.pem",
KORE_ACME_CERTDIR, domain);
if (len == -1 || (size_t)len >= sizeof(path))
fatal("failed to create certfile path");
*cert = kore_strdup(path);
len = snprintf(path, sizeof(path), "%s/%s/key.pem",
KORE_ACME_CERTDIR, domain);
if (len == -1 || (size_t)len >= sizeof(path))
fatal("failed to create certkey path");
*key = kore_strdup(path);
}
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
static void
acme_parse_directory(void)
{
struct acme_request req;
size_t len;
struct kore_json json;
const u_int8_t *body;
acme_request_prepare(&req, HTTP_METHOD_GET, acme_provider, NULL, 0);
if (!acme_request_run(&req)) {
acme_request_cleanup(&req);
return;
}
if (req.curl.http.status != HTTP_STATUS_OK) {
kore_log(LOG_NOTICE,
"request to '%s' failed: got %ld - expected 200",
req.curl.url, req.curl.http.status);
acme_request_cleanup(&req);
return;
}
kore_curl_response_as_bytes(&req.curl, &body, &len);
kore_json_init(&json, body, len);
if (!kore_json_parse(&json)) {
kore_log(LOG_NOTICE,
"failed to parse directory payload from ACME server (%s)",
kore_json_strerror());
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
goto cleanup;
}
acme_directory_set(&json, "newNonce", &nonce_url);
acme_directory_set(&json, "newOrder", &order_url);
acme_directory_set(&json, "newAccount", &account_url);
acme_directory_set(&json, "revokeCert", &revoke_url);
cleanup:
kore_json_cleanup(&json);
acme_request_cleanup(&req);
}
static char *
acme_nonce_fetch(void)
{
struct acme_request req;
char *ret;
const char *nonce;
ret = NULL;
acme_request_prepare(&req, HTTP_METHOD_HEAD, nonce_url, NULL, 0);
if (!acme_request_run(&req))
goto cleanup;
if (req.curl.http.status != HTTP_STATUS_OK) {
kore_log(LOG_NOTICE,
"request to '%s' failed: got %ld - expected 200",
req.curl.url, req.curl.http.status);
goto cleanup;
}
if (!kore_curl_http_get_header(&req.curl, "replay-nonce", &nonce)) {
kore_log(LOG_NOTICE, "new-nonce: no replay-nonce header found");
goto cleanup;
}
ret = kore_strdup(nonce);
cleanup:
acme_request_cleanup(&req);
return (ret);
}
static void
acme_account_create(struct kore_msg *msg, const void *data)
{
acme_account_reg(ACME_CREATE_ACCOUNT);
}
static void
acme_account_resolve(struct kore_msg *msg, const void *data)
{
acme_account_reg(ACME_RESOLVE_ACCOUNT);
}
static void
acme_account_reg(int resolve_only)
{
int len;
char mail[1024];
struct kore_json_item *json, *contact;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
if (account_url == NULL)
return;
kore_free(account_id);
account_id = NULL;
kore_log(LOG_INFO, "%s account with ACME provider",
resolve_only ? "resolving" : "creating");
json = kore_json_create_object(NULL, NULL);
kore_json_create_literal(json, "termsOfServiceAgreed", KORE_JSON_TRUE);
if (acme_email) {
len = snprintf(mail, sizeof(mail), "mailto:%s", acme_email);
if (len == -1 || (size_t)len >= sizeof(mail))
fatalx("mail contact '%s' too large", acme_email);
contact = kore_json_create_array(json, "contact");
kore_json_create_string(contact, NULL, mail);
}
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
if (resolve_only) {
kore_json_create_literal(json,
"onlyReturnExisting", KORE_JSON_TRUE);
}
acme_sign_submit(json, account_url, NULL, acme_account_reg_submit);
kore_json_item_free(json);
}
static void
acme_account_reg_submit(struct acme_sign_op *op, struct kore_buf *payload)
{
struct acme_request req;
const char *header;
acme_request_prepare(&req, HTTP_METHOD_POST, account_url,
payload->data, payload->offset);
if (!acme_request_run(&req))
goto cleanup;
switch (req.curl.http.status) {
case HTTP_STATUS_OK:
case HTTP_STATUS_CREATED:
break;
default:
kore_log(LOG_NOTICE,
"request to '%s' failed: status %ld - body '%s'",
req.curl.url, req.curl.http.status,
kore_curl_response_as_string(&req.curl));
goto cleanup;
}
if (!kore_curl_http_get_header(&req.curl, "location", &header)) {
kore_log(LOG_NOTICE, "new-acct: no location header found");
goto cleanup;
}
account_id = kore_strdup(header);
kore_log(LOG_INFO, "account_id = %s", account_id);
kore_msg_send(KORE_WORKER_KEYMGR, KORE_ACME_PROC_READY, NULL, 0);
cleanup:
acme_request_cleanup(&req);
}
static void
acme_order_create(struct kore_msg *msg, const void *data)
{
char *domain;
struct kore_json_item *json, *identifiers, *identifier;
domain = kore_calloc(1, msg->length + 1);
memcpy(domain, data, msg->length);
domain[msg->length] = '\0';
kore_log(LOG_INFO, "[%s] creating order", domain);
json = kore_json_create_object(NULL, NULL);
identifiers = kore_json_create_array(json, "identifiers");
identifier = kore_json_create_object(identifiers, NULL);
kore_json_create_string(identifier, "type", "dns");
kore_json_create_string(identifier, "value", domain);
acme_sign_submit(json, order_url, domain, acme_order_create_submit);
kore_json_item_free(json);
}
static void
acme_order_create_submit(struct acme_sign_op *op, struct kore_buf *payload)
{
struct acme_request req;
size_t len;
struct kore_json json;
int stval;
const u_int8_t *body;
struct acme_auth *auth;
struct acme_order *order;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
const char *header;
const char *domain;
struct kore_json_item *item, *array, *final, *status;
order = NULL;
domain = op->udata;
acme_request_prepare(&req, HTTP_METHOD_POST, order_url,
payload->data, payload->offset);
if (!acme_request_run(&req)) {
acme_request_cleanup(&req);
acme_order_retry(domain);
return;
}
if (req.curl.http.status != HTTP_STATUS_CREATED) {
kore_log(LOG_NOTICE,
"[%s] - request to '%s' failed: status %ld - body '%s'",
domain, req.curl.url, req.curl.http.status,
kore_curl_response_as_string(&req.curl));
acme_request_cleanup(&req);
acme_order_retry(domain);
return;
}
if (!kore_curl_http_get_header(&req.curl, "location", &header)) {
kore_log(LOG_NOTICE,
"[%s] new-order: no order id found", domain);
acme_request_cleanup(&req);
acme_order_retry(domain);
return;
}
kore_curl_response_as_bytes(&req.curl, &body, &len);
kore_json_init(&json, body, len);
if (!kore_json_parse(&json)) {
kore_log(LOG_NOTICE,
"[%s] failed to parse order payload from ACME server (%s)",
domain, kore_json_strerror());
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
goto cleanup;
}
array = kore_json_find_array(json.root, "authorizations");
if (array == NULL) {
kore_log(LOG_NOTICE, "[%s] body has no 'authorizations' array",
domain);
goto cleanup;
}
if (TAILQ_EMPTY(&array->data.items)) {
kore_log(LOG_NOTICE, "[%s] no authoritization URLs in payload",
domain);
goto cleanup;
}
if ((status = kore_json_find_string(json.root, "status")) == NULL) {
kore_log(LOG_NOTICE, "[%s] order has no 'status' string",
domain);
goto cleanup;
}
if ((final = kore_json_find_string(json.root, "finalize")) == NULL) {
kore_log(LOG_NOTICE, "[%s] order has no 'finalize' string",
domain);
goto cleanup;
}
if ((stval = acme_status_type(status->data.string)) == -1) {
kore_log(LOG_NOTICE, "[%s] order has invalid status",
domain);
goto cleanup;
}
order = kore_calloc(1, sizeof(*order));
LIST_INSERT_HEAD(&orders, order, list);
LIST_INIT(&order->auth);
order->status = stval;
order->start = kore_time_ms();
order->id = kore_strdup(header);
order->domain = kore_strdup(domain);
order->state = ACME_ORDER_STATE_UPDATE;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
order->final = kore_strdup(final->data.string);
kore_timer_add(acme_order_process, ACME_ORDER_TICK,
order, KORE_TIMER_ONESHOT);
TAILQ_FOREACH(item, &array->data.items, list) {
if (item->type != KORE_JSON_TYPE_STRING)
continue;
auth = kore_calloc(1, sizeof(*auth));
auth->order = order;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
auth->url = kore_strdup(item->data.string);
LIST_INSERT_HEAD(&order->auth, auth, list);
}
order->curauth = LIST_FIRST(&order->auth);
kore_log(LOG_INFO, "[%s] order_id = %s", order->domain, order->id);
cleanup:
if (order == NULL)
acme_order_retry(domain);
kore_json_cleanup(&json);
acme_request_cleanup(&req);
}
static void
acme_order_update(struct acme_order *order)
{
acme_sign_submit(NULL, order->id, order, acme_order_update_submit);
}
static void
acme_order_update_submit(struct acme_sign_op *op, struct kore_buf *payload)
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
{
struct acme_request req;
size_t len;
struct kore_json json;
struct acme_order *order;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
const u_int8_t *body;
int stval, ret;
struct kore_json_item *status, *cert;
order = op->udata;
op->udata = NULL;
acme_request_prepare(&req, HTTP_METHOD_POST, order->id,
payload->data, payload->offset);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
if (!acme_request_run(&req)) {
acme_request_cleanup(&req);
order->state = ACME_ORDER_STATE_ERROR;
return;
}
if (req.curl.http.status != HTTP_STATUS_OK) {
kore_log(LOG_NOTICE,
"[%s] - request to '%s' failed: status %ld - body '%s'",
order->domain, req.curl.url, req.curl.http.status,
kore_curl_response_as_string(&req.curl));
acme_request_cleanup(&req);
order->state = ACME_ORDER_STATE_ERROR;
return;
}
ret = KORE_RESULT_ERROR;
kore_curl_response_as_bytes(&req.curl, &body, &len);
kore_json_init(&json, body, len);
if (!kore_json_parse(&json)) {
kore_log(LOG_NOTICE,
"[%s] failed to parse order payload from ACME server (%s)",
order->domain, kore_json_strerror());
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
goto cleanup;
}
if ((status = kore_json_find_string(json.root, "status")) == NULL) {
kore_log(LOG_NOTICE, "[%s] order has no 'status' string",
order->domain);
goto cleanup;
}
if ((stval = acme_status_type(status->data.string)) == -1) {
kore_log(LOG_NOTICE, "[%s] order has invalid status",
order->domain);
goto cleanup;
}
order->status = stval;
if (order->status == ACME_STATUS_VALID) {
cert = kore_json_find_string(json.root, "certificate");
if (cert == NULL) {
kore_log(LOG_NOTICE,
"[%s] order has 'certificate' member",
order->domain);
goto cleanup;
}
order->certloc = kore_strdup(cert->data.string);
}
ret = KORE_RESULT_OK;
cleanup:
if (ret == KORE_RESULT_ERROR)
order->state = ACME_ORDER_STATE_ERROR;
else
order->state = ACME_ORDER_STATE_UPDATE_AUTH;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
kore_json_cleanup(&json);
acme_request_cleanup(&req);
}
/*
* We currently don't care why an order may have failed, (rate-limited,
* auth failed, etc).
*
* It would be neat if we could obey that a bit better.
*/
static void
acme_order_retry(const char *domain)
{
u_int32_t retry_after;
/* arbitrary number */
retry_after = 60000;
acme_keymgr_key_req(domain, &retry_after, sizeof(retry_after),
KORE_ACME_ORDER_FAILED);
}
/*
* Process an order, step by step.
*
* This callback is called every second to check on an active order.
* It will first update the order if required, and updated any of its
* active awuthoritizations to get the latest data.
*/
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
static void
acme_order_process(void *udata, u_int64_t now)
{
struct acme_auth *auth;
struct acme_order *order = udata;
if ((now - order->start) >= ACME_ORDER_TIMEOUT) {
acme_order_auth_deactivate(order);
acme_order_remove(order, "order ran too long");
return;
}
switch (order->state) {
case ACME_ORDER_STATE_WAITING:
break;
case ACME_ORDER_STATE_UPDATE:
acme_order_update(order);
order->state = ACME_ORDER_STATE_WAITING;
break;
case ACME_ORDER_STATE_UPDATE_AUTH:
order->auths = 0;
LIST_FOREACH(auth, &order->auth, list) {
acme_order_auth_update(order, auth);
order->auths++;
}
order->state = ACME_ORDER_STATE_WAITING;
break;
case ACME_ORDER_STATE_CANCELLED:
acme_order_remove(order, "cancelled");
order = NULL;
break;
case ACME_ORDER_STATE_COMPLETE:
acme_order_remove(order, "completed");
order = NULL;
break;
case ACME_ORDER_STATE_FETCH_CERT:
acme_order_fetch_certificate(order);
order->state = ACME_ORDER_STATE_WAITING;
break;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
case ACME_ORDER_STATE_RUNNING:
switch (order->status) {
case ACME_STATUS_PENDING:
if (!acme_order_auth_process(order, order->curauth)) {
acme_order_auth_log_error(order);
acme_order_remove(order, "cancelled");
order = NULL;
}
break;
case ACME_STATUS_READY:
acme_order_request_csr(order);
break;
case ACME_STATUS_PROCESSING:
kore_log(LOG_INFO, "[%s] waiting for certificate",
order->domain);
break;
case ACME_STATUS_VALID:
kore_log(LOG_INFO, "[%s] certificate available",
order->domain);
order->state = ACME_ORDER_STATE_FETCH_CERT;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
break;
case ACME_STATUS_INVALID:
kore_log(LOG_INFO, "[%s] order authorization failed",
order->domain);
acme_order_auth_log_error(order);
acme_order_remove(order, "authorization failure");
order = NULL;
break;
default:
acme_order_auth_deactivate(order);
acme_order_remove(order, "unknown status");
order = NULL;
break;
}
break;
case ACME_ORDER_STATE_ERROR:
acme_order_auth_deactivate(order);
acme_order_remove(order, "error");
order = NULL;
break;
default:
fatal("%s: invalid order state %d", __func__, order->state);
}
if (order != NULL) {
/* Do not go back to update if we are ready for the cert. */
if (order->state != ACME_ORDER_STATE_FETCH_CERT)
order->state = ACME_ORDER_STATE_UPDATE;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
kore_timer_add(acme_order_process, ACME_ORDER_TICK,
order, KORE_TIMER_ONESHOT);
}
}
static void
acme_order_remove(struct acme_order *order, const char *reason)
{
struct acme_auth *auth;
LIST_REMOVE(order, list);
while ((auth = LIST_FIRST(&order->auth)) != NULL) {
LIST_REMOVE(auth, list);
if (auth->challenge != NULL) {
kore_free(auth->challenge->error_detail);
kore_free(auth->challenge->error_type);
kore_free(auth->challenge->token);
kore_free(auth->challenge->type);
kore_free(auth->challenge->url);
kore_free(auth->challenge);
}
kore_free(auth->url);
kore_free(auth);
}
kore_log(LOG_INFO, "[%s] order removed (%s)", order->domain, reason);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
if (strcmp(reason, "completed"))
acme_order_retry(order->domain);
kore_free(order->domain);
kore_free(order->final);
kore_free(order->id);
kore_free(order);
}
static void
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
acme_order_fetch_certificate(struct acme_order *order)
{
acme_sign_submit(NULL, order->certloc, order,
acme_order_fetch_certificate_submit);
}
static void
acme_order_fetch_certificate_submit(struct acme_sign_op *op,
struct kore_buf *payload)
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
{
struct acme_request req;
size_t len;
const u_int8_t *body;
struct acme_order *order;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
order = op->udata;
op->udata = NULL;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
acme_request_prepare(&req, HTTP_METHOD_POST, order->certloc,
payload->data, payload->offset);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
if (!acme_request_run(&req)) {
acme_request_cleanup(&req);
order->state = ACME_ORDER_STATE_CANCELLED;
return;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
}
if (req.curl.http.status != HTTP_STATUS_OK) {
kore_log(LOG_NOTICE,
"[%s] request to '%s' failed: got %ld - expected 200",
order->domain, order->certloc, req.curl.http.status);
acme_request_cleanup(&req);
order->state = ACME_ORDER_STATE_CANCELLED;
return;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
}
kore_curl_response_as_bytes(&req.curl, &body, &len);
kore_log(LOG_INFO, "got %zu bytes of cert data", len);
acme_keymgr_key_req(order->domain, body, len, KORE_ACME_INSTALL_CERT);
acme_request_cleanup(&req);
order->state = ACME_ORDER_STATE_COMPLETE;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
}
static void
acme_order_request_csr(struct acme_order *order)
{
if (order->flags & ACME_ORDER_CSR_REQUESTED)
return;
kore_log(LOG_INFO, "[%s] requesting CSR", order->domain);
order->flags |= ACME_ORDER_CSR_REQUESTED;
acme_keymgr_key_req(order->domain, NULL, 0, KORE_ACME_CSR_REQUEST);
}
static void
acme_order_csr_response(struct kore_msg *msg, const void *data)
{
const struct kore_x509_msg *req;
struct kore_json_item *json;
struct acme_order *order;
char *b64, *url;
if (!kore_worker_keymgr_response_verify(msg, data, NULL))
return;
req = (const struct kore_x509_msg *)data;
LIST_FOREACH(order, &orders, list) {
if (!strcmp(order->domain, req->domain))
break;
}
if (order == NULL) {
kore_log(LOG_NOTICE, "[%s] csr received but no order active",
req->domain);
return;
}
url = kore_strdup(order->final);
b64 = acme_base64url(req->data, req->data_len);
json = kore_json_create_object(NULL, NULL);
kore_json_create_string(json, "csr", b64);
acme_sign_submit(json, url, url, acme_generic_submit);
kore_json_item_free(json);
kore_free(b64);
}
static void
acme_order_auth_deactivate(struct acme_order *order)
{
struct acme_request req;
struct acme_auth *auth;
LIST_FOREACH(auth, &order->auth, list) {
acme_request_prepare(&req, HTTP_METHOD_GET, auth->url, NULL, 0);
if (!acme_request_run(&req)) {
kore_log(LOG_NOTICE,
"[%s:auth] failed to deactivate %s", order->domain,
auth->url);
} else {
kore_log(LOG_NOTICE, "[%s:auth] deactivated %s",
order->domain, auth->url);
}
acme_request_cleanup(&req);
}
}
static void
acme_order_auth_log_error(struct acme_order *order)
{
struct acme_auth *auth;
LIST_FOREACH(auth, &order->auth, list) {
if (auth->challenge->status == ACME_STATUS_PENDING ||
auth->challenge->status == ACME_STATUS_VALID ||
auth->challenge->status == ACME_STATUS_PROCESSING)
continue;
kore_log(LOG_INFO, "[%s:auth:challenge] %s = %s (%s)",
order->domain, auth->challenge->type,
auth->challenge->error_type, auth->challenge->error_detail);
}
}
static int
acme_order_auth_process(struct acme_order *order, struct acme_auth *auth)
{
int ret;
if (auth == NULL)
return (KORE_RESULT_OK);
ret = KORE_RESULT_ERROR;
kore_log(LOG_INFO, "[%s] processing authentication", order->domain);
switch (auth->status) {
case ACME_STATUS_PENDING:
ret = auth->challenge->process(order, auth->challenge);
break;
case ACME_STATUS_VALID:
case ACME_STATUS_PROCESSING:
ret = KORE_RESULT_OK;
break;
case ACME_STATUS_INVALID:
kore_log(LOG_NOTICE, "[%s:auth] authorization invalid",
order->domain);
break;
case ACME_STATUS_EXPIRED:
kore_log(LOG_NOTICE, "[%s:auth] authorization expired",
order->domain);
break;
case ACME_STATUS_REVOKED:
kore_log(LOG_NOTICE, "[%s:auth] authorization revoked",
order->domain);
break;
default:
kore_log(LOG_NOTICE, "[%s:auth] invalid auth status %d",
order->domain, auth->status);
break;
}
if (ret == KORE_RESULT_OK)
order->curauth = LIST_NEXT(order->curauth, list);
return (ret);
}
static void
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
acme_order_auth_update(struct acme_order *order, struct acme_auth *auth)
{
acme_sign_submit(NULL, auth->url, auth, acme_order_auth_update_submit);
}
static void
acme_order_auth_update_submit(struct acme_sign_op *op, struct kore_buf *payload)
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
{
const char *p;
struct acme_request req;
size_t len;
struct kore_json json;
const u_int8_t *body;
struct acme_auth *auth;
struct acme_order *order;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
struct acme_challenge *challenge;
int ret, stval;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
struct kore_json_item *status, *type, *url, *token;
struct kore_json_item *array, *object, *err, *detail;
ret = KORE_RESULT_ERROR;
memset(&json, 0, sizeof(json));
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
auth = op->udata;
order = auth->order;
op->udata = NULL;
acme_request_prepare(&req, HTTP_METHOD_POST, auth->url,
payload->data, payload->offset);
if (!acme_request_run(&req))
goto cleanup;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
if (req.curl.http.status != HTTP_STATUS_OK) {
kore_log(LOG_NOTICE,
"[%s:auth] request to '%s' failed: got %ld - expected 200",
order->domain, auth->url, req.curl.http.status);
goto cleanup;
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
}
kore_curl_response_as_bytes(&req.curl, &body, &len);
kore_json_init(&json, body, len);
if (!kore_json_parse(&json)) {
kore_log(LOG_NOTICE,
"[%s:auth] failed to parse payload from ACME server (%s)",
order->domain, kore_json_strerror());
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
goto cleanup;
}
kore_log(LOG_INFO, "[%s:auth] %s updated", order->domain, auth->url);
if ((status = kore_json_find_string(json.root, "status")) == NULL) {
kore_log(LOG_NOTICE, "[%s:auth] payload has no 'status' string",
order->domain);
goto cleanup;
}
if ((array = kore_json_find_array(json.root, "challenges")) == NULL) {
kore_log(LOG_NOTICE,
"[%s:auth] payload has no 'challenges' array",
order->domain);
goto cleanup;
}
if (TAILQ_EMPTY(&array->data.items)) {
kore_log(LOG_NOTICE,
"[%s:auth] no challenges URLs in challenge array",
order->domain);
goto cleanup;
}
if ((stval = acme_status_type(status->data.string)) == -1) {
kore_log(LOG_NOTICE, "[%s] auth has invalid status",
order->domain);
goto cleanup;
}
auth->status = stval;
TAILQ_FOREACH(object, &array->data.items, list) {
if (object->type != KORE_JSON_TYPE_OBJECT)
continue;
if ((type = kore_json_find_string(object, "type")) == NULL) {
kore_log(LOG_NOTICE,
"[%s:auth:challenge] no type", order->domain);
continue;
}
/*
* We only support tls-alpn-01 for now, we ignore the rest.
*/
if (strcmp(type->data.string, "tls-alpn-01"))
continue;
url = kore_json_find_string(object, "url");
token = kore_json_find_string(object, "token");
status = kore_json_find_string(object, "status");
if (url == NULL || token == NULL || status == NULL) {
kore_log(LOG_NOTICE,
"[%s:auth:challenge] missing members",
order->domain);
continue;
}
if (strlen(token->data.string) > ACME_CHALLENGE_TOKEN_MAXLEN) {
kore_log(LOG_NOTICE,
"[%s:auth:challenge] invalid token length",
order->domain);
continue;
}
for (p = token->data.string; *p != '\0'; p++) {
if ((*p >= 'a' && *p <= 'z') ||
(*p >= 'A' && *p <= 'Z') ||
(*p >= '0' && *p <= '9') || *p == '_' || *p == '-')
continue;
break;
}
if (*p != '\0') {
kore_log(LOG_NOTICE,
"[%s:auth:challenge] invalid token",
order->domain);
continue;
}
if ((stval = acme_status_type(status->data.string)) == -1) {
kore_log(LOG_NOTICE,
"[%s:auth:challenge] invalid challenge status",
order->domain);
continue;
}
if (auth->challenge == NULL) {
challenge = kore_calloc(1, sizeof(*challenge));
challenge->url = kore_strdup(url->data.string);
challenge->process = acme_challenge_tls_alpn_01;
challenge->token = kore_strdup(token->data.string);
challenge->type = kore_strdup(type->data.string);
auth->challenge = challenge;
} else {
challenge = auth->challenge;
}
challenge->status = stval;
if (challenge->status == ACME_STATUS_INVALID &&
(err = kore_json_find_object(object, "error")) != NULL) {
type = kore_json_find_string(err, "type");
detail = kore_json_find_string(err, "detail");
if (type == NULL || detail == NULL) {
kore_log(LOG_NOTICE,
"[%s:auth:challenge] error missing fields",
order->domain);
} else {
kore_free(challenge->error_type);
kore_free(challenge->error_detail);
challenge->error_type =
kore_strdup(type->data.string);
challenge->error_detail =
kore_strdup(detail->data.string);
}
}
break;
}
if (auth->challenge == NULL) {
kore_log(LOG_NOTICE,
"[%s:auth] no supported challenges found", order->domain);
goto cleanup;
}
ret = KORE_RESULT_OK;
cleanup:
if (ret != KORE_RESULT_OK) {
order->state = ACME_ORDER_STATE_CANCELLED;
} else {
order->auths--;
if (order->auths == 0) {
kore_log(LOG_INFO,
"[%s:auth] authentications done", order->domain);
order->state = ACME_ORDER_STATE_RUNNING;
}
}
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
kore_json_cleanup(&json);
acme_request_cleanup(&req);
}
static int
acme_challenge_tls_alpn_01(struct acme_order *order,
struct acme_challenge *challenge)
{
int ret;
ret = KORE_RESULT_RETRY;
switch (challenge->status) {
case ACME_STATUS_PENDING:
acme_challenge_tls_alpn_01_create(order, challenge);
break;
case ACME_STATUS_PROCESSING:
kore_log(LOG_INFO,
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
"[%s:auth:challenge:tls-alpn-01] processing",
order->domain);
break;
case ACME_STATUS_VALID:
kore_log(LOG_INFO,
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
"[%s:auth:challenge:tls-alpn-01] valid",
order->domain);
ret = KORE_RESULT_OK;
break;
default:
kore_log(LOG_NOTICE,
"[%s:auth:challenge:tls-alpn-01] invalid (%d)",
order->domain, challenge->status);
ret = KORE_RESULT_ERROR;
break;
}
return (ret);
}
static void
acme_challenge_tls_alpn_01_create(struct acme_order *order,
struct acme_challenge *challenge)
{
struct kore_buf auth;
char *thumb;
u_int8_t digest[SHA256_DIGEST_LENGTH];
if (challenge->flags & ACME_FLAG_CHALLENGE_CREATED) {
kore_log(LOG_INFO,
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
"[%s:auth:challenge:tls-alpn-01] pending keymgr",
order->domain);
return;
}
challenge->flags |= ACME_FLAG_CHALLENGE_CREATED;
kore_log(LOG_INFO,
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
"[%s:auth:challenge:tls-alpn-01] requested from keymgr",
order->domain);
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_cleanup(&auth);
kore_free(thumb);
acme_keymgr_key_req(order->domain, digest, sizeof(digest),
KORE_ACME_CHALLENGE_CERT);
/* XXX - this maybe too fast, keymgr may not have had time. */
acme_challenge_respond(order, challenge->url, "tls-alpn-01");
}
static void
acme_challenge_respond(struct acme_order *order, const char *url,
const char *name)
{
struct kore_json_item *json;
char *copy;
kore_log(LOG_INFO, "[%s:auth:challenge:%s] submitting challenge",
order->domain, name);
copy = kore_strdup(url);
json = kore_json_create_object(NULL, NULL);
acme_sign_submit(json, url, copy, acme_generic_submit);
kore_json_item_free(json);
}
static void
acme_generic_submit(struct acme_sign_op *op, struct kore_buf *payload)
{
struct acme_request req;
acme_request_prepare(&req, HTTP_METHOD_POST, op->udata,
payload->data, payload->offset);
if (!acme_request_run(&req))
goto cleanup;
if (req.curl.http.status != HTTP_STATUS_OK) {
kore_log(LOG_NOTICE,
"request to '%s' failed: status %ld - body '%s'",
req.curl.url, req.curl.http.status,
kore_curl_response_as_string(&req.curl));
goto cleanup;
}
kore_log(LOG_INFO, "submitted %zu bytes to %s",
payload->offset, req.curl.url);
cleanup:
acme_request_cleanup(&req);
}
static void
acme_request_prepare(struct acme_request *req, int method,
const char *url, const void *data, size_t len)
{
memset(req, 0, sizeof(*req));
if (!kore_curl_init(&req->curl, url, KORE_CURL_SYNC))
fatal("failed to initialize request to '%s'", url);
/* Override default timeout. */
curl_easy_setopt(req->curl.handle,
CURLOPT_TIMEOUT, acme_request_timeout);
kore_curl_http_setup(&req->curl, method, data, len);
kore_curl_http_set_header(&req->curl, "content-type",
"application/jose+json");
}
static void
acme_request_json(struct kore_buf *buf, const char *payload,
const char *protected, const char *sig)
{
struct kore_json_item *json;
json = kore_json_create_object(NULL, NULL);
kore_json_create_string(json, "signature", sig);
kore_json_create_string(json, "payload", payload);
kore_json_create_string(json, "protected", protected);
kore_json_item_tobuf(json, buf);
kore_json_item_free(json);
}
static int
acme_request_run(struct acme_request *req)
{
size_t len;
struct kore_json json;
const u_int8_t *body;
struct kore_json_item *detail;
kore_curl_run(&req->curl);
if (!kore_curl_success(&req->curl)) {
kore_log(LOG_NOTICE, "request to '%s' failed: %s",
req->curl.url, kore_curl_strerror(&req->curl));
return (KORE_RESULT_ERROR);
}
if (req->curl.http.status == HTTP_STATUS_BAD_REQUEST) {
kore_curl_response_as_bytes(&req->curl, &body, &len);
kore_json_init(&json, body, len);
if (!kore_json_parse(&json)) {
detail = NULL;
} else {
detail = kore_json_find_string(json.root, "detail");
}
if (detail != NULL) {
kore_log(LOG_NOTICE,
"request to '%s' failed with 400 - detail: %s",
req->curl.url, detail->data.string);
} else {
kore_log(LOG_NOTICE,
"request to '%s' failed with 400 - body: %.*s",
req->curl.url, (int)len, (const char *)body);
}
kore_json_cleanup(&json);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static void
acme_request_cleanup(struct acme_request *req)
{
kore_curl_cleanup(&req->curl);
}
static void
acme_directory_set(struct kore_json *json, const char *name, char **out)
{
struct kore_json_item *item;
if ((item = kore_json_find_string(json->root, name)) == NULL) {
kore_log(LOG_NOTICE, "directory has missing '%s' URI", name);
return;
}
*out = kore_strdup(item->data.string);
}
static void
acme_sign_submit(struct kore_json_item *json, const char *url, void *udata,
void (*cb)(struct acme_sign_op *, struct kore_buf *))
{
struct acme_sign_op *op;
struct kore_buf buf;
char *nonce;
if ((nonce = acme_nonce_fetch()) == NULL) {
kore_log(LOG_ERR, "failed to fetch nonce from servers");
return;
}
kore_buf_init(&buf, 1024);
if (json != NULL)
kore_json_item_tobuf(json, &buf);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
op = kore_calloc(1, sizeof(*op));
LIST_INSERT_HEAD(&signops, op, list);
op->cb = cb;
op->udata = udata;
op->nonce = nonce;
op->id = signop_id++;
op->payload = acme_base64url(buf.data, buf.offset);
op->protected = acme_protected_component(op->nonce, url);
op->t = kore_timer_add(acme_sign_expire, 30000, op, KORE_TIMER_ONESHOT);
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
kore_buf_reset(&buf);
kore_buf_append(&buf, &op->id, sizeof(op->id));
kore_buf_appendf(&buf, "%s.%s", op->protected, op->payload);
kore_msg_send(KORE_WORKER_KEYMGR, KORE_ACME_SIGN, buf.data, buf.offset);
kore_buf_cleanup(&buf);
}
static void
acme_sign_expire(void *udata, u_int64_t now)
{
struct acme_sign_op *op = udata;
kore_log(LOG_NOTICE, "signop %u expired (no answer)", op->id);
LIST_REMOVE(op, list);
kore_free(op->protected);
kore_free(op->payload);
kore_free(op->udata);
kore_free(op->nonce);
kore_free(op);
}
static void
acme_sign_result(struct kore_msg *msg, const void *data)
{
u_int32_t id;
struct kore_buf buf;
struct acme_sign_op *op;
char *sig;
const u_int8_t *ptr;
if (msg->length < sizeof(id))
fatal("%s: invalid length (%zu)", __func__, msg->length);
ptr = data;
memcpy(&id, ptr, sizeof(id));
ptr += sizeof(id);
msg->length -= sizeof(id);
LIST_FOREACH(op, &signops, list) {
if (op->id == id)
break;
}
if (op == NULL) {
kore_log(LOG_NOTICE,
"received KORE_ACME_SIGN_RESULT for unknown op: %u", id);
return;
}
kore_timer_remove(op->t);
LIST_REMOVE(op, list);
sig = kore_malloc(msg->length + 1);
memcpy(sig, ptr, msg->length);
sig[msg->length] = '\0';
kore_buf_init(&buf, 1024);
acme_request_json(&buf, op->payload, op->protected, sig);
op->cb(op, &buf);
kore_free(op->protected);
kore_free(op->payload);
kore_free(op->udata);
kore_free(op->nonce);
kore_free(op);
kore_free(sig);
kore_buf_cleanup(&buf);
}
static char *
acme_protected_component(const char *nonce, const char *url)
{
char *b64;
struct kore_buf payload;
struct kore_json_item *root, *jwk;
root = kore_json_create_object(NULL, NULL);
kore_json_create_string(root, "url", url);
kore_json_create_string(root, "alg", "RS256");
kore_json_create_string(root, "nonce", nonce);
if (account_id == NULL) {
jwk = kore_json_create_object(root, "jwk");
kore_json_create_string(jwk, "kty", "RSA");
kore_json_create_string(jwk, "e", rsakey_e);
kore_json_create_string(jwk, "n", rsakey_n);
} else {
kore_json_create_string(root, "kid", account_id);
}
kore_buf_init(&payload, 128);
kore_json_item_tobuf(root, &payload);
b64 = acme_base64url(payload.data, payload.offset);
kore_json_item_free(root);
kore_buf_cleanup(&payload);
return (b64);
}
static char *
acme_thumbprint_component(void)
{
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);
return (acme_base64url(digest, sizeof(digest)));
}
static char *
acme_base64url(const void *data, size_t len)
{
char *b64;
if (!kore_base64url_encode(data, len, &b64, KORE_BASE64_RAW)) {
fatal("%s: failed to encode base64url data of %zu bytes",
__func__, len);
}
Add acmev2 (RFC8555) support to Kore. A new acme process is created that communicates with the acme servers. This process does not hold any of your private keys (no account keys, no domain keys etc). Whenever the acme process requires a signed payload it will ask the keymgr process to do the signing with the relevant keys. This process is also sandboxed with pledge+unveil on OpenBSD and seccomp syscall filtering on Linux. The implementation only supports the tls-alpn-01 challenge. This means that you do not need to open additional ports on your machine. http-01 and dns-01 are currently not supported (no wildcard support). A new configuration option "acme_provider" is available and can be set to the acme server its directory. By default this will point to the live letsencrypt environment: https://acme-v02.api.letsencrypt.org/directory The acme process can be controlled via the following config options: - acme_root (where the acme process will chroot/chdir into). - acme_runas (the user the acme process will run as). If none are set, the values from 'root' and 'runas' are taken. If you want to turn on acme for domains you do it as follows: domain kore.io { acme yes } You do not need to specify certkey/certfile anymore, if they are present still they will be overwritten by the acme system. The keymgr will store all certificates and keys under its root (keymgr_root), the account key is stored as "/account-key.pem" and all obtained certificates go under "certificates/<domain>/fullchain.pem" while keys go under "certificates/<domain>/key.pem". Kore will automatically renew certificates if they will expire in 7 days or less.
2019-11-06 19:33:53 +01:00
return (b64);
}
static void
acme_keymgr_key_req(const char *domain, const void *data, size_t len, int msg)
{
struct kore_keyreq req;
struct kore_buf buf;
memset(&req, 0, sizeof(req));
req.data_len = len;
if (kore_strlcpy(req.domain, domain, sizeof(req.domain)) >=
sizeof(req.domain))
fatal("%s: domain truncated", __func__);
kore_buf_init(&buf, sizeof(req) + len);
kore_buf_append(&buf, &req, sizeof(req));
if (data != NULL)
kore_buf_append(&buf, data, len);
kore_msg_send(KORE_WORKER_KEYMGR, msg, buf.data, buf.offset);
kore_buf_cleanup(&buf);
}
static int
acme_status_type(const char *status)
{
int type;
if (!strcmp(status, "pending")) {
type = ACME_STATUS_PENDING;
} else if (!strcmp(status, "processing")) {
type = ACME_STATUS_PROCESSING;
} else if (!strcmp(status, "valid")) {
type = ACME_STATUS_VALID;
} else if (!strcmp(status, "invalid")) {
type = ACME_STATUS_INVALID;
} else if (!strcmp(status, "ready")) {
type = ACME_STATUS_READY;
} else if (!strcmp(status, "expired")) {
type = ACME_STATUS_EXPIRED;
} else if (!strcmp(status, "revoked")) {
type = ACME_STATUS_REVOKED;
} else {
type = -1;
}
return (type);
}
static void
acme_rsakey_exp(struct kore_msg *msg, const void *data)
{
kore_free(rsakey_e);
rsakey_e = kore_calloc(1, msg->length + 1);
memcpy(rsakey_e, data, msg->length);
rsakey_e[msg->length] = '\0';
}
static void
acme_rsakey_mod(struct kore_msg *msg, const void *data)
{
kore_free(rsakey_n);
rsakey_n = kore_calloc(1, msg->length + 1);
memcpy(rsakey_n, data, msg->length);
rsakey_n[msg->length] = '\0';
}