summaryrefslogtreecommitdiffstats
path: root/contrib/unbound/smallapp
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2013-04-05 09:51:31 +0000
committerdes <des@FreeBSD.org>2013-04-05 09:51:31 +0000
commit977c6e8c4173172b0a2399d8f55f18a3b815a947 (patch)
treea17550a8c82df6e46c2bb87a9d9faf38d76f9933 /contrib/unbound/smallapp
parentb0cbd784b12baa8ea27f7196e9a297847e8284c1 (diff)
parent35be22788f689639c1a53f650cd8a1fad60a1466 (diff)
downloadFreeBSD-src-977c6e8c4173172b0a2399d8f55f18a3b815a947.zip
FreeBSD-src-977c6e8c4173172b0a2399d8f55f18a3b815a947.tar.gz
Upgrade to 1.4.20.
Diffstat (limited to 'contrib/unbound/smallapp')
-rw-r--r--contrib/unbound/smallapp/unbound-anchor.c165
-rw-r--r--contrib/unbound/smallapp/unbound-control.c26
-rw-r--r--contrib/unbound/smallapp/unbound-host.c10
3 files changed, 181 insertions, 20 deletions
diff --git a/contrib/unbound/smallapp/unbound-anchor.c b/contrib/unbound/smallapp/unbound-anchor.c
index e14ca73..ef0031c 100644
--- a/contrib/unbound/smallapp/unbound-anchor.c
+++ b/contrib/unbound/smallapp/unbound-anchor.c
@@ -134,6 +134,7 @@
#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 */
@@ -142,6 +143,8 @@
#define XMLNAME "root-anchors/root-anchors.xml"
/** path on HTTPS server to p7s file */
#define P7SNAME "root-anchors/root-anchors.p7s"
+/** name of the signer of the certificate */
+#define P7SIGNER "dnssec@iana.org"
/** port number for https access */
#define HTTPS_PORT 443
@@ -184,6 +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 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");
@@ -540,6 +544,11 @@ resolve_host_ip(struct ub_ctx* ctx, char* host, int port, int tp, int cl,
ub_ctx_delete(ctx);
exit(0);
}
+ if(!res->havedata || res->rcode || !res->data) {
+ if(verb) printf("resolve %s %s: no result\n", host,
+ (tp==LDNS_RR_TYPE_A)?"A":"AAAA");
+ return;
+ }
for(i = 0; res->data[i]; i++) {
struct ip_list* ip = RR_to_ip(tp, res->data[i], res->len[i],
port);
@@ -1498,6 +1507,20 @@ xml_endelem(void *userData, const XML_Char *name)
}
}
+/* Stop the parser when an entity declaration is encountered. For safety. */
+static void
+xml_entitydeclhandler(void *userData,
+ const XML_Char *ATTR_UNUSED(entityName),
+ int ATTR_UNUSED(is_parameter_entity),
+ const XML_Char *ATTR_UNUSED(value), int ATTR_UNUSED(value_length),
+ const XML_Char *ATTR_UNUSED(base),
+ const XML_Char *ATTR_UNUSED(systemId),
+ const XML_Char *ATTR_UNUSED(publicId),
+ const XML_Char *ATTR_UNUSED(notationName))
+{
+ (void)XML_StopParser((XML_Parser)userData, XML_FALSE);
+}
+
/**
* XML parser setup of the callbacks for the tags
*/
@@ -1526,6 +1549,7 @@ xml_parse_setup(XML_Parser parser, struct xml_data* data, time_t now)
if(verb) printf("out of memory\n");
exit(0);
}
+ XML_SetEntityDeclHandler(parser, xml_entitydeclhandler);
XML_SetElementHandler(parser, xml_startelem, xml_endelem);
XML_SetCharacterDataHandler(parser, xml_charhandle);
}
@@ -1603,12 +1627,113 @@ 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)
+{
+ 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);
+ return NULL;
+ }
+ if(!signers) {
+ if(verb) printf("no signers in pkcs7 signature\n");
+ sk_X509_free(validsigners);
+ return NULL;
+ }
+ for(i=0; i<sk_X509_num(signers); i++) {
+ X509_NAME* nm = X509_get_subject_name(
+ sk_X509_value(signers, i));
+ char buf[1024];
+ if(!nm) {
+ if(verb) printf("signer %d: cert has no subject name\n", i);
+ continue;
+ }
+ if(verb && nm) {
+ char* nmline = X509_NAME_oneline(nm, buf,
+ (int)sizeof(buf));
+ printf("signer %d: Subject: %s\n", i,
+ nmline?nmline:"no subject");
+ if(verb >= 3 && X509_NAME_get_text_by_NID(nm,
+ NID_commonName, buf, (int)sizeof(buf)))
+ printf("commonName: %s\n", buf);
+ if(verb >= 3 && X509_NAME_get_text_by_NID(nm,
+ NID_pkcs9_emailAddress, buf, (int)sizeof(buf)))
+ printf("emailAddress: %s\n", buf);
+ }
+ 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 */
+ }
+ }
+
+ /* 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
+ * signers certificates */
+ sk_X509_push(validsigners, sk_X509_value(signers, i));
+ }
+ sk_X509_free(signers);
+ return validsigners;
+}
+
/** verify a PKCS7 signature, false on failure */
static int
-verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust)
+verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust, char* p7signer)
{
PKCS7* p7;
X509_STORE *store = X509_STORE_new();
+ STACK_OF(X509)* validsigners;
int secure = 0;
int i;
#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
@@ -1630,6 +1755,9 @@ verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust)
#endif
return 0;
}
+#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
+ X509_VERIFY_PARAM_free(param);
+#endif
(void)BIO_reset(p7s);
(void)BIO_reset(data);
@@ -1654,7 +1782,15 @@ verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust)
}
if(verb >= 2) printf("setup the X509_STORE\n");
- if(PKCS7_verify(p7, NULL, store, data, NULL, 0) == 1) {
+ /* check what is in the Subject name of the certificates,
+ * and build a stack that contains only the right certificates */
+ validsigners = get_valid_signers(p7, p7signer);
+ if(!validsigners) {
+ X509_STORE_free(store);
+ PKCS7_free(p7);
+ return 0;
+ }
+ if(PKCS7_verify(p7, validsigners, store, data, NULL, PKCS7_NOINTERN) == 1) {
secure = 1;
if(verb) printf("the PKCS7 signature verified\n");
} else {
@@ -1663,6 +1799,7 @@ verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust)
}
}
+ sk_X509_free(validsigners);
X509_STORE_free(store);
PKCS7_free(p7);
return secure;
@@ -1723,12 +1860,12 @@ write_root_anchor(char* root_anchor_file, BIO* ds)
/** Perform the verification and update of the trustanchor file */
static void
verify_and_update_anchor(char* root_anchor_file, BIO* xml, BIO* p7s,
- STACK_OF(X509)* cert)
+ STACK_OF(X509)* cert, char* p7signer)
{
BIO* ds;
/* verify xml file */
- if(!verify_p7sig(xml, p7s, cert)) {
+ if(!verify_p7sig(xml, p7s, cert, p7signer)) {
printf("the PKCS7 signature failed\n");
exit(0);
}
@@ -1752,7 +1889,7 @@ static void do_wsa_cleanup(void) { WSACleanup(); }
/** perform actual certupdate work */
static int
do_certupdate(char* root_anchor_file, char* root_cert_file,
- char* urlname, char* xmlname, char* p7sname,
+ char* urlname, char* xmlname, char* p7sname, char* p7signer,
char* res_conf, char* root_hints, char* debugconf,
int ip4only, int ip6only, int port, struct ub_result* dnskey)
{
@@ -1785,7 +1922,7 @@ do_certupdate(char* root_anchor_file, char* root_cert_file,
p7s = https(ip_list, p7sname, urlname);
/* verify and update the root anchor */
- verify_and_update_anchor(root_anchor_file, xml, p7s, cert);
+ verify_and_update_anchor(root_anchor_file, xml, p7s, cert, p7signer);
if(verb) printf("success: the anchor has been updated "
"using the cert\n");
@@ -2035,7 +2172,7 @@ probe_date_allows_certupdate(char* root_anchor_file)
/** perform the unbound-anchor work */
static int
do_root_update_work(char* root_anchor_file, char* root_cert_file,
- char* urlname, char* xmlname, char* p7sname,
+ char* urlname, char* xmlname, char* p7sname, char* p7signer,
char* res_conf, char* root_hints, char* debugconf,
int ip4only, int ip6only, int force, int port)
{
@@ -2068,8 +2205,8 @@ do_root_update_work(char* root_anchor_file, char* root_cert_file,
if((dnskey->rcode == 0 &&
probe_date_allows_certupdate(root_anchor_file)) || force) {
if(do_certupdate(root_anchor_file, root_cert_file, urlname,
- xmlname, p7sname, res_conf, root_hints, debugconf,
- ip4only, ip6only, port, dnskey))
+ xmlname, p7sname, p7signer, res_conf, root_hints,
+ debugconf, ip4only, ip6only, port, dnskey))
return 1;
return used_builtin;
}
@@ -2092,12 +2229,13 @@ int main(int argc, char* argv[])
char* urlname = URLNAME;
char* xmlname = XMLNAME;
char* p7sname = P7SNAME;
+ char* p7signer = P7SIGNER;
char* res_conf = NULL;
char* root_hints = NULL;
char* debugconf = NULL;
int dolist=0, ip4only=0, ip6only=0, force=0, port = HTTPS_PORT;
/* parse the options */
- while( (c=getopt(argc, argv, "46C:FP:a:c:f:hlr:s:u:vx:")) != -1) {
+ while( (c=getopt(argc, argv, "46C:FP:a:c:f:hln:r:s:u:vx:")) != -1) {
switch(c) {
case 'l':
dolist = 1;
@@ -2123,6 +2261,9 @@ int main(int argc, char* argv[])
case 's':
p7sname = optarg;
break;
+ case 'n':
+ p7signer = optarg;
+ break;
case 'f':
res_conf = optarg;
break;
@@ -2160,6 +2301,6 @@ int main(int argc, char* argv[])
if(dolist) do_list_builtin();
return do_root_update_work(root_anchor_file, root_cert_file, urlname,
- xmlname, p7sname, res_conf, root_hints, debugconf, ip4only,
- ip6only, force, port);
+ xmlname, p7sname, p7signer, res_conf, root_hints, debugconf,
+ ip4only, ip6only, force, port);
}
diff --git a/contrib/unbound/smallapp/unbound-control.c b/contrib/unbound/smallapp/unbound-control.c
index 58be7b7..cc48866 100644
--- a/contrib/unbound/smallapp/unbound-control.c
+++ b/contrib/unbound/smallapp/unbound-control.c
@@ -68,6 +68,7 @@ usage()
printf("Options:\n");
printf(" -c file config file, default is %s\n", CONFIGFILE);
printf(" -s ip[@port] server address, if omitted config is used.\n");
+ printf(" -q quiet (don't print anything if it works ok).\n");
printf(" -h show this usage help.\n");
printf("Commands:\n");
printf(" start start server; runs unbound(8)\n");
@@ -93,6 +94,7 @@ usage()
printf(" flush_type <name> <type> flush name, type from cache\n");
printf(" flush_zone <name> flush everything at or under name\n");
printf(" from rr and dnssec caches\n");
+ printf(" flush_bogus flush all bogus data\n");
printf(" flush_stats flush statistics, make zero\n");
printf(" flush_requestlist drop queries that are worked on\n");
printf(" dump_requestlist show what is worked on\n");
@@ -262,7 +264,7 @@ send_file(SSL* ssl, FILE* in, char* buf, size_t sz)
/** send command and display result */
static int
-go_cmd(SSL* ssl, int argc, char* argv[])
+go_cmd(SSL* ssl, int quiet, int argc, char* argv[])
{
char pre[10];
const char* space=" ";
@@ -296,9 +298,12 @@ go_cmd(SSL* ssl, int argc, char* argv[])
ssl_err("could not SSL_read");
}
buf[r] = 0;
- printf("%s", buf);
- if(first_line && strncmp(buf, "error", 5) == 0)
+ if(first_line && strncmp(buf, "error", 5) == 0) {
+ printf("%s", buf);
was_error = 1;
+ } else if (!quiet)
+ printf("%s", buf);
+
first_line = 0;
}
return was_error;
@@ -306,7 +311,7 @@ go_cmd(SSL* ssl, int argc, char* argv[])
/** go ahead and read config, contact server and perform command and display */
static int
-go(const char* cfgfile, char* svr, int argc, char* argv[])
+go(const char* cfgfile, char* svr, int quiet, int argc, char* argv[])
{
struct config_file* cfg;
int fd, ret;
@@ -327,7 +332,7 @@ go(const char* cfgfile, char* svr, int argc, char* argv[])
ssl = setup_ssl(ctx, fd);
/* send command */
- ret = go_cmd(ssl, argc, argv);
+ ret = go_cmd(ssl, quiet, argc, argv);
SSL_free(ssl);
#ifndef USE_WINSOCK
@@ -349,6 +354,7 @@ extern char* optarg;
int main(int argc, char* argv[])
{
int c, ret;
+ int quiet = 0;
const char* cfgfile = CONFIGFILE;
char* svr = NULL;
#ifdef USE_WINSOCK
@@ -379,7 +385,8 @@ int main(int argc, char* argv[])
if(!RAND_status()) {
/* try to seed it */
unsigned char buf[256];
- unsigned int v, seed=(unsigned)time(NULL) ^ (unsigned)getpid();
+ unsigned int seed=(unsigned)time(NULL) ^ (unsigned)getpid();
+ unsigned int v = seed;
size_t i;
for(i=0; i<256/sizeof(v); i++) {
memmove(buf+i*sizeof(v), &v, sizeof(v));
@@ -390,7 +397,7 @@ int main(int argc, char* argv[])
}
/* parse the options */
- while( (c=getopt(argc, argv, "c:s:h")) != -1) {
+ while( (c=getopt(argc, argv, "c:s:qh")) != -1) {
switch(c) {
case 'c':
cfgfile = optarg;
@@ -398,6 +405,9 @@ int main(int argc, char* argv[])
case 's':
svr = optarg;
break;
+ case 'q':
+ quiet = 1;
+ break;
case '?':
case 'h':
default:
@@ -416,7 +426,7 @@ int main(int argc, char* argv[])
}
}
- ret = go(cfgfile, svr, argc, argv);
+ ret = go(cfgfile, svr, quiet, argc, argv);
#ifdef USE_WINSOCK
WSACleanup();
diff --git a/contrib/unbound/smallapp/unbound-host.c b/contrib/unbound/smallapp/unbound-host.c
index 0953967..715aa4a 100644
--- a/contrib/unbound/smallapp/unbound-host.c
+++ b/contrib/unbound/smallapp/unbound-host.c
@@ -61,6 +61,10 @@
#endif
#include "libunbound/unbound.h"
#include <ldns/ldns.h>
+#ifdef HAVE_NSS
+/* nss3 */
+#include "nss.h"
+#endif
/** verbosity for unbound-host app */
static int verb = 0;
@@ -509,6 +513,12 @@ int main(int argc, char* argv[])
if(argc != 1)
usage();
+#ifdef HAVE_NSS
+ if(NSS_NoDB_Init(".") != SECSuccess) {
+ fprintf(stderr, "could not init NSS\n");
+ return 1;
+ }
+#endif
lookup(ctx, argv[0], qtype, qclass);
return 0;
}
OpenPOWER on IntegriCloud