unbound-anchor work

git-svn-id: file:///svn/unbound/trunk@2242 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2010-09-23 13:51:29 +00:00
parent 1797024a4e
commit 1c2a8d977c
9 changed files with 651 additions and 11 deletions

View file

@ -110,6 +110,8 @@ CONTROL_SRC=smallapp/unbound-control.c smallapp/worker_cb.c $(COMMON_SRC)
CONTROL_OBJ=$(addprefix $(BUILD),$(CONTROL_SRC:.c=.lo)) $(COMPAT_OBJ)
HOST_SRC=smallapp/unbound-host.c
HOST_OBJ=$(addprefix $(BUILD),$(HOST_SRC:.c=.lo)) $(filter-out $(BUILD)compat/ctime_r.lo, $(COMPAT_OBJ))
UBANCHOR_SRC=smallapp/unbound-anchor.c
UBANCHOR_OBJ=$(addprefix $(BUILD),$(UBANCHOR_SRC:.c=.lo)) $(filter-out $(BUILD)compat/ctime_r.lo, $(COMPAT_OBJ))
TESTBOUND_SRC=testcode/testbound.c testcode/ldns-testpkts.c \
daemon/worker.c daemon/acl_list.c daemon/daemon.c daemon/stats.c \
testcode/replay.c testcode/fake_event.c $(filter-out util/netevent.c \
@ -141,7 +143,7 @@ ALL_SRC=$(sort $(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
$(TESTBOUND_SRC) $(LOCKVERIFY_SRC) $(PKTVIEW_SRC) $(SIGNIT_SRC) \
$(MEMSTATS_SRC) $(CHECKCONF_SRC) $(LIBUNBOUND_SRC) $(HOST_SRC) \
$(ASYNCLOOK_SRC) $(STREAMTCP_SRC) $(PERF_SRC) $(DELAYER_SRC) \
$(HARVEST_SRC) $(CONTROL_SRC))
$(HARVEST_SRC) $(CONTROL_SRC) $(UBANCHOR_SRC))
ALL_OBJ=$(addprefix $(BUILD),$(ALL_SRC:.c=.lo) \
$(addprefix compat/,$(LIBOBJS:.o=.lo))) $(COMPAT_OBJ)
@ -149,6 +151,7 @@ ifeq "$(UB_ON_WINDOWS)" "yes"
DAEMON_SRC+=winrc/win_svc.c winrc/w_inst.c
DAEMON_OBJ+=$(BUILD)winrc/rsrc_unbound.o $(BUILD)winrc/win_svc.lo
HOST_OBJ+=$(BUILD)winrc/rsrc_unbound_host.o
UBANCHOR_OBJ+=$(BUILD)winrc/rsrc_unbound_anchor.o
CONTROL_OBJ+=$(BUILD)winrc/rsrc_unbound_control.o
CHECKCONF_OBJ+=$(BUILD)winrc/rsrc_unbound_checkconf.o
@ -188,7 +191,7 @@ $(BUILD)%.lo: $(srcdir)/%.c
@-if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
$Q$(COMPILE) -o $@ -c $<
all: $(COMMON_OBJ) unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-control-setup $(WINAPPS)
all: $(COMMON_OBJ) unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup $(WINAPPS)
TEST_BIN=$(addsuffix $(EXEEXT),asynclook delayer harvest lock-verify \
memstats perf pktview signit streamtcp testbound unittest)
@ -238,6 +241,10 @@ unbound-host$(EXEEXT): $(HOST_OBJ) libunbound.la $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(HOST_OBJ)) -L. -L.libs -lunbound $(LIBS)
unbound-anchor$(EXEEXT): $(UBANCHOR_OBJ) libunbound.la $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(UBANCHOR_OBJ)) -L. -L.libs -lunbound -lexpat -lssl $(LIBS)
unbound-service-install$(EXEEXT): $(SVCINST_OBJ)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(SVCINST_OBJ)) $(LIBS)
@ -343,7 +350,7 @@ util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y
clean:
rm -f *.o *.d *.lo *~ tags
rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-control-setup libunbound.la
rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la
rm -rf autom4te.cache .libs build doc/html doc/xml
realclean: clean
@ -380,6 +387,7 @@ strip:
$(STRIP) unbound-checkconf$(EXEEXT)
$(STRIP) unbound-control$(EXEEXT)
$(STRIP) unbound-host$(EXEEXT)
$(STRIP) unbound-anchor$(EXEEXT)
install: all
$(INSTALL) -m 755 -d $(DESTDIR)$(sbindir)
@ -394,6 +402,7 @@ install: all
$(LIBTOOL) --mode=install cp unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT)
$(LIBTOOL) --mode=install cp unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT)
$(LIBTOOL) --mode=install cp unbound-host$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-host$(EXEEXT)
$(LIBTOOL) --mode=install cp unbound-anchor$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-anchor$(EXEEXT)
ifeq "$(WITH_PYTHONMODULE)" "yes"
$(INSTALL) -m 755 -d $(DESTDIR)$(PYTHON_SITE_PKG)
$(INSTALL) -c -m 644 pythonmod/unboundmodule.py $(DESTDIR)$(PYTHON_SITE_PKG)/unboundmodule.py
@ -407,6 +416,7 @@ endif
$(INSTALL) -c -m 644 doc/unbound.8 $(DESTDIR)$(mandir)/man8
$(INSTALL) -c -m 644 doc/unbound-checkconf.8 $(DESTDIR)$(mandir)/man8
$(INSTALL) -c -m 644 doc/unbound-control.8 $(DESTDIR)$(mandir)/man8
$(INSTALL) -c -m 644 doc/unbound-anchor.8 $(DESTDIR)$(mandir)/man8
$(INSTALL) -c -m 644 doc/unbound.conf.5 $(DESTDIR)$(mandir)/man5
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound-host.1 $(DESTDIR)$(mandir)/man1
$(INSTALL) -c -m 644 doc/libunbound.3 $(DESTDIR)$(mandir)/man3
@ -417,8 +427,8 @@ endif
$(LIBTOOL) --mode=finish $(DESTDIR)$(libdir)
uninstall:
rm -f -- $(DESTDIR)$(sbindir)/unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-host$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control-setup
rm -f -- $(DESTDIR)$(mandir)/man8/unbound.8 $(DESTDIR)$(mandir)/man8/unbound-checkconf.8 $(DESTDIR)$(mandir)/man5/unbound.conf.5 $(DESTDIR)$(mandir)/man8/unbound-control.8
rm -f -- $(DESTDIR)$(sbindir)/unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-host$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-anchor$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control-setup
rm -f -- $(DESTDIR)$(mandir)/man8/unbound.8 $(DESTDIR)$(mandir)/man8/unbound-checkconf.8 $(DESTDIR)$(mandir)/man5/unbound.conf.5 $(DESTDIR)$(mandir)/man8/unbound-control.8 $(DESTDIR)$(mandir)/man8/unbound-anchor.8
rm -f -- $(DESTDIR)$(mandir)/man1/unbound-host.1 $(DESTDIR)$(mandir)/man3/libunbound.3
rm -f -- $(DESTDIR)$(includedir)/unbound.h
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/libunbound.la

