acme.c (43984B)
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", len);
1681
1682 return (b64);
1683 }
1684
1685 static void
1686 acme_keymgr_key_req(const char *domain, const void *data, size_t len, int msg)
1687 {
1688 struct kore_keyreq req;
1689 struct kore_buf buf;
1690
1691 memset(&req, 0, sizeof(req));
1692 req.data_len = len;
1693
1694 if (kore_strlcpy(req.domain, domain, sizeof(req.domain)) >=
1695 sizeof(req.domain))
1696 fatal("%s: domain truncated", __func__);
1697
1698 kore_buf_init(&buf, sizeof(req) + len);
1699 kore_buf_append(&buf, &req, sizeof(req));
1700
1701 if (data != NULL)
1702 kore_buf_append(&buf, data, len);
1703
1704 kore_msg_send(KORE_WORKER_KEYMGR, msg, buf.data, buf.offset);
1705 kore_buf_cleanup(&buf);
1706 }
1707
1708 static int
1709 acme_status_type(const char *status)
1710 {
1711 int type;
1712
1713 if (!strcmp(status, "pending")) {
1714 type = ACME_STATUS_PENDING;
1715 } else if (!strcmp(status, "processing")) {
1716 type = ACME_STATUS_PROCESSING;
1717 } else if (!strcmp(status, "valid")) {
1718 type = ACME_STATUS_VALID;
1719 } else if (!strcmp(status, "invalid")) {
1720 type = ACME_STATUS_INVALID;
1721 } else if (!strcmp(status, "ready")) {
1722 type = ACME_STATUS_READY;
1723 } else if (!strcmp(status, "expired")) {
1724 type = ACME_STATUS_EXPIRED;
1725 } else if (!strcmp(status, "revoked")) {
1726 type = ACME_STATUS_REVOKED;
1727 } else {
1728 type = -1;
1729 }
1730
1731 return (type);
1732 }
1733
1734 static void
1735 acme_rsakey_exp(struct kore_msg *msg, const void *data)
1736 {
1737 kore_free(rsakey_e);
1738 rsakey_e = kore_calloc(1, msg->length + 1);
1739 memcpy(rsakey_e, data, msg->length);
1740 rsakey_e[msg->length] = '\0';
1741 }
1742
1743 static void
1744 acme_rsakey_mod(struct kore_msg *msg, const void *data)
1745 {
1746 kore_free(rsakey_n);
1747 rsakey_n = kore_calloc(1, msg->length + 1);
1748 memcpy(rsakey_n, data, msg->length);
1749 rsakey_n[msg->length] = '\0';
1750 }