diff options
Diffstat (limited to 'src')
| -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 | ||
