1 #include "rpp.h"
2
3 #include <stdlib.h>
4 #include "cert_stack.h"
5 #include "log.h"
6 #include "thread_var.h"
7 #include "types/uri.h"
8 #include "data_structure/array_list.h"
9 #include "object/certificate.h"
10 #include "object/crl.h"
11 #include "object/ghostbusters.h"
12 #include "object/roa.h"
13
14 STATIC_ARRAY_LIST(uris, struct rpki_uri *)
15
16 /** A Repository Publication Point (RFC 6481), as described by some manifest. */
17 struct rpp {
18 struct uris certs; /* Certificates */
19
20 /*
21 * uri NULL implies stack NULL and error 0.
22 * If uri is set, stack might or might not be set.
23 * error is only relevant when uri is set and stack is unset.
24 */
25 struct { /* Certificate Revocation List */
26 struct rpki_uri *uri;
27 /*
28 * CRL in libcrypto-friendly form.
29 * Initialized lazily; access via rpp_crl().
30 */
31 STACK_OF(X509_CRL) *stack;
32 /*
33 * Some error code if we already tried to initialize @stack but
34 * failed. Prevents us from wasting time doing it again, and
35 * flooding the log with identical error messages.
36 */
37 int error;
38 } crl;
39
40 /* The Manifest is not needed for now. */
41
42 struct uris roas; /* Route Origin Attestations */
43
44 struct uris ghostbusters;
45
46 /*
47 * Note that the reference counting functions are not prepared for
48 * multithreading, because this is not atomic.
49 */
50 unsigned int references;
51 };
52
53 struct rpp *
rpp_create(void)54 rpp_create(void)
55 {
56 struct rpp *result;
57
58 result = malloc(sizeof(struct rpp));
59 if (result == NULL)
60 return NULL;
61
62 uris_init(&result->certs);
63 result->crl.uri = NULL;
64 result->crl.stack = NULL;
65 result->crl.error = 0;
66 uris_init(&result->roas);
67 uris_init(&result->ghostbusters);
68 result->references = 1;
69
70 return result;
71 }
72
73 void
rpp_refget(struct rpp * pp)74 rpp_refget(struct rpp *pp)
75 {
76 pp->references++;
77 }
78
79 static void
__uri_refput(struct rpki_uri ** uri)80 __uri_refput(struct rpki_uri **uri)
81 {
82 uri_refput(*uri);
83 }
84
85 void
rpp_refput(struct rpp * pp)86 rpp_refput(struct rpp *pp)
87 {
88 pp->references--;
89 if (pp->references == 0) {
90 uris_cleanup(&pp->certs, __uri_refput);
91 if (pp->crl.uri != NULL)
92 uri_refput(pp->crl.uri);
93 if (pp->crl.stack != NULL)
94 sk_X509_CRL_pop_free(pp->crl.stack, X509_CRL_free);
95 uris_cleanup(&pp->roas, __uri_refput);
96 uris_cleanup(&pp->ghostbusters, __uri_refput);
97 free(pp);
98 }
99 }
100
101 /** Steals ownership of @uri. */
102 int
rpp_add_cert(struct rpp * pp,struct rpki_uri * uri)103 rpp_add_cert(struct rpp *pp, struct rpki_uri *uri)
104 {
105 return uris_add(&pp->certs, &uri);
106 }
107
108 /** Steals ownership of @uri. */
109 int
rpp_add_roa(struct rpp * pp,struct rpki_uri * uri)110 rpp_add_roa(struct rpp *pp, struct rpki_uri *uri)
111 {
112 return uris_add(&pp->roas, &uri);
113 }
114
115 /** Steals ownership of @uri. */
116 int
rpp_add_ghostbusters(struct rpp * pp,struct rpki_uri * uri)117 rpp_add_ghostbusters(struct rpp *pp, struct rpki_uri *uri)
118 {
119 return uris_add(&pp->ghostbusters, &uri);
120 }
121
122 /** Steals ownership of @uri. */
123 int
rpp_add_crl(struct rpp * pp,struct rpki_uri * uri)124 rpp_add_crl(struct rpp *pp, struct rpki_uri *uri)
125 {
126 /* rfc6481#section-2.2 */
127 if (pp->crl.uri)
128 return pr_val_err("Repository Publication Point has more than one CRL.");
129
130 pp->crl.uri = uri;
131 return 0;
132 }
133
134 struct rpki_uri *
rpp_get_crl(struct rpp const * pp)135 rpp_get_crl(struct rpp const *pp)
136 {
137 return pp->crl.uri;
138 }
139
140 static int
add_crl_to_stack(struct rpp * pp,STACK_OF (X509_CRL)* crls)141 add_crl_to_stack(struct rpp *pp, STACK_OF(X509_CRL) *crls)
142 {
143 X509_CRL *crl;
144 int error;
145 int idx;
146
147 fnstack_push_uri(pp->crl.uri);
148
149 error = crl_load(pp->crl.uri, &crl);
150 if (error)
151 goto end;
152
153 idx = sk_X509_CRL_push(crls, crl);
154 if (idx <= 0) {
155 error = val_crypto_err("Could not add CRL to a CRL stack");
156 X509_CRL_free(crl);
157 goto end;
158 }
159
160 end:
161 fnstack_pop();
162 return error;
163 }
164
165 /**
166 * Returns the pp's CRL in stack form (which is how libcrypto functions want
167 * it).
168 * The stack belongs to @pp and should not be released. Can be NULL, in which
169 * case you're currently validating the TA (since it lacks governing CRL).
170 */
171 int
rpp_crl(struct rpp * pp,STACK_OF (X509_CRL)** result)172 rpp_crl(struct rpp *pp, STACK_OF(X509_CRL) **result)
173 {
174 STACK_OF(X509_CRL) *stack;
175
176 /* -- Short circuits -- */
177 if (pp == NULL) {
178 /* No pp = currently validating TA. There's no CRL. */
179 *result = NULL;
180 return 0;
181 }
182 if (pp->crl.uri == NULL) {
183 /* rpp_crl() assumes the rpp has been populated already. */
184 pr_crit("RPP lacks a CRL.");
185 }
186 if (pp->crl.stack != NULL) {
187 /* Result already cached. */
188 *result = pp->crl.stack;
189 return 0;
190 }
191 if (pp->crl.error) {
192 /* Pretend that we did everything below. */
193 return pp->crl.error;
194 }
195
196 /* -- Actually initialize pp->crl.stack. -- */
197 stack = sk_X509_CRL_new_null();
198 if (stack == NULL) {
199 pp->crl.error = pr_enomem();
200 return pp->crl.error;
201 }
202 pp->crl.error = add_crl_to_stack(pp, stack);
203 if (pp->crl.error) {
204 sk_X509_CRL_pop_free(stack, X509_CRL_free);
205 return pp->crl.error;
206 }
207
208 pp->crl.stack = stack;
209 *result = stack;
210 return 0;
211 }
212
213 static int
__cert_traverse(struct rpp * pp)214 __cert_traverse(struct rpp *pp)
215 {
216 struct validation *state;
217 struct cert_stack *certstack;
218 ssize_t i;
219 struct deferred_cert deferred;
220 int error;
221
222 if (pp->certs.len == 0)
223 return 0;
224
225 state = state_retrieve();
226 if (state == NULL)
227 return -EINVAL;
228 certstack = validation_certstack(state);
229
230 deferred.pp = pp;
231 /*
232 * The for is inverted, to achieve FIFO behavior since the separator.
233 * Not really important; it simply makes the traversal order more
234 * intuitive.
235 */
236 for (i = pp->certs.len - 1; i >= 0; i--) {
237 deferred.uri = pp->certs.array[i];
238 error = deferstack_push(certstack, &deferred);
239 if (error)
240 return error;
241 }
242
243 return 0;
244 }
245
246 /**
247 * Traverses through all of @pp's known files, validating them.
248 */
249 void
rpp_traverse(struct rpp * pp)250 rpp_traverse(struct rpp *pp)
251 {
252 struct rpki_uri **uri;
253 array_index i;
254
255 /*
256 * A subtree should not invalidate the rest of the tree, so error codes
257 * are ignored.
258 * (Errors log messages anyway.)
259 */
260
261 /*
262 * Certificates cannot be validated now, because then the algorithm
263 * would be recursive.
264 * Store them in the defer stack (see cert_stack.h), will get back to
265 * them later.
266 */
267 __cert_traverse(pp);
268
269 /* Validate ROAs, apply validation_handler on them. */
270 ARRAYLIST_FOREACH(&pp->roas, uri, i)
271 roa_traverse(*uri, pp);
272
273 /*
274 * We don't do much with the ghostbusters right now.
275 * Just validate them.
276 */
277 ARRAYLIST_FOREACH(&pp->ghostbusters, uri, i)
278 ghostbusters_traverse(*uri, pp);
279 }
280