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