]> granicus.if.org Git - curl/commitdiff
cert_stuff: avoid double free in the PKCS12 code
authorDaniel Stenberg <daniel@haxx.se>
Mon, 10 Jun 2013 21:42:48 +0000 (23:42 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 10 Jun 2013 21:42:48 +0000 (23:42 +0200)
In the pkcs12 code, we get a list of x509 records returned from
PKCS12_parse but when iterating over the list and passing each to
SSL_CTX_add_extra_chain_cert() we didn't also properly remove them from
the "stack", which made them get freed twice (both in sk_X509_pop_free()
and then later in SSL_CTX_free).

This isn't really documented anywhere...

Bug: http://curl.haxx.se/bug/view.cgi?id=1236
Reported-by: Nikaiw
lib/ssluse.c

index e9ae45ae0070b13d62c6f5a47903fc4b5c0fd69f..1bb732785d5de3157c4517f8be5f0fb78e2a7558 100644 (file)
@@ -464,11 +464,22 @@ int cert_stuff(struct connectdata *conn,
       /* Set Certificate Verification chain */
       if(ca && sk_X509_num(ca)) {
         for(i = 0; i < sk_X509_num(ca); i++) {
-          if(!SSL_CTX_add_extra_chain_cert(ctx, sk_X509_value(ca, i))) {
+          /*
+           * Note that sk_X509_pop() is used below to make sure the cert is
+           * removed from the stack properly before getting passed to
+           * SSL_CTX_add_extra_chain_cert(). Previously we used
+           * sk_X509_value() instead, but then we'd clean it in the subsequent
+           * sk_X509_pop_free() call.
+           */
+          X509 *x = sk_X509_pop(ca);
+          if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
             failf(data, "cannot add certificate to certificate chain");
             goto fail;
           }
-          if(!SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i))) {
+          /* SSL_CTX_add_client_CA() seems to work with either sk_* function,
+           * presumably because it duplicates what we pass to it.
+           */
+          if(!SSL_CTX_add_client_CA(ctx, x)) {
             failf(data, "cannot add certificate to client CA list");
             goto fail;
           }