xref: /openbsd-src/usr.sbin/acme-client/certproc.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$Id: certproc.c,v 1.12 2019/06/07 08:07:52 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 <err.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 
24 #include <openssl/pem.h>
25 #include <openssl/x509.h>
26 #include <openssl/x509v3.h>
27 #include <openssl/err.h>
28 
29 #include "extern.h"
30 
31 #define MARKER "-----END CERTIFICATE-----\n"
32 
33 int
34 certproc(int netsock, int filesock)
35 {
36 	char		*csr = NULL, *chain = NULL, *url = NULL;
37 	char		*chaincp;
38 	size_t		 csrsz, chainsz;
39 	int		 rc = 0, cc;
40 	enum certop	 op;
41 	long		 lval;
42 
43 	if (pledge("stdio", NULL) == -1) {
44 		warn("pledge");
45 		goto out;
46 	}
47 
48 	/* Read what the netproc wants us to do. */
49 
50 	op = CERT__MAX;
51 	if ((lval = readop(netsock, COMM_CSR_OP)) == 0)
52 		op = CERT_STOP;
53 	else if (lval == CERT_REVOKE || lval == CERT_UPDATE)
54 		op = lval;
55 
56 	if (CERT_STOP == op) {
57 		rc = 1;
58 		goto out;
59 	} else if (CERT__MAX == op) {
60 		warnx("unknown operation from netproc");
61 		goto out;
62 	}
63 
64 	/*
65 	 * Pass revocation right through to fileproc.
66 	 * If the reader is terminated, ignore it.
67 	 */
68 
69 	if (CERT_REVOKE == op) {
70 		if (writeop(filesock, COMM_CHAIN_OP, FILE_REMOVE) >= 0)
71 			rc = 1;
72 		goto out;
73 	}
74 
75 	/*
76 	 * Wait until we receive the DER encoded (signed) certificate
77 	 * from the network process.
78 	 * Then convert the DER encoding into an X509 certificate.
79 	 */
80 
81 	if ((csr = readbuf(netsock, COMM_CSR, &csrsz)) == NULL)
82 		goto out;
83 
84 	if (csrsz < strlen(MARKER)) {
85 		warnx("invalid cert");
86 		goto out;
87 	}
88 
89 	chaincp = strstr(csr, MARKER);
90 
91 	if (chaincp == NULL) {
92 		warnx("invalid cert");
93 		goto out;
94 	}
95 
96 	chaincp += strlen(MARKER);
97 	if ((chain = strdup(chaincp)) == NULL) {
98 		warn("strdup");
99 		goto out;
100 	}
101 
102 	*chaincp = '\0';
103 	chainsz = strlen(chain);
104 	csrsz = strlen(csr);
105 
106 	/* Allow reader termination to just push us out. */
107 
108 	if ((cc = writeop(filesock, COMM_CHAIN_OP, FILE_CREATE)) == 0)
109 		rc = 1;
110 	if (cc <= 0)
111 		goto out;
112 	if ((cc = writebuf(filesock, COMM_CHAIN, chain, chainsz)) == 0)
113 		rc = 1;
114 	if (cc <= 0)
115 		goto out;
116 
117 	if (writebuf(filesock, COMM_CSR, csr, csrsz) < 0)
118 		goto out;
119 
120 	rc = 1;
121 out:
122 	close(netsock);
123 	close(filesock);
124 	free(csr);
125 	free(url);
126 	free(chain);
127 	return rc;
128 }
129