View file

@ -84,6 +84,9 @@
/* Define to 1 if you have the `ev_loop' function. */
#undef HAVE_EV_LOOP
/* Define to 1 if you have the <expat.h> header file. */
#undef HAVE_EXPAT_H
/* Define to 1 if you have the `fcntl' function. */
#undef HAVE_FCNTL

5
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
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
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
@ -16542,7 +16542,7 @@ _ACEOF
ac_config_files="$ac_config_files Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8"
ac_config_files="$ac_config_files Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8"
ac_config_headers="$ac_config_headers config.h"
@ -17497,6 +17497,7 @@ do
"doc/example.conf") CONFIG_FILES="$CONFIG_FILES doc/example.conf" ;;
"doc/libunbound.3") CONFIG_FILES="$CONFIG_FILES doc/libunbound.3" ;;
"doc/unbound.8") CONFIG_FILES="$CONFIG_FILES doc/unbound.8" ;;
"doc/unbound-anchor.8") CONFIG_FILES="$CONFIG_FILES doc/unbound-anchor.8" ;;
"doc/unbound-checkconf.8") CONFIG_FILES="$CONFIG_FILES doc/unbound-checkconf.8" ;;
"doc/unbound.conf.5") CONFIG_FILES="$CONFIG_FILES doc/unbound.conf.5" ;;
"doc/unbound-control.8") CONFIG_FILES="$CONFIG_FILES doc/unbound-control.8" ;;

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],,, [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 expat.h],,, [AC_INCLUDES_DEFAULT])
# check for types.
# Using own tests for int64* because autoconf builtin only give 32bit.
@ -816,6 +816,6 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
#define UNBOUND_DNS_PORT 53
])
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8])
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8])
AC_CONFIG_HEADER([config.h])
AC_OUTPUT

