diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/x509/x509_lib.c | 146 |
1 files changed, 89 insertions, 57 deletions
diff --git a/src/lib/libcrypto/x509/x509_lib.c b/src/lib/libcrypto/x509/x509_lib.c index 578f55ec55..4347875885 100644 --- a/src/lib/libcrypto/x509/x509_lib.c +++ b/src/lib/libcrypto/x509/x509_lib.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_lib.c,v 1.20 2024/05/11 18:59:39 tb Exp $ */ | 1 | /* $OpenBSD: x509_lib.c,v 1.21 2024/05/28 15:40:38 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 1999. | 3 | * project 1999. |
4 | */ | 4 | */ |
@@ -244,85 +244,117 @@ X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx) | |||
244 | } | 244 | } |
245 | LCRYPTO_ALIAS(X509V3_get_d2i); | 245 | LCRYPTO_ALIAS(X509V3_get_d2i); |
246 | 246 | ||
247 | /* This function is a general extension append, replace and delete utility. | ||
248 | * The precise operation is governed by the 'flags' value. The 'crit' and | ||
249 | * 'value' arguments (if relevant) are the extensions internal structure. | ||
250 | */ | ||
251 | |||
252 | int | 247 | int |
253 | X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, | 248 | X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, |
254 | int crit, unsigned long flags) | 249 | int crit, unsigned long flags) |
255 | { | 250 | { |
256 | int extidx = -1; | 251 | STACK_OF(X509_EXTENSION) *exts = *x; |
257 | int errcode; | 252 | X509_EXTENSION *ext = NULL; |
258 | X509_EXTENSION *ext, *extmp; | 253 | X509_EXTENSION *existing; |
259 | unsigned long ext_op = flags & X509V3_ADD_OP_MASK; | 254 | int extidx; |
260 | 255 | int errcode = 0; | |
261 | /* If appending we don't care if it exists, otherwise | 256 | int ret = 0; |
262 | * look for existing extension. | 257 | |
263 | */ | 258 | /* See if the extension already exists. */ |
264 | if (ext_op != X509V3_ADD_APPEND) | 259 | extidx = X509v3_get_ext_by_NID(*x, nid, -1); |
265 | extidx = X509v3_get_ext_by_NID(*x, nid, -1); | 260 | |
266 | 261 | switch (flags & X509V3_ADD_OP_MASK) { | |
267 | /* See if extension exists */ | 262 | case X509V3_ADD_DEFAULT: |
268 | if (extidx >= 0) { | 263 | /* If the extension exists, adding another one is an error. */ |
269 | /* If keep existing, nothing to do */ | 264 | if (extidx >= 0) { |
270 | if (ext_op == X509V3_ADD_KEEP_EXISTING) | ||
271 | return 1; | ||
272 | /* If default then its an error */ | ||
273 | if (ext_op == X509V3_ADD_DEFAULT) { | ||
274 | errcode = X509V3_R_EXTENSION_EXISTS; | 265 | errcode = X509V3_R_EXTENSION_EXISTS; |
275 | goto err; | 266 | goto err; |
276 | } | 267 | } |
277 | /* If delete, just delete it */ | 268 | break; |
278 | if (ext_op == X509V3_ADD_DELETE) { | 269 | case X509V3_ADD_APPEND: |
279 | if ((extmp = sk_X509_EXTENSION_delete(*x, extidx)) == NULL) | 270 | /* |
280 | return -1; | 271 | * XXX - Total misfeature. If the extension exists, appending |
281 | X509_EXTENSION_free(extmp); | 272 | * another one will invalidate the certificate. Unfortunately |
282 | return 1; | 273 | * things use this, in particular Viktor's DANE code. |
283 | } | ||
284 | } else { | ||
285 | /* If replace existing or delete, error since | ||
286 | * extension must exist | ||
287 | */ | 274 | */ |
288 | if ((ext_op == X509V3_ADD_REPLACE_EXISTING) || | 275 | /* Pretend the extension didn't exist and append the new one. */ |
289 | (ext_op == X509V3_ADD_DELETE)) { | 276 | extidx = -1; |
277 | break; | ||
278 | case X509V3_ADD_REPLACE: | ||
279 | /* Replace existing extension, otherwise append the new one. */ | ||
280 | break; | ||
281 | case X509V3_ADD_REPLACE_EXISTING: | ||
282 | /* Can't replace a non-existent extension. */ | ||
283 | if (extidx < 0) { | ||
290 | errcode = X509V3_R_EXTENSION_NOT_FOUND; | 284 | errcode = X509V3_R_EXTENSION_NOT_FOUND; |
291 | goto err; | 285 | goto err; |
292 | } | 286 | } |
287 | break; | ||
288 | case X509V3_ADD_KEEP_EXISTING: | ||
289 | /* If the extension exists, there's nothing to do. */ | ||
290 | if (extidx >= 0) | ||
291 | goto done; | ||
292 | break; | ||
293 | case X509V3_ADD_DELETE: | ||
294 | /* Can't delete a non-existent extension. */ | ||
295 | if (extidx < 0) { | ||
296 | errcode = X509V3_R_EXTENSION_NOT_FOUND; | ||
297 | goto err; | ||
298 | } | ||
299 | if ((existing = sk_X509_EXTENSION_delete(*x, extidx)) == NULL) { | ||
300 | ret = -1; | ||
301 | goto err; | ||
302 | } | ||
303 | X509_EXTENSION_free(existing); | ||
304 | existing = NULL; | ||
305 | goto done; | ||
306 | default: | ||
307 | errcode = X509V3_R_UNSUPPORTED_OPTION; /* XXX */ | ||
308 | ret = -1; | ||
309 | goto err; | ||
293 | } | 310 | } |
294 | 311 | ||
295 | /* If we get this far then we have to create an extension: | 312 | if ((ext = X509V3_EXT_i2d(nid, crit, value)) == NULL) { |
296 | * could have some flags for alternative encoding schemes... | ||
297 | */ | ||
298 | |||
299 | ext = X509V3_EXT_i2d(nid, crit, value); | ||
300 | |||
301 | if (!ext) { | ||
302 | X509V3error(X509V3_R_ERROR_CREATING_EXTENSION); | 313 | X509V3error(X509V3_R_ERROR_CREATING_EXTENSION); |
303 | return 0; | 314 | goto err; |
304 | } | 315 | } |
305 | 316 | ||
306 | /* If extension exists replace it.. */ | 317 | /* From here, errors are fatal. */ |
318 | ret = -1; | ||
319 | |||
320 | /* If extension exists, replace it. */ | ||
307 | if (extidx >= 0) { | 321 | if (extidx >= 0) { |
308 | extmp = sk_X509_EXTENSION_value(*x, extidx); | 322 | existing = sk_X509_EXTENSION_value(*x, extidx); |
309 | X509_EXTENSION_free(extmp); | 323 | X509_EXTENSION_free(existing); |
310 | if (!sk_X509_EXTENSION_set(*x, extidx, ext)) | 324 | existing = NULL; |
311 | return -1; | 325 | if (sk_X509_EXTENSION_set(*x, extidx, ext) == NULL) { |
312 | return 1; | 326 | /* |
327 | * XXX - Can't happen. If it did happen, |existing| is | ||
328 | * now a freed pointer. Nothing we can do here. | ||
329 | */ | ||
330 | goto err; | ||
331 | } | ||
332 | goto done; | ||
313 | } | 333 | } |
314 | 334 | ||
315 | if (!*x && !(*x = sk_X509_EXTENSION_new_null())) | 335 | if (exts == NULL) |
316 | return -1; | 336 | exts = sk_X509_EXTENSION_new_null(); |
317 | if (!sk_X509_EXTENSION_push(*x, ext)) | 337 | if (exts == NULL) |
318 | return -1; | 338 | goto err; |
339 | |||
340 | if (!sk_X509_EXTENSION_push(exts, ext)) | ||
341 | goto err; | ||
342 | ext = NULL; | ||
343 | |||
344 | *x = exts; | ||
319 | 345 | ||
346 | done: | ||
320 | return 1; | 347 | return 1; |
321 | 348 | ||
322 | err: | 349 | err: |
323 | if (!(flags & X509V3_ADD_SILENT)) | 350 | if ((flags & X509V3_ADD_SILENT) == 0 && errcode != 0) |
324 | X509V3error(errcode); | 351 | X509V3error(errcode); |
325 | return 0; | 352 | |
353 | if (exts != *x) | ||
354 | sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); | ||
355 | X509_EXTENSION_free(ext); | ||
356 | |||
357 | return ret; | ||
326 | } | 358 | } |
327 | LCRYPTO_ALIAS(X509V3_add1_i2d); | 359 | LCRYPTO_ALIAS(X509V3_add1_i2d); |
328 | 360 | ||