summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2025-07-27 07:06:41 +0000
committertb <>2025-07-27 07:06:41 +0000
commitd943e504ca5f07a9282522f6183ff0b704ec8c78 (patch)
treed8f2a2aa61750dd2eeee507c23d9c20218a68a9f /src
parent59f09d3bd92a58f2493043b70a91102b64275929 (diff)
downloadopenbsd-d943e504ca5f07a9282522f6183ff0b704ec8c78.tar.gz
openbsd-d943e504ca5f07a9282522f6183ff0b704ec8c78.tar.bz2
openbsd-d943e504ca5f07a9282522f6183ff0b704ec8c78.zip
Fix incorrect ownership handling in add_attribute()
This little gem has a number of issues. On failure, the caller can't know whether ownership of value was taken or not, so to avoid a double free, the only option is to leak value on failure. As X509_ATTRIBUTE_create() takes ownership on success, this call must be the last one that can fail. This way ownership is only taken on success. Next, if X509_ATTRIBUTE_create() fails in the case that the input stack already contains an attribute of type nid, that attr is freed and the caller freeing the stack with pop_free() will double free. So, rework this in a few ways. Make this transactional, so we don't fail with a modified *in_sk, so work with a local sk as usual. Then walk the stack and see if we have an attribute with the appropriate nid already. If not, make sure there's room to place the new attribute. Create the new attribute, free the old attribute if necessary and replace it with the new one. Finally assign the local sk to *in_sk and return success. On error unwind all we did. The behavior now matches OpenSSL 3's new behavior, except that we don't leave an empty stack around on error. ok kenjiro
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/pkcs7/pk7_doit.c76
1 files changed, 42 insertions, 34 deletions
diff --git a/src/lib/libcrypto/pkcs7/pk7_doit.c b/src/lib/libcrypto/pkcs7/pk7_doit.c
index 3a2076a25f..e39d960780 100644
--- a/src/lib/libcrypto/pkcs7/pk7_doit.c
+++ b/src/lib/libcrypto/pkcs7/pk7_doit.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: pk7_doit.c,v 1.60 2025/05/10 05:54:38 tb Exp $ */ 1/* $OpenBSD: pk7_doit.c,v 1.61 2025/07/27 07:06:41 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -1208,43 +1208,51 @@ PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
1208LCRYPTO_ALIAS(PKCS7_set_attributes); 1208LCRYPTO_ALIAS(PKCS7_set_attributes);
1209 1209
1210static int 1210static int
1211add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, void *value) 1211add_attribute(STACK_OF(X509_ATTRIBUTE) **in_sk, int nid, int atrtype, void *value)
1212{ 1212{
1213 X509_ATTRIBUTE *attr = NULL; 1213 STACK_OF(X509_ATTRIBUTE) *sk;
1214 X509_ATTRIBUTE *old_attr = NULL, *new_attr = NULL;
1215 int need_pop = 0;
1216 int i;
1214 1217
1215 if (*sk == NULL) { 1218 if ((sk = *in_sk) == NULL)
1216 *sk = sk_X509_ATTRIBUTE_new_null(); 1219 sk = sk_X509_ATTRIBUTE_new_null();
1217 if (*sk == NULL) 1220 if (sk == NULL)
1218 return 0; 1221 goto err;
1219new_attrib: 1222
1220 if (!(attr = X509_ATTRIBUTE_create(nid, atrtype, value))) 1223 /* Replace an already existing attribute with the given nid. */
1221 return 0; 1224 for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
1222 if (!sk_X509_ATTRIBUTE_push(*sk, attr)) { 1225 old_attr = sk_X509_ATTRIBUTE_value(sk, i);
1223 X509_ATTRIBUTE_free(attr); 1226 if(OBJ_obj2nid(old_attr->object) == nid)
1224 return 0; 1227 break;
1225 } 1228 }
1226 } else { 1229
1227 int i; 1230 /* If there is none, make room for the new one, so _set() succeeds. */
1228 1231 if (i == sk_X509_ATTRIBUTE_num(sk)) {
1229 for (i = 0; i < sk_X509_ATTRIBUTE_num(*sk); i++) { 1232 old_attr = NULL;
1230 attr = sk_X509_ATTRIBUTE_value(*sk, i); 1233 if (sk_X509_ATTRIBUTE_push(sk, NULL) <= 0)
1231 if (OBJ_obj2nid(attr->object) == nid) { 1234 goto err;
1232 X509_ATTRIBUTE_free(attr); 1235 need_pop = 1;
1233 attr = X509_ATTRIBUTE_create(nid, atrtype,
1234 value);
1235 if (attr == NULL)
1236 return 0;
1237 if (!sk_X509_ATTRIBUTE_set(*sk, i, attr)) {
1238 X509_ATTRIBUTE_free(attr);
1239 return 0;
1240 }
1241 goto end;
1242 }
1243 }
1244 goto new_attrib;
1245 } 1236 }
1246end: 1237
1238 /* On success, new_attr owns value. */
1239 if ((new_attr = X509_ATTRIBUTE_create(nid, atrtype, value)) == NULL)
1240 goto err;
1241
1242 X509_ATTRIBUTE_free(old_attr);
1243 (void)sk_X509_ATTRIBUTE_set(sk, i, new_attr);
1244
1245 *in_sk = sk;
1246
1247 return 1; 1247 return 1;
1248
1249 err:
1250 if (need_pop)
1251 (void)sk_X509_ATTRIBUTE_pop(sk);
1252 if (*in_sk != sk)
1253 sk_X509_ATTRIBUTE_pop_free(sk, X509_ATTRIBUTE_free);
1254
1255 return 0;
1248} 1256}
1249 1257
1250int 1258int