1 /* $Id: netproc.c,v 1.33 2022/12/14 18:32:26 florian Exp $ */ 2 /* 3 * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <assert.h> 19 #include <ctype.h> 20 #include <err.h> 21 #include <errno.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <unistd.h> 25 #include <tls.h> 26 #include <vis.h> 27 28 #include "http.h" 29 #include "extern.h" 30 #include "parse.h" 31 32 #define RETRY_DELAY 5 33 #define RETRY_MAX 10 34 35 /* 36 * Buffer used when collecting the results of an http transfer. 37 */ 38 struct buf { 39 char *buf; /* binary buffer */ 40 size_t sz; /* length of buffer */ 41 }; 42 43 /* 44 * Used for communication with other processes. 45 */ 46 struct conn { 47 const char *newnonce; /* nonce authority */ 48 char *kid; /* kid when account exists */ 49 int fd; /* acctproc handle */ 50 int dfd; /* dnsproc handle */ 51 struct buf buf; /* http body buffer */ 52 }; 53 54 /* 55 * If something goes wrong (or we're tracing output), we dump the 56 * current transfer's data as a debug message. 57 * Make sure that print all non-printable characters as question marks 58 * so that we don't spam the console. 59 * Also, consolidate white-space. 60 * This of course will ruin string literals, but the intent here is just 61 * to show the message, not to replicate it. 62 */ 63 static void 64 buf_dump(const struct buf *buf) 65 { 66 size_t i; 67 int j; 68 char *nbuf; 69 70 if (buf->sz == 0) 71 return; 72 if ((nbuf = malloc(buf->sz)) == NULL) 73 err(EXIT_FAILURE, "malloc"); 74 75 for (j = 0, i = 0; i < buf->sz; i++) 76 if (isspace((unsigned char)buf->buf[i])) { 77 nbuf[j++] = ' '; 78 while (isspace((unsigned char)buf->buf[i])) 79 i++; 80 i--; 81 } else 82 nbuf[j++] = isprint((unsigned char)buf->buf[i]) ? 83 buf->buf[i] : '?'; 84 dodbg("transfer buffer: [%.*s] (%zu bytes)", j, nbuf, buf->sz); 85 free(nbuf); 86 } 87 88 /* 89 * Extract the domain and port from a URL. 90 * The url must be formatted as schema://address[/stuff]. 91 * This returns NULL on failure. 92 */ 93 static char * 94 url2host(const char *host, short *port, char **path) 95 { 96 char *url, *ep; 97 98 /* We only understand HTTP and HTTPS. */ 99 if (strncmp(host, "https://", 8) == 0) { 100 *port = 443; 101 if ((url = strdup(host + 8)) == NULL) { 102 warn("strdup"); 103 return NULL; 104 } 105 } else if (strncmp(host, "http://", 7) == 0) { 106 *port = 80; 107 if ((url = strdup(host + 7)) == NULL) { 108 warn("strdup"); 109 return NULL; 110 } 111 } else { 112 warnx("%s: unknown schema", host); 113 return NULL; 114 } 115 116 /* Terminate path part. */ 117 if ((ep = strchr(url, '/')) != NULL) { 118 *path = strdup(ep); 119 *ep = '\0'; 120 } else 121 *path = strdup(""); 122 123 if (*path == NULL) { 124 warn("strdup"); 125 free(url); 126 return NULL; 127 } 128 129 return url; 130 } 131 132 /* 133 * Contact dnsproc and resolve a host. 134 * Place the answers in "v" and return the number of answers, which can 135 * be at most MAX_SERVERS_DNS. 136 * Return <0 on failure. 137 */ 138 static ssize_t 139 urlresolve(int fd, const char *host, struct source *v) 140 { 141 char *addr; 142 size_t i, sz; 143 long lval; 144 145 if (writeop(fd, COMM_DNS, DNS_LOOKUP) <= 0) 146 return -1; 147 else if (writestr(fd, COMM_DNSQ, host) <= 0) 148 return -1; 149 else if ((lval = readop(fd, COMM_DNSLEN)) < 0) 150 return -1; 151 152 sz = lval; 153 assert(sz <= MAX_SERVERS_DNS); 154 155 for (i = 0; i < sz; i++) { 156 memset(&v[i], 0, sizeof(struct source)); 157 if ((lval = readop(fd, COMM_DNSF)) < 0) 158 goto err; 159 else if (lval != 4 && lval != 6) 160 goto err; 161 else if ((addr = readstr(fd, COMM_DNSA)) == NULL) 162 goto err; 163 v[i].family = lval; 164 v[i].ip = addr; 165 } 166 167 return sz; 168 err: 169 for (i = 0; i < sz; i++) 170 free(v[i].ip); 171 return -1; 172 } 173 174 /* 175 * Send a "regular" HTTP GET message to "addr" and stuff the response 176 * into the connection buffer. 177 * Return the HTTP error code or <0 on failure. 178 */ 179 static long 180 nreq(struct conn *c, const char *addr) 181 { 182 struct httpget *g; 183 struct source src[MAX_SERVERS_DNS]; 184 struct httphead *st; 185 char *host, *path; 186 short port; 187 size_t srcsz; 188 ssize_t ssz; 189 long code; 190 int redirects = 0; 191 192 if ((host = url2host(addr, &port, &path)) == NULL) 193 return -1; 194 195 again: 196 if ((ssz = urlresolve(c->dfd, host, src)) < 0) { 197 free(host); 198 free(path); 199 return -1; 200 } 201 srcsz = ssz; 202 203 g = http_get(src, srcsz, host, port, path, 0, NULL, 0); 204 free(host); 205 free(path); 206 if (g == NULL) 207 return -1; 208 209 switch (g->code) { 210 case 301: 211 case 302: 212 case 303: 213 case 307: 214 case 308: 215 redirects++; 216 if (redirects > 3) { 217 warnx("too many redirects"); 218 http_get_free(g); 219 return -1; 220 } 221 222 if ((st = http_head_get("Location", g->head, g->headsz)) == 223 NULL) { 224 warnx("redirect without location header"); 225 http_get_free(g); 226 return -1; 227 } 228 229 host = url2host(st->val, &port, &path); 230 http_get_free(g); 231 if (host == NULL) 232 return -1; 233 goto again; 234 break; 235 default: 236 code = g->code; 237 break; 238 } 239 240 /* Copy the body part into our buffer. */ 241 free(c->buf.buf); 242 c->buf.sz = g->bodypartsz; 243 c->buf.buf = malloc(c->buf.sz); 244 if (c->buf.buf == NULL) { 245 warn("malloc"); 246 code = -1; 247 } else 248 memcpy(c->buf.buf, g->bodypart, c->buf.sz); 249 http_get_free(g); 250 return code; 251 } 252 253 /* 254 * Create and send a signed communication to the ACME server. 255 * Stuff the response into the communication buffer. 256 * Return <0 on failure on the HTTP error code otherwise. 257 */ 258 static long 259 sreq(struct conn *c, const char *addr, int kid, const char *req, char **loc) 260 { 261 struct httpget *g; 262 struct source src[MAX_SERVERS_DNS]; 263 char *host, *path, *nonce, *reqsn; 264 short port; 265 struct httphead *h; 266 ssize_t ssz; 267 long code; 268 269 if ((host = url2host(c->newnonce, &port, &path)) == NULL) 270 return -1; 271 272 if ((ssz = urlresolve(c->dfd, host, src)) < 0) { 273 free(host); 274 free(path); 275 return -1; 276 } 277 278 g = http_get(src, (size_t)ssz, host, port, path, 1, NULL, 0); 279 free(host); 280 free(path); 281 if (g == NULL) 282 return -1; 283 284 h = http_head_get("Replay-Nonce", g->head, g->headsz); 285 if (h == NULL) { 286 warnx("%s: no replay nonce", c->newnonce); 287 http_get_free(g); 288 return -1; 289 } else if ((nonce = strdup(h->val)) == NULL) { 290 warn("strdup"); 291 http_get_free(g); 292 return -1; 293 } 294 http_get_free(g); 295 296 /* 297 * Send the url, nonce and request payload to the acctproc. 298 * This will create the proper JSON object we need. 299 */ 300 if (writeop(c->fd, COMM_ACCT, kid ? ACCT_KID_SIGN : ACCT_SIGN) <= 0) { 301 free(nonce); 302 return -1; 303 } else if (writestr(c->fd, COMM_PAY, req) <= 0) { 304 free(nonce); 305 return -1; 306 } else if (writestr(c->fd, COMM_NONCE, nonce) <= 0) { 307 free(nonce); 308 return -1; 309 } else if (writestr(c->fd, COMM_URL, addr) <= 0) { 310 free(nonce); 311 return -1; 312 } 313 free(nonce); 314 315 if (kid && writestr(c->fd, COMM_KID, c->kid) <= 0) 316 return -1; 317 318 /* Now read back the signed payload. */ 319 if ((reqsn = readstr(c->fd, COMM_REQ)) == NULL) 320 return -1; 321 322 /* Now send the signed payload to the CA. */ 323 if ((host = url2host(addr, &port, &path)) == NULL) { 324 free(reqsn); 325 return -1; 326 } else if ((ssz = urlresolve(c->dfd, host, src)) < 0) { 327 free(host); 328 free(path); 329 free(reqsn); 330 return -1; 331 } 332 333 g = http_get(src, (size_t)ssz, host, port, path, 0, reqsn, 334 strlen(reqsn)); 335 336 free(host); 337 free(path); 338 free(reqsn); 339 if (g == NULL) 340 return -1; 341 342 /* Stuff response into parse buffer. */ 343 code = g->code; 344 345 free(c->buf.buf); 346 c->buf.sz = g->bodypartsz; 347 c->buf.buf = malloc(c->buf.sz); 348 if (c->buf.buf == NULL) { 349 warn("malloc"); 350 code = -1; 351 } else 352 memcpy(c->buf.buf, g->bodypart, c->buf.sz); 353 354 if (loc != NULL) { 355 free(*loc); 356 *loc = NULL; 357 h = http_head_get("Location", g->head, g->headsz); 358 /* error checking done by caller */ 359 if (h != NULL) 360 *loc = strdup(h->val); 361 } 362 363 http_get_free(g); 364 return code; 365 } 366 367 /* 368 * Send to the CA that we want to authorise a new account. 369 * This only happens once for a new account key. 370 * Returns non-zero on success. 371 */ 372 static int 373 donewacc(struct conn *c, const struct capaths *p, const char *contact) 374 { 375 struct jsmnn *j = NULL; 376 int rc = 0; 377 char *req, *detail, *error = NULL; 378 long lc; 379 380 if ((req = json_fmt_newacc(contact)) == NULL) 381 warnx("json_fmt_newacc"); 382 else if ((lc = sreq(c, p->newaccount, 0, req, &c->kid)) < 0) 383 warnx("%s: bad comm", p->newaccount); 384 else if (lc == 400) { 385 if ((j = json_parse(c->buf.buf, c->buf.sz)) == NULL) 386 warnx("%s: bad JSON object", p->newaccount); 387 else { 388 detail = json_getstr(j, "detail"); 389 if (detail != NULL && stravis(&error, detail, VIS_SAFE) 390 != -1) { 391 warnx("%s", error); 392 free(error); 393 } 394 } 395 } else if (lc != 200 && lc != 201) 396 warnx("%s: bad HTTP: %ld", p->newaccount, lc); 397 else if (c->buf.buf == NULL || c->buf.sz == 0) 398 warnx("%s: empty response", p->newaccount); 399 else 400 rc = 1; 401 402 if (rc == 0 || verbose > 1) 403 buf_dump(&c->buf); 404 free(req); 405 return rc; 406 } 407 408 /* 409 * Check if our account already exists, if not create it. 410 * Populates conn->kid. 411 * Returns non-zero on success. 412 */ 413 static int 414 dochkacc(struct conn *c, const struct capaths *p, const char *contact) 415 { 416 int rc = 0; 417 char *req; 418 long lc; 419 420 if ((req = json_fmt_chkacc()) == NULL) 421 warnx("json_fmt_chkacc"); 422 else if ((lc = sreq(c, p->newaccount, 0, req, &c->kid)) < 0) 423 warnx("%s: bad comm", p->newaccount); 424 else if (lc != 200 && lc != 400) 425 warnx("%s: bad HTTP: %ld", p->newaccount, lc); 426 else if (c->buf.buf == NULL || c->buf.sz == 0) 427 warnx("%s: empty response", p->newaccount); 428 else if (lc == 400) 429 rc = donewacc(c, p, contact); 430 else 431 rc = 1; 432 433 if (c->kid == NULL) 434 rc = 0; 435 436 if (rc == 0 || verbose > 1) 437 buf_dump(&c->buf); 438 free(req); 439 return rc; 440 } 441 442 /* 443 * Submit a new order for a certificate. 444 */ 445 static int 446 doneworder(struct conn *c, const char *const *alts, size_t altsz, 447 struct order *order, const struct capaths *p) 448 { 449 struct jsmnn *j = NULL; 450 int rc = 0; 451 char *req; 452 long lc; 453 454 if ((req = json_fmt_neworder(alts, altsz)) == NULL) 455 warnx("json_fmt_neworder"); 456 else if ((lc = sreq(c, p->neworder, 1, req, &order->uri)) < 0) 457 warnx("%s: bad comm", p->neworder); 458 else if (lc != 201) 459 warnx("%s: bad HTTP: %ld", p->neworder, lc); 460 else if ((j = json_parse(c->buf.buf, c->buf.sz)) == NULL) 461 warnx("%s: bad JSON object", p->neworder); 462 else if (!json_parse_order(j, order)) 463 warnx("%s: bad order", p->neworder); 464 else if (order->status == ORDER_INVALID) 465 warnx("%s: order invalid", p->neworder); 466 else 467 rc = 1; 468 469 if (rc == 0 || verbose > 1) 470 buf_dump(&c->buf); 471 472 free(req); 473 json_free(j); 474 return rc; 475 } 476 477 /* 478 * Update order status 479 */ 480 static int 481 doupdorder(struct conn *c, struct order *order) 482 { 483 struct jsmnn *j = NULL; 484 int rc = 0; 485 long lc; 486 487 if ((lc = sreq(c, order->uri, 1, "", NULL)) < 0) 488 warnx("%s: bad comm", order->uri); 489 else if (lc != 200) 490 warnx("%s: bad HTTP: %ld", order->uri, lc); 491 else if ((j = json_parse(c->buf.buf, c->buf.sz)) == NULL) 492 warnx("%s: bad JSON object", order->uri); 493 else if (!json_parse_upd_order(j, order)) 494 warnx("%s: bad order", order->uri); 495 else 496 rc = 1; 497 498 if (rc == 0 || verbose > 1) 499 buf_dump(&c->buf); 500 501 json_free(j); 502 return rc; 503 } 504 505 /* 506 * Request a challenge for the given domain name. 507 * This must be called for each name "alt". 508 * On non-zero exit, fills in "chng" with the challenge. 509 */ 510 static int 511 dochngreq(struct conn *c, const char *auth, struct chng *chng) 512 { 513 int rc = 0; 514 long lc; 515 struct jsmnn *j = NULL; 516 517 dodbg("%s: %s", __func__, auth); 518 519 if ((lc = sreq(c, auth, 1, "", NULL)) < 0) 520 warnx("%s: bad comm", auth); 521 else if (lc != 200) 522 warnx("%s: bad HTTP: %ld", auth, lc); 523 else if ((j = json_parse(c->buf.buf, c->buf.sz)) == NULL) 524 warnx("%s: bad JSON object", auth); 525 else if (!json_parse_challenge(j, chng)) 526 warnx("%s: bad challenge", auth); 527 else 528 rc = 1; 529 530 if (rc == 0 || verbose > 1) 531 buf_dump(&c->buf); 532 json_free(j); 533 return rc; 534 } 535 536 /* 537 * Tell the CA that a challenge response is in place. 538 */ 539 static int 540 dochngresp(struct conn *c, const struct chng *chng) 541 { 542 int rc = 0; 543 long lc; 544 545 dodbg("%s: challenge", chng->uri); 546 547 if ((lc = sreq(c, chng->uri, 1, "{}", NULL)) < 0) 548 warnx("%s: bad comm", chng->uri); 549 else if (lc != 200 && lc != 201 && lc != 202) 550 warnx("%s: bad HTTP: %ld", chng->uri, lc); 551 else 552 rc = 1; 553 554 if (rc == 0 || verbose > 1) 555 buf_dump(&c->buf); 556 return rc; 557 } 558 559 /* 560 * Submit our csr to the CA. 561 */ 562 static int 563 docert(struct conn *c, const char *uri, const char *csr) 564 { 565 char *req; 566 int rc = 0; 567 long lc; 568 569 dodbg("%s: certificate", uri); 570 571 if ((req = json_fmt_newcert(csr)) == NULL) 572 warnx("json_fmt_newcert"); 573 else if ((lc = sreq(c, uri, 1, req, NULL)) < 0) 574 warnx("%s: bad comm", uri); 575 else if (lc != 200) 576 warnx("%s: bad HTTP: %ld", uri, lc); 577 else if (c->buf.sz == 0 || c->buf.buf == NULL) 578 warnx("%s: empty response", uri); 579 else 580 rc = 1; 581 582 if (rc == 0 || verbose > 1) 583 buf_dump(&c->buf); 584 free(req); 585 return rc; 586 } 587 588 /* 589 * Get certificate from CA 590 */ 591 static int 592 dogetcert(struct conn *c, const char *uri) 593 { 594 int rc = 0; 595 long lc; 596 597 dodbg("%s: certificate", uri); 598 599 if ((lc = sreq(c, uri, 1, "", NULL)) < 0) 600 warnx("%s: bad comm", uri); 601 else if (lc != 200) 602 warnx("%s: bad HTTP: %ld", uri, lc); 603 else if (c->buf.sz == 0 || c->buf.buf == NULL) 604 warnx("%s: empty response", uri); 605 else 606 rc = 1; 607 608 if (rc == 0 || verbose > 1) 609 buf_dump(&c->buf); 610 611 return rc; 612 } 613 614 static int 615 dorevoke(struct conn *c, const char *addr, const char *cert) 616 { 617 char *req; 618 int rc = 0; 619 long lc = 0; 620 621 dodbg("%s: revocation", addr); 622 623 if ((req = json_fmt_revokecert(cert)) == NULL) 624 warnx("json_fmt_revokecert"); 625 else if ((lc = sreq(c, addr, 1, req, NULL)) < 0) 626 warnx("%s: bad comm", addr); 627 else if (lc != 200 && lc != 201 && lc != 409) 628 warnx("%s: bad HTTP: %ld", addr, lc); 629 else 630 rc = 1; 631 632 if (lc == 409) 633 warnx("%s: already revoked", addr); 634 635 if (rc == 0 || verbose > 1) 636 buf_dump(&c->buf); 637 free(req); 638 return rc; 639 } 640 641 /* 642 * Look up directories from the certificate authority. 643 */ 644 static int 645 dodirs(struct conn *c, const char *addr, struct capaths *paths) 646 { 647 struct jsmnn *j = NULL; 648 long lc; 649 int rc = 0; 650 651 dodbg("%s: directories", addr); 652 653 if ((lc = nreq(c, addr)) < 0) 654 warnx("%s: bad comm", addr); 655 else if (lc != 200 && lc != 201) 656 warnx("%s: bad HTTP: %ld", addr, lc); 657 else if ((j = json_parse(c->buf.buf, c->buf.sz)) == NULL) 658 warnx("json_parse"); 659 else if (!json_parse_capaths(j, paths)) 660 warnx("%s: bad CA paths", addr); 661 else 662 rc = 1; 663 664 if (rc == 0 || verbose > 1) 665 buf_dump(&c->buf); 666 json_free(j); 667 return rc; 668 } 669 670 /* 671 * Communicate with the ACME server. 672 * We need the certificate we want to upload and our account key information. 673 */ 674 int 675 netproc(int kfd, int afd, int Cfd, int cfd, int dfd, int rfd, 676 int revocate, struct authority_c *authority, 677 const char *const *alts, size_t altsz) 678 { 679 int rc = 0; 680 size_t i; 681 char *cert = NULL, *thumb = NULL, *url = NULL, *error = NULL; 682 struct conn c; 683 struct capaths paths; 684 struct order order; 685 struct chng *chngs = NULL; 686 long lval; 687 688 memset(&paths, 0, sizeof(struct capaths)); 689 memset(&c, 0, sizeof(struct conn)); 690 691 if (unveil(tls_default_ca_cert_file(), "r") == -1) { 692 warn("unveil %s", tls_default_ca_cert_file()); 693 goto out; 694 } 695 696 if (pledge("stdio inet rpath", NULL) == -1) { 697 warn("pledge"); 698 goto out; 699 } 700 701 if (http_init() == -1) { 702 warn("http_init"); 703 goto out; 704 } 705 706 if (pledge("stdio inet", NULL) == -1) { 707 warn("pledge"); 708 goto out; 709 } 710 711 /* 712 * Wait until the acctproc, keyproc, and revokeproc have started up and 713 * are ready to serve us data. 714 * Then check whether revokeproc indicates that the certificate on file 715 * (if any) can be updated. 716 */ 717 if ((lval = readop(afd, COMM_ACCT_STAT)) == 0) { 718 rc = 1; 719 goto out; 720 } else if (lval != ACCT_READY) { 721 warnx("unknown operation from acctproc"); 722 goto out; 723 } 724 725 if ((lval = readop(kfd, COMM_KEY_STAT)) == 0) { 726 rc = 1; 727 goto out; 728 } else if (lval != KEY_READY) { 729 warnx("unknown operation from keyproc"); 730 goto out; 731 } 732 733 if ((lval = readop(rfd, COMM_REVOKE_RESP)) == 0) { 734 rc = 1; 735 goto out; 736 } else if (lval != REVOKE_EXP && lval != REVOKE_OK) { 737 warnx("unknown operation from revokeproc"); 738 goto out; 739 } 740 741 /* If our certificate is up-to-date, return now. */ 742 if (lval == REVOKE_OK) { 743 rc = 1; 744 goto out; 745 } 746 747 c.dfd = dfd; 748 c.fd = afd; 749 750 /* 751 * Look up the API urls of the ACME server. 752 */ 753 if (!dodirs(&c, authority->api, &paths)) 754 goto out; 755 756 c.newnonce = paths.newnonce; 757 758 /* Check if our account already exists or create it. */ 759 if (!dochkacc(&c, &paths, authority->contact)) 760 goto out; 761 762 /* 763 * If we're meant to revoke, then wait for revokeproc to send us 764 * the certificate (if it's found at all). 765 * Following that, submit the request to the CA then notify the 766 * certproc, which will in turn notify the fileproc. 767 * XXX currently we can only sign with the account key, the RFC 768 * also mentions signing with the privat key of the cert itself. 769 */ 770 if (revocate) { 771 if ((cert = readstr(rfd, COMM_CSR)) == NULL) 772 goto out; 773 if (!dorevoke(&c, paths.revokecert, cert)) 774 goto out; 775 else if (writeop(cfd, COMM_CSR_OP, CERT_REVOKE) > 0) 776 rc = 1; 777 goto out; 778 } 779 780 memset(&order, 0, sizeof(order)); 781 782 if (!doneworder(&c, alts, altsz, &order, &paths)) 783 goto out; 784 785 chngs = calloc(order.authsz, sizeof(struct chng)); 786 if (chngs == NULL) { 787 warn("calloc"); 788 goto out; 789 } 790 791 /* 792 * Get thumbprint from acctproc. We will need it to construct 793 * a response to the challenge 794 */ 795 if (writeop(afd, COMM_ACCT, ACCT_THUMBPRINT) <= 0) 796 goto out; 797 else if ((thumb = readstr(afd, COMM_THUMB)) == NULL) 798 goto out; 799 800 while(order.status != ORDER_VALID && order.status != ORDER_INVALID) { 801 switch (order.status) { 802 case ORDER_INVALID: 803 warnx("order invalid"); 804 goto out; 805 case ORDER_VALID: 806 rc = 1; 807 continue; 808 case ORDER_PENDING: 809 if (order.authsz < 1) { 810 warnx("order is in state pending but no " 811 "authorizations know"); 812 goto out; 813 } 814 for (i = 0; i < order.authsz; i++) { 815 if (!dochngreq(&c, order.auths[i], &chngs[i])) 816 goto out; 817 818 dodbg("challenge, token: %s, uri: %s, status: " 819 "%d", chngs[i].token, chngs[i].uri, 820 chngs[i].status); 821 822 if (chngs[i].status == CHNG_VALID || 823 chngs[i].status == CHNG_INVALID) 824 continue; 825 826 if (chngs[i].retry++ >= RETRY_MAX) { 827 warnx("%s: too many tries", 828 chngs[i].uri); 829 goto out; 830 } 831 832 if (writeop(Cfd, COMM_CHNG_OP, CHNG_SYN) <= 0) 833 goto out; 834 else if (writestr(Cfd, COMM_THUMB, thumb) <= 0) 835 goto out; 836 else if (writestr(Cfd, COMM_TOK, 837 chngs[i].token) <= 0) 838 goto out; 839 840 /* Read that the challenge has been made. */ 841 if (readop(Cfd, COMM_CHNG_ACK) != CHNG_ACK) 842 goto out; 843 844 } 845 /* Write to the CA that it's ready. */ 846 for (i = 0; i < order.authsz; i++) { 847 if (chngs[i].status == CHNG_VALID || 848 chngs[i].status == CHNG_INVALID) 849 continue; 850 if (!dochngresp(&c, &chngs[i])) 851 goto out; 852 } 853 break; 854 case ORDER_READY: 855 /* 856 * Write our acknowledgement that the challenges are 857 * over. 858 * The challenge process will remove all of the files. 859 */ 860 if (writeop(Cfd, COMM_CHNG_OP, CHNG_STOP) <= 0) 861 goto out; 862 863 /* Wait to receive the certificate itself. */ 864 if ((cert = readstr(kfd, COMM_CERT)) == NULL) 865 goto out; 866 if (!docert(&c, order.finalize, cert)) 867 goto out; 868 break; 869 default: 870 warnx("unhandled status: %d", order.status); 871 goto out; 872 } 873 if (!doupdorder(&c, &order)) 874 goto out; 875 876 dodbg("order.status %d", order.status); 877 if (order.status == ORDER_PENDING) 878 sleep(RETRY_DELAY); 879 } 880 881 if (order.status != ORDER_VALID) { 882 for (i = 0; i < order.authsz; i++) { 883 dochngreq(&c, order.auths[i], &chngs[i]); 884 if (chngs[i].error != NULL) { 885 if (stravis(&error, chngs[i].error, VIS_SAFE) 886 != -1) { 887 warnx("%s", error); 888 free(error); 889 error = NULL; 890 } 891 } 892 } 893 goto out; 894 } 895 896 if (order.certificate == NULL) { 897 warnx("no certificate url received"); 898 goto out; 899 } 900 901 if (!dogetcert(&c, order.certificate)) 902 goto out; 903 else if (writeop(cfd, COMM_CSR_OP, CERT_UPDATE) <= 0) 904 goto out; 905 else if (writebuf(cfd, COMM_CSR, c.buf.buf, c.buf.sz) <= 0) 906 goto out; 907 rc = 1; 908 out: 909 close(cfd); 910 close(kfd); 911 close(afd); 912 close(Cfd); 913 close(dfd); 914 close(rfd); 915 free(cert); 916 free(url); 917 free(thumb); 918 free(c.kid); 919 free(c.buf.buf); 920 if (chngs != NULL) 921 for (i = 0; i < order.authsz; i++) 922 json_free_challenge(&chngs[i]); 923 free(chngs); 924 json_free_capaths(&paths); 925 return rc; 926 } 927