]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- unbound-anchors checks the emailAddress of the signer of the
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 17 Jan 2013 11:17:04 +0000 (11:17 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 17 Jan 2013 11:17:04 +0000 (11:17 +0000)
  root.xml file, default is dnssec@iana.org.  It also checks that
  the signer has the correct key usage for a digital signature.

git-svn-id: file:///svn/unbound/trunk@2807 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
doc/unbound-anchor.8.in
smallapp/unbound-anchor.c

index 36ae697b273961aa639639c4acbfe4785f55908a..01a2802a60161f6a43cc46fdf119d0a41c1daabe 100644 (file)
@@ -1,3 +1,8 @@
+17 January 2013: Wouter
+       - unbound-anchors checks the emailAddress of the signer of the
+         root.xml file, default is dnssec@iana.org.  It also checks that
+         the signer has the correct key usage for a digital signature.
+
 3 January 2013: Wouter
        - Test that unbound-control checks client credentials.
        - Test that unbound can handle a CNAME at an intermediate node in
index 0848fac029a9a62ca42185d5d03a79335b31f0a2..64a4ef3ba154b20ddfeeb753fdc2a602914e402c 100644 (file)
@@ -78,9 +78,9 @@ The default is /root\-anchors/root\-anchors.p7s.  This file has to be a PKCS7
 signature over the xml file, using the pem file (\-c) as trust anchor.
 .TP
 .B \-n \fIname
-The commonName for the Subject of the signer's certificate from the p7s
+The emailAddress for the Subject of the signer's certificate from the p7s
 signature file.  Only signatures from this name are allowed.  default is
-dnssec@iana.org.  If you pass "" then the commonName is not checked.
+dnssec@iana.org.  If you pass "" then the emailAddress is not checked.
 .TP
 .B \-4
 Use IPv4 for domain resolution and contacting the server on https.  Default is
index 88e3c015d555d235f48c2c5ae50ae744599bdfd8..37521729baceaf713628ee8d68b2337abdfbfbef 100644 (file)
 #include <openssl/rand.h>
 #endif
 #include <openssl/x509.h>
+#include <openssl/x509v3.h>
 #include <openssl/pem.h>
 
 /** name of server in URL to fetch HTTPS from */
@@ -186,7 +187,7 @@ usage()
        printf("-u name         server in https url, default %s\n", URLNAME);
        printf("-x path         pathname to xml in url, default %s\n", XMLNAME);
        printf("-s path         pathname to p7s in url, default %s\n", P7SNAME);
-       printf("-n name         signer's subject commonName, default %s\n", P7SIGNER);
+       printf("-n name         signer's subject emailAddress, default %s\n", P7SIGNER);
        printf("-4              work using IPv4 only\n");
        printf("-6              work using IPv6 only\n");
        printf("-f resolv.conf  use given resolv.conf to resolve -u name\n");
@@ -1626,6 +1627,23 @@ xml_parse(BIO* xml, time_t now)
        }
 }
 
+/* get key usage out of its extension, returns 0 if no key_usage extension */
+static unsigned long
+get_usage_of_ex(X509* cert)
+{
+       unsigned long val = 0;
+       ASN1_BIT_STRING* s;
+       if((s=X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL))) {
+               if(s->length > 0) {
+                       val = s->data[0];
+                       if(s->length > 1)
+                               val |= s->data[1] << 8;
+               }
+               ASN1_BIT_STRING_free(s);
+       }
+       return val;
+}
+
 /** get valid signers from the list of signers in the signature */
 static STACK_OF(X509)*
 get_valid_signers(PKCS7* p7, char* p7signer)
@@ -1633,6 +1651,7 @@ get_valid_signers(PKCS7* p7, char* p7signer)
        int i;
        STACK_OF(X509)* validsigners = sk_X509_new_null();
        STACK_OF(X509)* signers = PKCS7_get0_signers(p7, NULL, 0);
+       unsigned long usage = 0;
        if(!validsigners) {
                if(verb) printf("out of memory\n");
                sk_X509_free(signers);
@@ -1643,12 +1662,6 @@ get_valid_signers(PKCS7* p7, char* p7signer)
                sk_X509_free(validsigners);
                return NULL;
        }
-       if(!p7signer || strcmp(p7signer, "")==0) {
-               /* there is no name to check, return all records */
-               if(verb) printf("did not check commonName of signer\n");
-               sk_X509_free(validsigners);
-               return signers;
-       }
        for(i=0; i<sk_X509_num(signers); i++) {
                X509_NAME* nm = X509_get_subject_name(
                        sk_X509_value(signers, i));
@@ -1657,7 +1670,7 @@ get_valid_signers(PKCS7* p7, char* p7signer)
                        if(verb) printf("signer %d: cert has no subject name\n", i);
                        continue;
                }
-               if(verb) {
+               if(verb && nm) {
                        char* nmline = X509_NAME_oneline(nm, buf,
                                (int)sizeof(buf));
                        printf("signer %d: Subject: %s\n", i,
@@ -1669,14 +1682,41 @@ get_valid_signers(PKCS7* p7, char* p7signer)
                                NID_pkcs9_emailAddress, buf, (int)sizeof(buf)))
                                printf("emailAddress: %s\n", buf);
                }
-               if(!X509_NAME_get_text_by_NID(nm, NID_commonName,
-                       buf, (int)sizeof(buf))) {
-                       if(verb) printf("removed cert with no name\n");
-                       continue; /* no name, no use */
+               if(verb) {
+                       int ku_loc = X509_get_ext_by_NID(
+                               sk_X509_value(signers, i), NID_key_usage, -1);
+                       if(verb >= 3 && ku_loc >= 0) {
+                               X509_EXTENSION *ex = X509_get_ext(
+                                       sk_X509_value(signers, i), ku_loc);
+                               if(ex) {
+                                       printf("keyUsage: ");
+                                       X509V3_EXT_print_fp(stdout, ex, 0, 0);
+                                       printf("\n");
+                               }
+                       }
+               }
+               if(!p7signer || strcmp(p7signer, "")==0) {
+                       /* there is no name to check, return all records */
+                       if(verb) printf("did not check commonName of signer\n");
+               } else {
+                       if(!X509_NAME_get_text_by_NID(nm,
+                               NID_pkcs9_emailAddress,
+                               buf, (int)sizeof(buf))) {
+                               if(verb) printf("removed cert with no name\n");
+                               continue; /* no name, no use */
+                       }
+                       if(strcmp(buf, p7signer) != 0) {
+                               if(verb) printf("removed cert with wrong name\n");
+                               continue; /* wrong name, skip it */
+                       }
                }
-               if(strcmp(buf, p7signer) != 0) {
-                       if(verb) printf("removed cert with wrong name\n");
-                       continue; /* wrong name, skip it */
+
+               /* check that the key usage allows digital signatures
+                * (the p7s) */
+               usage = get_usage_of_ex(sk_X509_value(signers, i));
+               if(!(usage & KU_DIGITAL_SIGNATURE)) {
+                       if(verb) printf("removed cert with no key usage Digital Signature allowed\n");
+                       continue;
                }
 
                /* we like this cert, add it to our list of valid