unbound-anchor work

git-svn-id: file:///svn/unbound/trunk@2243 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2010-09-23 15:28:08 +00:00
parent 1c2a8d977c
commit 8ef0b0ff30
3 changed files with 299 additions and 53 deletions

38
configure vendored
View file

@ -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.

View file

@ -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=""

View file

@ -50,6 +50,8 @@
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include <openssl/x509.h>
#include <openssl/pem.h>
/* 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
*/