kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

acme.c (44005B)



      1 /*
      2  * Copyright (c) 2019-2022 Joris Vink <joris@coders.se>
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 /*
     18  * ACMEv2 protocol implementation.
     19  *
     20  * The acme process is responsible for talking to the acme servers, parsing
     21  * their JSON responses and requesting signed data / a csr from the keymgr
     22  * process.
     23  *
     24  * The acme process does not hold your account or domain keys, so anything
     25  * that needs to be signed is sent to the keymgr process instead.
     26  */
     27 
     28 #include <sys/types.h>
     29 #include <sys/stat.h>
     30 
     31 #include <openssl/sha.h>
     32 
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 
     36 #include "kore.h"
     37 #include "acme.h"
     38 #include "curl.h"
     39 
     40 #define ACME_CREATE_ACCOUNT	0
     41 #define ACME_RESOLVE_ACCOUNT	1
     42 
     43 #define ACME_STATUS_PENDING	1
     44 #define ACME_STATUS_PROCESSING	2
     45 #define ACME_STATUS_VALID	3
     46 #define ACME_STATUS_INVALID	4
     47 #define ACME_STATUS_READY	5
     48 #define ACME_STATUS_EXPIRED	6
     49 #define ACME_STATUS_REVOKED	7
     50 
     51 /*
     52  * The default provider is letsencrypt, can be overwritten via the config
     53  * file its acme_provider setting.
     54  */
     55 #define ACME_DEFAULT_PROVIDER	"https://acme-v02.api.letsencrypt.org/directory"
     56 
     57 #if defined(__linux__)
     58 #include "seccomp.h"
     59 
     60 /*
     61  * The syscalls our acme worker is allowed to perform, only.
     62  *
     63  * Since we drop all previously loaded seccomp rules to apply our own
     64  * we will have to reinclude the ones curl does.
     65  */
     66 static struct sock_filter filter_acme[] = {
     67 	KORE_SYSCALL_ALLOW(prctl),
     68 #if defined(SYS_poll)
     69 	KORE_SYSCALL_ALLOW(poll),
     70 #endif
     71 	KORE_SYSCALL_ALLOW(ppoll),
     72 	KORE_SYSCALL_ALLOW(sendto),
     73 	KORE_SYSCALL_ALLOW(recvfrom),
     74 #if defined(SYS_epoll_wait)
     75 	KORE_SYSCALL_ALLOW(epoll_wait),
     76 #endif
     77 	KORE_SYSCALL_ALLOW(epoll_pwait),
     78 	KORE_SYSCALL_ALLOW(recvmsg),
     79 	KORE_SYSCALL_ALLOW(sendmsg),
     80 	KORE_SYSCALL_ALLOW(sendmmsg),
     81 	KORE_SYSCALL_ALLOW(getpeername),
     82 
     83 	KORE_SYSCALL_ALLOW(gettid),
     84 	KORE_SYSCALL_ALLOW(exit),
     85 
     86 	KORE_SYSCALL_ALLOW(brk),
     87 #if defined(SYS_mmap)
     88 	KORE_SYSCALL_ALLOW(mmap),
     89 #endif
     90 #if defined(SYS_mmap2)
     91 	KORE_SYSCALL_ALLOW(mmap2),
     92 #endif
     93 	KORE_SYSCALL_ALLOW(ioctl),
     94 	KORE_SYSCALL_ALLOW(uname),
     95 	KORE_SYSCALL_ALLOW(munmap),
     96 	KORE_SYSCALL_ALLOW(madvise),
     97 	KORE_SYSCALL_ALLOW(faccessat),
     98 	KORE_SYSCALL_ALLOW(newfstatat),
     99 	KORE_SYSCALL_ALLOW(clock_gettime),
    100 
    101 	KORE_SYSCALL_ALLOW(bind),
    102 	KORE_SYSCALL_ALLOW(ioctl),
    103 	KORE_SYSCALL_ALLOW(connect),
    104 	KORE_SYSCALL_ALLOW(getsockopt),
    105 	KORE_SYSCALL_ALLOW(socketpair),
    106 	KORE_SYSCALL_ALLOW(getsockname),
    107 	KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET),
    108 	KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_INET6),
    109 	KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_UNIX),
    110 	KORE_SYSCALL_ALLOW_ARG(socket, 0, AF_NETLINK),
    111 
    112 	KORE_SYSCALL_ALLOW(clone),
    113 	KORE_SYSCALL_ALLOW(membarrier),
    114 	KORE_SYSCALL_ALLOW(set_robust_list),
    115 };
    116 #endif
    117 
    118 struct acme_request {
    119 	struct kore_curl	curl;
    120 };
    121 
    122 struct acme_sign_op {
    123 	u_int32_t			id;
    124 	struct kore_timer		*t;
    125 	void				*udata;
    126 	char				*nonce;
    127 	char				*payload;
    128 	char				*protected;
    129 	void				(*cb)(struct acme_sign_op *,
    130 					    struct kore_buf *);
    131 	LIST_ENTRY(acme_sign_op)	list;
    132 };
    133 
    134 #define ACME_AUTH_STATE_DOWNLOAD		1
    135 #define ACME_AUTH_STATE_CHALLENGE		2
    136 
    137 struct acme_auth {
    138 	char				*url;
    139 	struct acme_order		*order;
    140 	int				status;
    141 	struct acme_challenge		*challenge;
    142 	LIST_ENTRY(acme_auth)		list;
    143 };
    144 
    145 #define ACME_ORDER_STATE_RUNNING		1
    146 #define ACME_ORDER_STATE_ERROR			2
    147 #define ACME_ORDER_STATE_CANCELLED		3
    148 #define ACME_ORDER_STATE_UPDATE			4
    149 #define ACME_ORDER_STATE_UPDATE_AUTH		5
    150 #define ACME_ORDER_STATE_WAITING		6
    151 #define ACME_ORDER_STATE_FETCH_CERT		7
    152 #define ACME_ORDER_STATE_COMPLETE		8
    153 #define ACME_ORDER_TICK				1000
    154 #define ACME_ORDER_TIMEOUT			120000
    155 
    156 #define ACME_ORDER_CSR_REQUESTED		0x1000
    157 
    158 struct acme_order {
    159 	int				state;
    160 	int				status;
    161 	int				flags;
    162 	int				auths;
    163 	u_int64_t			start;
    164 	char				*id;
    165 	char				*final;
    166 	char				*domain;
    167 	char				*certloc;
    168 	struct acme_auth		*curauth;
    169 	LIST_HEAD(, acme_auth)		auth;
    170 	LIST_ENTRY(acme_order)		list;
    171 };
    172 
    173 static LIST_HEAD(, acme_order)		orders;
    174 
    175 #define ACME_FLAG_CHALLENGE_CREATED	0x0001
    176 #define ACME_CHALLENGE_TOKEN_MAXLEN	64
    177 
    178 struct acme_challenge {
    179 	int		status;
    180 	int		flags;
    181 	char		*url;
    182 	char		*type;
    183 	char		*token;
    184 	char		*error_type;
    185 	char		*error_detail;
    186 	int		(*process)(struct acme_order *,
    187 			    struct acme_challenge *);
    188 };
    189 
    190 static LIST_HEAD(, acme_sign_op)	signops;
    191 
    192 static int	acme_status_type(const char *);
    193 static int	acme_request_run(struct acme_request *);
    194 static void	acme_request_cleanup(struct acme_request *);
    195 static void	acme_request_prepare(struct acme_request *,
    196 		    int, const char *, const void *, size_t);
    197 static void	acme_request_json(struct kore_buf *, const char *,
    198 		    const char *, const char *);
    199 
    200 static char	*acme_nonce_fetch(void);
    201 static char	*acme_thumbprint_component(void);
    202 static char	*acme_base64url(const void *, size_t);
    203 static char	*acme_protected_component(const char *, const char *);
    204 static void	acme_keymgr_key_req(const char *, const void *, size_t, int);
    205 
    206 static void	acme_parse_directory(void);
    207 static void	acme_directory_set(struct kore_json *, const char *, char **);
    208 
    209 static void	acme_sign_expire(void *, u_int64_t);
    210 static void	acme_sign_result(struct kore_msg *, const void *);
    211 static void	acme_sign_submit(struct kore_json_item *, const char *, void *,
    212 		    void (*cb)(struct acme_sign_op *, struct kore_buf *));
    213 
    214 static void	acme_rsakey_exp(struct kore_msg *, const void *);
    215 static void	acme_rsakey_mod(struct kore_msg *, const void *);
    216 
    217 static void	acme_account_reg(int);
    218 static void	acme_account_create(struct kore_msg *, const void *);
    219 static void	acme_account_resolve(struct kore_msg *, const void *);
    220 static void	acme_generic_submit(struct acme_sign_op *, struct kore_buf *);
    221 static void	acme_account_reg_submit(struct acme_sign_op *,
    222 		    struct kore_buf *);
    223 
    224 static void	acme_order_retry(const char *);
    225 static void	acme_order_process(void *, u_int64_t);
    226 static void	acme_order_update(struct acme_order *);
    227 static void	acme_order_update_submit(struct acme_sign_op *,
    228 		    struct kore_buf *);
    229 static void	acme_order_request_csr(struct acme_order *);
    230 static void	acme_order_fetch_certificate(struct acme_order *);
    231 static void	acme_order_fetch_certificate_submit(struct acme_sign_op *,
    232 		    struct kore_buf *);
    233 static void	acme_order_create(struct kore_msg *, const void *);
    234 static void	acme_order_remove(struct acme_order *, const char *);
    235 static void	acme_order_csr_response(struct kore_msg *, const void *);
    236 static void	acme_order_create_submit(struct acme_sign_op *,
    237 		    struct kore_buf *);
    238 
    239 static void	acme_order_auth_log_error(struct acme_order *);
    240 static void	acme_order_auth_deactivate(struct acme_order *);
    241 static int	acme_order_auth_process(struct acme_order *,
    242 		    struct acme_auth *);
    243 static void	acme_order_auth_update(struct acme_order *,
    244 		    struct acme_auth *);
    245 static void	acme_order_auth_update_submit(struct acme_sign_op *,
    246 		    struct kore_buf *);
    247 
    248 static int	acme_challenge_tls_alpn_01(struct acme_order *,
    249 		    struct acme_challenge *);
    250 static void	acme_challenge_tls_alpn_01_create(struct acme_order *,
    251 		    struct acme_challenge *);
    252 
    253 static void	acme_challenge_respond(struct acme_order *,
    254 		    const char *, const char *);
    255 
    256 static int		signop_id = 0;
    257 static char		*rsakey_n = NULL;
    258 static char		*rsakey_e = NULL;
    259 static char		*nonce_url = NULL;
    260 static char		*order_url = NULL;
    261 static char		*revoke_url = NULL;
    262 static char		*account_id = NULL;
    263 static char		*account_url = NULL;
    264 
    265 struct kore_privsep	acme_privsep;
    266 int			acme_domains = 0;
    267 char			*acme_email = NULL;
    268 char			*acme_provider = NULL;
    269 u_int32_t		acme_request_timeout = 8;
    270 
    271 void
    272 kore_acme_init(void)
    273 {
    274 	acme_provider = kore_strdup(ACME_DEFAULT_PROVIDER);
    275 }
    276 
    277 void
    278 kore_acme_run(void)
    279 {
    280 	int		quit;
    281 	u_int64_t	now, netwait;
    282 
    283 	quit = 0;
    284 
    285 	kore_server_closeall();
    286 	kore_module_cleanup();
    287 
    288 	net_init();
    289 	kore_timer_init();
    290 	kore_connection_init();
    291 	kore_platform_event_init();
    292 	kore_msg_worker_init();
    293 
    294 	kore_msg_register(KORE_ACME_RSAKEY_E, acme_rsakey_exp);
    295 	kore_msg_register(KORE_ACME_RSAKEY_N, acme_rsakey_mod);
    296 	kore_msg_register(KORE_ACME_SIGN_RESULT, acme_sign_result);
    297 	kore_msg_register(KORE_ACME_ORDER_CREATE, acme_order_create);
    298 	kore_msg_register(KORE_ACME_ACCOUNT_CREATE, acme_account_create);
    299 	kore_msg_register(KORE_ACME_ACCOUNT_RESOLVE, acme_account_resolve);
    300 	kore_msg_register(KORE_ACME_CSR_RESPONSE, acme_order_csr_response);
    301 
    302 #if defined(__linux__)
    303 	/* Drop all enabled seccomp filters, and add only ours. */
    304 	kore_seccomp_drop();
    305 	kore_seccomp_filter("acme", filter_acme, KORE_FILTER_LEN(filter_acme));
    306 #endif
    307 #if defined(KORE_USE_PYTHON)
    308 	kore_msg_unregister(KORE_PYTHON_SEND_OBJ);
    309 #endif
    310 	kore_worker_privsep();
    311 
    312 #if defined(__OpenBSD__)
    313 	if (unveil("/etc/ssl/", "r") == -1)
    314 		fatal("unveil: %s", errno_s);
    315 	if (pledge("stdio inet dns rpath", NULL) == -1)
    316 		fatal("pledge acme process: %s", errno_s);
    317 #endif
    318 
    319 	http_init();
    320 
    321 	LIST_INIT(&orders);
    322 	LIST_INIT(&signops);
    323 
    324 	kore_worker_started();
    325 	acme_parse_directory();
    326 
    327 	while (quit != 1) {
    328 		now = kore_time_ms();
    329 		netwait = kore_timer_next_run(now);
    330 		kore_platform_event_wait(netwait);
    331 
    332 		if (sig_recv != 0) {
    333 			switch (sig_recv) {
    334 			case SIGQUIT:
    335 			case SIGINT:
    336 			case SIGTERM:
    337 				quit = 1;
    338 				break;
    339 			default:
    340 				break;
    341 			}
    342 			sig_recv = 0;
    343 		}
    344 
    345 		if (quit)
    346 			break;
    347 
    348 		now = kore_time_ms();
    349 		kore_timer_run(now);
    350 		kore_connection_prune(KORE_CONNECTION_PRUNE_DISCONNECT);
    351 	}
    352 
    353 	kore_platform_event_cleanup();
    354 	kore_connection_cleanup();
    355 	net_cleanup();
    356 }
    357 
    358 void
    359 kore_acme_get_paths(const char *domain, char **key, char **cert)
    360 {
    361 	int		len;
    362 	char		path[MAXPATHLEN];
    363 
    364 	len = snprintf(path, sizeof(path), "%s/%s/fullchain.pem",
    365 	    KORE_ACME_CERTDIR, domain);
    366 	if (len == -1 || (size_t)len >= sizeof(path))
    367 		fatal("failed to create certfile path");
    368 
    369 	*cert = kore_strdup(path);
    370 
    371 	len = snprintf(path, sizeof(path), "%s/%s/key.pem",
    372 	    KORE_ACME_CERTDIR, domain);
    373 	if (len == -1 || (size_t)len >= sizeof(path))
    374 		fatal("failed to create certkey path");
    375 
    376 	*key = kore_strdup(path);
    377 }
    378 
    379 static void
    380 acme_parse_directory(void)
    381 {
    382 	struct acme_request	req;
    383 	size_t			len;
    384 	struct kore_json	json;
    385 	const u_int8_t		*body;
    386 
    387 	acme_request_prepare(&req, HTTP_METHOD_GET, acme_provider, NULL, 0);
    388 
    389 	if (!acme_request_run(&req)) {
    390 		acme_request_cleanup(&req);
    391 		return;
    392 	}
    393 
    394 	if (req.curl.http.status != HTTP_STATUS_OK) {
    395 		kore_log(LOG_NOTICE,
    396 		    "request to '%s' failed: got %ld - expected 200",
    397 		    req.curl.url, req.curl.http.status);
    398 		acme_request_cleanup(&req);
    399 		return;
    400 	}
    401 
    402 	kore_curl_response_as_bytes(&req.curl, &body, &len);
    403 
    404 	kore_json_init(&json, body, len);
    405 
    406 	if (!kore_json_parse(&json)) {
    407 		kore_log(LOG_NOTICE,
    408 		    "failed to parse directory payload from ACME server (%s)",
    409 		    kore_json_strerror());
    410 		goto cleanup;
    411 	}
    412 
    413 	acme_directory_set(&json, "newNonce", &nonce_url);
    414 	acme_directory_set(&json, "newOrder", &order_url);
    415 	acme_directory_set(&json, "newAccount", &account_url);
    416 	acme_directory_set(&json, "revokeCert", &revoke_url);
    417 
    418 cleanup:
    419 	kore_json_cleanup(&json);
    420 	acme_request_cleanup(&req);
    421 }
    422 
    423 static char *
    424 acme_nonce_fetch(void)
    425 {
    426 	struct acme_request	req;
    427 	char			*ret;
    428 	const char		*nonce;
    429 
    430 	ret = NULL;
    431 	acme_request_prepare(&req, HTTP_METHOD_HEAD, nonce_url, NULL, 0);
    432 
    433 	if (!acme_request_run(&req))
    434 		goto cleanup;
    435 
    436 	if (req.curl.http.status != HTTP_STATUS_OK) {
    437 		kore_log(LOG_NOTICE,
    438 		    "request to '%s' failed: got %ld - expected 200",
    439 		    req.curl.url, req.curl.http.status);
    440 		goto cleanup;
    441 	}
    442 
    443 	if (!kore_curl_http_get_header(&req.curl, "replay-nonce", &nonce)) {
    444 		kore_log(LOG_NOTICE, "new-nonce: no replay-nonce header found");
    445 		goto cleanup;
    446 	}
    447 
    448 	ret = kore_strdup(nonce);
    449 
    450 cleanup:
    451 	acme_request_cleanup(&req);
    452 
    453 	return (ret);
    454 }
    455 
    456 static void
    457 acme_account_create(struct kore_msg *msg, const void *data)
    458 {
    459 	acme_account_reg(ACME_CREATE_ACCOUNT);
    460 }
    461 
    462 static void
    463 acme_account_resolve(struct kore_msg *msg, const void *data)
    464 {
    465 	acme_account_reg(ACME_RESOLVE_ACCOUNT);
    466 }
    467 
    468 static void
    469 acme_account_reg(int resolve_only)
    470 {
    471 	int			len;
    472 	char			mail[1024];
    473 	struct kore_json_item	*json, *contact;
    474 
    475 	if (account_url == NULL)
    476 		return;
    477 
    478 	kore_free(account_id);
    479 	account_id = NULL;
    480 
    481 	kore_log(LOG_INFO, "%s account with ACME provider",
    482 	    resolve_only ? "resolving" : "creating");
    483 
    484 	json = kore_json_create_object(NULL, NULL);
    485 	kore_json_create_literal(json, "termsOfServiceAgreed", KORE_JSON_TRUE);
    486 
    487 	if (acme_email) {
    488 		len = snprintf(mail, sizeof(mail), "mailto:%s", acme_email);
    489 		if (len == -1 || (size_t)len >= sizeof(mail))
    490 			fatalx("mail contact '%s' too large", acme_email);
    491 
    492 		contact = kore_json_create_array(json, "contact");
    493 		kore_json_create_string(contact, NULL, mail);
    494 	}
    495 
    496 	if (resolve_only) {
    497 		kore_json_create_literal(json,
    498 		    "onlyReturnExisting", KORE_JSON_TRUE);
    499 	}
    500 
    501 	acme_sign_submit(json, account_url, NULL, acme_account_reg_submit);
    502 	kore_json_item_free(json);
    503 }
    504 
    505 static void
    506 acme_account_reg_submit(struct acme_sign_op *op, struct kore_buf *payload)
    507 {
    508 	struct acme_request	req;
    509 	const char		*header;
    510 
    511 	acme_request_prepare(&req, HTTP_METHOD_POST, account_url,
    512 	    payload->data, payload->offset);
    513 
    514 	if (!acme_request_run(&req))
    515 		goto cleanup;
    516 
    517 	switch (req.curl.http.status) {
    518 	case HTTP_STATUS_OK:
    519 	case HTTP_STATUS_CREATED:
    520 		break;
    521 	default:
    522 		kore_log(LOG_NOTICE,
    523 		    "request to '%s' failed: status %ld - body '%s'",
    524 		    req.curl.url, req.curl.http.status,
    525 		    kore_curl_response_as_string(&req.curl));
    526 		goto cleanup;
    527 	}
    528 
    529 	if (!kore_curl_http_get_header(&req.curl, "location", &header)) {
    530 		kore_log(LOG_NOTICE, "new-acct: no location header found");
    531 		goto cleanup;
    532 	}
    533 
    534 	account_id = kore_strdup(header);
    535 	kore_log(LOG_INFO, "account_id =  %s", account_id);
    536 	kore_msg_send(KORE_WORKER_KEYMGR, KORE_ACME_PROC_READY, NULL, 0);
    537 
    538 cleanup:
    539 	acme_request_cleanup(&req);
    540 }
    541 
    542 static void
    543 acme_order_create(struct kore_msg *msg, const void *data)
    544 {
    545 	char			*domain;
    546 	struct kore_json_item	*json, *identifiers, *identifier;
    547 
    548 	domain = kore_calloc(1, msg->length + 1);
    549 	memcpy(domain, data, msg->length);
    550 	domain[msg->length] = '\0';
    551 
    552 	kore_log(LOG_INFO, "[%s] creating order", domain);
    553 
    554 	json = kore_json_create_object(NULL, NULL);
    555 	identifiers = kore_json_create_array(json, "identifiers");
    556 
    557 	identifier = kore_json_create_object(identifiers, NULL);
    558 	kore_json_create_string(identifier, "type", "dns");
    559 	kore_json_create_string(identifier, "value", domain);
    560 
    561 	acme_sign_submit(json, order_url, domain, acme_order_create_submit);
    562 	kore_json_item_free(json);
    563 }
    564 
    565 static void
    566 acme_order_create_submit(struct acme_sign_op *op, struct kore_buf *payload)
    567 {
    568 	struct acme_request		req;
    569 	size_t				len;
    570 	struct kore_json		json;
    571 	int				stval;
    572 	const u_int8_t			*body;
    573 	struct acme_auth		*auth;
    574 	struct acme_order		*order;
    575 	const char			*header;
    576 	const char			*domain;
    577 	struct kore_json_item		*item, *array, *final, *status;
    578 
    579 	order = NULL;
    580 	domain = op->udata;
    581 	acme_request_prepare(&req, HTTP_METHOD_POST, order_url,
    582 	    payload->data, payload->offset);
    583 
    584 	if (!acme_request_run(&req)) {
    585 		acme_request_cleanup(&req);
    586 		acme_order_retry(domain);
    587 		return;
    588 	}
    589 
    590 	if (req.curl.http.status != HTTP_STATUS_CREATED) {
    591 		kore_log(LOG_NOTICE,
    592 		    "[%s] - request to '%s' failed: status %ld - body '%s'",
    593 		    domain, req.curl.url, req.curl.http.status,
    594 		    kore_curl_response_as_string(&req.curl));
    595 		acme_request_cleanup(&req);
    596 		acme_order_retry(domain);
    597 		return;
    598 	}
    599 
    600 	if (!kore_curl_http_get_header(&req.curl, "location", &header)) {
    601 		kore_log(LOG_NOTICE,
    602 		    "[%s] new-order: no order id found", domain);
    603 		acme_request_cleanup(&req);
    604 		acme_order_retry(domain);
    605 		return;
    606 	}
    607 
    608 	kore_curl_response_as_bytes(&req.curl, &body, &len);
    609 	kore_json_init(&json, body, len);
    610 
    611 	if (!kore_json_parse(&json)) {
    612 		kore_log(LOG_NOTICE,
    613 		    "[%s] failed to parse order payload from ACME server (%s)",
    614 		    domain, kore_json_strerror());
    615 		goto cleanup;
    616 	}
    617 
    618 	array = kore_json_find_array(json.root, "authorizations");
    619 	if (array == NULL) {
    620 		kore_log(LOG_NOTICE, "[%s] body has no 'authorizations' array",
    621 		    domain);
    622 		goto cleanup;
    623 	}
    624 
    625 	if (TAILQ_EMPTY(&array->data.items)) {
    626 		kore_log(LOG_NOTICE, "[%s] no authoritization URLs in payload",
    627 		    domain);
    628 		goto cleanup;
    629 	}
    630 
    631 	if ((status = kore_json_find_string(json.root, "status")) == NULL) {
    632 		kore_log(LOG_NOTICE, "[%s] order has no 'status' string",
    633 		    domain);
    634 		goto cleanup;
    635 	}
    636 
    637 	if ((final = kore_json_find_string(json.root, "finalize")) == NULL) {
    638 		kore_log(LOG_NOTICE, "[%s] order has no 'finalize' string",
    639 		    domain);
    640 		goto cleanup;
    641 	}
    642 
    643 	if ((stval = acme_status_type(status->data.string)) == -1) {
    644 		kore_log(LOG_NOTICE, "[%s] order has invalid status",
    645 		    domain);
    646 		goto cleanup;
    647 	}
    648 
    649 	order = kore_calloc(1, sizeof(*order));
    650 	LIST_INSERT_HEAD(&orders, order, list);
    651 
    652 	LIST_INIT(&order->auth);
    653 
    654 	order->status = stval;
    655 	order->start = kore_time_ms();
    656 	order->id = kore_strdup(header);
    657 	order->domain = kore_strdup(domain);
    658 	order->state = ACME_ORDER_STATE_UPDATE;
    659 	order->final = kore_strdup(final->data.string);
    660 
    661 	kore_timer_add(acme_order_process, ACME_ORDER_TICK,
    662 	    order, KORE_TIMER_ONESHOT);
    663 
    664 	TAILQ_FOREACH(item, &array->data.items, list) {
    665 		if (item->type != KORE_JSON_TYPE_STRING)
    666 			continue;
    667 
    668 		auth = kore_calloc(1, sizeof(*auth));
    669 		auth->order = order;
    670 		auth->url = kore_strdup(item->data.string);
    671 		LIST_INSERT_HEAD(&order->auth, auth, list);
    672 	}
    673 
    674 	order->curauth = LIST_FIRST(&order->auth);
    675 	kore_log(LOG_INFO, "[%s] order_id =  %s", order->domain, order->id);
    676 
    677 cleanup:
    678 	if (order == NULL)
    679 		acme_order_retry(domain);
    680 
    681 	kore_json_cleanup(&json);
    682 	acme_request_cleanup(&req);
    683 }
    684 
    685 static void
    686 acme_order_update(struct acme_order *order)
    687 {
    688 	acme_sign_submit(NULL, order->id, order, acme_order_update_submit);
    689 }
    690 
    691 static void
    692 acme_order_update_submit(struct acme_sign_op *op, struct kore_buf *payload)
    693 {
    694 	struct acme_request		req;
    695 	size_t				len;
    696 	struct kore_json		json;
    697 	struct acme_order		*order;
    698 	const u_int8_t			*body;
    699 	int				stval, ret;
    700 	struct kore_json_item		*status, *cert;
    701 
    702 	order = op->udata;
    703 	op->udata = NULL;
    704 
    705 	acme_request_prepare(&req, HTTP_METHOD_POST, order->id,
    706 	    payload->data, payload->offset);
    707 
    708 	if (!acme_request_run(&req)) {
    709 		acme_request_cleanup(&req);
    710 		order->state = ACME_ORDER_STATE_ERROR;
    711 		return;
    712 	}
    713 
    714 	if (req.curl.http.status != HTTP_STATUS_OK) {
    715 		kore_log(LOG_NOTICE,
    716 		    "[%s] - request to '%s' failed: status %ld - body '%s'",
    717 		    order->domain, req.curl.url, req.curl.http.status,
    718 		    kore_curl_response_as_string(&req.curl));
    719 		acme_request_cleanup(&req);
    720 		order->state = ACME_ORDER_STATE_ERROR;
    721 		return;
    722 	}
    723 
    724 	ret = KORE_RESULT_ERROR;
    725 	kore_curl_response_as_bytes(&req.curl, &body, &len);
    726 
    727 	kore_json_init(&json, body, len);
    728 
    729 	if (!kore_json_parse(&json)) {
    730 		kore_log(LOG_NOTICE,
    731 		    "[%s] failed to parse order payload from ACME server (%s)",
    732 		    order->domain, kore_json_strerror());
    733 		goto cleanup;
    734 	}
    735 
    736 	if ((status = kore_json_find_string(json.root, "status")) == NULL) {
    737 		kore_log(LOG_NOTICE, "[%s] order has no 'status' string",
    738 		    order->domain);
    739 		goto cleanup;
    740 	}
    741 
    742 	if ((stval = acme_status_type(status->data.string)) == -1) {
    743 		kore_log(LOG_NOTICE, "[%s] order has invalid status",
    744 		    order->domain);
    745 		goto cleanup;
    746 	}
    747 
    748 	order->status = stval;
    749 
    750 	if (order->status == ACME_STATUS_VALID) {
    751 		cert = kore_json_find_string(json.root, "certificate");
    752 		if (cert == NULL) {
    753 			kore_log(LOG_NOTICE,
    754 			    "[%s] order has 'certificate' member",
    755 			    order->domain);
    756 			goto cleanup;
    757 		}
    758 
    759 		order->certloc = kore_strdup(cert->data.string);
    760 	}
    761 
    762 	ret = KORE_RESULT_OK;
    763 
    764 cleanup:
    765 	if (ret == KORE_RESULT_ERROR)
    766 		order->state = ACME_ORDER_STATE_ERROR;
    767 	else
    768 		order->state = ACME_ORDER_STATE_UPDATE_AUTH;
    769 
    770 	kore_json_cleanup(&json);
    771 	acme_request_cleanup(&req);
    772 }
    773 
    774 /*
    775  * We currently don't care why an order may have failed, (rate-limited,
    776  * auth failed, etc).
    777  *
    778  * It would be neat if we could obey that a bit better.
    779  */
    780 static void
    781 acme_order_retry(const char *domain)
    782 {
    783 	u_int32_t	retry_after;
    784 
    785 	/* arbitrary number */
    786 	retry_after = 60000;
    787 
    788 	acme_keymgr_key_req(domain, &retry_after, sizeof(retry_after),
    789 	    KORE_ACME_ORDER_FAILED);
    790 }
    791 
    792 /*
    793  * Process an order, step by step.
    794  *
    795  * This callback is called every second to check on an active order.
    796  * It will first update the order if required, and updated any of its
    797  * active awuthoritizations to get the latest data.
    798  */
    799 static void
    800 acme_order_process(void *udata, u_int64_t now)
    801 {
    802 	struct acme_auth	*auth;
    803 	struct acme_order	*order = udata;
    804 
    805 	if ((now - order->start) >= ACME_ORDER_TIMEOUT) {
    806 		acme_order_auth_deactivate(order);
    807 		acme_order_remove(order, "order ran too long");
    808 		return;
    809 	}
    810 
    811 	switch (order->state) {
    812 	case ACME_ORDER_STATE_WAITING:
    813 		break;
    814 	case ACME_ORDER_STATE_UPDATE:
    815 		acme_order_update(order);
    816 		order->state = ACME_ORDER_STATE_WAITING;
    817 		break;
    818 	case ACME_ORDER_STATE_UPDATE_AUTH:
    819 		order->auths = 0;
    820 		LIST_FOREACH(auth, &order->auth, list) {
    821 			acme_order_auth_update(order, auth);
    822 			order->auths++;
    823 		}
    824 		order->state = ACME_ORDER_STATE_WAITING;
    825 		break;
    826 	case ACME_ORDER_STATE_CANCELLED:
    827 		acme_order_remove(order, "cancelled");
    828 		order = NULL;
    829 		break;
    830 	case ACME_ORDER_STATE_COMPLETE:
    831 		acme_order_remove(order, "completed");
    832 		order = NULL;
    833 		break;
    834 	case ACME_ORDER_STATE_FETCH_CERT:
    835 		acme_order_fetch_certificate(order);
    836 		order->state = ACME_ORDER_STATE_WAITING;
    837 		break;
    838 	case ACME_ORDER_STATE_RUNNING:
    839 		switch (order->status) {
    840 		case ACME_STATUS_PENDING:
    841 			if (!acme_order_auth_process(order, order->curauth)) {
    842 				acme_order_auth_log_error(order);
    843 				acme_order_remove(order, "cancelled");
    844 				order = NULL;
    845 			}
    846 			break;
    847 		case ACME_STATUS_READY:
    848 			acme_order_request_csr(order);
    849 			break;
    850 		case ACME_STATUS_PROCESSING:
    851 			kore_log(LOG_INFO, "[%s] waiting for certificate",
    852 			    order->domain);
    853 			break;
    854 		case ACME_STATUS_VALID:
    855 			kore_log(LOG_INFO, "[%s] certificate available",
    856 			    order->domain);
    857 			order->state = ACME_ORDER_STATE_FETCH_CERT;
    858 			break;
    859 		case ACME_STATUS_INVALID:
    860 			kore_log(LOG_INFO, "[%s] order authorization failed",
    861 			    order->domain);
    862 			acme_order_auth_log_error(order);
    863 			acme_order_remove(order, "authorization failure");
    864 			order = NULL;
    865 			break;
    866 		default:
    867 			acme_order_auth_deactivate(order);
    868 			acme_order_remove(order, "unknown status");
    869 			order = NULL;
    870 			break;
    871 		}
    872 		break;
    873 	case ACME_ORDER_STATE_ERROR:
    874 		acme_order_auth_deactivate(order);
    875 		acme_order_remove(order, "error");
    876 		order = NULL;
    877 		break;
    878 	default:
    879 		fatal("%s: invalid order state %d", __func__, order->state);
    880 	}
    881 
    882 	if (order != NULL) {
    883 		/* Do not go back to update if we are ready for the cert. */
    884 		if (order->state != ACME_ORDER_STATE_FETCH_CERT)
    885 			order->state = ACME_ORDER_STATE_UPDATE;
    886 
    887 		kore_timer_add(acme_order_process, ACME_ORDER_TICK,
    888 		    order, KORE_TIMER_ONESHOT);
    889 	}
    890 }
    891 
    892 static void
    893 acme_order_remove(struct acme_order *order, const char *reason)
    894 {
    895 	struct acme_auth	*auth;
    896 
    897 	LIST_REMOVE(order, list);
    898 
    899 	while ((auth = LIST_FIRST(&order->auth)) != NULL) {
    900 		LIST_REMOVE(auth, list);
    901 
    902 		if (auth->challenge != NULL) {
    903 			kore_free(auth->challenge->error_detail);
    904 			kore_free(auth->challenge->error_type);
    905 			kore_free(auth->challenge->token);
    906 			kore_free(auth->challenge->type);
    907 			kore_free(auth->challenge->url);
    908 			kore_free(auth->challenge);
    909 		}
    910 
    911 		kore_free(auth->url);
    912 		kore_free(auth);
    913 	}
    914 
    915 	kore_log(LOG_INFO, "[%s] order removed (%s)", order->domain, reason);
    916 
    917 	if (strcmp(reason, "completed"))
    918 		acme_order_retry(order->domain);
    919 
    920 	kore_free(order->domain);
    921 	kore_free(order->final);
    922 	kore_free(order->id);
    923 	kore_free(order);
    924 }
    925 
    926 static void
    927 acme_order_fetch_certificate(struct acme_order *order)
    928 {
    929 	acme_sign_submit(NULL, order->certloc, order,
    930 	    acme_order_fetch_certificate_submit);
    931 }
    932 
    933 static void
    934 acme_order_fetch_certificate_submit(struct acme_sign_op *op,
    935     struct kore_buf *payload)
    936 {
    937 	struct acme_request	req;
    938 	size_t			len;
    939 	const u_int8_t		*body;
    940 	struct acme_order	*order;
    941 
    942 	order = op->udata;
    943 	op->udata = NULL;
    944 
    945 	acme_request_prepare(&req, HTTP_METHOD_POST, order->certloc,
    946 	    payload->data, payload->offset);
    947 
    948 	if (!acme_request_run(&req)) {
    949 		acme_request_cleanup(&req);
    950 		order->state = ACME_ORDER_STATE_CANCELLED;
    951 		return;
    952 	}
    953 
    954 	if (req.curl.http.status != HTTP_STATUS_OK) {
    955 		kore_log(LOG_NOTICE,
    956 		    "[%s] request to '%s' failed: got %ld - expected 200",
    957 		    order->domain, order->certloc, req.curl.http.status);
    958 		acme_request_cleanup(&req);
    959 		order->state = ACME_ORDER_STATE_CANCELLED;
    960 		return;
    961 	}
    962 
    963 	kore_curl_response_as_bytes(&req.curl, &body, &len);
    964 
    965 	kore_log(LOG_INFO, "got %zu bytes of cert data", len);
    966 	acme_keymgr_key_req(order->domain, body, len, KORE_ACME_INSTALL_CERT);
    967 
    968 	acme_request_cleanup(&req);
    969 	order->state = ACME_ORDER_STATE_COMPLETE;
    970 }
    971 
    972 static void
    973 acme_order_request_csr(struct acme_order *order)
    974 {
    975 	if (order->flags & ACME_ORDER_CSR_REQUESTED)
    976 		return;
    977 
    978 	kore_log(LOG_INFO, "[%s] requesting CSR", order->domain);
    979 
    980 	order->flags |= ACME_ORDER_CSR_REQUESTED;
    981 	acme_keymgr_key_req(order->domain, NULL, 0, KORE_ACME_CSR_REQUEST);
    982 }
    983 
    984 static void
    985 acme_order_csr_response(struct kore_msg *msg, const void *data)
    986 {
    987 	const struct kore_x509_msg	*req;
    988 	struct kore_json_item		*json;
    989 	struct acme_order		*order;
    990 	char				*b64, *url;
    991 
    992 	if (!kore_worker_keymgr_response_verify(msg, data, NULL))
    993 		return;
    994 
    995 	req = (const struct kore_x509_msg *)data;
    996 
    997 	LIST_FOREACH(order, &orders, list) {
    998 		if (!strcmp(order->domain, req->domain))
    999 			break;
   1000 	}
   1001 
   1002 	if (order == NULL) {
   1003 		kore_log(LOG_NOTICE, "[%s] csr received but no order active",
   1004 		    req->domain);
   1005 		return;
   1006 	}
   1007 
   1008 	url = kore_strdup(order->final);
   1009 	b64 = acme_base64url(req->data, req->data_len);
   1010 
   1011 	json = kore_json_create_object(NULL, NULL);
   1012 	kore_json_create_string(json, "csr", b64);
   1013 	acme_sign_submit(json, url, url, acme_generic_submit);
   1014 
   1015 	kore_json_item_free(json);
   1016 	kore_free(b64);
   1017 }
   1018 
   1019 static void
   1020 acme_order_auth_deactivate(struct acme_order *order)
   1021 {
   1022 	struct acme_request	req;
   1023 	struct acme_auth	*auth;
   1024 
   1025 	LIST_FOREACH(auth, &order->auth, list) {
   1026 		acme_request_prepare(&req, HTTP_METHOD_GET, auth->url, NULL, 0);
   1027 
   1028 		if (!acme_request_run(&req)) {
   1029 			kore_log(LOG_NOTICE,
   1030 			    "[%s:auth] failed to deactivate %s", order->domain,
   1031 			    auth->url);
   1032 		} else {
   1033 			kore_log(LOG_NOTICE, "[%s:auth] deactivated %s",
   1034 			    order->domain, auth->url);
   1035 		}
   1036 
   1037 		acme_request_cleanup(&req);
   1038 	}
   1039 }
   1040 
   1041 static void
   1042 acme_order_auth_log_error(struct acme_order *order)
   1043 {
   1044 	struct acme_auth	*auth;
   1045 
   1046 	LIST_FOREACH(auth, &order->auth, list) {
   1047 		if (auth->challenge->status == ACME_STATUS_PENDING ||
   1048 		    auth->challenge->status == ACME_STATUS_VALID ||
   1049 		    auth->challenge->status == ACME_STATUS_PROCESSING)
   1050 			continue;
   1051 
   1052 		kore_log(LOG_INFO, "[%s:auth:challenge] %s = %s (%s)",
   1053 		    order->domain, auth->challenge->type,
   1054 		    auth->challenge->error_type, auth->challenge->error_detail);
   1055 	}
   1056 }
   1057 
   1058 static int
   1059 acme_order_auth_process(struct acme_order *order, struct acme_auth *auth)
   1060 {
   1061 	int		ret;
   1062 
   1063 	if (auth == NULL)
   1064 		return (KORE_RESULT_OK);
   1065 
   1066 	ret = KORE_RESULT_ERROR;
   1067 	kore_log(LOG_INFO, "[%s] processing authentication", order->domain);
   1068 
   1069 	switch (auth->status) {
   1070 	case ACME_STATUS_PENDING:
   1071 		ret = auth->challenge->process(order, auth->challenge);
   1072 		break;
   1073 	case ACME_STATUS_VALID:
   1074 	case ACME_STATUS_PROCESSING:
   1075 		ret = KORE_RESULT_OK;
   1076 		break;
   1077 	case ACME_STATUS_INVALID:
   1078 		kore_log(LOG_NOTICE, "[%s:auth] authorization invalid",
   1079 		    order->domain);
   1080 		break;
   1081 	case ACME_STATUS_EXPIRED:
   1082 		kore_log(LOG_NOTICE, "[%s:auth] authorization expired",
   1083 		    order->domain);
   1084 		break;
   1085 	case ACME_STATUS_REVOKED:
   1086 		kore_log(LOG_NOTICE, "[%s:auth] authorization revoked",
   1087 		    order->domain);
   1088 		break;
   1089 	default:
   1090 		kore_log(LOG_NOTICE, "[%s:auth] invalid auth status %d",
   1091 		    order->domain, auth->status);
   1092 		break;
   1093 	}
   1094 
   1095 	if (ret == KORE_RESULT_OK)
   1096 		order->curauth = LIST_NEXT(order->curauth, list);
   1097 
   1098 	return (ret);
   1099 }
   1100 
   1101 static void
   1102 acme_order_auth_update(struct acme_order *order, struct acme_auth *auth)
   1103 {
   1104 	acme_sign_submit(NULL, auth->url, auth, acme_order_auth_update_submit);
   1105 }
   1106 
   1107 static void
   1108 acme_order_auth_update_submit(struct acme_sign_op *op, struct kore_buf *payload)
   1109 {
   1110 	const char			*p;
   1111 	struct acme_request		req;
   1112 	size_t				len;
   1113 	struct kore_json		json;
   1114 	const u_int8_t			*body;
   1115 	struct acme_auth		*auth;
   1116 	struct acme_order		*order;
   1117 	struct acme_challenge		*challenge;
   1118 	int				ret, stval;
   1119 	struct kore_json_item		*status, *type, *url, *token;
   1120 	struct kore_json_item		*array, *object, *err, *detail;
   1121 
   1122 	ret = KORE_RESULT_ERROR;
   1123 	memset(&json, 0, sizeof(json));
   1124 
   1125 	auth = op->udata;
   1126 	order = auth->order;
   1127 
   1128 	op->udata = NULL;
   1129 
   1130 	acme_request_prepare(&req, HTTP_METHOD_POST, auth->url,
   1131 	    payload->data, payload->offset);
   1132 
   1133 	if (!acme_request_run(&req))
   1134 		goto cleanup;
   1135 
   1136 	if (req.curl.http.status != HTTP_STATUS_OK) {
   1137 		kore_log(LOG_NOTICE,
   1138 		    "[%s:auth] request to '%s' failed: got %ld - expected 200",
   1139 		    order->domain, auth->url, req.curl.http.status);
   1140 		goto cleanup;
   1141 	}
   1142 
   1143 	kore_curl_response_as_bytes(&req.curl, &body, &len);
   1144 
   1145 	kore_json_init(&json, body, len);
   1146 
   1147 	if (!kore_json_parse(&json)) {
   1148 		kore_log(LOG_NOTICE,
   1149 		    "[%s:auth] failed to parse payload from ACME server (%s)",
   1150 		    order->domain, kore_json_strerror());
   1151 		goto cleanup;
   1152 	}
   1153 
   1154 	kore_log(LOG_INFO, "[%s:auth] %s updated", order->domain, auth->url);
   1155 
   1156 	if ((status = kore_json_find_string(json.root, "status")) == NULL) {
   1157 		kore_log(LOG_NOTICE, "[%s:auth] payload has no 'status' string",
   1158 		    order->domain);
   1159 		goto cleanup;
   1160 	}
   1161 
   1162 	if ((array = kore_json_find_array(json.root, "challenges")) == NULL) {
   1163 		kore_log(LOG_NOTICE,
   1164 		    "[%s:auth] payload has no 'challenges' array",
   1165 		    order->domain);
   1166 		goto cleanup;
   1167 	}
   1168 
   1169 	if (TAILQ_EMPTY(&array->data.items)) {
   1170 		kore_log(LOG_NOTICE,
   1171 		    "[%s:auth] no challenges URLs in challenge array",
   1172 		    order->domain);
   1173 		goto cleanup;
   1174 	}
   1175 
   1176 	if ((stval = acme_status_type(status->data.string)) == -1) {
   1177 		kore_log(LOG_NOTICE, "[%s] auth has invalid status",
   1178 		    order->domain);
   1179 		goto cleanup;
   1180 	}
   1181 
   1182 	auth->status = stval;
   1183 
   1184 	TAILQ_FOREACH(object, &array->data.items, list) {
   1185 		if (object->type != KORE_JSON_TYPE_OBJECT)
   1186 			continue;
   1187 
   1188 		if ((type = kore_json_find_string(object, "type")) == NULL) {
   1189 			kore_log(LOG_NOTICE,
   1190 			    "[%s:auth:challenge] no type", order->domain);
   1191 			continue;
   1192 		}
   1193 
   1194 		/*
   1195 		 * We only support tls-alpn-01 for now, we ignore the rest.
   1196 		 */
   1197 		if (strcmp(type->data.string, "tls-alpn-01"))
   1198 			continue;
   1199 
   1200 		url = kore_json_find_string(object, "url");
   1201 		token = kore_json_find_string(object, "token");
   1202 		status = kore_json_find_string(object, "status");
   1203 
   1204 		if (url == NULL || token == NULL || status == NULL) {
   1205 			kore_log(LOG_NOTICE,
   1206 			    "[%s:auth:challenge] missing members",
   1207 			    order->domain);
   1208 			continue;
   1209 		}
   1210 
   1211 		if (strlen(token->data.string) > ACME_CHALLENGE_TOKEN_MAXLEN) {
   1212 			kore_log(LOG_NOTICE,
   1213 			    "[%s:auth:challenge] invalid token length",
   1214 			    order->domain);
   1215 			continue;
   1216 		}
   1217 
   1218 		for (p = token->data.string; *p != '\0'; p++) {
   1219 			if ((*p >= 'a' && *p <= 'z') ||
   1220 			    (*p >= 'A' && *p <= 'Z') ||
   1221 			    (*p >= '0' && *p <= '9') || *p == '_' || *p == '-')
   1222 				continue;
   1223 			break;
   1224 		}
   1225 
   1226 		if (*p != '\0') {
   1227 			kore_log(LOG_NOTICE,
   1228 			    "[%s:auth:challenge] invalid token",
   1229 			    order->domain);
   1230 			continue;
   1231 		}
   1232 
   1233 		if ((stval = acme_status_type(status->data.string)) == -1) {
   1234 			kore_log(LOG_NOTICE,
   1235 			    "[%s:auth:challenge] invalid challenge status",
   1236 			    order->domain);
   1237 			continue;
   1238 		}
   1239 
   1240 		if (auth->challenge == NULL) {
   1241 			challenge = kore_calloc(1, sizeof(*challenge));
   1242 
   1243 			challenge->url = kore_strdup(url->data.string);
   1244 			challenge->process = acme_challenge_tls_alpn_01;
   1245 			challenge->token = kore_strdup(token->data.string);
   1246 			challenge->type = kore_strdup(type->data.string);
   1247 
   1248 			auth->challenge = challenge;
   1249 		} else {
   1250 			challenge = auth->challenge;
   1251 		}
   1252 
   1253 		challenge->status = stval;
   1254 
   1255 		if (challenge->status == ACME_STATUS_INVALID &&
   1256 		    (err = kore_json_find_object(object, "error")) != NULL) {
   1257 			type = kore_json_find_string(err, "type");
   1258 			detail = kore_json_find_string(err, "detail");
   1259 
   1260 			if (type == NULL || detail == NULL) {
   1261 				kore_log(LOG_NOTICE,
   1262 				    "[%s:auth:challenge] error missing fields",
   1263 				    order->domain);
   1264 			} else {
   1265 				kore_free(challenge->error_type);
   1266 				kore_free(challenge->error_detail);
   1267 
   1268 				challenge->error_type =
   1269 				    kore_strdup(type->data.string);
   1270 				challenge->error_detail =
   1271 				    kore_strdup(detail->data.string);
   1272 			}
   1273 		}
   1274 
   1275 		break;
   1276 	}
   1277 
   1278 	if (auth->challenge == NULL) {
   1279 		kore_log(LOG_NOTICE,
   1280 		    "[%s:auth] no supported challenges found", order->domain);
   1281 		goto cleanup;
   1282 	}
   1283 
   1284 	ret = KORE_RESULT_OK;
   1285 
   1286 cleanup:
   1287 	if (ret != KORE_RESULT_OK) {
   1288 		order->state = ACME_ORDER_STATE_CANCELLED;
   1289 	} else {
   1290 		order->auths--;
   1291 		if (order->auths == 0) {
   1292 			kore_log(LOG_INFO,
   1293 			    "[%s:auth] authentications done", order->domain);
   1294 			order->state = ACME_ORDER_STATE_RUNNING;
   1295 		}
   1296 	}
   1297 
   1298 	kore_json_cleanup(&json);
   1299 	acme_request_cleanup(&req);
   1300 }
   1301 
   1302 static int
   1303 acme_challenge_tls_alpn_01(struct acme_order *order,
   1304     struct acme_challenge *challenge)
   1305 {
   1306 	int			ret;
   1307 
   1308 	ret = KORE_RESULT_RETRY;
   1309 
   1310 	switch (challenge->status) {
   1311 	case ACME_STATUS_PENDING:
   1312 		acme_challenge_tls_alpn_01_create(order, challenge);
   1313 		break;
   1314 	case ACME_STATUS_PROCESSING:
   1315 		kore_log(LOG_INFO,
   1316 		    "[%s:auth:challenge:tls-alpn-01] processing",
   1317 		    order->domain);
   1318 		break;
   1319 	case ACME_STATUS_VALID:
   1320 		kore_log(LOG_INFO,
   1321 		    "[%s:auth:challenge:tls-alpn-01] valid",
   1322 		    order->domain);
   1323 		ret = KORE_RESULT_OK;
   1324 		break;
   1325 	default:
   1326 		kore_log(LOG_NOTICE,
   1327 		    "[%s:auth:challenge:tls-alpn-01] invalid (%d)",
   1328 		    order->domain, challenge->status);
   1329 		ret = KORE_RESULT_ERROR;
   1330 		break;
   1331 	}
   1332 
   1333 	return (ret);
   1334 }
   1335 
   1336 static void
   1337 acme_challenge_tls_alpn_01_create(struct acme_order *order,
   1338     struct acme_challenge *challenge)
   1339 {
   1340 	struct kore_buf		auth;
   1341 	char			*thumb;
   1342 	u_int8_t		digest[SHA256_DIGEST_LENGTH];
   1343 
   1344 	if (challenge->flags & ACME_FLAG_CHALLENGE_CREATED) {
   1345 		kore_log(LOG_INFO,
   1346 		    "[%s:auth:challenge:tls-alpn-01] pending keymgr",
   1347 		    order->domain);
   1348 		return;
   1349 	}
   1350 
   1351 	challenge->flags |= ACME_FLAG_CHALLENGE_CREATED;
   1352 
   1353 	kore_log(LOG_INFO,
   1354 	    "[%s:auth:challenge:tls-alpn-01] requested from keymgr",
   1355 	    order->domain);
   1356 
   1357 	thumb = acme_thumbprint_component();
   1358 
   1359 	kore_buf_init(&auth, 128);
   1360 	kore_buf_appendf(&auth, "%s.%s", challenge->token, thumb);
   1361 	(void)SHA256(auth.data, auth.offset, digest);
   1362 
   1363 	kore_buf_cleanup(&auth);
   1364 	kore_free(thumb);
   1365 
   1366 	acme_keymgr_key_req(order->domain, digest, sizeof(digest),
   1367 	    KORE_ACME_CHALLENGE_CERT);
   1368 
   1369 	/* XXX - this maybe too fast, keymgr may not have had time. */
   1370 	acme_challenge_respond(order, challenge->url, "tls-alpn-01");
   1371 }
   1372 
   1373 static void
   1374 acme_challenge_respond(struct acme_order *order, const char *url,
   1375     const char *name)
   1376 {
   1377 	struct kore_json_item	*json;
   1378 	char			*copy;
   1379 
   1380 	kore_log(LOG_INFO, "[%s:auth:challenge:%s] submitting challenge",
   1381 	    order->domain, name);
   1382 
   1383 	copy = kore_strdup(url);
   1384 
   1385 	json = kore_json_create_object(NULL, NULL);
   1386 	acme_sign_submit(json, url, copy, acme_generic_submit);
   1387 	kore_json_item_free(json);
   1388 }
   1389 
   1390 static void
   1391 acme_generic_submit(struct acme_sign_op *op, struct kore_buf *payload)
   1392 {
   1393 	struct acme_request	req;
   1394 
   1395 	acme_request_prepare(&req, HTTP_METHOD_POST, op->udata,
   1396 	    payload->data, payload->offset);
   1397 
   1398 	if (!acme_request_run(&req))
   1399 		goto cleanup;
   1400 
   1401 	if (req.curl.http.status != HTTP_STATUS_OK) {
   1402 		kore_log(LOG_NOTICE,
   1403 		    "request to '%s' failed: status %ld - body '%s'",
   1404 		    req.curl.url, req.curl.http.status,
   1405 		    kore_curl_response_as_string(&req.curl));
   1406 		goto cleanup;
   1407 	}
   1408 
   1409 	kore_log(LOG_INFO, "submitted %zu bytes to %s",
   1410 	    payload->offset, req.curl.url);
   1411 
   1412 cleanup:
   1413 	acme_request_cleanup(&req);
   1414 }
   1415 
   1416 static void
   1417 acme_request_prepare(struct acme_request *req, int method,
   1418     const char *url, const void *data, size_t len)
   1419 {
   1420 	memset(req, 0, sizeof(*req));
   1421 
   1422 	if (!kore_curl_init(&req->curl, url, KORE_CURL_SYNC))
   1423 		fatal("failed to initialize request to '%s'", url);
   1424 
   1425 	/* Override default timeout. */
   1426 	curl_easy_setopt(req->curl.handle,
   1427 	    CURLOPT_TIMEOUT, acme_request_timeout);
   1428 
   1429 	kore_curl_http_setup(&req->curl, method, data, len);
   1430 	kore_curl_http_set_header(&req->curl, "content-type",
   1431 	    "application/jose+json");
   1432 }
   1433 
   1434 static void
   1435 acme_request_json(struct kore_buf *buf, const char *payload,
   1436     const char *protected, const char *sig)
   1437 {
   1438 	struct kore_json_item	*json;
   1439 
   1440 	json = kore_json_create_object(NULL, NULL);
   1441 
   1442 	kore_json_create_string(json, "signature", sig);
   1443 	kore_json_create_string(json, "payload", payload);
   1444 	kore_json_create_string(json, "protected", protected);
   1445 
   1446 	kore_json_item_tobuf(json, buf);
   1447 	kore_json_item_free(json);
   1448 }
   1449 
   1450 static int
   1451 acme_request_run(struct acme_request *req)
   1452 {
   1453 	size_t				len;
   1454 	struct kore_json		json;
   1455 	const u_int8_t			*body;
   1456 	struct kore_json_item		*detail;
   1457 
   1458 	kore_curl_run(&req->curl);
   1459 
   1460 	if (!kore_curl_success(&req->curl)) {
   1461 		kore_log(LOG_NOTICE, "request to '%s' failed: %s",
   1462 		    req->curl.url, kore_curl_strerror(&req->curl));
   1463 		return (KORE_RESULT_ERROR);
   1464 	}
   1465 
   1466 	if (req->curl.http.status == HTTP_STATUS_BAD_REQUEST) {
   1467 		kore_curl_response_as_bytes(&req->curl, &body, &len);
   1468 		kore_json_init(&json, body, len);
   1469 
   1470 		if (!kore_json_parse(&json)) {
   1471 			detail = NULL;
   1472 		} else {
   1473 			detail = kore_json_find_string(json.root, "detail");
   1474 		}
   1475 
   1476 		if (detail != NULL) {
   1477 			kore_log(LOG_NOTICE,
   1478 			    "request to '%s' failed with 400 - detail: %s",
   1479 			    req->curl.url, detail->data.string);
   1480 		} else {
   1481 			kore_log(LOG_NOTICE,
   1482 			    "request to '%s' failed with 400 - body: %.*s",
   1483 			    req->curl.url, (int)len, (const char *)body);
   1484 		}
   1485 
   1486 		kore_json_cleanup(&json);
   1487 		return (KORE_RESULT_ERROR);
   1488 	}
   1489 
   1490 	return (KORE_RESULT_OK);
   1491 }
   1492 
   1493 static void
   1494 acme_request_cleanup(struct acme_request *req)
   1495 {
   1496 	kore_curl_cleanup(&req->curl);
   1497 }
   1498 
   1499 static void
   1500 acme_directory_set(struct kore_json *json, const char *name, char **out)
   1501 {
   1502 	struct kore_json_item	*item;
   1503 
   1504 	if ((item = kore_json_find_string(json->root, name)) == NULL) {
   1505 		kore_log(LOG_NOTICE, "directory has missing '%s' URI", name);
   1506 		return;
   1507 	}
   1508 
   1509 	*out = kore_strdup(item->data.string);
   1510 }
   1511 
   1512 static void
   1513 acme_sign_submit(struct kore_json_item *json, const char *url, void *udata,
   1514     void (*cb)(struct acme_sign_op *, struct kore_buf *))
   1515 {
   1516 	struct acme_sign_op	*op;
   1517 	struct kore_buf		buf;
   1518 	char			*nonce;
   1519 
   1520 	if ((nonce = acme_nonce_fetch()) == NULL) {
   1521 		kore_log(LOG_ERR, "failed to fetch nonce from servers");
   1522 		return;
   1523 	}
   1524 
   1525 	kore_buf_init(&buf, 1024);
   1526 
   1527 	if (json != NULL)
   1528 		kore_json_item_tobuf(json, &buf);
   1529 
   1530 	op = kore_calloc(1, sizeof(*op));
   1531 	LIST_INSERT_HEAD(&signops, op, list);
   1532 
   1533 	op->cb = cb;
   1534 	op->udata = udata;
   1535 	op->nonce = nonce;
   1536 	op->id = signop_id++;
   1537 	op->payload = acme_base64url(buf.data, buf.offset);
   1538 	op->protected = acme_protected_component(op->nonce, url);
   1539 	op->t = kore_timer_add(acme_sign_expire, 30000, op, KORE_TIMER_ONESHOT);
   1540 
   1541 	kore_buf_reset(&buf);
   1542 	kore_buf_append(&buf, &op->id, sizeof(op->id));
   1543 	kore_buf_appendf(&buf, "%s.%s", op->protected, op->payload);
   1544 
   1545 	kore_msg_send(KORE_WORKER_KEYMGR, KORE_ACME_SIGN, buf.data, buf.offset);
   1546 	kore_buf_cleanup(&buf);
   1547 }
   1548 
   1549 static void
   1550 acme_sign_expire(void *udata, u_int64_t now)
   1551 {
   1552 	struct acme_sign_op	*op = udata;
   1553 
   1554 	kore_log(LOG_NOTICE, "signop %u expired (no answer)", op->id);
   1555 
   1556 	LIST_REMOVE(op, list);
   1557 
   1558 	kore_free(op->protected);
   1559 	kore_free(op->payload);
   1560 	kore_free(op->udata);
   1561 	kore_free(op->nonce);
   1562 	kore_free(op);
   1563 }
   1564 
   1565 static void
   1566 acme_sign_result(struct kore_msg *msg, const void *data)
   1567 {
   1568 	u_int32_t		id;
   1569 	struct kore_buf		buf;
   1570 	struct acme_sign_op	*op;
   1571 	char			*sig;
   1572 	const u_int8_t		*ptr;
   1573 
   1574 	if (msg->length < sizeof(id))
   1575 		fatal("%s: invalid length (%zu)", __func__, msg->length);
   1576 
   1577 	ptr = data;
   1578 	memcpy(&id, ptr, sizeof(id));
   1579 
   1580 	ptr += sizeof(id);
   1581 	msg->length -= sizeof(id);
   1582 
   1583 	LIST_FOREACH(op, &signops, list) {
   1584 		if (op->id == id)
   1585 			break;
   1586 	}
   1587 
   1588 	if (op == NULL) {
   1589 		kore_log(LOG_NOTICE,
   1590 		    "received KORE_ACME_SIGN_RESULT for unknown op: %u", id);
   1591 		return;
   1592 	}
   1593 
   1594 	kore_timer_remove(op->t);
   1595 	LIST_REMOVE(op, list);
   1596 
   1597 	sig = kore_malloc(msg->length + 1);
   1598 	memcpy(sig, ptr, msg->length);
   1599 	sig[msg->length] = '\0';
   1600 
   1601 	kore_buf_init(&buf, 1024);
   1602 	acme_request_json(&buf, op->payload, op->protected, sig);
   1603 
   1604 	op->cb(op, &buf);
   1605 
   1606 	kore_free(op->protected);
   1607 	kore_free(op->payload);
   1608 	kore_free(op->udata);
   1609 	kore_free(op->nonce);
   1610 	kore_free(op);
   1611 
   1612 	kore_free(sig);
   1613 	kore_buf_cleanup(&buf);
   1614 }
   1615 
   1616 static char *
   1617 acme_protected_component(const char *nonce, const char *url)
   1618 {
   1619 	char			*b64;
   1620 	struct kore_buf		payload;
   1621 	struct kore_json_item	*root, *jwk;
   1622 
   1623 	root = kore_json_create_object(NULL, NULL);
   1624 
   1625 	kore_json_create_string(root, "url", url);
   1626 	kore_json_create_string(root, "alg", "RS256");
   1627 	kore_json_create_string(root, "nonce", nonce);
   1628 
   1629 	if (account_id == NULL) {
   1630 		jwk = kore_json_create_object(root, "jwk");
   1631 		kore_json_create_string(jwk, "kty", "RSA");
   1632 		kore_json_create_string(jwk, "e", rsakey_e);
   1633 		kore_json_create_string(jwk, "n", rsakey_n);
   1634 	} else {
   1635 		kore_json_create_string(root, "kid", account_id);
   1636 	}
   1637 
   1638 	kore_buf_init(&payload, 128);
   1639 	kore_json_item_tobuf(root, &payload);
   1640 
   1641 	b64 = acme_base64url(payload.data, payload.offset);
   1642 
   1643 	kore_json_item_free(root);
   1644 	kore_buf_cleanup(&payload);
   1645 
   1646 	return (b64);
   1647 }
   1648 
   1649 static char *
   1650 acme_thumbprint_component(void)
   1651 {
   1652 	struct kore_json_item	*json;
   1653 	struct kore_buf		payload;
   1654 	u_int8_t		digest[SHA256_DIGEST_LENGTH];
   1655 
   1656 	json = kore_json_create_object(NULL, NULL);
   1657 
   1658 	/* Order matters here, see RFC7638. */
   1659 	kore_json_create_string(json, "e", rsakey_e);
   1660 	kore_json_create_string(json, "kty", "RSA");
   1661 	kore_json_create_string(json, "n", rsakey_n);
   1662 
   1663 	kore_buf_init(&payload, 128);
   1664 	kore_json_item_tobuf(json, &payload);
   1665 
   1666 	(void)SHA256(payload.data, payload.offset, digest);
   1667 
   1668 	kore_json_item_free(json);
   1669 	kore_buf_cleanup(&payload);
   1670 
   1671 	return (acme_base64url(digest, sizeof(digest)));
   1672 }
   1673 
   1674 static char *
   1675 acme_base64url(const void *data, size_t len)
   1676 {
   1677 	char		*b64;
   1678 
   1679 	if (!kore_base64url_encode(data, len, &b64, KORE_BASE64_RAW)) {
   1680 		fatal("%s: failed to encode base64url data of %zu bytes",
   1681 		    __func__, len);
   1682 	}
   1683 
   1684 	return (b64);
   1685 }
   1686 
   1687 static void
   1688 acme_keymgr_key_req(const char *domain, const void *data, size_t len, int msg)
   1689 {
   1690 	struct kore_keyreq	req;
   1691 	struct kore_buf		buf;
   1692 
   1693 	memset(&req, 0, sizeof(req));
   1694 	req.data_len = len;
   1695 
   1696 	if (kore_strlcpy(req.domain, domain, sizeof(req.domain)) >=
   1697 	    sizeof(req.domain))
   1698 		fatal("%s: domain truncated", __func__);
   1699 
   1700 	kore_buf_init(&buf, sizeof(req) + len);
   1701 	kore_buf_append(&buf, &req, sizeof(req));
   1702 
   1703 	if (data != NULL)
   1704 		kore_buf_append(&buf, data, len);
   1705 
   1706 	kore_msg_send(KORE_WORKER_KEYMGR, msg, buf.data, buf.offset);
   1707 	kore_buf_cleanup(&buf);
   1708 }
   1709 
   1710 static int
   1711 acme_status_type(const char *status)
   1712 {
   1713 	int	type;
   1714 
   1715 	if (!strcmp(status, "pending")) {
   1716 		type = ACME_STATUS_PENDING;
   1717 	} else if (!strcmp(status, "processing")) {
   1718 		type = ACME_STATUS_PROCESSING;
   1719 	} else if (!strcmp(status, "valid")) {
   1720 		type = ACME_STATUS_VALID;
   1721 	} else if (!strcmp(status, "invalid")) {
   1722 		type = ACME_STATUS_INVALID;
   1723 	} else if (!strcmp(status, "ready")) {
   1724 		type = ACME_STATUS_READY;
   1725 	} else if (!strcmp(status, "expired")) {
   1726 		type = ACME_STATUS_EXPIRED;
   1727 	} else if (!strcmp(status, "revoked")) {
   1728 		type = ACME_STATUS_REVOKED;
   1729 	} else {
   1730 		type = -1;
   1731 	}
   1732 
   1733 	return (type);
   1734 }
   1735 
   1736 static void
   1737 acme_rsakey_exp(struct kore_msg *msg, const void *data)
   1738 {
   1739 	kore_free(rsakey_e);
   1740 	rsakey_e = kore_calloc(1, msg->length + 1);
   1741 	memcpy(rsakey_e, data, msg->length);
   1742 	rsakey_e[msg->length] = '\0';
   1743 }
   1744 
   1745 static void
   1746 acme_rsakey_mod(struct kore_msg *msg, const void *data)
   1747 {
   1748 	kore_free(rsakey_n);
   1749 	rsakey_n = kore_calloc(1, msg->length + 1);
   1750 	memcpy(rsakey_n, data, msg->length);
   1751 	rsakey_n[msg->length] = '\0';
   1752 }