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