summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/x509/x509_lib.c146
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}
245LCRYPTO_ALIAS(X509V3_get_d2i); 245LCRYPTO_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
252int 247int
253X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, 248X509V3_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
322err: 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}
327LCRYPTO_ALIAS(X509V3_add1_i2d); 359LCRYPTO_ALIAS(X509V3_add1_i2d);
328 360