From: Wouter Wijngaards Date: Thu, 17 Jan 2013 11:17:04 +0000 (+0000) Subject: - unbound-anchors checks the emailAddress of the signer of the X-Git-Tag: release-1.4.20rc1~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=98b3b1a36dffe120f7e399b9f3a78269d38cee4c;p=thirdparty%2Funbound.git - 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. git-svn-id: file:///svn/unbound/trunk@2807 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 36ae697b2..01a2802a6 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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 diff --git a/doc/unbound-anchor.8.in b/doc/unbound-anchor.8.in index 0848fac02..64a4ef3ba 100644 --- a/doc/unbound-anchor.8.in +++ b/doc/unbound-anchor.8.in @@ -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 diff --git a/smallapp/unbound-anchor.c b/smallapp/unbound-anchor.c index 88e3c015d..37521729b 100644 --- a/smallapp/unbound-anchor.c +++ b/smallapp/unbound-anchor.c @@ -134,6 +134,7 @@ #include #endif #include +#include #include /** 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= 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