View file

@ -1,3 +1,6 @@
23 September 2010: Wouter
- unbound-anchor app, unbound requires libexpat (xml parser library).
22 September 2010: Wouter
- compliance with draft-ietf-dnsop-default-local-zones-14, removed
reverse ipv6 orchid prefix from builtin list.

64
doc/unbound-anchor.8.in Normal file
View file

@ -0,0 +1,64 @@
.TH "unbound-anchor" "8" "@date@" "NLnet Labs" "unbound @version@"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
.\" Copyright (c) 2008, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.SH "NAME"
.LP
.B unbound\-anchor
\- Unbound anchor utility.
.SH "SYNOPSIS"
.B unbound\-anchor
.RB [ opts ]
.SH "DESCRIPTION"
.B Unbound\-anchor
performs setup or update of the root trust anchor for DNSSEC validation.
It can be run (as root) from the commandline, or run as part of startup
scripts. Before you start the \fIunbound\fR(8) DNS server.
.P
It provides builtin default contents for the root anchor and root update
certificate files.
.P
It tests if the root anchor file works, and if not, and an update is possible,
attempts to update the root anchor using the root update certificate.
It performs a https fetch of root-anchors.xml and checks the results, if
all checks are successful, it updates the root anchor file. Otherwise
the root anchor file is unchanged. It performs RFC5011 tracking if the
DNSSEC information available via the DNS makes that possible.
.P
If does not perform an update if the certificate is expired, if the network
is down or other errors occur.
.P
The available options are:
.TP
.B \-a \fIfile
The root anchor key file, that is read in and written out.
Default is /usr/local/etc/unbound/root.key.
.TP
.B \-c \fIfile
The root update certificate file, that is read in. It can be updated too.
Default is /usr/local/etc/unbound/icannbundle.pem.
.TP
.B \-h
Show the version and commandline option help.
.TP
.B \-v
More verbose. Prints output detailing what happens.
.TP
.B \-C \fIcfgfile
Config file to read with debug settings.
.SH "FILES"
.TP
.I /usr/local/etc/unbound/root.key
The root anchor file, updated with 5011 tracking, and read and written to.
.TP
.I /usr/local/etc/unbound/icannbundle.pem
The trusted self\-signed certificate that is used to verify the downloaded
DNSSEC root trust anchor.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
\fIunbound\fR(8).

View file

