static int fd_revoke(struct lwp *l, int fd, register_t *retval) { file_t *fp; vnode_t *vp; int error; if ((fp = fd_getfile(fd)) == NULL) return EBADF; if (fp->f_type != DTYPE_VNODE) { fd_putfile(fd); return EINVAL; } vp = (vnode_t *) fp->f_data; if (vp->v_type != VCHR && vp->v_type != VBLK) { error = EINVAL; goto out; } error = dorevoke(vp, l->l_cred); out: vrele(vp); fd_putfile(fd); return error; }
/* * Here we communicate with the letsencrypt server. * For this, we'll need the certificate we want to upload and our * account key information. */ int netproc(int kfd, int afd, int Cfd, int cfd, int dfd, int rfd, int newacct, int revoke, int staging, const char *const *alts, size_t altsz) { int rc; size_t i; char *cert, *thumb, *url; struct conn c; struct capaths paths; struct chng *chngs; long lval; rc = 0; memset(&paths, 0, sizeof(struct capaths)); memset(&c, 0, sizeof(struct conn)); url = cert = thumb = NULL; chngs = NULL; /* File-system, user, and sandbox jail. */ if ( ! sandbox_before()) goto out; else if ( ! dropfs(PATH_VAR_EMPTY)) goto out; else if ( ! dropprivs()) goto out; else if ( ! sandbox_after()) goto out; /* * Wait until the acctproc, keyproc, and revokeproc have started * up and are ready to serve us data. * There's no point in running if these don't work. * Then check whether revokeproc indicates that the certificate * on file (if any) can be updated. */ if (0 == (lval = readop(afd, COMM_ACCT_STAT))) { rc = 1; goto out; } else if (ACCT_READY != lval) { warnx("unknown operation from acctproc"); goto out; } if (0 == (lval = readop(kfd, COMM_KEY_STAT))) { rc = 1; goto out; } else if (KEY_READY != lval) { warnx("unknown operation from keyproc"); goto out; } if (0 == (lval = readop(rfd, COMM_REVOKE_RESP))) { rc = 1; goto out; } else if (REVOKE_EXP != lval && REVOKE_OK != lval) { warnx("unknown operation from revokeproc"); goto out; } /* If our certificate is up-to-date, return now. */ if (REVOKE_OK == lval) { rc = 1; goto out; } /* Allocate main state. */ chngs = calloc(altsz, sizeof(struct chng)); if (NULL == chngs) { warn("calloc"); goto out; } c.dfd = dfd; c.fd = afd; c.na = staging ? URL_STAGE_CA : URL_REAL_CA; /* * Look up the domain of the ACME server. * We'll use this ourselves instead of having libcurl do the DNS * resolution itself. */ if ( ! dodirs(&c, c.na, &paths)) goto out; /* * If we're meant to revoke, then wait for revokeproc to send us * the certificate (if it's found at all). * Following that, submit the request to the CA then notify the * certproc, which will in turn notify the fileproc. */ if (revoke) { if (NULL == (cert = readstr(rfd, COMM_CSR))) goto out; if ( ! dorevoke(&c, paths.revokecert, cert)) goto out; else if (writeop(cfd, COMM_CSR_OP, CERT_REVOKE) > 0) rc = 1; goto out; } /* If new, register with the CA server. */ if (newacct && ! donewreg(&c, &paths)) goto out; /* Pre-authorise all domains with CA server. */ for (i = 0; i < altsz; i++) if ( ! dochngreq(&c, alts[i], &chngs[i], &paths)) goto out; /* * We now have our challenges. * We need to ask the acctproc for the thumbprint. * We'll combine this to the challenge to create our response, * which will be orchestrated by the chngproc. */ if (writeop(afd, COMM_ACCT, ACCT_THUMBPRINT) <= 0) goto out; else if (NULL == (thumb = readstr(afd, COMM_THUMB))) goto out; /* We'll now ask chngproc to build the challenge. */ for (i = 0; i < altsz; i++) { if (writeop(Cfd, COMM_CHNG_OP, CHNG_SYN) <= 0) goto out; else if (writestr(Cfd, COMM_THUMB, thumb) <= 0) goto out; else if (writestr(Cfd, COMM_TOK, chngs[i].token) <= 0) goto out; /* Read that the challenge has been made. */ if (CHNG_ACK != readop(Cfd, COMM_CHNG_ACK)) goto out; /* Write to the CA that it's ready. */ if ( ! dochngresp(&c, &chngs[i], thumb)) goto out; } /* * We now wait on the ACME server for each domain. * Connect to the server (assume it's the same server) once * every five seconds. */ for (i = 0; i < altsz; i++) { if (1 == chngs[i].status) continue; if (chngs[i].retry++ >= RETRY_MAX) { warnx("%s: too many tries", chngs[i].uri); goto out; } /* Sleep before every attempt. */ sleep(RETRY_DELAY); if ( ! dochngcheck(&c, &chngs[i])) goto out; } /* * Write our acknowledgement that the challenges are over. * The challenge process will remove all of the files. */ if (writeop(Cfd, COMM_CHNG_OP, CHNG_STOP) <= 0) goto out; /* Wait to receive the certificate itself. */ if (NULL == (cert = readstr(kfd, COMM_CERT))) goto out; /* * Otherwise, submit the CA for signing, download the signed * copy, and ship that into the certificate process for copying. */ if ( ! docert(&c, paths.newcert, cert)) goto out; else if (writeop(cfd, COMM_CSR_OP, CERT_UPDATE) <= 0) goto out; else if (writebuf(cfd, COMM_CSR, c.buf.buf, c.buf.sz) <= 0) goto out; /* * Read back the issuer from the certproc. * Then contact the issuer to get the certificate chain. * Write this chain directly back to the certproc. */ if (NULL == (url = readstr(cfd, COMM_ISSUER))) goto out; else if ( ! dofullchain(&c, url)) goto out; else if (writebuf(cfd, COMM_CHAIN, c.buf.buf, c.buf.sz) <= 0) goto out; rc = 1; out: close(cfd); close(kfd); close(afd); close(Cfd); close(dfd); close(rfd); free(cert); free(url); free(thumb); free(c.buf.buf); if (NULL != chngs) for (i = 0; i < altsz; i++) json_free_challenge(&chngs[i]); free(chngs); json_free_capaths(&paths); return(rc); }