From: Wouter Wijngaards Date: Thu, 23 Sep 2010 15:28:08 +0000 (+0000) Subject: unbound-anchor work X-Git-Tag: release-1.4.7rc1~82 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8ef0b0ff30fd2f845a46ef329d7d7f92be57b7e8;p=thirdparty%2Funbound.git unbound-anchor work git-svn-id: file:///svn/unbound/trunk@2243 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/configure b/configure index b10d2d075..06b766351 100755 --- a/configure +++ b/configure @@ -12421,7 +12421,7 @@ CC="$lt_save_CC" # Checks for header files. -for ac_header in stdarg.h stdbool.h netinet/in.h sys/param.h sys/socket.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h expat.h +for ac_header in stdarg.h stdbool.h netinet/in.h sys/param.h sys/socket.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default @@ -15601,7 +15601,41 @@ $as_echo "#define USE_MINI_EVENT 1" >>confdefs.h fi -# set static linking if requested +# check for libexpat +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libexpat" >&5 +$as_echo_n "checking for libexpat... " >&6; } +found_libexpat="no" +for dir in /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr; do + echo if test -f "$dir/include/expat.h" + if test -f "$dir/include/expat.h"; then + found_libexpat="yes" + if test "$dir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$dir/include" + LDFLAGS="$LDFLAGS -L$dir/lib" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5 +$as_echo "found in $dir" >&6; } + break; + fi +done +if test x_$found_libexpat != x_yes; then + as_fn_error "Could not find libexpat, expat.h" "$LINENO" 5 +fi +for ac_header in expat.h +do : + ac_fn_c_check_header_compile "$LINENO" "expat.h" "ac_cv_header_expat_h" "$ac_includes_default +" +if test "x$ac_cv_header_expat_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EXPAT_H 1 +_ACEOF + +fi + +done + + +# set static linking if requestd staticexe="" # Check whether --enable-staticexe was given. diff --git a/configure.ac b/configure.ac index dd3c4d9d1..eedc2f5d6 100644 --- a/configure.ac +++ b/configure.ac @@ -218,7 +218,7 @@ AC_CHECK_TOOL(STRIP, strip) ACX_LIBTOOL_C_ONLY # Checks for header files. -AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h sys/param.h sys/socket.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h expat.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h sys/param.h sys/socket.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT]) # check for types. # Using own tests for int64* because autoconf builtin only give 32bit. @@ -528,6 +528,26 @@ else AC_DEFINE(USE_MINI_EVENT, 1, [Define if you want to use internal select based events]) fi +# check for libexpat +AC_MSG_CHECKING(for libexpat) +found_libexpat="no" +for dir in /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr; do + if test -f "$dir/include/expat.h"; then + found_libexpat="yes" + dnl assume /usr is in default path. + if test "$dir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$dir/include" + LDFLAGS="$LDFLAGS -L$dir/lib" + fi + AC_MSG_RESULT(found in $dir) + break; + fi +done +if test x_$found_libexpat != x_yes; then + AC_ERROR([Could not find libexpat, expat.h]) +fi +AC_CHECK_HEADERS([expat.h],,, [AC_INCLUDES_DEFAULT]) + # set static linking if requested AC_SUBST(staticexe) staticexe="" diff --git a/smallapp/unbound-anchor.c b/smallapp/unbound-anchor.c index 48d01dff8..431e1a397 100644 --- a/smallapp/unbound-anchor.c +++ b/smallapp/unbound-anchor.c @@ -50,6 +50,8 @@ #ifdef HAVE_GETOPT_H #include #endif +#include +#include /* TODO configure defines with prefix */ /** root key file, 5011 tracked */ @@ -68,6 +70,16 @@ /** verbosity for this application */ static int verb = 0; +/** list of IP addresses */ +struct ip_list { + /** next in list */ + struct ip_list* next; + /** length of addr */ + socklen_t len; + /** address ready to connect to */ + struct sockaddr_storage addr; +}; + /** Give unbound-anchor usage, and exit (1). */ static void usage() @@ -105,6 +117,222 @@ usage() exit(1); } +/** print ub context creation error and exit */ +static void +ub_ctx_error_exit(struct ub_ctx* ctx, const char* str, const char* str2) +{ + ub_ctx_delete(ctx); + if(str && str2 && verb) printf("%s: %s\n", str, str2); + if(verb) printf("error: could not create unbound resolver context\n"); + exit(0); +} + +/** + * Create a new unbound context with the commandline settings applied + */ +static struct ub_ctx* +create_unbound_context(char* res_conf, char* root_hints, char* debugconf, + int ip4only, int ip6only) +{ + int r; + struct ub_ctx* ctx = ub_ctx_create(); + if(!ctx) { + if(verb) printf("out of memory\n"); + exit(0); + } + /* do not waste time and network traffic to fetch extra nameservers */ + r = ub_ctx_set_option(ctx, "target-fetch-policy:", "0 0 0 0 0"); + if(r && verb) printf("ctx targetfetchpolicy: %s\n", ub_strerror(r)); + /* read config file first, so its settings can be overridden */ + if(debugconf) { + r = ub_ctx_config(ctx, debugconf); + if(r) ub_ctx_error_exit(ctx, debugconf, ub_strerror(r)); + } + if(res_conf) { + r = ub_ctx_resolvconf(ctx, res_conf); + if(r) ub_ctx_error_exit(ctx, res_conf, ub_strerror(r)); + } + if(root_hints) { + r = ub_ctx_set_option(ctx, "root-hints:", root_hints); + if(r) ub_ctx_error_exit(ctx, root_hints, ub_strerror(r)); + } + if(ip4only) { + r = ub_ctx_set_option(ctx, "do-ip6:", "no"); + if(r) ub_ctx_error_exit(ctx, "ip4only", ub_strerror(r)); + } + if(ip6only) { + r = ub_ctx_set_option(ctx, "do-ip4:", "no"); + if(r) ub_ctx_error_exit(ctx, "ip6only", ub_strerror(r)); + } + return ctx; +} + +/** read certificates from a PEM bio */ +static STACK_OF(X509)* +read_cert_bio(BIO* bio) +{ + STACK_OF(X509) *sk = sk_X509_new_null(); + if(!sk) { + if(verb) printf("out of memory\n"); + exit(0); + } + while(!BIO_eof(bio)) { + X509* x = PEM_read_bio_X509(bio, NULL, 0, NULL); + if(x == NULL) { + if(verb) printf("failed to read X509\n"); + continue; + } + if(!sk_X509_push(sk, x)) { + if(verb) printf("out of memory\n"); + exit(0); + } + } + return sk; +} + +/* read the certificate file */ +static STACK_OF(X509)* +read_cert_file(char* file) +{ + STACK_OF(X509)* sk = sk_X509_new_null(); + FILE* in; + int content = 0; + if(!sk) { + if(verb) printf("out of memory\n"); + exit(0); + } + in = fopen(file, "r"); + if(!in) { + if(verb) printf("%s: %s\n", file, strerror(errno)); + sk_X509_free(sk); + return NULL; + } + while(!feof(in)) { + X509* x = PEM_read_X509(in, NULL, 0, NULL); + if(x == NULL) { + if(verb) printf("failed to read X509\n"); + continue; + } + if(!sk_X509_push(sk, x)) { + if(verb) printf("out of memory\n"); + fclose(in); + exit(0); + } + content = 1; + } + fclose(in); + if(!content) { + if(verb) printf("%s is empty\n", file); + sk_X509_free(sk); + return NULL; + } + return sk; +} + +/** read certificates from the builtin certificate */ +static STACK_OF(X509)* +read_builtin_cert(void) +{ + const char* builtin_cert = +"-----BEGIN CERTIFICATE-----\n" +"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n" +"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n" +"BAMTDUlDQU5OIFJvb3QgQ0ExCzAJBgNVBAYTAlVTMB4XDTA5MTIyMzA0MTkxMloX\n" +"DTI5MTIxODA0MTkxMlowXTEOMAwGA1UEChMFSUNBTk4xJjAkBgNVBAsTHUlDQU5O\n" +"IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1JQ0FOTiBSb290IENB\n" +"MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDb\n" +"cLhPNNqc1NB+u+oVvOnJESofYS9qub0/PXagmgr37pNublVThIzyLPGCJ8gPms9S\n" +"G1TaKNIsMI7d+5IgMy3WyPEOECGIcfqEIktdR1YWfJufXcMReZwU4v/AdKzdOdfg\n" +"ONiwc6r70duEr1IiqPbVm5T05l1e6D+HkAvHGnf1LtOPGs4CHQdpIUcy2kauAEy2\n" +"paKcOcHASvbTHK7TbbvHGPB+7faAztABLoneErruEcumetcNfPMIjXKdv1V1E3C7\n" +"MSJKy+jAqqQJqjZoQGB0necZgUMiUv7JK1IPQRM2CXJllcyJrm9WFxY0c1KjBO29\n" +"iIKK69fcglKcBuFShUECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n" +"Af8EBAMCAf4wHQYDVR0OBBYEFLpS6UmDJIZSL8eZzfyNa2kITcBQMA0GCSqGSIb3\n" +"DQEBCwUAA4IBAQAP8emCogqHny2UYFqywEuhLys7R9UKmYY4suzGO4nkbgfPFMfH\n" +"6M+Zj6owwxlwueZt1j/IaCayoKU3QsrYYoDRolpILh+FPwx7wseUEV8ZKpWsoDoD\n" +"2JFbLg2cfB8u/OlE4RYmcxxFSmXBg0yQ8/IoQt/bxOcEEhhiQ168H2yE5rxJMt9h\n" +"15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF\n" +"0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n" +"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n" +"-----END CERTIFICATE-----\n" + ; + STACK_OF(X509)* sk; + BIO *bio = BIO_new_mem_buf((void*)builtin_cert, strlen(builtin_cert)); + if(!bio) { + if(verb) printf("out of memory\n"); + exit(0); + } + sk = read_cert_bio(bio); + if(!sk) { + if(verb) printf("internal error, out of memory\n"); + exit(0); + } + BIO_free(bio); + return sk; +} + +/** read update cert file or use builtin */ +static STACK_OF(X509)* +read_cert_or_builtin(char* file, int* write_cert) +{ + STACK_OF(X509) *sk = read_cert_file(file); + if(!sk) { + *write_cert = 1; + if(verb) printf("using builtin certificate\n"); + sk = read_builtin_cert(); + } + if(verb) printf("have %d trusted certificates\n", sk_X509_num(sk)); + return sk; +} + +/** Resolve name, type, class and add addresses to iplist */ +static void +add_ip(struct ub_ctx* ctx, char* host, int tp, int cl, struct ip_list** head) +{ +} + +/** + * Resolve a domain name (even though the resolver is down and there is + * no trust anchor). Without DNSSEC validation. + */ +static struct ip_list* +resolve_name(char* host, char* res_conf, char* root_hints, char* debugconf, + int ip4only, int ip6only) +{ + struct ub_ctx* ctx; + struct ip_list* list = NULL; + /* first see if name is an IP address itself */ + /* TODO */ + + /* create resolver context */ + ctx = create_unbound_context(res_conf, root_hints, debugconf, + ip4only, ip6only); + + /* try resolution of A */ + if(!ip6only) { + add_ip(ctx, host, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, &list); + } + + /* try resolution of AAAA */ + if(!ip4only) { + add_ip(ctx, host, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN, &list); + } + + ub_ctx_delete(ctx); + return list; +} + +/** + * Do a HTTPS, HTTP1.1 over TLS, to fetch a file + * @param ip_list: list of IP addresses to use to fetch from. + * @param pathname: pathname of file on server to GET. + * @return a memory BIO with the file in it. + */ +static BIO* +https(struct ip_list* ip_list, char* pathname) +{ +} + /** perform actual certupdate work */ static int do_certupdate(char* root_anchor_file, char* root_cert_file, @@ -112,11 +340,21 @@ do_certupdate(char* root_anchor_file, char* root_cert_file, char* res_conf, char* root_hints, char* debugconf, int ip4only, int ip6only, struct ub_result* dnskey) { + int write_cert = 0; + STACK_OF(X509)* cert; + BIO *pem, *xml, *p7s; + struct ip_list* ip_list; /* read pem file or provide builtin */ + cert = read_cert_or_builtin(root_cert_file, &write_cert); /* lookup A, AAAA for the urlname (or parse urlname if IP address) */ + ip_list = resolve_name(urlname, res_conf, root_hints, debugconf, + ip4only, ip6only); /* fetch the necessary files over HTTPS */ + xml = https(ip_list, xmlname); + p7s = https(ip_list, p7sname); + pem = https(ip_list, pemname); /* update the pem file (optional) */ @@ -126,6 +364,10 @@ do_certupdate(char* root_anchor_file, char* root_cert_file, /* reinstate 5011 tracking */ if(verb) printf("success: the anchor has been updated " "using the cert\n"); + BIO_free(xml); + BIO_free(p7s); + BIO_free(pem); + sk_X509_free(cert); ub_resolve_free(dnskey); return 0; } @@ -223,56 +465,6 @@ provide_builtin(char* root_anchor_file) return 1; } -/** print ub context creation error and exit */ -static void -ub_ctx_error_exit(struct ub_ctx* ctx, const char* str, const char* str2) -{ - ub_ctx_delete(ctx); - if(str && str2 && verb) printf("%s: %s\n", str, str2); - if(verb) printf("error: could not create unbound resolver context\n"); - exit(0); -} - -/** - * Create a new unbound context with the commandline settings applied - */ -static struct ub_ctx* -create_unbound_context(char* res_conf, char* root_hints, char* debugconf, - int ip4only, int ip6only) -{ - int r; - struct ub_ctx* ctx = ub_ctx_create(); - if(!ctx) { - if(verb) printf("out of memory\n"); - exit(0); - } - /* do not waste time and network traffic to fetch extra nameservers */ - r = ub_ctx_set_option(ctx, "target-fetch-policy:", "0 0 0 0 0"); - if(r && verb) printf("ctx targetfetchpolicy: %s\n", ub_strerror(r)); - /* read config file first, so its settings can be overridden */ - if(debugconf) { - r = ub_ctx_config(ctx, debugconf); - if(r) ub_ctx_error_exit(ctx, debugconf, ub_strerror(r)); - } - if(res_conf) { - r = ub_ctx_resolvconf(ctx, res_conf); - if(r) ub_ctx_error_exit(ctx, res_conf, ub_strerror(r)); - } - if(root_hints) { - r = ub_ctx_set_option(ctx, "root-hints:", root_hints); - if(r) ub_ctx_error_exit(ctx, root_hints, ub_strerror(r)); - } - if(ip4only) { - r = ub_ctx_set_option(ctx, "do-ip6:", "no"); - if(r) ub_ctx_error_exit(ctx, "ip4only", ub_strerror(r)); - } - if(ip6only) { - r = ub_ctx_set_option(ctx, "do-ip4:", "no"); - if(r) ub_ctx_error_exit(ctx, "ip6only", ub_strerror(r)); - } - return ctx; -} - /** * add an autotrust anchor for the root to the context */