Home | History | Annotate | Line # | Download | only in smallapp
unbound-anchor.c revision 1.1.1.1.2.2
      1  1.1.1.1.2.2  pgoyette /*
      2  1.1.1.1.2.2  pgoyette  * unbound-anchor.c - update the root anchor if necessary.
      3  1.1.1.1.2.2  pgoyette  *
      4  1.1.1.1.2.2  pgoyette  * Copyright (c) 2010, NLnet Labs. All rights reserved.
      5  1.1.1.1.2.2  pgoyette  *
      6  1.1.1.1.2.2  pgoyette  * This software is open source.
      7  1.1.1.1.2.2  pgoyette  *
      8  1.1.1.1.2.2  pgoyette  * Redistribution and use in source and binary forms, with or without
      9  1.1.1.1.2.2  pgoyette  * modification, are permitted provided that the following conditions
     10  1.1.1.1.2.2  pgoyette  * are met:
     11  1.1.1.1.2.2  pgoyette  *
     12  1.1.1.1.2.2  pgoyette  * Redistributions of source code must retain the above copyright notice,
     13  1.1.1.1.2.2  pgoyette  * this list of conditions and the following disclaimer.
     14  1.1.1.1.2.2  pgoyette  *
     15  1.1.1.1.2.2  pgoyette  * Redistributions in binary form must reproduce the above copyright notice,
     16  1.1.1.1.2.2  pgoyette  * this list of conditions and the following disclaimer in the documentation
     17  1.1.1.1.2.2  pgoyette  * and/or other materials provided with the distribution.
     18  1.1.1.1.2.2  pgoyette  *
     19  1.1.1.1.2.2  pgoyette  * Neither the name of the NLNET LABS nor the names of its contributors may
     20  1.1.1.1.2.2  pgoyette  * be used to endorse or promote products derived from this software without
     21  1.1.1.1.2.2  pgoyette  * specific prior written permission.
     22  1.1.1.1.2.2  pgoyette  *
     23  1.1.1.1.2.2  pgoyette  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     24  1.1.1.1.2.2  pgoyette  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     25  1.1.1.1.2.2  pgoyette  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     26  1.1.1.1.2.2  pgoyette  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     27  1.1.1.1.2.2  pgoyette  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     28  1.1.1.1.2.2  pgoyette  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
     29  1.1.1.1.2.2  pgoyette  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     30  1.1.1.1.2.2  pgoyette  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     31  1.1.1.1.2.2  pgoyette  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     32  1.1.1.1.2.2  pgoyette  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     33  1.1.1.1.2.2  pgoyette  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     34  1.1.1.1.2.2  pgoyette  */
     35  1.1.1.1.2.2  pgoyette 
     36  1.1.1.1.2.2  pgoyette /**
     37  1.1.1.1.2.2  pgoyette  * \file
     38  1.1.1.1.2.2  pgoyette  *
     39  1.1.1.1.2.2  pgoyette  * This file checks to see that the current 5011 keys work to prime the
     40  1.1.1.1.2.2  pgoyette  * current root anchor.  If not a certificate is used to update the anchor.
     41  1.1.1.1.2.2  pgoyette  *
     42  1.1.1.1.2.2  pgoyette  * This is a concept solution for distribution of the DNSSEC root
     43  1.1.1.1.2.2  pgoyette  * trust anchor.  It is a small tool, called "unbound-anchor", that
     44  1.1.1.1.2.2  pgoyette  * runs before the main validator starts.  I.e. in the init script:
     45  1.1.1.1.2.2  pgoyette  * unbound-anchor; unbound.  Thus it is meant to run at system boot time.
     46  1.1.1.1.2.2  pgoyette  *
     47  1.1.1.1.2.2  pgoyette  * Management-Abstract:
     48  1.1.1.1.2.2  pgoyette  *    * first run: fill root.key file with hardcoded DS record.
     49  1.1.1.1.2.2  pgoyette  *    * mostly: use RFC5011 tracking, quick . DNSKEY UDP query.
     50  1.1.1.1.2.2  pgoyette  *    * failover: use builtin certificate, do https and update.
     51  1.1.1.1.2.2  pgoyette  * Special considerations:
     52  1.1.1.1.2.2  pgoyette  *    * 30-days RFC5011 timer saves a lot of https traffic.
     53  1.1.1.1.2.2  pgoyette  *    * DNSKEY probe must be NOERROR, saves a lot of https traffic.
     54  1.1.1.1.2.2  pgoyette  *    * fail if clock before sign date of the root, if cert expired.
     55  1.1.1.1.2.2  pgoyette  *    * if the root goes back to unsigned, deals with it.
     56  1.1.1.1.2.2  pgoyette  *
     57  1.1.1.1.2.2  pgoyette  * It has hardcoded the root DS anchors and the ICANN CA root certificate.
     58  1.1.1.1.2.2  pgoyette  * It allows with options to override those.  It also takes root-hints (it
     59  1.1.1.1.2.2  pgoyette  * has to do a DNS resolve), and also has hardcoded defaults for those.
     60  1.1.1.1.2.2  pgoyette  *
     61  1.1.1.1.2.2  pgoyette  * Once it starts, just before the validator starts, it quickly checks if
     62  1.1.1.1.2.2  pgoyette  * the root anchor file needs to be updated.  First it tries to use
     63  1.1.1.1.2.2  pgoyette  * RFC5011-tracking of the root key.  If that fails (and for 30-days since
     64  1.1.1.1.2.2  pgoyette  * last successful probe), then it attempts to update using the
     65  1.1.1.1.2.2  pgoyette  * certificate.  So most of the time, the RFC5011 tracking will work fine,
     66  1.1.1.1.2.2  pgoyette  * and within a couple milliseconds, the main daemon can start.  It will
     67  1.1.1.1.2.2  pgoyette  * have only probed the . DNSKEY, not done expensive https transfers on the
     68  1.1.1.1.2.2  pgoyette  * root infrastructure.
     69  1.1.1.1.2.2  pgoyette  *
     70  1.1.1.1.2.2  pgoyette  * If there is no root key in the root.key file, it bootstraps the
     71  1.1.1.1.2.2  pgoyette  * RFC5011-tracking with its builtin DS anchors; if that fails it
     72  1.1.1.1.2.2  pgoyette  * bootstraps the RFC5011-tracking using the certificate.  (again to avoid
     73  1.1.1.1.2.2  pgoyette  * https, and it is also faster).
     74  1.1.1.1.2.2  pgoyette  *
     75  1.1.1.1.2.2  pgoyette  * It uses the XML file by converting it to DS records and writing that to the
     76  1.1.1.1.2.2  pgoyette  * key file.  Unbound can detect that the 'special comments' are gone, and
     77  1.1.1.1.2.2  pgoyette  * the file contains a list of normal DNSKEY/DS records, and uses that to
     78  1.1.1.1.2.2  pgoyette  * bootstrap 5011 (the KSK is made VALID).
     79  1.1.1.1.2.2  pgoyette  *
     80  1.1.1.1.2.2  pgoyette  * The certificate update is done by fetching root-anchors.xml and
     81  1.1.1.1.2.2  pgoyette  * root-anchors.p7s via SSL.  The HTTPS certificate can be logged but is
     82  1.1.1.1.2.2  pgoyette  * not validated (https for channel security; the security comes from the
     83  1.1.1.1.2.2  pgoyette  * certificate).  The 'data.iana.org' domain name A and AAAA are resolved
     84  1.1.1.1.2.2  pgoyette  * without DNSSEC.  It tries a random IP until the transfer succeeds.  It
     85  1.1.1.1.2.2  pgoyette  * then checks the p7s signature.
     86  1.1.1.1.2.2  pgoyette  *
     87  1.1.1.1.2.2  pgoyette  * On any failure, it leaves the root key file untouched.  The main
     88  1.1.1.1.2.2  pgoyette  * validator has to cope with it, it cannot fix things (So a failure does
     89  1.1.1.1.2.2  pgoyette  * not go 'without DNSSEC', no downgrade).  If it used its builtin stuff or
     90  1.1.1.1.2.2  pgoyette  * did the https, it exits with an exit code, so that this can trigger the
     91  1.1.1.1.2.2  pgoyette  * init script to log the event and potentially alert the operator that can
     92  1.1.1.1.2.2  pgoyette  * do a manual check.
     93  1.1.1.1.2.2  pgoyette  *
     94  1.1.1.1.2.2  pgoyette  * The date is also checked.  Before 2010-07-15 is a failure (root not
     95  1.1.1.1.2.2  pgoyette  * signed yet; avoids attacks on system clock).  The
     96  1.1.1.1.2.2  pgoyette  * last-successful-RFC5011-probe (if available) has to be more than 30 days
     97  1.1.1.1.2.2  pgoyette  * in the past (otherwise, RFC5011 should have worked).  This keeps
     98  1.1.1.1.2.2  pgoyette  * unnecessary https traffic down.  If the main certificate is expired, it
     99  1.1.1.1.2.2  pgoyette  * fails.
    100  1.1.1.1.2.2  pgoyette  *
    101  1.1.1.1.2.2  pgoyette  * The dates on the keys in the xml are checked (uses the libexpat xml
    102  1.1.1.1.2.2  pgoyette  * parser), only the valid ones are used to re-enstate RFC5011 tracking.
    103  1.1.1.1.2.2  pgoyette  * If 0 keys are valid, the zone has gone to insecure (a special marker is
    104  1.1.1.1.2.2  pgoyette  * written in the keyfile that tells the main validator daemon the zone is
    105  1.1.1.1.2.2  pgoyette  * insecure).
    106  1.1.1.1.2.2  pgoyette  *
    107  1.1.1.1.2.2  pgoyette  * Only the root ICANN CA is shipped, not the intermediate ones.  The
    108  1.1.1.1.2.2  pgoyette  * intermediate CAs are included in the p7s file that was downloaded.  (the
    109  1.1.1.1.2.2  pgoyette  * root cert is valid to 2028 and the intermediate to 2014, today).
    110  1.1.1.1.2.2  pgoyette  *
    111  1.1.1.1.2.2  pgoyette  * Obviously, the tool also has options so the operator can provide a new
    112  1.1.1.1.2.2  pgoyette  * keyfile, a new certificate and new URLs, and fresh root hints.  By
    113  1.1.1.1.2.2  pgoyette  * default it logs nothing on failure and success; it 'just works'.
    114  1.1.1.1.2.2  pgoyette  *
    115  1.1.1.1.2.2  pgoyette  */
    116  1.1.1.1.2.2  pgoyette 
    117  1.1.1.1.2.2  pgoyette #include "config.h"
    118  1.1.1.1.2.2  pgoyette #include "libunbound/unbound.h"
    119  1.1.1.1.2.2  pgoyette #include "sldns/rrdef.h"
    120  1.1.1.1.2.2  pgoyette #include "sldns/parseutil.h"
    121  1.1.1.1.2.2  pgoyette #include <expat.h>
    122  1.1.1.1.2.2  pgoyette #ifndef HAVE_EXPAT_H
    123  1.1.1.1.2.2  pgoyette #error "need libexpat to parse root-anchors.xml file."
    124  1.1.1.1.2.2  pgoyette #endif
    125  1.1.1.1.2.2  pgoyette #ifdef HAVE_GETOPT_H
    126  1.1.1.1.2.2  pgoyette #include <getopt.h>
    127  1.1.1.1.2.2  pgoyette #endif
    128  1.1.1.1.2.2  pgoyette #ifdef HAVE_OPENSSL_SSL_H
    129  1.1.1.1.2.2  pgoyette #include <openssl/ssl.h>
    130  1.1.1.1.2.2  pgoyette #endif
    131  1.1.1.1.2.2  pgoyette #ifdef HAVE_OPENSSL_ERR_H
    132  1.1.1.1.2.2  pgoyette #include <openssl/err.h>
    133  1.1.1.1.2.2  pgoyette #endif
    134  1.1.1.1.2.2  pgoyette #ifdef HAVE_OPENSSL_RAND_H
    135  1.1.1.1.2.2  pgoyette #include <openssl/rand.h>
    136  1.1.1.1.2.2  pgoyette #endif
    137  1.1.1.1.2.2  pgoyette #include <openssl/x509.h>
    138  1.1.1.1.2.2  pgoyette #include <openssl/x509v3.h>
    139  1.1.1.1.2.2  pgoyette #include <openssl/pem.h>
    140  1.1.1.1.2.2  pgoyette 
    141  1.1.1.1.2.2  pgoyette /** name of server in URL to fetch HTTPS from */
    142  1.1.1.1.2.2  pgoyette #define URLNAME "data.iana.org"
    143  1.1.1.1.2.2  pgoyette /** path on HTTPS server to xml file */
    144  1.1.1.1.2.2  pgoyette #define XMLNAME "root-anchors/root-anchors.xml"
    145  1.1.1.1.2.2  pgoyette /** path on HTTPS server to p7s file */
    146  1.1.1.1.2.2  pgoyette #define P7SNAME "root-anchors/root-anchors.p7s"
    147  1.1.1.1.2.2  pgoyette /** name of the signer of the certificate */
    148  1.1.1.1.2.2  pgoyette #define P7SIGNER "dnssec (at) iana.org"
    149  1.1.1.1.2.2  pgoyette /** port number for https access */
    150  1.1.1.1.2.2  pgoyette #define HTTPS_PORT 443
    151  1.1.1.1.2.2  pgoyette 
    152  1.1.1.1.2.2  pgoyette #ifdef USE_WINSOCK
    153  1.1.1.1.2.2  pgoyette /* sneakily reuse the the wsa_strerror function, on windows */
    154  1.1.1.1.2.2  pgoyette char* wsa_strerror(int err);
    155  1.1.1.1.2.2  pgoyette #endif
    156  1.1.1.1.2.2  pgoyette 
    157  1.1.1.1.2.2  pgoyette /** verbosity for this application */
    158  1.1.1.1.2.2  pgoyette static int verb = 0;
    159  1.1.1.1.2.2  pgoyette 
    160  1.1.1.1.2.2  pgoyette /** list of IP addresses */
    161  1.1.1.1.2.2  pgoyette struct ip_list {
    162  1.1.1.1.2.2  pgoyette 	/** next in list */
    163  1.1.1.1.2.2  pgoyette 	struct ip_list* next;
    164  1.1.1.1.2.2  pgoyette 	/** length of addr */
    165  1.1.1.1.2.2  pgoyette 	socklen_t len;
    166  1.1.1.1.2.2  pgoyette 	/** address ready to connect to */
    167  1.1.1.1.2.2  pgoyette 	struct sockaddr_storage addr;
    168  1.1.1.1.2.2  pgoyette 	/** has the address been used */
    169  1.1.1.1.2.2  pgoyette 	int used;
    170  1.1.1.1.2.2  pgoyette };
    171  1.1.1.1.2.2  pgoyette 
    172  1.1.1.1.2.2  pgoyette /** Give unbound-anchor usage, and exit (1). */
    173  1.1.1.1.2.2  pgoyette static void
    174  1.1.1.1.2.2  pgoyette usage()
    175  1.1.1.1.2.2  pgoyette {
    176  1.1.1.1.2.2  pgoyette 	printf("Usage:	unbound-anchor [opts]\n");
    177  1.1.1.1.2.2  pgoyette 	printf("	Setup or update root anchor. "
    178  1.1.1.1.2.2  pgoyette 		"Most options have defaults.\n");
    179  1.1.1.1.2.2  pgoyette 	printf("	Run this program before you start the validator.\n");
    180  1.1.1.1.2.2  pgoyette 	printf("\n");
    181  1.1.1.1.2.2  pgoyette 	printf("	The anchor and cert have default builtin content\n");
    182  1.1.1.1.2.2  pgoyette 	printf("	if the file does not exist or is empty.\n");
    183  1.1.1.1.2.2  pgoyette 	printf("\n");
    184  1.1.1.1.2.2  pgoyette 	printf("-a file		root key file, default %s\n", ROOT_ANCHOR_FILE);
    185  1.1.1.1.2.2  pgoyette 	printf("		The key is input and output for this tool.\n");
    186  1.1.1.1.2.2  pgoyette 	printf("-c file		cert file, default %s\n", ROOT_CERT_FILE);
    187  1.1.1.1.2.2  pgoyette 	printf("-l		list builtin key and cert on stdout\n");
    188  1.1.1.1.2.2  pgoyette 	printf("-u name		server in https url, default %s\n", URLNAME);
    189  1.1.1.1.2.2  pgoyette 	printf("-x path		pathname to xml in url, default %s\n", XMLNAME);
    190  1.1.1.1.2.2  pgoyette 	printf("-s path		pathname to p7s in url, default %s\n", P7SNAME);
    191  1.1.1.1.2.2  pgoyette 	printf("-n name		signer's subject emailAddress, default %s\n", P7SIGNER);
    192  1.1.1.1.2.2  pgoyette 	printf("-4		work using IPv4 only\n");
    193  1.1.1.1.2.2  pgoyette 	printf("-6		work using IPv6 only\n");
    194  1.1.1.1.2.2  pgoyette 	printf("-f resolv.conf	use given resolv.conf to resolve -u name\n");
    195  1.1.1.1.2.2  pgoyette 	printf("-r root.hints	use given root.hints to resolve -u name\n"
    196  1.1.1.1.2.2  pgoyette 		"		builtin root hints are used by default\n");
    197  1.1.1.1.2.2  pgoyette 	printf("-v		more verbose\n");
    198  1.1.1.1.2.2  pgoyette 	printf("-C conf		debug, read config\n");
    199  1.1.1.1.2.2  pgoyette 	printf("-P port		use port for https connect, default 443\n");
    200  1.1.1.1.2.2  pgoyette 	printf("-F 		debug, force update with cert\n");
    201  1.1.1.1.2.2  pgoyette 	printf("-h		show this usage help\n");
    202  1.1.1.1.2.2  pgoyette 	printf("Version %s\n", PACKAGE_VERSION);
    203  1.1.1.1.2.2  pgoyette 	printf("BSD licensed, see LICENSE in source package for details.\n");
    204  1.1.1.1.2.2  pgoyette 	printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
    205  1.1.1.1.2.2  pgoyette 	exit(1);
    206  1.1.1.1.2.2  pgoyette }
    207  1.1.1.1.2.2  pgoyette 
    208  1.1.1.1.2.2  pgoyette /** return the built in root update certificate */
    209  1.1.1.1.2.2  pgoyette static const char*
    210  1.1.1.1.2.2  pgoyette get_builtin_cert(void)
    211  1.1.1.1.2.2  pgoyette {
    212  1.1.1.1.2.2  pgoyette 	return
    213  1.1.1.1.2.2  pgoyette /* The ICANN CA fetched at 24 Sep 2010.  Valid to 2028 */
    214  1.1.1.1.2.2  pgoyette "-----BEGIN CERTIFICATE-----\n"
    215  1.1.1.1.2.2  pgoyette "MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n"
    216  1.1.1.1.2.2  pgoyette "TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n"
    217  1.1.1.1.2.2  pgoyette "BAMTDUlDQU5OIFJvb3QgQ0ExCzAJBgNVBAYTAlVTMB4XDTA5MTIyMzA0MTkxMloX\n"
    218  1.1.1.1.2.2  pgoyette "DTI5MTIxODA0MTkxMlowXTEOMAwGA1UEChMFSUNBTk4xJjAkBgNVBAsTHUlDQU5O\n"
    219  1.1.1.1.2.2  pgoyette "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1JQ0FOTiBSb290IENB\n"
    220  1.1.1.1.2.2  pgoyette "MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDb\n"
    221  1.1.1.1.2.2  pgoyette "cLhPNNqc1NB+u+oVvOnJESofYS9qub0/PXagmgr37pNublVThIzyLPGCJ8gPms9S\n"
    222  1.1.1.1.2.2  pgoyette "G1TaKNIsMI7d+5IgMy3WyPEOECGIcfqEIktdR1YWfJufXcMReZwU4v/AdKzdOdfg\n"
    223  1.1.1.1.2.2  pgoyette "ONiwc6r70duEr1IiqPbVm5T05l1e6D+HkAvHGnf1LtOPGs4CHQdpIUcy2kauAEy2\n"
    224  1.1.1.1.2.2  pgoyette "paKcOcHASvbTHK7TbbvHGPB+7faAztABLoneErruEcumetcNfPMIjXKdv1V1E3C7\n"
    225  1.1.1.1.2.2  pgoyette "MSJKy+jAqqQJqjZoQGB0necZgUMiUv7JK1IPQRM2CXJllcyJrm9WFxY0c1KjBO29\n"
    226  1.1.1.1.2.2  pgoyette "iIKK69fcglKcBuFShUECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n"
    227  1.1.1.1.2.2  pgoyette "Af8EBAMCAf4wHQYDVR0OBBYEFLpS6UmDJIZSL8eZzfyNa2kITcBQMA0GCSqGSIb3\n"
    228  1.1.1.1.2.2  pgoyette "DQEBCwUAA4IBAQAP8emCogqHny2UYFqywEuhLys7R9UKmYY4suzGO4nkbgfPFMfH\n"
    229  1.1.1.1.2.2  pgoyette "6M+Zj6owwxlwueZt1j/IaCayoKU3QsrYYoDRolpILh+FPwx7wseUEV8ZKpWsoDoD\n"
    230  1.1.1.1.2.2  pgoyette "2JFbLg2cfB8u/OlE4RYmcxxFSmXBg0yQ8/IoQt/bxOcEEhhiQ168H2yE5rxJMt9h\n"
    231  1.1.1.1.2.2  pgoyette "15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF\n"
    232  1.1.1.1.2.2  pgoyette "0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n"
    233  1.1.1.1.2.2  pgoyette "j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n"
    234  1.1.1.1.2.2  pgoyette "-----END CERTIFICATE-----\n"
    235  1.1.1.1.2.2  pgoyette 		;
    236  1.1.1.1.2.2  pgoyette }
    237  1.1.1.1.2.2  pgoyette 
    238  1.1.1.1.2.2  pgoyette /** return the built in root DS trust anchor */
    239  1.1.1.1.2.2  pgoyette static const char*
    240  1.1.1.1.2.2  pgoyette get_builtin_ds(void)
    241  1.1.1.1.2.2  pgoyette {
    242  1.1.1.1.2.2  pgoyette 	return
    243  1.1.1.1.2.2  pgoyette ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n";
    244  1.1.1.1.2.2  pgoyette }
    245  1.1.1.1.2.2  pgoyette 
    246  1.1.1.1.2.2  pgoyette /** print hex data */
    247  1.1.1.1.2.2  pgoyette static void
    248  1.1.1.1.2.2  pgoyette print_data(const char* msg, const char* data, int len)
    249  1.1.1.1.2.2  pgoyette {
    250  1.1.1.1.2.2  pgoyette 	int i;
    251  1.1.1.1.2.2  pgoyette 	printf("%s: ", msg);
    252  1.1.1.1.2.2  pgoyette 	for(i=0; i<len; i++) {
    253  1.1.1.1.2.2  pgoyette 		printf(" %2.2x", (unsigned char)data[i]);
    254  1.1.1.1.2.2  pgoyette 	}
    255  1.1.1.1.2.2  pgoyette 	printf("\n");
    256  1.1.1.1.2.2  pgoyette }
    257  1.1.1.1.2.2  pgoyette 
    258  1.1.1.1.2.2  pgoyette /** print ub context creation error and exit */
    259  1.1.1.1.2.2  pgoyette static void
    260  1.1.1.1.2.2  pgoyette ub_ctx_error_exit(struct ub_ctx* ctx, const char* str, const char* str2)
    261  1.1.1.1.2.2  pgoyette {
    262  1.1.1.1.2.2  pgoyette 	ub_ctx_delete(ctx);
    263  1.1.1.1.2.2  pgoyette 	if(str && str2 && verb) printf("%s: %s\n", str, str2);
    264  1.1.1.1.2.2  pgoyette 	if(verb) printf("error: could not create unbound resolver context\n");
    265  1.1.1.1.2.2  pgoyette 	exit(0);
    266  1.1.1.1.2.2  pgoyette }
    267  1.1.1.1.2.2  pgoyette 
    268  1.1.1.1.2.2  pgoyette /**
    269  1.1.1.1.2.2  pgoyette  * Create a new unbound context with the commandline settings applied
    270  1.1.1.1.2.2  pgoyette  */
    271  1.1.1.1.2.2  pgoyette static struct ub_ctx*
    272  1.1.1.1.2.2  pgoyette create_unbound_context(const char* res_conf, const char* root_hints,
    273  1.1.1.1.2.2  pgoyette 	const char* debugconf, int ip4only, int ip6only)
    274  1.1.1.1.2.2  pgoyette {
    275  1.1.1.1.2.2  pgoyette 	int r;
    276  1.1.1.1.2.2  pgoyette 	struct ub_ctx* ctx = ub_ctx_create();
    277  1.1.1.1.2.2  pgoyette 	if(!ctx) {
    278  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
    279  1.1.1.1.2.2  pgoyette 		exit(0);
    280  1.1.1.1.2.2  pgoyette 	}
    281  1.1.1.1.2.2  pgoyette 	/* do not waste time and network traffic to fetch extra nameservers */
    282  1.1.1.1.2.2  pgoyette 	r = ub_ctx_set_option(ctx, "target-fetch-policy:", "0 0 0 0 0");
    283  1.1.1.1.2.2  pgoyette 	if(r && verb) printf("ctx targetfetchpolicy: %s\n", ub_strerror(r));
    284  1.1.1.1.2.2  pgoyette 	/* read config file first, so its settings can be overridden */
    285  1.1.1.1.2.2  pgoyette 	if(debugconf) {
    286  1.1.1.1.2.2  pgoyette 		r = ub_ctx_config(ctx, debugconf);
    287  1.1.1.1.2.2  pgoyette 		if(r) ub_ctx_error_exit(ctx, debugconf, ub_strerror(r));
    288  1.1.1.1.2.2  pgoyette 	}
    289  1.1.1.1.2.2  pgoyette 	if(res_conf) {
    290  1.1.1.1.2.2  pgoyette 		r = ub_ctx_resolvconf(ctx, res_conf);
    291  1.1.1.1.2.2  pgoyette 		if(r) ub_ctx_error_exit(ctx, res_conf, ub_strerror(r));
    292  1.1.1.1.2.2  pgoyette 	}
    293  1.1.1.1.2.2  pgoyette 	if(root_hints) {
    294  1.1.1.1.2.2  pgoyette 		r = ub_ctx_set_option(ctx, "root-hints:", root_hints);
    295  1.1.1.1.2.2  pgoyette 		if(r) ub_ctx_error_exit(ctx, root_hints, ub_strerror(r));
    296  1.1.1.1.2.2  pgoyette 	}
    297  1.1.1.1.2.2  pgoyette 	if(ip4only) {
    298  1.1.1.1.2.2  pgoyette 		r = ub_ctx_set_option(ctx, "do-ip6:", "no");
    299  1.1.1.1.2.2  pgoyette 		if(r) ub_ctx_error_exit(ctx, "ip4only", ub_strerror(r));
    300  1.1.1.1.2.2  pgoyette 	}
    301  1.1.1.1.2.2  pgoyette 	if(ip6only) {
    302  1.1.1.1.2.2  pgoyette 		r = ub_ctx_set_option(ctx, "do-ip4:", "no");
    303  1.1.1.1.2.2  pgoyette 		if(r) ub_ctx_error_exit(ctx, "ip6only", ub_strerror(r));
    304  1.1.1.1.2.2  pgoyette 	}
    305  1.1.1.1.2.2  pgoyette 	return ctx;
    306  1.1.1.1.2.2  pgoyette }
    307  1.1.1.1.2.2  pgoyette 
    308  1.1.1.1.2.2  pgoyette /** printout certificate in detail */
    309  1.1.1.1.2.2  pgoyette static void
    310  1.1.1.1.2.2  pgoyette verb_cert(const char* msg, X509* x)
    311  1.1.1.1.2.2  pgoyette {
    312  1.1.1.1.2.2  pgoyette 	if(verb == 0 || verb == 1) return;
    313  1.1.1.1.2.2  pgoyette 	if(verb == 2) {
    314  1.1.1.1.2.2  pgoyette 		if(msg) printf("%s\n", msg);
    315  1.1.1.1.2.2  pgoyette 		X509_print_ex_fp(stdout, x, 0, (unsigned long)-1
    316  1.1.1.1.2.2  pgoyette 			^(X509_FLAG_NO_SUBJECT
    317  1.1.1.1.2.2  pgoyette 			|X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY));
    318  1.1.1.1.2.2  pgoyette 		return;
    319  1.1.1.1.2.2  pgoyette 	}
    320  1.1.1.1.2.2  pgoyette 	if(msg) printf("%s\n", msg);
    321  1.1.1.1.2.2  pgoyette 	X509_print_fp(stdout, x);
    322  1.1.1.1.2.2  pgoyette }
    323  1.1.1.1.2.2  pgoyette 
    324  1.1.1.1.2.2  pgoyette /** printout certificates in detail */
    325  1.1.1.1.2.2  pgoyette static void
    326  1.1.1.1.2.2  pgoyette verb_certs(const char* msg, STACK_OF(X509)* sk)
    327  1.1.1.1.2.2  pgoyette {
    328  1.1.1.1.2.2  pgoyette 	int i, num = sk_X509_num(sk);
    329  1.1.1.1.2.2  pgoyette 	if(verb == 0 || verb == 1) return;
    330  1.1.1.1.2.2  pgoyette 	for(i=0; i<num; i++) {
    331  1.1.1.1.2.2  pgoyette 		printf("%s (%d/%d)\n", msg, i, num);
    332  1.1.1.1.2.2  pgoyette 		verb_cert(NULL, sk_X509_value(sk, i));
    333  1.1.1.1.2.2  pgoyette 	}
    334  1.1.1.1.2.2  pgoyette }
    335  1.1.1.1.2.2  pgoyette 
    336  1.1.1.1.2.2  pgoyette /** read certificates from a PEM bio */
    337  1.1.1.1.2.2  pgoyette static STACK_OF(X509)*
    338  1.1.1.1.2.2  pgoyette read_cert_bio(BIO* bio)
    339  1.1.1.1.2.2  pgoyette {
    340  1.1.1.1.2.2  pgoyette 	STACK_OF(X509) *sk = sk_X509_new_null();
    341  1.1.1.1.2.2  pgoyette 	if(!sk) {
    342  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
    343  1.1.1.1.2.2  pgoyette 		exit(0);
    344  1.1.1.1.2.2  pgoyette 	}
    345  1.1.1.1.2.2  pgoyette 	while(!BIO_eof(bio)) {
    346  1.1.1.1.2.2  pgoyette 		X509* x = PEM_read_bio_X509(bio, NULL, 0, NULL);
    347  1.1.1.1.2.2  pgoyette 		if(x == NULL) {
    348  1.1.1.1.2.2  pgoyette 			if(verb) {
    349  1.1.1.1.2.2  pgoyette 				printf("failed to read X509\n");
    350  1.1.1.1.2.2  pgoyette 			 	ERR_print_errors_fp(stdout);
    351  1.1.1.1.2.2  pgoyette 			}
    352  1.1.1.1.2.2  pgoyette 			continue;
    353  1.1.1.1.2.2  pgoyette 		}
    354  1.1.1.1.2.2  pgoyette 		if(!sk_X509_push(sk, x)) {
    355  1.1.1.1.2.2  pgoyette 			if(verb) printf("out of memory\n");
    356  1.1.1.1.2.2  pgoyette 			exit(0);
    357  1.1.1.1.2.2  pgoyette 		}
    358  1.1.1.1.2.2  pgoyette 	}
    359  1.1.1.1.2.2  pgoyette 	return sk;
    360  1.1.1.1.2.2  pgoyette }
    361  1.1.1.1.2.2  pgoyette 
    362  1.1.1.1.2.2  pgoyette /* read the certificate file */
    363  1.1.1.1.2.2  pgoyette static STACK_OF(X509)*
    364  1.1.1.1.2.2  pgoyette read_cert_file(const char* file)
    365  1.1.1.1.2.2  pgoyette {
    366  1.1.1.1.2.2  pgoyette 	STACK_OF(X509)* sk;
    367  1.1.1.1.2.2  pgoyette 	FILE* in;
    368  1.1.1.1.2.2  pgoyette 	int content = 0;
    369  1.1.1.1.2.2  pgoyette 	char buf[128];
    370  1.1.1.1.2.2  pgoyette 	if(file == NULL || strcmp(file, "") == 0) {
    371  1.1.1.1.2.2  pgoyette 		return NULL;
    372  1.1.1.1.2.2  pgoyette 	}
    373  1.1.1.1.2.2  pgoyette 	sk = sk_X509_new_null();
    374  1.1.1.1.2.2  pgoyette 	if(!sk) {
    375  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
    376  1.1.1.1.2.2  pgoyette 		exit(0);
    377  1.1.1.1.2.2  pgoyette 	}
    378  1.1.1.1.2.2  pgoyette 	in = fopen(file, "r");
    379  1.1.1.1.2.2  pgoyette 	if(!in) {
    380  1.1.1.1.2.2  pgoyette 		if(verb) printf("%s: %s\n", file, strerror(errno));
    381  1.1.1.1.2.2  pgoyette #ifndef S_SPLINT_S
    382  1.1.1.1.2.2  pgoyette 		sk_X509_pop_free(sk, X509_free);
    383  1.1.1.1.2.2  pgoyette #endif
    384  1.1.1.1.2.2  pgoyette 		return NULL;
    385  1.1.1.1.2.2  pgoyette 	}
    386  1.1.1.1.2.2  pgoyette 	while(!feof(in)) {
    387  1.1.1.1.2.2  pgoyette 		X509* x = PEM_read_X509(in, NULL, 0, NULL);
    388  1.1.1.1.2.2  pgoyette 		if(x == NULL) {
    389  1.1.1.1.2.2  pgoyette 			if(verb) {
    390  1.1.1.1.2.2  pgoyette 				printf("failed to read X509 file\n");
    391  1.1.1.1.2.2  pgoyette 			 	ERR_print_errors_fp(stdout);
    392  1.1.1.1.2.2  pgoyette 			}
    393  1.1.1.1.2.2  pgoyette 			continue;
    394  1.1.1.1.2.2  pgoyette 		}
    395  1.1.1.1.2.2  pgoyette 		if(!sk_X509_push(sk, x)) {
    396  1.1.1.1.2.2  pgoyette 			if(verb) printf("out of memory\n");
    397  1.1.1.1.2.2  pgoyette 			fclose(in);
    398  1.1.1.1.2.2  pgoyette 			exit(0);
    399  1.1.1.1.2.2  pgoyette 		}
    400  1.1.1.1.2.2  pgoyette 		content = 1;
    401  1.1.1.1.2.2  pgoyette 		/* read away newline after --END CERT-- */
    402  1.1.1.1.2.2  pgoyette 		if(!fgets(buf, (int)sizeof(buf), in))
    403  1.1.1.1.2.2  pgoyette 			break;
    404  1.1.1.1.2.2  pgoyette 	}
    405  1.1.1.1.2.2  pgoyette 	fclose(in);
    406  1.1.1.1.2.2  pgoyette 	if(!content) {
    407  1.1.1.1.2.2  pgoyette 		if(verb) printf("%s is empty\n", file);
    408  1.1.1.1.2.2  pgoyette #ifndef S_SPLINT_S
    409  1.1.1.1.2.2  pgoyette 		sk_X509_pop_free(sk, X509_free);
    410  1.1.1.1.2.2  pgoyette #endif
    411  1.1.1.1.2.2  pgoyette 		return NULL;
    412  1.1.1.1.2.2  pgoyette 	}
    413  1.1.1.1.2.2  pgoyette 	return sk;
    414  1.1.1.1.2.2  pgoyette }
    415  1.1.1.1.2.2  pgoyette 
    416  1.1.1.1.2.2  pgoyette /** read certificates from the builtin certificate */
    417  1.1.1.1.2.2  pgoyette static STACK_OF(X509)*
    418  1.1.1.1.2.2  pgoyette read_builtin_cert(void)
    419  1.1.1.1.2.2  pgoyette {
    420  1.1.1.1.2.2  pgoyette 	const char* builtin_cert = get_builtin_cert();
    421  1.1.1.1.2.2  pgoyette 	STACK_OF(X509)* sk;
    422  1.1.1.1.2.2  pgoyette 	BIO *bio = BIO_new_mem_buf((void*)builtin_cert,
    423  1.1.1.1.2.2  pgoyette 		(int)strlen(builtin_cert));
    424  1.1.1.1.2.2  pgoyette 	if(!bio) {
    425  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
    426  1.1.1.1.2.2  pgoyette 		exit(0);
    427  1.1.1.1.2.2  pgoyette 	}
    428  1.1.1.1.2.2  pgoyette 	sk = read_cert_bio(bio);
    429  1.1.1.1.2.2  pgoyette 	if(!sk) {
    430  1.1.1.1.2.2  pgoyette 		if(verb) printf("internal error, out of memory\n");
    431  1.1.1.1.2.2  pgoyette 		exit(0);
    432  1.1.1.1.2.2  pgoyette 	}
    433  1.1.1.1.2.2  pgoyette 	BIO_free(bio);
    434  1.1.1.1.2.2  pgoyette 	return sk;
    435  1.1.1.1.2.2  pgoyette }
    436  1.1.1.1.2.2  pgoyette 
    437  1.1.1.1.2.2  pgoyette /** read update cert file or use builtin */
    438  1.1.1.1.2.2  pgoyette static STACK_OF(X509)*
    439  1.1.1.1.2.2  pgoyette read_cert_or_builtin(const char* file)
    440  1.1.1.1.2.2  pgoyette {
    441  1.1.1.1.2.2  pgoyette 	STACK_OF(X509) *sk = read_cert_file(file);
    442  1.1.1.1.2.2  pgoyette 	if(!sk) {
    443  1.1.1.1.2.2  pgoyette 		if(verb) printf("using builtin certificate\n");
    444  1.1.1.1.2.2  pgoyette 		sk = read_builtin_cert();
    445  1.1.1.1.2.2  pgoyette 	}
    446  1.1.1.1.2.2  pgoyette 	if(verb) printf("have %d trusted certificates\n", sk_X509_num(sk));
    447  1.1.1.1.2.2  pgoyette 	verb_certs("trusted certificates", sk);
    448  1.1.1.1.2.2  pgoyette 	return sk;
    449  1.1.1.1.2.2  pgoyette }
    450  1.1.1.1.2.2  pgoyette 
    451  1.1.1.1.2.2  pgoyette static void
    452  1.1.1.1.2.2  pgoyette do_list_builtin(void)
    453  1.1.1.1.2.2  pgoyette {
    454  1.1.1.1.2.2  pgoyette 	const char* builtin_cert = get_builtin_cert();
    455  1.1.1.1.2.2  pgoyette 	const char* builtin_ds = get_builtin_ds();
    456  1.1.1.1.2.2  pgoyette 	printf("%s\n", builtin_ds);
    457  1.1.1.1.2.2  pgoyette 	printf("%s\n", builtin_cert);
    458  1.1.1.1.2.2  pgoyette 	exit(0);
    459  1.1.1.1.2.2  pgoyette }
    460  1.1.1.1.2.2  pgoyette 
    461  1.1.1.1.2.2  pgoyette /** printout IP address with message */
    462  1.1.1.1.2.2  pgoyette static void
    463  1.1.1.1.2.2  pgoyette verb_addr(const char* msg, struct ip_list* ip)
    464  1.1.1.1.2.2  pgoyette {
    465  1.1.1.1.2.2  pgoyette 	if(verb) {
    466  1.1.1.1.2.2  pgoyette 		char out[100];
    467  1.1.1.1.2.2  pgoyette 		void* a = &((struct sockaddr_in*)&ip->addr)->sin_addr;
    468  1.1.1.1.2.2  pgoyette 		if(ip->len != (socklen_t)sizeof(struct sockaddr_in))
    469  1.1.1.1.2.2  pgoyette 			a = &((struct sockaddr_in6*)&ip->addr)->sin6_addr;
    470  1.1.1.1.2.2  pgoyette 
    471  1.1.1.1.2.2  pgoyette 		if(inet_ntop((int)((struct sockaddr_in*)&ip->addr)->sin_family,
    472  1.1.1.1.2.2  pgoyette 			a, out, (socklen_t)sizeof(out))==0)
    473  1.1.1.1.2.2  pgoyette 			printf("%s (inet_ntop error)\n", msg);
    474  1.1.1.1.2.2  pgoyette 		else printf("%s %s\n", msg, out);
    475  1.1.1.1.2.2  pgoyette 	}
    476  1.1.1.1.2.2  pgoyette }
    477  1.1.1.1.2.2  pgoyette 
    478  1.1.1.1.2.2  pgoyette /** free ip_list */
    479  1.1.1.1.2.2  pgoyette static void
    480  1.1.1.1.2.2  pgoyette ip_list_free(struct ip_list* p)
    481  1.1.1.1.2.2  pgoyette {
    482  1.1.1.1.2.2  pgoyette 	struct ip_list* np;
    483  1.1.1.1.2.2  pgoyette 	while(p) {
    484  1.1.1.1.2.2  pgoyette 		np = p->next;
    485  1.1.1.1.2.2  pgoyette 		free(p);
    486  1.1.1.1.2.2  pgoyette 		p = np;
    487  1.1.1.1.2.2  pgoyette 	}
    488  1.1.1.1.2.2  pgoyette }
    489  1.1.1.1.2.2  pgoyette 
    490  1.1.1.1.2.2  pgoyette /** create ip_list entry for a RR record */
    491  1.1.1.1.2.2  pgoyette static struct ip_list*
    492  1.1.1.1.2.2  pgoyette RR_to_ip(int tp, char* data, int len, int port)
    493  1.1.1.1.2.2  pgoyette {
    494  1.1.1.1.2.2  pgoyette 	struct ip_list* ip = (struct ip_list*)calloc(1, sizeof(*ip));
    495  1.1.1.1.2.2  pgoyette 	uint16_t p = (uint16_t)port;
    496  1.1.1.1.2.2  pgoyette 	if(tp == LDNS_RR_TYPE_A) {
    497  1.1.1.1.2.2  pgoyette 		struct sockaddr_in* sa = (struct sockaddr_in*)&ip->addr;
    498  1.1.1.1.2.2  pgoyette 		ip->len = (socklen_t)sizeof(*sa);
    499  1.1.1.1.2.2  pgoyette 		sa->sin_family = AF_INET;
    500  1.1.1.1.2.2  pgoyette 		sa->sin_port = (in_port_t)htons(p);
    501  1.1.1.1.2.2  pgoyette 		if(len != (int)sizeof(sa->sin_addr)) {
    502  1.1.1.1.2.2  pgoyette 			if(verb) printf("skipped badly formatted A\n");
    503  1.1.1.1.2.2  pgoyette 			free(ip);
    504  1.1.1.1.2.2  pgoyette 			return NULL;
    505  1.1.1.1.2.2  pgoyette 		}
    506  1.1.1.1.2.2  pgoyette 		memmove(&sa->sin_addr, data, sizeof(sa->sin_addr));
    507  1.1.1.1.2.2  pgoyette 
    508  1.1.1.1.2.2  pgoyette 	} else if(tp == LDNS_RR_TYPE_AAAA) {
    509  1.1.1.1.2.2  pgoyette 		struct sockaddr_in6* sa = (struct sockaddr_in6*)&ip->addr;
    510  1.1.1.1.2.2  pgoyette 		ip->len = (socklen_t)sizeof(*sa);
    511  1.1.1.1.2.2  pgoyette 		sa->sin6_family = AF_INET6;
    512  1.1.1.1.2.2  pgoyette 		sa->sin6_port = (in_port_t)htons(p);
    513  1.1.1.1.2.2  pgoyette 		if(len != (int)sizeof(sa->sin6_addr)) {
    514  1.1.1.1.2.2  pgoyette 			if(verb) printf("skipped badly formatted AAAA\n");
    515  1.1.1.1.2.2  pgoyette 			free(ip);
    516  1.1.1.1.2.2  pgoyette 			return NULL;
    517  1.1.1.1.2.2  pgoyette 		}
    518  1.1.1.1.2.2  pgoyette 		memmove(&sa->sin6_addr, data, sizeof(sa->sin6_addr));
    519  1.1.1.1.2.2  pgoyette 	} else {
    520  1.1.1.1.2.2  pgoyette 		if(verb) printf("internal error: bad type in RRtoip\n");
    521  1.1.1.1.2.2  pgoyette 		free(ip);
    522  1.1.1.1.2.2  pgoyette 		return NULL;
    523  1.1.1.1.2.2  pgoyette 	}
    524  1.1.1.1.2.2  pgoyette 	verb_addr("resolved server address", ip);
    525  1.1.1.1.2.2  pgoyette 	return ip;
    526  1.1.1.1.2.2  pgoyette }
    527  1.1.1.1.2.2  pgoyette 
    528  1.1.1.1.2.2  pgoyette /** Resolve name, type, class and add addresses to iplist */
    529  1.1.1.1.2.2  pgoyette static void
    530  1.1.1.1.2.2  pgoyette resolve_host_ip(struct ub_ctx* ctx, const char* host, int port, int tp, int cl,
    531  1.1.1.1.2.2  pgoyette 	struct ip_list** head)
    532  1.1.1.1.2.2  pgoyette {
    533  1.1.1.1.2.2  pgoyette 	struct ub_result* res = NULL;
    534  1.1.1.1.2.2  pgoyette 	int r;
    535  1.1.1.1.2.2  pgoyette 	int i;
    536  1.1.1.1.2.2  pgoyette 
    537  1.1.1.1.2.2  pgoyette 	r = ub_resolve(ctx, host, tp, cl, &res);
    538  1.1.1.1.2.2  pgoyette 	if(r) {
    539  1.1.1.1.2.2  pgoyette 		if(verb) printf("error: resolve %s %s: %s\n", host,
    540  1.1.1.1.2.2  pgoyette 			(tp==LDNS_RR_TYPE_A)?"A":"AAAA", ub_strerror(r));
    541  1.1.1.1.2.2  pgoyette 		return;
    542  1.1.1.1.2.2  pgoyette 	}
    543  1.1.1.1.2.2  pgoyette 	if(!res) {
    544  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
    545  1.1.1.1.2.2  pgoyette 		ub_ctx_delete(ctx);
    546  1.1.1.1.2.2  pgoyette 		exit(0);
    547  1.1.1.1.2.2  pgoyette 	}
    548  1.1.1.1.2.2  pgoyette 	if(!res->havedata || res->rcode || !res->data) {
    549  1.1.1.1.2.2  pgoyette 		if(verb) printf("resolve %s %s: no result\n", host,
    550  1.1.1.1.2.2  pgoyette 			(tp==LDNS_RR_TYPE_A)?"A":"AAAA");
    551  1.1.1.1.2.2  pgoyette 		return;
    552  1.1.1.1.2.2  pgoyette 	}
    553  1.1.1.1.2.2  pgoyette 	for(i = 0; res->data[i]; i++) {
    554  1.1.1.1.2.2  pgoyette 		struct ip_list* ip = RR_to_ip(tp, res->data[i], res->len[i],
    555  1.1.1.1.2.2  pgoyette 			port);
    556  1.1.1.1.2.2  pgoyette 		if(!ip) continue;
    557  1.1.1.1.2.2  pgoyette 		ip->next = *head;
    558  1.1.1.1.2.2  pgoyette 		*head = ip;
    559  1.1.1.1.2.2  pgoyette 	}
    560  1.1.1.1.2.2  pgoyette 	ub_resolve_free(res);
    561  1.1.1.1.2.2  pgoyette }
    562  1.1.1.1.2.2  pgoyette 
    563  1.1.1.1.2.2  pgoyette /** parse a text IP address into a sockaddr */
    564  1.1.1.1.2.2  pgoyette static struct ip_list*
    565  1.1.1.1.2.2  pgoyette parse_ip_addr(const char* str, int port)
    566  1.1.1.1.2.2  pgoyette {
    567  1.1.1.1.2.2  pgoyette 	socklen_t len = 0;
    568  1.1.1.1.2.2  pgoyette 	union {
    569  1.1.1.1.2.2  pgoyette 		struct sockaddr_in6 a6;
    570  1.1.1.1.2.2  pgoyette 		struct sockaddr_in a;
    571  1.1.1.1.2.2  pgoyette 	} addr;
    572  1.1.1.1.2.2  pgoyette 	struct ip_list* ip;
    573  1.1.1.1.2.2  pgoyette 	uint16_t p = (uint16_t)port;
    574  1.1.1.1.2.2  pgoyette 	memset(&addr, 0, sizeof(addr));
    575  1.1.1.1.2.2  pgoyette 
    576  1.1.1.1.2.2  pgoyette 	if(inet_pton(AF_INET6, str, &addr.a6.sin6_addr) > 0) {
    577  1.1.1.1.2.2  pgoyette 		/* it is an IPv6 */
    578  1.1.1.1.2.2  pgoyette 		addr.a6.sin6_family = AF_INET6;
    579  1.1.1.1.2.2  pgoyette 		addr.a6.sin6_port = (in_port_t)htons(p);
    580  1.1.1.1.2.2  pgoyette 		len = (socklen_t)sizeof(addr.a6);
    581  1.1.1.1.2.2  pgoyette 	}
    582  1.1.1.1.2.2  pgoyette 	if(inet_pton(AF_INET, str, &addr.a.sin_addr) > 0) {
    583  1.1.1.1.2.2  pgoyette 		/* it is an IPv4 */
    584  1.1.1.1.2.2  pgoyette 		addr.a.sin_family = AF_INET;
    585  1.1.1.1.2.2  pgoyette 		addr.a.sin_port = (in_port_t)htons(p);
    586  1.1.1.1.2.2  pgoyette 		len = (socklen_t)sizeof(struct sockaddr_in);
    587  1.1.1.1.2.2  pgoyette 	}
    588  1.1.1.1.2.2  pgoyette 	if(!len) return NULL;
    589  1.1.1.1.2.2  pgoyette 	ip = (struct ip_list*)calloc(1, sizeof(*ip));
    590  1.1.1.1.2.2  pgoyette 	if(!ip) {
    591  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
    592  1.1.1.1.2.2  pgoyette 		exit(0);
    593  1.1.1.1.2.2  pgoyette 	}
    594  1.1.1.1.2.2  pgoyette 	ip->len = len;
    595  1.1.1.1.2.2  pgoyette 	memmove(&ip->addr, &addr, len);
    596  1.1.1.1.2.2  pgoyette 	if(verb) printf("server address is %s\n", str);
    597  1.1.1.1.2.2  pgoyette 	return ip;
    598  1.1.1.1.2.2  pgoyette }
    599  1.1.1.1.2.2  pgoyette 
    600  1.1.1.1.2.2  pgoyette /**
    601  1.1.1.1.2.2  pgoyette  * Resolve a domain name (even though the resolver is down and there is
    602  1.1.1.1.2.2  pgoyette  * no trust anchor).  Without DNSSEC validation.
    603  1.1.1.1.2.2  pgoyette  * @param host: the name to resolve.
    604  1.1.1.1.2.2  pgoyette  * 	If this name is an IP4 or IP6 address this address is returned.
    605  1.1.1.1.2.2  pgoyette  * @param port: the port number used for the returned IP structs.
    606  1.1.1.1.2.2  pgoyette  * @param res_conf: resolv.conf (if any).
    607  1.1.1.1.2.2  pgoyette  * @param root_hints: root hints (if any).
    608  1.1.1.1.2.2  pgoyette  * @param debugconf: unbound.conf for debugging options.
    609  1.1.1.1.2.2  pgoyette  * @param ip4only: use only ip4 for resolve and only lookup A
    610  1.1.1.1.2.2  pgoyette  * @param ip6only: use only ip6 for resolve and only lookup AAAA
    611  1.1.1.1.2.2  pgoyette  * 	default is to lookup A and AAAA using ip4 and ip6.
    612  1.1.1.1.2.2  pgoyette  * @return list of IP addresses.
    613  1.1.1.1.2.2  pgoyette  */
    614  1.1.1.1.2.2  pgoyette static struct ip_list*
    615  1.1.1.1.2.2  pgoyette resolve_name(const char* host, int port, const char* res_conf,
    616  1.1.1.1.2.2  pgoyette 	const char* root_hints, const char* debugconf, int ip4only, int ip6only)
    617  1.1.1.1.2.2  pgoyette {
    618  1.1.1.1.2.2  pgoyette 	struct ub_ctx* ctx;
    619  1.1.1.1.2.2  pgoyette 	struct ip_list* list = NULL;
    620  1.1.1.1.2.2  pgoyette 	/* first see if name is an IP address itself */
    621  1.1.1.1.2.2  pgoyette 	if( (list=parse_ip_addr(host, port)) ) {
    622  1.1.1.1.2.2  pgoyette 		return list;
    623  1.1.1.1.2.2  pgoyette 	}
    624  1.1.1.1.2.2  pgoyette 
    625  1.1.1.1.2.2  pgoyette 	/* create resolver context */
    626  1.1.1.1.2.2  pgoyette 	ctx = create_unbound_context(res_conf, root_hints, debugconf,
    627  1.1.1.1.2.2  pgoyette         	ip4only, ip6only);
    628  1.1.1.1.2.2  pgoyette 
    629  1.1.1.1.2.2  pgoyette 	/* try resolution of A */
    630  1.1.1.1.2.2  pgoyette 	if(!ip6only) {
    631  1.1.1.1.2.2  pgoyette 		resolve_host_ip(ctx, host, port, LDNS_RR_TYPE_A,
    632  1.1.1.1.2.2  pgoyette 			LDNS_RR_CLASS_IN, &list);
    633  1.1.1.1.2.2  pgoyette 	}
    634  1.1.1.1.2.2  pgoyette 
    635  1.1.1.1.2.2  pgoyette 	/* try resolution of AAAA */
    636  1.1.1.1.2.2  pgoyette 	if(!ip4only) {
    637  1.1.1.1.2.2  pgoyette 		resolve_host_ip(ctx, host, port, LDNS_RR_TYPE_AAAA,
    638  1.1.1.1.2.2  pgoyette 			LDNS_RR_CLASS_IN, &list);
    639  1.1.1.1.2.2  pgoyette 	}
    640  1.1.1.1.2.2  pgoyette 
    641  1.1.1.1.2.2  pgoyette 	ub_ctx_delete(ctx);
    642  1.1.1.1.2.2  pgoyette 	if(!list) {
    643  1.1.1.1.2.2  pgoyette 		if(verb) printf("%s has no IP addresses I can use\n", host);
    644  1.1.1.1.2.2  pgoyette 		exit(0);
    645  1.1.1.1.2.2  pgoyette 	}
    646  1.1.1.1.2.2  pgoyette 	return list;
    647  1.1.1.1.2.2  pgoyette }
    648  1.1.1.1.2.2  pgoyette 
    649  1.1.1.1.2.2  pgoyette /** clear used flags */
    650  1.1.1.1.2.2  pgoyette static void
    651  1.1.1.1.2.2  pgoyette wipe_ip_usage(struct ip_list* p)
    652  1.1.1.1.2.2  pgoyette {
    653  1.1.1.1.2.2  pgoyette 	while(p) {
    654  1.1.1.1.2.2  pgoyette 		p->used = 0;
    655  1.1.1.1.2.2  pgoyette 		p = p->next;
    656  1.1.1.1.2.2  pgoyette 	}
    657  1.1.1.1.2.2  pgoyette }
    658  1.1.1.1.2.2  pgoyette 
    659  1.1.1.1.2.2  pgoyette /** cound unused IPs */
    660  1.1.1.1.2.2  pgoyette static int
    661  1.1.1.1.2.2  pgoyette count_unused(struct ip_list* p)
    662  1.1.1.1.2.2  pgoyette {
    663  1.1.1.1.2.2  pgoyette 	int num = 0;
    664  1.1.1.1.2.2  pgoyette 	while(p) {
    665  1.1.1.1.2.2  pgoyette 		if(!p->used) num++;
    666  1.1.1.1.2.2  pgoyette 		p = p->next;
    667  1.1.1.1.2.2  pgoyette 	}
    668  1.1.1.1.2.2  pgoyette 	return num;
    669  1.1.1.1.2.2  pgoyette }
    670  1.1.1.1.2.2  pgoyette 
    671  1.1.1.1.2.2  pgoyette /** pick random unused element from IP list */
    672  1.1.1.1.2.2  pgoyette static struct ip_list*
    673  1.1.1.1.2.2  pgoyette pick_random_ip(struct ip_list* list)
    674  1.1.1.1.2.2  pgoyette {
    675  1.1.1.1.2.2  pgoyette 	struct ip_list* p = list;
    676  1.1.1.1.2.2  pgoyette 	int num = count_unused(list);
    677  1.1.1.1.2.2  pgoyette 	int sel;
    678  1.1.1.1.2.2  pgoyette 	if(num == 0) return NULL;
    679  1.1.1.1.2.2  pgoyette 	/* not perfect, but random enough */
    680  1.1.1.1.2.2  pgoyette 	sel = (int)arc4random_uniform((uint32_t)num);
    681  1.1.1.1.2.2  pgoyette 	/* skip over unused elements that we did not select */
    682  1.1.1.1.2.2  pgoyette 	while(sel > 0 && p) {
    683  1.1.1.1.2.2  pgoyette 		if(!p->used) sel--;
    684  1.1.1.1.2.2  pgoyette 		p = p->next;
    685  1.1.1.1.2.2  pgoyette 	}
    686  1.1.1.1.2.2  pgoyette 	/* find the next unused element */
    687  1.1.1.1.2.2  pgoyette 	while(p && p->used)
    688  1.1.1.1.2.2  pgoyette 		p = p->next;
    689  1.1.1.1.2.2  pgoyette 	if(!p) return NULL; /* robustness */
    690  1.1.1.1.2.2  pgoyette 	return p;
    691  1.1.1.1.2.2  pgoyette }
    692  1.1.1.1.2.2  pgoyette 
    693  1.1.1.1.2.2  pgoyette /** close the fd */
    694  1.1.1.1.2.2  pgoyette static void
    695  1.1.1.1.2.2  pgoyette fd_close(int fd)
    696  1.1.1.1.2.2  pgoyette {
    697  1.1.1.1.2.2  pgoyette #ifndef USE_WINSOCK
    698  1.1.1.1.2.2  pgoyette 	close(fd);
    699  1.1.1.1.2.2  pgoyette #else
    700  1.1.1.1.2.2  pgoyette 	closesocket(fd);
    701  1.1.1.1.2.2  pgoyette #endif
    702  1.1.1.1.2.2  pgoyette }
    703  1.1.1.1.2.2  pgoyette 
    704  1.1.1.1.2.2  pgoyette /** printout socket errno */
    705  1.1.1.1.2.2  pgoyette static void
    706  1.1.1.1.2.2  pgoyette print_sock_err(const char* msg)
    707  1.1.1.1.2.2  pgoyette {
    708  1.1.1.1.2.2  pgoyette #ifndef USE_WINSOCK
    709  1.1.1.1.2.2  pgoyette 	if(verb) printf("%s: %s\n", msg, strerror(errno));
    710  1.1.1.1.2.2  pgoyette #else
    711  1.1.1.1.2.2  pgoyette 	if(verb) printf("%s: %s\n", msg, wsa_strerror(WSAGetLastError()));
    712  1.1.1.1.2.2  pgoyette #endif
    713  1.1.1.1.2.2  pgoyette }
    714  1.1.1.1.2.2  pgoyette 
    715  1.1.1.1.2.2  pgoyette /** connect to IP address */
    716  1.1.1.1.2.2  pgoyette static int
    717  1.1.1.1.2.2  pgoyette connect_to_ip(struct ip_list* ip)
    718  1.1.1.1.2.2  pgoyette {
    719  1.1.1.1.2.2  pgoyette 	int fd;
    720  1.1.1.1.2.2  pgoyette 	verb_addr("connect to", ip);
    721  1.1.1.1.2.2  pgoyette 	fd = socket(ip->len==(socklen_t)sizeof(struct sockaddr_in)?
    722  1.1.1.1.2.2  pgoyette 		AF_INET:AF_INET6, SOCK_STREAM, 0);
    723  1.1.1.1.2.2  pgoyette 	if(fd == -1) {
    724  1.1.1.1.2.2  pgoyette 		print_sock_err("socket");
    725  1.1.1.1.2.2  pgoyette 		return -1;
    726  1.1.1.1.2.2  pgoyette 	}
    727  1.1.1.1.2.2  pgoyette 	if(connect(fd, (struct sockaddr*)&ip->addr, ip->len) < 0) {
    728  1.1.1.1.2.2  pgoyette 		print_sock_err("connect");
    729  1.1.1.1.2.2  pgoyette 		fd_close(fd);
    730  1.1.1.1.2.2  pgoyette 		return -1;
    731  1.1.1.1.2.2  pgoyette 	}
    732  1.1.1.1.2.2  pgoyette 	return fd;
    733  1.1.1.1.2.2  pgoyette }
    734  1.1.1.1.2.2  pgoyette 
    735  1.1.1.1.2.2  pgoyette /** create SSL context */
    736  1.1.1.1.2.2  pgoyette static SSL_CTX*
    737  1.1.1.1.2.2  pgoyette setup_sslctx(void)
    738  1.1.1.1.2.2  pgoyette {
    739  1.1.1.1.2.2  pgoyette 	SSL_CTX* sslctx = SSL_CTX_new(SSLv23_client_method());
    740  1.1.1.1.2.2  pgoyette 	if(!sslctx) {
    741  1.1.1.1.2.2  pgoyette 		if(verb) printf("SSL_CTX_new error\n");
    742  1.1.1.1.2.2  pgoyette 		return NULL;
    743  1.1.1.1.2.2  pgoyette 	}
    744  1.1.1.1.2.2  pgoyette 	return sslctx;
    745  1.1.1.1.2.2  pgoyette }
    746  1.1.1.1.2.2  pgoyette 
    747  1.1.1.1.2.2  pgoyette /** initiate TLS on a connection */
    748  1.1.1.1.2.2  pgoyette static SSL*
    749  1.1.1.1.2.2  pgoyette TLS_initiate(SSL_CTX* sslctx, int fd)
    750  1.1.1.1.2.2  pgoyette {
    751  1.1.1.1.2.2  pgoyette 	X509* x;
    752  1.1.1.1.2.2  pgoyette 	int r;
    753  1.1.1.1.2.2  pgoyette 	SSL* ssl = SSL_new(sslctx);
    754  1.1.1.1.2.2  pgoyette 	if(!ssl) {
    755  1.1.1.1.2.2  pgoyette 		if(verb) printf("SSL_new error\n");
    756  1.1.1.1.2.2  pgoyette 		return NULL;
    757  1.1.1.1.2.2  pgoyette 	}
    758  1.1.1.1.2.2  pgoyette 	SSL_set_connect_state(ssl);
    759  1.1.1.1.2.2  pgoyette 	(void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
    760  1.1.1.1.2.2  pgoyette 	if(!SSL_set_fd(ssl, fd)) {
    761  1.1.1.1.2.2  pgoyette 		if(verb) printf("SSL_set_fd error\n");
    762  1.1.1.1.2.2  pgoyette 		SSL_free(ssl);
    763  1.1.1.1.2.2  pgoyette 		return NULL;
    764  1.1.1.1.2.2  pgoyette 	}
    765  1.1.1.1.2.2  pgoyette 	while(1) {
    766  1.1.1.1.2.2  pgoyette 		ERR_clear_error();
    767  1.1.1.1.2.2  pgoyette 		if( (r=SSL_do_handshake(ssl)) == 1)
    768  1.1.1.1.2.2  pgoyette 			break;
    769  1.1.1.1.2.2  pgoyette 		r = SSL_get_error(ssl, r);
    770  1.1.1.1.2.2  pgoyette 		if(r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) {
    771  1.1.1.1.2.2  pgoyette 			if(verb) printf("SSL handshake failed\n");
    772  1.1.1.1.2.2  pgoyette 			SSL_free(ssl);
    773  1.1.1.1.2.2  pgoyette 			return NULL;
    774  1.1.1.1.2.2  pgoyette 		}
    775  1.1.1.1.2.2  pgoyette 		/* wants to be called again */
    776  1.1.1.1.2.2  pgoyette 	}
    777  1.1.1.1.2.2  pgoyette 	x = SSL_get_peer_certificate(ssl);
    778  1.1.1.1.2.2  pgoyette 	if(!x) {
    779  1.1.1.1.2.2  pgoyette 		if(verb) printf("Server presented no peer certificate\n");
    780  1.1.1.1.2.2  pgoyette 		SSL_free(ssl);
    781  1.1.1.1.2.2  pgoyette 		return NULL;
    782  1.1.1.1.2.2  pgoyette 	}
    783  1.1.1.1.2.2  pgoyette 	verb_cert("server SSL certificate", x);
    784  1.1.1.1.2.2  pgoyette 	X509_free(x);
    785  1.1.1.1.2.2  pgoyette 	return ssl;
    786  1.1.1.1.2.2  pgoyette }
    787  1.1.1.1.2.2  pgoyette 
    788  1.1.1.1.2.2  pgoyette /** perform neat TLS shutdown */
    789  1.1.1.1.2.2  pgoyette static void
    790  1.1.1.1.2.2  pgoyette TLS_shutdown(int fd, SSL* ssl, SSL_CTX* sslctx)
    791  1.1.1.1.2.2  pgoyette {
    792  1.1.1.1.2.2  pgoyette 	/* shutdown the SSL connection nicely */
    793  1.1.1.1.2.2  pgoyette 	if(SSL_shutdown(ssl) == 0) {
    794  1.1.1.1.2.2  pgoyette 		SSL_shutdown(ssl);
    795  1.1.1.1.2.2  pgoyette 	}
    796  1.1.1.1.2.2  pgoyette 	SSL_free(ssl);
    797  1.1.1.1.2.2  pgoyette 	SSL_CTX_free(sslctx);
    798  1.1.1.1.2.2  pgoyette 	fd_close(fd);
    799  1.1.1.1.2.2  pgoyette }
    800  1.1.1.1.2.2  pgoyette 
    801  1.1.1.1.2.2  pgoyette /** write a line over SSL */
    802  1.1.1.1.2.2  pgoyette static int
    803  1.1.1.1.2.2  pgoyette write_ssl_line(SSL* ssl, const char* str, const char* sec)
    804  1.1.1.1.2.2  pgoyette {
    805  1.1.1.1.2.2  pgoyette 	char buf[1024];
    806  1.1.1.1.2.2  pgoyette 	size_t l;
    807  1.1.1.1.2.2  pgoyette 	if(sec) {
    808  1.1.1.1.2.2  pgoyette 		snprintf(buf, sizeof(buf), str, sec);
    809  1.1.1.1.2.2  pgoyette 	} else {
    810  1.1.1.1.2.2  pgoyette 		snprintf(buf, sizeof(buf), "%s", str);
    811  1.1.1.1.2.2  pgoyette 	}
    812  1.1.1.1.2.2  pgoyette 	l = strlen(buf);
    813  1.1.1.1.2.2  pgoyette 	if(l+2 >= sizeof(buf)) {
    814  1.1.1.1.2.2  pgoyette 		if(verb) printf("line too long\n");
    815  1.1.1.1.2.2  pgoyette 		return 0;
    816  1.1.1.1.2.2  pgoyette 	}
    817  1.1.1.1.2.2  pgoyette 	if(verb >= 2) printf("SSL_write: %s\n", buf);
    818  1.1.1.1.2.2  pgoyette 	buf[l] = '\r';
    819  1.1.1.1.2.2  pgoyette 	buf[l+1] = '\n';
    820  1.1.1.1.2.2  pgoyette 	buf[l+2] = 0;
    821  1.1.1.1.2.2  pgoyette 	/* add \r\n */
    822  1.1.1.1.2.2  pgoyette 	if(SSL_write(ssl, buf, (int)strlen(buf)) <= 0) {
    823  1.1.1.1.2.2  pgoyette 		if(verb) printf("could not SSL_write %s", str);
    824  1.1.1.1.2.2  pgoyette 		return 0;
    825  1.1.1.1.2.2  pgoyette 	}
    826  1.1.1.1.2.2  pgoyette 	return 1;
    827  1.1.1.1.2.2  pgoyette }
    828  1.1.1.1.2.2  pgoyette 
    829  1.1.1.1.2.2  pgoyette /** process header line, check rcode and keeping track of size */
    830  1.1.1.1.2.2  pgoyette static int
    831  1.1.1.1.2.2  pgoyette process_one_header(char* buf, size_t* clen, int* chunked)
    832  1.1.1.1.2.2  pgoyette {
    833  1.1.1.1.2.2  pgoyette 	if(verb>=2) printf("header: '%s'\n", buf);
    834  1.1.1.1.2.2  pgoyette 	if(strncasecmp(buf, "HTTP/1.1 ", 9) == 0) {
    835  1.1.1.1.2.2  pgoyette 		/* check returncode */
    836  1.1.1.1.2.2  pgoyette 		if(buf[9] != '2') {
    837  1.1.1.1.2.2  pgoyette 			if(verb) printf("bad status %s\n", buf+9);
    838  1.1.1.1.2.2  pgoyette 			return 0;
    839  1.1.1.1.2.2  pgoyette 		}
    840  1.1.1.1.2.2  pgoyette 	} else if(strncasecmp(buf, "Content-Length: ", 16) == 0) {
    841  1.1.1.1.2.2  pgoyette 		if(!*chunked)
    842  1.1.1.1.2.2  pgoyette 			*clen = (size_t)atoi(buf+16);
    843  1.1.1.1.2.2  pgoyette 	} else if(strncasecmp(buf, "Transfer-Encoding: chunked", 19+7) == 0) {
    844  1.1.1.1.2.2  pgoyette 		*clen = 0;
    845  1.1.1.1.2.2  pgoyette 		*chunked = 1;
    846  1.1.1.1.2.2  pgoyette 	}
    847  1.1.1.1.2.2  pgoyette 	return 1;
    848  1.1.1.1.2.2  pgoyette }
    849  1.1.1.1.2.2  pgoyette 
    850  1.1.1.1.2.2  pgoyette /**
    851  1.1.1.1.2.2  pgoyette  * Read one line from SSL
    852  1.1.1.1.2.2  pgoyette  * zero terminates.
    853  1.1.1.1.2.2  pgoyette  * skips "\r\n" (but not copied to buf).
    854  1.1.1.1.2.2  pgoyette  * @param ssl: the SSL connection to read from (blocking).
    855  1.1.1.1.2.2  pgoyette  * @param buf: buffer to return line in.
    856  1.1.1.1.2.2  pgoyette  * @param len: size of the buffer.
    857  1.1.1.1.2.2  pgoyette  * @return 0 on error, 1 on success.
    858  1.1.1.1.2.2  pgoyette  */
    859  1.1.1.1.2.2  pgoyette static int
    860  1.1.1.1.2.2  pgoyette read_ssl_line(SSL* ssl, char* buf, size_t len)
    861  1.1.1.1.2.2  pgoyette {
    862  1.1.1.1.2.2  pgoyette 	size_t n = 0;
    863  1.1.1.1.2.2  pgoyette 	int r;
    864  1.1.1.1.2.2  pgoyette 	int endnl = 0;
    865  1.1.1.1.2.2  pgoyette 	while(1) {
    866  1.1.1.1.2.2  pgoyette 		if(n >= len) {
    867  1.1.1.1.2.2  pgoyette 			if(verb) printf("line too long\n");
    868  1.1.1.1.2.2  pgoyette 			return 0;
    869  1.1.1.1.2.2  pgoyette 		}
    870  1.1.1.1.2.2  pgoyette 		if((r = SSL_read(ssl, buf+n, 1)) <= 0) {
    871  1.1.1.1.2.2  pgoyette 			if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
    872  1.1.1.1.2.2  pgoyette 				/* EOF */
    873  1.1.1.1.2.2  pgoyette 				break;
    874  1.1.1.1.2.2  pgoyette 			}
    875  1.1.1.1.2.2  pgoyette 			if(verb) printf("could not SSL_read\n");
    876  1.1.1.1.2.2  pgoyette 			return 0;
    877  1.1.1.1.2.2  pgoyette 		}
    878  1.1.1.1.2.2  pgoyette 		if(endnl && buf[n] == '\n') {
    879  1.1.1.1.2.2  pgoyette 			break;
    880  1.1.1.1.2.2  pgoyette 		} else if(endnl) {
    881  1.1.1.1.2.2  pgoyette 			/* bad data */
    882  1.1.1.1.2.2  pgoyette 			if(verb) printf("error: stray linefeeds\n");
    883  1.1.1.1.2.2  pgoyette 			return 0;
    884  1.1.1.1.2.2  pgoyette 		} else if(buf[n] == '\r') {
    885  1.1.1.1.2.2  pgoyette 			/* skip \r, and also \n on the wire */
    886  1.1.1.1.2.2  pgoyette 			endnl = 1;
    887  1.1.1.1.2.2  pgoyette 			continue;
    888  1.1.1.1.2.2  pgoyette 		} else if(buf[n] == '\n') {
    889  1.1.1.1.2.2  pgoyette 			/* skip the \n, we are done */
    890  1.1.1.1.2.2  pgoyette 			break;
    891  1.1.1.1.2.2  pgoyette 		} else n++;
    892  1.1.1.1.2.2  pgoyette 	}
    893  1.1.1.1.2.2  pgoyette 	buf[n] = 0;
    894  1.1.1.1.2.2  pgoyette 	return 1;
    895  1.1.1.1.2.2  pgoyette }
    896  1.1.1.1.2.2  pgoyette 
    897  1.1.1.1.2.2  pgoyette /** read http headers and process them */
    898  1.1.1.1.2.2  pgoyette static size_t
    899  1.1.1.1.2.2  pgoyette read_http_headers(SSL* ssl, size_t* clen)
    900  1.1.1.1.2.2  pgoyette {
    901  1.1.1.1.2.2  pgoyette 	char buf[1024];
    902  1.1.1.1.2.2  pgoyette 	int chunked = 0;
    903  1.1.1.1.2.2  pgoyette 	*clen = 0;
    904  1.1.1.1.2.2  pgoyette 	while(read_ssl_line(ssl, buf, sizeof(buf))) {
    905  1.1.1.1.2.2  pgoyette 		if(buf[0] == 0)
    906  1.1.1.1.2.2  pgoyette 			return 1;
    907  1.1.1.1.2.2  pgoyette 		if(!process_one_header(buf, clen, &chunked))
    908  1.1.1.1.2.2  pgoyette 			return 0;
    909  1.1.1.1.2.2  pgoyette 	}
    910  1.1.1.1.2.2  pgoyette 	return 0;
    911  1.1.1.1.2.2  pgoyette }
    912  1.1.1.1.2.2  pgoyette 
    913  1.1.1.1.2.2  pgoyette /** read a data chunk */
    914  1.1.1.1.2.2  pgoyette static char*
    915  1.1.1.1.2.2  pgoyette read_data_chunk(SSL* ssl, size_t len)
    916  1.1.1.1.2.2  pgoyette {
    917  1.1.1.1.2.2  pgoyette 	size_t got = 0;
    918  1.1.1.1.2.2  pgoyette 	int r;
    919  1.1.1.1.2.2  pgoyette 	char* data;
    920  1.1.1.1.2.2  pgoyette 	if(len >= 0xfffffff0)
    921  1.1.1.1.2.2  pgoyette 		return NULL; /* to protect against integer overflow in malloc*/
    922  1.1.1.1.2.2  pgoyette 	data = malloc(len+1);
    923  1.1.1.1.2.2  pgoyette 	if(!data) {
    924  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
    925  1.1.1.1.2.2  pgoyette 		return NULL;
    926  1.1.1.1.2.2  pgoyette 	}
    927  1.1.1.1.2.2  pgoyette 	while(got < len) {
    928  1.1.1.1.2.2  pgoyette 		if((r = SSL_read(ssl, data+got, (int)(len-got))) <= 0) {
    929  1.1.1.1.2.2  pgoyette 			if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
    930  1.1.1.1.2.2  pgoyette 				/* EOF */
    931  1.1.1.1.2.2  pgoyette 				if(verb) printf("could not SSL_read: unexpected EOF\n");
    932  1.1.1.1.2.2  pgoyette 				free(data);
    933  1.1.1.1.2.2  pgoyette 				return NULL;
    934  1.1.1.1.2.2  pgoyette 			}
    935  1.1.1.1.2.2  pgoyette 			if(verb) printf("could not SSL_read\n");
    936  1.1.1.1.2.2  pgoyette 			free(data);
    937  1.1.1.1.2.2  pgoyette 			return NULL;
    938  1.1.1.1.2.2  pgoyette 		}
    939  1.1.1.1.2.2  pgoyette 		if(verb >= 2) printf("at %d/%d\n", (int)got, (int)len);
    940  1.1.1.1.2.2  pgoyette 		got += r;
    941  1.1.1.1.2.2  pgoyette 	}
    942  1.1.1.1.2.2  pgoyette 	if(verb>=2) printf("read %d data\n", (int)len);
    943  1.1.1.1.2.2  pgoyette 	data[len] = 0;
    944  1.1.1.1.2.2  pgoyette 	return data;
    945  1.1.1.1.2.2  pgoyette }
    946  1.1.1.1.2.2  pgoyette 
    947  1.1.1.1.2.2  pgoyette /** parse chunk header */
    948  1.1.1.1.2.2  pgoyette static int
    949  1.1.1.1.2.2  pgoyette parse_chunk_header(char* buf, size_t* result)
    950  1.1.1.1.2.2  pgoyette {
    951  1.1.1.1.2.2  pgoyette 	char* e = NULL;
    952  1.1.1.1.2.2  pgoyette 	size_t v = (size_t)strtol(buf, &e, 16);
    953  1.1.1.1.2.2  pgoyette 	if(e == buf)
    954  1.1.1.1.2.2  pgoyette 		return 0;
    955  1.1.1.1.2.2  pgoyette 	*result = v;
    956  1.1.1.1.2.2  pgoyette 	return 1;
    957  1.1.1.1.2.2  pgoyette }
    958  1.1.1.1.2.2  pgoyette 
    959  1.1.1.1.2.2  pgoyette /** read chunked data from connection */
    960  1.1.1.1.2.2  pgoyette static BIO*
    961  1.1.1.1.2.2  pgoyette do_chunked_read(SSL* ssl)
    962  1.1.1.1.2.2  pgoyette {
    963  1.1.1.1.2.2  pgoyette 	char buf[1024];
    964  1.1.1.1.2.2  pgoyette 	size_t len;
    965  1.1.1.1.2.2  pgoyette 	char* body;
    966  1.1.1.1.2.2  pgoyette 	BIO* mem = BIO_new(BIO_s_mem());
    967  1.1.1.1.2.2  pgoyette 	if(verb>=3) printf("do_chunked_read\n");
    968  1.1.1.1.2.2  pgoyette 	if(!mem) {
    969  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
    970  1.1.1.1.2.2  pgoyette 		return NULL;
    971  1.1.1.1.2.2  pgoyette 	}
    972  1.1.1.1.2.2  pgoyette 	while(read_ssl_line(ssl, buf, sizeof(buf))) {
    973  1.1.1.1.2.2  pgoyette 		/* read the chunked start line */
    974  1.1.1.1.2.2  pgoyette 		if(verb>=2) printf("chunk header: %s\n", buf);
    975  1.1.1.1.2.2  pgoyette 		if(!parse_chunk_header(buf, &len)) {
    976  1.1.1.1.2.2  pgoyette 			BIO_free(mem);
    977  1.1.1.1.2.2  pgoyette 			if(verb>=3) printf("could not parse chunk header\n");
    978  1.1.1.1.2.2  pgoyette 			return NULL;
    979  1.1.1.1.2.2  pgoyette 		}
    980  1.1.1.1.2.2  pgoyette 		if(verb>=2) printf("chunk len: %d\n", (int)len);
    981  1.1.1.1.2.2  pgoyette 		/* are we done? */
    982  1.1.1.1.2.2  pgoyette 		if(len == 0) {
    983  1.1.1.1.2.2  pgoyette 			char z = 0;
    984  1.1.1.1.2.2  pgoyette 			/* skip end-of-chunk-trailer lines,
    985  1.1.1.1.2.2  pgoyette 			 * until the empty line after that */
    986  1.1.1.1.2.2  pgoyette 			do {
    987  1.1.1.1.2.2  pgoyette 				if(!read_ssl_line(ssl, buf, sizeof(buf))) {
    988  1.1.1.1.2.2  pgoyette 					BIO_free(mem);
    989  1.1.1.1.2.2  pgoyette 					return NULL;
    990  1.1.1.1.2.2  pgoyette 				}
    991  1.1.1.1.2.2  pgoyette 			} while (strlen(buf) > 0);
    992  1.1.1.1.2.2  pgoyette 			/* end of chunks, zero terminate it */
    993  1.1.1.1.2.2  pgoyette 			if(BIO_write(mem, &z, 1) <= 0) {
    994  1.1.1.1.2.2  pgoyette 				if(verb) printf("out of memory\n");
    995  1.1.1.1.2.2  pgoyette 				BIO_free(mem);
    996  1.1.1.1.2.2  pgoyette 				return NULL;
    997  1.1.1.1.2.2  pgoyette 			}
    998  1.1.1.1.2.2  pgoyette 			return mem;
    999  1.1.1.1.2.2  pgoyette 		}
   1000  1.1.1.1.2.2  pgoyette 		/* read the chunked body */
   1001  1.1.1.1.2.2  pgoyette 		body = read_data_chunk(ssl, len);
   1002  1.1.1.1.2.2  pgoyette 		if(!body) {
   1003  1.1.1.1.2.2  pgoyette 			BIO_free(mem);
   1004  1.1.1.1.2.2  pgoyette 			return NULL;
   1005  1.1.1.1.2.2  pgoyette 		}
   1006  1.1.1.1.2.2  pgoyette 		if(BIO_write(mem, body, (int)len) <= 0) {
   1007  1.1.1.1.2.2  pgoyette 			if(verb) printf("out of memory\n");
   1008  1.1.1.1.2.2  pgoyette 			free(body);
   1009  1.1.1.1.2.2  pgoyette 			BIO_free(mem);
   1010  1.1.1.1.2.2  pgoyette 			return NULL;
   1011  1.1.1.1.2.2  pgoyette 		}
   1012  1.1.1.1.2.2  pgoyette 		free(body);
   1013  1.1.1.1.2.2  pgoyette 		/* skip empty line after data chunk */
   1014  1.1.1.1.2.2  pgoyette 		if(!read_ssl_line(ssl, buf, sizeof(buf))) {
   1015  1.1.1.1.2.2  pgoyette 			BIO_free(mem);
   1016  1.1.1.1.2.2  pgoyette 			return NULL;
   1017  1.1.1.1.2.2  pgoyette 		}
   1018  1.1.1.1.2.2  pgoyette 	}
   1019  1.1.1.1.2.2  pgoyette 	BIO_free(mem);
   1020  1.1.1.1.2.2  pgoyette 	return NULL;
   1021  1.1.1.1.2.2  pgoyette }
   1022  1.1.1.1.2.2  pgoyette 
   1023  1.1.1.1.2.2  pgoyette /** start HTTP1.1 transaction on SSL */
   1024  1.1.1.1.2.2  pgoyette static int
   1025  1.1.1.1.2.2  pgoyette write_http_get(SSL* ssl, const char* pathname, const char* urlname)
   1026  1.1.1.1.2.2  pgoyette {
   1027  1.1.1.1.2.2  pgoyette 	if(write_ssl_line(ssl, "GET /%s HTTP/1.1", pathname) &&
   1028  1.1.1.1.2.2  pgoyette 	   write_ssl_line(ssl, "Host: %s", urlname) &&
   1029  1.1.1.1.2.2  pgoyette 	   write_ssl_line(ssl, "User-Agent: unbound-anchor/%s",
   1030  1.1.1.1.2.2  pgoyette 	   	PACKAGE_VERSION) &&
   1031  1.1.1.1.2.2  pgoyette 	   /* We do not really do multiple queries per connection,
   1032  1.1.1.1.2.2  pgoyette 	    * but this header setting is also not needed.
   1033  1.1.1.1.2.2  pgoyette 	    * write_ssl_line(ssl, "Connection: close", NULL) &&*/
   1034  1.1.1.1.2.2  pgoyette 	   write_ssl_line(ssl, "", NULL)) {
   1035  1.1.1.1.2.2  pgoyette 		return 1;
   1036  1.1.1.1.2.2  pgoyette 	}
   1037  1.1.1.1.2.2  pgoyette 	return 0;
   1038  1.1.1.1.2.2  pgoyette }
   1039  1.1.1.1.2.2  pgoyette 
   1040  1.1.1.1.2.2  pgoyette /** read chunked data and zero terminate; len is without zero */
   1041  1.1.1.1.2.2  pgoyette static char*
   1042  1.1.1.1.2.2  pgoyette read_chunked_zero_terminate(SSL* ssl, size_t* len)
   1043  1.1.1.1.2.2  pgoyette {
   1044  1.1.1.1.2.2  pgoyette 	/* do the chunked version */
   1045  1.1.1.1.2.2  pgoyette 	BIO* tmp = do_chunked_read(ssl);
   1046  1.1.1.1.2.2  pgoyette 	char* data, *d = NULL;
   1047  1.1.1.1.2.2  pgoyette 	size_t l;
   1048  1.1.1.1.2.2  pgoyette 	if(!tmp) {
   1049  1.1.1.1.2.2  pgoyette 		if(verb) printf("could not read from https\n");
   1050  1.1.1.1.2.2  pgoyette 		return NULL;
   1051  1.1.1.1.2.2  pgoyette 	}
   1052  1.1.1.1.2.2  pgoyette 	l = (size_t)BIO_get_mem_data(tmp, &d);
   1053  1.1.1.1.2.2  pgoyette 	if(verb>=2) printf("chunked data is %d\n", (int)l);
   1054  1.1.1.1.2.2  pgoyette 	if(l == 0 || d == NULL) {
   1055  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   1056  1.1.1.1.2.2  pgoyette 		return NULL;
   1057  1.1.1.1.2.2  pgoyette 	}
   1058  1.1.1.1.2.2  pgoyette 	*len = l-1;
   1059  1.1.1.1.2.2  pgoyette 	data = (char*)malloc(l);
   1060  1.1.1.1.2.2  pgoyette 	if(data == NULL) {
   1061  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   1062  1.1.1.1.2.2  pgoyette 		return NULL;
   1063  1.1.1.1.2.2  pgoyette 	}
   1064  1.1.1.1.2.2  pgoyette 	memcpy(data, d, l);
   1065  1.1.1.1.2.2  pgoyette 	BIO_free(tmp);
   1066  1.1.1.1.2.2  pgoyette 	return data;
   1067  1.1.1.1.2.2  pgoyette }
   1068  1.1.1.1.2.2  pgoyette 
   1069  1.1.1.1.2.2  pgoyette /** read HTTP result from SSL */
   1070  1.1.1.1.2.2  pgoyette static BIO*
   1071  1.1.1.1.2.2  pgoyette read_http_result(SSL* ssl)
   1072  1.1.1.1.2.2  pgoyette {
   1073  1.1.1.1.2.2  pgoyette 	size_t len = 0;
   1074  1.1.1.1.2.2  pgoyette 	char* data;
   1075  1.1.1.1.2.2  pgoyette 	BIO* m;
   1076  1.1.1.1.2.2  pgoyette 	if(!read_http_headers(ssl, &len)) {
   1077  1.1.1.1.2.2  pgoyette 		return NULL;
   1078  1.1.1.1.2.2  pgoyette 	}
   1079  1.1.1.1.2.2  pgoyette 	if(len == 0) {
   1080  1.1.1.1.2.2  pgoyette 		data = read_chunked_zero_terminate(ssl, &len);
   1081  1.1.1.1.2.2  pgoyette 	} else {
   1082  1.1.1.1.2.2  pgoyette 		data = read_data_chunk(ssl, len);
   1083  1.1.1.1.2.2  pgoyette 	}
   1084  1.1.1.1.2.2  pgoyette 	if(!data) return NULL;
   1085  1.1.1.1.2.2  pgoyette 	if(verb >= 4) print_data("read data", data, (int)len);
   1086  1.1.1.1.2.2  pgoyette 	m = BIO_new_mem_buf(data, (int)len);
   1087  1.1.1.1.2.2  pgoyette 	if(!m) {
   1088  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   1089  1.1.1.1.2.2  pgoyette 		exit(0);
   1090  1.1.1.1.2.2  pgoyette 	}
   1091  1.1.1.1.2.2  pgoyette 	return m;
   1092  1.1.1.1.2.2  pgoyette }
   1093  1.1.1.1.2.2  pgoyette 
   1094  1.1.1.1.2.2  pgoyette /** https to an IP addr, return BIO with pathname or NULL */
   1095  1.1.1.1.2.2  pgoyette static BIO*
   1096  1.1.1.1.2.2  pgoyette https_to_ip(struct ip_list* ip, const char* pathname, const char* urlname)
   1097  1.1.1.1.2.2  pgoyette {
   1098  1.1.1.1.2.2  pgoyette 	int fd;
   1099  1.1.1.1.2.2  pgoyette 	SSL* ssl;
   1100  1.1.1.1.2.2  pgoyette 	BIO* bio;
   1101  1.1.1.1.2.2  pgoyette 	SSL_CTX* sslctx = setup_sslctx();
   1102  1.1.1.1.2.2  pgoyette 	if(!sslctx) {
   1103  1.1.1.1.2.2  pgoyette 		return NULL;
   1104  1.1.1.1.2.2  pgoyette 	}
   1105  1.1.1.1.2.2  pgoyette 	fd = connect_to_ip(ip);
   1106  1.1.1.1.2.2  pgoyette 	if(fd == -1) {
   1107  1.1.1.1.2.2  pgoyette 		SSL_CTX_free(sslctx);
   1108  1.1.1.1.2.2  pgoyette 		return NULL;
   1109  1.1.1.1.2.2  pgoyette 	}
   1110  1.1.1.1.2.2  pgoyette 	ssl = TLS_initiate(sslctx, fd);
   1111  1.1.1.1.2.2  pgoyette 	if(!ssl) {
   1112  1.1.1.1.2.2  pgoyette 		SSL_CTX_free(sslctx);
   1113  1.1.1.1.2.2  pgoyette 		fd_close(fd);
   1114  1.1.1.1.2.2  pgoyette 		return NULL;
   1115  1.1.1.1.2.2  pgoyette 	}
   1116  1.1.1.1.2.2  pgoyette 	if(!write_http_get(ssl, pathname, urlname)) {
   1117  1.1.1.1.2.2  pgoyette 		if(verb) printf("could not write to server\n");
   1118  1.1.1.1.2.2  pgoyette 		SSL_free(ssl);
   1119  1.1.1.1.2.2  pgoyette 		SSL_CTX_free(sslctx);
   1120  1.1.1.1.2.2  pgoyette 		fd_close(fd);
   1121  1.1.1.1.2.2  pgoyette 		return NULL;
   1122  1.1.1.1.2.2  pgoyette 	}
   1123  1.1.1.1.2.2  pgoyette 	bio = read_http_result(ssl);
   1124  1.1.1.1.2.2  pgoyette 	TLS_shutdown(fd, ssl, sslctx);
   1125  1.1.1.1.2.2  pgoyette 	return bio;
   1126  1.1.1.1.2.2  pgoyette }
   1127  1.1.1.1.2.2  pgoyette 
   1128  1.1.1.1.2.2  pgoyette /**
   1129  1.1.1.1.2.2  pgoyette  * Do a HTTPS, HTTP1.1 over TLS, to fetch a file
   1130  1.1.1.1.2.2  pgoyette  * @param ip_list: list of IP addresses to use to fetch from.
   1131  1.1.1.1.2.2  pgoyette  * @param pathname: pathname of file on server to GET.
   1132  1.1.1.1.2.2  pgoyette  * @param urlname: name to pass as the virtual host for this request.
   1133  1.1.1.1.2.2  pgoyette  * @return a memory BIO with the file in it.
   1134  1.1.1.1.2.2  pgoyette  */
   1135  1.1.1.1.2.2  pgoyette static BIO*
   1136  1.1.1.1.2.2  pgoyette https(struct ip_list* ip_list, const char* pathname, const char* urlname)
   1137  1.1.1.1.2.2  pgoyette {
   1138  1.1.1.1.2.2  pgoyette 	struct ip_list* ip;
   1139  1.1.1.1.2.2  pgoyette 	BIO* bio = NULL;
   1140  1.1.1.1.2.2  pgoyette 	/* try random address first, and work through the list */
   1141  1.1.1.1.2.2  pgoyette 	wipe_ip_usage(ip_list);
   1142  1.1.1.1.2.2  pgoyette 	while( (ip = pick_random_ip(ip_list)) ) {
   1143  1.1.1.1.2.2  pgoyette 		ip->used = 1;
   1144  1.1.1.1.2.2  pgoyette 		bio = https_to_ip(ip, pathname, urlname);
   1145  1.1.1.1.2.2  pgoyette 		if(bio) break;
   1146  1.1.1.1.2.2  pgoyette 	}
   1147  1.1.1.1.2.2  pgoyette 	if(!bio) {
   1148  1.1.1.1.2.2  pgoyette 		if(verb) printf("could not fetch %s\n", pathname);
   1149  1.1.1.1.2.2  pgoyette 		exit(0);
   1150  1.1.1.1.2.2  pgoyette 	} else {
   1151  1.1.1.1.2.2  pgoyette 		if(verb) printf("fetched %s (%d bytes)\n",
   1152  1.1.1.1.2.2  pgoyette 			pathname, (int)BIO_ctrl_pending(bio));
   1153  1.1.1.1.2.2  pgoyette 	}
   1154  1.1.1.1.2.2  pgoyette 	return bio;
   1155  1.1.1.1.2.2  pgoyette }
   1156  1.1.1.1.2.2  pgoyette 
   1157  1.1.1.1.2.2  pgoyette /** free up a downloaded file BIO */
   1158  1.1.1.1.2.2  pgoyette static void
   1159  1.1.1.1.2.2  pgoyette free_file_bio(BIO* bio)
   1160  1.1.1.1.2.2  pgoyette {
   1161  1.1.1.1.2.2  pgoyette 	char* pp = NULL;
   1162  1.1.1.1.2.2  pgoyette 	(void)BIO_reset(bio);
   1163  1.1.1.1.2.2  pgoyette 	(void)BIO_get_mem_data(bio, &pp);
   1164  1.1.1.1.2.2  pgoyette 	free(pp);
   1165  1.1.1.1.2.2  pgoyette 	BIO_free(bio);
   1166  1.1.1.1.2.2  pgoyette }
   1167  1.1.1.1.2.2  pgoyette 
   1168  1.1.1.1.2.2  pgoyette /** XML parse private data during the parse */
   1169  1.1.1.1.2.2  pgoyette struct xml_data {
   1170  1.1.1.1.2.2  pgoyette 	/** the parser, reference */
   1171  1.1.1.1.2.2  pgoyette 	XML_Parser parser;
   1172  1.1.1.1.2.2  pgoyette 	/** the current tag; malloced; or NULL outside of tags */
   1173  1.1.1.1.2.2  pgoyette 	char* tag;
   1174  1.1.1.1.2.2  pgoyette 	/** current date to use during the parse */
   1175  1.1.1.1.2.2  pgoyette 	time_t date;
   1176  1.1.1.1.2.2  pgoyette 	/** number of keys usefully read in */
   1177  1.1.1.1.2.2  pgoyette 	int num_keys;
   1178  1.1.1.1.2.2  pgoyette 	/** the compiled anchors as DS records */
   1179  1.1.1.1.2.2  pgoyette 	BIO* ds;
   1180  1.1.1.1.2.2  pgoyette 
   1181  1.1.1.1.2.2  pgoyette 	/** do we want to use this anchor? */
   1182  1.1.1.1.2.2  pgoyette 	int use_key;
   1183  1.1.1.1.2.2  pgoyette 	/** the current anchor: Zone */
   1184  1.1.1.1.2.2  pgoyette 	BIO* czone;
   1185  1.1.1.1.2.2  pgoyette 	/** the current anchor: KeyTag */
   1186  1.1.1.1.2.2  pgoyette 	BIO* ctag;
   1187  1.1.1.1.2.2  pgoyette 	/** the current anchor: Algorithm */
   1188  1.1.1.1.2.2  pgoyette 	BIO* calgo;
   1189  1.1.1.1.2.2  pgoyette 	/** the current anchor: DigestType */
   1190  1.1.1.1.2.2  pgoyette 	BIO* cdigtype;
   1191  1.1.1.1.2.2  pgoyette 	/** the current anchor: Digest*/
   1192  1.1.1.1.2.2  pgoyette 	BIO* cdigest;
   1193  1.1.1.1.2.2  pgoyette };
   1194  1.1.1.1.2.2  pgoyette 
   1195  1.1.1.1.2.2  pgoyette /** The BIO for the tag */
   1196  1.1.1.1.2.2  pgoyette static BIO*
   1197  1.1.1.1.2.2  pgoyette xml_selectbio(struct xml_data* data, const char* tag)
   1198  1.1.1.1.2.2  pgoyette {
   1199  1.1.1.1.2.2  pgoyette 	BIO* b = NULL;
   1200  1.1.1.1.2.2  pgoyette 	if(strcasecmp(tag, "KeyTag") == 0)
   1201  1.1.1.1.2.2  pgoyette 		b = data->ctag;
   1202  1.1.1.1.2.2  pgoyette 	else if(strcasecmp(tag, "Algorithm") == 0)
   1203  1.1.1.1.2.2  pgoyette 		b = data->calgo;
   1204  1.1.1.1.2.2  pgoyette 	else if(strcasecmp(tag, "DigestType") == 0)
   1205  1.1.1.1.2.2  pgoyette 		b = data->cdigtype;
   1206  1.1.1.1.2.2  pgoyette 	else if(strcasecmp(tag, "Digest") == 0)
   1207  1.1.1.1.2.2  pgoyette 		b = data->cdigest;
   1208  1.1.1.1.2.2  pgoyette 	return b;
   1209  1.1.1.1.2.2  pgoyette }
   1210  1.1.1.1.2.2  pgoyette 
   1211  1.1.1.1.2.2  pgoyette /**
   1212  1.1.1.1.2.2  pgoyette  * XML handle character data, the data inside an element.
   1213  1.1.1.1.2.2  pgoyette  * @param userData: xml_data structure
   1214  1.1.1.1.2.2  pgoyette  * @param s: the character data.  May not all be in one callback.
   1215  1.1.1.1.2.2  pgoyette  * 	NOT zero terminated.
   1216  1.1.1.1.2.2  pgoyette  * @param len: length of this part of the data.
   1217  1.1.1.1.2.2  pgoyette  */
   1218  1.1.1.1.2.2  pgoyette static void
   1219  1.1.1.1.2.2  pgoyette xml_charhandle(void *userData, const XML_Char *s, int len)
   1220  1.1.1.1.2.2  pgoyette {
   1221  1.1.1.1.2.2  pgoyette 	struct xml_data* data = (struct xml_data*)userData;
   1222  1.1.1.1.2.2  pgoyette 	BIO* b = NULL;
   1223  1.1.1.1.2.2  pgoyette 	/* skip characters outside of elements */
   1224  1.1.1.1.2.2  pgoyette 	if(!data->tag)
   1225  1.1.1.1.2.2  pgoyette 		return;
   1226  1.1.1.1.2.2  pgoyette 	if(verb>=4) {
   1227  1.1.1.1.2.2  pgoyette 		int i;
   1228  1.1.1.1.2.2  pgoyette 		printf("%s%s charhandle: '",
   1229  1.1.1.1.2.2  pgoyette 			data->use_key?"use ":"",
   1230  1.1.1.1.2.2  pgoyette 			data->tag?data->tag:"none");
   1231  1.1.1.1.2.2  pgoyette 		for(i=0; i<len; i++)
   1232  1.1.1.1.2.2  pgoyette 			printf("%c", s[i]);
   1233  1.1.1.1.2.2  pgoyette 		printf("'\n");
   1234  1.1.1.1.2.2  pgoyette 	}
   1235  1.1.1.1.2.2  pgoyette 	if(strcasecmp(data->tag, "Zone") == 0) {
   1236  1.1.1.1.2.2  pgoyette 		if(BIO_write(data->czone, s, len) < 0) {
   1237  1.1.1.1.2.2  pgoyette 			if(verb) printf("out of memory in BIO_write\n");
   1238  1.1.1.1.2.2  pgoyette 			exit(0);
   1239  1.1.1.1.2.2  pgoyette 		}
   1240  1.1.1.1.2.2  pgoyette 		return;
   1241  1.1.1.1.2.2  pgoyette 	}
   1242  1.1.1.1.2.2  pgoyette 	/* only store if key is used */
   1243  1.1.1.1.2.2  pgoyette 	if(!data->use_key)
   1244  1.1.1.1.2.2  pgoyette 		return;
   1245  1.1.1.1.2.2  pgoyette 	b = xml_selectbio(data, data->tag);
   1246  1.1.1.1.2.2  pgoyette 	if(b) {
   1247  1.1.1.1.2.2  pgoyette 		if(BIO_write(b, s, len) < 0) {
   1248  1.1.1.1.2.2  pgoyette 			if(verb) printf("out of memory in BIO_write\n");
   1249  1.1.1.1.2.2  pgoyette 			exit(0);
   1250  1.1.1.1.2.2  pgoyette 		}
   1251  1.1.1.1.2.2  pgoyette 	}
   1252  1.1.1.1.2.2  pgoyette }
   1253  1.1.1.1.2.2  pgoyette 
   1254  1.1.1.1.2.2  pgoyette /**
   1255  1.1.1.1.2.2  pgoyette  * XML fetch value of particular attribute(by name) or NULL if not present.
   1256  1.1.1.1.2.2  pgoyette  * @param atts: attribute array (from xml_startelem).
   1257  1.1.1.1.2.2  pgoyette  * @param name: name of attribute to look for.
   1258  1.1.1.1.2.2  pgoyette  * @return the value or NULL. (ptr into atts).
   1259  1.1.1.1.2.2  pgoyette  */
   1260  1.1.1.1.2.2  pgoyette static const XML_Char*
   1261  1.1.1.1.2.2  pgoyette find_att(const XML_Char **atts, const XML_Char* name)
   1262  1.1.1.1.2.2  pgoyette {
   1263  1.1.1.1.2.2  pgoyette 	int i;
   1264  1.1.1.1.2.2  pgoyette 	for(i=0; atts[i]; i+=2) {
   1265  1.1.1.1.2.2  pgoyette 		if(strcasecmp(atts[i], name) == 0)
   1266  1.1.1.1.2.2  pgoyette 			return atts[i+1];
   1267  1.1.1.1.2.2  pgoyette 	}
   1268  1.1.1.1.2.2  pgoyette 	return NULL;
   1269  1.1.1.1.2.2  pgoyette }
   1270  1.1.1.1.2.2  pgoyette 
   1271  1.1.1.1.2.2  pgoyette /**
   1272  1.1.1.1.2.2  pgoyette  * XML convert DateTime element to time_t.
   1273  1.1.1.1.2.2  pgoyette  * [-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
   1274  1.1.1.1.2.2  pgoyette  * (with optional .ssssss fractional seconds)
   1275  1.1.1.1.2.2  pgoyette  * @param str: the string
   1276  1.1.1.1.2.2  pgoyette  * @return a time_t representation or 0 on failure.
   1277  1.1.1.1.2.2  pgoyette  */
   1278  1.1.1.1.2.2  pgoyette static time_t
   1279  1.1.1.1.2.2  pgoyette xml_convertdate(const char* str)
   1280  1.1.1.1.2.2  pgoyette {
   1281  1.1.1.1.2.2  pgoyette 	time_t t = 0;
   1282  1.1.1.1.2.2  pgoyette 	struct tm tm;
   1283  1.1.1.1.2.2  pgoyette 	const char* s;
   1284  1.1.1.1.2.2  pgoyette 	/* for this application, ignore minus in front;
   1285  1.1.1.1.2.2  pgoyette 	 * only positive dates are expected */
   1286  1.1.1.1.2.2  pgoyette 	s = str;
   1287  1.1.1.1.2.2  pgoyette 	if(s[0] == '-') s++;
   1288  1.1.1.1.2.2  pgoyette 	memset(&tm, 0, sizeof(tm));
   1289  1.1.1.1.2.2  pgoyette 	/* parse initial content of the string (lots of whitespace allowed) */
   1290  1.1.1.1.2.2  pgoyette 	s = strptime(s, "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t:%t%S%t", &tm);
   1291  1.1.1.1.2.2  pgoyette 	if(!s) {
   1292  1.1.1.1.2.2  pgoyette 		if(verb) printf("xml_convertdate parse failure %s\n", str);
   1293  1.1.1.1.2.2  pgoyette 		return 0;
   1294  1.1.1.1.2.2  pgoyette 	}
   1295  1.1.1.1.2.2  pgoyette 	/* parse remainder of date string */
   1296  1.1.1.1.2.2  pgoyette 	if(*s == '.') {
   1297  1.1.1.1.2.2  pgoyette 		/* optional '.' and fractional seconds */
   1298  1.1.1.1.2.2  pgoyette 		int frac = 0, n = 0;
   1299  1.1.1.1.2.2  pgoyette 		if(sscanf(s+1, "%d%n", &frac, &n) < 1) {
   1300  1.1.1.1.2.2  pgoyette 			if(verb) printf("xml_convertdate f failure %s\n", str);
   1301  1.1.1.1.2.2  pgoyette 			return 0;
   1302  1.1.1.1.2.2  pgoyette 		}
   1303  1.1.1.1.2.2  pgoyette 		/* fraction is not used, time_t has second accuracy */
   1304  1.1.1.1.2.2  pgoyette 		s++;
   1305  1.1.1.1.2.2  pgoyette 		s+=n;
   1306  1.1.1.1.2.2  pgoyette 	}
   1307  1.1.1.1.2.2  pgoyette 	if(*s == 'Z' || *s == 'z') {
   1308  1.1.1.1.2.2  pgoyette 		/* nothing to do for this */
   1309  1.1.1.1.2.2  pgoyette 		s++;
   1310  1.1.1.1.2.2  pgoyette 	} else if(*s == '+' || *s == '-') {
   1311  1.1.1.1.2.2  pgoyette 		/* optional timezone spec: Z or +hh:mm or -hh:mm */
   1312  1.1.1.1.2.2  pgoyette 		int hr = 0, mn = 0, n = 0;
   1313  1.1.1.1.2.2  pgoyette 		if(sscanf(s+1, "%d:%d%n", &hr, &mn, &n) < 2) {
   1314  1.1.1.1.2.2  pgoyette 			if(verb) printf("xml_convertdate tz failure %s\n", str);
   1315  1.1.1.1.2.2  pgoyette 			return 0;
   1316  1.1.1.1.2.2  pgoyette 		}
   1317  1.1.1.1.2.2  pgoyette 		if(*s == '+') {
   1318  1.1.1.1.2.2  pgoyette 			tm.tm_hour += hr;
   1319  1.1.1.1.2.2  pgoyette 			tm.tm_min += mn;
   1320  1.1.1.1.2.2  pgoyette 		} else {
   1321  1.1.1.1.2.2  pgoyette 			tm.tm_hour -= hr;
   1322  1.1.1.1.2.2  pgoyette 			tm.tm_min -= mn;
   1323  1.1.1.1.2.2  pgoyette 		}
   1324  1.1.1.1.2.2  pgoyette 		s++;
   1325  1.1.1.1.2.2  pgoyette 		s += n;
   1326  1.1.1.1.2.2  pgoyette 	}
   1327  1.1.1.1.2.2  pgoyette 	if(*s != 0) {
   1328  1.1.1.1.2.2  pgoyette 		/* not ended properly */
   1329  1.1.1.1.2.2  pgoyette 		/* but ignore, (lenient) */
   1330  1.1.1.1.2.2  pgoyette 	}
   1331  1.1.1.1.2.2  pgoyette 
   1332  1.1.1.1.2.2  pgoyette 	t = sldns_mktime_from_utc(&tm);
   1333  1.1.1.1.2.2  pgoyette 	if(t == (time_t)-1) {
   1334  1.1.1.1.2.2  pgoyette 		if(verb) printf("xml_convertdate mktime failure\n");
   1335  1.1.1.1.2.2  pgoyette 		return 0;
   1336  1.1.1.1.2.2  pgoyette 	}
   1337  1.1.1.1.2.2  pgoyette 	return t;
   1338  1.1.1.1.2.2  pgoyette }
   1339  1.1.1.1.2.2  pgoyette 
   1340  1.1.1.1.2.2  pgoyette /**
   1341  1.1.1.1.2.2  pgoyette  * XML handle the KeyDigest start tag, check validity periods.
   1342  1.1.1.1.2.2  pgoyette  */
   1343  1.1.1.1.2.2  pgoyette static void
   1344  1.1.1.1.2.2  pgoyette handle_keydigest(struct xml_data* data, const XML_Char **atts)
   1345  1.1.1.1.2.2  pgoyette {
   1346  1.1.1.1.2.2  pgoyette 	data->use_key = 0;
   1347  1.1.1.1.2.2  pgoyette 	if(find_att(atts, "validFrom")) {
   1348  1.1.1.1.2.2  pgoyette 		time_t from = xml_convertdate(find_att(atts, "validFrom"));
   1349  1.1.1.1.2.2  pgoyette 		if(from == 0) {
   1350  1.1.1.1.2.2  pgoyette 			if(verb) printf("error: xml cannot be parsed\n");
   1351  1.1.1.1.2.2  pgoyette 			exit(0);
   1352  1.1.1.1.2.2  pgoyette 		}
   1353  1.1.1.1.2.2  pgoyette 		if(data->date < from)
   1354  1.1.1.1.2.2  pgoyette 			return;
   1355  1.1.1.1.2.2  pgoyette 	}
   1356  1.1.1.1.2.2  pgoyette 	if(find_att(atts, "validUntil")) {
   1357  1.1.1.1.2.2  pgoyette 		time_t until = xml_convertdate(find_att(atts, "validUntil"));
   1358  1.1.1.1.2.2  pgoyette 		if(until == 0) {
   1359  1.1.1.1.2.2  pgoyette 			if(verb) printf("error: xml cannot be parsed\n");
   1360  1.1.1.1.2.2  pgoyette 			exit(0);
   1361  1.1.1.1.2.2  pgoyette 		}
   1362  1.1.1.1.2.2  pgoyette 		if(data->date > until)
   1363  1.1.1.1.2.2  pgoyette 			return;
   1364  1.1.1.1.2.2  pgoyette 	}
   1365  1.1.1.1.2.2  pgoyette 	/* yes we want to use this key */
   1366  1.1.1.1.2.2  pgoyette 	data->use_key = 1;
   1367  1.1.1.1.2.2  pgoyette 	(void)BIO_reset(data->ctag);
   1368  1.1.1.1.2.2  pgoyette 	(void)BIO_reset(data->calgo);
   1369  1.1.1.1.2.2  pgoyette 	(void)BIO_reset(data->cdigtype);
   1370  1.1.1.1.2.2  pgoyette 	(void)BIO_reset(data->cdigest);
   1371  1.1.1.1.2.2  pgoyette }
   1372  1.1.1.1.2.2  pgoyette 
   1373  1.1.1.1.2.2  pgoyette /** See if XML element equals the zone name */
   1374  1.1.1.1.2.2  pgoyette static int
   1375  1.1.1.1.2.2  pgoyette xml_is_zone_name(BIO* zone, const char* name)
   1376  1.1.1.1.2.2  pgoyette {
   1377  1.1.1.1.2.2  pgoyette 	char buf[1024];
   1378  1.1.1.1.2.2  pgoyette 	char* z = NULL;
   1379  1.1.1.1.2.2  pgoyette 	long zlen;
   1380  1.1.1.1.2.2  pgoyette 	(void)BIO_seek(zone, 0);
   1381  1.1.1.1.2.2  pgoyette 	zlen = BIO_get_mem_data(zone, &z);
   1382  1.1.1.1.2.2  pgoyette 	if(!zlen || !z) return 0;
   1383  1.1.1.1.2.2  pgoyette 	/* zero terminate */
   1384  1.1.1.1.2.2  pgoyette 	if(zlen >= (long)sizeof(buf)) return 0;
   1385  1.1.1.1.2.2  pgoyette 	memmove(buf, z, (size_t)zlen);
   1386  1.1.1.1.2.2  pgoyette 	buf[zlen] = 0;
   1387  1.1.1.1.2.2  pgoyette 	/* compare */
   1388  1.1.1.1.2.2  pgoyette 	return (strncasecmp(buf, name, strlen(name)) == 0);
   1389  1.1.1.1.2.2  pgoyette }
   1390  1.1.1.1.2.2  pgoyette 
   1391  1.1.1.1.2.2  pgoyette /**
   1392  1.1.1.1.2.2  pgoyette  * XML start of element. This callback is called whenever an XML tag starts.
   1393  1.1.1.1.2.2  pgoyette  * XML_Char is UTF8.
   1394  1.1.1.1.2.2  pgoyette  * @param userData: the xml_data structure.
   1395  1.1.1.1.2.2  pgoyette  * @param name: the tag that starts.
   1396  1.1.1.1.2.2  pgoyette  * @param atts: array of strings, pairs of attr = value, ends with NULL.
   1397  1.1.1.1.2.2  pgoyette  * 	i.e. att[0]="att[1]" att[2]="att[3]" att[4]isNull
   1398  1.1.1.1.2.2  pgoyette  */
   1399  1.1.1.1.2.2  pgoyette static void
   1400  1.1.1.1.2.2  pgoyette xml_startelem(void *userData, const XML_Char *name, const XML_Char **atts)
   1401  1.1.1.1.2.2  pgoyette {
   1402  1.1.1.1.2.2  pgoyette 	struct xml_data* data = (struct xml_data*)userData;
   1403  1.1.1.1.2.2  pgoyette 	BIO* b;
   1404  1.1.1.1.2.2  pgoyette 	if(verb>=4) printf("xml tag start '%s'\n", name);
   1405  1.1.1.1.2.2  pgoyette 	free(data->tag);
   1406  1.1.1.1.2.2  pgoyette 	data->tag = strdup(name);
   1407  1.1.1.1.2.2  pgoyette 	if(!data->tag) {
   1408  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   1409  1.1.1.1.2.2  pgoyette 		exit(0);
   1410  1.1.1.1.2.2  pgoyette 	}
   1411  1.1.1.1.2.2  pgoyette 	if(verb>=4) {
   1412  1.1.1.1.2.2  pgoyette 		int i;
   1413  1.1.1.1.2.2  pgoyette 		for(i=0; atts[i]; i+=2) {
   1414  1.1.1.1.2.2  pgoyette 			printf("  %s='%s'\n", atts[i], atts[i+1]);
   1415  1.1.1.1.2.2  pgoyette 		}
   1416  1.1.1.1.2.2  pgoyette 	}
   1417  1.1.1.1.2.2  pgoyette 	/* handle attributes to particular types */
   1418  1.1.1.1.2.2  pgoyette 	if(strcasecmp(name, "KeyDigest") == 0) {
   1419  1.1.1.1.2.2  pgoyette 		handle_keydigest(data, atts);
   1420  1.1.1.1.2.2  pgoyette 		return;
   1421  1.1.1.1.2.2  pgoyette 	} else if(strcasecmp(name, "Zone") == 0) {
   1422  1.1.1.1.2.2  pgoyette 		(void)BIO_reset(data->czone);
   1423  1.1.1.1.2.2  pgoyette 		return;
   1424  1.1.1.1.2.2  pgoyette 	}
   1425  1.1.1.1.2.2  pgoyette 
   1426  1.1.1.1.2.2  pgoyette 	/* for other types we prepare to pick up the data */
   1427  1.1.1.1.2.2  pgoyette 	if(!data->use_key)
   1428  1.1.1.1.2.2  pgoyette 		return;
   1429  1.1.1.1.2.2  pgoyette 	b = xml_selectbio(data, data->tag);
   1430  1.1.1.1.2.2  pgoyette 	if(b) {
   1431  1.1.1.1.2.2  pgoyette 		/* empty it */
   1432  1.1.1.1.2.2  pgoyette 		(void)BIO_reset(b);
   1433  1.1.1.1.2.2  pgoyette 	}
   1434  1.1.1.1.2.2  pgoyette }
   1435  1.1.1.1.2.2  pgoyette 
   1436  1.1.1.1.2.2  pgoyette /** Append str to bio */
   1437  1.1.1.1.2.2  pgoyette static void
   1438  1.1.1.1.2.2  pgoyette xml_append_str(BIO* b, const char* s)
   1439  1.1.1.1.2.2  pgoyette {
   1440  1.1.1.1.2.2  pgoyette 	if(BIO_write(b, s, (int)strlen(s)) < 0) {
   1441  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory in BIO_write\n");
   1442  1.1.1.1.2.2  pgoyette 		exit(0);
   1443  1.1.1.1.2.2  pgoyette 	}
   1444  1.1.1.1.2.2  pgoyette }
   1445  1.1.1.1.2.2  pgoyette 
   1446  1.1.1.1.2.2  pgoyette /** Append bio to bio */
   1447  1.1.1.1.2.2  pgoyette static void
   1448  1.1.1.1.2.2  pgoyette xml_append_bio(BIO* b, BIO* a)
   1449  1.1.1.1.2.2  pgoyette {
   1450  1.1.1.1.2.2  pgoyette 	char* z = NULL;
   1451  1.1.1.1.2.2  pgoyette 	long i, len;
   1452  1.1.1.1.2.2  pgoyette 	(void)BIO_seek(a, 0);
   1453  1.1.1.1.2.2  pgoyette 	len = BIO_get_mem_data(a, &z);
   1454  1.1.1.1.2.2  pgoyette 	if(!len || !z) {
   1455  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory in BIO_write\n");
   1456  1.1.1.1.2.2  pgoyette 		exit(0);
   1457  1.1.1.1.2.2  pgoyette 	}
   1458  1.1.1.1.2.2  pgoyette 	/* remove newlines in the data here */
   1459  1.1.1.1.2.2  pgoyette 	for(i=0; i<len; i++) {
   1460  1.1.1.1.2.2  pgoyette 		if(z[i] == '\r' || z[i] == '\n')
   1461  1.1.1.1.2.2  pgoyette 			z[i] = ' ';
   1462  1.1.1.1.2.2  pgoyette 	}
   1463  1.1.1.1.2.2  pgoyette 	/* write to BIO */
   1464  1.1.1.1.2.2  pgoyette 	if(BIO_write(b, z, len) < 0) {
   1465  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory in BIO_write\n");
   1466  1.1.1.1.2.2  pgoyette 		exit(0);
   1467  1.1.1.1.2.2  pgoyette 	}
   1468  1.1.1.1.2.2  pgoyette }
   1469  1.1.1.1.2.2  pgoyette 
   1470  1.1.1.1.2.2  pgoyette /** write the parsed xml-DS to the DS list */
   1471  1.1.1.1.2.2  pgoyette static void
   1472  1.1.1.1.2.2  pgoyette xml_append_ds(struct xml_data* data)
   1473  1.1.1.1.2.2  pgoyette {
   1474  1.1.1.1.2.2  pgoyette 	/* write DS to accumulated DS */
   1475  1.1.1.1.2.2  pgoyette 	xml_append_str(data->ds, ". IN DS ");
   1476  1.1.1.1.2.2  pgoyette 	xml_append_bio(data->ds, data->ctag);
   1477  1.1.1.1.2.2  pgoyette 	xml_append_str(data->ds, " ");
   1478  1.1.1.1.2.2  pgoyette 	xml_append_bio(data->ds, data->calgo);
   1479  1.1.1.1.2.2  pgoyette 	xml_append_str(data->ds, " ");
   1480  1.1.1.1.2.2  pgoyette 	xml_append_bio(data->ds, data->cdigtype);
   1481  1.1.1.1.2.2  pgoyette 	xml_append_str(data->ds, " ");
   1482  1.1.1.1.2.2  pgoyette 	xml_append_bio(data->ds, data->cdigest);
   1483  1.1.1.1.2.2  pgoyette 	xml_append_str(data->ds, "\n");
   1484  1.1.1.1.2.2  pgoyette 	data->num_keys++;
   1485  1.1.1.1.2.2  pgoyette }
   1486  1.1.1.1.2.2  pgoyette 
   1487  1.1.1.1.2.2  pgoyette /**
   1488  1.1.1.1.2.2  pgoyette  * XML end of element. This callback is called whenever an XML tag ends.
   1489  1.1.1.1.2.2  pgoyette  * XML_Char is UTF8.
   1490  1.1.1.1.2.2  pgoyette  * @param userData: the xml_data structure
   1491  1.1.1.1.2.2  pgoyette  * @param name: the tag that ends.
   1492  1.1.1.1.2.2  pgoyette  */
   1493  1.1.1.1.2.2  pgoyette static void
   1494  1.1.1.1.2.2  pgoyette xml_endelem(void *userData, const XML_Char *name)
   1495  1.1.1.1.2.2  pgoyette {
   1496  1.1.1.1.2.2  pgoyette 	struct xml_data* data = (struct xml_data*)userData;
   1497  1.1.1.1.2.2  pgoyette 	if(verb>=4) printf("xml tag end   '%s'\n", name);
   1498  1.1.1.1.2.2  pgoyette 	free(data->tag);
   1499  1.1.1.1.2.2  pgoyette 	data->tag = NULL;
   1500  1.1.1.1.2.2  pgoyette 	if(strcasecmp(name, "KeyDigest") == 0) {
   1501  1.1.1.1.2.2  pgoyette 		if(data->use_key)
   1502  1.1.1.1.2.2  pgoyette 			xml_append_ds(data);
   1503  1.1.1.1.2.2  pgoyette 		data->use_key = 0;
   1504  1.1.1.1.2.2  pgoyette 	} else if(strcasecmp(name, "Zone") == 0) {
   1505  1.1.1.1.2.2  pgoyette 		if(!xml_is_zone_name(data->czone, ".")) {
   1506  1.1.1.1.2.2  pgoyette 			if(verb) printf("xml not for the right zone\n");
   1507  1.1.1.1.2.2  pgoyette 			exit(0);
   1508  1.1.1.1.2.2  pgoyette 		}
   1509  1.1.1.1.2.2  pgoyette 	}
   1510  1.1.1.1.2.2  pgoyette }
   1511  1.1.1.1.2.2  pgoyette 
   1512  1.1.1.1.2.2  pgoyette /* Stop the parser when an entity declaration is encountered. For safety. */
   1513  1.1.1.1.2.2  pgoyette static void
   1514  1.1.1.1.2.2  pgoyette xml_entitydeclhandler(void *userData,
   1515  1.1.1.1.2.2  pgoyette 	const XML_Char *ATTR_UNUSED(entityName),
   1516  1.1.1.1.2.2  pgoyette 	int ATTR_UNUSED(is_parameter_entity),
   1517  1.1.1.1.2.2  pgoyette 	const XML_Char *ATTR_UNUSED(value), int ATTR_UNUSED(value_length),
   1518  1.1.1.1.2.2  pgoyette 	const XML_Char *ATTR_UNUSED(base),
   1519  1.1.1.1.2.2  pgoyette 	const XML_Char *ATTR_UNUSED(systemId),
   1520  1.1.1.1.2.2  pgoyette 	const XML_Char *ATTR_UNUSED(publicId),
   1521  1.1.1.1.2.2  pgoyette 	const XML_Char *ATTR_UNUSED(notationName))
   1522  1.1.1.1.2.2  pgoyette {
   1523  1.1.1.1.2.2  pgoyette #if HAVE_DECL_XML_STOPPARSER
   1524  1.1.1.1.2.2  pgoyette 	(void)XML_StopParser((XML_Parser)userData, XML_FALSE);
   1525  1.1.1.1.2.2  pgoyette #else
   1526  1.1.1.1.2.2  pgoyette 	(void)userData;
   1527  1.1.1.1.2.2  pgoyette #endif
   1528  1.1.1.1.2.2  pgoyette }
   1529  1.1.1.1.2.2  pgoyette 
   1530  1.1.1.1.2.2  pgoyette /**
   1531  1.1.1.1.2.2  pgoyette  * XML parser setup of the callbacks for the tags
   1532  1.1.1.1.2.2  pgoyette  */
   1533  1.1.1.1.2.2  pgoyette static void
   1534  1.1.1.1.2.2  pgoyette xml_parse_setup(XML_Parser parser, struct xml_data* data, time_t now)
   1535  1.1.1.1.2.2  pgoyette {
   1536  1.1.1.1.2.2  pgoyette 	char buf[1024];
   1537  1.1.1.1.2.2  pgoyette 	memset(data, 0, sizeof(*data));
   1538  1.1.1.1.2.2  pgoyette 	XML_SetUserData(parser, data);
   1539  1.1.1.1.2.2  pgoyette 	data->parser = parser;
   1540  1.1.1.1.2.2  pgoyette 	data->date = now;
   1541  1.1.1.1.2.2  pgoyette 	data->ds = BIO_new(BIO_s_mem());
   1542  1.1.1.1.2.2  pgoyette 	data->ctag = BIO_new(BIO_s_mem());
   1543  1.1.1.1.2.2  pgoyette 	data->czone = BIO_new(BIO_s_mem());
   1544  1.1.1.1.2.2  pgoyette 	data->calgo = BIO_new(BIO_s_mem());
   1545  1.1.1.1.2.2  pgoyette 	data->cdigtype = BIO_new(BIO_s_mem());
   1546  1.1.1.1.2.2  pgoyette 	data->cdigest = BIO_new(BIO_s_mem());
   1547  1.1.1.1.2.2  pgoyette 	if(!data->ds || !data->ctag || !data->calgo || !data->czone ||
   1548  1.1.1.1.2.2  pgoyette 		!data->cdigtype || !data->cdigest) {
   1549  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   1550  1.1.1.1.2.2  pgoyette 		exit(0);
   1551  1.1.1.1.2.2  pgoyette 	}
   1552  1.1.1.1.2.2  pgoyette 	snprintf(buf, sizeof(buf), "; created by unbound-anchor on %s",
   1553  1.1.1.1.2.2  pgoyette 		ctime(&now));
   1554  1.1.1.1.2.2  pgoyette 	if(BIO_write(data->ds, buf, (int)strlen(buf)) < 0) {
   1555  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   1556  1.1.1.1.2.2  pgoyette 		exit(0);
   1557  1.1.1.1.2.2  pgoyette 	}
   1558  1.1.1.1.2.2  pgoyette 	XML_SetEntityDeclHandler(parser, xml_entitydeclhandler);
   1559  1.1.1.1.2.2  pgoyette 	XML_SetElementHandler(parser, xml_startelem, xml_endelem);
   1560  1.1.1.1.2.2  pgoyette 	XML_SetCharacterDataHandler(parser, xml_charhandle);
   1561  1.1.1.1.2.2  pgoyette }
   1562  1.1.1.1.2.2  pgoyette 
   1563  1.1.1.1.2.2  pgoyette /**
   1564  1.1.1.1.2.2  pgoyette  * Perform XML parsing of the root-anchors file
   1565  1.1.1.1.2.2  pgoyette  * Its format description can be read here
   1566  1.1.1.1.2.2  pgoyette  * https://data.iana.org/root-anchors/draft-icann-dnssec-trust-anchor.txt
   1567  1.1.1.1.2.2  pgoyette  * It uses libexpat.
   1568  1.1.1.1.2.2  pgoyette  * @param xml: BIO with xml data.
   1569  1.1.1.1.2.2  pgoyette  * @param now: the current time for checking DS validity periods.
   1570  1.1.1.1.2.2  pgoyette  * @return memoryBIO with the DS data in zone format.
   1571  1.1.1.1.2.2  pgoyette  * 	or NULL if the zone is insecure.
   1572  1.1.1.1.2.2  pgoyette  * 	(It exit()s on error)
   1573  1.1.1.1.2.2  pgoyette  */
   1574  1.1.1.1.2.2  pgoyette static BIO*
   1575  1.1.1.1.2.2  pgoyette xml_parse(BIO* xml, time_t now)
   1576  1.1.1.1.2.2  pgoyette {
   1577  1.1.1.1.2.2  pgoyette 	char* pp;
   1578  1.1.1.1.2.2  pgoyette 	int len;
   1579  1.1.1.1.2.2  pgoyette 	XML_Parser parser;
   1580  1.1.1.1.2.2  pgoyette 	struct xml_data data;
   1581  1.1.1.1.2.2  pgoyette 
   1582  1.1.1.1.2.2  pgoyette 	parser = XML_ParserCreate(NULL);
   1583  1.1.1.1.2.2  pgoyette 	if(!parser) {
   1584  1.1.1.1.2.2  pgoyette 		if(verb) printf("could not XML_ParserCreate\n");
   1585  1.1.1.1.2.2  pgoyette 		exit(0);
   1586  1.1.1.1.2.2  pgoyette 	}
   1587  1.1.1.1.2.2  pgoyette 
   1588  1.1.1.1.2.2  pgoyette 	/* setup callbacks */
   1589  1.1.1.1.2.2  pgoyette 	xml_parse_setup(parser, &data, now);
   1590  1.1.1.1.2.2  pgoyette 
   1591  1.1.1.1.2.2  pgoyette 	/* parse it */
   1592  1.1.1.1.2.2  pgoyette 	(void)BIO_reset(xml);
   1593  1.1.1.1.2.2  pgoyette 	len = (int)BIO_get_mem_data(xml, &pp);
   1594  1.1.1.1.2.2  pgoyette 	if(!len || !pp) {
   1595  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   1596  1.1.1.1.2.2  pgoyette 		exit(0);
   1597  1.1.1.1.2.2  pgoyette 	}
   1598  1.1.1.1.2.2  pgoyette 	if(!XML_Parse(parser, pp, len, 1 /*isfinal*/ )) {
   1599  1.1.1.1.2.2  pgoyette 		const char *e = XML_ErrorString(XML_GetErrorCode(parser));
   1600  1.1.1.1.2.2  pgoyette 		if(verb) printf("XML_Parse failure %s\n", e?e:"");
   1601  1.1.1.1.2.2  pgoyette 		exit(0);
   1602  1.1.1.1.2.2  pgoyette 	}
   1603  1.1.1.1.2.2  pgoyette 
   1604  1.1.1.1.2.2  pgoyette 	/* parsed */
   1605  1.1.1.1.2.2  pgoyette 	if(verb) printf("XML was parsed successfully, %d keys\n",
   1606  1.1.1.1.2.2  pgoyette 			data.num_keys);
   1607  1.1.1.1.2.2  pgoyette 	free(data.tag);
   1608  1.1.1.1.2.2  pgoyette 	XML_ParserFree(parser);
   1609  1.1.1.1.2.2  pgoyette 
   1610  1.1.1.1.2.2  pgoyette 	if(verb >= 4) {
   1611  1.1.1.1.2.2  pgoyette 		(void)BIO_seek(data.ds, 0);
   1612  1.1.1.1.2.2  pgoyette 		len = BIO_get_mem_data(data.ds, &pp);
   1613  1.1.1.1.2.2  pgoyette 		printf("got DS bio %d: '", len);
   1614  1.1.1.1.2.2  pgoyette 		if(!fwrite(pp, (size_t)len, 1, stdout))
   1615  1.1.1.1.2.2  pgoyette 			/* compilers do not allow us to ignore fwrite .. */
   1616  1.1.1.1.2.2  pgoyette 			fprintf(stderr, "error writing to stdout\n");
   1617  1.1.1.1.2.2  pgoyette 		printf("'\n");
   1618  1.1.1.1.2.2  pgoyette 	}
   1619  1.1.1.1.2.2  pgoyette 	BIO_free(data.czone);
   1620  1.1.1.1.2.2  pgoyette 	BIO_free(data.ctag);
   1621  1.1.1.1.2.2  pgoyette 	BIO_free(data.calgo);
   1622  1.1.1.1.2.2  pgoyette 	BIO_free(data.cdigtype);
   1623  1.1.1.1.2.2  pgoyette 	BIO_free(data.cdigest);
   1624  1.1.1.1.2.2  pgoyette 
   1625  1.1.1.1.2.2  pgoyette 	if(data.num_keys == 0) {
   1626  1.1.1.1.2.2  pgoyette 		/* the root zone seems to have gone insecure */
   1627  1.1.1.1.2.2  pgoyette 		BIO_free(data.ds);
   1628  1.1.1.1.2.2  pgoyette 		return NULL;
   1629  1.1.1.1.2.2  pgoyette 	} else {
   1630  1.1.1.1.2.2  pgoyette 		return data.ds;
   1631  1.1.1.1.2.2  pgoyette 	}
   1632  1.1.1.1.2.2  pgoyette }
   1633  1.1.1.1.2.2  pgoyette 
   1634  1.1.1.1.2.2  pgoyette /* get key usage out of its extension, returns 0 if no key_usage extension */
   1635  1.1.1.1.2.2  pgoyette static unsigned long
   1636  1.1.1.1.2.2  pgoyette get_usage_of_ex(X509* cert)
   1637  1.1.1.1.2.2  pgoyette {
   1638  1.1.1.1.2.2  pgoyette 	unsigned long val = 0;
   1639  1.1.1.1.2.2  pgoyette 	ASN1_BIT_STRING* s;
   1640  1.1.1.1.2.2  pgoyette 	if((s=X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL))) {
   1641  1.1.1.1.2.2  pgoyette 		if(s->length > 0) {
   1642  1.1.1.1.2.2  pgoyette 			val = s->data[0];
   1643  1.1.1.1.2.2  pgoyette 			if(s->length > 1)
   1644  1.1.1.1.2.2  pgoyette 				val |= s->data[1] << 8;
   1645  1.1.1.1.2.2  pgoyette 		}
   1646  1.1.1.1.2.2  pgoyette 		ASN1_BIT_STRING_free(s);
   1647  1.1.1.1.2.2  pgoyette 	}
   1648  1.1.1.1.2.2  pgoyette 	return val;
   1649  1.1.1.1.2.2  pgoyette }
   1650  1.1.1.1.2.2  pgoyette 
   1651  1.1.1.1.2.2  pgoyette /** get valid signers from the list of signers in the signature */
   1652  1.1.1.1.2.2  pgoyette static STACK_OF(X509)*
   1653  1.1.1.1.2.2  pgoyette get_valid_signers(PKCS7* p7, const char* p7signer)
   1654  1.1.1.1.2.2  pgoyette {
   1655  1.1.1.1.2.2  pgoyette 	int i;
   1656  1.1.1.1.2.2  pgoyette 	STACK_OF(X509)* validsigners = sk_X509_new_null();
   1657  1.1.1.1.2.2  pgoyette 	STACK_OF(X509)* signers = PKCS7_get0_signers(p7, NULL, 0);
   1658  1.1.1.1.2.2  pgoyette 	unsigned long usage = 0;
   1659  1.1.1.1.2.2  pgoyette 	if(!validsigners) {
   1660  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   1661  1.1.1.1.2.2  pgoyette 		sk_X509_free(signers);
   1662  1.1.1.1.2.2  pgoyette 		return NULL;
   1663  1.1.1.1.2.2  pgoyette 	}
   1664  1.1.1.1.2.2  pgoyette 	if(!signers) {
   1665  1.1.1.1.2.2  pgoyette 		if(verb) printf("no signers in pkcs7 signature\n");
   1666  1.1.1.1.2.2  pgoyette 		sk_X509_free(validsigners);
   1667  1.1.1.1.2.2  pgoyette 		return NULL;
   1668  1.1.1.1.2.2  pgoyette 	}
   1669  1.1.1.1.2.2  pgoyette 	for(i=0; i<sk_X509_num(signers); i++) {
   1670  1.1.1.1.2.2  pgoyette 		X509_NAME* nm = X509_get_subject_name(
   1671  1.1.1.1.2.2  pgoyette 			sk_X509_value(signers, i));
   1672  1.1.1.1.2.2  pgoyette 		char buf[1024];
   1673  1.1.1.1.2.2  pgoyette 		if(!nm) {
   1674  1.1.1.1.2.2  pgoyette 			if(verb) printf("signer %d: cert has no subject name\n", i);
   1675  1.1.1.1.2.2  pgoyette 			continue;
   1676  1.1.1.1.2.2  pgoyette 		}
   1677  1.1.1.1.2.2  pgoyette 		if(verb && nm) {
   1678  1.1.1.1.2.2  pgoyette 			char* nmline = X509_NAME_oneline(nm, buf,
   1679  1.1.1.1.2.2  pgoyette 				(int)sizeof(buf));
   1680  1.1.1.1.2.2  pgoyette 			printf("signer %d: Subject: %s\n", i,
   1681  1.1.1.1.2.2  pgoyette 				nmline?nmline:"no subject");
   1682  1.1.1.1.2.2  pgoyette 			if(verb >= 3 && X509_NAME_get_text_by_NID(nm,
   1683  1.1.1.1.2.2  pgoyette 				NID_commonName, buf, (int)sizeof(buf)))
   1684  1.1.1.1.2.2  pgoyette 				printf("commonName: %s\n", buf);
   1685  1.1.1.1.2.2  pgoyette 			if(verb >= 3 && X509_NAME_get_text_by_NID(nm,
   1686  1.1.1.1.2.2  pgoyette 				NID_pkcs9_emailAddress, buf, (int)sizeof(buf)))
   1687  1.1.1.1.2.2  pgoyette 				printf("emailAddress: %s\n", buf);
   1688  1.1.1.1.2.2  pgoyette 		}
   1689  1.1.1.1.2.2  pgoyette 		if(verb) {
   1690  1.1.1.1.2.2  pgoyette 			int ku_loc = X509_get_ext_by_NID(
   1691  1.1.1.1.2.2  pgoyette 				sk_X509_value(signers, i), NID_key_usage, -1);
   1692  1.1.1.1.2.2  pgoyette 			if(verb >= 3 && ku_loc >= 0) {
   1693  1.1.1.1.2.2  pgoyette 				X509_EXTENSION *ex = X509_get_ext(
   1694  1.1.1.1.2.2  pgoyette 					sk_X509_value(signers, i), ku_loc);
   1695  1.1.1.1.2.2  pgoyette 				if(ex) {
   1696  1.1.1.1.2.2  pgoyette 					printf("keyUsage: ");
   1697  1.1.1.1.2.2  pgoyette 					X509V3_EXT_print_fp(stdout, ex, 0, 0);
   1698  1.1.1.1.2.2  pgoyette 					printf("\n");
   1699  1.1.1.1.2.2  pgoyette 				}
   1700  1.1.1.1.2.2  pgoyette 			}
   1701  1.1.1.1.2.2  pgoyette 		}
   1702  1.1.1.1.2.2  pgoyette 		if(!p7signer || strcmp(p7signer, "")==0) {
   1703  1.1.1.1.2.2  pgoyette 			/* there is no name to check, return all records */
   1704  1.1.1.1.2.2  pgoyette 			if(verb) printf("did not check commonName of signer\n");
   1705  1.1.1.1.2.2  pgoyette 		} else {
   1706  1.1.1.1.2.2  pgoyette 			if(!X509_NAME_get_text_by_NID(nm,
   1707  1.1.1.1.2.2  pgoyette 				NID_pkcs9_emailAddress,
   1708  1.1.1.1.2.2  pgoyette 				buf, (int)sizeof(buf))) {
   1709  1.1.1.1.2.2  pgoyette 				if(verb) printf("removed cert with no name\n");
   1710  1.1.1.1.2.2  pgoyette 				continue; /* no name, no use */
   1711  1.1.1.1.2.2  pgoyette 			}
   1712  1.1.1.1.2.2  pgoyette 			if(strcmp(buf, p7signer) != 0) {
   1713  1.1.1.1.2.2  pgoyette 				if(verb) printf("removed cert with wrong name\n");
   1714  1.1.1.1.2.2  pgoyette 				continue; /* wrong name, skip it */
   1715  1.1.1.1.2.2  pgoyette 			}
   1716  1.1.1.1.2.2  pgoyette 		}
   1717  1.1.1.1.2.2  pgoyette 
   1718  1.1.1.1.2.2  pgoyette 		/* check that the key usage allows digital signatures
   1719  1.1.1.1.2.2  pgoyette 		 * (the p7s) */
   1720  1.1.1.1.2.2  pgoyette 		usage = get_usage_of_ex(sk_X509_value(signers, i));
   1721  1.1.1.1.2.2  pgoyette 		if(!(usage & KU_DIGITAL_SIGNATURE)) {
   1722  1.1.1.1.2.2  pgoyette 			if(verb) printf("removed cert with no key usage Digital Signature allowed\n");
   1723  1.1.1.1.2.2  pgoyette 			continue;
   1724  1.1.1.1.2.2  pgoyette 		}
   1725  1.1.1.1.2.2  pgoyette 
   1726  1.1.1.1.2.2  pgoyette 		/* we like this cert, add it to our list of valid
   1727  1.1.1.1.2.2  pgoyette 		 * signers certificates */
   1728  1.1.1.1.2.2  pgoyette 		sk_X509_push(validsigners, sk_X509_value(signers, i));
   1729  1.1.1.1.2.2  pgoyette 	}
   1730  1.1.1.1.2.2  pgoyette 	sk_X509_free(signers);
   1731  1.1.1.1.2.2  pgoyette 	return validsigners;
   1732  1.1.1.1.2.2  pgoyette }
   1733  1.1.1.1.2.2  pgoyette 
   1734  1.1.1.1.2.2  pgoyette /** verify a PKCS7 signature, false on failure */
   1735  1.1.1.1.2.2  pgoyette static int
   1736  1.1.1.1.2.2  pgoyette verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust, const char* p7signer)
   1737  1.1.1.1.2.2  pgoyette {
   1738  1.1.1.1.2.2  pgoyette 	PKCS7* p7;
   1739  1.1.1.1.2.2  pgoyette 	X509_STORE *store = X509_STORE_new();
   1740  1.1.1.1.2.2  pgoyette 	STACK_OF(X509)* validsigners;
   1741  1.1.1.1.2.2  pgoyette 	int secure = 0;
   1742  1.1.1.1.2.2  pgoyette 	int i;
   1743  1.1.1.1.2.2  pgoyette #ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
   1744  1.1.1.1.2.2  pgoyette 	X509_VERIFY_PARAM* param = X509_VERIFY_PARAM_new();
   1745  1.1.1.1.2.2  pgoyette 	if(!param) {
   1746  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   1747  1.1.1.1.2.2  pgoyette 		X509_STORE_free(store);
   1748  1.1.1.1.2.2  pgoyette 		return 0;
   1749  1.1.1.1.2.2  pgoyette 	}
   1750  1.1.1.1.2.2  pgoyette 	/* do the selfcheck on the root certificate; it checks that the
   1751  1.1.1.1.2.2  pgoyette 	 * input is valid */
   1752  1.1.1.1.2.2  pgoyette 	X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CHECK_SS_SIGNATURE);
   1753  1.1.1.1.2.2  pgoyette 	if(store) X509_STORE_set1_param(store, param);
   1754  1.1.1.1.2.2  pgoyette #endif
   1755  1.1.1.1.2.2  pgoyette 	if(!store) {
   1756  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   1757  1.1.1.1.2.2  pgoyette #ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
   1758  1.1.1.1.2.2  pgoyette 		X509_VERIFY_PARAM_free(param);
   1759  1.1.1.1.2.2  pgoyette #endif
   1760  1.1.1.1.2.2  pgoyette 		return 0;
   1761  1.1.1.1.2.2  pgoyette 	}
   1762  1.1.1.1.2.2  pgoyette #ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
   1763  1.1.1.1.2.2  pgoyette 	X509_VERIFY_PARAM_free(param);
   1764  1.1.1.1.2.2  pgoyette #endif
   1765  1.1.1.1.2.2  pgoyette 
   1766  1.1.1.1.2.2  pgoyette 	(void)BIO_reset(p7s);
   1767  1.1.1.1.2.2  pgoyette 	(void)BIO_reset(data);
   1768  1.1.1.1.2.2  pgoyette 
   1769  1.1.1.1.2.2  pgoyette 	/* convert p7s to p7 (the signature) */
   1770  1.1.1.1.2.2  pgoyette 	p7 = d2i_PKCS7_bio(p7s, NULL);
   1771  1.1.1.1.2.2  pgoyette 	if(!p7) {
   1772  1.1.1.1.2.2  pgoyette 		if(verb) printf("could not parse p7s signature file\n");
   1773  1.1.1.1.2.2  pgoyette 		X509_STORE_free(store);
   1774  1.1.1.1.2.2  pgoyette 		return 0;
   1775  1.1.1.1.2.2  pgoyette 	}
   1776  1.1.1.1.2.2  pgoyette 	if(verb >= 2) printf("parsed the PKCS7 signature\n");
   1777  1.1.1.1.2.2  pgoyette 
   1778  1.1.1.1.2.2  pgoyette 	/* convert trust to trusted certificate store */
   1779  1.1.1.1.2.2  pgoyette 	for(i=0; i<sk_X509_num(trust); i++) {
   1780  1.1.1.1.2.2  pgoyette 		if(!X509_STORE_add_cert(store, sk_X509_value(trust, i))) {
   1781  1.1.1.1.2.2  pgoyette 			if(verb) printf("failed X509_STORE_add_cert\n");
   1782  1.1.1.1.2.2  pgoyette 			X509_STORE_free(store);
   1783  1.1.1.1.2.2  pgoyette 			PKCS7_free(p7);
   1784  1.1.1.1.2.2  pgoyette 			return 0;
   1785  1.1.1.1.2.2  pgoyette 		}
   1786  1.1.1.1.2.2  pgoyette 	}
   1787  1.1.1.1.2.2  pgoyette 	if(verb >= 2) printf("setup the X509_STORE\n");
   1788  1.1.1.1.2.2  pgoyette 
   1789  1.1.1.1.2.2  pgoyette 	/* check what is in the Subject name of the certificates,
   1790  1.1.1.1.2.2  pgoyette 	 * and build a stack that contains only the right certificates */
   1791  1.1.1.1.2.2  pgoyette 	validsigners = get_valid_signers(p7, p7signer);
   1792  1.1.1.1.2.2  pgoyette 	if(!validsigners) {
   1793  1.1.1.1.2.2  pgoyette 			X509_STORE_free(store);
   1794  1.1.1.1.2.2  pgoyette 			PKCS7_free(p7);
   1795  1.1.1.1.2.2  pgoyette 			return 0;
   1796  1.1.1.1.2.2  pgoyette 	}
   1797  1.1.1.1.2.2  pgoyette 	if(PKCS7_verify(p7, validsigners, store, data, NULL, PKCS7_NOINTERN) == 1) {
   1798  1.1.1.1.2.2  pgoyette 		secure = 1;
   1799  1.1.1.1.2.2  pgoyette 		if(verb) printf("the PKCS7 signature verified\n");
   1800  1.1.1.1.2.2  pgoyette 	} else {
   1801  1.1.1.1.2.2  pgoyette 		if(verb) {
   1802  1.1.1.1.2.2  pgoyette 			ERR_print_errors_fp(stdout);
   1803  1.1.1.1.2.2  pgoyette 		}
   1804  1.1.1.1.2.2  pgoyette 	}
   1805  1.1.1.1.2.2  pgoyette 
   1806  1.1.1.1.2.2  pgoyette 	sk_X509_free(validsigners);
   1807  1.1.1.1.2.2  pgoyette 	X509_STORE_free(store);
   1808  1.1.1.1.2.2  pgoyette 	PKCS7_free(p7);
   1809  1.1.1.1.2.2  pgoyette 	return secure;
   1810  1.1.1.1.2.2  pgoyette }
   1811  1.1.1.1.2.2  pgoyette 
   1812  1.1.1.1.2.2  pgoyette /** write unsigned root anchor file, a 5011 revoked tp */
   1813  1.1.1.1.2.2  pgoyette static void
   1814  1.1.1.1.2.2  pgoyette write_unsigned_root(const char* root_anchor_file)
   1815  1.1.1.1.2.2  pgoyette {
   1816  1.1.1.1.2.2  pgoyette 	FILE* out;
   1817  1.1.1.1.2.2  pgoyette 	time_t now = time(NULL);
   1818  1.1.1.1.2.2  pgoyette 	out = fopen(root_anchor_file, "w");
   1819  1.1.1.1.2.2  pgoyette 	if(!out) {
   1820  1.1.1.1.2.2  pgoyette 		if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno));
   1821  1.1.1.1.2.2  pgoyette 		return;
   1822  1.1.1.1.2.2  pgoyette 	}
   1823  1.1.1.1.2.2  pgoyette 	if(fprintf(out, "; autotrust trust anchor file\n"
   1824  1.1.1.1.2.2  pgoyette 		";;REVOKED\n"
   1825  1.1.1.1.2.2  pgoyette 		";;id: . 1\n"
   1826  1.1.1.1.2.2  pgoyette 		"; This file was written by unbound-anchor on %s"
   1827  1.1.1.1.2.2  pgoyette 		"; It indicates that the root does not use DNSSEC\n"
   1828  1.1.1.1.2.2  pgoyette 		"; to restart DNSSEC overwrite this file with a\n"
   1829  1.1.1.1.2.2  pgoyette 		"; valid trustanchor or (empty-it and run unbound-anchor)\n"
   1830  1.1.1.1.2.2  pgoyette 		, ctime(&now)) < 0) {
   1831  1.1.1.1.2.2  pgoyette 		if(verb) printf("failed to write 'unsigned' to %s\n",
   1832  1.1.1.1.2.2  pgoyette 			root_anchor_file);
   1833  1.1.1.1.2.2  pgoyette 		if(verb && errno != 0) printf("%s\n", strerror(errno));
   1834  1.1.1.1.2.2  pgoyette 	}
   1835  1.1.1.1.2.2  pgoyette 	fflush(out);
   1836  1.1.1.1.2.2  pgoyette #ifdef HAVE_FSYNC
   1837  1.1.1.1.2.2  pgoyette 	fsync(fileno(out));
   1838  1.1.1.1.2.2  pgoyette #else
   1839  1.1.1.1.2.2  pgoyette 	FlushFileBuffers((HANDLE)_fileno(out));
   1840  1.1.1.1.2.2  pgoyette #endif
   1841  1.1.1.1.2.2  pgoyette 	fclose(out);
   1842  1.1.1.1.2.2  pgoyette }
   1843  1.1.1.1.2.2  pgoyette 
   1844  1.1.1.1.2.2  pgoyette /** write root anchor file */
   1845  1.1.1.1.2.2  pgoyette static void
   1846  1.1.1.1.2.2  pgoyette write_root_anchor(const char* root_anchor_file, BIO* ds)
   1847  1.1.1.1.2.2  pgoyette {
   1848  1.1.1.1.2.2  pgoyette 	char* pp = NULL;
   1849  1.1.1.1.2.2  pgoyette 	int len;
   1850  1.1.1.1.2.2  pgoyette 	FILE* out;
   1851  1.1.1.1.2.2  pgoyette 	(void)BIO_seek(ds, 0);
   1852  1.1.1.1.2.2  pgoyette 	len = BIO_get_mem_data(ds, &pp);
   1853  1.1.1.1.2.2  pgoyette 	if(!len || !pp) {
   1854  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   1855  1.1.1.1.2.2  pgoyette 		return;
   1856  1.1.1.1.2.2  pgoyette 	}
   1857  1.1.1.1.2.2  pgoyette 	out = fopen(root_anchor_file, "w");
   1858  1.1.1.1.2.2  pgoyette 	if(!out) {
   1859  1.1.1.1.2.2  pgoyette 		if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno));
   1860  1.1.1.1.2.2  pgoyette 		return;
   1861  1.1.1.1.2.2  pgoyette 	}
   1862  1.1.1.1.2.2  pgoyette 	if(fwrite(pp, (size_t)len, 1, out) != 1) {
   1863  1.1.1.1.2.2  pgoyette 		if(verb) printf("failed to write all data to %s\n",
   1864  1.1.1.1.2.2  pgoyette 			root_anchor_file);
   1865  1.1.1.1.2.2  pgoyette 		if(verb && errno != 0) printf("%s\n", strerror(errno));
   1866  1.1.1.1.2.2  pgoyette 	}
   1867  1.1.1.1.2.2  pgoyette 	fflush(out);
   1868  1.1.1.1.2.2  pgoyette #ifdef HAVE_FSYNC
   1869  1.1.1.1.2.2  pgoyette 	fsync(fileno(out));
   1870  1.1.1.1.2.2  pgoyette #else
   1871  1.1.1.1.2.2  pgoyette 	FlushFileBuffers((HANDLE)_fileno(out));
   1872  1.1.1.1.2.2  pgoyette #endif
   1873  1.1.1.1.2.2  pgoyette 	fclose(out);
   1874  1.1.1.1.2.2  pgoyette }
   1875  1.1.1.1.2.2  pgoyette 
   1876  1.1.1.1.2.2  pgoyette /** Perform the verification and update of the trustanchor file */
   1877  1.1.1.1.2.2  pgoyette static void
   1878  1.1.1.1.2.2  pgoyette verify_and_update_anchor(const char* root_anchor_file, BIO* xml, BIO* p7s,
   1879  1.1.1.1.2.2  pgoyette 	STACK_OF(X509)* cert, const char* p7signer)
   1880  1.1.1.1.2.2  pgoyette {
   1881  1.1.1.1.2.2  pgoyette 	BIO* ds;
   1882  1.1.1.1.2.2  pgoyette 
   1883  1.1.1.1.2.2  pgoyette 	/* verify xml file */
   1884  1.1.1.1.2.2  pgoyette 	if(!verify_p7sig(xml, p7s, cert, p7signer)) {
   1885  1.1.1.1.2.2  pgoyette 		printf("the PKCS7 signature failed\n");
   1886  1.1.1.1.2.2  pgoyette 		exit(0);
   1887  1.1.1.1.2.2  pgoyette 	}
   1888  1.1.1.1.2.2  pgoyette 
   1889  1.1.1.1.2.2  pgoyette 	/* parse the xml file into DS records */
   1890  1.1.1.1.2.2  pgoyette 	ds = xml_parse(xml, time(NULL));
   1891  1.1.1.1.2.2  pgoyette 	if(!ds) {
   1892  1.1.1.1.2.2  pgoyette 		/* the root zone is unsigned now */
   1893  1.1.1.1.2.2  pgoyette 		write_unsigned_root(root_anchor_file);
   1894  1.1.1.1.2.2  pgoyette 	} else {
   1895  1.1.1.1.2.2  pgoyette 		/* reinstate 5011 tracking */
   1896  1.1.1.1.2.2  pgoyette 		write_root_anchor(root_anchor_file, ds);
   1897  1.1.1.1.2.2  pgoyette 	}
   1898  1.1.1.1.2.2  pgoyette 	BIO_free(ds);
   1899  1.1.1.1.2.2  pgoyette }
   1900  1.1.1.1.2.2  pgoyette 
   1901  1.1.1.1.2.2  pgoyette #ifdef USE_WINSOCK
   1902  1.1.1.1.2.2  pgoyette static void do_wsa_cleanup(void) { WSACleanup(); }
   1903  1.1.1.1.2.2  pgoyette #endif
   1904  1.1.1.1.2.2  pgoyette 
   1905  1.1.1.1.2.2  pgoyette /** perform actual certupdate work */
   1906  1.1.1.1.2.2  pgoyette static int
   1907  1.1.1.1.2.2  pgoyette do_certupdate(const char* root_anchor_file, const char* root_cert_file,
   1908  1.1.1.1.2.2  pgoyette 	const char* urlname, const char* xmlname, const char* p7sname,
   1909  1.1.1.1.2.2  pgoyette 	const char* p7signer, const char* res_conf, const char* root_hints,
   1910  1.1.1.1.2.2  pgoyette 	const char* debugconf, int ip4only, int ip6only, int port,
   1911  1.1.1.1.2.2  pgoyette 	struct ub_result* dnskey)
   1912  1.1.1.1.2.2  pgoyette {
   1913  1.1.1.1.2.2  pgoyette 	STACK_OF(X509)* cert;
   1914  1.1.1.1.2.2  pgoyette 	BIO *xml, *p7s;
   1915  1.1.1.1.2.2  pgoyette 	struct ip_list* ip_list = NULL;
   1916  1.1.1.1.2.2  pgoyette 
   1917  1.1.1.1.2.2  pgoyette 	/* read pem file or provide builtin */
   1918  1.1.1.1.2.2  pgoyette 	cert = read_cert_or_builtin(root_cert_file);
   1919  1.1.1.1.2.2  pgoyette 
   1920  1.1.1.1.2.2  pgoyette 	/* lookup A, AAAA for the urlname (or parse urlname if IP address) */
   1921  1.1.1.1.2.2  pgoyette 	ip_list = resolve_name(urlname, port, res_conf, root_hints, debugconf,
   1922  1.1.1.1.2.2  pgoyette 		ip4only, ip6only);
   1923  1.1.1.1.2.2  pgoyette 
   1924  1.1.1.1.2.2  pgoyette #ifdef USE_WINSOCK
   1925  1.1.1.1.2.2  pgoyette 	if(1) { /* libunbound finished, startup WSA for the https connection */
   1926  1.1.1.1.2.2  pgoyette 		WSADATA wsa_data;
   1927  1.1.1.1.2.2  pgoyette 		int r;
   1928  1.1.1.1.2.2  pgoyette 		if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) {
   1929  1.1.1.1.2.2  pgoyette 			if(verb) printf("WSAStartup failed: %s\n",
   1930  1.1.1.1.2.2  pgoyette 				wsa_strerror(r));
   1931  1.1.1.1.2.2  pgoyette 			exit(0);
   1932  1.1.1.1.2.2  pgoyette 		}
   1933  1.1.1.1.2.2  pgoyette 		atexit(&do_wsa_cleanup);
   1934  1.1.1.1.2.2  pgoyette 	}
   1935  1.1.1.1.2.2  pgoyette #endif
   1936  1.1.1.1.2.2  pgoyette 
   1937  1.1.1.1.2.2  pgoyette 	/* fetch the necessary files over HTTPS */
   1938  1.1.1.1.2.2  pgoyette 	xml = https(ip_list, xmlname, urlname);
   1939  1.1.1.1.2.2  pgoyette 	p7s = https(ip_list, p7sname, urlname);
   1940  1.1.1.1.2.2  pgoyette 
   1941  1.1.1.1.2.2  pgoyette 	/* verify and update the root anchor */
   1942  1.1.1.1.2.2  pgoyette 	verify_and_update_anchor(root_anchor_file, xml, p7s, cert, p7signer);
   1943  1.1.1.1.2.2  pgoyette 	if(verb) printf("success: the anchor has been updated "
   1944  1.1.1.1.2.2  pgoyette 			"using the cert\n");
   1945  1.1.1.1.2.2  pgoyette 
   1946  1.1.1.1.2.2  pgoyette 	free_file_bio(xml);
   1947  1.1.1.1.2.2  pgoyette 	free_file_bio(p7s);
   1948  1.1.1.1.2.2  pgoyette #ifndef S_SPLINT_S
   1949  1.1.1.1.2.2  pgoyette 	sk_X509_pop_free(cert, X509_free);
   1950  1.1.1.1.2.2  pgoyette #endif
   1951  1.1.1.1.2.2  pgoyette 	ub_resolve_free(dnskey);
   1952  1.1.1.1.2.2  pgoyette 	ip_list_free(ip_list);
   1953  1.1.1.1.2.2  pgoyette 	return 1;
   1954  1.1.1.1.2.2  pgoyette }
   1955  1.1.1.1.2.2  pgoyette 
   1956  1.1.1.1.2.2  pgoyette /**
   1957  1.1.1.1.2.2  pgoyette  * Try to read the root RFC5011 autotrust anchor file,
   1958  1.1.1.1.2.2  pgoyette  * @param file: filename.
   1959  1.1.1.1.2.2  pgoyette  * @return:
   1960  1.1.1.1.2.2  pgoyette  * 	0 if does not exist or empty
   1961  1.1.1.1.2.2  pgoyette  * 	1 if trust-point-revoked-5011
   1962  1.1.1.1.2.2  pgoyette  * 	2 if it is OK.
   1963  1.1.1.1.2.2  pgoyette  */
   1964  1.1.1.1.2.2  pgoyette static int
   1965  1.1.1.1.2.2  pgoyette try_read_anchor(const char* file)
   1966  1.1.1.1.2.2  pgoyette {
   1967  1.1.1.1.2.2  pgoyette 	int empty = 1;
   1968  1.1.1.1.2.2  pgoyette 	char line[10240];
   1969  1.1.1.1.2.2  pgoyette 	char* p;
   1970  1.1.1.1.2.2  pgoyette 	FILE* in = fopen(file, "r");
   1971  1.1.1.1.2.2  pgoyette 	if(!in) {
   1972  1.1.1.1.2.2  pgoyette 		/* only if the file does not exist, can we fix it */
   1973  1.1.1.1.2.2  pgoyette 		if(errno != ENOENT) {
   1974  1.1.1.1.2.2  pgoyette 			if(verb) printf("%s: %s\n", file, strerror(errno));
   1975  1.1.1.1.2.2  pgoyette 			if(verb) printf("error: cannot access the file\n");
   1976  1.1.1.1.2.2  pgoyette 			exit(0);
   1977  1.1.1.1.2.2  pgoyette 		}
   1978  1.1.1.1.2.2  pgoyette 		if(verb) printf("%s does not exist\n", file);
   1979  1.1.1.1.2.2  pgoyette 		return 0;
   1980  1.1.1.1.2.2  pgoyette 	}
   1981  1.1.1.1.2.2  pgoyette 	while(fgets(line, (int)sizeof(line), in)) {
   1982  1.1.1.1.2.2  pgoyette 		line[sizeof(line)-1] = 0;
   1983  1.1.1.1.2.2  pgoyette 		if(strncmp(line, ";;REVOKED", 9) == 0) {
   1984  1.1.1.1.2.2  pgoyette 			fclose(in);
   1985  1.1.1.1.2.2  pgoyette 			if(verb) printf("%s : the trust point is revoked\n"
   1986  1.1.1.1.2.2  pgoyette 				"and the zone is considered unsigned.\n"
   1987  1.1.1.1.2.2  pgoyette 				"if you wish to re-enable, delete the file\n",
   1988  1.1.1.1.2.2  pgoyette 				file);
   1989  1.1.1.1.2.2  pgoyette 			return 1;
   1990  1.1.1.1.2.2  pgoyette 		}
   1991  1.1.1.1.2.2  pgoyette 		p=line;
   1992  1.1.1.1.2.2  pgoyette 		while(*p == ' ' || *p == '\t')
   1993  1.1.1.1.2.2  pgoyette 			p++;
   1994  1.1.1.1.2.2  pgoyette 		if(p[0]==0 || p[0]=='\n' || p[0]==';') continue;
   1995  1.1.1.1.2.2  pgoyette 		/* this line is a line of content */
   1996  1.1.1.1.2.2  pgoyette 		empty = 0;
   1997  1.1.1.1.2.2  pgoyette 	}
   1998  1.1.1.1.2.2  pgoyette 	fclose(in);
   1999  1.1.1.1.2.2  pgoyette 	if(empty) {
   2000  1.1.1.1.2.2  pgoyette 		if(verb) printf("%s is empty\n", file);
   2001  1.1.1.1.2.2  pgoyette 		return 0;
   2002  1.1.1.1.2.2  pgoyette 	}
   2003  1.1.1.1.2.2  pgoyette 	if(verb) printf("%s has content\n", file);
   2004  1.1.1.1.2.2  pgoyette 	return 2;
   2005  1.1.1.1.2.2  pgoyette }
   2006  1.1.1.1.2.2  pgoyette 
   2007  1.1.1.1.2.2  pgoyette /** Write the builtin root anchor to a file */
   2008  1.1.1.1.2.2  pgoyette static void
   2009  1.1.1.1.2.2  pgoyette write_builtin_anchor(const char* file)
   2010  1.1.1.1.2.2  pgoyette {
   2011  1.1.1.1.2.2  pgoyette 	const char* builtin_root_anchor = get_builtin_ds();
   2012  1.1.1.1.2.2  pgoyette 	FILE* out = fopen(file, "w");
   2013  1.1.1.1.2.2  pgoyette 	if(!out) {
   2014  1.1.1.1.2.2  pgoyette 		if(verb) printf("%s: %s\n", file, strerror(errno));
   2015  1.1.1.1.2.2  pgoyette 		if(verb) printf("  could not write builtin anchor\n");
   2016  1.1.1.1.2.2  pgoyette 		return;
   2017  1.1.1.1.2.2  pgoyette 	}
   2018  1.1.1.1.2.2  pgoyette 	if(!fwrite(builtin_root_anchor, strlen(builtin_root_anchor), 1, out)) {
   2019  1.1.1.1.2.2  pgoyette 		if(verb) printf("%s: %s\n", file, strerror(errno));
   2020  1.1.1.1.2.2  pgoyette 		if(verb) printf("  could not complete write builtin anchor\n");
   2021  1.1.1.1.2.2  pgoyette 	}
   2022  1.1.1.1.2.2  pgoyette 	fclose(out);
   2023  1.1.1.1.2.2  pgoyette }
   2024  1.1.1.1.2.2  pgoyette 
   2025  1.1.1.1.2.2  pgoyette /**
   2026  1.1.1.1.2.2  pgoyette  * Check the root anchor file.
   2027  1.1.1.1.2.2  pgoyette  * If does not exist, provide builtin and write file.
   2028  1.1.1.1.2.2  pgoyette  * If empty, provide builtin and write file.
   2029  1.1.1.1.2.2  pgoyette  * If trust-point-revoked-5011 file: make the program exit.
   2030  1.1.1.1.2.2  pgoyette  * @param root_anchor_file: filename of the root anchor.
   2031  1.1.1.1.2.2  pgoyette  * @param used_builtin: set to 1 if the builtin is written.
   2032  1.1.1.1.2.2  pgoyette  * @return 0 if trustpoint is insecure, 1 on success.  Exit on failure.
   2033  1.1.1.1.2.2  pgoyette  */
   2034  1.1.1.1.2.2  pgoyette static int
   2035  1.1.1.1.2.2  pgoyette provide_builtin(const char* root_anchor_file, int* used_builtin)
   2036  1.1.1.1.2.2  pgoyette {
   2037  1.1.1.1.2.2  pgoyette 	/* try to read it */
   2038  1.1.1.1.2.2  pgoyette 	switch(try_read_anchor(root_anchor_file))
   2039  1.1.1.1.2.2  pgoyette 	{
   2040  1.1.1.1.2.2  pgoyette 		case 0: /* no exist or empty */
   2041  1.1.1.1.2.2  pgoyette 			write_builtin_anchor(root_anchor_file);
   2042  1.1.1.1.2.2  pgoyette 			*used_builtin = 1;
   2043  1.1.1.1.2.2  pgoyette 			break;
   2044  1.1.1.1.2.2  pgoyette 		case 1: /* revoked tp */
   2045  1.1.1.1.2.2  pgoyette 			return 0;
   2046  1.1.1.1.2.2  pgoyette 		case 2: /* it is fine */
   2047  1.1.1.1.2.2  pgoyette 		default:
   2048  1.1.1.1.2.2  pgoyette 			break;
   2049  1.1.1.1.2.2  pgoyette 	}
   2050  1.1.1.1.2.2  pgoyette 	return 1;
   2051  1.1.1.1.2.2  pgoyette }
   2052  1.1.1.1.2.2  pgoyette 
   2053  1.1.1.1.2.2  pgoyette /**
   2054  1.1.1.1.2.2  pgoyette  * add an autotrust anchor for the root to the context
   2055  1.1.1.1.2.2  pgoyette  */
   2056  1.1.1.1.2.2  pgoyette static void
   2057  1.1.1.1.2.2  pgoyette add_5011_probe_root(struct ub_ctx* ctx, const char* root_anchor_file)
   2058  1.1.1.1.2.2  pgoyette {
   2059  1.1.1.1.2.2  pgoyette 	int r;
   2060  1.1.1.1.2.2  pgoyette 	r = ub_ctx_set_option(ctx, "auto-trust-anchor-file:", root_anchor_file);
   2061  1.1.1.1.2.2  pgoyette 	if(r) {
   2062  1.1.1.1.2.2  pgoyette 		if(verb) printf("add 5011 probe to ctx: %s\n", ub_strerror(r));
   2063  1.1.1.1.2.2  pgoyette 		ub_ctx_delete(ctx);
   2064  1.1.1.1.2.2  pgoyette 		exit(0);
   2065  1.1.1.1.2.2  pgoyette 	}
   2066  1.1.1.1.2.2  pgoyette }
   2067  1.1.1.1.2.2  pgoyette 
   2068  1.1.1.1.2.2  pgoyette /**
   2069  1.1.1.1.2.2  pgoyette  * Prime the root key and return the result.  Exit on error.
   2070  1.1.1.1.2.2  pgoyette  * @param ctx: the unbound context to perform the priming with.
   2071  1.1.1.1.2.2  pgoyette  * @return: the result of the prime, on error it exit()s.
   2072  1.1.1.1.2.2  pgoyette  */
   2073  1.1.1.1.2.2  pgoyette static struct ub_result*
   2074  1.1.1.1.2.2  pgoyette prime_root_key(struct ub_ctx* ctx)
   2075  1.1.1.1.2.2  pgoyette {
   2076  1.1.1.1.2.2  pgoyette 	struct ub_result* res = NULL;
   2077  1.1.1.1.2.2  pgoyette 	int r;
   2078  1.1.1.1.2.2  pgoyette 	r = ub_resolve(ctx, ".", LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, &res);
   2079  1.1.1.1.2.2  pgoyette 	if(r) {
   2080  1.1.1.1.2.2  pgoyette 		if(verb) printf("resolve DNSKEY: %s\n", ub_strerror(r));
   2081  1.1.1.1.2.2  pgoyette 		ub_ctx_delete(ctx);
   2082  1.1.1.1.2.2  pgoyette 		exit(0);
   2083  1.1.1.1.2.2  pgoyette 	}
   2084  1.1.1.1.2.2  pgoyette 	if(!res) {
   2085  1.1.1.1.2.2  pgoyette 		if(verb) printf("out of memory\n");
   2086  1.1.1.1.2.2  pgoyette 		ub_ctx_delete(ctx);
   2087  1.1.1.1.2.2  pgoyette 		exit(0);
   2088  1.1.1.1.2.2  pgoyette 	}
   2089  1.1.1.1.2.2  pgoyette 	return res;
   2090  1.1.1.1.2.2  pgoyette }
   2091  1.1.1.1.2.2  pgoyette 
   2092  1.1.1.1.2.2  pgoyette /** see if ADDPEND keys exist in autotrust file (if possible) */
   2093  1.1.1.1.2.2  pgoyette static int
   2094  1.1.1.1.2.2  pgoyette read_if_pending_keys(const char* file)
   2095  1.1.1.1.2.2  pgoyette {
   2096  1.1.1.1.2.2  pgoyette 	FILE* in = fopen(file, "r");
   2097  1.1.1.1.2.2  pgoyette 	char line[8192];
   2098  1.1.1.1.2.2  pgoyette 	if(!in) {
   2099  1.1.1.1.2.2  pgoyette 		if(verb>=2) printf("%s: %s\n", file, strerror(errno));
   2100  1.1.1.1.2.2  pgoyette 		return 0;
   2101  1.1.1.1.2.2  pgoyette 	}
   2102  1.1.1.1.2.2  pgoyette 	while(fgets(line, (int)sizeof(line), in)) {
   2103  1.1.1.1.2.2  pgoyette 		if(line[0]==';') continue;
   2104  1.1.1.1.2.2  pgoyette 		if(strstr(line, "[ ADDPEND ]")) {
   2105  1.1.1.1.2.2  pgoyette 			fclose(in);
   2106  1.1.1.1.2.2  pgoyette 			if(verb) printf("RFC5011-state has ADDPEND keys\n");
   2107  1.1.1.1.2.2  pgoyette 			return 1;
   2108  1.1.1.1.2.2  pgoyette 		}
   2109  1.1.1.1.2.2  pgoyette 	}
   2110  1.1.1.1.2.2  pgoyette 	fclose(in);
   2111  1.1.1.1.2.2  pgoyette 	return 0;
   2112  1.1.1.1.2.2  pgoyette }
   2113  1.1.1.1.2.2  pgoyette 
   2114  1.1.1.1.2.2  pgoyette /** read last successful probe time from autotrust file (if possible) */
   2115  1.1.1.1.2.2  pgoyette static int32_t
   2116  1.1.1.1.2.2  pgoyette read_last_success_time(const char* file)
   2117  1.1.1.1.2.2  pgoyette {
   2118  1.1.1.1.2.2  pgoyette 	FILE* in = fopen(file, "r");
   2119  1.1.1.1.2.2  pgoyette 	char line[1024];
   2120  1.1.1.1.2.2  pgoyette 	if(!in) {
   2121  1.1.1.1.2.2  pgoyette 		if(verb) printf("%s: %s\n", file, strerror(errno));
   2122  1.1.1.1.2.2  pgoyette 		return 0;
   2123  1.1.1.1.2.2  pgoyette 	}
   2124  1.1.1.1.2.2  pgoyette 	while(fgets(line, (int)sizeof(line), in)) {
   2125  1.1.1.1.2.2  pgoyette 		if(strncmp(line, ";;last_success: ", 16) == 0) {
   2126  1.1.1.1.2.2  pgoyette 			char* e;
   2127  1.1.1.1.2.2  pgoyette 			time_t x = (unsigned int)strtol(line+16, &e, 10);
   2128  1.1.1.1.2.2  pgoyette 			fclose(in);
   2129  1.1.1.1.2.2  pgoyette 			if(line+16 == e) {
   2130  1.1.1.1.2.2  pgoyette 				if(verb) printf("failed to parse "
   2131  1.1.1.1.2.2  pgoyette 					"last_success probe time\n");
   2132  1.1.1.1.2.2  pgoyette 				return 0;
   2133  1.1.1.1.2.2  pgoyette 			}
   2134  1.1.1.1.2.2  pgoyette 			if(verb) printf("last successful probe: %s", ctime(&x));
   2135  1.1.1.1.2.2  pgoyette 			return (int32_t)x;
   2136  1.1.1.1.2.2  pgoyette 		}
   2137  1.1.1.1.2.2  pgoyette 	}
   2138  1.1.1.1.2.2  pgoyette 	fclose(in);
   2139  1.1.1.1.2.2  pgoyette 	if(verb) printf("no last_success probe time in anchor file\n");
   2140  1.1.1.1.2.2  pgoyette 	return 0;
   2141  1.1.1.1.2.2  pgoyette }
   2142  1.1.1.1.2.2  pgoyette 
   2143  1.1.1.1.2.2  pgoyette /**
   2144  1.1.1.1.2.2  pgoyette  * Read autotrust 5011 probe file and see if the date
   2145  1.1.1.1.2.2  pgoyette  * compared to the current date allows a certupdate.
   2146  1.1.1.1.2.2  pgoyette  * If the last successful probe was recent then 5011 cannot be behind,
   2147  1.1.1.1.2.2  pgoyette  * and the failure cannot be solved with a certupdate.
   2148  1.1.1.1.2.2  pgoyette  * The debugconf is to validation-override the date for testing.
   2149  1.1.1.1.2.2  pgoyette  * @param root_anchor_file: filename of root key
   2150  1.1.1.1.2.2  pgoyette  * @return true if certupdate is ok.
   2151  1.1.1.1.2.2  pgoyette  */
   2152  1.1.1.1.2.2  pgoyette static int
   2153  1.1.1.1.2.2  pgoyette probe_date_allows_certupdate(const char* root_anchor_file)
   2154  1.1.1.1.2.2  pgoyette {
   2155  1.1.1.1.2.2  pgoyette 	int has_pending_keys = read_if_pending_keys(root_anchor_file);
   2156  1.1.1.1.2.2  pgoyette 	int32_t last_success = read_last_success_time(root_anchor_file);
   2157  1.1.1.1.2.2  pgoyette 	int32_t now = (int32_t)time(NULL);
   2158  1.1.1.1.2.2  pgoyette 	int32_t leeway = 30 * 24 * 3600; /* 30 days leeway */
   2159  1.1.1.1.2.2  pgoyette 	/* if the date is before 2010-07-15:00.00.00 then the root has not
   2160  1.1.1.1.2.2  pgoyette 	 * been signed yet, and thus we refuse to take action. */
   2161  1.1.1.1.2.2  pgoyette 	if(time(NULL) < xml_convertdate("2010-07-15T00:00:00")) {
   2162  1.1.1.1.2.2  pgoyette 		if(verb) printf("the date is before the root was first signed,"
   2163  1.1.1.1.2.2  pgoyette 			" please correct the clock\n");
   2164  1.1.1.1.2.2  pgoyette 		return 0;
   2165  1.1.1.1.2.2  pgoyette 	}
   2166  1.1.1.1.2.2  pgoyette 	if(last_success == 0)
   2167  1.1.1.1.2.2  pgoyette 		return 1; /* no probe time */
   2168  1.1.1.1.2.2  pgoyette 	if(has_pending_keys)
   2169  1.1.1.1.2.2  pgoyette 		return 1; /* key in ADDPEND state, a previous probe has
   2170  1.1.1.1.2.2  pgoyette 		inserted that, and it was present in all recent probes,
   2171  1.1.1.1.2.2  pgoyette 		but it has not become active.  The 30 day timer may not have
   2172  1.1.1.1.2.2  pgoyette 		expired, but we know(for sure) there is a rollover going on.
   2173  1.1.1.1.2.2  pgoyette 		If we only managed to pickup the new key on its last day
   2174  1.1.1.1.2.2  pgoyette 		of announcement (for example) this can happen. */
   2175  1.1.1.1.2.2  pgoyette 	if(now - last_success < 0) {
   2176  1.1.1.1.2.2  pgoyette 		if(verb) printf("the last successful probe is in the future,"
   2177  1.1.1.1.2.2  pgoyette 			" clock was modified\n");
   2178  1.1.1.1.2.2  pgoyette 		return 0;
   2179  1.1.1.1.2.2  pgoyette 	}
   2180  1.1.1.1.2.2  pgoyette 	if(now - last_success >= leeway) {
   2181  1.1.1.1.2.2  pgoyette 		if(verb) printf("the last successful probe was more than 30 "
   2182  1.1.1.1.2.2  pgoyette 			"days ago\n");
   2183  1.1.1.1.2.2  pgoyette 		return 1;
   2184  1.1.1.1.2.2  pgoyette 	}
   2185  1.1.1.1.2.2  pgoyette 	if(verb) printf("the last successful probe is recent\n");
   2186  1.1.1.1.2.2  pgoyette 	return 0;
   2187  1.1.1.1.2.2  pgoyette }
   2188  1.1.1.1.2.2  pgoyette 
   2189  1.1.1.1.2.2  pgoyette /** perform the unbound-anchor work */
   2190  1.1.1.1.2.2  pgoyette static int
   2191  1.1.1.1.2.2  pgoyette do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
   2192  1.1.1.1.2.2  pgoyette 	const char* urlname, const char* xmlname, const char* p7sname,
   2193  1.1.1.1.2.2  pgoyette 	const char* p7signer, const char* res_conf, const char* root_hints,
   2194  1.1.1.1.2.2  pgoyette 	const char* debugconf, int ip4only, int ip6only, int force, int port)
   2195  1.1.1.1.2.2  pgoyette {
   2196  1.1.1.1.2.2  pgoyette 	struct ub_ctx* ctx;
   2197  1.1.1.1.2.2  pgoyette 	struct ub_result* dnskey;
   2198  1.1.1.1.2.2  pgoyette 	int used_builtin = 0;
   2199  1.1.1.1.2.2  pgoyette 
   2200  1.1.1.1.2.2  pgoyette 	/* see if builtin rootanchor needs to be provided, or if
   2201  1.1.1.1.2.2  pgoyette 	 * rootanchor is 'revoked-trust-point' */
   2202  1.1.1.1.2.2  pgoyette 	if(!provide_builtin(root_anchor_file, &used_builtin))
   2203  1.1.1.1.2.2  pgoyette 		return 0;
   2204  1.1.1.1.2.2  pgoyette 
   2205  1.1.1.1.2.2  pgoyette 	/* make unbound context with 5011-probe for root anchor,
   2206  1.1.1.1.2.2  pgoyette 	 * and probe . DNSKEY */
   2207  1.1.1.1.2.2  pgoyette 	ctx = create_unbound_context(res_conf, root_hints, debugconf,
   2208  1.1.1.1.2.2  pgoyette 		ip4only, ip6only);
   2209  1.1.1.1.2.2  pgoyette 	add_5011_probe_root(ctx, root_anchor_file);
   2210  1.1.1.1.2.2  pgoyette 	dnskey = prime_root_key(ctx);
   2211  1.1.1.1.2.2  pgoyette 	ub_ctx_delete(ctx);
   2212  1.1.1.1.2.2  pgoyette 
   2213  1.1.1.1.2.2  pgoyette 	/* if secure: exit */
   2214  1.1.1.1.2.2  pgoyette 	if(dnskey->secure && !force) {
   2215  1.1.1.1.2.2  pgoyette 		if(verb) printf("success: the anchor is ok\n");
   2216  1.1.1.1.2.2  pgoyette 		ub_resolve_free(dnskey);
   2217  1.1.1.1.2.2  pgoyette 		return used_builtin;
   2218  1.1.1.1.2.2  pgoyette 	}
   2219  1.1.1.1.2.2  pgoyette 	if(force && verb) printf("debug cert update forced\n");
   2220  1.1.1.1.2.2  pgoyette 
   2221  1.1.1.1.2.2  pgoyette 	/* if not (and NOERROR): check date and do certupdate */
   2222  1.1.1.1.2.2  pgoyette 	if((dnskey->rcode == 0 &&
   2223  1.1.1.1.2.2  pgoyette 		probe_date_allows_certupdate(root_anchor_file)) || force) {
   2224  1.1.1.1.2.2  pgoyette 		if(do_certupdate(root_anchor_file, root_cert_file, urlname,
   2225  1.1.1.1.2.2  pgoyette 			xmlname, p7sname, p7signer, res_conf, root_hints,
   2226  1.1.1.1.2.2  pgoyette 			debugconf, ip4only, ip6only, port, dnskey))
   2227  1.1.1.1.2.2  pgoyette 			return 1;
   2228  1.1.1.1.2.2  pgoyette 		return used_builtin;
   2229  1.1.1.1.2.2  pgoyette 	}
   2230  1.1.1.1.2.2  pgoyette 	if(verb) printf("fail: the anchor is NOT ok and could not be fixed\n");
   2231  1.1.1.1.2.2  pgoyette 	ub_resolve_free(dnskey);
   2232  1.1.1.1.2.2  pgoyette 	return used_builtin;
   2233  1.1.1.1.2.2  pgoyette }
   2234  1.1.1.1.2.2  pgoyette 
   2235  1.1.1.1.2.2  pgoyette /** getopt global, in case header files fail to declare it. */
   2236  1.1.1.1.2.2  pgoyette extern int optind;
   2237  1.1.1.1.2.2  pgoyette /** getopt global, in case header files fail to declare it. */
   2238  1.1.1.1.2.2  pgoyette extern char* optarg;
   2239  1.1.1.1.2.2  pgoyette 
   2240  1.1.1.1.2.2  pgoyette /** Main routine for unbound-anchor */
   2241  1.1.1.1.2.2  pgoyette int main(int argc, char* argv[])
   2242  1.1.1.1.2.2  pgoyette {
   2243  1.1.1.1.2.2  pgoyette 	int c;
   2244  1.1.1.1.2.2  pgoyette 	const char* root_anchor_file = ROOT_ANCHOR_FILE;
   2245  1.1.1.1.2.2  pgoyette 	const char* root_cert_file = ROOT_CERT_FILE;
   2246  1.1.1.1.2.2  pgoyette 	const char* urlname = URLNAME;
   2247  1.1.1.1.2.2  pgoyette 	const char* xmlname = XMLNAME;
   2248  1.1.1.1.2.2  pgoyette 	const char* p7sname = P7SNAME;
   2249  1.1.1.1.2.2  pgoyette 	const char* p7signer = P7SIGNER;
   2250  1.1.1.1.2.2  pgoyette 	const char* res_conf = NULL;
   2251  1.1.1.1.2.2  pgoyette 	const char* root_hints = NULL;
   2252  1.1.1.1.2.2  pgoyette 	const char* debugconf = NULL;
   2253  1.1.1.1.2.2  pgoyette 	int dolist=0, ip4only=0, ip6only=0, force=0, port = HTTPS_PORT;
   2254  1.1.1.1.2.2  pgoyette 	/* parse the options */
   2255  1.1.1.1.2.2  pgoyette 	while( (c=getopt(argc, argv, "46C:FP:a:c:f:hln:r:s:u:vx:")) != -1) {
   2256  1.1.1.1.2.2  pgoyette 		switch(c) {
   2257  1.1.1.1.2.2  pgoyette 		case 'l':
   2258  1.1.1.1.2.2  pgoyette 			dolist = 1;
   2259  1.1.1.1.2.2  pgoyette 			break;
   2260  1.1.1.1.2.2  pgoyette 		case '4':
   2261  1.1.1.1.2.2  pgoyette 			ip4only = 1;
   2262  1.1.1.1.2.2  pgoyette 			break;
   2263  1.1.1.1.2.2  pgoyette 		case '6':
   2264  1.1.1.1.2.2  pgoyette 			ip6only = 1;
   2265  1.1.1.1.2.2  pgoyette 			break;
   2266  1.1.1.1.2.2  pgoyette 		case 'a':
   2267  1.1.1.1.2.2  pgoyette 			root_anchor_file = optarg;
   2268  1.1.1.1.2.2  pgoyette 			break;
   2269  1.1.1.1.2.2  pgoyette 		case 'c':
   2270  1.1.1.1.2.2  pgoyette 			root_cert_file = optarg;
   2271  1.1.1.1.2.2  pgoyette 			break;
   2272  1.1.1.1.2.2  pgoyette 		case 'u':
   2273  1.1.1.1.2.2  pgoyette 			urlname = optarg;
   2274  1.1.1.1.2.2  pgoyette 			break;
   2275  1.1.1.1.2.2  pgoyette 		case 'x':
   2276  1.1.1.1.2.2  pgoyette 			xmlname = optarg;
   2277  1.1.1.1.2.2  pgoyette 			break;
   2278  1.1.1.1.2.2  pgoyette 		case 's':
   2279  1.1.1.1.2.2  pgoyette 			p7sname = optarg;
   2280  1.1.1.1.2.2  pgoyette 			break;
   2281  1.1.1.1.2.2  pgoyette 		case 'n':
   2282  1.1.1.1.2.2  pgoyette 			p7signer = optarg;
   2283  1.1.1.1.2.2  pgoyette 			break;
   2284  1.1.1.1.2.2  pgoyette 		case 'f':
   2285  1.1.1.1.2.2  pgoyette 			res_conf = optarg;
   2286  1.1.1.1.2.2  pgoyette 			break;
   2287  1.1.1.1.2.2  pgoyette 		case 'r':
   2288  1.1.1.1.2.2  pgoyette 			root_hints = optarg;
   2289  1.1.1.1.2.2  pgoyette 			break;
   2290  1.1.1.1.2.2  pgoyette 		case 'C':
   2291  1.1.1.1.2.2  pgoyette 			debugconf = optarg;
   2292  1.1.1.1.2.2  pgoyette 			break;
   2293  1.1.1.1.2.2  pgoyette 		case 'F':
   2294  1.1.1.1.2.2  pgoyette 			force = 1;
   2295  1.1.1.1.2.2  pgoyette 			break;
   2296  1.1.1.1.2.2  pgoyette 		case 'P':
   2297  1.1.1.1.2.2  pgoyette 			port = atoi(optarg);
   2298  1.1.1.1.2.2  pgoyette 			break;
   2299  1.1.1.1.2.2  pgoyette 		case 'v':
   2300  1.1.1.1.2.2  pgoyette 			verb++;
   2301  1.1.1.1.2.2  pgoyette 			break;
   2302  1.1.1.1.2.2  pgoyette 		case '?':
   2303  1.1.1.1.2.2  pgoyette 		case 'h':
   2304  1.1.1.1.2.2  pgoyette 		default:
   2305  1.1.1.1.2.2  pgoyette 			usage();
   2306  1.1.1.1.2.2  pgoyette 		}
   2307  1.1.1.1.2.2  pgoyette 	}
   2308  1.1.1.1.2.2  pgoyette 	argc -= optind;
   2309  1.1.1.1.2.2  pgoyette 	argv += optind;
   2310  1.1.1.1.2.2  pgoyette 	if(argc != 0)
   2311  1.1.1.1.2.2  pgoyette 		usage();
   2312  1.1.1.1.2.2  pgoyette 
   2313  1.1.1.1.2.2  pgoyette 	ERR_load_crypto_strings();
   2314  1.1.1.1.2.2  pgoyette 	ERR_load_SSL_strings();
   2315  1.1.1.1.2.2  pgoyette 	OpenSSL_add_all_algorithms();
   2316  1.1.1.1.2.2  pgoyette 	(void)SSL_library_init();
   2317  1.1.1.1.2.2  pgoyette 
   2318  1.1.1.1.2.2  pgoyette 	if(dolist) do_list_builtin();
   2319  1.1.1.1.2.2  pgoyette 
   2320  1.1.1.1.2.2  pgoyette 	return do_root_update_work(root_anchor_file, root_cert_file, urlname,
   2321  1.1.1.1.2.2  pgoyette 		xmlname, p7sname, p7signer, res_conf, root_hints, debugconf,
   2322  1.1.1.1.2.2  pgoyette 		ip4only, ip6only, force, port);
   2323  1.1.1.1.2.2  pgoyette }
   2324