1 /* $Id: netproc.c,v 1.31 2021/08/24 10:07:30 benno 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((int)buf->buf[i])) { 77 nbuf[j++] = ' '; 78 while (isspace((int)buf->buf[i])) 79 i++; 80 i--; 81 } else 82 nbuf[j++] = isprint((int)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 return -1; 226 } 227 228 host = url2host(st->val, &port, &path); 229 http_get_free(g); 230 if (host == NULL) 231 return -1; 232 goto again; 233 break; 234 default: 235 code = g->code; 236 break; 237 } 238 239 /* Copy the body part into our buffer. */ 240 free(c->buf.buf); 241 c->buf.sz = g->bodypartsz; 242 c->buf.buf = malloc(c->buf.sz); 243 if (c->buf.buf == NULL) { 244 warn("malloc"); 245 code = -1; 246 } else 247 memcpy(c->buf.buf, g->bodypart, c->buf.sz); 248 http_get_free(g); 249 return code; 250 } 251 252 /* 253 * Create and send a signed communication to the ACME server. 254 * Stuff the response into the communication buffer. 255 * Return <0 on failure on the HTTP error code otherwise. 256 */ 257 static long 258 sreq(struct conn *c, const char *addr, int kid, const char *req, char **loc) 259 { 260 struct httpget *g; 261 struct source src[MAX_SERVERS_DNS]; 262 char *host, *path, *nonce, *reqsn; 263 short port; 264 struct httphead *h; 265 ssize_t ssz; 266 long code; 267 268 if ((host = url2host(c->newnonce, &port, &path)) == NULL) 269 return -1; 270 271 if ((ssz = urlresolve(c->dfd, host, src)) < 0) { 272 free(host); 273 free(path); 274 return -1; 275 } 276 277 g = http_get(src, (size_t)ssz, host, port, path, 1, NULL, 0); 278 free(host); 279 free(path); 280 if (g == NULL) 281 return -1; 282 283 h = http_head_get("Replay-Nonce", g->head, g->headsz); 284 if (h == NULL) { 285 warnx("%s: no replay nonce", c->newnonce); 286 http_get_free(g); 287 return -1; 288 } else if ((nonce = strdup(h->val)) == NULL) { 289 warn("strdup"); 290 http_get_free(g); 291 return -1; 292 } 293 http_get_free(g); 294 295 /* 296 * Send the url, nonce and request payload to the acctproc. 297 * This will create the proper JSON object we need. 298 */ 299 if (writeop(c->fd, COMM_ACCT, kid ? ACCT_KID_SIGN : ACCT_SIGN) <= 0) { 300 free(nonce); 301 return -1; 302 } else if (writestr(c->fd, COMM_PAY, req) <= 0) { 303 free(nonce); 304 return -1; 305 } else if (writestr(c->fd, COMM_NONCE, nonce) <= 0) { 306 free(nonce); 307 return -1; 308 } else if (writestr(c->fd, COMM_URL, addr) <= 0) { 309 free(nonce); 310 return -1; 311 } 312 free(nonce); 313 314 if (kid && writestr(c->fd, COMM_KID, c->kid) <= 0) 315 return -1; 316 317 /* Now read back the signed payload. */ 318 if ((reqsn = readstr(c->fd, COMM_REQ)) == NULL) 319 return -1; 320 321 /* Now send the signed payload to the CA. */ 322 if ((host = url2host(addr, &port, &path)) == NULL) { 323 free(reqsn); 324 return -1; 325 } else if ((ssz = urlresolve(c->dfd, host, src)) < 0) { 326 free(host); 327 free(path); 328 free(reqsn); 329 return -1; 330 } 331 332 g = http_get(src, (size_t)ssz, host, port, path, 0, reqsn, 333 strlen(reqsn)); 334 335 free(host); 336 free(path); 337 free(reqsn); 338 if (g == NULL) 339 return -1; 340 341 /* Stuff response into parse buffer. */ 342 code = g->code; 343 344 free(c->buf.buf); 345 c->buf.sz = g->bodypartsz; 346 c->buf.buf = malloc(c->buf.sz); 347 if (c->buf.buf == NULL) { 348 warn("malloc"); 349 code = -1; 350 } else 351 memcpy(c->buf.buf, g->bodypart, c->buf.sz); 352 353 if (loc != NULL) { 354 free(*loc); 355 *loc = NULL; 356 h = http_head_get("Location", g->head, g->headsz); 357 /* error checking done by caller */ 358 if (h != NULL) 359 *loc = strdup(h->val); 360 } 361 362 http_get_free(g); 363 return code; 364 } 365 366 /* 367 * Send to the CA that we want to authorise a new account. 368 * This only happens once for a new account key. 369 * Returns non-zero on success. 370 */ 371 static int 372 donewacc(struct conn *c, const struct capaths *p, const char *contact) 373 { 374 struct jsmnn *j = NULL; 375 int rc = 0; 376 char *req, *detail, *error = NULL; 377 long lc; 378 379 if ((req = json_fmt_newacc(contact)) == NULL) 380 warnx("json_fmt_newacc"); 381 else if ((lc = sreq(c, p->newaccount, 0, req, &c->kid)) < 0) 382 warnx("%s: bad comm", p->newaccount); 383 else if (lc == 400) { 384 if ((j = json_parse(c->buf.buf, c->buf.sz)) == NULL) 385 warnx("%s: bad JSON object", p->newaccount); 386 else { 387 detail = json_getstr(j, "detail"); 388 if (detail != NULL && stravis(&error, detail, VIS_SAFE) 389 != -1) { 390 warnx("%s", error); 391 free(error); 392 } 393 } 394 } else if (lc != 200 && lc != 201) 395 warnx("%s: bad HTTP: %ld", p->newaccount, lc); 396 else if (c->buf.buf == NULL || c->buf.sz == 0) 397 warnx("%s: empty response", p->newaccount); 398 else 399 rc = 1; 400 401 if (rc == 0 || verbose > 1) 402 buf_dump(&c->buf); 403 free(req); 404 return rc; 405 } 406 407 /* 408 * Check if our account already exists, if not create it. 409 * Populates conn->kid. 410 * Returns non-zero on success. 411 */ 412 static int 413 dochkacc(struct conn *c, const struct capaths *p, const char *contact) 414 { 415 int rc = 0; 416 char *req; 417 long lc; 418 419 if ((req = json_fmt_chkacc()) == NULL) 420 warnx("json_fmt_chkacc"); 421 else if ((lc = sreq(c, p->newaccount, 0, req, &c->kid)) < 0) 422 warnx("%s: bad comm", p->newaccount); 423 else if (lc != 200 && lc != 400) 424 warnx("%s: bad HTTP: %ld", p->newaccount, lc); 425 else if (c->buf.buf == NULL || c->buf.sz == 0) 426 warnx("%s: empty response", p->newaccount); 427 else if (lc == 400) 428 rc = donewacc(c, p, contact); 429 else 430 rc = 1; 431 432 if (c->kid == NULL) 433 rc = 0; 434 435 if (rc == 0 || verbose > 1) 436 buf_dump(&c->buf); 437 free(req); 438 return rc; 439 } 440 441 /* 442 * Submit a new order for a certificate. 443 */ 444 static int 445 doneworder(struct conn *c, const char *const *alts, size_t altsz, 446 struct order *order, const struct capaths *p) 447 { 448 struct jsmnn *j = NULL; 449 int rc = 0; 450 char *req; 451 long lc; 452 453 if ((req = json_fmt_neworder(alts, altsz)) == NULL) 454 warnx("json_fmt_neworder"); 455 else if ((lc = sreq(c, p->neworder, 1, req, &order->uri)) < 0) 456 warnx("%s: bad comm", p->neworder); 457 else if (lc != 201) 458 warnx("%s: bad HTTP: %ld", p->neworder, lc); 459 else if ((j = json_parse(c->buf.buf, c->buf.sz)) == NULL) 460 warnx("%s: bad JSON object", p->neworder); 461 else if (!json_parse_order(j, order)) 462 warnx("%s: bad order", p->neworder); 463 else if (order->status == ORDER_INVALID) 464 warnx("%s: order invalid", p->neworder); 465 else 466 rc = 1; 467 468 if (rc == 0 || verbose > 1) 469 buf_dump(&c->buf); 470 471 free(req); 472 json_free(j); 473 return rc; 474 } 475 476 /* 477 * Update order status 478 */ 479 static int 480 doupdorder(struct conn *c, struct order *order) 481 { 482 struct jsmnn *j = NULL; 483 int rc = 0; 484 long lc; 485 486 if ((lc = sreq(c, order->uri, 1, "", NULL)) < 0) 487 warnx("%s: bad comm", order->uri); 488 else if (lc != 200) 489 warnx("%s: bad HTTP: %ld", order->uri, lc); 490 else if ((j = json_parse(c->buf.buf, c->buf.sz)) == NULL) 491 warnx("%s: bad JSON object", order->uri); 492 else if (!json_parse_upd_order(j, order)) 493 warnx("%s: bad order", order->uri); 494 else 495 rc = 1; 496 497 if (rc == 0 || verbose > 1) 498 buf_dump(&c->buf); 499 500 json_free(j); 501 return rc; 502 } 503 504 /* 505 * Request a challenge for the given domain name. 506 * This must be called for each name "alt". 507 * On non-zero exit, fills in "chng" with the challenge. 508 */ 509 static int 510 dochngreq(struct conn *c, const char *auth, struct chng *chng) 511 { 512 int rc = 0; 513 long lc; 514 struct jsmnn *j = NULL; 515 516 dodbg("%s: %s", __func__, auth); 517 518 if ((lc = sreq(c, auth, 1, "", NULL)) < 0) 519 warnx("%s: bad comm", auth); 520 else if (lc != 200) 521 warnx("%s: bad HTTP: %ld", auth, lc); 522 else if ((j = json_parse(c->buf.buf, c->buf.sz)) == NULL) 523 warnx("%s: bad JSON object", auth); 524 else if (!json_parse_challenge(j, chng)) 525 warnx("%s: bad challenge", auth); 526 else 527 rc = 1; 528 529 if (rc == 0 || verbose > 1) 530 buf_dump(&c->buf); 531 json_free(j); 532 return rc; 533 } 534 535 /* 536 * Tell the CA that a challenge response is in place. 537 */ 538 static int 539 dochngresp(struct conn *c, const struct chng *chng) 540 { 541 int rc = 0; 542 long lc; 543 544 dodbg("%s: challenge", chng->uri); 545 546 if ((lc = sreq(c, chng->uri, 1, "{}", NULL)) < 0) 547 warnx("%s: bad comm", chng->uri); 548 else if (lc != 200 && lc != 201 && lc != 202) 549 warnx("%s: bad HTTP: %ld", chng->uri, lc); 550 else 551 rc = 1; 552 553 if (rc == 0 || verbose > 1) 554 buf_dump(&c->buf); 555 return rc; 556 } 557 558 /* 559 * Submit our csr to the CA. 560 */ 561 static int 562 docert(struct conn *c, const char *uri, const char *csr) 563 { 564 char *req; 565 int rc = 0; 566 long lc; 567 568 dodbg("%s: certificate", uri); 569 570 if ((req = json_fmt_newcert(csr)) == NULL) 571 warnx("json_fmt_newcert"); 572 else if ((lc = sreq(c, uri, 1, req, NULL)) < 0) 573 warnx("%s: bad comm", uri); 574 else if (lc != 200) 575 warnx("%s: bad HTTP: %ld", uri, lc); 576 else if (c->buf.sz == 0 || c->buf.buf == NULL) 577 warnx("%s: empty response", uri); 578 else 579 rc = 1; 580 581 if (rc == 0 || verbose > 1) 582 buf_dump(&c->buf); 583 free(req); 584 return rc; 585 } 586 587 /* 588 * Get certificate from CA 589 */ 590 static int 591 dogetcert(struct conn *c, const char *uri) 592 { 593 int rc = 0; 594 long lc; 595 596 dodbg("%s: certificate", uri); 597 598 if ((lc = sreq(c, uri, 1, "", NULL)) < 0) 599 warnx("%s: bad comm", uri); 600 else if (lc != 200) 601 warnx("%s: bad HTTP: %ld", uri, lc); 602 else if (c->buf.sz == 0 || c->buf.buf == NULL) 603 warnx("%s: empty response", uri); 604 else 605 rc = 1; 606 607 if (rc == 0 || verbose > 1) 608 buf_dump(&c->buf); 609 610 return rc; 611 } 612 613 static int 614 dorevoke(struct conn *c, const char *addr, const char *cert) 615 { 616 char *req; 617 int rc = 0; 618 long lc = 0; 619 620 dodbg("%s: revocation", addr); 621 622 if ((req = json_fmt_revokecert(cert)) == NULL) 623 warnx("json_fmt_revokecert"); 624 else if ((lc = sreq(c, addr, 1, req, NULL)) < 0) 625 warnx("%s: bad comm", addr); 626 else if (lc != 200 && lc != 201 && lc != 409) 627 warnx("%s: bad HTTP: %ld", addr, lc); 628 else 629 rc = 1; 630 631 if (lc == 409) 632 warnx("%s: already revoked", addr); 633 634 if (rc == 0 || verbose > 1) 635 buf_dump(&c->buf); 636 free(req); 637 return rc; 638 } 639 640 /* 641 * Look up directories from the certificate authority. 642 */ 643 static int 644 dodirs(struct conn *c, const char *addr, struct capaths *paths) 645 { 646 struct jsmnn *j = NULL; 647 long lc; 648 int rc = 0; 649 650 dodbg("%s: directories", addr); 651 652 if ((lc = nreq(c, addr)) < 0) 653 warnx("%s: bad comm", addr); 654 else if (lc != 200 && lc != 201) 655 warnx("%s: bad HTTP: %ld", addr, lc); 656 else if ((j = json_parse(c->buf.buf, c->buf.sz)) == NULL) 657 warnx("json_parse"); 658 else if (!json_parse_capaths(j, paths)) 659 warnx("%s: bad CA paths", addr); 660 else 661 rc = 1; 662 663 if (rc == 0 || verbose > 1) 664 buf_dump(&c->buf); 665 json_free(j); 666 return rc; 667 } 668 669 /* 670 * Communicate with the ACME server. 671 * We need the certificate we want to upload and our account key information. 672 */ 673 int 674 netproc(int kfd, int afd, int Cfd, int cfd, int dfd, int rfd, 675 int revocate, struct authority_c *authority, 676 const char *const *alts, size_t altsz) 677 { 678 int rc = 0; 679 size_t i; 680 char *cert = NULL, *thumb = NULL, *url = NULL, *error = NULL; 681 struct conn c; 682 struct capaths paths; 683 struct order order; 684 struct chng *chngs = NULL; 685 long lval; 686 687 memset(&paths, 0, sizeof(struct capaths)); 688 memset(&c, 0, sizeof(struct conn)); 689 690 if (unveil(tls_default_ca_cert_file(), "r") == -1) { 691 warn("unveil %s", tls_default_ca_cert_file()); 692 goto out; 693 } 694 695 if (pledge("stdio inet rpath", NULL) == -1) { 696 warn("pledge"); 697 goto out; 698 } 699 700 if (http_init() == -1) { 701 warn("http_init"); 702 goto out; 703 } 704 705 if (pledge("stdio inet", NULL) == -1) { 706 warn("pledge"); 707 goto out; 708 } 709 710 /* 711 * Wait until the acctproc, keyproc, and revokeproc have started up and 712 * are ready to serve us data. 713 * Then check whether revokeproc indicates that the certificate on file 714 * (if any) can be updated. 715 */ 716 if ((lval = readop(afd, COMM_ACCT_STAT)) == 0) { 717 rc = 1; 718 goto out; 719 } else if (lval != ACCT_READY) { 720 warnx("unknown operation from acctproc"); 721 goto out; 722 } 723 724 if ((lval = readop(kfd, COMM_KEY_STAT)) == 0) { 725 rc = 1; 726 goto out; 727 } else if (lval != KEY_READY) { 728 warnx("unknown operation from keyproc"); 729 goto out; 730 } 731 732 if ((lval = readop(rfd, COMM_REVOKE_RESP)) == 0) { 733 rc = 1; 734 goto out; 735 } else if (lval != REVOKE_EXP && lval != REVOKE_OK) { 736 warnx("unknown operation from revokeproc"); 737 goto out; 738 } 739 740 /* If our certificate is up-to-date, return now. */ 741 if (lval == REVOKE_OK) { 742 rc = 1; 743 goto out; 744 } 745 746 c.dfd = dfd; 747 c.fd = afd; 748 749 /* 750 * Look up the API urls of the ACME server. 751 */ 752 if (!dodirs(&c, authority->api, &paths)) 753 goto out; 754 755 c.newnonce = paths.newnonce; 756 757 /* Check if our account already exists or create it. */ 758 if (!dochkacc(&c, &paths, authority->contact)) 759 goto out; 760 761 /* 762 * If we're meant to revoke, then wait for revokeproc to send us 763 * the certificate (if it's found at all). 764 * Following that, submit the request to the CA then notify the 765 * certproc, which will in turn notify the fileproc. 766 * XXX currently we can only sign with the account key, the RFC 767 * also mentions signing with the privat key of the cert itself. 768 */ 769 if (revocate) { 770 if ((cert = readstr(rfd, COMM_CSR)) == NULL) 771 goto out; 772 if (!dorevoke(&c, paths.revokecert, cert)) 773 goto out; 774 else if (writeop(cfd, COMM_CSR_OP, CERT_REVOKE) > 0) 775 rc = 1; 776 goto out; 777 } 778 779 memset(&order, 0, sizeof(order)); 780 781 if (!doneworder(&c, alts, altsz, &order, &paths)) 782 goto out; 783 784 chngs = calloc(order.authsz, sizeof(struct chng)); 785 if (chngs == NULL) { 786 warn("calloc"); 787 goto out; 788 } 789 790 /* 791 * Get thumbprint from acctproc. We will need it to construct 792 * a response to the challenge 793 */ 794 if (writeop(afd, COMM_ACCT, ACCT_THUMBPRINT) <= 0) 795 goto out; 796 else if ((thumb = readstr(afd, COMM_THUMB)) == NULL) 797 goto out; 798 799 while(order.status != ORDER_VALID && order.status != ORDER_INVALID) { 800 switch (order.status) { 801 case ORDER_INVALID: 802 warnx("order invalid"); 803 goto out; 804 case ORDER_VALID: 805 rc = 1; 806 continue; 807 case ORDER_PENDING: 808 if (order.authsz < 1) { 809 warnx("order is in state pending but no " 810 "authorizations know"); 811 goto out; 812 } 813 for (i = 0; i < order.authsz; i++) { 814 if (!dochngreq(&c, order.auths[i], &chngs[i])) 815 goto out; 816 817 dodbg("challenge, token: %s, uri: %s, status: " 818 "%d", chngs[i].token, chngs[i].uri, 819 chngs[i].status); 820 821 if (chngs[i].status == CHNG_VALID || 822 chngs[i].status == CHNG_INVALID) 823 continue; 824 825 if (chngs[i].retry++ >= RETRY_MAX) { 826 warnx("%s: too many tries", 827 chngs[i].uri); 828 goto out; 829 } 830 831 if (writeop(Cfd, COMM_CHNG_OP, CHNG_SYN) <= 0) 832 goto out; 833 else if (writestr(Cfd, COMM_THUMB, thumb) <= 0) 834 goto out; 835 else if (writestr(Cfd, COMM_TOK, 836 chngs[i].token) <= 0) 837 goto out; 838 839 /* Read that the challenge has been made. */ 840 if (readop(Cfd, COMM_CHNG_ACK) != CHNG_ACK) 841 goto out; 842 843 } 844 /* Write to the CA that it's ready. */ 845 for (i = 0; i < order.authsz; i++) { 846 if (chngs[i].status == CHNG_VALID || 847 chngs[i].status == CHNG_INVALID) 848 continue; 849 if (!dochngresp(&c, &chngs[i])) 850 goto out; 851 } 852 break; 853 case ORDER_READY: 854 /* 855 * Write our acknowledgement that the challenges are 856 * over. 857 * The challenge process will remove all of the files. 858 */ 859 if (writeop(Cfd, COMM_CHNG_OP, CHNG_STOP) <= 0) 860 goto out; 861 862 /* Wait to receive the certificate itself. */ 863 if ((cert = readstr(kfd, COMM_CERT)) == NULL) 864 goto out; 865 if (!docert(&c, order.finalize, cert)) 866 goto out; 867 break; 868 default: 869 warnx("unhandled status: %d", order.status); 870 goto out; 871 } 872 if (!doupdorder(&c, &order)) 873 goto out; 874 875 dodbg("order.status %d", order.status); 876 if (order.status == ORDER_PENDING) 877 sleep(RETRY_DELAY); 878 } 879 880 if (order.status != ORDER_VALID) { 881 for (i = 0; i < order.authsz; i++) { 882 dochngreq(&c, order.auths[i], &chngs[i]); 883 if (chngs[i].error != NULL) { 884 if (stravis(&error, chngs[i].error, VIS_SAFE) 885 != -1) { 886 warnx("%s", error); 887 free(error); 888 error = NULL; 889 } 890 } 891 } 892 goto out; 893 } 894 895 if (order.certificate == NULL) { 896 warnx("no certificate url received"); 897 goto out; 898 } 899 900 if (!dogetcert(&c, order.certificate)) 901 goto out; 902 else if (writeop(cfd, COMM_CSR_OP, CERT_UPDATE) <= 0) 903 goto out; 904 else if (writebuf(cfd, COMM_CSR, c.buf.buf, c.buf.sz) <= 0) 905 goto out; 906 rc = 1; 907 out: 908 close(cfd); 909 close(kfd); 910 close(afd); 911 close(Cfd); 912 close(dfd); 913 close(rfd); 914 free(cert); 915 free(url); 916 free(thumb); 917 free(c.kid); 918 free(c.buf.buf); 919 if (chngs != NULL) 920 for (i = 0; i < order.authsz; i++) 921 json_free_challenge(&chngs[i]); 922 free(chngs); 923 json_free_capaths(&paths); 924 return rc; 925 } 926