aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/smallapp
diff options
context:
space:
mode:
authoranonimal <anonimal@i2pmail.org>2017-06-28 21:07:24 +0000
committeranonimal <anonimal@i2pmail.org>2018-03-18 15:52:19 +0000
commit84c5a9ba481d7a33cc0fd0ca43867b61d127d907 (patch)
treef05d3d3f107da02005b4a61f0e5074c113a7165c /external/unbound/smallapp
parentMerge pull request #3416 (diff)
downloadmonero-84c5a9ba481d7a33cc0fd0ca43867b61d127d907.tar.xz
Unbound: remove unbound from in-tree source
We'll instead use a git submodule to pull from our unbound repo.
Diffstat (limited to 'external/unbound/smallapp')
-rw-r--r--external/unbound/smallapp/unbound-anchor.c2346
-rw-r--r--external/unbound/smallapp/unbound-checkconf.c619
-rw-r--r--external/unbound/smallapp/unbound-control-setup.sh.in160
-rw-r--r--external/unbound/smallapp/unbound-control.c791
-rw-r--r--external/unbound/smallapp/unbound-host.c497
-rw-r--r--external/unbound/smallapp/worker_cb.c250
6 files changed, 0 insertions, 4663 deletions
diff --git a/external/unbound/smallapp/unbound-anchor.c b/external/unbound/smallapp/unbound-anchor.c
deleted file mode 100644
index 2828088d9..000000000
--- a/external/unbound/smallapp/unbound-anchor.c
+++ /dev/null
@@ -1,2346 +0,0 @@
-/*
- * unbound-anchor.c - update the root anchor if necessary.
- *
- * Copyright (c) 2010, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file checks to see that the current 5011 keys work to prime the
- * current root anchor. If not a certificate is used to update the anchor,
- * with RFC7958 https xml fetch.
- *
- * This is a concept solution for distribution of the DNSSEC root
- * trust anchor. It is a small tool, called "unbound-anchor", that
- * runs before the main validator starts. I.e. in the init script:
- * unbound-anchor; unbound. Thus it is meant to run at system boot time.
- *
- * Management-Abstract:
- * * first run: fill root.key file with hardcoded DS record.
- * * mostly: use RFC5011 tracking, quick . DNSKEY UDP query.
- * * failover: use RFC7958 builtin certificate, do https and update.
- * Special considerations:
- * * 30-days RFC5011 timer saves a lot of https traffic.
- * * DNSKEY probe must be NOERROR, saves a lot of https traffic.
- * * fail if clock before sign date of the root, if cert expired.
- * * if the root goes back to unsigned, deals with it.
- *
- * It has hardcoded the root DS anchors and the ICANN CA root certificate.
- * It allows with options to override those. It also takes root-hints (it
- * has to do a DNS resolve), and also has hardcoded defaults for those.
- *
- * Once it starts, just before the validator starts, it quickly checks if
- * the root anchor file needs to be updated. First it tries to use
- * RFC5011-tracking of the root key. If that fails (and for 30-days since
- * last successful probe), then it attempts to update using the
- * certificate. So most of the time, the RFC5011 tracking will work fine,
- * and within a couple milliseconds, the main daemon can start. It will
- * have only probed the . DNSKEY, not done expensive https transfers on the
- * root infrastructure.
- *
- * If there is no root key in the root.key file, it bootstraps the
- * RFC5011-tracking with its builtin DS anchors; if that fails it
- * bootstraps the RFC5011-tracking using the certificate. (again to avoid
- * https, and it is also faster).
- *
- * It uses the XML file by converting it to DS records and writing that to the
- * key file. Unbound can detect that the 'special comments' are gone, and
- * the file contains a list of normal DNSKEY/DS records, and uses that to
- * bootstrap 5011 (the KSK is made VALID).
- *
- * The certificate RFC7958 update is done by fetching root-anchors.xml and
- * root-anchors.p7s via SSL. The HTTPS certificate can be logged but is
- * not validated (https for channel security; the security comes from the
- * certificate). The 'data.iana.org' domain name A and AAAA are resolved
- * without DNSSEC. It tries a random IP until the transfer succeeds. It
- * then checks the p7s signature.
- *
- * On any failure, it leaves the root key file untouched. The main
- * validator has to cope with it, it cannot fix things (So a failure does
- * not go 'without DNSSEC', no downgrade). If it used its builtin stuff or
- * did the https, it exits with an exit code, so that this can trigger the
- * init script to log the event and potentially alert the operator that can
- * do a manual check.
- *
- * The date is also checked. Before 2010-07-15 is a failure (root not
- * signed yet; avoids attacks on system clock). The
- * last-successful-RFC5011-probe (if available) has to be more than 30 days
- * in the past (otherwise, RFC5011 should have worked). This keeps
- * unnecessary https traffic down. If the main certificate is expired, it
- * fails.
- *
- * The dates on the keys in the xml are checked (uses the libexpat xml
- * parser), only the valid ones are used to re-enstate RFC5011 tracking.
- * If 0 keys are valid, the zone has gone to insecure (a special marker is
- * written in the keyfile that tells the main validator daemon the zone is
- * insecure).
- *
- * Only the root ICANN CA is shipped, not the intermediate ones. The
- * intermediate CAs are included in the p7s file that was downloaded. (the
- * root cert is valid to 2028 and the intermediate to 2014, today).
- *
- * Obviously, the tool also has options so the operator can provide a new
- * keyfile, a new certificate and new URLs, and fresh root hints. By
- * default it logs nothing on failure and success; it 'just works'.
- *
- */
-
-#include "config.h"
-#include "libunbound/unbound.h"
-#include "sldns/rrdef.h"
-#include "sldns/parseutil.h"
-#include <expat.h>
-#ifndef HAVE_EXPAT_H
-#error "need libexpat to parse root-anchors.xml file."
-#endif
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#ifdef HAVE_OPENSSL_SSL_H
-#include <openssl/ssl.h>
-#endif
-#ifdef HAVE_OPENSSL_ERR_H
-#include <openssl/err.h>
-#endif
-#ifdef HAVE_OPENSSL_RAND_H
-#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 */
-#define URLNAME "data.iana.org"
-/** path on HTTPS server to xml file */
-#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
-
-#ifdef USE_WINSOCK
-/* sneakily reuse the the wsa_strerror function, on windows */
-char* wsa_strerror(int err);
-#endif
-
-/** verbosity for this application */
-static int verb = 0;
-
-/** list of IP addresses */
-struct ip_list {
- /** next in list */
- struct ip_list* next;
- /** length of addr */
- socklen_t len;
- /** address ready to connect to */
- struct sockaddr_storage addr;
- /** has the address been used */
- int used;
-};
-
-/** Give unbound-anchor usage, and exit (1). */
-static void
-usage(void)
-{
- printf("Usage: unbound-anchor [opts]\n");
- printf(" Setup or update root anchor. "
- "Most options have defaults.\n");
- printf(" Run this program before you start the validator.\n");
- printf("\n");
- printf(" The anchor and cert have default builtin content\n");
- printf(" if the file does not exist or is empty.\n");
- printf("\n");
- printf("-a file root key file, default %s\n", ROOT_ANCHOR_FILE);
- printf(" The key is input and output for this tool.\n");
- printf("-c file cert file, default %s\n", ROOT_CERT_FILE);
- printf("-l list builtin key and cert on stdout\n");
- 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");
- printf("-r root.hints use given root.hints to resolve -u name\n"
- " builtin root hints are used by default\n");
- printf("-v more verbose\n");
- printf("-C conf debug, read config\n");
- printf("-P port use port for https connect, default 443\n");
- printf("-F debug, force update with cert\n");
- printf("-h show this usage help\n");
- printf("Version %s\n", PACKAGE_VERSION);
- printf("BSD licensed, see LICENSE in source package for details.\n");
- printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
- exit(1);
-}
-
-/** return the built in root update certificate */
-static const char*
-get_builtin_cert(void)
-{
- return
-/* The ICANN CA fetched at 24 Sep 2010. Valid to 2028 */
-"-----BEGIN CERTIFICATE-----\n"
-"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n"
-"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n"
-"BAMTDUlDQU5OIFJvb3QgQ0ExCzAJBgNVBAYTAlVTMB4XDTA5MTIyMzA0MTkxMloX\n"
-"DTI5MTIxODA0MTkxMlowXTEOMAwGA1UEChMFSUNBTk4xJjAkBgNVBAsTHUlDQU5O\n"
-"IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1JQ0FOTiBSb290IENB\n"
-"MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDb\n"
-"cLhPNNqc1NB+u+oVvOnJESofYS9qub0/PXagmgr37pNublVThIzyLPGCJ8gPms9S\n"
-"G1TaKNIsMI7d+5IgMy3WyPEOECGIcfqEIktdR1YWfJufXcMReZwU4v/AdKzdOdfg\n"
-"ONiwc6r70duEr1IiqPbVm5T05l1e6D+HkAvHGnf1LtOPGs4CHQdpIUcy2kauAEy2\n"
-"paKcOcHASvbTHK7TbbvHGPB+7faAztABLoneErruEcumetcNfPMIjXKdv1V1E3C7\n"
-"MSJKy+jAqqQJqjZoQGB0necZgUMiUv7JK1IPQRM2CXJllcyJrm9WFxY0c1KjBO29\n"
-"iIKK69fcglKcBuFShUECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n"
-"Af8EBAMCAf4wHQYDVR0OBBYEFLpS6UmDJIZSL8eZzfyNa2kITcBQMA0GCSqGSIb3\n"
-"DQEBCwUAA4IBAQAP8emCogqHny2UYFqywEuhLys7R9UKmYY4suzGO4nkbgfPFMfH\n"
-"6M+Zj6owwxlwueZt1j/IaCayoKU3QsrYYoDRolpILh+FPwx7wseUEV8ZKpWsoDoD\n"
-"2JFbLg2cfB8u/OlE4RYmcxxFSmXBg0yQ8/IoQt/bxOcEEhhiQ168H2yE5rxJMt9h\n"
-"15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF\n"
-"0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n"
-"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n"
-"-----END CERTIFICATE-----\n"
- ;
-}
-
-/** return the built in root DS trust anchor */
-static const char*
-get_builtin_ds(void)
-{
- return
-/* anchor 19036 is from 2010 */
-/* anchor 20326 is from 2017 */
-". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n"
-". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D\n";
-}
-
-/** print hex data */
-static void
-print_data(const char* msg, const char* data, int len)
-{
- int i;
- printf("%s: ", msg);
- for(i=0; i<len; i++) {
- printf(" %2.2x", (unsigned char)data[i]);
- }
- printf("\n");
-}
-
-/** print ub context creation error and exit */
-static void
-ub_ctx_error_exit(struct ub_ctx* ctx, const char* str, const char* str2)
-{
- ub_ctx_delete(ctx);
- if(str && str2 && verb) printf("%s: %s\n", str, str2);
- if(verb) printf("error: could not create unbound resolver context\n");
- exit(0);
-}
-
-/**
- * Create a new unbound context with the commandline settings applied
- */
-static struct ub_ctx*
-create_unbound_context(const char* res_conf, const char* root_hints,
- const char* debugconf, int ip4only, int ip6only)
-{
- int r;
- struct ub_ctx* ctx = ub_ctx_create();
- if(!ctx) {
- if(verb) printf("out of memory\n");
- exit(0);
- }
- /* do not waste time and network traffic to fetch extra nameservers */
- r = ub_ctx_set_option(ctx, "target-fetch-policy:", "0 0 0 0 0");
- if(r && verb) printf("ctx targetfetchpolicy: %s\n", ub_strerror(r));
- /* read config file first, so its settings can be overridden */
- if(debugconf) {
- r = ub_ctx_config(ctx, debugconf);
- if(r) ub_ctx_error_exit(ctx, debugconf, ub_strerror(r));
- }
- if(res_conf) {
- r = ub_ctx_resolvconf(ctx, res_conf);
- if(r) ub_ctx_error_exit(ctx, res_conf, ub_strerror(r));
- }
- if(root_hints) {
- r = ub_ctx_set_option(ctx, "root-hints:", root_hints);
- if(r) ub_ctx_error_exit(ctx, root_hints, ub_strerror(r));
- }
- if(ip4only) {
- r = ub_ctx_set_option(ctx, "do-ip6:", "no");
- if(r) ub_ctx_error_exit(ctx, "ip4only", ub_strerror(r));
- }
- if(ip6only) {
- r = ub_ctx_set_option(ctx, "do-ip4:", "no");
- if(r) ub_ctx_error_exit(ctx, "ip6only", ub_strerror(r));
- }
- return ctx;
-}
-
-/** printout certificate in detail */
-static void
-verb_cert(const char* msg, X509* x)
-{
- if(verb == 0 || verb == 1) return;
- if(verb == 2) {
- if(msg) printf("%s\n", msg);
- X509_print_ex_fp(stdout, x, 0, (unsigned long)-1
- ^(X509_FLAG_NO_SUBJECT
- |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY));
- return;
- }
- if(msg) printf("%s\n", msg);
- X509_print_fp(stdout, x);
-}
-
-/** printout certificates in detail */
-static void
-verb_certs(const char* msg, STACK_OF(X509)* sk)
-{
- int i, num = sk_X509_num(sk);
- if(verb == 0 || verb == 1) return;
- for(i=0; i<num; i++) {
- printf("%s (%d/%d)\n", msg, i, num);
- verb_cert(NULL, sk_X509_value(sk, i));
- }
-}
-
-/** read certificates from a PEM bio */
-static STACK_OF(X509)*
-read_cert_bio(BIO* bio)
-{
- STACK_OF(X509) *sk = sk_X509_new_null();
- if(!sk) {
- if(verb) printf("out of memory\n");
- exit(0);
- }
- while(!BIO_eof(bio)) {
- X509* x = PEM_read_bio_X509(bio, NULL, 0, NULL);
- if(x == NULL) {
- if(verb) {
- printf("failed to read X509\n");
- ERR_print_errors_fp(stdout);
- }
- continue;
- }
- if(!sk_X509_push(sk, x)) {
- if(verb) printf("out of memory\n");
- exit(0);
- }
- }
- return sk;
-}
-
-/* read the certificate file */
-static STACK_OF(X509)*
-read_cert_file(const char* file)
-{
- STACK_OF(X509)* sk;
- FILE* in;
- int content = 0;
- char buf[128];
- if(file == NULL || strcmp(file, "") == 0) {
- return NULL;
- }
- sk = sk_X509_new_null();
- if(!sk) {
- if(verb) printf("out of memory\n");
- exit(0);
- }
- in = fopen(file, "r");
- if(!in) {
- if(verb) printf("%s: %s\n", file, strerror(errno));
-#ifndef S_SPLINT_S
- sk_X509_pop_free(sk, X509_free);
-#endif
- return NULL;
- }
- while(!feof(in)) {
- X509* x = PEM_read_X509(in, NULL, 0, NULL);
- if(x == NULL) {
- if(verb) {
- printf("failed to read X509 file\n");
- ERR_print_errors_fp(stdout);
- }
- continue;
- }
- if(!sk_X509_push(sk, x)) {
- if(verb) printf("out of memory\n");
- fclose(in);
- exit(0);
- }
- content = 1;
- /* read away newline after --END CERT-- */
- if(!fgets(buf, (int)sizeof(buf), in))
- break;
- }
- fclose(in);
- if(!content) {
- if(verb) printf("%s is empty\n", file);
-#ifndef S_SPLINT_S
- sk_X509_pop_free(sk, X509_free);
-#endif
- return NULL;
- }
- return sk;
-}
-
-/** read certificates from the builtin certificate */
-static STACK_OF(X509)*
-read_builtin_cert(void)
-{
- const char* builtin_cert = get_builtin_cert();
- STACK_OF(X509)* sk;
- BIO *bio;
- char* d = strdup(builtin_cert); /* to avoid const warnings in the
- changed prototype of BIO_new_mem_buf */
- if(!d) {
- if(verb) printf("out of memory\n");
- exit(0);
- }
- bio = BIO_new_mem_buf(d, (int)strlen(d));
- if(!bio) {
- if(verb) printf("out of memory\n");
- exit(0);
- }
- sk = read_cert_bio(bio);
- if(!sk) {
- if(verb) printf("internal error, out of memory\n");
- exit(0);
- }
- BIO_free(bio);
- free(d);
- return sk;
-}
-
-/** read update cert file or use builtin */
-static STACK_OF(X509)*
-read_cert_or_builtin(const char* file)
-{
- STACK_OF(X509) *sk = read_cert_file(file);
- if(!sk) {
- if(verb) printf("using builtin certificate\n");
- sk = read_builtin_cert();
- }
- if(verb) printf("have %d trusted certificates\n", sk_X509_num(sk));
- verb_certs("trusted certificates", sk);
- return sk;
-}
-
-static void
-do_list_builtin(void)
-{
- const char* builtin_cert = get_builtin_cert();
- const char* builtin_ds = get_builtin_ds();
- printf("%s\n", builtin_ds);
- printf("%s\n", builtin_cert);
- exit(0);
-}
-
-/** printout IP address with message */
-static void
-verb_addr(const char* msg, struct ip_list* ip)
-{
- if(verb) {
- char out[100];
- void* a = &((struct sockaddr_in*)&ip->addr)->sin_addr;
- if(ip->len != (socklen_t)sizeof(struct sockaddr_in))
- a = &((struct sockaddr_in6*)&ip->addr)->sin6_addr;
-
- if(inet_ntop((int)((struct sockaddr_in*)&ip->addr)->sin_family,
- a, out, (socklen_t)sizeof(out))==0)
- printf("%s (inet_ntop error)\n", msg);
- else printf("%s %s\n", msg, out);
- }
-}
-
-/** free ip_list */
-static void
-ip_list_free(struct ip_list* p)
-{
- struct ip_list* np;
- while(p) {
- np = p->next;
- free(p);
- p = np;
- }
-}
-
-/** create ip_list entry for a RR record */
-static struct ip_list*
-RR_to_ip(int tp, char* data, int len, int port)
-{
- struct ip_list* ip = (struct ip_list*)calloc(1, sizeof(*ip));
- uint16_t p = (uint16_t)port;
- if(tp == LDNS_RR_TYPE_A) {
- struct sockaddr_in* sa = (struct sockaddr_in*)&ip->addr;
- ip->len = (socklen_t)sizeof(*sa);
- sa->sin_family = AF_INET;
- sa->sin_port = (in_port_t)htons(p);
- if(len != (int)sizeof(sa->sin_addr)) {
- if(verb) printf("skipped badly formatted A\n");
- free(ip);
- return NULL;
- }
- memmove(&sa->sin_addr, data, sizeof(sa->sin_addr));
-
- } else if(tp == LDNS_RR_TYPE_AAAA) {
- struct sockaddr_in6* sa = (struct sockaddr_in6*)&ip->addr;
- ip->len = (socklen_t)sizeof(*sa);
- sa->sin6_family = AF_INET6;
- sa->sin6_port = (in_port_t)htons(p);
- if(len != (int)sizeof(sa->sin6_addr)) {
- if(verb) printf("skipped badly formatted AAAA\n");
- free(ip);
- return NULL;
- }
- memmove(&sa->sin6_addr, data, sizeof(sa->sin6_addr));
- } else {
- if(verb) printf("internal error: bad type in RRtoip\n");
- free(ip);
- return NULL;
- }
- verb_addr("resolved server address", ip);
- return ip;
-}
-
-/** Resolve name, type, class and add addresses to iplist */
-static void
-resolve_host_ip(struct ub_ctx* ctx, const char* host, int port, int tp, int cl,
- struct ip_list** head)
-{
- struct ub_result* res = NULL;
- int r;
- int i;
-
- r = ub_resolve(ctx, host, tp, cl, &res);
- if(r) {
- if(verb) printf("error: resolve %s %s: %s\n", host,
- (tp==LDNS_RR_TYPE_A)?"A":"AAAA", ub_strerror(r));
- return;
- }
- if(!res) {
- if(verb) printf("out of memory\n");
- 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);
- if(!ip) continue;
- ip->next = *head;
- *head = ip;
- }
- ub_resolve_free(res);
-}
-
-/** parse a text IP address into a sockaddr */
-static struct ip_list*
-parse_ip_addr(const char* str, int port)
-{
- socklen_t len = 0;
- union {
- struct sockaddr_in6 a6;
- struct sockaddr_in a;
- } addr;
- struct ip_list* ip;
- uint16_t p = (uint16_t)port;
- memset(&addr, 0, sizeof(addr));
-
- if(inet_pton(AF_INET6, str, &addr.a6.sin6_addr) > 0) {
- /* it is an IPv6 */
- addr.a6.sin6_family = AF_INET6;
- addr.a6.sin6_port = (in_port_t)htons(p);
- len = (socklen_t)sizeof(addr.a6);
- }
- if(inet_pton(AF_INET, str, &addr.a.sin_addr) > 0) {
- /* it is an IPv4 */
- addr.a.sin_family = AF_INET;
- addr.a.sin_port = (in_port_t)htons(p);
- len = (socklen_t)sizeof(struct sockaddr_in);
- }
- if(!len) return NULL;
- ip = (struct ip_list*)calloc(1, sizeof(*ip));
- if(!ip) {
- if(verb) printf("out of memory\n");
- exit(0);
- }
- ip->len = len;
- memmove(&ip->addr, &addr, len);
- if(verb) printf("server address is %s\n", str);
- return ip;
-}
-
-/**
- * Resolve a domain name (even though the resolver is down and there is
- * no trust anchor). Without DNSSEC validation.
- * @param host: the name to resolve.
- * If this name is an IP4 or IP6 address this address is returned.
- * @param port: the port number used for the returned IP structs.
- * @param res_conf: resolv.conf (if any).
- * @param root_hints: root hints (if any).
- * @param debugconf: unbound.conf for debugging options.
- * @param ip4only: use only ip4 for resolve and only lookup A
- * @param ip6only: use only ip6 for resolve and only lookup AAAA
- * default is to lookup A and AAAA using ip4 and ip6.
- * @return list of IP addresses.
- */
-static struct ip_list*
-resolve_name(const char* host, int port, const char* res_conf,
- const char* root_hints, const char* debugconf, int ip4only, int ip6only)
-{
- struct ub_ctx* ctx;
- struct ip_list* list = NULL;
- /* first see if name is an IP address itself */
- if( (list=parse_ip_addr(host, port)) ) {
- return list;
- }
-
- /* create resolver context */
- ctx = create_unbound_context(res_conf, root_hints, debugconf,
- ip4only, ip6only);
-
- /* try resolution of A */
- if(!ip6only) {
- resolve_host_ip(ctx, host, port, LDNS_RR_TYPE_A,
- LDNS_RR_CLASS_IN, &list);
- }
-
- /* try resolution of AAAA */
- if(!ip4only) {
- resolve_host_ip(ctx, host, port, LDNS_RR_TYPE_AAAA,
- LDNS_RR_CLASS_IN, &list);
- }
-
- ub_ctx_delete(ctx);
- if(!list) {
- if(verb) printf("%s has no IP addresses I can use\n", host);
- exit(0);
- }
- return list;
-}
-
-/** clear used flags */
-static void
-wipe_ip_usage(struct ip_list* p)
-{
- while(p) {
- p->used = 0;
- p = p->next;
- }
-}
-
-/** cound unused IPs */
-static int
-count_unused(struct ip_list* p)
-{
- int num = 0;
- while(p) {
- if(!p->used) num++;
- p = p->next;
- }
- return num;
-}
-
-/** pick random unused element from IP list */
-static struct ip_list*
-pick_random_ip(struct ip_list* list)
-{
- struct ip_list* p = list;
- int num = count_unused(list);
- int sel;
- if(num == 0) return NULL;
- /* not perfect, but random enough */
- sel = (int)arc4random_uniform((uint32_t)num);
- /* skip over unused elements that we did not select */
- while(sel > 0 && p) {
- if(!p->used) sel--;
- p = p->next;
- }
- /* find the next unused element */
- while(p && p->used)
- p = p->next;
- if(!p) return NULL; /* robustness */
- return p;
-}
-
-/** close the fd */
-static void
-fd_close(int fd)
-{
-#ifndef USE_WINSOCK
- close(fd);
-#else
- closesocket(fd);
-#endif
-}
-
-/** printout socket errno */
-static void
-print_sock_err(const char* msg)
-{
-#ifndef USE_WINSOCK
- if(verb) printf("%s: %s\n", msg, strerror(errno));
-#else
- if(verb) printf("%s: %s\n", msg, wsa_strerror(WSAGetLastError()));
-#endif
-}
-
-/** connect to IP address */
-static int
-connect_to_ip(struct ip_list* ip)
-{
- int fd;
- verb_addr("connect to", ip);
- fd = socket(ip->len==(socklen_t)sizeof(struct sockaddr_in)?
- AF_INET:AF_INET6, SOCK_STREAM, 0);
- if(fd == -1) {
- print_sock_err("socket");
- return -1;
- }
- if(connect(fd, (struct sockaddr*)&ip->addr, ip->len) < 0) {
- print_sock_err("connect");
- fd_close(fd);
- return -1;
- }
- return fd;
-}
-
-/** create SSL context */
-static SSL_CTX*
-setup_sslctx(void)
-{
- SSL_CTX* sslctx = SSL_CTX_new(SSLv23_client_method());
- if(!sslctx) {
- if(verb) printf("SSL_CTX_new error\n");
- return NULL;
- }
- return sslctx;
-}
-
-/** initiate TLS on a connection */
-static SSL*
-TLS_initiate(SSL_CTX* sslctx, int fd)
-{
- X509* x;
- int r;
- SSL* ssl = SSL_new(sslctx);
- if(!ssl) {
- if(verb) printf("SSL_new error\n");
- return NULL;
- }
- SSL_set_connect_state(ssl);
- (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
- if(!SSL_set_fd(ssl, fd)) {
- if(verb) printf("SSL_set_fd error\n");
- SSL_free(ssl);
- return NULL;
- }
- while(1) {
- ERR_clear_error();
- if( (r=SSL_do_handshake(ssl)) == 1)
- break;
- r = SSL_get_error(ssl, r);
- if(r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) {
- if(verb) printf("SSL handshake failed\n");
- SSL_free(ssl);
- return NULL;
- }
- /* wants to be called again */
- }
- x = SSL_get_peer_certificate(ssl);
- if(!x) {
- if(verb) printf("Server presented no peer certificate\n");
- SSL_free(ssl);
- return NULL;
- }
- verb_cert("server SSL certificate", x);
- X509_free(x);
- return ssl;
-}
-
-/** perform neat TLS shutdown */
-static void
-TLS_shutdown(int fd, SSL* ssl, SSL_CTX* sslctx)
-{
- /* shutdown the SSL connection nicely */
- if(SSL_shutdown(ssl) == 0) {
- SSL_shutdown(ssl);
- }
- SSL_free(ssl);
- SSL_CTX_free(sslctx);
- fd_close(fd);
-}
-
-/** write a line over SSL */
-static int
-write_ssl_line(SSL* ssl, const char* str, const char* sec)
-{
- char buf[1024];
- size_t l;
- if(sec) {
- snprintf(buf, sizeof(buf), str, sec);
- } else {
- snprintf(buf, sizeof(buf), "%s", str);
- }
- l = strlen(buf);
- if(l+2 >= sizeof(buf)) {
- if(verb) printf("line too long\n");
- return 0;
- }
- if(verb >= 2) printf("SSL_write: %s\n", buf);
- buf[l] = '\r';
- buf[l+1] = '\n';
- buf[l+2] = 0;
- /* add \r\n */
- if(SSL_write(ssl, buf, (int)strlen(buf)) <= 0) {
- if(verb) printf("could not SSL_write %s", str);
- return 0;
- }
- return 1;
-}
-
-/** process header line, check rcode and keeping track of size */
-static int
-process_one_header(char* buf, size_t* clen, int* chunked)
-{
- if(verb>=2) printf("header: '%s'\n", buf);
- if(strncasecmp(buf, "HTTP/1.1 ", 9) == 0) {
- /* check returncode */
- if(buf[9] != '2') {
- if(verb) printf("bad status %s\n", buf+9);
- return 0;
- }
- } else if(strncasecmp(buf, "Content-Length: ", 16) == 0) {
- if(!*chunked)
- *clen = (size_t)atoi(buf+16);
- } else if(strncasecmp(buf, "Transfer-Encoding: chunked", 19+7) == 0) {
- *clen = 0;
- *chunked = 1;
- }
- return 1;
-}
-
-/**
- * Read one line from SSL
- * zero terminates.
- * skips "\r\n" (but not copied to buf).
- * @param ssl: the SSL connection to read from (blocking).
- * @param buf: buffer to return line in.
- * @param len: size of the buffer.
- * @return 0 on error, 1 on success.
- */
-static int
-read_ssl_line(SSL* ssl, char* buf, size_t len)
-{
- size_t n = 0;
- int r;
- int endnl = 0;
- while(1) {
- if(n >= len) {
- if(verb) printf("line too long\n");
- return 0;
- }
- if((r = SSL_read(ssl, buf+n, 1)) <= 0) {
- if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
- /* EOF */
- break;
- }
- if(verb) printf("could not SSL_read\n");
- return 0;
- }
- if(endnl && buf[n] == '\n') {
- break;
- } else if(endnl) {
- /* bad data */
- if(verb) printf("error: stray linefeeds\n");
- return 0;
- } else if(buf[n] == '\r') {
- /* skip \r, and also \n on the wire */
- endnl = 1;
- continue;
- } else if(buf[n] == '\n') {
- /* skip the \n, we are done */
- break;
- } else n++;
- }
- buf[n] = 0;
- return 1;
-}
-
-/** read http headers and process them */
-static size_t
-read_http_headers(SSL* ssl, size_t* clen)
-{
- char buf[1024];
- int chunked = 0;
- *clen = 0;
- while(read_ssl_line(ssl, buf, sizeof(buf))) {
- if(buf[0] == 0)
- return 1;
- if(!process_one_header(buf, clen, &chunked))
- return 0;
- }
- return 0;
-}
-
-/** read a data chunk */
-static char*
-read_data_chunk(SSL* ssl, size_t len)
-{
- size_t got = 0;
- int r;
- char* data;
- if(len >= 0xfffffff0)
- return NULL; /* to protect against integer overflow in malloc*/
- data = malloc(len+1);
- if(!data) {
- if(verb) printf("out of memory\n");
- return NULL;
- }
- while(got < len) {
- if((r = SSL_read(ssl, data+got, (int)(len-got))) <= 0) {
- if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
- /* EOF */
- if(verb) printf("could not SSL_read: unexpected EOF\n");
- free(data);
- return NULL;
- }
- if(verb) printf("could not SSL_read\n");
- free(data);
- return NULL;
- }
- if(verb >= 2) printf("at %d/%d\n", (int)got, (int)len);
- got += r;
- }
- if(verb>=2) printf("read %d data\n", (int)len);
- data[len] = 0;
- return data;
-}
-
-/** parse chunk header */
-static int
-parse_chunk_header(char* buf, size_t* result)
-{
- char* e = NULL;
- size_t v = (size_t)strtol(buf, &e, 16);
- if(e == buf)
- return 0;
- *result = v;
- return 1;
-}
-
-/** read chunked data from connection */
-static BIO*
-do_chunked_read(SSL* ssl)
-{
- char buf[1024];
- size_t len;
- char* body;
- BIO* mem = BIO_new(BIO_s_mem());
- if(verb>=3) printf("do_chunked_read\n");
- if(!mem) {
- if(verb) printf("out of memory\n");
- return NULL;
- }
- while(read_ssl_line(ssl, buf, sizeof(buf))) {
- /* read the chunked start line */
- if(verb>=2) printf("chunk header: %s\n", buf);
- if(!parse_chunk_header(buf, &len)) {
- BIO_free(mem);
- if(verb>=3) printf("could not parse chunk header\n");
- return NULL;
- }
- if(verb>=2) printf("chunk len: %d\n", (int)len);
- /* are we done? */
- if(len == 0) {
- char z = 0;
- /* skip end-of-chunk-trailer lines,
- * until the empty line after that */
- do {
- if(!read_ssl_line(ssl, buf, sizeof(buf))) {
- BIO_free(mem);
- return NULL;
- }
- } while (strlen(buf) > 0);
- /* end of chunks, zero terminate it */
- if(BIO_write(mem, &z, 1) <= 0) {
- if(verb) printf("out of memory\n");
- BIO_free(mem);
- return NULL;
- }
- return mem;
- }
- /* read the chunked body */
- body = read_data_chunk(ssl, len);
- if(!body) {
- BIO_free(mem);
- return NULL;
- }
- if(BIO_write(mem, body, (int)len) <= 0) {
- if(verb) printf("out of memory\n");
- free(body);
- BIO_free(mem);
- return NULL;
- }
- free(body);
- /* skip empty line after data chunk */
- if(!read_ssl_line(ssl, buf, sizeof(buf))) {
- BIO_free(mem);
- return NULL;
- }
- }
- BIO_free(mem);
- return NULL;
-}
-
-/** start HTTP1.1 transaction on SSL */
-static int
-write_http_get(SSL* ssl, const char* pathname, const char* urlname)
-{
- if(write_ssl_line(ssl, "GET /%s HTTP/1.1", pathname) &&
- write_ssl_line(ssl, "Host: %s", urlname) &&
- write_ssl_line(ssl, "User-Agent: unbound-anchor/%s",
- PACKAGE_VERSION) &&
- /* We do not really do multiple queries per connection,
- * but this header setting is also not needed.
- * write_ssl_line(ssl, "Connection: close", NULL) &&*/
- write_ssl_line(ssl, "", NULL)) {
- return 1;
- }
- return 0;
-}
-
-/** read chunked data and zero terminate; len is without zero */
-static char*
-read_chunked_zero_terminate(SSL* ssl, size_t* len)
-{
- /* do the chunked version */
- BIO* tmp = do_chunked_read(ssl);
- char* data, *d = NULL;
- size_t l;
- if(!tmp) {
- if(verb) printf("could not read from https\n");
- return NULL;
- }
- l = (size_t)BIO_get_mem_data(tmp, &d);
- if(verb>=2) printf("chunked data is %d\n", (int)l);
- if(l == 0 || d == NULL) {
- if(verb) printf("out of memory\n");
- return NULL;
- }
- *len = l-1;
- data = (char*)malloc(l);
- if(data == NULL) {
- if(verb) printf("out of memory\n");
- return NULL;
- }
- memcpy(data, d, l);
- BIO_free(tmp);
- return data;
-}
-
-/** read HTTP result from SSL */
-static BIO*
-read_http_result(SSL* ssl)
-{
- size_t len = 0;
- char* data;
- BIO* m;
- if(!read_http_headers(ssl, &len)) {
- return NULL;
- }
- if(len == 0) {
- data = read_chunked_zero_terminate(ssl, &len);
- } else {
- data = read_data_chunk(ssl, len);
- }
- if(!data) return NULL;
- if(verb >= 4) print_data("read data", data, (int)len);
- m = BIO_new_mem_buf(data, (int)len);
- if(!m) {
- if(verb) printf("out of memory\n");
- exit(0);
- }
- return m;
-}
-
-/** https to an IP addr, return BIO with pathname or NULL */
-static BIO*
-https_to_ip(struct ip_list* ip, const char* pathname, const char* urlname)
-{
- int fd;
- SSL* ssl;
- BIO* bio;
- SSL_CTX* sslctx = setup_sslctx();
- if(!sslctx) {
- return NULL;
- }
- fd = connect_to_ip(ip);
- if(fd == -1) {
- SSL_CTX_free(sslctx);
- return NULL;
- }
- ssl = TLS_initiate(sslctx, fd);
- if(!ssl) {
- SSL_CTX_free(sslctx);
- fd_close(fd);
- return NULL;
- }
- if(!write_http_get(ssl, pathname, urlname)) {
- if(verb) printf("could not write to server\n");
- SSL_free(ssl);
- SSL_CTX_free(sslctx);
- fd_close(fd);
- return NULL;
- }
- bio = read_http_result(ssl);
- TLS_shutdown(fd, ssl, sslctx);
- return bio;
-}
-
-/**
- * Do a HTTPS, HTTP1.1 over TLS, to fetch a file
- * @param ip_list: list of IP addresses to use to fetch from.
- * @param pathname: pathname of file on server to GET.
- * @param urlname: name to pass as the virtual host for this request.
- * @return a memory BIO with the file in it.
- */
-static BIO*
-https(struct ip_list* ip_list, const char* pathname, const char* urlname)
-{
- struct ip_list* ip;
- BIO* bio = NULL;
- /* try random address first, and work through the list */
- wipe_ip_usage(ip_list);
- while( (ip = pick_random_ip(ip_list)) ) {
- ip->used = 1;
- bio = https_to_ip(ip, pathname, urlname);
- if(bio) break;
- }
- if(!bio) {
- if(verb) printf("could not fetch %s\n", pathname);
- exit(0);
- } else {
- if(verb) printf("fetched %s (%d bytes)\n",
- pathname, (int)BIO_ctrl_pending(bio));
- }
- return bio;
-}
-
-/** free up a downloaded file BIO */
-static void
-free_file_bio(BIO* bio)
-{
- char* pp = NULL;
- (void)BIO_reset(bio);
- (void)BIO_get_mem_data(bio, &pp);
- free(pp);
- BIO_free(bio);
-}
-
-/** XML parse private data during the parse */
-struct xml_data {
- /** the parser, reference */
- XML_Parser parser;
- /** the current tag; malloced; or NULL outside of tags */
- char* tag;
- /** current date to use during the parse */
- time_t date;
- /** number of keys usefully read in */
- int num_keys;
- /** the compiled anchors as DS records */
- BIO* ds;
-
- /** do we want to use this anchor? */
- int use_key;
- /** the current anchor: Zone */
- BIO* czone;
- /** the current anchor: KeyTag */
- BIO* ctag;
- /** the current anchor: Algorithm */
- BIO* calgo;
- /** the current anchor: DigestType */
- BIO* cdigtype;
- /** the current anchor: Digest*/
- BIO* cdigest;
-};
-
-/** The BIO for the tag */
-static BIO*
-xml_selectbio(struct xml_data* data, const char* tag)
-{
- BIO* b = NULL;
- if(strcasecmp(tag, "KeyTag") == 0)
- b = data->ctag;
- else if(strcasecmp(tag, "Algorithm") == 0)
- b = data->calgo;
- else if(strcasecmp(tag, "DigestType") == 0)
- b = data->cdigtype;
- else if(strcasecmp(tag, "Digest") == 0)
- b = data->cdigest;
- return b;
-}
-
-/**
- * XML handle character data, the data inside an element.
- * @param userData: xml_data structure
- * @param s: the character data. May not all be in one callback.
- * NOT zero terminated.
- * @param len: length of this part of the data.
- */
-static void
-xml_charhandle(void *userData, const XML_Char *s, int len)
-{
- struct xml_data* data = (struct xml_data*)userData;
- BIO* b = NULL;
- /* skip characters outside of elements */
- if(!data->tag)
- return;
- if(verb>=4) {
- int i;
- printf("%s%s charhandle: '",
- data->use_key?"use ":"",
- data->tag?data->tag:"none");
- for(i=0; i<len; i++)
- printf("%c", s[i]);
- printf("'\n");
- }
- if(strcasecmp(data->tag, "Zone") == 0) {
- if(BIO_write(data->czone, s, len) < 0) {
- if(verb) printf("out of memory in BIO_write\n");
- exit(0);
- }
- return;
- }
- /* only store if key is used */
- if(!data->use_key)
- return;
- b = xml_selectbio(data, data->tag);
- if(b) {
- if(BIO_write(b, s, len) < 0) {
- if(verb) printf("out of memory in BIO_write\n");
- exit(0);
- }
- }
-}
-
-/**
- * XML fetch value of particular attribute(by name) or NULL if not present.
- * @param atts: attribute array (from xml_startelem).
- * @param name: name of attribute to look for.
- * @return the value or NULL. (ptr into atts).
- */
-static const XML_Char*
-find_att(const XML_Char **atts, const XML_Char* name)
-{
- int i;
- for(i=0; atts[i]; i+=2) {
- if(strcasecmp(atts[i], name) == 0)
- return atts[i+1];
- }
- return NULL;
-}
-
-/**
- * XML convert DateTime element to time_t.
- * [-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
- * (with optional .ssssss fractional seconds)
- * @param str: the string
- * @return a time_t representation or 0 on failure.
- */
-static time_t
-xml_convertdate(const char* str)
-{
- time_t t = 0;
- struct tm tm;
- const char* s;
- /* for this application, ignore minus in front;
- * only positive dates are expected */
- s = str;
- if(s[0] == '-') s++;
- memset(&tm, 0, sizeof(tm));
- /* parse initial content of the string (lots of whitespace allowed) */
- s = strptime(s, "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t:%t%S%t", &tm);
- if(!s) {
- if(verb) printf("xml_convertdate parse failure %s\n", str);
- return 0;
- }
- /* parse remainder of date string */
- if(*s == '.') {
- /* optional '.' and fractional seconds */
- int frac = 0, n = 0;
- if(sscanf(s+1, "%d%n", &frac, &n) < 1) {
- if(verb) printf("xml_convertdate f failure %s\n", str);
- return 0;
- }
- /* fraction is not used, time_t has second accuracy */
- s++;
- s+=n;
- }
- if(*s == 'Z' || *s == 'z') {
- /* nothing to do for this */
- s++;
- } else if(*s == '+' || *s == '-') {
- /* optional timezone spec: Z or +hh:mm or -hh:mm */
- int hr = 0, mn = 0, n = 0;
- if(sscanf(s+1, "%d:%d%n", &hr, &mn, &n) < 2) {
- if(verb) printf("xml_convertdate tz failure %s\n", str);
- return 0;
- }
- if(*s == '+') {
- tm.tm_hour += hr;
- tm.tm_min += mn;
- } else {
- tm.tm_hour -= hr;
- tm.tm_min -= mn;
- }
- s++;
- s += n;
- }
- if(*s != 0) {
- /* not ended properly */
- /* but ignore, (lenient) */
- }
-
- t = sldns_mktime_from_utc(&tm);
- if(t == (time_t)-1) {
- if(verb) printf("xml_convertdate mktime failure\n");
- return 0;
- }
- return t;
-}
-
-/**
- * XML handle the KeyDigest start tag, check validity periods.
- */
-static void
-handle_keydigest(struct xml_data* data, const XML_Char **atts)
-{
- data->use_key = 0;
- if(find_att(atts, "validFrom")) {
- time_t from = xml_convertdate(find_att(atts, "validFrom"));
- if(from == 0) {
- if(verb) printf("error: xml cannot be parsed\n");
- exit(0);
- }
- if(data->date < from)
- return;
- }
- if(find_att(atts, "validUntil")) {
- time_t until = xml_convertdate(find_att(atts, "validUntil"));
- if(until == 0) {
- if(verb) printf("error: xml cannot be parsed\n");
- exit(0);
- }
- if(data->date > until)
- return;
- }
- /* yes we want to use this key */
- data->use_key = 1;
- (void)BIO_reset(data->ctag);
- (void)BIO_reset(data->calgo);
- (void)BIO_reset(data->cdigtype);
- (void)BIO_reset(data->cdigest);
-}
-
-/** See if XML element equals the zone name */
-static int
-xml_is_zone_name(BIO* zone, const char* name)
-{
- char buf[1024];
- char* z = NULL;
- long zlen;
- (void)BIO_seek(zone, 0);
- zlen = BIO_get_mem_data(zone, &z);
- if(!zlen || !z) return 0;
- /* zero terminate */
- if(zlen >= (long)sizeof(buf)) return 0;
- memmove(buf, z, (size_t)zlen);
- buf[zlen] = 0;
- /* compare */
- return (strncasecmp(buf, name, strlen(name)) == 0);
-}
-
-/**
- * XML start of element. This callback is called whenever an XML tag starts.
- * XML_Char is UTF8.
- * @param userData: the xml_data structure.
- * @param name: the tag that starts.
- * @param atts: array of strings, pairs of attr = value, ends with NULL.
- * i.e. att[0]="att[1]" att[2]="att[3]" att[4]isNull
- */
-static void
-xml_startelem(void *userData, const XML_Char *name, const XML_Char **atts)
-{
- struct xml_data* data = (struct xml_data*)userData;
- BIO* b;
- if(verb>=4) printf("xml tag start '%s'\n", name);
- free(data->tag);
- data->tag = strdup(name);
- if(!data->tag) {
- if(verb) printf("out of memory\n");
- exit(0);
- }
- if(verb>=4) {
- int i;
- for(i=0; atts[i]; i+=2) {
- printf(" %s='%s'\n", atts[i], atts[i+1]);
- }
- }
- /* handle attributes to particular types */
- if(strcasecmp(name, "KeyDigest") == 0) {
- handle_keydigest(data, atts);
- return;
- } else if(strcasecmp(name, "Zone") == 0) {
- (void)BIO_reset(data->czone);
- return;
- }
-
- /* for other types we prepare to pick up the data */
- if(!data->use_key)
- return;
- b = xml_selectbio(data, data->tag);
- if(b) {
- /* empty it */
- (void)BIO_reset(b);
- }
-}
-
-/** Append str to bio */
-static void
-xml_append_str(BIO* b, const char* s)
-{
- if(BIO_write(b, s, (int)strlen(s)) < 0) {
- if(verb) printf("out of memory in BIO_write\n");
- exit(0);
- }
-}
-
-/** Append bio to bio */
-static void
-xml_append_bio(BIO* b, BIO* a)
-{
- char* z = NULL;
- long i, len;
- (void)BIO_seek(a, 0);
- len = BIO_get_mem_data(a, &z);
- if(!len || !z) {
- if(verb) printf("out of memory in BIO_write\n");
- exit(0);
- }
- /* remove newlines in the data here */
- for(i=0; i<len; i++) {
- if(z[i] == '\r' || z[i] == '\n')
- z[i] = ' ';
- }
- /* write to BIO */
- if(BIO_write(b, z, len) < 0) {
- if(verb) printf("out of memory in BIO_write\n");
- exit(0);
- }
-}
-
-/** write the parsed xml-DS to the DS list */
-static void
-xml_append_ds(struct xml_data* data)
-{
- /* write DS to accumulated DS */
- xml_append_str(data->ds, ". IN DS ");
- xml_append_bio(data->ds, data->ctag);
- xml_append_str(data->ds, " ");
- xml_append_bio(data->ds, data->calgo);
- xml_append_str(data->ds, " ");
- xml_append_bio(data->ds, data->cdigtype);
- xml_append_str(data->ds, " ");
- xml_append_bio(data->ds, data->cdigest);
- xml_append_str(data->ds, "\n");
- data->num_keys++;
-}
-
-/**
- * XML end of element. This callback is called whenever an XML tag ends.
- * XML_Char is UTF8.
- * @param userData: the xml_data structure
- * @param name: the tag that ends.
- */
-static void
-xml_endelem(void *userData, const XML_Char *name)
-{
- struct xml_data* data = (struct xml_data*)userData;
- if(verb>=4) printf("xml tag end '%s'\n", name);
- free(data->tag);
- data->tag = NULL;
- if(strcasecmp(name, "KeyDigest") == 0) {
- if(data->use_key)
- xml_append_ds(data);
- data->use_key = 0;
- } else if(strcasecmp(name, "Zone") == 0) {
- if(!xml_is_zone_name(data->czone, ".")) {
- if(verb) printf("xml not for the right zone\n");
- exit(0);
- }
- }
-}
-
-/* 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))
-{
-#if HAVE_DECL_XML_STOPPARSER
- (void)XML_StopParser((XML_Parser)userData, XML_FALSE);
-#else
- (void)userData;
-#endif
-}
-
-/**
- * XML parser setup of the callbacks for the tags
- */
-static void
-xml_parse_setup(XML_Parser parser, struct xml_data* data, time_t now)
-{
- char buf[1024];
- memset(data, 0, sizeof(*data));
- XML_SetUserData(parser, data);
- data->parser = parser;
- data->date = now;
- data->ds = BIO_new(BIO_s_mem());
- data->ctag = BIO_new(BIO_s_mem());
- data->czone = BIO_new(BIO_s_mem());
- data->calgo = BIO_new(BIO_s_mem());
- data->cdigtype = BIO_new(BIO_s_mem());
- data->cdigest = BIO_new(BIO_s_mem());
- if(!data->ds || !data->ctag || !data->calgo || !data->czone ||
- !data->cdigtype || !data->cdigest) {
- if(verb) printf("out of memory\n");
- exit(0);
- }
- snprintf(buf, sizeof(buf), "; created by unbound-anchor on %s",
- ctime(&now));
- if(BIO_write(data->ds, buf, (int)strlen(buf)) < 0) {
- 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);
-}
-
-/**
- * Perform XML parsing of the root-anchors file
- * Its format description can be read here
- * https://data.iana.org/root-anchors/draft-icann-dnssec-trust-anchor.txt
- * It uses libexpat.
- * @param xml: BIO with xml data.
- * @param now: the current time for checking DS validity periods.
- * @return memoryBIO with the DS data in zone format.
- * or NULL if the zone is insecure.
- * (It exit()s on error)
- */
-static BIO*
-xml_parse(BIO* xml, time_t now)
-{
- char* pp;
- int len;
- XML_Parser parser;
- struct xml_data data;
-
- parser = XML_ParserCreate(NULL);
- if(!parser) {
- if(verb) printf("could not XML_ParserCreate\n");
- exit(0);
- }
-
- /* setup callbacks */
- xml_parse_setup(parser, &data, now);
-
- /* parse it */
- (void)BIO_reset(xml);
- len = (int)BIO_get_mem_data(xml, &pp);
- if(!len || !pp) {
- if(verb) printf("out of memory\n");
- exit(0);
- }
- if(!XML_Parse(parser, pp, len, 1 /*isfinal*/ )) {
- const char *e = XML_ErrorString(XML_GetErrorCode(parser));
- if(verb) printf("XML_Parse failure %s\n", e?e:"");
- exit(0);
- }
-
- /* parsed */
- if(verb) printf("XML was parsed successfully, %d keys\n",
- data.num_keys);
- free(data.tag);
- XML_ParserFree(parser);
-
- if(verb >= 4) {
- (void)BIO_seek(data.ds, 0);
- len = BIO_get_mem_data(data.ds, &pp);
- printf("got DS bio %d: '", len);
- if(!fwrite(pp, (size_t)len, 1, stdout))
- /* compilers do not allow us to ignore fwrite .. */
- fprintf(stderr, "error writing to stdout\n");
- printf("'\n");
- }
- BIO_free(data.czone);
- BIO_free(data.ctag);
- BIO_free(data.calgo);
- BIO_free(data.cdigtype);
- BIO_free(data.cdigest);
-
- if(data.num_keys == 0) {
- /* the root zone seems to have gone insecure */
- BIO_free(data.ds);
- return NULL;
- } else {
- return data.ds;
- }
-}
-
-/* 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, const 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, const 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
- X509_VERIFY_PARAM* param = X509_VERIFY_PARAM_new();
- if(!param) {
- if(verb) printf("out of memory\n");
- X509_STORE_free(store);
- return 0;
- }
- /* do the selfcheck on the root certificate; it checks that the
- * input is valid */
- X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CHECK_SS_SIGNATURE);
- if(store) X509_STORE_set1_param(store, param);
-#endif
- if(!store) {
- if(verb) printf("out of memory\n");
-#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
- X509_VERIFY_PARAM_free(param);
-#endif
- return 0;
- }
-#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
- X509_VERIFY_PARAM_free(param);
-#endif
-
- (void)BIO_reset(p7s);
- (void)BIO_reset(data);
-
- /* convert p7s to p7 (the signature) */
- p7 = d2i_PKCS7_bio(p7s, NULL);
- if(!p7) {
- if(verb) printf("could not parse p7s signature file\n");
- X509_STORE_free(store);
- return 0;
- }
- if(verb >= 2) printf("parsed the PKCS7 signature\n");
-
- /* convert trust to trusted certificate store */
- for(i=0; i<sk_X509_num(trust); i++) {
- if(!X509_STORE_add_cert(store, sk_X509_value(trust, i))) {
- if(verb) printf("failed X509_STORE_add_cert\n");
- X509_STORE_free(store);
- PKCS7_free(p7);
- return 0;
- }
- }
- if(verb >= 2) printf("setup the X509_STORE\n");
-
- /* 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 {
- if(verb) {
- ERR_print_errors_fp(stdout);
- }
- }
-
- sk_X509_free(validsigners);
- X509_STORE_free(store);
- PKCS7_free(p7);
- return secure;
-}
-
-/** write unsigned root anchor file, a 5011 revoked tp */
-static void
-write_unsigned_root(const char* root_anchor_file)
-{
- FILE* out;
- time_t now = time(NULL);
- out = fopen(root_anchor_file, "w");
- if(!out) {
- if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno));
- return;
- }
- if(fprintf(out, "; autotrust trust anchor file\n"
- ";;REVOKED\n"
- ";;id: . 1\n"
- "; This file was written by unbound-anchor on %s"
- "; It indicates that the root does not use DNSSEC\n"
- "; to restart DNSSEC overwrite this file with a\n"
- "; valid trustanchor or (empty-it and run unbound-anchor)\n"
- , ctime(&now)) < 0) {
- if(verb) printf("failed to write 'unsigned' to %s\n",
- root_anchor_file);
- if(verb && errno != 0) printf("%s\n", strerror(errno));
- }
- fflush(out);
-#ifdef HAVE_FSYNC
- fsync(fileno(out));
-#else
- FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
-#endif
- fclose(out);
-}
-
-/** write root anchor file */
-static void
-write_root_anchor(const char* root_anchor_file, BIO* ds)
-{
- char* pp = NULL;
- int len;
- FILE* out;
- (void)BIO_seek(ds, 0);
- len = BIO_get_mem_data(ds, &pp);
- if(!len || !pp) {
- if(verb) printf("out of memory\n");
- return;
- }
- out = fopen(root_anchor_file, "w");
- if(!out) {
- if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno));
- return;
- }
- if(fwrite(pp, (size_t)len, 1, out) != 1) {
- if(verb) printf("failed to write all data to %s\n",
- root_anchor_file);
- if(verb && errno != 0) printf("%s\n", strerror(errno));
- }
- fflush(out);
-#ifdef HAVE_FSYNC
- fsync(fileno(out));
-#else
- FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
-#endif
- fclose(out);
-}
-
-/** Perform the verification and update of the trustanchor file */
-static void
-verify_and_update_anchor(const char* root_anchor_file, BIO* xml, BIO* p7s,
- STACK_OF(X509)* cert, const char* p7signer)
-{
- BIO* ds;
-
- /* verify xml file */
- if(!verify_p7sig(xml, p7s, cert, p7signer)) {
- printf("the PKCS7 signature failed\n");
- exit(0);
- }
-
- /* parse the xml file into DS records */
- ds = xml_parse(xml, time(NULL));
- if(!ds) {
- /* the root zone is unsigned now */
- write_unsigned_root(root_anchor_file);
- } else {
- /* reinstate 5011 tracking */
- write_root_anchor(root_anchor_file, ds);
- }
- BIO_free(ds);
-}
-
-#ifdef USE_WINSOCK
-static void do_wsa_cleanup(void) { WSACleanup(); }
-#endif
-
-/** perform actual certupdate work */
-static int
-do_certupdate(const char* root_anchor_file, const char* root_cert_file,
- const char* urlname, const char* xmlname, const char* p7sname,
- const char* p7signer, const char* res_conf, const char* root_hints,
- const char* debugconf, int ip4only, int ip6only, int port,
- struct ub_result* dnskey)
-{
- STACK_OF(X509)* cert;
- BIO *xml, *p7s;
- struct ip_list* ip_list = NULL;
-
- /* read pem file or provide builtin */
- cert = read_cert_or_builtin(root_cert_file);
-
- /* lookup A, AAAA for the urlname (or parse urlname if IP address) */
- ip_list = resolve_name(urlname, port, res_conf, root_hints, debugconf,
- ip4only, ip6only);
-
-#ifdef USE_WINSOCK
- if(1) { /* libunbound finished, startup WSA for the https connection */
- WSADATA wsa_data;
- int r;
- if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) {
- if(verb) printf("WSAStartup failed: %s\n",
- wsa_strerror(r));
- exit(0);
- }
- atexit(&do_wsa_cleanup);
- }
-#endif
-
- /* fetch the necessary files over HTTPS */
- xml = https(ip_list, xmlname, urlname);
- p7s = https(ip_list, p7sname, urlname);
-
- /* verify and update the root anchor */
- verify_and_update_anchor(root_anchor_file, xml, p7s, cert, p7signer);
- if(verb) printf("success: the anchor has been updated "
- "using the cert\n");
-
- free_file_bio(xml);
- free_file_bio(p7s);
-#ifndef S_SPLINT_S
- sk_X509_pop_free(cert, X509_free);
-#endif
- ub_resolve_free(dnskey);
- ip_list_free(ip_list);
- return 1;
-}
-
-/**
- * Try to read the root RFC5011 autotrust anchor file,
- * @param file: filename.
- * @return:
- * 0 if does not exist or empty
- * 1 if trust-point-revoked-5011
- * 2 if it is OK.
- */
-static int
-try_read_anchor(const char* file)
-{
- int empty = 1;
- char line[10240];
- char* p;
- FILE* in = fopen(file, "r");
- if(!in) {
- /* only if the file does not exist, can we fix it */
- if(errno != ENOENT) {
- if(verb) printf("%s: %s\n", file, strerror(errno));
- if(verb) printf("error: cannot access the file\n");
- exit(0);
- }
- if(verb) printf("%s does not exist\n", file);
- return 0;
- }
- while(fgets(line, (int)sizeof(line), in)) {
- line[sizeof(line)-1] = 0;
- if(strncmp(line, ";;REVOKED", 9) == 0) {
- fclose(in);
- if(verb) printf("%s : the trust point is revoked\n"
- "and the zone is considered unsigned.\n"
- "if you wish to re-enable, delete the file\n",
- file);
- return 1;
- }
- p=line;
- while(*p == ' ' || *p == '\t')
- p++;
- if(p[0]==0 || p[0]=='\n' || p[0]==';') continue;
- /* this line is a line of content */
- empty = 0;
- }
- fclose(in);
- if(empty) {
- if(verb) printf("%s is empty\n", file);
- return 0;
- }
- if(verb) printf("%s has content\n", file);
- return 2;
-}
-
-/** Write the builtin root anchor to a file */
-static void
-write_builtin_anchor(const char* file)
-{
- const char* builtin_root_anchor = get_builtin_ds();
- FILE* out = fopen(file, "w");
- if(!out) {
- if(verb) printf("%s: %s\n", file, strerror(errno));
- if(verb) printf(" could not write builtin anchor\n");
- return;
- }
- if(!fwrite(builtin_root_anchor, strlen(builtin_root_anchor), 1, out)) {
- if(verb) printf("%s: %s\n", file, strerror(errno));
- if(verb) printf(" could not complete write builtin anchor\n");
- }
- fclose(out);
-}
-
-/**
- * Check the root anchor file.
- * If does not exist, provide builtin and write file.
- * If empty, provide builtin and write file.
- * If trust-point-revoked-5011 file: make the program exit.
- * @param root_anchor_file: filename of the root anchor.
- * @param used_builtin: set to 1 if the builtin is written.
- * @return 0 if trustpoint is insecure, 1 on success. Exit on failure.
- */
-static int
-provide_builtin(const char* root_anchor_file, int* used_builtin)
-{
- /* try to read it */
- switch(try_read_anchor(root_anchor_file))
- {
- case 0: /* no exist or empty */
- write_builtin_anchor(root_anchor_file);
- *used_builtin = 1;
- break;
- case 1: /* revoked tp */
- return 0;
- case 2: /* it is fine */
- default:
- break;
- }
- return 1;
-}
-
-/**
- * add an autotrust anchor for the root to the context
- */
-static void
-add_5011_probe_root(struct ub_ctx* ctx, const char* root_anchor_file)
-{
- int r;
- r = ub_ctx_set_option(ctx, "auto-trust-anchor-file:", root_anchor_file);
- if(r) {
- if(verb) printf("add 5011 probe to ctx: %s\n", ub_strerror(r));
- ub_ctx_delete(ctx);
- exit(0);
- }
-}
-
-/**
- * Prime the root key and return the result. Exit on error.
- * @param ctx: the unbound context to perform the priming with.
- * @return: the result of the prime, on error it exit()s.
- */
-static struct ub_result*
-prime_root_key(struct ub_ctx* ctx)
-{
- struct ub_result* res = NULL;
- int r;
- r = ub_resolve(ctx, ".", LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, &res);
- if(r) {
- if(verb) printf("resolve DNSKEY: %s\n", ub_strerror(r));
- ub_ctx_delete(ctx);
- exit(0);
- }
- if(!res) {
- if(verb) printf("out of memory\n");
- ub_ctx_delete(ctx);
- exit(0);
- }
- return res;
-}
-
-/** see if ADDPEND keys exist in autotrust file (if possible) */
-static int
-read_if_pending_keys(const char* file)
-{
- FILE* in = fopen(file, "r");
- char line[8192];
- if(!in) {
- if(verb>=2) printf("%s: %s\n", file, strerror(errno));
- return 0;
- }
- while(fgets(line, (int)sizeof(line), in)) {
- if(line[0]==';') continue;
- if(strstr(line, "[ ADDPEND ]")) {
- fclose(in);
- if(verb) printf("RFC5011-state has ADDPEND keys\n");
- return 1;
- }
- }
- fclose(in);
- return 0;
-}
-
-/** read last successful probe time from autotrust file (if possible) */
-static int32_t
-read_last_success_time(const char* file)
-{
- FILE* in = fopen(file, "r");
- char line[1024];
- if(!in) {
- if(verb) printf("%s: %s\n", file, strerror(errno));
- return 0;
- }
- while(fgets(line, (int)sizeof(line), in)) {
- if(strncmp(line, ";;last_success: ", 16) == 0) {
- char* e;
- time_t x = (unsigned int)strtol(line+16, &e, 10);
- fclose(in);
- if(line+16 == e) {
- if(verb) printf("failed to parse "
- "last_success probe time\n");
- return 0;
- }
- if(verb) printf("last successful probe: %s", ctime(&x));
- return (int32_t)x;
- }
- }
- fclose(in);
- if(verb) printf("no last_success probe time in anchor file\n");
- return 0;
-}
-
-/**
- * Read autotrust 5011 probe file and see if the date
- * compared to the current date allows a certupdate.
- * If the last successful probe was recent then 5011 cannot be behind,
- * and the failure cannot be solved with a certupdate.
- * The debugconf is to validation-override the date for testing.
- * @param root_anchor_file: filename of root key
- * @return true if certupdate is ok.
- */
-static int
-probe_date_allows_certupdate(const char* root_anchor_file)
-{
- int has_pending_keys = read_if_pending_keys(root_anchor_file);
- int32_t last_success = read_last_success_time(root_anchor_file);
- int32_t now = (int32_t)time(NULL);
- int32_t leeway = 30 * 24 * 3600; /* 30 days leeway */
- /* if the date is before 2010-07-15:00.00.00 then the root has not
- * been signed yet, and thus we refuse to take action. */
- if(time(NULL) < xml_convertdate("2010-07-15T00:00:00")) {
- if(verb) printf("the date is before the root was first signed,"
- " please correct the clock\n");
- return 0;
- }
- if(last_success == 0)
- return 1; /* no probe time */
- if(has_pending_keys)
- return 1; /* key in ADDPEND state, a previous probe has
- inserted that, and it was present in all recent probes,
- but it has not become active. The 30 day timer may not have
- expired, but we know(for sure) there is a rollover going on.
- If we only managed to pickup the new key on its last day
- of announcement (for example) this can happen. */
- if(now - last_success < 0) {
- if(verb) printf("the last successful probe is in the future,"
- " clock was modified\n");
- return 0;
- }
- if(now - last_success >= leeway) {
- if(verb) printf("the last successful probe was more than 30 "
- "days ago\n");
- return 1;
- }
- if(verb) printf("the last successful probe is recent\n");
- return 0;
-}
-
-/** perform the unbound-anchor work */
-static int
-do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
- const char* urlname, const char* xmlname, const char* p7sname,
- const char* p7signer, const char* res_conf, const char* root_hints,
- const char* debugconf, int ip4only, int ip6only, int force, int port)
-{
- struct ub_ctx* ctx;
- struct ub_result* dnskey;
- int used_builtin = 0;
-
- /* see if builtin rootanchor needs to be provided, or if
- * rootanchor is 'revoked-trust-point' */
- if(!provide_builtin(root_anchor_file, &used_builtin))
- return 0;
-
- /* make unbound context with 5011-probe for root anchor,
- * and probe . DNSKEY */
- ctx = create_unbound_context(res_conf, root_hints, debugconf,
- ip4only, ip6only);
- add_5011_probe_root(ctx, root_anchor_file);
- dnskey = prime_root_key(ctx);
- ub_ctx_delete(ctx);
-
- /* if secure: exit */
- if(dnskey->secure && !force) {
- if(verb) printf("success: the anchor is ok\n");
- ub_resolve_free(dnskey);
- return used_builtin;
- }
- if(force && verb) printf("debug cert update forced\n");
-
- /* if not (and NOERROR): check date and do certupdate */
- if((dnskey->rcode == 0 &&
- probe_date_allows_certupdate(root_anchor_file)) || force) {
- if(do_certupdate(root_anchor_file, root_cert_file, urlname,
- xmlname, p7sname, p7signer, res_conf, root_hints,
- debugconf, ip4only, ip6only, port, dnskey))
- return 1;
- return used_builtin;
- }
- if(verb) printf("fail: the anchor is NOT ok and could not be fixed\n");
- ub_resolve_free(dnskey);
- return used_builtin;
-}
-
-/** getopt global, in case header files fail to declare it. */
-extern int optind;
-/** getopt global, in case header files fail to declare it. */
-extern char* optarg;
-
-/** Main routine for unbound-anchor */
-int main(int argc, char* argv[])
-{
- int c;
- const char* root_anchor_file = ROOT_ANCHOR_FILE;
- const char* root_cert_file = ROOT_CERT_FILE;
- const char* urlname = URLNAME;
- const char* xmlname = XMLNAME;
- const char* p7sname = P7SNAME;
- const char* p7signer = P7SIGNER;
- const char* res_conf = NULL;
- const char* root_hints = NULL;
- const 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:hln:r:s:u:vx:")) != -1) {
- switch(c) {
- case 'l':
- dolist = 1;
- break;
- case '4':
- ip4only = 1;
- break;
- case '6':
- ip6only = 1;
- break;
- case 'a':
- root_anchor_file = optarg;
- break;
- case 'c':
- root_cert_file = optarg;
- break;
- case 'u':
- urlname = optarg;
- break;
- case 'x':
- xmlname = optarg;
- break;
- case 's':
- p7sname = optarg;
- break;
- case 'n':
- p7signer = optarg;
- break;
- case 'f':
- res_conf = optarg;
- break;
- case 'r':
- root_hints = optarg;
- break;
- case 'C':
- debugconf = optarg;
- break;
- case 'F':
- force = 1;
- break;
- case 'P':
- port = atoi(optarg);
- break;
- case 'v':
- verb++;
- break;
- case '?':
- case 'h':
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
- if(argc != 0)
- usage();
-
-#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
- ERR_load_crypto_strings();
-#endif
- ERR_load_SSL_strings();
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
- OpenSSL_add_all_algorithms();
-#else
- OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
- | OPENSSL_INIT_ADD_ALL_DIGESTS
- | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
-#endif
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
- (void)SSL_library_init();
-#else
- (void)OPENSSL_init_ssl(0, NULL);
-#endif
-
- if(dolist) do_list_builtin();
-
- return do_root_update_work(root_anchor_file, root_cert_file, urlname,
- xmlname, p7sname, p7signer, res_conf, root_hints, debugconf,
- ip4only, ip6only, force, port);
-}
diff --git a/external/unbound/smallapp/unbound-checkconf.c b/external/unbound/smallapp/unbound-checkconf.c
deleted file mode 100644
index ddf8b3a75..000000000
--- a/external/unbound/smallapp/unbound-checkconf.c
+++ /dev/null
@@ -1,619 +0,0 @@
-/*
- * checkconf/unbound-checkconf.c - config file checker for unbound.conf file.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * The config checker checks for syntax and other errors in the unbound.conf
- * file, and can be used to check for errors before the server is started
- * or sigHUPped.
- * Exit status 1 means an error.
- */
-
-#include "config.h"
-#include "util/log.h"
-#include "util/config_file.h"
-#include "util/module.h"
-#include "util/net_help.h"
-#include "util/regional.h"
-#include "iterator/iterator.h"
-#include "iterator/iter_fwd.h"
-#include "iterator/iter_hints.h"
-#include "validator/validator.h"
-#include "services/localzone.h"
-#include "services/view.h"
-#include "respip/respip.h"
-#include "sldns/sbuffer.h"
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_GLOB_H
-#include <glob.h>
-#endif
-#ifdef WITH_PYTHONMODULE
-#include "pythonmod/pythonmod.h"
-#endif
-
-/** Give checkconf usage, and exit (1). */
-static void
-usage(void)
-{
- printf("Usage: unbound-checkconf [file]\n");
- printf(" Checks unbound configuration file for errors.\n");
- printf("file if omitted %s is used.\n", CONFIGFILE);
- printf("-o option print value of option to stdout.\n");
- printf("-f output full pathname with chroot applied, eg. with -o pidfile.\n");
- printf("-h show this usage help.\n");
- printf("Version %s\n", PACKAGE_VERSION);
- printf("BSD licensed, see LICENSE in source package for details.\n");
- printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
- exit(1);
-}
-
-/**
- * Print given option to stdout
- * @param cfg: config
- * @param opt: option name without trailing :.
- * This is different from config_set_option.
- * @param final: if final pathname with chroot applied has to be printed.
- */
-static void
-print_option(struct config_file* cfg, const char* opt, int final)
-{
- if(strcmp(opt, "pidfile") == 0 && final) {
- char *p = fname_after_chroot(cfg->pidfile, cfg, 1);
- if(!p) fatal_exit("out of memory");
- printf("%s\n", p);
- free(p);
- return;
- }
- if(!config_get_option(cfg, opt, config_print_func, stdout))
- fatal_exit("cannot print option '%s'", opt);
-}
-
-/** check if module works with config */
-static void
-check_mod(struct config_file* cfg, struct module_func_block* fb)
-{
- struct module_env env;
- memset(&env, 0, sizeof(env));
- env.cfg = cfg;
- env.scratch = regional_create();
- env.scratch_buffer = sldns_buffer_new(BUFSIZ);
- if(!env.scratch || !env.scratch_buffer)
- fatal_exit("out of memory");
- if(!edns_known_options_init(&env))
- fatal_exit("out of memory");
- if(!(*fb->init)(&env, 0)) {
- fatal_exit("bad config for %s module", fb->name);
- }
- (*fb->deinit)(&env, 0);
- sldns_buffer_free(env.scratch_buffer);
- regional_destroy(env.scratch);
- edns_known_options_delete(&env);
-}
-
-/** check localzones */
-static void
-localzonechecks(struct config_file* cfg)
-{
- struct local_zones* zs;
- if(!(zs = local_zones_create()))
- fatal_exit("out of memory");
- if(!local_zones_apply_cfg(zs, cfg))
- fatal_exit("failed local-zone, local-data configuration");
- local_zones_delete(zs);
-}
-
-/** check view and response-ip configuration */
-static void
-view_and_respipchecks(struct config_file* cfg)
-{
- struct views* views = NULL;
- struct respip_set* respip = NULL;
- int ignored = 0;
- if(!(views = views_create()))
- fatal_exit("Could not create views: out of memory");
- if(!(respip = respip_set_create()))
- fatal_exit("Could not create respip set: out of memory");
- if(!views_apply_cfg(views, cfg))
- fatal_exit("Could not set up views");
- if(!respip_global_apply_cfg(respip, cfg))
- fatal_exit("Could not setup respip set");
- if(!respip_views_apply_cfg(views, cfg, &ignored))
- fatal_exit("Could not setup per-view respip sets");
- views_delete(views);
- respip_set_delete(respip);
-}
-
-/** emit warnings for IP in hosts */
-static void
-warn_hosts(const char* typ, struct config_stub* list)
-{
- struct sockaddr_storage a;
- socklen_t alen;
- struct config_stub* s;
- struct config_strlist* h;
- for(s=list; s; s=s->next) {
- for(h=s->hosts; h; h=h->next) {
- if(extstrtoaddr(h->str, &a, &alen)) {
- fprintf(stderr, "unbound-checkconf: warning:"
- " %s %s: \"%s\" is an IP%s address, "
- "and when looked up as a host name "
- "during use may not resolve.\n",
- s->name, typ, h->str,
- addr_is_ip6(&a, alen)?"6":"4");
- }
- }
- }
-}
-
-/** check interface strings */
-static void
-interfacechecks(struct config_file* cfg)
-{
- int d;
- struct sockaddr_storage a;
- socklen_t alen;
- int i, j;
- for(i=0; i<cfg->num_ifs; i++) {
- if(!extstrtoaddr(cfg->ifs[i], &a, &alen)) {
- fatal_exit("cannot parse interface specified as '%s'",
- cfg->ifs[i]);
- }
- for(j=0; j<cfg->num_ifs; j++) {
- if(i!=j && strcmp(cfg->ifs[i], cfg->ifs[j])==0)
- fatal_exit("interface: %s present twice, "
- "cannot bind same ports twice.",
- cfg->ifs[i]);
- }
- }
- for(i=0; i<cfg->num_out_ifs; i++) {
- if(!ipstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, &a, &alen) &&
- !netblockstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, &a, &alen, &d)) {
- fatal_exit("cannot parse outgoing-interface "
- "specified as '%s'", cfg->out_ifs[i]);
- }
- for(j=0; j<cfg->num_out_ifs; j++) {
- if(i!=j && strcmp(cfg->out_ifs[i], cfg->out_ifs[j])==0)
- fatal_exit("outgoing-interface: %s present "
- "twice, cannot bind same ports twice.",
- cfg->out_ifs[i]);
- }
- }
-}
-
-/** check acl ips */
-static void
-aclchecks(struct config_file* cfg)
-{
- int d;
- struct sockaddr_storage a;
- socklen_t alen;
- struct config_str2list* acl;
- for(acl=cfg->acls; acl; acl = acl->next) {
- if(!netblockstrtoaddr(acl->str, UNBOUND_DNS_PORT, &a, &alen,
- &d)) {
- fatal_exit("cannot parse access control address %s %s",
- acl->str, acl->str2);
- }
- }
-}
-
-/** true if fname is a file */
-static int
-is_file(const char* fname)
-{
- struct stat buf;
- if(stat(fname, &buf) < 0) {
- if(errno==EACCES) {
- printf("warning: no search permission for one of the directories in path: %s\n", fname);
- return 1;
- }
- perror(fname);
- return 0;
- }
- if(S_ISDIR(buf.st_mode)) {
- printf("%s is not a file\n", fname);
- return 0;
- }
- return 1;
-}
-
-/** true if fname is a directory */
-static int
-is_dir(const char* fname)
-{
- struct stat buf;
- if(stat(fname, &buf) < 0) {
- if(errno==EACCES) {
- printf("warning: no search permission for one of the directories in path: %s\n", fname);
- return 1;
- }
- perror(fname);
- return 0;
- }
- if(!(S_ISDIR(buf.st_mode))) {
- printf("%s is not a directory\n", fname);
- return 0;
- }
- return 1;
-}
-
-/** get base dir of a fname */
-static char*
-basedir(char* fname)
-{
- char* rev;
- if(!fname) fatal_exit("out of memory");
- rev = strrchr(fname, '/');
- if(!rev) return NULL;
- if(fname == rev) return NULL;
- rev[0] = 0;
- return fname;
-}
-
-/** check chroot for a file string */
-static void
-check_chroot_string(const char* desc, char** ss,
- const char* chrootdir, struct config_file* cfg)
-{
- char* str = *ss;
- if(str && str[0]) {
- *ss = fname_after_chroot(str, cfg, 1);
- if(!*ss) fatal_exit("out of memory");
- if(!is_file(*ss)) {
- if(chrootdir && chrootdir[0])
- fatal_exit("%s: \"%s\" does not exist in "
- "chrootdir %s", desc, str, chrootdir);
- else
- fatal_exit("%s: \"%s\" does not exist",
- desc, str);
- }
- /* put in a new full path for continued checking */
- free(str);
- }
-}
-
-/** check file list, every file must be inside the chroot location */
-static void
-check_chroot_filelist(const char* desc, struct config_strlist* list,
- const char* chrootdir, struct config_file* cfg)
-{
- struct config_strlist* p;
- for(p=list; p; p=p->next) {
- check_chroot_string(desc, &p->str, chrootdir, cfg);
- }
-}
-
-/** check file list, with wildcard processing */
-static void
-check_chroot_filelist_wild(const char* desc, struct config_strlist* list,
- const char* chrootdir, struct config_file* cfg)
-{
- struct config_strlist* p;
- for(p=list; p; p=p->next) {
-#ifdef HAVE_GLOB
- if(strchr(p->str, '*') || strchr(p->str, '[') ||
- strchr(p->str, '?') || strchr(p->str, '{') ||
- strchr(p->str, '~')) {
- char* s = p->str;
- /* adjust whole pattern for chroot and check later */
- p->str = fname_after_chroot(p->str, cfg, 1);
- free(s);
- } else
-#endif /* HAVE_GLOB */
- check_chroot_string(desc, &p->str, chrootdir, cfg);
- }
-}
-
-/** check configuration for errors */
-static void
-morechecks(struct config_file* cfg, const char* fname)
-{
- warn_hosts("stub-host", cfg->stubs);
- warn_hosts("forward-host", cfg->forwards);
- interfacechecks(cfg);
- aclchecks(cfg);
-
- if(cfg->verbosity < 0)
- fatal_exit("verbosity value < 0");
- if(cfg->num_threads <= 0 || cfg->num_threads > 10000)
- fatal_exit("num_threads value weird");
- if(!cfg->do_ip4 && !cfg->do_ip6)
- fatal_exit("ip4 and ip6 are both disabled, pointless");
- if(!cfg->do_ip6 && cfg->prefer_ip6)
- fatal_exit("cannot prefer and disable ip6, pointless");
- if(!cfg->do_udp && !cfg->do_tcp)
- fatal_exit("udp and tcp are both disabled, pointless");
- if(cfg->edns_buffer_size > cfg->msg_buffer_size)
- fatal_exit("edns-buffer-size larger than msg-buffer-size, "
- "answers will not fit in processing buffer");
-#ifdef UB_ON_WINDOWS
- w_config_adjust_directory(cfg);
-#endif
- if(cfg->chrootdir && cfg->chrootdir[0] &&
- cfg->chrootdir[strlen(cfg->chrootdir)-1] == '/')
- fatal_exit("chootdir %s has trailing slash '/' please remove.",
- cfg->chrootdir);
- if(cfg->chrootdir && cfg->chrootdir[0] &&
- !is_dir(cfg->chrootdir)) {
- fatal_exit("bad chroot directory");
- }
- if(cfg->chrootdir && cfg->chrootdir[0]) {
- char buf[10240];
- buf[0] = 0;
- if(fname[0] != '/') {
- if(getcwd(buf, sizeof(buf)) == NULL)
- fatal_exit("getcwd: %s", strerror(errno));
- (void)strlcat(buf, "/", sizeof(buf));
- }
- (void)strlcat(buf, fname, sizeof(buf));
- if(strncmp(buf, cfg->chrootdir, strlen(cfg->chrootdir)) != 0)
- fatal_exit("config file %s is not inside chroot %s",
- buf, cfg->chrootdir);
- }
- if(cfg->directory && cfg->directory[0]) {
- char* ad = fname_after_chroot(cfg->directory, cfg, 0);
- if(!ad) fatal_exit("out of memory");
- if(!is_dir(ad)) fatal_exit("bad chdir directory");
- free(ad);
- }
- if( (cfg->chrootdir && cfg->chrootdir[0]) ||
- (cfg->directory && cfg->directory[0])) {
- if(cfg->pidfile && cfg->pidfile[0]) {
- char* ad = (cfg->pidfile[0]=='/')?strdup(cfg->pidfile):
- fname_after_chroot(cfg->pidfile, cfg, 1);
- char* bd = basedir(ad);
- if(bd && !is_dir(bd))
- fatal_exit("pidfile directory does not exist");
- free(ad);
- }
- if(cfg->logfile && cfg->logfile[0]) {
- char* ad = fname_after_chroot(cfg->logfile, cfg, 1);
- char* bd = basedir(ad);
- if(bd && !is_dir(bd))
- fatal_exit("logfile directory does not exist");
- free(ad);
- }
- }
-
- check_chroot_filelist("file with root-hints",
- cfg->root_hints, cfg->chrootdir, cfg);
- check_chroot_filelist("trust-anchor-file",
- cfg->trust_anchor_file_list, cfg->chrootdir, cfg);
- check_chroot_filelist("auto-trust-anchor-file",
- cfg->auto_trust_anchor_file_list, cfg->chrootdir, cfg);
- check_chroot_filelist_wild("trusted-keys-file",
- cfg->trusted_keys_file_list, cfg->chrootdir, cfg);
- check_chroot_string("dlv-anchor-file", &cfg->dlv_anchor_file,
- cfg->chrootdir, cfg);
- /* remove chroot setting so that modules are not stripping pathnames*/
- free(cfg->chrootdir);
- cfg->chrootdir = NULL;
-
- /* There should be no reason for 'respip' module not to work with
- * dns64, but it's not explicitly confirmed, so the combination is
- * excluded below. It's simply unknown yet for the combination of
- * respip and other modules. */
- if(strcmp(cfg->module_conf, "iterator") != 0
- && strcmp(cfg->module_conf, "validator iterator") != 0
- && strcmp(cfg->module_conf, "dns64 validator iterator") != 0
- && strcmp(cfg->module_conf, "dns64 iterator") != 0
- && strcmp(cfg->module_conf, "respip iterator") != 0
- && strcmp(cfg->module_conf, "respip validator iterator") != 0
-#ifdef WITH_PYTHONMODULE
- && strcmp(cfg->module_conf, "python iterator") != 0
- && strcmp(cfg->module_conf, "python validator iterator") != 0
- && strcmp(cfg->module_conf, "validator python iterator") != 0
- && strcmp(cfg->module_conf, "dns64 python iterator") != 0
- && strcmp(cfg->module_conf, "dns64 python validator iterator") != 0
- && strcmp(cfg->module_conf, "dns64 validator python iterator") != 0
- && strcmp(cfg->module_conf, "python dns64 iterator") != 0
- && strcmp(cfg->module_conf, "python dns64 validator iterator") != 0
-#endif
-#ifdef USE_CACHEDB
- && strcmp(cfg->module_conf, "validator cachedb iterator") != 0
- && strcmp(cfg->module_conf, "cachedb iterator") != 0
- && strcmp(cfg->module_conf, "dns64 validator cachedb iterator") != 0
- && strcmp(cfg->module_conf, "dns64 cachedb iterator") != 0
-#endif
-#if defined(WITH_PYTHONMODULE) && defined(USE_CACHEDB)
- && strcmp(cfg->module_conf, "python dns64 cachedb iterator") != 0
- && strcmp(cfg->module_conf, "python dns64 validator cachedb iterator") != 0
- && strcmp(cfg->module_conf, "dns64 python cachedb iterator") != 0
- && strcmp(cfg->module_conf, "dns64 python validator cachedb iterator") != 0
- && strcmp(cfg->module_conf, "python cachedb iterator") != 0
- && strcmp(cfg->module_conf, "python validator cachedb iterator") != 0
- && strcmp(cfg->module_conf, "cachedb python iterator") != 0
- && strcmp(cfg->module_conf, "validator cachedb python iterator") != 0
- && strcmp(cfg->module_conf, "validator python cachedb iterator") != 0
-#endif
-#ifdef CLIENT_SUBNET
- && strcmp(cfg->module_conf, "subnetcache iterator") != 0
- && strcmp(cfg->module_conf, "subnetcache validator iterator") != 0
-#endif
-#if defined(WITH_PYTHONMODULE) && defined(CLIENT_SUBNET)
- && strcmp(cfg->module_conf, "python subnetcache iterator") != 0
- && strcmp(cfg->module_conf, "subnetcache python iterator") != 0
- && strcmp(cfg->module_conf, "subnetcache validator iterator") != 0
- && strcmp(cfg->module_conf, "python subnetcache validator iterator") != 0
- && strcmp(cfg->module_conf, "subnetcache python validator iterator") != 0
- && strcmp(cfg->module_conf, "subnetcache validator python iterator") != 0
-#endif
- ) {
- fatal_exit("module conf '%s' is not known to work",
- cfg->module_conf);
- }
-
-#ifdef HAVE_GETPWNAM
- if(cfg->username && cfg->username[0]) {
- if(getpwnam(cfg->username) == NULL)
- fatal_exit("user '%s' does not exist.", cfg->username);
-# ifdef HAVE_ENDPWENT
- endpwent();
-# endif
- }
-#endif
- if(cfg->remote_control_enable && cfg->remote_control_use_cert) {
- check_chroot_string("server-key-file", &cfg->server_key_file,
- cfg->chrootdir, cfg);
- check_chroot_string("server-cert-file", &cfg->server_cert_file,
- cfg->chrootdir, cfg);
- if(!is_file(cfg->control_key_file))
- fatal_exit("control-key-file: \"%s\" does not exist",
- cfg->control_key_file);
- if(!is_file(cfg->control_cert_file))
- fatal_exit("control-cert-file: \"%s\" does not exist",
- cfg->control_cert_file);
- }
-
- localzonechecks(cfg);
- view_and_respipchecks(cfg);
-}
-
-/** check forwards */
-static void
-check_fwd(struct config_file* cfg)
-{
- struct iter_forwards* fwd = forwards_create();
- if(!fwd || !forwards_apply_cfg(fwd, cfg)) {
- fatal_exit("Could not set forward zones");
- }
- forwards_delete(fwd);
-}
-
-/** check hints */
-static void
-check_hints(struct config_file* cfg)
-{
- struct iter_hints* hints = hints_create();
- if(!hints || !hints_apply_cfg(hints, cfg)) {
- fatal_exit("Could not set root or stub hints");
- }
- hints_delete(hints);
-}
-
-/** check config file */
-static void
-checkconf(const char* cfgfile, const char* opt, int final)
-{
- char oldwd[4096];
- struct config_file* cfg = config_create();
- if(!cfg)
- fatal_exit("out of memory");
- oldwd[0] = 0;
- if(!getcwd(oldwd, sizeof(oldwd))) {
- log_err("cannot getcwd: %s", strerror(errno));
- oldwd[0] = 0;
- }
- if(!config_read(cfg, cfgfile, NULL)) {
- /* config_read prints messages to stderr */
- config_delete(cfg);
- exit(1);
- }
- if(oldwd[0] && chdir(oldwd) == -1)
- log_err("cannot chdir(%s): %s", oldwd, strerror(errno));
- if(opt) {
- print_option(cfg, opt, final);
- config_delete(cfg);
- return;
- }
- morechecks(cfg, cfgfile);
- check_mod(cfg, iter_get_funcblock());
- check_mod(cfg, val_get_funcblock());
-#ifdef WITH_PYTHONMODULE
- if(strstr(cfg->module_conf, "python"))
- check_mod(cfg, pythonmod_get_funcblock());
-#endif
- check_fwd(cfg);
- check_hints(cfg);
- printf("unbound-checkconf: no errors in %s\n", cfgfile);
- config_delete(cfg);
-}
-
-/** getopt global, in case header files fail to declare it. */
-extern int optind;
-/** getopt global, in case header files fail to declare it. */
-extern char* optarg;
-
-/** Main routine for checkconf */
-int main(int argc, char* argv[])
-{
- int c;
- int final = 0;
- const char* f;
- const char* opt = NULL;
- const char* cfgfile = CONFIGFILE;
- log_ident_set("unbound-checkconf");
- log_init(NULL, 0, NULL);
- checklock_start();
-#ifdef USE_WINSOCK
- /* use registry config file in preference to compiletime location */
- if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile")))
- cfgfile = CONFIGFILE;
-#endif /* USE_WINSOCK */
- /* parse the options */
- while( (c=getopt(argc, argv, "fho:")) != -1) {
- switch(c) {
- case 'f':
- final = 1;
- break;
- case 'o':
- opt = optarg;
- break;
- case '?':
- case 'h':
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
- if(argc != 0 && argc != 1)
- usage();
- if(argc == 1)
- f = argv[0];
- else f = cfgfile;
- checkconf(f, opt, final);
- checklock_stop();
- return 0;
-}
diff --git a/external/unbound/smallapp/unbound-control-setup.sh.in b/external/unbound/smallapp/unbound-control-setup.sh.in
deleted file mode 100644
index 0d759f441..000000000
--- a/external/unbound/smallapp/unbound-control-setup.sh.in
+++ /dev/null
@@ -1,160 +0,0 @@
-#!/bin/sh
-#
-# unbound-control-setup.sh - set up SSL certificates for unbound-control
-#
-# Copyright (c) 2008, NLnet Labs. All rights reserved.
-#
-# This software is open source.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-#
-# Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# Neither the name of the NLNET LABS nor the names of its contributors may
-# be used to endorse or promote products derived from this software without
-# specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# settings:
-
-# directory for files
-DESTDIR=@ub_conf_dir@
-
-# issuer and subject name for certificates
-SERVERNAME=unbound
-CLIENTNAME=unbound-control
-
-# validity period for certificates
-DAYS=7200
-
-# size of keys in bits
-BITS=3072
-
-# hash algorithm
-HASH=sha256
-
-# base name for unbound server keys
-SVR_BASE=unbound_server
-
-# base name for unbound-control keys
-CTL_BASE=unbound_control
-
-# we want -rw-r----- access (say you run this as root: grp=yes (server), all=no).
-umask 0027
-
-# end of options
-
-# functions:
-error ( ) {
- echo "$0 fatal error: $1"
- exit 1
-}
-
-# check arguments:
-while test $# -ne 0; do
- case $1 in
- -d)
- if test $# -eq 1; then error "need argument for -d"; fi
- DESTDIR="$2"
- shift
- ;;
- *)
- echo "unbound-control-setup.sh - setup SSL keys for unbound-control"
- echo " -d dir use directory to store keys and certificates."
- echo " default: $DESTDIR"
- echo "please run this command using the same user id that the "
- echo "unbound daemon uses, it needs read privileges."
- exit 1
- ;;
- esac
- shift
-done
-
-# go!:
-echo "setup in directory $DESTDIR"
-cd "$DESTDIR" || error "could not cd to $DESTDIR"
-
-# create certificate keys; do not recreate if they already exist.
-if test -f $SVR_BASE.key; then
- echo "$SVR_BASE.key exists"
-else
- echo "generating $SVR_BASE.key"
- openssl genrsa -out $SVR_BASE.key $BITS || error "could not genrsa"
-fi
-if test -f $CTL_BASE.key; then
- echo "$CTL_BASE.key exists"
-else
- echo "generating $CTL_BASE.key"
- openssl genrsa -out $CTL_BASE.key $BITS || error "could not genrsa"
-fi
-
-# create self-signed cert for server
-echo "[req]" > request.cfg
-echo "default_bits=$BITS" >> request.cfg
-echo "default_md=$HASH" >> request.cfg
-echo "prompt=no" >> request.cfg
-echo "distinguished_name=req_distinguished_name" >> request.cfg
-echo "" >> request.cfg
-echo "[req_distinguished_name]" >> request.cfg
-echo "commonName=$SERVERNAME" >> request.cfg
-
-test -f request.cfg || error "could not create request.cfg"
-
-echo "create $SVR_BASE.pem (self signed certificate)"
-openssl req -key $SVR_BASE.key -config request.cfg -new -x509 -days $DAYS -out $SVR_BASE.pem || error "could not create $SVR_BASE.pem"
-# create trusted usage pem
-openssl x509 -in $SVR_BASE.pem -addtrust serverAuth -out $SVR_BASE"_trust.pem"
-
-# create client request and sign it, piped
-echo "[req]" > request.cfg
-echo "default_bits=$BITS" >> request.cfg
-echo "default_md=$HASH" >> request.cfg
-echo "prompt=no" >> request.cfg
-echo "distinguished_name=req_distinguished_name" >> request.cfg
-echo "" >> request.cfg
-echo "[req_distinguished_name]" >> request.cfg
-echo "commonName=$CLIENTNAME" >> request.cfg
-
-test -f request.cfg || error "could not create request.cfg"
-
-echo "create $CTL_BASE.pem (signed client certificate)"
-openssl req -key $CTL_BASE.key -config request.cfg -new | openssl x509 -req -days $DAYS -CA $SVR_BASE"_trust.pem" -CAkey $SVR_BASE.key -CAcreateserial -$HASH -out $CTL_BASE.pem
-test -f $CTL_BASE.pem || error "could not create $CTL_BASE.pem"
-# create trusted usage pem
-# openssl x509 -in $CTL_BASE.pem -addtrust clientAuth -out $CTL_BASE"_trust.pem"
-
-# see details with openssl x509 -noout -text < $SVR_BASE.pem
-# echo "create $CTL_BASE""_browser.pfx (web client certificate)"
-# echo "create webbrowser PKCS#12 .PFX certificate file. In Firefox import in:"
-# echo "preferences - advanced - encryption - view certificates - your certs"
-# echo "empty password is used, simply click OK on the password dialog box."
-# openssl pkcs12 -export -in $CTL_BASE"_trust.pem" -inkey $CTL_BASE.key -name "unbound remote control client cert" -out $CTL_BASE"_browser.pfx" -password "pass:" || error "could not create browser certificate"
-
-# remove unused permissions
-chmod o-rw $SVR_BASE.pem $SVR_BASE.key $CTL_BASE.pem $CTL_BASE.key
-
-# remove crap
-rm -f request.cfg
-rm -f $CTL_BASE"_trust.pem" $SVR_BASE"_trust.pem" $SVR_BASE"_trust.srl"
-
-echo "Setup success. Certificates created. Enable in unbound.conf file to use"
-
-exit 0
diff --git a/external/unbound/smallapp/unbound-control.c b/external/unbound/smallapp/unbound-control.c
deleted file mode 100644
index 6cd4e7086..000000000
--- a/external/unbound/smallapp/unbound-control.c
+++ /dev/null
@@ -1,791 +0,0 @@
-/*
- * checkconf/unbound-control.c - remote control utility for unbound.
- *
- * Copyright (c) 2008, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * The remote control utility contacts the unbound server over ssl and
- * sends the command, receives the answer, and displays the result
- * from the commandline.
- */
-
-#include "config.h"
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#ifdef HAVE_OPENSSL_SSL_H
-#include <openssl/ssl.h>
-#endif
-#ifdef HAVE_OPENSSL_ERR_H
-#include <openssl/err.h>
-#endif
-#ifdef HAVE_OPENSSL_RAND_H
-#include <openssl/rand.h>
-#endif
-#include "util/log.h"
-#include "util/config_file.h"
-#include "util/locks.h"
-#include "util/net_help.h"
-#include "util/shm_side/shm_main.h"
-#include "daemon/stats.h"
-#include "sldns/wire2str.h"
-#include "sldns/pkthdr.h"
-
-#ifdef HAVE_SYS_IPC_H
-#include "sys/ipc.h"
-#endif
-#ifdef HAVE_SYS_SHM_H
-#include "sys/shm.h"
-#endif
-#ifdef HAVE_SYS_UN_H
-#include <sys/un.h>
-#endif
-
-/** Give unbound-control usage, and exit (1). */
-static void
-usage(void)
-{
- printf("Usage: unbound-control [options] command\n");
- printf(" Remote control utility for unbound server.\n");
- 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");
- printf(" stop stops the server\n");
- printf(" reload reloads the server\n");
- printf(" (this flushes data, stats, requestlist)\n");
- printf(" stats print statistics\n");
- printf(" stats_noreset peek at statistics\n");
-#ifdef HAVE_SHMGET
- printf(" stats_shm print statistics using shm\n");
-#endif
- printf(" status display status of server\n");
- printf(" verbosity <number> change logging detail\n");
- printf(" log_reopen close and open the logfile\n");
- printf(" local_zone <name> <type> add new local zone\n");
- printf(" local_zone_remove <name> remove local zone and its contents\n");
- printf(" local_data <RR data...> add local data, for example\n");
- printf(" local_data www.example.com A 192.0.2.1\n");
- printf(" local_data_remove <name> remove local RR data from name\n");
- printf(" local_zones, local_zones_remove, local_datas, local_datas_remove\n");
- printf(" same, but read list from stdin\n");
- printf(" (one entry per line).\n");
- printf(" dump_cache print cache to stdout\n");
- printf(" load_cache load cache from stdin\n");
- printf(" lookup <name> print nameservers for name\n");
- printf(" flush <name> flushes common types for name from cache\n");
- printf(" types: A, AAAA, MX, PTR, NS,\n");
- printf(" SOA, CNAME, DNAME, SRV, NAPTR\n");
- 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_negative flush all negative 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 by first thread\n");
- printf(" flush_infra [all | ip] remove ping, edns for one IP or all\n");
- printf(" dump_infra show ping and edns entries\n");
- printf(" set_option opt: val set option to value, no reload\n");
- printf(" get_option opt get option value\n");
- printf(" list_stubs list stub-zones and root hints in use\n");
- printf(" list_forwards list forward-zones in use\n");
- printf(" list_insecure list domain-insecure zones\n");
- printf(" list_local_zones list local-zones in use\n");
- printf(" list_local_data list local-data RRs in use\n");
- printf(" insecure_add zone add domain-insecure zone\n");
- printf(" insecure_remove zone remove domain-insecure zone\n");
- printf(" forward_add [+i] zone addr.. add forward-zone with servers\n");
- printf(" forward_remove [+i] zone remove forward zone\n");
- printf(" stub_add [+ip] zone addr.. add stub-zone with servers\n");
- printf(" stub_remove [+i] zone remove stub zone\n");
- printf(" +i also do dnssec insecure point\n");
- printf(" +p set stub to use priming\n");
- printf(" forward [off | addr ...] without arg show forward setup\n");
- printf(" or off to turn off root forwarding\n");
- printf(" or give list of ip addresses\n");
- printf(" ratelimit_list [+a] list ratelimited domains\n");
- printf(" ip_ratelimit_list [+a] list ratelimited ip addresses\n");
- printf(" +a list all, also not ratelimited\n");
- printf(" view_list_local_zones view list local-zones in view\n");
- printf(" view_list_local_data view list local-data RRs in view\n");
- printf(" view_local_zone view name type add local-zone in view\n");
- printf(" view_local_zone_remove view name remove local-zone in view\n");
- printf(" view_local_data view RR... add local-data in view\n");
- printf(" view_local_data_remove view name remove local-data in view\n");
- printf("Version %s\n", PACKAGE_VERSION);
- printf("BSD licensed, see LICENSE in source package for details.\n");
- printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
- exit(1);
-}
-
-#ifdef HAVE_SHMGET
-/** what to put on statistics lines between var and value, ": " or "=" */
-#define SQ "="
-/** if true, inhibits a lot of =0 lines from the stats output */
-static const int inhibit_zero = 1;
-/** divide sum of timers to get average */
-static void
-timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)
-{
-#ifndef S_SPLINT_S
- size_t leftover;
- if(d == 0) {
- avg->tv_sec = 0;
- avg->tv_usec = 0;
- return;
- }
- avg->tv_sec = sum->tv_sec / d;
- avg->tv_usec = sum->tv_usec / d;
- /* handle fraction from seconds divide */
- leftover = sum->tv_sec - avg->tv_sec*d;
- avg->tv_usec += (leftover*1000000)/d;
-#endif
-}
-
-/** print unsigned long stats value */
-#define PR_UL_NM(str, var) printf("%s."str SQ"%lu\n", nm, (unsigned long)(var));
-#define PR_UL(str, var) printf(str SQ"%lu\n", (unsigned long)(var));
-#define PR_UL_SUB(str, nm, var) printf(str".%s"SQ"%lu\n", nm, (unsigned long)(var));
-#define PR_TIMEVAL(str, var) printf(str SQ ARG_LL "d.%6.6d\n", \
- (long long)var.tv_sec, (int)var.tv_usec);
-#define PR_LL(str, var) printf(str SQ ARG_LL"d\n", (long long)(var));
-
-/** print stat block */
-static void pr_stats(const char* nm, struct stats_info* s)
-{
- struct timeval avg;
- PR_UL_NM("num.queries", s->svr.num_queries);
- PR_UL_NM("num.queries_ip_ratelimited",
- s->svr.num_queries_ip_ratelimited);
- PR_UL_NM("num.cachehits",
- s->svr.num_queries - s->svr.num_queries_missed_cache);
- PR_UL_NM("num.cachemiss", s->svr.num_queries_missed_cache);
- PR_UL_NM("num.prefetch", s->svr.num_queries_prefetch);
- PR_UL_NM("num.zero_ttl", s->svr.zero_ttl_responses);
- PR_UL_NM("num.recursivereplies", s->mesh_replies_sent);
-#ifdef USE_DNSCRYPT
- PR_UL_NM("num.dnscrypt.crypted", s->svr.num_query_dnscrypt_crypted);
- PR_UL_NM("num.dnscrypt.cert", s->svr.num_query_dnscrypt_cert);
- PR_UL_NM("num.dnscrypt.cleartext", s->svr.num_query_dnscrypt_cleartext);
- PR_UL_NM("num.dnscrypt.malformed",
- s->svr.num_query_dnscrypt_crypted_malformed);
-#endif
- printf("%s.requestlist.avg"SQ"%g\n", nm,
- (s->svr.num_queries_missed_cache+s->svr.num_queries_prefetch)?
- (double)s->svr.sum_query_list_size/
- (s->svr.num_queries_missed_cache+
- s->svr.num_queries_prefetch) : 0.0);
- PR_UL_NM("requestlist.max", s->svr.max_query_list_size);
- PR_UL_NM("requestlist.overwritten", s->mesh_jostled);
- PR_UL_NM("requestlist.exceeded", s->mesh_dropped);
- PR_UL_NM("requestlist.current.all", s->mesh_num_states);
- PR_UL_NM("requestlist.current.user", s->mesh_num_reply_states);
- timeval_divide(&avg, &s->mesh_replies_sum_wait, s->mesh_replies_sent);
- printf("%s.", nm);
- PR_TIMEVAL("recursion.time.avg", avg);
- printf("%s.recursion.time.median"SQ"%g\n", nm, s->mesh_time_median);
- PR_UL_NM("tcpusage", s->svr.tcp_accept_usage);
-}
-
-/** print uptime */
-static void print_uptime(struct shm_stat_info* shm_stat)
-{
- PR_TIMEVAL("time.now", shm_stat->time.now);
- PR_TIMEVAL("time.up", shm_stat->time.up);
- PR_TIMEVAL("time.elapsed", shm_stat->time.elapsed);
-}
-
-/** print memory usage */
-static void print_mem(struct shm_stat_info* shm_stat)
-{
- PR_LL("mem.cache.rrset", shm_stat->mem.rrset);
- PR_LL("mem.cache.message", shm_stat->mem.msg);
- PR_LL("mem.cache.iterator", shm_stat->mem.iter);
- PR_LL("mem.cache.validator", shm_stat->mem.val);
-#ifdef CLIENT_SUBNET
- PR_LL("mem.cache.subnet", shm_stat->mem.subnet);
-#endif
-}
-
-/** print histogram */
-static void print_hist(struct stats_info* s)
-{
- struct timehist* hist;
- size_t i;
- hist = timehist_setup();
- if(!hist)
- fatal_exit("out of memory");
- timehist_import(hist, s->svr.hist, NUM_BUCKETS_HIST);
- for(i=0; i<hist->num; i++) {
- printf("histogram.%6.6d.%6.6d.to.%6.6d.%6.6d=%lu\n",
- (int)hist->buckets[i].lower.tv_sec,
- (int)hist->buckets[i].lower.tv_usec,
- (int)hist->buckets[i].upper.tv_sec,
- (int)hist->buckets[i].upper.tv_usec,
- (unsigned long)hist->buckets[i].count);
- }
- timehist_delete(hist);
-}
-
-/** print extended */
-static void print_extended(struct stats_info* s)
-{
- int i;
- char nm[16];
-
- /* TYPE */
- for(i=0; i<STATS_QTYPE_NUM; i++) {
- if(inhibit_zero && s->svr.qtype[i] == 0)
- continue;
- sldns_wire2str_type_buf((uint16_t)i, nm, sizeof(nm));
- PR_UL_SUB("num.query.type", nm, s->svr.qtype[i]);
- }
- if(!inhibit_zero || s->svr.qtype_big) {
- PR_UL("num.query.type.other", s->svr.qtype_big);
- }
-
- /* CLASS */
- for(i=0; i<STATS_QCLASS_NUM; i++) {
- if(inhibit_zero && s->svr.qclass[i] == 0)
- continue;
- sldns_wire2str_class_buf((uint16_t)i, nm, sizeof(nm));
- PR_UL_SUB("num.query.class", nm, s->svr.qclass[i]);
- }
- if(!inhibit_zero || s->svr.qclass_big) {
- PR_UL("num.query.class.other", s->svr.qclass_big);
- }
-
- /* OPCODE */
- for(i=0; i<STATS_OPCODE_NUM; i++) {
- if(inhibit_zero && s->svr.qopcode[i] == 0)
- continue;
- sldns_wire2str_opcode_buf(i, nm, sizeof(nm));
- PR_UL_SUB("num.query.opcode", nm, s->svr.qopcode[i]);
- }
-
- /* transport */
- PR_UL("num.query.tcp", s->svr.qtcp);
- PR_UL("num.query.tcpout", s->svr.qtcp_outgoing);
- PR_UL("num.query.ipv6", s->svr.qipv6);
-
- /* flags */
- PR_UL("num.query.flags.QR", s->svr.qbit_QR);
- PR_UL("num.query.flags.AA", s->svr.qbit_AA);
- PR_UL("num.query.flags.TC", s->svr.qbit_TC);
- PR_UL("num.query.flags.RD", s->svr.qbit_RD);
- PR_UL("num.query.flags.RA", s->svr.qbit_RA);
- PR_UL("num.query.flags.Z", s->svr.qbit_Z);
- PR_UL("num.query.flags.AD", s->svr.qbit_AD);
- PR_UL("num.query.flags.CD", s->svr.qbit_CD);
- PR_UL("num.query.edns.present", s->svr.qEDNS);
- PR_UL("num.query.edns.DO", s->svr.qEDNS_DO);
-
- /* RCODE */
- for(i=0; i<STATS_RCODE_NUM; i++) {
- /* Always include RCODEs 0-5 */
- if(inhibit_zero && i > LDNS_RCODE_REFUSED && s->svr.ans_rcode[i] == 0)
- continue;
- sldns_wire2str_rcode_buf(i, nm, sizeof(nm));
- PR_UL_SUB("num.answer.rcode", nm, s->svr.ans_rcode[i]);
- }
- if(!inhibit_zero || s->svr.ans_rcode_nodata) {
- PR_UL("num.answer.rcode.nodata", s->svr.ans_rcode_nodata);
- }
- /* validation */
- PR_UL("num.answer.secure", s->svr.ans_secure);
- PR_UL("num.answer.bogus", s->svr.ans_bogus);
- PR_UL("num.rrset.bogus", s->svr.rrset_bogus);
- /* threat detection */
- PR_UL("unwanted.queries", s->svr.unwanted_queries);
- PR_UL("unwanted.replies", s->svr.unwanted_replies);
- /* cache counts */
- PR_UL("msg.cache.count", s->svr.msg_cache_count);
- PR_UL("rrset.cache.count", s->svr.rrset_cache_count);
- PR_UL("infra.cache.count", s->svr.infra_cache_count);
- PR_UL("key.cache.count", s->svr.key_cache_count);
-}
-
-/** print statistics out of memory structures */
-static void do_stats_shm(struct config_file* cfg, struct stats_info* stats,
- struct shm_stat_info* shm_stat)
-{
- int i;
- char nm[16];
- for(i=0; i<cfg->num_threads; i++) {
- snprintf(nm, sizeof(nm), "thread%d", i);
- pr_stats(nm, &stats[i+1]);
- }
- pr_stats("total", &stats[0]);
- print_uptime(shm_stat);
- if(cfg->stat_extended) {
- print_mem(shm_stat);
- print_hist(stats);
- print_extended(stats);
- }
-}
-#endif /* HAVE_SHMGET */
-
-/** print statistics from shm memory segment */
-static void print_stats_shm(const char* cfgfile)
-{
-#ifdef HAVE_SHMGET
- struct config_file* cfg;
- struct stats_info* stats;
- struct shm_stat_info* shm_stat;
- int id_ctl, id_arr;
- /* read config */
- if(!(cfg = config_create()))
- fatal_exit("out of memory");
- if(!config_read(cfg, cfgfile, NULL))
- fatal_exit("could not read config file");
- /* get shm segments */
- id_ctl = shmget(cfg->shm_key, sizeof(int), SHM_R|SHM_W);
- if(id_ctl == -1) {
- fatal_exit("shmget(%d): %s", cfg->shm_key, strerror(errno));
- }
- id_arr = shmget(cfg->shm_key+1, sizeof(int), SHM_R|SHM_W);
- if(id_arr == -1) {
- fatal_exit("shmget(%d): %s", cfg->shm_key+1, strerror(errno));
- }
- shm_stat = (struct shm_stat_info*)shmat(id_ctl, NULL, 0);
- if(shm_stat == (void*)-1) {
- fatal_exit("shmat(%d): %s", id_ctl, strerror(errno));
- }
- stats = (struct stats_info*)shmat(id_arr, NULL, 0);
- if(stats == (void*)-1) {
- fatal_exit("shmat(%d): %s", id_arr, strerror(errno));
- }
-
- /* print the stats */
- do_stats_shm(cfg, stats, shm_stat);
-
- /* shutdown */
- shmdt(shm_stat);
- shmdt(stats);
- config_delete(cfg);
-#else
- (void)cfgfile;
-#endif /* HAVE_SHMGET */
-}
-
-/** exit with ssl error */
-static void ssl_err(const char* s)
-{
- fprintf(stderr, "error: %s\n", s);
- ERR_print_errors_fp(stderr);
- exit(1);
-}
-
-/** setup SSL context */
-static SSL_CTX*
-setup_ctx(struct config_file* cfg)
-{
- char* s_cert=NULL, *c_key=NULL, *c_cert=NULL;
- SSL_CTX* ctx;
-
- if(cfg->remote_control_use_cert) {
- s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1);
- c_key = fname_after_chroot(cfg->control_key_file, cfg, 1);
- c_cert = fname_after_chroot(cfg->control_cert_file, cfg, 1);
- if(!s_cert || !c_key || !c_cert)
- fatal_exit("out of memory");
- }
- ctx = SSL_CTX_new(SSLv23_client_method());
- if(!ctx)
- ssl_err("could not allocate SSL_CTX pointer");
- if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
- != SSL_OP_NO_SSLv2)
- ssl_err("could not set SSL_OP_NO_SSLv2");
- if(cfg->remote_control_use_cert) {
- if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
- != SSL_OP_NO_SSLv3)
- ssl_err("could not set SSL_OP_NO_SSLv3");
- if(!SSL_CTX_use_certificate_chain_file(ctx,c_cert) ||
- !SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM)
- || !SSL_CTX_check_private_key(ctx))
- ssl_err("Error setting up SSL_CTX client key and cert");
- if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
- ssl_err("Error setting up SSL_CTX verify, server cert");
- SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
-
- free(s_cert);
- free(c_key);
- free(c_cert);
- } else {
- /* Use ciphers that don't require authentication */
-#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
- SSL_CTX_set_security_level(ctx, 0);
-#endif
- if(!SSL_CTX_set_cipher_list(ctx, "aNULL, eNULL"))
- ssl_err("Error setting NULL cipher!");
- }
- return ctx;
-}
-
-/** contact the server with TCP connect */
-static int
-contact_server(const char* svr, struct config_file* cfg, int statuscmd)
-{
- struct sockaddr_storage addr;
- socklen_t addrlen;
- int addrfamily = 0;
- int fd;
- /* use svr or the first config entry */
- if(!svr) {
- if(cfg->control_ifs) {
- svr = cfg->control_ifs->str;
- } else if(cfg->do_ip4) {
- svr = "127.0.0.1";
- } else {
- svr = "::1";
- }
- /* config 0 addr (everything), means ask localhost */
- if(strcmp(svr, "0.0.0.0") == 0)
- svr = "127.0.0.1";
- else if(strcmp(svr, "::0") == 0 ||
- strcmp(svr, "0::0") == 0 ||
- strcmp(svr, "0::") == 0 ||
- strcmp(svr, "::") == 0)
- svr = "::1";
- }
- if(strchr(svr, '@')) {
- if(!extstrtoaddr(svr, &addr, &addrlen))
- fatal_exit("could not parse IP@port: %s", svr);
-#ifdef HAVE_SYS_UN_H
- } else if(svr[0] == '/') {
- struct sockaddr_un* usock = (struct sockaddr_un *) &addr;
- usock->sun_family = AF_LOCAL;
-#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
- usock->sun_len = (unsigned)sizeof(usock);
-#endif
- (void)strlcpy(usock->sun_path, svr, sizeof(usock->sun_path));
- addrlen = (socklen_t)sizeof(struct sockaddr_un);
- addrfamily = AF_LOCAL;
-#endif
- } else {
- if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen))
- fatal_exit("could not parse IP: %s", svr);
- }
-
- if(addrfamily == 0)
- addrfamily = addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET;
- fd = socket(addrfamily, SOCK_STREAM, 0);
- if(fd == -1) {
-#ifndef USE_WINSOCK
- fatal_exit("socket: %s", strerror(errno));
-#else
- fatal_exit("socket: %s", wsa_strerror(WSAGetLastError()));
-#endif
- }
- if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
-#ifndef USE_WINSOCK
- log_err_addr("connect", strerror(errno), &addr, addrlen);
- if(errno == ECONNREFUSED && statuscmd) {
- printf("unbound is stopped\n");
- exit(3);
- }
-#else
- log_err_addr("connect", wsa_strerror(WSAGetLastError()), &addr, addrlen);
- if(WSAGetLastError() == WSAECONNREFUSED && statuscmd) {
- printf("unbound is stopped\n");
- exit(3);
- }
-#endif
- exit(1);
- }
- return fd;
-}
-
-/** setup SSL on the connection */
-static SSL*
-setup_ssl(SSL_CTX* ctx, int fd, struct config_file* cfg)
-{
- SSL* ssl;
- X509* x;
- int r;
-
- ssl = SSL_new(ctx);
- if(!ssl)
- ssl_err("could not SSL_new");
- SSL_set_connect_state(ssl);
- (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
- if(!SSL_set_fd(ssl, fd))
- ssl_err("could not SSL_set_fd");
- while(1) {
- ERR_clear_error();
- if( (r=SSL_do_handshake(ssl)) == 1)
- break;
- r = SSL_get_error(ssl, r);
- if(r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
- ssl_err("SSL handshake failed");
- /* wants to be called again */
- }
-
- /* check authenticity of server */
- if(SSL_get_verify_result(ssl) != X509_V_OK)
- ssl_err("SSL verification failed");
- if(cfg->remote_control_use_cert) {
- x = SSL_get_peer_certificate(ssl);
- if(!x)
- ssl_err("Server presented no peer certificate");
- X509_free(x);
- }
-
- return ssl;
-}
-
-/** send stdin to server */
-static void
-send_file(SSL* ssl, FILE* in, char* buf, size_t sz)
-{
- while(fgets(buf, (int)sz, in)) {
- if(SSL_write(ssl, buf, (int)strlen(buf)) <= 0)
- ssl_err("could not SSL_write contents");
- }
-}
-
-/** send end-of-file marker to server */
-static void
-send_eof(SSL* ssl)
-{
- char e[] = {0x04, 0x0a};
- if(SSL_write(ssl, e, (int)sizeof(e)) <= 0)
- ssl_err("could not SSL_write end-of-file marker");
-}
-
-/** send command and display result */
-static int
-go_cmd(SSL* ssl, int quiet, int argc, char* argv[])
-{
- char pre[10];
- const char* space=" ";
- const char* newline="\n";
- int was_error = 0, first_line = 1;
- int r, i;
- char buf[1024];
- snprintf(pre, sizeof(pre), "UBCT%d ", UNBOUND_CONTROL_VERSION);
- if(SSL_write(ssl, pre, (int)strlen(pre)) <= 0)
- ssl_err("could not SSL_write");
- for(i=0; i<argc; i++) {
- if(SSL_write(ssl, space, (int)strlen(space)) <= 0)
- ssl_err("could not SSL_write");
- if(SSL_write(ssl, argv[i], (int)strlen(argv[i])) <= 0)
- ssl_err("could not SSL_write");
- }
- if(SSL_write(ssl, newline, (int)strlen(newline)) <= 0)
- ssl_err("could not SSL_write");
-
- if(argc == 1 && strcmp(argv[0], "load_cache") == 0) {
- send_file(ssl, stdin, buf, sizeof(buf));
- }
- else if(argc == 1 && (strcmp(argv[0], "local_zones") == 0 ||
- strcmp(argv[0], "local_zones_remove") == 0 ||
- strcmp(argv[0], "local_datas") == 0 ||
- strcmp(argv[0], "local_datas_remove") == 0)) {
- send_file(ssl, stdin, buf, sizeof(buf));
- send_eof(ssl);
- }
-
- while(1) {
- ERR_clear_error();
- if((r = SSL_read(ssl, buf, (int)sizeof(buf)-1)) <= 0) {
- if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
- /* EOF */
- break;
- }
- ssl_err("could not SSL_read");
- }
- buf[r] = 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;
-}
-
-/** go ahead and read config, contact server and perform command and display */
-static int
-go(const char* cfgfile, char* svr, int quiet, int argc, char* argv[])
-{
- struct config_file* cfg;
- int fd, ret;
- SSL_CTX* ctx;
- SSL* ssl;
-
- /* read config */
- if(!(cfg = config_create()))
- fatal_exit("out of memory");
- if(!config_read(cfg, cfgfile, NULL))
- fatal_exit("could not read config file");
- if(!cfg->remote_control_enable)
- log_warn("control-enable is 'no' in the config file.");
-#ifdef UB_ON_WINDOWS
- w_config_adjust_directory(cfg);
-#endif
- ctx = setup_ctx(cfg);
-
- /* contact server */
- fd = contact_server(svr, cfg, argc>0&&strcmp(argv[0],"status")==0);
- ssl = setup_ssl(ctx, fd, cfg);
-
- /* send command */
- ret = go_cmd(ssl, quiet, argc, argv);
-
- SSL_free(ssl);
-#ifndef USE_WINSOCK
- close(fd);
-#else
- closesocket(fd);
-#endif
- SSL_CTX_free(ctx);
- config_delete(cfg);
- return ret;
-}
-
-/** getopt global, in case header files fail to declare it. */
-extern int optind;
-/** getopt global, in case header files fail to declare it. */
-extern char* optarg;
-
-/** Main routine for unbound-control */
-int main(int argc, char* argv[])
-{
- int c, ret;
- int quiet = 0;
- const char* cfgfile = CONFIGFILE;
- char* svr = NULL;
-#ifdef USE_WINSOCK
- int r;
- WSADATA wsa_data;
-#endif
-#ifdef USE_THREAD_DEBUG
- /* stop the file output from unbound-control, overwites the servers */
- extern int check_locking_order;
- check_locking_order = 0;
-#endif /* USE_THREAD_DEBUG */
- log_ident_set("unbound-control");
- log_init(NULL, 0, NULL);
- checklock_start();
-#ifdef USE_WINSOCK
- /* use registry config file in preference to compiletime location */
- if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile")))
- cfgfile = CONFIGFILE;
-#endif
- /* parse the options */
- while( (c=getopt(argc, argv, "c:s:qh")) != -1) {
- switch(c) {
- case 'c':
- cfgfile = optarg;
- break;
- case 's':
- svr = optarg;
- break;
- case 'q':
- quiet = 1;
- break;
- case '?':
- case 'h':
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
- if(argc == 0)
- usage();
- if(argc >= 1 && strcmp(argv[0], "start")==0) {
- if(execlp("unbound", "unbound", "-c", cfgfile,
- (char*)NULL) < 0) {
- fatal_exit("could not exec unbound: %s",
- strerror(errno));
- }
- }
- if(argc >= 1 && strcmp(argv[0], "stats_shm")==0) {
- print_stats_shm(cfgfile);
- return 0;
- }
-
-#ifdef USE_WINSOCK
- if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0)
- fatal_exit("WSAStartup failed: %s", wsa_strerror(r));
-#endif
-
-#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
- ERR_load_crypto_strings();
-#endif
- ERR_load_SSL_strings();
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
- OpenSSL_add_all_algorithms();
-#else
- OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
- | OPENSSL_INIT_ADD_ALL_DIGESTS
- | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
-#endif
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
- (void)SSL_library_init();
-#else
- (void)OPENSSL_init_ssl(0, NULL);
-#endif
-
- if(!RAND_status()) {
- /* try to seed it */
- unsigned char buf[256];
- 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));
- v = v*seed + (unsigned int)i;
- }
- RAND_seed(buf, 256);
- log_warn("no entropy, seeding openssl PRNG with time\n");
- }
-
- ret = go(cfgfile, svr, quiet, argc, argv);
-
-#ifdef USE_WINSOCK
- WSACleanup();
-#endif
- checklock_stop();
- return ret;
-}
diff --git a/external/unbound/smallapp/unbound-host.c b/external/unbound/smallapp/unbound-host.c
deleted file mode 100644
index d7a36a231..000000000
--- a/external/unbound/smallapp/unbound-host.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * checkconf/unbound-host.c - replacement for host that supports validation.
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file performs functionality like 'host', and also supports validation.
- * It uses the libunbound library.
- */
-
-#include "config.h"
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-/* remove alloc checks, not in this part of the code */
-#ifdef UNBOUND_ALLOC_STATS
-#undef malloc
-#undef calloc
-#undef free
-#undef realloc
-#endif
-#ifdef UNBOUND_ALLOC_LITE
-#undef malloc
-#undef calloc
-#undef free
-#undef realloc
-#undef strdup
-#define unbound_lite_wrapstr(s) s
-#endif
-#include "libunbound/unbound.h"
-#include "sldns/rrdef.h"
-#include "sldns/wire2str.h"
-#ifdef HAVE_NSS
-/* nss3 */
-#include "nss.h"
-#endif
-
-/** verbosity for unbound-host app */
-static int verb = 0;
-
-/** Give unbound-host usage, and exit (1). */
-static void
-usage(void)
-{
- printf("Usage: unbound-host [-vdhr46] [-c class] [-t type] hostname\n");
- printf(" [-y key] [-f keyfile] [-F namedkeyfile]\n");
- printf(" [-C configfile]\n");
- printf(" Queries the DNS for information.\n");
- printf(" The hostname is looked up for IP4, IP6 and mail.\n");
- printf(" If an ip-address is given a reverse lookup is done.\n");
- printf(" Use the -v option to see DNSSEC security information.\n");
- printf(" -t type what type to look for.\n");
- printf(" -c class what class to look for, if not class IN.\n");
- printf(" -y 'keystring' specify trust anchor, DS or DNSKEY, like\n");
- printf(" -y 'example.com DS 31560 5 1 1CFED8478...'\n");
- printf(" -D DNSSEC enable with default root anchor\n");
- printf(" from %s\n", ROOT_ANCHOR_FILE);
- printf(" -f keyfile read trust anchors from file, with lines as -y.\n");
- printf(" -F keyfile read named.conf-style trust anchors.\n");
- printf(" -C config use the specified unbound.conf (none read by default)\n");
- printf(" -r read forwarder information from /etc/resolv.conf\n");
- printf(" breaks validation if the forwarder does not do DNSSEC.\n");
- printf(" -v be more verbose, shows nodata and security.\n");
- printf(" -d debug, traces the action, -d -d shows more.\n");
- printf(" -4 use ipv4 network, avoid ipv6.\n");
- printf(" -6 use ipv6 network, avoid ipv4.\n");
- printf(" -h show this usage help.\n");
- printf("Version %s\n", PACKAGE_VERSION);
- printf("BSD licensed, see LICENSE in source package for details.\n");
- printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
- exit(1);
-}
-
-/** determine if str is ip4 and put into reverse lookup format */
-static int
-isip4(const char* nm, char** res)
-{
- struct in_addr addr;
- /* ddd.ddd.ddd.ddd.in-addr.arpa. is less than 32 */
- char buf[32];
- if(inet_pton(AF_INET, nm, &addr) <= 0) {
- return 0;
- }
- snprintf(buf, sizeof(buf), "%u.%u.%u.%u.in-addr.arpa",
- (unsigned)((uint8_t*)&addr)[3], (unsigned)((uint8_t*)&addr)[2],
- (unsigned)((uint8_t*)&addr)[1], (unsigned)((uint8_t*)&addr)[0]);
- *res = strdup(buf);
- return 1;
-}
-
-/** determine if str is ip6 and put into reverse lookup format */
-static int
-isip6(const char* nm, char** res)
-{
- struct in6_addr addr;
- /* [nibble.]{32}.ip6.arpa. is less than 128 */
- const char* hex = "0123456789abcdef";
- char buf[128];
- char *p;
- int i;
- if(inet_pton(AF_INET6, nm, &addr) <= 0) {
- return 0;
- }
- p = buf;
- for(i=15; i>=0; i--) {
- uint8_t b = ((uint8_t*)&addr)[i];
- *p++ = hex[ (b&0x0f) ];
- *p++ = '.';
- *p++ = hex[ (b&0xf0) >> 4 ];
- *p++ = '.';
- }
- snprintf(buf+16*4, sizeof(buf)-16*4, "ip6.arpa");
- *res = strdup(buf);
- if(!*res) {
- fprintf(stderr, "error: out of memory\n");
- exit(1);
- }
- return 1;
-}
-
-/** massage input name */
-static char*
-massage_qname(const char* nm, int* reverse)
-{
- /* recognise IP4 and IP6, create reverse addresses if needed */
- char* res;
- if(isip4(nm, &res)) {
- *reverse = 1;
- } else if(isip6(nm, &res)) {
- *reverse = 1;
- } else {
- res = strdup(nm);
- }
- if(!res) {
- fprintf(stderr, "error: out of memory\n");
- exit(1);
- }
- return res;
-}
-
-/** massage input type */
-static int
-massage_type(const char* t, int reverse, int* multi)
-{
- if(t) {
- int r = sldns_get_rr_type_by_name(t);
- if(r == 0 && strcasecmp(t, "TYPE0") != 0 &&
- strcmp(t, "") != 0) {
- fprintf(stderr, "error unknown type %s\n", t);
- exit(1);
- }
- return r;
- }
- if(!t && reverse)
- return LDNS_RR_TYPE_PTR;
- *multi = 1;
- return LDNS_RR_TYPE_A;
-}
-
-/** massage input class */
-static int
-massage_class(const char* c)
-{
- if(c) {
- int r = sldns_get_rr_class_by_name(c);
- if(r == 0 && strcasecmp(c, "CLASS0") != 0 &&
- strcmp(c, "") != 0) {
- fprintf(stderr, "error unknown class %s\n", c);
- exit(1);
- }
- return r;
- }
- return LDNS_RR_CLASS_IN;
-}
-
-/** nice security status string */
-static const char*
-secure_str(struct ub_result* result)
-{
- if(result->secure) return "(secure)";
- if(result->bogus) return "(BOGUS (security failure))";
- return "(insecure)";
-}
-
-/** nice string for type */
-static void
-pretty_type(char* s, size_t len, int t)
-{
- char d[16];
- sldns_wire2str_type_buf((uint16_t)t, d, sizeof(d));
- snprintf(s, len, "%s", d);
-}
-
-/** nice string for class */
-static void
-pretty_class(char* s, size_t len, int c)
-{
- char d[16];
- sldns_wire2str_class_buf((uint16_t)c, d, sizeof(d));
- snprintf(s, len, "%s", d);
-}
-
-/** nice string for rcode */
-static void
-pretty_rcode(char* s, size_t len, int r)
-{
- char d[16];
- sldns_wire2str_rcode_buf(r, d, sizeof(d));
- snprintf(s, len, "%s", d);
-}
-
-/** convert and print rdata */
-static void
-print_rd(int t, char* data, size_t len)
-{
- char s[65535];
- sldns_wire2str_rdata_buf((uint8_t*)data, len, s, sizeof(s), (uint16_t)t);
- printf(" %s", s);
-}
-
-/** pretty line of RR data for results */
-static void
-pretty_rdata(char* q, char* cstr, char* tstr, int t, const char* sec,
- char* data, size_t len)
-{
- printf("%s", q);
- if(strcmp(cstr, "IN") != 0)
- printf(" in class %s", cstr);
- if(t == LDNS_RR_TYPE_A)
- printf(" has address");
- else if(t == LDNS_RR_TYPE_AAAA)
- printf(" has IPv6 address");
- else if(t == LDNS_RR_TYPE_MX)
- printf(" mail is handled by");
- else if(t == LDNS_RR_TYPE_PTR)
- printf(" domain name pointer");
- else printf(" has %s record", tstr);
- print_rd(t, data, len);
- if(verb > 0)
- printf(" %s", sec);
- printf("\n");
-}
-
-/** pretty line of output for results */
-static void
-pretty_output(char* q, int t, int c, struct ub_result* result, int docname)
-{
- int i;
- const char *secstatus = secure_str(result);
- char tstr[16];
- char cstr[16];
- char rcodestr[16];
- pretty_type(tstr, 16, t);
- pretty_class(cstr, 16, c);
- pretty_rcode(rcodestr, 16, result->rcode);
-
- if(!result->havedata && result->rcode) {
- printf("Host %s not found: %d(%s).",
- q, result->rcode, rcodestr);
- if(verb > 0)
- printf(" %s", secstatus);
- printf("\n");
- if(result->bogus && result->why_bogus)
- printf("%s\n", result->why_bogus);
- return;
- }
- if(docname && result->canonname &&
- result->canonname != result->qname) {
- printf("%s is an alias for %s", result->qname,
- result->canonname);
- if(verb > 0)
- printf(" %s", secstatus);
- printf("\n");
- }
- /* remove trailing . from long canonnames for nicer output */
- if(result->canonname && strlen(result->canonname) > 1 &&
- result->canonname[strlen(result->canonname)-1] == '.')
- result->canonname[strlen(result->canonname)-1] = 0;
- if(!result->havedata) {
- if(verb > 0) {
- printf("%s", result->canonname?result->canonname:q);
- if(strcmp(cstr, "IN") != 0)
- printf(" in class %s", cstr);
- if(t == LDNS_RR_TYPE_A)
- printf(" has no address");
- else if(t == LDNS_RR_TYPE_AAAA)
- printf(" has no IPv6 address");
- else if(t == LDNS_RR_TYPE_PTR)
- printf(" has no domain name ptr");
- else if(t == LDNS_RR_TYPE_MX)
- printf(" has no mail handler record");
- else if(t == LDNS_RR_TYPE_ANY) {
- char* s = sldns_wire2str_pkt(
- result->answer_packet,
- (size_t)result->answer_len);
- if(!s) {
- fprintf(stderr, "alloc failure\n");
- exit(1);
- }
- printf("%s\n", s);
- } else printf(" has no %s record", tstr);
- printf(" %s\n", secstatus);
- }
- /* else: emptiness to indicate no data */
- if(result->bogus && result->why_bogus)
- printf("%s\n", result->why_bogus);
- return;
- }
- i=0;
- while(result->data[i])
- {
- pretty_rdata(
- result->canonname?result->canonname:q,
- cstr, tstr, t, secstatus, result->data[i],
- (size_t)result->len[i]);
- i++;
- }
- if(result->bogus && result->why_bogus)
- printf("%s\n", result->why_bogus);
-}
-
-/** perform a lookup and printout return if domain existed */
-static int
-dnslook(struct ub_ctx* ctx, char* q, int t, int c, int docname)
-{
- int ret;
- struct ub_result* result;
-
- ret = ub_resolve(ctx, q, t, c, &result);
- if(ret != 0) {
- fprintf(stderr, "resolve error: %s\n", ub_strerror(ret));
- exit(1);
- }
- pretty_output(q, t, c, result, docname);
- ret = result->nxdomain;
- ub_resolve_free(result);
- return ret;
-}
-
-/** perform host lookup */
-static void
-lookup(struct ub_ctx* ctx, const char* nm, const char* qt, const char* qc)
-{
- /* massage input into a query name, type and class */
- int multi = 0; /* no type, so do A, AAAA, MX */
- int reverse = 0; /* we are doing a reverse lookup */
- char* realq = massage_qname(nm, &reverse);
- int t = massage_type(qt, reverse, &multi);
- int c = massage_class(qc);
-
- /* perform the query */
- if(multi) {
- if(!dnslook(ctx, realq, LDNS_RR_TYPE_A, c, 1)) {
- /* domain exists, lookup more */
- (void)dnslook(ctx, realq, LDNS_RR_TYPE_AAAA, c, 0);
- (void)dnslook(ctx, realq, LDNS_RR_TYPE_MX, c, 0);
- }
- } else {
- (void)dnslook(ctx, realq, t, c, 1);
- }
- ub_ctx_delete(ctx);
- free(realq);
-}
-
-/** print error if any */
-static void
-check_ub_res(int r)
-{
- if(r != 0) {
- fprintf(stderr, "error: %s\n", ub_strerror(r));
- exit(1);
- }
-}
-
-/** getopt global, in case header files fail to declare it. */
-extern int optind;
-/** getopt global, in case header files fail to declare it. */
-extern char* optarg;
-
-/** Main routine for unbound-host */
-int main(int argc, char* argv[])
-{
- int c;
- char* qclass = NULL;
- char* qtype = NULL;
- struct ub_ctx* ctx = NULL;
- int debuglevel = 0;
-
- ctx = ub_ctx_create();
- if(!ctx) {
- fprintf(stderr, "error: out of memory\n");
- exit(1);
- }
- /* no need to fetch additional targets, we only do few lookups */
- check_ub_res(ub_ctx_set_option(ctx, "target-fetch-policy:", "0 0 0 0 0"));
-
- /* parse the options */
- while( (c=getopt(argc, argv, "46DF:c:df:hrt:vy:C:")) != -1) {
- switch(c) {
- case '4':
- check_ub_res(ub_ctx_set_option(ctx, "do-ip6:", "no"));
- break;
- case '6':
- check_ub_res(ub_ctx_set_option(ctx, "do-ip4:", "no"));
- break;
- case 'c':
- qclass = optarg;
- break;
- case 'C':
- check_ub_res(ub_ctx_config(ctx, optarg));
- break;
- case 'D':
- check_ub_res(ub_ctx_add_ta_file(ctx, ROOT_ANCHOR_FILE));
- break;
- case 'd':
- debuglevel++;
- if(debuglevel < 2)
- debuglevel = 2; /* at least VERB_DETAIL */
- break;
- case 'r':
- check_ub_res(ub_ctx_resolvconf(ctx, "/etc/resolv.conf"));
- break;
- case 't':
- qtype = optarg;
- break;
- case 'v':
- verb++;
- break;
- case 'y':
- check_ub_res(ub_ctx_add_ta(ctx, optarg));
- break;
- case 'f':
- check_ub_res(ub_ctx_add_ta_file(ctx, optarg));
- break;
- case 'F':
- check_ub_res(ub_ctx_trustedkeys(ctx, optarg));
- break;
- case '?':
- case 'h':
- default:
- usage();
- }
- }
- if(debuglevel != 0) /* set after possible -C options */
- check_ub_res(ub_ctx_debuglevel(ctx, debuglevel));
- if(ub_ctx_get_option(ctx, "use-syslog", &optarg) == 0) {
- if(strcmp(optarg, "yes") == 0) /* disable use-syslog */
- check_ub_res(ub_ctx_set_option(ctx,
- "use-syslog:", "no"));
- free(optarg);
- }
- argc -= optind;
- argv += optind;
- 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;
-}
diff --git a/external/unbound/smallapp/worker_cb.c b/external/unbound/smallapp/worker_cb.c
deleted file mode 100644
index e88e8c8d7..000000000
--- a/external/unbound/smallapp/worker_cb.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * checkconf/worker_cb.c - fake callback routines to make fptr_wlist work
- *
- * Copyright (c) 2007, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * \file
- *
- * This file contains fake callback functions, so that the symbols exist
- * and the fptr_wlist continues to work even if the daemon/worker is not
- * linked into the resulting program.
- */
-#include "config.h"
-#include "libunbound/context.h"
-#include "libunbound/worker.h"
-#include "util/fptr_wlist.h"
-#include "util/log.h"
-#include "services/mesh.h"
-
-void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
- uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len),
- int ATTR_UNUSED(error), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-int worker_handle_request(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(repinfo))
-{
- log_assert(0);
- return 0;
-}
-
-int worker_handle_reply(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(reply_info))
-{
- log_assert(0);
- return 0;
-}
-
-int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(reply_info))
-{
- log_assert(0);
- return 0;
-}
-
-int remote_accept_callback(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(repinfo))
-{
- log_assert(0);
- return 0;
-}
-
-int remote_control_callback(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(repinfo))
-{
- log_assert(0);
- return 0;
-}
-
-void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-struct outbound_entry* worker_send_query(
- struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
- int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
- socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
- size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
- struct module_qstate* ATTR_UNUSED(q))
-{
- log_assert(0);
- return 0;
-}
-
-#ifdef UB_ON_WINDOWS
-void
-worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void*
- ATTR_UNUSED(arg)) {
- log_assert(0);
-}
-
-void
-wsvc_cron_cb(void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-#endif /* UB_ON_WINDOWS */
-
-void
-worker_alloc_cleanup(void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-struct outbound_entry* libworker_send_query(
- struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
- int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
- socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
- size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
- struct module_qstate* ATTR_UNUSED(q))
-{
- log_assert(0);
- return 0;
-}
-
-int libworker_handle_reply(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(reply_info))
-{
- log_assert(0);
- return 0;
-}
-
-int libworker_handle_service_reply(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(reply_info))
-{
- log_assert(0);
- return 0;
-}
-
-void libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
- uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len),
- int ATTR_UNUSED(error), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void libworker_fg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
- struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
- char* ATTR_UNUSED(why_bogus))
-{
- log_assert(0);
-}
-
-void libworker_bg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
- struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
- char* ATTR_UNUSED(why_bogus))
-{
- log_assert(0);
-}
-
-void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
- struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
- char* ATTR_UNUSED(why_bogus))
-{
- log_assert(0);
-}
-
-int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
-{
- log_assert(0);
- return 0;
-}
-
-void worker_stat_timer_cb(void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void worker_probe_timer_cb(void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void worker_start_accept(void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-void worker_stop_accept(void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}
-
-/** keep track of lock id in lock-verify application */
-struct order_id {
- /** the thread id that created it */
- int thr;
- /** the instance number of creation */
- int instance;
-};
-
-int order_lock_cmp(const void* e1, const void* e2)
-{
- const struct order_id* o1 = e1;
- const struct order_id* o2 = e2;
- if(o1->thr < o2->thr) return -1;
- if(o1->thr > o2->thr) return 1;
- if(o1->instance < o2->instance) return -1;
- if(o1->instance > o2->instance) return 1;
- return 0;
-}
-
-int
-codeline_cmp(const void* a, const void* b)
-{
- return strcmp(a, b);
-}
-
-int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
-{
- log_assert(0);
- return 0;
-}
-
-void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
-{
- log_assert(0);
-}