diff options
author | tb <> | 2024-01-06 17:17:08 +0000 |
---|---|---|
committer | tb <> | 2024-01-06 17:17:08 +0000 |
commit | ca00b1e55ab503cc77058c62611b0b6ec94882f2 (patch) | |
tree | 542d1e5cc853bc1b3fbe0eb77ff56e21067b795b | |
parent | c75f680fbdc8f13b45b60c1e3502617bea21071d (diff) | |
download | openbsd-ca00b1e55ab503cc77058c62611b0b6ec94882f2.tar.gz openbsd-ca00b1e55ab503cc77058c62611b0b6ec94882f2.tar.bz2 openbsd-ca00b1e55ab503cc77058c62611b0b6ec94882f2.zip |
Remove X509_PURPOSE extensibility
Another bit of global state without lock protection. The by now familiar
complications of a stack to make this user configurable, which, of course,
no one ever did. The table is not currently const, and the API exposes its
entries directly, so anyone can modify it. This fits very well with the
safety guarantees of Rust's 'static lifetime, which is how rust-openssl
exposes it (for no good reason).
Remove the stack and make the X509_PURPOSE_add() API always fail.
Simplify the other bits accordingly.
In addition, this API inflicts the charming difference between purpose
identifiers and purpose indexes (the former minus one) onto the user.
Neither of the two obvious solutions to avoid this trap seems to have
crossed the implementer's mind.
ok jsing
-rw-r--r-- | src/lib/libcrypto/x509/x509_purp.c | 122 |
1 files changed, 10 insertions, 112 deletions
diff --git a/src/lib/libcrypto/x509/x509_purp.c b/src/lib/libcrypto/x509/x509_purp.c index de6e03df2b..dbae7bcb7c 100644 --- a/src/lib/libcrypto/x509/x509_purp.c +++ b/src/lib/libcrypto/x509/x509_purp.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_purp.c,v 1.33 2023/12/31 07:19:13 tb Exp $ */ | 1 | /* $OpenBSD: x509_purp.c,v 1.34 2024/01/06 17:17:08 tb Exp $ */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | * project 2001. | 3 | * project 2001. |
4 | */ | 4 | */ |
@@ -95,9 +95,6 @@ static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, | |||
95 | static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); | 95 | static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); |
96 | static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); | 96 | static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); |
97 | 97 | ||
98 | static int xp_cmp(const X509_PURPOSE * const *a, const X509_PURPOSE * const *b); | ||
99 | static void xptable_free(X509_PURPOSE *p); | ||
100 | |||
101 | static X509_PURPOSE xstandard[] = { | 98 | static X509_PURPOSE xstandard[] = { |
102 | { | 99 | { |
103 | .purpose = X509_PURPOSE_SSL_CLIENT, | 100 | .purpose = X509_PURPOSE_SSL_CLIENT, |
@@ -166,14 +163,6 @@ static X509_PURPOSE xstandard[] = { | |||
166 | 163 | ||
167 | #define X509_PURPOSE_COUNT (sizeof(xstandard) / sizeof(xstandard[0])) | 164 | #define X509_PURPOSE_COUNT (sizeof(xstandard) / sizeof(xstandard[0])) |
168 | 165 | ||
169 | static STACK_OF(X509_PURPOSE) *xptable = NULL; | ||
170 | |||
171 | static int | ||
172 | xp_cmp(const X509_PURPOSE * const *a, const X509_PURPOSE * const *b) | ||
173 | { | ||
174 | return (*a)->purpose - (*b)->purpose; | ||
175 | } | ||
176 | |||
177 | /* As much as I'd like to make X509_check_purpose use a "const" X509* | 166 | /* As much as I'd like to make X509_check_purpose use a "const" X509* |
178 | * I really can't because it does recalculate hashes and do other non-const | 167 | * I really can't because it does recalculate hashes and do other non-const |
179 | * things. */ | 168 | * things. */ |
@@ -211,20 +200,17 @@ LCRYPTO_ALIAS(X509_PURPOSE_set); | |||
211 | int | 200 | int |
212 | X509_PURPOSE_get_count(void) | 201 | X509_PURPOSE_get_count(void) |
213 | { | 202 | { |
214 | if (!xptable) | 203 | return X509_PURPOSE_COUNT; |
215 | return X509_PURPOSE_COUNT; | ||
216 | return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT; | ||
217 | } | 204 | } |
218 | LCRYPTO_ALIAS(X509_PURPOSE_get_count); | 205 | LCRYPTO_ALIAS(X509_PURPOSE_get_count); |
219 | 206 | ||
220 | X509_PURPOSE * | 207 | X509_PURPOSE * |
221 | X509_PURPOSE_get0(int idx) | 208 | X509_PURPOSE_get0(int idx) |
222 | { | 209 | { |
223 | if (idx < 0) | 210 | if (idx < 0 || (size_t)idx >= X509_PURPOSE_COUNT) |
224 | return NULL; | 211 | return NULL; |
225 | if (idx < (int)X509_PURPOSE_COUNT) | 212 | |
226 | return xstandard + idx; | 213 | return &xstandard[idx]; |
227 | return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT); | ||
228 | } | 214 | } |
229 | LCRYPTO_ALIAS(X509_PURPOSE_get0); | 215 | LCRYPTO_ALIAS(X509_PURPOSE_get0); |
230 | 216 | ||
@@ -246,18 +232,11 @@ LCRYPTO_ALIAS(X509_PURPOSE_get_by_sname); | |||
246 | int | 232 | int |
247 | X509_PURPOSE_get_by_id(int purpose) | 233 | X509_PURPOSE_get_by_id(int purpose) |
248 | { | 234 | { |
249 | X509_PURPOSE tmp; | 235 | /* X509_PURPOSE_MIN == 1, so the bounds are correct. */ |
250 | int idx; | 236 | if (purpose < X509_PURPOSE_MIN || purpose > X509_PURPOSE_MAX) |
251 | |||
252 | if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX)) | ||
253 | return purpose - X509_PURPOSE_MIN; | ||
254 | tmp.purpose = purpose; | ||
255 | if (!xptable) | ||
256 | return -1; | ||
257 | idx = sk_X509_PURPOSE_find(xptable, &tmp); | ||
258 | if (idx == -1) | ||
259 | return -1; | 237 | return -1; |
260 | return idx + X509_PURPOSE_COUNT; | 238 | |
239 | return purpose - X509_PURPOSE_MIN; | ||
261 | } | 240 | } |
262 | LCRYPTO_ALIAS(X509_PURPOSE_get_by_id); | 241 | LCRYPTO_ALIAS(X509_PURPOSE_get_by_id); |
263 | 242 | ||
@@ -266,95 +245,14 @@ X509_PURPOSE_add(int id, int trust, int flags, | |||
266 | int (*ck)(const X509_PURPOSE *, const X509 *, int), const char *name, | 245 | int (*ck)(const X509_PURPOSE *, const X509 *, int), const char *name, |
267 | const char *sname, void *arg) | 246 | const char *sname, void *arg) |
268 | { | 247 | { |
269 | int idx; | 248 | X509error(ERR_R_DISABLED); |
270 | X509_PURPOSE *ptmp; | ||
271 | char *name_dup, *sname_dup; | ||
272 | |||
273 | name_dup = sname_dup = NULL; | ||
274 | |||
275 | if (name == NULL || sname == NULL) { | ||
276 | X509V3error(X509V3_R_INVALID_NULL_ARGUMENT); | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | /* This is set according to what we change: application can't set it */ | ||
281 | flags &= ~X509_PURPOSE_DYNAMIC; | ||
282 | /* This will always be set for application modified trust entries */ | ||
283 | flags |= X509_PURPOSE_DYNAMIC_NAME; | ||
284 | /* Get existing entry if any */ | ||
285 | idx = X509_PURPOSE_get_by_id(id); | ||
286 | /* Need a new entry */ | ||
287 | if (idx == -1) { | ||
288 | if ((ptmp = malloc(sizeof(X509_PURPOSE))) == NULL) { | ||
289 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
290 | return 0; | ||
291 | } | ||
292 | ptmp->flags = X509_PURPOSE_DYNAMIC; | ||
293 | } else | ||
294 | ptmp = X509_PURPOSE_get0(idx); | ||
295 | |||
296 | if ((name_dup = strdup(name)) == NULL) | ||
297 | goto err; | ||
298 | if ((sname_dup = strdup(sname)) == NULL) | ||
299 | goto err; | ||
300 | |||
301 | /* free existing name if dynamic */ | ||
302 | if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { | ||
303 | free(ptmp->name); | ||
304 | free(ptmp->sname); | ||
305 | } | ||
306 | /* dup supplied name */ | ||
307 | ptmp->name = name_dup; | ||
308 | ptmp->sname = sname_dup; | ||
309 | /* Keep the dynamic flag of existing entry */ | ||
310 | ptmp->flags &= X509_PURPOSE_DYNAMIC; | ||
311 | /* Set all other flags */ | ||
312 | ptmp->flags |= flags; | ||
313 | |||
314 | ptmp->purpose = id; | ||
315 | ptmp->trust = trust; | ||
316 | ptmp->check_purpose = ck; | ||
317 | ptmp->usr_data = arg; | ||
318 | |||
319 | /* If its a new entry manage the dynamic table */ | ||
320 | if (idx == -1) { | ||
321 | if (xptable == NULL && | ||
322 | (xptable = sk_X509_PURPOSE_new(xp_cmp)) == NULL) | ||
323 | goto err; | ||
324 | if (sk_X509_PURPOSE_push(xptable, ptmp) == 0) | ||
325 | goto err; | ||
326 | } | ||
327 | return 1; | ||
328 | |||
329 | err: | ||
330 | free(name_dup); | ||
331 | free(sname_dup); | ||
332 | if (idx == -1) | ||
333 | free(ptmp); | ||
334 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
335 | return 0; | 249 | return 0; |
336 | } | 250 | } |
337 | LCRYPTO_ALIAS(X509_PURPOSE_add); | 251 | LCRYPTO_ALIAS(X509_PURPOSE_add); |
338 | 252 | ||
339 | static void | ||
340 | xptable_free(X509_PURPOSE *p) | ||
341 | { | ||
342 | if (!p) | ||
343 | return; | ||
344 | if (p->flags & X509_PURPOSE_DYNAMIC) { | ||
345 | if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { | ||
346 | free(p->name); | ||
347 | free(p->sname); | ||
348 | } | ||
349 | free(p); | ||
350 | } | ||
351 | } | ||
352 | |||
353 | void | 253 | void |
354 | X509_PURPOSE_cleanup(void) | 254 | X509_PURPOSE_cleanup(void) |
355 | { | 255 | { |
356 | sk_X509_PURPOSE_pop_free(xptable, xptable_free); | ||
357 | xptable = NULL; | ||
358 | } | 256 | } |
359 | LCRYPTO_ALIAS(X509_PURPOSE_cleanup); | 257 | LCRYPTO_ALIAS(X509_PURPOSE_cleanup); |
360 | 258 | ||