@ -260,14 +260,15 @@ if [ "$DOWIN" = "yes" ]; then
$strip anchor-update.exe
$strip unbound-control.exe
$strip unbound-host.exe
$strip unbound-anchor.exe
$strip unbound-checkconf.exe
$strip unbound-service-install.exe
$strip unbound-service-remove.exe
cd tmp.$$
cp ../doc/example.conf example.conf
cp ../unbound.exe ../unbound-host.exe ../unbound-control.exe ../unbound-checkconf.exe ../unbound-service-install.exe ../unbound-service-remove.exe ../LICENSE ../winrc/unbound-website.url ../winrc/service.conf ../winrc/README.txt .
cp ../unbound.exe ../unbound-anchor.exe ../unbound-host.exe ../unbound-control.exe ../unbound-checkconf.exe ../unbound-service-install.exe ../unbound-service-remove.exe ../LICENSE ../winrc/unbound-website.url ../winrc/service.conf ../winrc/README.txt .
# zipfile
zip ../$file LICENSE README.txt unbound.exe unbound-host.exe unbound-control.exe unbound-checkconf.exe unbound-service-install.exe unbound-service-remove.exe example.conf service.conf unbound-website.url
zip ../$file LICENSE README.txt unbound.exe unbound-anchor.exe unbound-host.exe unbound-control.exe unbound-checkconf.exe unbound-service-install.exe unbound-service-remove.exe example.conf service.conf unbound-website.url
info "Testing $file"
(cd .. ; zip -T $file )
# installer
@ -385,6 +386,7 @@ replace_all doc/unbound.8.in
replace_all doc/unbound.conf.5.in
replace_all doc/unbound-checkconf.8.in
replace_all doc/unbound-control.8.in
replace_all doc/unbound-anchor.8.in
replace_all doc/unbound-host.1
replace_all doc/libunbound.3.in

520
smallapp/unbound-anchor.c Normal file
View file

