xref: /openbsd-src/usr.sbin/acme-client/certproc.c (revision d2368eff448f6e0092aa0e6d44f3ed71e85bf1b9)
1*d2368effSflorian /*	$Id: certproc.c,v 1.13 2020/09/14 15:58:50 florian Exp $ */
2de579d12Sflorian /*
3de579d12Sflorian  * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv>
4de579d12Sflorian  *
5de579d12Sflorian  * Permission to use, copy, modify, and distribute this software for any
6de579d12Sflorian  * purpose with or without fee is hereby granted, provided that the above
7de579d12Sflorian  * copyright notice and this permission notice appear in all copies.
8de579d12Sflorian  *
9de579d12Sflorian  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
10de579d12Sflorian  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11de579d12Sflorian  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
12de579d12Sflorian  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13de579d12Sflorian  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14de579d12Sflorian  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15de579d12Sflorian  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16de579d12Sflorian  */
17de579d12Sflorian 
18de579d12Sflorian #include <err.h>
19de579d12Sflorian #include <stdio.h>
20de579d12Sflorian #include <stdlib.h>
21de579d12Sflorian #include <string.h>
22de579d12Sflorian #include <unistd.h>
23de579d12Sflorian 
24de579d12Sflorian #include <openssl/pem.h>
25de579d12Sflorian #include <openssl/x509.h>
26de579d12Sflorian #include <openssl/x509v3.h>
27de579d12Sflorian #include <openssl/err.h>
28de579d12Sflorian 
29de579d12Sflorian #include "extern.h"
30de579d12Sflorian 
31*d2368effSflorian #define BEGIN_MARKER "-----BEGIN CERTIFICATE-----"
32*d2368effSflorian #define END_MARKER "-----END CERTIFICATE-----"
33de579d12Sflorian 
34de579d12Sflorian int
certproc(int netsock,int filesock)35de579d12Sflorian certproc(int netsock, int filesock)
36de579d12Sflorian {
377bce6888Sderaadt 	char		*csr = NULL, *chain = NULL, *url = NULL;
387b00f4e9Sflorian 	char		*chaincp;
39de579d12Sflorian 	size_t		 csrsz, chainsz;
407b00f4e9Sflorian 	int		 rc = 0, cc;
41de579d12Sflorian 	enum certop	 op;
42de579d12Sflorian 	long		 lval;
43de579d12Sflorian 
44ec0d8c8bSderaadt 	if (pledge("stdio", NULL) == -1) {
45ec0d8c8bSderaadt 		warn("pledge");
46de579d12Sflorian 		goto out;
47ec0d8c8bSderaadt 	}
48de579d12Sflorian 
49de579d12Sflorian 	/* Read what the netproc wants us to do. */
50de579d12Sflorian 
51de579d12Sflorian 	op = CERT__MAX;
527cd8f039Sjsing 	if ((lval = readop(netsock, COMM_CSR_OP)) == 0)
53de579d12Sflorian 		op = CERT_STOP;
547cd8f039Sjsing 	else if (lval == CERT_REVOKE || lval == CERT_UPDATE)
55de579d12Sflorian 		op = lval;
56de579d12Sflorian 
57de579d12Sflorian 	if (CERT_STOP == op) {
58de579d12Sflorian 		rc = 1;
59de579d12Sflorian 		goto out;
60de579d12Sflorian 	} else if (CERT__MAX == op) {
61de579d12Sflorian 		warnx("unknown operation from netproc");
62de579d12Sflorian 		goto out;
63de579d12Sflorian 	}
64de579d12Sflorian 
65de579d12Sflorian 	/*
66de579d12Sflorian 	 * Pass revocation right through to fileproc.
67de579d12Sflorian 	 * If the reader is terminated, ignore it.
68de579d12Sflorian 	 */
69de579d12Sflorian 
70de579d12Sflorian 	if (CERT_REVOKE == op) {
71de579d12Sflorian 		if (writeop(filesock, COMM_CHAIN_OP, FILE_REMOVE) >= 0)
72de579d12Sflorian 			rc = 1;
73de579d12Sflorian 		goto out;
74de579d12Sflorian 	}
75de579d12Sflorian 
76de579d12Sflorian 	/*
77de579d12Sflorian 	 * Wait until we receive the DER encoded (signed) certificate
78de579d12Sflorian 	 * from the network process.
79de579d12Sflorian 	 * Then convert the DER encoding into an X509 certificate.
80de579d12Sflorian 	 */
81de579d12Sflorian 
827cd8f039Sjsing 	if ((csr = readbuf(netsock, COMM_CSR, &csrsz)) == NULL)
83de579d12Sflorian 		goto out;
84de579d12Sflorian 
85*d2368effSflorian 	if (csrsz < strlen(END_MARKER)) {
867b00f4e9Sflorian 		warnx("invalid cert");
87de579d12Sflorian 		goto out;
88de579d12Sflorian 	}
89de579d12Sflorian 
90*d2368effSflorian 	chaincp = strstr(csr, END_MARKER);
91de579d12Sflorian 
927b00f4e9Sflorian 	if (chaincp == NULL) {
937b00f4e9Sflorian 		warnx("invalid cert");
947b00f4e9Sflorian 		goto out;
957b00f4e9Sflorian 	}
96de579d12Sflorian 
97*d2368effSflorian 	chaincp += strlen(END_MARKER);
98*d2368effSflorian 
99*d2368effSflorian 	if ((chaincp = strstr(chaincp, BEGIN_MARKER)) == NULL) {
100*d2368effSflorian 		warnx("invalid certificate chain");
101*d2368effSflorian 		goto out;
102*d2368effSflorian 	}
103*d2368effSflorian 
1047b00f4e9Sflorian 	if ((chain = strdup(chaincp)) == NULL) {
105de579d12Sflorian 		warn("strdup");
106de579d12Sflorian 		goto out;
107de579d12Sflorian 	}
108de579d12Sflorian 
1097b00f4e9Sflorian 	*chaincp = '\0';
1107b00f4e9Sflorian 	chainsz = strlen(chain);
1117b00f4e9Sflorian 	csrsz = strlen(csr);
112de579d12Sflorian 
113de579d12Sflorian 	/* Allow reader termination to just push us out. */
114de579d12Sflorian 
1157cd8f039Sjsing 	if ((cc = writeop(filesock, COMM_CHAIN_OP, FILE_CREATE)) == 0)
116de579d12Sflorian 		rc = 1;
117de579d12Sflorian 	if (cc <= 0)
118de579d12Sflorian 		goto out;
1197cd8f039Sjsing 	if ((cc = writebuf(filesock, COMM_CHAIN, chain, chainsz)) == 0)
120de579d12Sflorian 		rc = 1;
121de579d12Sflorian 	if (cc <= 0)
122de579d12Sflorian 		goto out;
123de579d12Sflorian 
1247b00f4e9Sflorian 	if (writebuf(filesock, COMM_CSR, csr, csrsz) < 0)
125de579d12Sflorian 		goto out;
126de579d12Sflorian 
127de579d12Sflorian 	rc = 1;
128de579d12Sflorian out:
129de579d12Sflorian 	close(netsock);
130de579d12Sflorian 	close(filesock);
131de579d12Sflorian 	free(csr);
132de579d12Sflorian 	free(url);
133de579d12Sflorian 	free(chain);
13434335c11Sjsing 	return rc;
135de579d12Sflorian }
136