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