@ -0,0 +1,520 @@
/*
* unbound-anchor.c - update the root anchor if necessary.
*
* Copyright (c) 2010, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file checks to see that the current 5011 keys work to prime the
* current root anchor. If not a certificate is used to update the anchor.
*/
#include "config.h"
#include "libunbound/unbound.h"
#include <ldns/rr.h>
#include <expat.h>
#ifndef HAVE_EXPAT_H
#error "need libexpat to parse root-anchors.xml file."
#endif
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
/* TODO configure defines with prefix */
/** root key file, 5011 tracked */
#define ROOT_ANCHOR_FILE "/usr/local/etc/unbound/root.key"
/** root update cert file */
#define ROOT_CERT_FILE "/usr/local/etc/unbound/icannbundle.pem"
/** name of server in URL to fetch HTTPS from */
#define URLNAME "data.iana.org"
/** path on HTTPS server to xml file */
#define XMLNAME "/root-anchors/root-anchors.xml"
/** path on HTTPS server to p7s file */
#define P7SNAME "/root-anchors/root-anchors.p7s"
/** path on HTTPS server to pem file */
#define PEMNAME "/root-anchors/icannbundle.pem"
/** verbosity for this application */
static int verb = 0;
/** Give unbound-anchor usage, and exit (1). */
static void
usage()
{
printf("Usage: unbound-anchor [opts]\n");
printf(" Setup or update root anchor. "
"Most options have defaults.\n");
printf(" Run this program before you start the validator.\n");
printf("\n");
printf(" The anchor and cert are filled with default builtin\n");
printf(" values if the file does not exist or is empty.\n");
printf("\n");
printf("-a file root key file, default %s\n", ROOT_ANCHOR_FILE);
printf("-c file cert file, default %s\n", ROOT_CERT_FILE);
/* TODO
printf("-o file output key file, if enabled new key written"
" there and exit code 4 for manual change\n");
*/
printf("-u name server in https url, default %s\n", URLNAME);
printf("-x path pathname to xml, default %s\n", XMLNAME);
printf("-s path pathname to p7s, default %s\n", P7SNAME);
printf("-p path pathname to pem, default %s\n", PEMNAME);
printf("-4 work using IPv4 only\n");
printf("-6 work using IPv6 only\n");
printf("-f resolv.conf use given resolv.conf to resolve -u name\n");
printf("-r root.hints use given root.hints to resolve -u name\n"
" builtin root hints are used by default\n");
printf("-v more verbose\n");
printf("-C conf debug, read config\n");
printf("-F debug, force update with cert\n");
printf("-h show this usage help\n");
printf("Version %s\n", PACKAGE_VERSION);
printf("BSD licensed, see LICENSE in source package for details.\n");
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
exit(1);
}
/** perform actual certupdate work */
static int
do_certupdate(char* root_anchor_file, char* root_cert_file,
char* urlname, char* xmlname, char* p7sname, char* pemname,
char* res_conf, char* root_hints, char* debugconf,
int ip4only, int ip6only, struct ub_result* dnskey)
{
/* read pem file or provide builtin */
/* lookup A, AAAA for the urlname (or parse urlname if IP address) */
/* fetch the necessary files over HTTPS */
/* update the pem file (optional) */
/* verify and update the root anchor */
/* verify xml file */
/* see if xml file verifies the dnskey that was probed */
/* reinstate 5011 tracking */
if(verb) printf("success: the anchor has been updated "
"using the cert\n");
ub_resolve_free(dnskey);
return 0;
}
/**
* Try to read the root RFC5011 autotrust anchor file,
* @param file: filename.
* @return:
* 0 if does not exist or empty
* 1 if trust-point-revoked-5011
* 2 if it is OK.
*/
static int
try_read_anchor(char* file)
{
int empty = 1;
char line[10240];
char* p;
FILE* in = fopen(file, "r");
if(!in) {
/* only if the file does not exist, can we fix it */
if(errno != ENOENT) {
if(verb) printf("%s: %s\n", file, strerror(errno));
if(verb) printf("error: cannot access the file\n");
exit(0);
}
if(verb) printf("%s does not exist\n", file);
return 0;
}
while(fgets(line, (int)sizeof(line), in)) {
line[sizeof(line)-1] = 0;
if(strncmp(line, ";;REVOKED", 9) == 0) {
fclose(in);
if(verb) printf("%s : the trust point is revoked\n"
"and the zone is considered unsigned.\n"
"if you wish to re-enable, delete the file\n",
file);
return 1;
}
p=line;
while(*p == ' ' || *p == '\t')
p++;
if(p[0]==0 || p[0]=='\n' || p[0]==';') continue;
/* this line is a line of content */
empty = 0;
}
fclose(in);
if(empty) {
if(verb) printf("%s is empty\n", file);
return 0;
}
if(verb) printf("%s has content\n", file);
return 2;
}
/** Write the builtin root anchor to a file */
static void
write_builtin_anchor(char* file)
{
const char* builtin_root_anchor = ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n";
FILE* out = fopen(file, "w");
if(!out) {
if(verb) printf("%s: %s\n", file, strerror(errno));
if(verb) printf(" could not write builtin anchor\n");
return;
}
if(!fwrite(builtin_root_anchor, strlen(builtin_root_anchor), 1, out)) {
if(verb) printf("%s: %s\n", file, strerror(errno));
if(verb) printf(" could not complete write builtin anchor\n");
}
fclose(out);
}
/**
* Check the root anchor file.
* If does not exist, provide builtin and write file.
* If empty, provide builtin and write file.
* If trust-point-revoked-5011 file: make the program exit.
*/
static int
provide_builtin(char* root_anchor_file)
{
/* try to read it */
switch(try_read_anchor(root_anchor_file))
{
case 0: /* no exist or empty */
write_builtin_anchor(root_anchor_file);
break;
case 1: /* revoked tp */
return 0;
case 2: /* it is fine */
default:
break;
}
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
*/
static void
add_5011_probe_root(struct ub_ctx* ctx, char* root_anchor_file)
{
int r;
r = ub_ctx_set_option(ctx, "auto-trust-anchor-file:", root_anchor_file);
if(r) {
if(verb) printf("add 5011 probe to ctx: %s\n", ub_strerror(r));
ub_ctx_delete(ctx);
exit(0);
}
}
/**
* Prime the root key and return the result. Exit on error.
*/
static struct ub_result*
prime_root_key(struct ub_ctx* ctx)
{
struct ub_result* res = NULL;
int r;
r = ub_resolve(ctx, ".", LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, &res);
if(r) {
if(verb) printf("resolve DNSKEY: %s\n", ub_strerror(r));
ub_ctx_delete(ctx);
exit(0);
}
if(!res) {
if(verb) printf("out of memory\n");
ub_ctx_delete(ctx);
exit(0);
}
return res;
}
/** read last successful probe time from autotrust file (if possible) */
static int32_t
read_last_success_time(char* file)
{
FILE* in = fopen(file, "r");
char line[1024];
if(!in) {
if(verb) printf("%s: %s\n", file, strerror(errno));
return 0;
}
while(fgets(line, (int)sizeof(line), in)) {
if(strncmp(line, ";;last_success: ", 16) == 0) {
char* e;
time_t x = (unsigned int)strtol(line+16, &e, 10);
fclose(in);
if(line+16 == e) {
if(verb) printf("failed to parse "
"last_success probe time\n");
return 0;
}
if(verb) printf("last successful probe: %s", ctime(&x));
return (int32_t)x;
}
}
fclose(in);
if(verb) printf("no last_success probe time in anchor file\n");
return 0;
}
/**
* Get current time.
* @param debugconf: with override time for tests
*/
static int32_t
get_time_now(char* debugconf)
{
if(debugconf) {
FILE* in = fopen(debugconf, "r");
char line[1024];
if(!in) {
if(verb) printf("%s: %s\n", debugconf, strerror(errno));
return (int32_t)time(NULL);
}
/* must be ^val-override-date: 1234567$ formatted */
while(fgets(line, (int)sizeof(line), in)) {
if(strncmp(line, "val-override-date: ", 19) == 0) {
fclose(in);
return (int32_t)atoi(line+19);
}
}
fclose(in);
}
return (int32_t)time(NULL);
}
/**
* Read autotrust 5011 probe file and see if the date
* compared to the current date allows a certupdate.
* If the last successful probe was recent then 5011 cannot be behind,
* and the failure cannot be solved with a certupdate.
* The debugconf is to validation-override the date for testing.
* @return true if certupdate is ok.
*/
static int
probe_date_allows_certupdate(char* root_anchor_file, char* debugconf)
{
int32_t last_success = read_last_success_time(root_anchor_file);
int32_t now = get_time_now(debugconf);
int32_t leeway = 30 * 24 * 3600; /* 30 days leeway */
/* if the date is before 2010-07-15:00.00.00 then the root has not
* been signed yet, and thus we refuse to take action. */
if(now - 1279144800 < 0) {
if(verb) printf("the date is before the root was first signed,"
" please correct the clock\n");
return 0;
}
if(now - last_success < 0) {
if(verb) printf("the last successful probe is in the future,"
" clock was modified\n");
return 0;
}
if(now - last_success >= leeway) {
if(verb) printf("the last successful probe was more than 30 "
"days ago\n");
return 1;
}
if(verb) printf("the last successful probe is recent\n");
return 0;
}
/** perform the unbound-anchor work */
static int
do_root_update_work(char* root_anchor_file, char* root_cert_file,
char* urlname, char* xmlname, char* p7sname, char* pemname,
char* res_conf, char* root_hints, char* debugconf,
int ip4only, int ip6only, int force)
{
struct ub_ctx* ctx;
struct ub_result* dnskey;
/* see if builtin rootanchor needs to be provided, or if
* rootanchor is 'revoked-trust-point' */
if(!provide_builtin(root_anchor_file))
return 0;
/* make unbound context with 5011-probe for root anchor,
* and probe . DNSKEY */
ctx = create_unbound_context(res_conf, root_hints, debugconf,
ip4only, ip6only);
add_5011_probe_root(ctx, root_anchor_file);
dnskey = prime_root_key(ctx);
ub_ctx_delete(ctx);
/* if secure: exit */
if(dnskey->secure && !force) {
if(verb) printf("success: the anchor is ok\n");
ub_resolve_free(dnskey);
return 0;
}
if(force && verb) printf("debug cert update forced\n");
/* if not (and NOERROR): check date and do certupdate */
if((dnskey->rcode == 0 && probe_date_allows_certupdate(root_anchor_file,
debugconf)) || force)
return do_certupdate(root_anchor_file, root_cert_file,
urlname, xmlname, p7sname, pemname,
res_conf, root_hints, debugconf, ip4only, ip6only,
dnskey);
if(verb) printf("fail: the anchor is NOT ok and could not be fixed\n");
ub_resolve_free(dnskey);
return 0;
}
/** getopt global, in case header files fail to declare it. */
extern int optind;
/** getopt global, in case header files fail to declare it. */
extern char* optarg;
/** Main routine for checkconf */
int main(int argc, char* argv[])
{
int c;
char* root_anchor_file = ROOT_ANCHOR_FILE;
char* root_cert_file = ROOT_CERT_FILE;
char* urlname = URLNAME;
char* xmlname = XMLNAME;
char* p7sname = P7SNAME;
char* pemname = PEMNAME;
char* res_conf = NULL;
char* root_hints = NULL;
char* debugconf = NULL;
int ip4only=0, ip6only=0, force=0;
/* parse the options */
while( (c=getopt(argc, argv, "46C:Fa:c:f:hp:r:s:u:vx:")) != -1) {
switch(c) {
case '4':
ip4only = 1;
break;
case '6':
ip6only = 1;
break;
case 'a':
root_anchor_file = optarg;
break;
case 'c':
root_cert_file = optarg;
break;
case 'u':
urlname = optarg;
break;
case 'x':
xmlname = optarg;
break;
case 's':
p7sname = optarg;
break;
case 'p':
pemname = optarg;
break;
case 'f':
res_conf = optarg;
break;
case 'r':
root_hints = optarg;
break;
case 'C':
debugconf = optarg;
break;
case 'F':
force = 1;
break;
case 'v':
verb++;
break;
case '?':
case 'h':
default:
usage();
}
}
argc -= optind;
argv += optind;
if(argc != 0)
usage();
return do_root_update_work(root_anchor_file, root_cert_file,
urlname, xmlname, p7sname, pemname,
res_conf, root_hints, debugconf, ip4only, ip6only, force);
}

View file

@ -0,0 +1,37 @@
/*
Unbound resource file for windows. For use with windres
*/
#include "winver.h"
#include "config.h"
1 ICON "winrc/combined.ico"
1 VERSIONINFO
FILEVERSION RSRC_PACKAGE_VERSION
PRODUCTVERSION RSRC_PACKAGE_VERSION
FILEFLAGSMASK 0
FILEFLAGS 0
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE 0
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "NLnet Labs"
VALUE "FileDescription", "Unbound Anchor Utility"
VALUE "FileVersion", PACKAGE_VERSION
VALUE "InternalName", "unbound-anchor"
VALUE "OriginalFilename", "unbound-anchor.exe"
VALUE "ProductName", "unbound"
VALUE "ProductVersion", PACKAGE_VERSION
VALUE "LegalCopyright", "(C) 2010 NLnet Labs. Source is BSD licensed."
END
END
BLOCK "VarFileInfo"
BEGIN
/* English(409), windows ANSI codepage (1252) */
VALUE "Translation", 0x409, 0x1252
END
END