diff --git a/CHANGES b/CHANGES index 9de600b7c4..d6c7e56635 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,25 @@ +2989. [func] Added support for writable DLZ zones. (Contributed + by Andrew Tridgell of the Samba project.) [RT #22629] + +2988. [experimental] Added a "dlopen" DLZ driver, allowing the creation + of external DLZ drivers that can be loaded as + shared objects at runtime rather than linked with + named. Currently this is switched on via a + compile-time option, "configure --with-dlz-dlopen". + Note: the syntax for configuring DLZ zones + is likely to be refined in future releases. + (Contributed by Andrew Tridgell of the Samba + project.) [RT #22629] + +2987. [func] Improve ease of configuring TKEY/GSS updates by + adding a "tkey-gssapi-keytab" option. If set, + updates will be allowed with any key matching + a principal in the specified keytab file. + "tkey-gssapi-credential" is no longer required + and is expected to be deprecated. (Contributed + by Andrew Tridgell of the Samba project.) + [RT #22629] + 2986. [func] Add new zone type "static-stub". It's like a stub zone, but the nameserver names and/or their IP addresses are statically configured. [RT #21474] diff --git a/bin/named/include/named/zoneconf.h b/bin/named/include/named/zoneconf.h index b973013c22..6bf2027591 100644 --- a/bin/named/include/named/zoneconf.h +++ b/bin/named/include/named/zoneconf.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.h,v 1.26 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: zoneconf.h,v 1.27 2010/12/18 01:56:19 each Exp $ */ #ifndef NS_ZONECONF_H #define NS_ZONECONF_H 1 @@ -58,6 +58,21 @@ ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig); * and recreated, return ISC_FALSE. */ + +isc_result_t +ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, + dns_rdataclass_t rdclass, dns_name_t *name); +/*%> + * configure a DLZ zone, setting up the database methods and calling + * postload to load the origin values + * + * Require: + * \li 'dlzdatabase' to be a valid dlz database + * \li 'zone' to be initialized. + * \li 'rdclass' to be a valid rdataclass + * \li 'name' to be a valid zone origin name + */ + ISC_LANG_ENDDECLS #endif /* NS_ZONECONF_H */ diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook index 45a5735498..93bfa08f44 100644 --- a/bin/named/named.conf.docbook +++ b/bin/named/named.conf.docbook @@ -17,7 +17,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + Aug 13, 2004 @@ -225,6 +225,7 @@ options { tcp-listen-queue integer; tkey-dhkey quoted_string integer; tkey-gssapi-credential quoted_string; + tkey-gssapi-keytab quoted_string; tkey-domain quoted_string; transfers-per-ns integer; transfers-in integer; diff --git a/bin/named/server.c b/bin/named/server.c index d0f61fa04e..f0aa5d1e24 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.590 2010/12/09 00:54:33 marka Exp $ */ +/* $Id: server.c,v 1.591 2010/12/18 01:56:19 each Exp $ */ /*! \file */ @@ -1290,6 +1290,27 @@ cache_sharable(dns_view_t *originview, dns_view_t *view, return (ISC_TRUE); } +#ifdef DLZ +/* + * Callback from DLZ configure when the driver sets up a writeable zone + */ +static isc_result_t +dlzconfigure_callback(dns_view_t *view, dns_zone_t *zone) { + dns_name_t *origin = dns_zone_getorigin(zone); + dns_rdataclass_t zclass = view->rdclass; + isc_result_t result; + + result = dns_zonemgr_managezone(ns_g_server->zonemgr, zone); + if (result != ISC_R_SUCCESS) + return result; + dns_zone_setstats(zone, ns_g_server->zonestats); + + return ns_zone_configure_writeable_dlz(view->dlzdatabase, + zone, zclass, origin); +} +#endif + + /* * Configure 'view' according to 'vconfig', taking defaults from 'config' * where values are missing in 'vconfig'. @@ -1563,6 +1584,14 @@ configure_view(dns_view_t *view, cfg_parser_t* parser, isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv)); if (result != ISC_R_SUCCESS) goto cleanup; + + /* + * If the dlz backend supports configuration, + * then call its configure method now. + */ + result = dns_dlzconfigure(view, dlzconfigure_callback); + if (result != ISC_R_SUCCESS) + goto cleanup; } } #endif diff --git a/bin/named/tkeyconf.c b/bin/named/tkeyconf.c index e11aaa22d3..b1fbfbd9c4 100644 --- a/bin/named/tkeyconf.c +++ b/bin/named/tkeyconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tkeyconf.c,v 1.31 2009/09/02 23:48:01 tbox Exp $ */ +/* $Id: tkeyconf.c,v 1.32 2010/12/18 01:56:19 each Exp $ */ /*! \file */ @@ -114,6 +114,18 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, &tctx->gsscred)); } + obj = NULL; + result = cfg_map_get(options, "tkey-gssapi-keytab", &obj); + if (result == ISC_R_SUCCESS) { + s = cfg_obj_asstring(obj); + tctx->gssapi_keytab = isc_mem_strdup(mctx, s); + if (tctx->gssapi_keytab == NULL) { + result = ISC_R_NOMEMORY; + goto failure; + } + } + + *tctxp = tctx; return (ISC_R_SUCCESS); diff --git a/bin/named/update.c b/bin/named/update.c index 8124773305..a31a88ae58 100644 --- a/bin/named/update.c +++ b/bin/named/update.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: update.c,v 1.185 2010/12/09 06:17:33 marka Exp $ */ +/* $Id: update.c,v 1.186 2010/12/18 01:56:19 each Exp $ */ #include @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -851,6 +852,9 @@ typedef struct { /* The ssu table to check against. */ dns_ssutable_t *table; + + /* the key used for TKEY requests */ + dst_key_t *key; } ssu_check_t; static isc_result_t @@ -867,14 +871,14 @@ ssu_checkrule(void *data, dns_rdataset_t *rrset) { return (ISC_R_SUCCESS); result = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer, ssuinfo->name, ssuinfo->tcpaddr, - rrset->type); + rrset->type, ssuinfo->key); return (result == ISC_TRUE ? ISC_R_SUCCESS : ISC_R_FAILURE); } static isc_boolean_t ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_ssutable_t *ssutable, dns_name_t *signer, - isc_netaddr_t *tcpaddr) + isc_netaddr_t *tcpaddr, dst_key_t *key) { isc_result_t result; ssu_check_t ssuinfo; @@ -883,6 +887,7 @@ ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, ssuinfo.table = ssutable; ssuinfo.signer = signer; ssuinfo.tcpaddr = tcpaddr; + ssuinfo.key = key; result = foreach_rrset(db, ver, name, ssu_checkrule, &ssuinfo); return (ISC_TF(result == ISC_R_SUCCESS)); } @@ -2719,6 +2724,7 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) { switch(dns_zone_gettype(zone)) { case dns_zone_master: + case dns_zone_dlz: /* * We can now fail due to a bad signature as we now know * that we are the master. @@ -3744,6 +3750,7 @@ update_action(isc_task_t *task, isc_event_t *event) { if (ssutable != NULL) { isc_netaddr_t *tcpaddr, netaddr; + dst_key_t *tsigkey = NULL; /* * If this is a TCP connection then pass the * address of the client through for tcp-self @@ -3756,16 +3763,22 @@ update_action(isc_task_t *task, isc_event_t *event) { tcpaddr = &netaddr; } else tcpaddr = NULL; + + if (client->message->tsigkey != NULL) + tsigkey = client->message->tsigkey->key; + if (rdata.type != dns_rdatatype_any) { if (!dns_ssutable_checkrules(ssutable, client->signer, name, tcpaddr, - rdata.type)) + rdata.type, + tsigkey)) FAILC(DNS_R_REFUSED, "rejected by secure update"); } else { if (!ssu_checkall(db, ver, name, ssutable, - client->signer, tcpaddr)) + client->signer, tcpaddr, + tsigkey)) FAILC(DNS_R_REFUSED, "rejected by secure update"); } diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c index bfce03a49c..d87de5ee3c 100644 --- a/bin/named/xfrout.c +++ b/bin/named/xfrout.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: xfrout.c,v 1.138 2010/05/27 23:51:08 tbox Exp $ */ +/* $Id: xfrout.c,v 1.139 2010/12/18 01:56:19 each Exp $ */ #include @@ -863,6 +863,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { switch(dns_zone_gettype(zone)) { case dns_zone_master: case dns_zone_slave: + case dns_zone_dlz: break; /* Master and slave zones are OK for transfer. */ default: FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 502792b6c8..faf03d43fd 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.c,v 1.167 2010/12/16 23:47:08 tbox Exp $ */ +/* $Id: zoneconf.c,v 1.168 2010/12/18 01:56:19 each Exp $ */ /*% */ @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -1429,6 +1430,31 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, return (ISC_R_SUCCESS); } + +#ifdef DLZ +/* + * Set up a DLZ zone as writeable + */ +isc_result_t +ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, + dns_rdataclass_t rdclass, dns_name_t *name) +{ + dns_db_t *db = NULL; + isc_time_t now; + isc_result_t result; + + TIME_NOW(&now); + + dns_zone_settype(zone, dns_zone_dlz); + result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db); + if (result != ISC_R_SUCCESS) + return result; + result = dns_zone_dlzpostload(zone, db); + dns_db_detach(&db); + return result; +} +#endif + isc_boolean_t ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { const cfg_obj_t *zoptions = NULL; diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 25d1a212e8..01fea441a1 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsupdate.c,v 1.186 2010/12/09 04:31:57 tbox Exp $ */ +/* $Id: nsupdate.c,v 1.187 2010/12/18 01:56:19 each Exp $ */ /*! \file */ @@ -205,7 +205,7 @@ typedef struct nsu_gssinfo { } nsu_gssinfo_t; static void -start_gssrequest(dns_name_t *master); +start_gssrequest(dns_name_t *master, dns_name_t *zone); static void send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, dns_message_t *msg, dns_request_t **request, @@ -2371,7 +2371,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) { dns_name_dup(zonename, mctx, &tmpzonename); dns_name_init(&restart_master, NULL); dns_name_dup(&master, mctx, &restart_master); - start_gssrequest(&master); + start_gssrequest(&master, zonename); } else { send_update(zonename, serveraddr, localaddr); setzoneclass(dns_rdataclass_none); @@ -2432,7 +2432,7 @@ sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, #ifdef GSSAPI static void -start_gssrequest(dns_name_t *master) +start_gssrequest(dns_name_t *master, dns_name_t *zone) { gss_ctx_id_t context; isc_buffer_t buf; @@ -2444,6 +2444,7 @@ start_gssrequest(dns_name_t *master) dns_fixedname_t fname; char namestr[DNS_NAME_FORMATSIZE]; char keystr[DNS_NAME_FORMATSIZE]; + char *err_message = NULL; debug("start_gssrequest"); usevc = ISC_TRUE; @@ -2512,9 +2513,11 @@ start_gssrequest(dns_name_t *master) /* Build first request. */ context = GSS_C_NO_CONTEXT; result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0, - &context, use_win2k_gsstsig); + &context, use_win2k_gsstsig, + zone, mctx, &err_message); if (result == ISC_R_FAILURE) - fatal("Check your Kerberos ticket, it may have expired."); + fatal("tkey query failed: %s", + err_message != NULL ? err_message : "unknown error"); if (result != ISC_R_SUCCESS) fatal("dns_tkey_buildgssquery failed: %s", isc_result_totext(result)); @@ -2563,6 +2566,7 @@ recvgss(isc_task_t *task, isc_event_t *event) { isc_buffer_t buf; dns_name_t *servname; dns_fixedname_t fname; + char *err_message = NULL; UNUSED(task); @@ -2632,7 +2636,7 @@ recvgss(isc_task_t *task, isc_event_t *event) { else use_win2k_gsstsig = ISC_TRUE; tried_other_gsstsig = ISC_TRUE; - start_gssrequest(&restart_master); + start_gssrequest(&restart_master, zonename); goto done; } @@ -2651,7 +2655,8 @@ recvgss(isc_task_t *task, isc_event_t *event) { tsigkey = NULL; result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, &context, &tsigkey, gssring, - use_win2k_gsstsig); + use_win2k_gsstsig, + &tmpzonename, &err_message); switch (result) { case DNS_R_CONTINUE: @@ -2694,7 +2699,9 @@ recvgss(isc_task_t *task, isc_event_t *event) { break; default: - fatal("dns_tkey_negotiategss: %s", isc_result_totext(result)); + fatal("dns_tkey_negotiategss: %s %s", + isc_result_totext(result), + err_message != NULL ? err_message : ""); } done: diff --git a/bin/tests/dst/gsstest.c b/bin/tests/dst/gsstest.c index 6c314d227c..c36058422b 100755 --- a/bin/tests/dst/gsstest.c +++ b/bin/tests/dst/gsstest.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: gsstest.c,v 1.8 2009/09/02 23:48:01 tbox Exp $ */ +/* $Id: gsstest.c,v 1.9 2010/12/18 01:56:19 each Exp $ */ #include @@ -304,7 +304,7 @@ initctx2(isc_task_t *task, isc_event_t *event) { result = dns_tkey_processgssresponse(query, response, dns_fixedname_name(&gssname), &gssctx, &outtoken, - &tsigkey, ring); + &tsigkey, ring, NULL); gssctx = *gssctxp; CHECK("dns_tkey_processgssresponse", result); printf("Context accepted\n"); diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in index 009d9f088d..9116a75bac 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -15,7 +15,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: conf.sh.in,v 1.55 2010/12/16 09:51:27 jinmei Exp $ +# $Id: conf.sh.in,v 1.56 2010/12/18 01:56:19 each Exp $ # # Common configuration data for system tests, to be sourced into @@ -53,10 +53,10 @@ JOURNALPRINT=$TOP/bin/tools/named-journalprint # load on the machine to make it unusable to other users. # v6synth SUBDIRS="acl allow_query addzone autosign cacheclean checkconf checknames - dlv @DLZ_SYSTEM_TEST@ dns64 dnssec forward glue ixfr limits lwresd - masterfile masterformat metadata notify nsupdate pending pkcs11 - resolver rrsetorder sortlist smartsign staticstub stub tkey unknown upforwd - views xfer xferquota zonechecks" + dlv @DLZ_SYSTEM_TEST@ dlzexternal dns64 dnssec forward glue ixfr limits + lwresd masterfile masterformat metadata notify nsupdate pending pkcs11 + resolver rrsetorder sortlist smartsign staticstub stub tkey + tsig tsiggss unknown upforwd views xfer xferquota zonechecks" # PERL will be an empty string if no perl interpreter was found. PERL=@PERL@ diff --git a/bin/tests/system/dlzexternal/clean.sh b/bin/tests/system/dlzexternal/clean.sh new file mode 100644 index 0000000000..07f00e002c --- /dev/null +++ b/bin/tests/system/dlzexternal/clean.sh @@ -0,0 +1,8 @@ +#!/bin/sh +# +# Clean up after dlzexternal tests. +# + +rm -f ns1/update.txt +rm -f */named.memstats +rm -f ns1/ddns.key diff --git a/bin/tests/system/dlzexternal/ns1/named.conf b/bin/tests/system/dlzexternal/ns1/named.conf new file mode 100644 index 0000000000..1cb85eb78d --- /dev/null +++ b/bin/tests/system/dlzexternal/ns1/named.conf @@ -0,0 +1,29 @@ +controls { }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port 5300; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.1; 127.0.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +include "ddns.key"; + +controls { + inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; }; +}; + +dlz "example zone" { + database "dlopen ../../../../../contrib/dlz/example/dlz_example.so example.nil"; +}; diff --git a/bin/tests/system/dlzexternal/prereq.sh b/bin/tests/system/dlzexternal/prereq.sh new file mode 100644 index 0000000000..9791692989 --- /dev/null +++ b/bin/tests/system/dlzexternal/prereq.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +TOP=${SYSTEMTESTTOP:=.}/../../../.. + +# enable the dlzexternal test only if it builds and dlz-dlopen was enabled +$TOP/bin/named/named -V | grep with.dlz.dlopen | grep -v with.dlz.dlopen=no > /dev/null || { + echo "I:not built with --with-dlz-dlopen=yes - skipping dlzexternal test" + exit 1 +} + +cd ../../../../contrib/dlz/example && make all > /dev/null || { + echo "I:build of dlz_example.so failed - skipping dlzexternal test" + exit 1 +} +exit 0 + + diff --git a/bin/tests/system/dlzexternal/setup.sh b/bin/tests/system/dlzexternal/setup.sh new file mode 100644 index 0000000000..edb1b25a1a --- /dev/null +++ b/bin/tests/system/dlzexternal/setup.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +../../../tools/genrandom 400 random.data +$DDNSCONFGEN -q -r random.data -z example.nil > ns1/ddns.key diff --git a/bin/tests/system/dlzexternal/tests.sh b/bin/tests/system/dlzexternal/tests.sh new file mode 100644 index 0000000000..019e37d309 --- /dev/null +++ b/bin/tests/system/dlzexternal/tests.sh @@ -0,0 +1,43 @@ +#!/bin/sh +# tests for TSIG-GSS updates + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +status=0 + +DIGOPTS="@10.53.0.1 -p 5300" + +test_update() { + host="$1" + type="$2" + cmd="$3" + digout="$4" + + cat < ns1/update.txt +server 10.53.0.1 5300 +update add $host $cmd +send +EOF + echo "I:testing update for $host $type $cmd" + $NSUPDATE -k ns1/ddns.key ns1/update.txt || { + echo "I:update failed for $host $type $cmd" + return 1 + } + + out="$($DIG $DIGOPTS -t $type -q $host | egrep ^$host)" + [ $(echo "$out" | grep "$digout" | wc -l) -eq 1 ] || { + echo "I:dig output incorrect for $host $type $cmd: $out" + return 1 + } + return 0 +} + +test_update testdc1.example.nil. A "86400 A 10.53.0.10" "10.53.0.10" || status=1 +test_update testdc2.example.nil. A "86400 A 10.53.0.11" "10.53.0.11" || status=1 +test_update testdc3.example.nil. A "86400 A 10.53.0.10" "10.53.0.10" || status=1 +test_update deny.example.nil. TXT "86400 TXT helloworld" "helloworld" && status=1 + +[ $status -eq 0 ] && echo "I:dlzexternal tests all OK" + +exit $status diff --git a/bin/tests/system/tsiggss/clean.sh b/bin/tests/system/tsiggss/clean.sh new file mode 100644 index 0000000000..aeba6084a5 --- /dev/null +++ b/bin/tests/system/tsiggss/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# +# Clean up after tsiggss tests. +# + +rm -f ns1/*.jnl ns1/update.txt +rm -f */named.memstats diff --git a/bin/tests/system/tsiggss/ns1/administrator.ccache b/bin/tests/system/tsiggss/ns1/administrator.ccache new file mode 100644 index 0000000000..e6c2e74770 Binary files /dev/null and b/bin/tests/system/tsiggss/ns1/administrator.ccache differ diff --git a/bin/tests/system/tsiggss/ns1/dns.keytab b/bin/tests/system/tsiggss/ns1/dns.keytab new file mode 100644 index 0000000000..dcb863b7b2 Binary files /dev/null and b/bin/tests/system/tsiggss/ns1/dns.keytab differ diff --git a/bin/tests/system/tsiggss/ns1/example.nil.zone b/bin/tests/system/tsiggss/ns1/example.nil.zone new file mode 100644 index 0000000000..001bb29837 --- /dev/null +++ b/bin/tests/system/tsiggss/ns1/example.nil.zone @@ -0,0 +1,51 @@ +; -*- zone -*- +; this was generated by a Samba4 provision, and is typical +; of a AD DNS zone +$ORIGIN example.nil. +$TTL 1W +@ IN SOA blu hostmaster ( + 2010113027 ; serial + 2D ; refresh + 4H ; retry + 6W ; expiry + 1W ) ; minimum + IN NS blu + + IN A 10.53.0.1 +; + +blu IN A 10.53.0.1 +gc._msdcs IN A 10.53.0.1 + +fb33eb58-5d58-4100-a114-256e0a97ffc1._msdcs IN CNAME blu +; +; global catalog servers +_gc._tcp IN SRV 0 100 3268 blu +_gc._tcp.Default-First-Site-Name._sites IN SRV 0 100 3268 blu +_ldap._tcp.gc._msdcs IN SRV 0 100 3268 blu +_ldap._tcp.Default-First-Site-Name._sites.gc._msdcs IN SRV 0 100 3268 blu +; +; ldap servers +_ldap._tcp IN SRV 0 100 389 blu +_ldap._tcp.dc._msdcs IN SRV 0 100 389 blu +_ldap._tcp.pdc._msdcs IN SRV 0 100 389 blu +_ldap._tcp.d86745b4-f3e0-4af3-be03-2130d1534be8.domains._msdcs IN SRV 0 100 389 blu +_ldap._tcp.Default-First-Site-Name._sites IN SRV 0 100 389 blu +_ldap._tcp.Default-First-Site-Name._sites.dc._msdcs IN SRV 0 100 389 blu +; +; krb5 servers +_kerberos._tcp IN SRV 0 100 88 blu +_kerberos._tcp.dc._msdcs IN SRV 0 100 88 blu +_kerberos._tcp.Default-First-Site-Name._sites IN SRV 0 100 88 blu +_kerberos._tcp.Default-First-Site-Name._sites.dc._msdcs IN SRV 0 100 88 blu +_kerberos._udp IN SRV 0 100 88 blu +; MIT kpasswd likes to lookup this name on password change +_kerberos-master._tcp IN SRV 0 100 88 blu +_kerberos-master._udp IN SRV 0 100 88 blu +; +; kpasswd +_kpasswd._tcp IN SRV 0 100 464 blu +_kpasswd._udp IN SRV 0 100 464 blu +; +; heimdal 'find realm for host' hack +_kerberos IN TXT EXAMPLE.NIL diff --git a/bin/tests/system/tsiggss/ns1/named.conf b/bin/tests/system/tsiggss/ns1/named.conf new file mode 100644 index 0000000000..c51c46ebbc --- /dev/null +++ b/bin/tests/system/tsiggss/ns1/named.conf @@ -0,0 +1,37 @@ +controls { }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port 5300; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.1; 127.0.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + tkey-gssapi-keytab "dns.keytab"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-md5; +}; + +controls { + inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; }; +}; + +zone "example.nil." IN { + type master; + file "example.nil.zone"; + + update-policy { + grant Administrator@EXAMPLE.NIL wildcard * A AAAA SRV CNAME; + grant testdenied@EXAMPLE.NIL wildcard * TXT; + }; + + /* we need to use check-names ignore so _msdcs A records can be created */ + check-names ignore; +}; diff --git a/bin/tests/system/tsiggss/ns1/testdenied.ccache b/bin/tests/system/tsiggss/ns1/testdenied.ccache new file mode 100644 index 0000000000..070e85b5aa Binary files /dev/null and b/bin/tests/system/tsiggss/ns1/testdenied.ccache differ diff --git a/bin/tests/system/tsiggss/setup.sh b/bin/tests/system/tsiggss/setup.sh new file mode 100644 index 0000000000..11121811a4 --- /dev/null +++ b/bin/tests/system/tsiggss/setup.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +rm -f ns1/*.jnl diff --git a/bin/tests/system/tsiggss/tests.sh b/bin/tests/system/tsiggss/tests.sh new file mode 100644 index 0000000000..1f37578e7a --- /dev/null +++ b/bin/tests/system/tsiggss/tests.sh @@ -0,0 +1,56 @@ +#!/bin/sh +# tests for TSIG-GSS updates + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +status=0 + +DIGOPTS="@10.53.0.1 -p 5300" + +# we don't want a KRB5_CONFIG setting breaking the tests +unset KRB5_CONFIG + +test_update() { + host="$1" + type="$2" + cmd="$3" + digout="$4" + + cat < ns1/update.txt +server 10.53.0.1 5300 +update add $host $cmd +send +EOF + echo "I:testing update for $host $type $cmd" + $NSUPDATE -g ns1/update.txt || { + echo "I:update failed for $host $type $cmd" + return 1 + } + + out="$($DIG $DIGOPTS -t $type -q $host | egrep ^$host)" + [ $(echo "$out" | grep "$digout" | wc -l) -eq 1 ] || { + echo "I:dig output incorrect for $host $type $cmd: $out" + return 1 + } + return 0 +} + +echo "I:testing updates as administrator" +KRB5CCNAME=$(pwd)/ns1/administrator.ccache +export KRB5CCNAME + +test_update testdc1.example.nil. A "86400 A 10.53.0.10" "10.53.0.10" || status=1 +test_update testdc2.example.nil. A "86400 A 10.53.0.11" "10.53.0.11" || status=1 +test_update denied.example.nil. TXT "86400 TXT helloworld" "helloworld" && status=1 + +echo "I:testing updates as a user" +KRB5CCNAME=$(pwd)/ns1/testdenied.ccache +export KRB5CCNAME + +test_update testdenied.example.nil. A "86400 A 10.53.0.12" "10.53.0.12" && status=1 +test_update testdenied.example.nil. TXT "86400 TXT helloworld" "helloworld" || status=1 + +[ $status -eq 0 ] && echo "I:tsiggss tests all OK" + +exit $status diff --git a/config.h.in b/config.h.in index 8ca5e8a2fb..d8f824056e 100644 --- a/config.h.in +++ b/config.h.in @@ -16,7 +16,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.h.in,v 1.136 2010/12/03 00:57:57 marka Exp $ */ +/* $Id: config.h.in,v 1.137 2010/12/18 01:56:17 each Exp $ */ /*! \file */ @@ -193,9 +193,15 @@ int sigwait(const unsigned int *set, int *sig); /* Define to 1 if you have the header file. */ #undef HAVE_GSSAPI_GSSAPI_H +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_KRB5_H + /* Define to 1 if you have the header file. */ #undef HAVE_GSSAPI_H +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_KRB5_H + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H @@ -378,14 +384,10 @@ int sigwait(const unsigned int *set, int *sig); /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif +#if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +#elif ! defined __LITTLE_ENDIAN__ +# undef WORDS_BIGENDIAN #endif /* Define to empty if `const' does not conform to ANSI C. */ diff --git a/configure b/configure index 697fb3ba9f..3fc00d275f 100755 --- a/configure +++ b/configure @@ -14,7 +14,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # -# $Id: configure,v 1.487 2010/12/03 00:57:57 marka Exp $ +# $Id: configure,v 1.488 2010/12/18 01:56:17 each Exp $ # # Portions Copyright (C) 1996-2001 Nominum, Inc. # @@ -31,12 +31,12 @@ # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # From configure.in Revision: 1.504 . # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.67. +# Generated by GNU Autoconf 2.65. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software -# Foundation, Inc. +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. # # # This configure script is free software; the Free Software Foundation @@ -347,7 +347,7 @@ $as_echo X"$as_dir" | test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -387,19 +387,19 @@ else fi # as_fn_arith -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. +# script with status $?, using 1 if that was 0. as_fn_error () { - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi - $as_echo "$as_me: error: $2" >&2 + $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error @@ -715,7 +715,7 @@ test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` @@ -926,6 +926,7 @@ DNS_GSSAPI_LIBS DST_GSSAPI_INC USE_GSSAPI ISC_PLATFORM_KRB5HEADER +ISC_PLATFORM_GSSAPI_KRB5_HEADER ISC_PLATFORM_GSSAPIHEADER ISC_PLATFORM_HAVEGSSAPI PKCS11_PROVIDER @@ -1092,6 +1093,7 @@ with_dlz_filesystem with_dlz_ldap with_dlz_odbc with_dlz_stub +with_dlz_dlopen with_make_clean ' ac_precious_vars='build_alias @@ -1171,9 +1173,8 @@ do fi case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. @@ -1218,7 +1219,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1244,7 +1245,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" + as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1448,7 +1449,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1464,7 +1465,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" + as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1494,8 +1495,8 @@ do | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; - -*) as_fn_error $? "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information" + -*) as_fn_error "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information." ;; *=*) @@ -1503,7 +1504,7 @@ Try \`$0 --help' for more information" # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; @@ -1521,13 +1522,13 @@ done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" + as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1550,7 +1551,7 @@ do [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" + as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' @@ -1564,8 +1565,8 @@ target=$target_alias if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used" >&2 + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -1580,9 +1581,9 @@ test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" + as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" + as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. @@ -1621,11 +1622,11 @@ else fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" + as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then @@ -1665,7 +1666,7 @@ Configuration: --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking ...' messages + -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files @@ -1796,6 +1797,8 @@ Optional Packages: (Required to use ODBC with DLZ) --with-dlz-stub=PATH Build with stub DLZ driver yes|no. (Required to use stub driver with DLZ) + --with-dlz-dlopen=PATH Build with dlopen DLZ driver yes|no. + (Required to use dlopen driver with DLZ) --with-make-clean Run "make clean" at end of configure [yes|no]. Some influential environment variables: @@ -1880,9 +1883,9 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure -generated by GNU Autoconf 2.67 +generated by GNU Autoconf 2.65 -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -1998,7 +2001,7 @@ $as_echo "$ac_try_echo"; } >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { + test $ac_status = 0; } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : @@ -2022,10 +2025,10 @@ fi ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval "test \"\${$3+set}\"" = set; then : + if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 @@ -2061,7 +2064,7 @@ if ac_fn_c_try_cpp "$LINENO"; then : else ac_header_preproc=no fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } @@ -2088,7 +2091,7 @@ $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" @@ -2152,7 +2155,7 @@ ac_fn_c_check_header_compile () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2182,7 +2185,7 @@ ac_fn_c_check_func () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -2300,7 +2303,7 @@ $as_echo "$ac_try_echo"; } >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { + test $ac_status = 0; } >/dev/null && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : @@ -2455,7 +2458,7 @@ ac_fn_c_check_type () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if eval "test \"\${$3+set}\"" = set; then : +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=no" @@ -2504,7 +2507,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ @@ -2614,9 +2617,11 @@ trap 'exit_status=$? { echo - $as_echo "## ---------------- ## + cat <<\_ASBOX +## ---------------- ## ## Cache variables. ## -## ---------------- ##" +## ---------------- ## +_ASBOX echo # The following way of writing the cache mishandles newlines in values, ( @@ -2650,9 +2655,11 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; ) echo - $as_echo "## ----------------- ## + cat <<\_ASBOX +## ----------------- ## ## Output variables. ## -## ----------------- ##" +## ----------------- ## +_ASBOX echo for ac_var in $ac_subst_vars do @@ -2665,9 +2672,11 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; echo if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## + cat <<\_ASBOX +## ------------------- ## ## File substitutions. ## -## ------------------- ##" +## ------------------- ## +_ASBOX echo for ac_var in $ac_subst_files do @@ -2681,9 +2690,11 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; fi if test -s confdefs.h; then - $as_echo "## ----------- ## + cat <<\_ASBOX +## ----------- ## ## confdefs.h. ## -## ----------- ##" +## ----------- ## +_ASBOX echo cat confdefs.h echo @@ -2738,12 +2749,7 @@ _ACEOF ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac + ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site @@ -2758,11 +2764,7 @@ do { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5; } + . "$ac_site_file" fi done @@ -2838,7 +2840,7 @@ if $ac_cache_corrupted; then $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 + as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## @@ -2858,22 +2860,16 @@ ac_config_headers="$ac_config_headers config.h" ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi + for ac_t in install-sh install.sh shtool; do + if test -f "$ac_dir/$ac_t"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/$ac_t -c" + break 2 + fi + done done if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 + as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, @@ -2887,7 +2883,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } @@ -2898,16 +2894,16 @@ else test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && - as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 + as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +*) as_fn_error "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' @@ -2932,7 +2928,7 @@ else ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 + as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi @@ -2940,7 +2936,7 @@ fi $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +*) as_fn_error "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' @@ -2961,7 +2957,7 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\"" = set; then : +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF @@ -2969,7 +2965,7 @@ SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF -# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; @@ -3373,8 +3369,8 @@ fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } +as_fn_error "no acceptable C compiler found in \$PATH +See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 @@ -3488,8 +3484,9 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5; } +{ as_fn_set_status 77 +as_fn_error "C compiler cannot create executables +See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -3531,8 +3528,8 @@ done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5; } +as_fn_error "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 @@ -3589,9 +3586,9 @@ $as_echo "$ac_try_echo"; } >&5 else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run C compiled programs. +as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5; } +See \`config.log' for more details." "$LINENO" 5; } fi fi fi @@ -3642,8 +3639,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5; } +as_fn_error "cannot compute suffix of object files: cannot compile +See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi @@ -3973,7 +3970,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then - as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP @@ -4039,7 +4036,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then - as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP @@ -4136,7 +4133,7 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi -test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if test "${lt_cv_prog_gnu_ld+set}" = set; then : @@ -4482,7 +4479,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 4485 "configure"' > conftest.$ac_ext + echo '#line 4482 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -4689,7 +4686,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4705,11 +4702,11 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi @@ -4748,7 +4745,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4764,18 +4761,18 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } +as_fn_error "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." "$LINENO" 5; } fi ac_ext=c @@ -4904,7 +4901,8 @@ 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 " -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -5226,7 +5224,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -5242,11 +5240,11 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi @@ -5285,7 +5283,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -5301,18 +5299,18 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.i conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } +as_fn_error "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." "$LINENO" 5; } fi ac_ext=cpp @@ -5329,7 +5327,7 @@ ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu if test -n "$ac_tool_prefix"; then - for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn + for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 @@ -5373,7 +5371,7 @@ fi fi if test -z "$F77"; then ac_ct_F77=$F77 - for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn + for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -6776,11 +6774,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6779: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6777: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:6783: \$? = $ac_status" >&5 + echo "$as_me:6781: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7066,11 +7064,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7069: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7067: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7073: \$? = $ac_status" >&5 + echo "$as_me:7071: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7170,11 +7168,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7173: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7171: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7177: \$? = $ac_status" >&5 + echo "$as_me:7175: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -9195,7 +9193,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&2;} # Check whether tagname contains only valid characters case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in "") ;; - *) as_fn_error $? "invalid tag name: $tagname" "$LINENO" 5 + *) as_fn_error "invalid tag name: $tagname" "$LINENO" 5 ;; esac if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null then - as_fn_error $? "tag name \"$tagname\" already exists" "$LINENO" 5 + as_fn_error "tag name \"$tagname\" already exists" "$LINENO" 5 fi # Update the list of available tags. @@ -10191,7 +10189,7 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi -test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if test "${lt_cv_prog_gnu_ld+set}" = set; then : @@ -11640,11 +11638,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:11643: $lt_compile\"" >&5) + (eval echo "\"\$as_me:11641: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:11647: \$? = $ac_status" >&5 + echo "$as_me:11645: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -11744,11 +11742,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:11747: $lt_compile\"" >&5) + (eval echo "\"\$as_me:11745: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:11751: \$? = $ac_status" >&5 + echo "$as_me:11749: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -13327,11 +13325,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13330: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13328: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:13334: \$? = $ac_status" >&5 + echo "$as_me:13332: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -13431,11 +13429,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13434: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13432: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:13438: \$? = $ac_status" >&5 + echo "$as_me:13436: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -15596,11 +15594,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15599: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15597: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:15603: \$? = $ac_status" >&5 + echo "$as_me:15601: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -15886,11 +15884,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15889: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15887: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:15893: \$? = $ac_status" >&5 + echo "$as_me:15891: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -15990,11 +15988,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15993: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15991: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:15997: \$? = $ac_status" >&5 + echo "$as_me:15995: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -18558,7 +18556,7 @@ CC="$lt_save_CC" ;; *) - as_fn_error $? "Unsupported tag name: $tagname" "$LINENO" 5 + as_fn_error "Unsupported tag name: $tagname" "$LINENO" 5 ;; esac @@ -18576,7 +18574,7 @@ CC="$lt_save_CC" chmod +x "$ofile" else rm -f "${ofile}T" - as_fn_error $? "unable to update list of available tagged configurations." "$LINENO" 5 + as_fn_error "unable to update list of available tagged configurations." "$LINENO" 5 fi fi @@ -18728,7 +18726,7 @@ fi case "$enable_libbind" in yes) - as_fn_error $? "'libbind' is no longer part of the BIND 9 distribution. + as_fn_error "'libbind' is no longer part of the BIND 9 distribution. It is available from http://www.isc.org as a separate download." "$LINENO" 5 ;; no|'') @@ -18794,7 +18792,7 @@ LN=ln case "$AR" in "") - as_fn_error $? " + as_fn_error " ar program not found. Please fix your PATH to include the directory in which ar resides, or set AR in the environment with the full path to ar. " "$LINENO" 5 @@ -19328,8 +19326,8 @@ fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } +as_fn_error "no acceptable C compiler found in \$PATH +See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 @@ -19734,7 +19732,8 @@ ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_include #endif " -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -19956,7 +19955,8 @@ for ac_func in seteuid setresuid do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF @@ -19968,7 +19968,8 @@ for ac_func in setegid setresgid do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF @@ -20264,8 +20265,8 @@ $as_echo_n "checking epoll support... " >&6; } if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run test program while cross compiling -See \`config.log' for more details" "$LINENO" 5; } +as_fn_error "cannot run test program while cross compiling +See \`config.log' for more details." "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20317,7 +20318,8 @@ yes) do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -20371,7 +20373,7 @@ $as_echo "no" >&6; } LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1" ;; no) - as_fn_error $? "need either working unistd.h or sys/select.h" "$LINENO" 5 + as_fn_error "need either working unistd.h or sys/select.h" "$LINENO" 5 ;; esac @@ -20385,7 +20387,7 @@ no) LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1" ;; no) - as_fn_error $? "need either unistd.h or sys/select.h" "$LINENO" 5 + as_fn_error "need either unistd.h or sys/select.h" "$LINENO" 5 ;; esac ;; @@ -20616,7 +20618,7 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) - as_fn_error $? "unknown endianness + as_fn_error "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac @@ -20663,7 +20665,7 @@ $as_echo "no" >&6; } USE_OPENSSL="" OPENSSLLINKOBJS="" OPENSSLLINKSRCS="" - as_fn_error $? "OpenSSL was not found in any of $openssldirs; use --with-openssl=/path + as_fn_error "OpenSSL was not found in any of $openssldirs; use --with-openssl=/path If you don't want OpenSSL, use --without-openssl" "$LINENO" 5 ;; *) @@ -20682,11 +20684,11 @@ If you don't want OpenSSL, use --without-openssl" "$LINENO" 5 then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - as_fn_error $? "OpenSSL was not found in any of $openssldirs; use --with-openssl=/path" "$LINENO" 5 + as_fn_error "OpenSSL was not found in any of $openssldirs; use --with-openssl=/path" "$LINENO" 5 fi elif ! test -f "$use_openssl"/include/openssl/opensslv.h then - as_fn_error $? "\"$use_openssl/include/openssl/opensslv.h\" not found" "$LINENO" 5 + as_fn_error "\"$use_openssl/include/openssl/opensslv.h\" not found" "$LINENO" 5 fi USE_OPENSSL='-DOPENSSL' if test "$use_openssl" = "/usr" @@ -20751,7 +20753,7 @@ $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - as_fn_error $? "Could not run test program using OpenSSL from + as_fn_error "Could not run test program using OpenSSL from $use_openssl/lib and $use_openssl/include. Please check the argument to --with-openssl and your shared library configuration (e.g., LD_LIBRARY_PATH)." "$LINENO" 5 @@ -20801,7 +20803,7 @@ $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5 $as_echo "unknown" >&6; } - as_fn_error $? "OpenSSL has unsupported dynamic loading" "$LINENO" 5 + as_fn_error "OpenSSL has unsupported dynamic loading" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext @@ -20877,7 +20879,8 @@ $as_echo "no" >&6; } do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF @@ -20919,7 +20922,7 @@ case $want_openssl_hash in yes) if test "$USE_OPENSSL" = "" then - as_fn_error $? "No OpenSSL for hash functions" "$LINENO" 5 + as_fn_error "No OpenSSL for hash functions" "$LINENO" 5 fi ISC_PLATFORM_OPENSSLHASH="#define ISC_PLATFORM_OPENSSLHASH 1" ISC_OPENSSL_INC="$DST_OPENSSL_INC" @@ -21013,7 +21016,7 @@ $as_echo "disabled" >&6; } USE_GSSAPI='' ;; yes) - as_fn_error $? "--with-gssapi must specify a path" "$LINENO" 5 + as_fn_error "--with-gssapi must specify a path" "$LINENO" 5 ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: looking in $use_gssapi/lib" >&5 @@ -21025,7 +21028,8 @@ $as_echo "looking in $use_gssapi/lib" >&6; } do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -21036,14 +21040,34 @@ done if test "$ISC_PLATFORM_GSSAPIHEADER" = ""; then - as_fn_error $? "gssapi.h not found" "$LINENO" 5 + as_fn_error "gssapi.h not found" "$LINENO" 5 + fi + + for ac_header in gssapi_krb5.h gssapi/gssapi_krb5.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + ISC_PLATFORM_GSSAPI_KRB5_HEADER="#define ISC_PLATFORM_GSSAPI_KRB5_HEADER <$ac_header>" +fi + +done + + + if test "$ISC_PLATFORM_GSSAPI_KRB5_HEADER" = ""; then + as_fn_error "gssapi_krb5.h not found" "$LINENO" 5 fi for ac_header in krb5.h krb5/krb5.h kerberosv5/krb5.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -21054,7 +21078,7 @@ done if test "$ISC_PLATFORM_KRB5HEADER" = ""; then - as_fn_error $? "krb5.h not found" "$LINENO" 5 + as_fn_error "krb5.h not found" "$LINENO" 5 fi CPPFLAGS="$saved_cppflags" @@ -21124,7 +21148,7 @@ $as_echo "no" >&6; } ;; done case $gssapi_linked in - no) as_fn_error $? "could not determine proper GSSAPI linkage" "$LINENO" 5 ;; + no) as_fn_error "could not determine proper GSSAPI linkage" "$LINENO" 5 ;; esac # @@ -21159,7 +21183,7 @@ $as_echo "no" >&6; } ;; NEW_LIBS="$NEW_LIBS $new_lib" ;; *) - as_fn_error $? "KTH vs MIT Kerberos confusion!" "$LINENO" 5 + as_fn_error "KTH vs MIT Kerberos confusion!" "$LINENO" 5 ;; esac done @@ -21183,6 +21207,7 @@ esac + DNS_CRYPTO_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_LIBS" # @@ -21220,11 +21245,11 @@ $as_echo "$devrandom" >&6; } as_ac_File=`$as_echo "ac_cv_file_$devrandom" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $devrandom" >&5 $as_echo_n "checking for $devrandom... " >&6; } -if eval "test \"\${$as_ac_File+set}\"" = set; then : +if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 + as_fn_error "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "$devrandom"; then eval "$as_ac_File=yes" else @@ -21234,7 +21259,8 @@ fi eval ac_res=\$$as_ac_File { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_File"\" = x"yes"; then : +eval as_val=\$$as_ac_File + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define PATH_RANDOMDEV "$devrandom" _ACEOF @@ -21243,7 +21269,7 @@ fi ;; yes) - as_fn_error $? "--with-randomdev must specify a path" "$LINENO" 5 + as_fn_error "--with-randomdev must specify a path" "$LINENO" 5 ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 @@ -21350,7 +21376,7 @@ case "$enable_threads" in # Use system-dependent default ;; *) - as_fn_error $? "--enable-threads takes yes or no" "$LINENO" 5 + as_fn_error "--enable-threads takes yes or no" "$LINENO" 5 ;; esac @@ -21410,7 +21436,7 @@ $as_echo "native" >&6; } then { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } - as_fn_error $? "\"could not find thread libraries\"" "$LINENO" 5 + as_fn_error "\"could not find thread libraries\"" "$LINENO" 5 fi if $use_threads @@ -21638,7 +21664,7 @@ _ACEOF LIBS="-lc $LIBS" else - as_fn_error $? "\"could not find thread libraries\"" "$LINENO" 5 + as_fn_error "\"could not find thread libraries\"" "$LINENO" 5 fi fi @@ -21870,7 +21896,7 @@ _ACEOF LIBS="-lc $LIBS" else - as_fn_error $? "\"could not find thread libraries\"" "$LINENO" 5 + as_fn_error "\"could not find thread libraries\"" "$LINENO" 5 fi fi @@ -22666,7 +22692,7 @@ $as_echo "$purify_path" >&6; } PURIFYFLAGS="`echo $PURIFYOPTIONS`" PURIFY="$purify_path $PURIFYFLAGS" else - as_fn_error $? "$purify_path not found. + as_fn_error "$purify_path not found. Please choose the proper path with the following command: @@ -22769,7 +22795,7 @@ case $want_symtable in yes|all|minimal) # "yes" is a hidden value equivalent to "minimal" if test "$PERL" = "" then - as_fn_error $? "Internal symbol table requires perl but no perl is found. + as_fn_error "Internal symbol table requires perl but no perl is found. Install perl or explicitly disable the feature by --disable-symtable." "$LINENO" 5 fi if test "$use_libtool" = "yes"; then @@ -22836,7 +22862,7 @@ case "$enable_exportlib" in fi done if test -z "$gmake"; then - as_fn_error $? "exportlib requires GNU make. Install it or disable the feature." "$LINENO" 5 + as_fn_error "exportlib requires GNU make. Install it or disable the feature." "$LINENO" 5 fi LIBEXPORT=lib/export @@ -22961,7 +22987,7 @@ $as_echo "no" >&6; } $as_echo "$kame_path/lib/libinet6.a" >&6; } LIBS="-L$kame_path/lib -linet6 $LIBS" else - as_fn_error $? "$kame_path/lib/libinet6.a not found. + as_fn_error "$kame_path/lib/libinet6.a not found. Please choose the proper path with the following command: @@ -24173,7 +24199,8 @@ case "$enable_linux_caps" in do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -24363,7 +24390,7 @@ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE int" else if test "$cross_compiling" = yes; then : - as_fn_error $? "this cannot happen" "$LINENO" 5 + as_fn_error "this cannot happen" "$LINENO" 5 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -24380,7 +24407,7 @@ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long int" else if test "$cross_compiling" = yes; then : - as_fn_error $? "this cannot happen" "$LINENO" 5 + as_fn_error "this cannot happen" "$LINENO" 5 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -24395,7 +24422,7 @@ if ac_fn_c_try_run "$LINENO"; then : $as_echo "long long int" >&6; } ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long long int" else - as_fn_error $? "unable to determine sizeof rlim_cur" "$LINENO" 5 + as_fn_error "unable to determine sizeof rlim_cur" "$LINENO" 5 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -25780,7 +25807,7 @@ else fi if test "$idnlib" = yes; then - as_fn_error $? "You must specify ARG for --with-idnlib." "$LINENO" 5 + as_fn_error "You must specify ARG for --with-idnlib." "$LINENO" 5 fi IDNLIBS= @@ -26042,7 +26069,7 @@ then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - as_fn_error $? "No pg_config and PostgreSQL was not found in any of $pgdirs; use --with-dlz-postgres=/path or put pg_config in your path" "$LINENO" 5 + as_fn_error "No pg_config and PostgreSQL was not found in any of $pgdirs; use --with-dlz-postgres=/path or put pg_config in your path" "$LINENO" 5 fi case "$use_dlz_postgres" in @@ -26149,7 +26176,7 @@ if test "$use_dlz_mysql" = "yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - as_fn_error $? "MySQL was not found in any of $mysqldirs; use --with-dlz-mysql=/path" "$LINENO" 5 + as_fn_error "MySQL was not found in any of $mysqldirs; use --with-dlz-mysql=/path" "$LINENO" 5 fi case "$use_dlz_mysql" in @@ -26213,7 +26240,7 @@ $as_echo "no" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - as_fn_error $? "path $use_dlz_bdb does not exist" "$LINENO" 5 + as_fn_error "path $use_dlz_bdb does not exist" "$LINENO" 5 bdbdirs="" fi @@ -26292,14 +26319,14 @@ $as_echo "not found" >&6; } then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - as_fn_error $? "could not find Berkeley DB include directory" "$LINENO" 5 + as_fn_error "could not find Berkeley DB include directory" "$LINENO" 5 fi if test "$dlz_bdb_libs" = "yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - as_fn_error $? "could not find Berkeley DB library" "$LINENO" 5 + as_fn_error "could not find Berkeley DB library" "$LINENO" 5 fi @@ -26405,7 +26432,7 @@ if test "$use_dlz_ldap" = "yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - as_fn_error $? "LDAP headers were not found in any of $ldapdirs; use --with-dlz-ldap=/path" "$LINENO" 5 + as_fn_error "LDAP headers were not found in any of $ldapdirs; use --with-dlz-ldap=/path" "$LINENO" 5 fi case "$use_dlz_ldap" in @@ -26474,7 +26501,7 @@ $as_echo "no" >&6; } yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - as_fn_error $? "ODBC headers were not found in any of $odbcdirs; use --with-dlz-odbc=/path" "$LINENO" 5 + as_fn_error "ODBC headers were not found in any of $odbcdirs; use --with-dlz-odbc=/path" "$LINENO" 5 ;; *) @@ -26544,6 +26571,107 @@ $as_echo "yes" >&6; } ;; esac +# +# Was --with-dlz-dlopen specified? +# + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen DLZ driver" >&5 +$as_echo_n "checking for dlopen DLZ driver... " >&6; } + +# Check whether --with-dlz_dlopen was given. +if test "${with_dlz_dlopen+set}" = set; then : + withval=$with_dlz_dlopen; use_dlz_dlopen="$withval" +else + use_dlz_dlopen="no" +fi + + +case "$use_dlz_dlopen" in + no) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlclose in -ldl" >&5 +$as_echo_n "checking for dlclose in -ldl... " >&6; } +if test "${ac_cv_lib_dl_dlclose+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlclose (); +int +main () +{ +return dlclose (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlclose=yes +else + ac_cv_lib_dl_dlclose=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlclose" >&5 +$as_echo "$ac_cv_lib_dl_dlclose" >&6; } +if test "x$ac_cv_lib_dl_dlclose" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBS="-ldl $LIBS" + +fi + + for ac_func in dlopen dlclose dlsym +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + USE_DLZ="$USE_DLZ -DDLZ_DLOPEN" + for i in dlz_dlopen_driver + do + DLZ_DRIVER_SRCS="$DLZ_DRIVER_SRCS $dlzdir/$i.c" + DLZ_DRIVER_OBJS="$DLZ_DRIVER_OBJS $i.$O" + done + if test -n "" + then + DLZ_DRIVER_INCLUDES="$DLZ_DRIVER_INCLUDES " + fi + if test -n "" + then + DLZ_DRIVER_LIBS="$DLZ_DRIVER_LIBS " + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ;; +esac + # Add any additional DLZ drivers here. @@ -26593,7 +26721,7 @@ fi if test "$cross_compiling" = "yes"; then if test -z "$BUILD_CC"; then - as_fn_error $? "BUILD_CC not set" "$LINENO" 5 + as_fn_error "BUILD_CC not set" "$LINENO" 5 fi BUILD_CFLAGS="$BUILD_CFLAGS" BUILD_CPPFLAGS="$BUILD_CPPFLAGS" @@ -26805,7 +26933,6 @@ DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= -U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' @@ -26968,19 +27095,19 @@ export LANGUAGE (unset CDPATH) >/dev/null 2>&1 && unset CDPATH -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. +# script with status $?, using 1 if that was 0. as_fn_error () { - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi - $as_echo "$as_me: error: $2" >&2 + $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error @@ -27176,7 +27303,7 @@ $as_echo X"$as_dir" | test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -27230,7 +27357,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # values after options handling. ac_log=" This file was extended by $as_me, which was -generated by GNU Autoconf 2.67. Invocation command line was +generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -27296,10 +27423,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.67, +configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" -Copyright (C) 2010 Free Software Foundation, Inc. +Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -27315,16 +27442,11 @@ ac_need_defaults=: while test $# != 0 do case $1 in - --*=?*) + --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; *) ac_option=$1 ac_optarg=$2 @@ -27346,7 +27468,6 @@ do $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; @@ -27359,7 +27480,7 @@ do ac_need_defaults=false;; --he | --h) # Conflict between --help and --header - as_fn_error $? "ambiguous option: \`$1' + as_fn_error "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; @@ -27368,7 +27489,7 @@ Try \`$0 --help' for more information.";; ac_cs_silent=: ;; # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' + -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" @@ -27539,7 +27660,7 @@ do "doc/doxygen/Makefile") CONFIG_FILES="$CONFIG_FILES doc/doxygen/Makefile" ;; "doc/doxygen/doxygen-input-filter") CONFIG_FILES="$CONFIG_FILES doc/doxygen/doxygen-input-filter" ;; - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -27577,7 +27698,7 @@ $debug || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -27611,7 +27732,7 @@ if test "x$ac_cr" = x; then fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' + ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi @@ -27628,7 +27749,7 @@ _ACEOF echo "_ACEOF" } >conf$$files.sh && . ./conf$$files.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 rm -f conf$$files.sh { @@ -27636,18 +27757,18 @@ rm -f conf$$files.sh echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -27742,28 +27863,20 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 + || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// s/^[^=]*=[ ]*$// }' fi @@ -27791,7 +27904,7 @@ for ac_last_try in false false :; do if test -z "$ac_t"; then break elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -27876,7 +27989,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 + as_fn_error "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" @@ -27889,7 +28002,7 @@ do esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -27917,7 +28030,7 @@ do [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -27944,7 +28057,7 @@ $as_echo "$as_me: creating $ac_file" >&6;} case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -28080,22 +28193,22 @@ if $ac_cs_awk_getline; then else $AWK -f "$tmp/subs.awk" | $SHELL fi >$tmp/out \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 +which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} +which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; :H) # @@ -28106,19 +28219,19 @@ which seems to be undefined. Please make sure it is defined" >&2;} $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" } >"$tmp/config.h" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$tmp/config.h" "$ac_file" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + || as_fn_error "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ - || as_fn_error $? "could not create -" "$LINENO" 5 + || as_fn_error "could not create -" "$LINENO" 5 fi ;; @@ -28140,7 +28253,7 @@ _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. @@ -28161,7 +28274,7 @@ if test "$no_create" != yes; then exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 + $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 diff --git a/configure.in b/configure.in index 1c136dc321..090acdb225 100644 --- a/configure.in +++ b/configure.in @@ -18,7 +18,7 @@ AC_DIVERT_PUSH(1)dnl esyscmd([sed "s/^/# /" COPYRIGHT])dnl AC_DIVERT_POP()dnl -AC_REVISION($Revision: 1.504 $) +AC_REVISION($Revision: 1.505 $) AC_INIT(lib/dns/name.c) AC_PREREQ(2.59) @@ -793,6 +793,13 @@ case "$use_gssapi" in AC_MSG_ERROR([gssapi.h not found]) fi + AC_CHECK_HEADERS(gssapi_krb5.h gssapi/gssapi_krb5.h, + [ISC_PLATFORM_GSSAPI_KRB5_HEADER="#define ISC_PLATFORM_GSSAPI_KRB5_HEADER <$ac_header>"]) + + if test "$ISC_PLATFORM_GSSAPI_KRB5_HEADER" = ""; then + AC_MSG_ERROR([gssapi_krb5.h not found]) + fi + AC_CHECK_HEADERS(krb5.h krb5/krb5.h kerberosv5/krb5.h, [ISC_PLATFORM_KRB5HEADER="#define ISC_PLATFORM_KRB5HEADER <$ac_header>"]) @@ -901,6 +908,7 @@ esac AC_SUBST(ISC_PLATFORM_HAVEGSSAPI) AC_SUBST(ISC_PLATFORM_GSSAPIHEADER) +AC_SUBST(ISC_PLATFORM_GSSAPI_KRB5_HEADER) AC_SUBST(ISC_PLATFORM_KRB5HEADER) AC_SUBST(USE_GSSAPI) diff --git a/contrib/dlz/config.dlz.in b/contrib/dlz/config.dlz.in index ff3783ad66..a49e40b39b 100644 --- a/contrib/dlz/config.dlz.in +++ b/contrib/dlz/config.dlz.in @@ -456,6 +456,29 @@ case "$use_dlz_stub" in ;; esac +# +# Was --with-dlz-dlopen specified? +# + +AC_MSG_CHECKING(for dlopen DLZ driver) +AC_ARG_WITH(dlz_dlopen, +[ --with-dlz-dlopen[=PATH] Build with dlopen DLZ driver [yes|no]. + (Required to use dlopen driver with DLZ)], + use_dlz_dlopen="$withval", use_dlz_dlopen="no") + +case "$use_dlz_dlopen" in + no) + AC_MSG_RESULT(no) + ;; + *) + AC_CHECK_LIB(dl, dlclose) + AC_CHECK_FUNCS(dlopen dlclose dlsym) + DLZ_ADD_DRIVER(DLOPEN, dlz_dlopen_driver) + + AC_MSG_RESULT(yes) + ;; +esac + # Add any additional DLZ drivers here. diff --git a/contrib/dlz/drivers/dlz_bdb_driver.c b/contrib/dlz/drivers/dlz_bdb_driver.c index ebbb6dda34..a4d7a9d7ba 100644 --- a/contrib/dlz/drivers/dlz_bdb_driver.c +++ b/contrib/dlz/drivers/dlz_bdb_driver.c @@ -742,7 +742,14 @@ static dns_sdlzmethods_t dlz_bdb_methods = { bdb_lookup, NULL, bdb_allnodes, - bdb_allowzonexfr + bdb_allowzonexfr, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; /*% diff --git a/contrib/dlz/drivers/dlz_bdbhpt_driver.c b/contrib/dlz/drivers/dlz_bdbhpt_driver.c index 3a170d6fb1..25d78d7e68 100644 --- a/contrib/dlz/drivers/dlz_bdbhpt_driver.c +++ b/contrib/dlz/drivers/dlz_bdbhpt_driver.c @@ -807,7 +807,14 @@ static dns_sdlzmethods_t dlz_bdbhpt_methods = { bdbhpt_lookup, NULL, bdbhpt_allnodes, - bdbhpt_allowzonexfr + bdbhpt_allowzonexfr, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; /*% diff --git a/contrib/dlz/drivers/dlz_dlopen_driver.c b/contrib/dlz/drivers/dlz_dlopen_driver.c new file mode 100644 index 0000000000..e70601584b --- /dev/null +++ b/contrib/dlz/drivers/dlz_dlopen_driver.c @@ -0,0 +1,624 @@ +/* + * Copyright (C) 2010 Andrew Tridgell + * + * based on dlz_stub_driver.c + * which is: + * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl. + * Copyright (C) 1999-2001 Internet Software Consortium. + * see dlz_stub_driver.c for details + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE + * USE OR PERFORMANCE OF THIS SOFTWARE. + * + * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was + * conceived and contributed by Rob Butler. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE + * USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef DLZ_DLOPEN + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +static dns_sdlzimplementation_t *dlz_dlopen = NULL; + + +typedef struct dlopen_data { + isc_mem_t *mctx; + char *dl_path; + char *dlzname; + void *dl_handle; + void *dbdata; + unsigned int flags; + isc_mutex_t lock; + int version; + isc_boolean_t in_configure; + + int (*dlz_version)(unsigned int *flags); + isc_result_t (*dlz_create)(const char *dlzname, + unsigned int argc, char *argv[], + void **dbdata, ...); + isc_result_t (*dlz_findzonedb)(void *dbdata, const char *name); + isc_result_t (*dlz_lookup)(const char *zone, const char *name, + void *dbdata, dns_sdlzlookup_t *lookup); + isc_result_t (*dlz_authority)(const char *zone, void *dbdata, + dns_sdlzlookup_t *lookup); + isc_result_t (*dlz_allnodes)(const char *zone, void *dbdata, + dns_sdlzallnodes_t *allnodes); + isc_result_t (*dlz_allowzonexfr)(void *dbdata, const char *name, + const char *client); + isc_result_t (*dlz_newversion)(const char *zone, void *dbdata, + void **versionp); + void (*dlz_closeversion)(const char *zone, isc_boolean_t commit, + void *dbdata, void **versionp); + isc_result_t (*dlz_configure)(dns_view_t *view, void *dbdata); + isc_boolean_t (*dlz_ssumatch)(const char *signer, const char *name, + const char *tcpaddr, const char *type, + const char *key, uint32_t keydatalen, + uint8_t *keydata, void *dbdata); + isc_result_t (*dlz_addrdataset)(const char *name, const char *rdatastr, + void *dbdata, void *version); + isc_result_t (*dlz_subrdataset)(const char *name, const char *rdatastr, + void *dbdata, void *version); + isc_result_t (*dlz_delrdataset)(const char *name, const char *type, + void *dbdata, void *version); + void (*dlz_destroy)(void *dbdata); +} dlopen_data_t; + +/* Modules can choose whether they are lock-safe or not. */ +#define MAYBE_LOCK(cd) \ + do { \ + if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ + cd->in_configure == ISC_FALSE) \ + LOCK(&cd->lock); \ + } while (0) + +#define MAYBE_UNLOCK(cd) \ + do { \ + if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ + cd->in_configure == ISC_FALSE) \ + UNLOCK(&cd->lock); \ + } while (0) + +/* + * Log a message at the given level. + */ +static void dlopen_log(int level, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level), + fmt, ap); + va_end(ap); +} + +/* + * SDLZ methods + */ + +static isc_result_t +dlopen_dlz_allnodes(const char *zone, void *driverarg, void *dbdata, + dns_sdlzallnodes_t *allnodes) +{ + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_result_t result; + + + UNUSED(driverarg); + + if (cd->dlz_allnodes == NULL) { + return (ISC_R_NOPERM); + } + + MAYBE_LOCK(cd); + result = cd->dlz_allnodes(zone, cd->dbdata, allnodes); + MAYBE_UNLOCK(cd); + return (result); +} + + +static isc_result_t +dlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name, + const char *client) +{ + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_result_t result; + + UNUSED(driverarg); + + + if (cd->dlz_allowzonexfr == NULL) { + return (ISC_R_NOPERM); + } + + MAYBE_LOCK(cd); + result = cd->dlz_allowzonexfr(cd->dbdata, name, client); + MAYBE_UNLOCK(cd); + return (result); +} + +static isc_result_t +dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata, + dns_sdlzlookup_t *lookup) +{ + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_authority == NULL) { + return (ISC_R_NOTIMPLEMENTED); + } + + MAYBE_LOCK(cd); + result = cd->dlz_authority(zone, cd->dbdata, lookup); + MAYBE_UNLOCK(cd); + return (result); +} + +static isc_result_t +dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name) +{ + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_result_t result; + + UNUSED(driverarg); + + MAYBE_LOCK(cd); + result = cd->dlz_findzonedb(cd->dbdata, name); + MAYBE_UNLOCK(cd); + return (result); +} + + +static isc_result_t +dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg, + void *dbdata, dns_sdlzlookup_t *lookup) +{ + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_result_t result; + + UNUSED(driverarg); + + MAYBE_LOCK(cd); + result = cd->dlz_lookup(zone, name, cd->dbdata, lookup); + MAYBE_UNLOCK(cd); + return (result); +} + +/* + * Load a symbol from the library + */ +static void * +dl_load_symbol(dlopen_data_t *cd, const char *symbol, bool mandatory) { + void *ptr = dlsym(cd->dl_handle, symbol); + if (ptr == NULL && mandatory) { + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen: library '%s' is missing " + "required symbol '%s'", cd->dl_path, symbol); + } + return (ptr); +} + +/* + * Called at startup for each dlopen zone in named.conf + */ +static isc_result_t +dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], + void *driverarg, void **dbdata) +{ + dlopen_data_t *cd; + isc_mem_t *mctx = NULL; + isc_result_t result = ISC_R_FAILURE; + int dlopen_flags; + + UNUSED(driverarg); + + if (argc < 2) { + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen driver for '%s' needs a path to " + "the shared library", dlzname); + return (ISC_R_FAILURE); + } + + isc_mem_create(0, 0, &mctx); + + cd = isc_mem_get(mctx, sizeof(*cd)); + if (cd == NULL) { + isc_mem_destroy(&mctx); + return (ISC_R_NOMEMORY); + } + memset(cd, 0, sizeof(*cd)); + + cd->mctx = mctx; + + cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]); + if (cd->dl_path == NULL) { + goto failed; + } + + cd->dlzname = isc_mem_strdup(cd->mctx, dlzname); + if (cd->dlzname == NULL) { + goto failed; + } + + /* Open the library */ + dlopen_flags = RTLD_NOW; + +#ifdef RTLD_DEEPBIND + /* + * If RTLD_DEEPBIND is available then use it. This can avoid + * issues with a module using a different version of a system + * library than one that bind9 uses. For example, bind9 may link + * to MIT kerberos, but the module may use Heimdal. If we don't + * use RTLD_DEEPBIND then we could end up with Heimdal functions + * calling MIT functions, which leads to bizarre results (usually + * a segfault). + */ + dlopen_flags |= RTLD_DEEPBIND; +#endif + + cd->dl_handle = dlopen(cd->dl_path, dlopen_flags); + if (cd->dl_handle == NULL) { + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen failed to open library '%s' - %s", + cd->dl_path, dlerror()); + goto failed; + } + + /* Find the symbols */ + cd->dlz_version = dl_load_symbol(cd, "dlz_version", true); + cd->dlz_create = dl_load_symbol(cd, "dlz_create", true); + cd->dlz_lookup = dl_load_symbol(cd, "dlz_lookup", true); + cd->dlz_findzonedb = dl_load_symbol(cd, "dlz_findzonedb", true); + + if (cd->dlz_create == NULL || cd->dlz_lookup == NULL || + cd->dlz_findzonedb == NULL) + { + /* We're missing a required symbol */ + goto failed; + } + + cd->dlz_allowzonexfr = dl_load_symbol(cd, "dlz_allowzonexfr", false); + cd->dlz_allnodes = dl_load_symbol(cd, "dlz_allnodes", + cd->dlz_allowzonexfr != NULL); + cd->dlz_authority = dl_load_symbol(cd, "dlz_authority", false); + cd->dlz_newversion = dl_load_symbol(cd, "dlz_newversion", false); + cd->dlz_closeversion = dl_load_symbol(cd, "dlz_closeversion", + cd->dlz_newversion != NULL); + cd->dlz_configure = dl_load_symbol(cd, "dlz_configure", false); + cd->dlz_ssumatch = dl_load_symbol(cd, "dlz_ssumatch", false); + cd->dlz_addrdataset = dl_load_symbol(cd, "dlz_addrdataset", false); + cd->dlz_subrdataset = dl_load_symbol(cd, "dlz_subrdataset", false); + cd->dlz_delrdataset = dl_load_symbol(cd, "dlz_delrdataset", false); + + /* Check the version of the API is the same */ + cd->version = cd->dlz_version(&cd->flags); + if (cd->version != DLZ_DLOPEN_VERSION) { + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen: incorrect version %d " + "should be %d in '%s'", + cd->version, DLZ_DLOPEN_VERSION, cd->dl_path); + goto failed; + } + + /* + * Call the library's create function. Note that this is an + * extended version of dlz create, with the addition of + * named function pointers for helper functions that the + * driver will need. This avoids the need for the backend to + * link the bind9 libraries + */ + MAYBE_LOCK(cd); + result = cd->dlz_create(dlzname, argc-1, argv+1, + &cd->dbdata, + "log", dlopen_log, + "putrr", dns_sdlz_putrr, + "putnamedrr", dns_sdlz_putnamedrr, + "writeable_zone", dns_dlz_writeablezone, + NULL); + MAYBE_UNLOCK(cd); + if (result != ISC_R_SUCCESS) + goto failed; + + *dbdata = cd; + + return (ISC_R_SUCCESS); + +failed: + dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname); + if (cd->dl_path) + isc_mem_free(mctx, cd->dl_path); + if (cd->dlzname) + isc_mem_free(mctx, cd->dlzname); +#ifdef HAVE_DLCLOSE + if (cd->dl_handle) + dlclose(cd->dl_handle); +#endif + isc_mem_put(mctx, cd, sizeof(*cd)); + isc_mem_destroy(&mctx); + return (result); +} + + +/* + * Called when bind is shutting down + */ +static void +dlopen_dlz_destroy(void *driverarg, void *dbdata) { + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_mem_t *mctx; + + UNUSED(driverarg); + + if (cd->dlz_destroy) { + MAYBE_LOCK(cd); + cd->dlz_destroy(cd->dbdata); + MAYBE_UNLOCK(cd); + } + + if (cd->dl_path) + isc_mem_free(cd->mctx, cd->dl_path); + if (cd->dlzname) + isc_mem_free(cd->mctx, cd->dlzname); +#ifdef HAVE_DLCLOSE + if (cd->dl_handle) + dlclose(cd->dl_handle); +#endif + mctx = cd->mctx; + isc_mem_put(mctx, cd, sizeof(*cd)); + isc_mem_destroy(&mctx); +} + +/* + * Called to start a transaction + */ +static isc_result_t +dlopen_dlz_newversion(const char *zone, void *driverarg, void *dbdata, + void **versionp) +{ + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_newversion == NULL) + return (ISC_R_NOTIMPLEMENTED); + + MAYBE_LOCK(cd); + result = cd->dlz_newversion(zone, cd->dbdata, versionp); + MAYBE_UNLOCK(cd); + return (result); +} + +/* + * Called to end a transaction + */ +static void +dlopen_dlz_closeversion(const char *zone, isc_boolean_t commit, + void *driverarg, void *dbdata, void **versionp) +{ + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + + UNUSED(driverarg); + + if (cd->dlz_newversion == NULL) { + *versionp = NULL; + return; + } + + MAYBE_LOCK(cd); + cd->dlz_closeversion(zone, commit, cd->dbdata, versionp); + MAYBE_UNLOCK(cd); +} + +/* + * Called on startup to configure any writeable zones + */ +static isc_result_t +dlopen_dlz_configure(dns_view_t *view, void *driverarg, void *dbdata) { + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_configure == NULL) + return (ISC_R_SUCCESS); + + MAYBE_LOCK(cd); + cd->in_configure = ISC_TRUE; + result = cd->dlz_configure(view, cd->dbdata); + cd->in_configure = ISC_FALSE; + MAYBE_UNLOCK(cd); + + return (result); +} + + +/* + * Check for authority to change a name + */ +static isc_boolean_t +dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, + const char *type, const char *key, uint32_t keydatalen, + uint8_t *keydata, void *driverarg, void *dbdata) +{ + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_boolean_t ret; + + UNUSED(driverarg); + + if (cd->dlz_ssumatch == NULL) + return (ISC_FALSE); + + MAYBE_LOCK(cd); + ret = cd->dlz_ssumatch(signer, name, tcpaddr, type, key, keydatalen, + keydata, cd->dbdata); + MAYBE_UNLOCK(cd); + + return (ret); +} + + +/* + * Add an rdataset + */ +static isc_result_t +dlopen_dlz_addrdataset(const char *name, const char *rdatastr, + void *driverarg, void *dbdata, void *version) +{ + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_addrdataset == NULL) + return (ISC_R_NOTIMPLEMENTED); + + MAYBE_LOCK(cd); + result = cd->dlz_addrdataset(name, rdatastr, cd->dbdata, version); + MAYBE_UNLOCK(cd); + + return (result); +} + +/* + * Subtract an rdataset + */ +static isc_result_t +dlopen_dlz_subrdataset(const char *name, const char *rdatastr, + void *driverarg, void *dbdata, void *version) +{ + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_subrdataset == NULL) + return (ISC_R_NOTIMPLEMENTED); + + MAYBE_LOCK(cd); + result = cd->dlz_subrdataset(name, rdatastr, cd->dbdata, version); + MAYBE_UNLOCK(cd); + + return (result); +} + +/* + delete a rdataset + */ +static isc_result_t +dlopen_dlz_delrdataset(const char *name, const char *type, + void *driverarg, void *dbdata, void *version) +{ + dlopen_data_t *cd = (dlopen_data_t *) dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_delrdataset == NULL) + return (ISC_R_NOTIMPLEMENTED); + + MAYBE_LOCK(cd); + result = cd->dlz_delrdataset(name, type, cd->dbdata, version); + MAYBE_UNLOCK(cd); + + return (result); +} + + +static dns_sdlzmethods_t dlz_dlopen_methods = { + dlopen_dlz_create, + dlopen_dlz_destroy, + dlopen_dlz_findzonedb, + dlopen_dlz_lookup, + dlopen_dlz_authority, + dlopen_dlz_allnodes, + dlopen_dlz_allowzonexfr, + dlopen_dlz_newversion, + dlopen_dlz_closeversion, + dlopen_dlz_configure, + dlopen_dlz_ssumatch, + dlopen_dlz_addrdataset, + dlopen_dlz_subrdataset, + dlopen_dlz_delrdataset +}; + +/* + * Register driver with BIND + */ +isc_result_t +dlz_dlopen_init(void) { + isc_result_t result; + + dlopen_log(2, "Registering DLZ_dlopen driver"); + + result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL, + DNS_SDLZFLAG_RELATIVEOWNER | + DNS_SDLZFLAG_THREADSAFE, + ns_g_mctx, &dlz_dlopen); + + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "dns_sdlzregister() failed: %s", + isc_result_totext(result)); + result = ISC_R_UNEXPECTED; + } + + return (result); +} + + +/* + * Unregister the driver + */ +void +dlz_dlopen_clear(void) { + dlopen_log(2, "Unregistering DLZ_dlopen driver"); + if (dlz_dlopen != NULL) + dns_sdlzunregister(&dlz_dlopen); +} + +#endif diff --git a/contrib/dlz/drivers/dlz_drivers.c b/contrib/dlz/drivers/dlz_drivers.c index e2c6a6e10d..568843760d 100644 --- a/contrib/dlz/drivers/dlz_drivers.c +++ b/contrib/dlz/drivers/dlz_drivers.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dlz_drivers.c,v 1.2 2005/09/05 00:10:55 marka Exp $ */ +/* $Id: dlz_drivers.c,v 1.3 2010/12/18 01:56:20 each Exp $ */ /*! \file */ @@ -61,6 +61,10 @@ #include #endif +#ifdef DLZ_DLOPEN +#include +#endif + /*% * Call init functions for all relevant DLZ drivers. */ @@ -115,6 +119,12 @@ dlz_drivers_init(void) { return (result); #endif +#ifdef DLZ_DLOPEN + result = dlz_dlopen_init(); + if (result != ISC_R_SUCCESS) + return (result); +#endif + return (result); } @@ -154,4 +164,8 @@ dlz_drivers_clear(void) { dlz_odbc_clear(); #endif +#ifdef DLZ_DLOPEN + dlz_dlopen_clear(); +#endif + } diff --git a/contrib/dlz/drivers/dlz_filesystem_driver.c b/contrib/dlz/drivers/dlz_filesystem_driver.c index 3651491877..a04faaac38 100644 --- a/contrib/dlz/drivers/dlz_filesystem_driver.c +++ b/contrib/dlz/drivers/dlz_filesystem_driver.c @@ -996,7 +996,14 @@ static dns_sdlzmethods_t dlz_fs_methods = { fs_lookup, NULL, fs_allnodes, - fs_allowzonexfr + fs_allowzonexfr, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; /*% diff --git a/contrib/dlz/drivers/dlz_ldap_driver.c b/contrib/dlz/drivers/dlz_ldap_driver.c index 35d75489b9..77422baee4 100644 --- a/contrib/dlz/drivers/dlz_ldap_driver.c +++ b/contrib/dlz/drivers/dlz_ldap_driver.c @@ -1287,7 +1287,14 @@ static dns_sdlzmethods_t dlz_ldap_methods = { dlz_ldap_lookup, dlz_ldap_authority, dlz_ldap_allnodes, - dlz_ldap_allowzonexfr + dlz_ldap_allowzonexfr, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; /*% diff --git a/contrib/dlz/drivers/dlz_mysql_driver.c b/contrib/dlz/drivers/dlz_mysql_driver.c index 50cceb139c..dcfab1e6da 100644 --- a/contrib/dlz/drivers/dlz_mysql_driver.c +++ b/contrib/dlz/drivers/dlz_mysql_driver.c @@ -1013,7 +1013,14 @@ static dns_sdlzmethods_t dlz_mysql_methods = { mysql_lookup, mysql_authority, mysql_allnodes, - mysql_allowzonexfr + mysql_allowzonexfr, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; /*% diff --git a/contrib/dlz/drivers/dlz_odbc_driver.c b/contrib/dlz/drivers/dlz_odbc_driver.c index eb088a2132..6031b08d70 100644 --- a/contrib/dlz/drivers/dlz_odbc_driver.c +++ b/contrib/dlz/drivers/dlz_odbc_driver.c @@ -1506,7 +1506,14 @@ static dns_sdlzmethods_t dlz_odbc_methods = { odbc_lookup, odbc_authority, odbc_allnodes, - odbc_allowzonexfr + odbc_allowzonexfr, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; /*% diff --git a/contrib/dlz/drivers/dlz_postgres_driver.c b/contrib/dlz/drivers/dlz_postgres_driver.c index 5cad59e343..c5367c6164 100644 --- a/contrib/dlz/drivers/dlz_postgres_driver.c +++ b/contrib/dlz/drivers/dlz_postgres_driver.c @@ -1310,7 +1310,14 @@ static dns_sdlzmethods_t dlz_postgres_methods = { postgres_lookup, postgres_authority, postgres_allnodes, - postgres_allowzonexfr + postgres_allowzonexfr, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; /*% diff --git a/contrib/dlz/drivers/dlz_stub_driver.c b/contrib/dlz/drivers/dlz_stub_driver.c index f9a3bb8f0a..c2e72ddb92 100644 --- a/contrib/dlz/drivers/dlz_stub_driver.c +++ b/contrib/dlz/drivers/dlz_stub_driver.c @@ -164,7 +164,7 @@ stub_dlz_findzonedb(void *driverarg, void *dbdata, const char *name) if (strcmp(cd->myzone, name) == 0) return (ISC_R_SUCCESS); else - return (ISC_R_SUCCESS); + return (ISC_R_NOTFOUND); } @@ -279,7 +279,14 @@ static dns_sdlzmethods_t dlz_stub_methods = { stub_dlz_lookup, stub_dlz_authority, stub_dlz_allnodes, - stub_dlz_allowzonexfr + stub_dlz_allowzonexfr, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, }; /*% diff --git a/contrib/dlz/drivers/include/dlz/dlz_dlopen_driver.h b/contrib/dlz/drivers/include/dlz/dlz_dlopen_driver.h new file mode 100644 index 0000000000..d155f315dc --- /dev/null +++ b/contrib/dlz/drivers/include/dlz/dlz_dlopen_driver.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010 Andrew Tridgell + * + * based on dlz_stub_driver.h + * which is: + * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl. + * Copyright (C) 1999-2001 Internet Software Consortium. + * see dlz_stub_driver.h for details + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE + * USE OR PERFORMANCE OF THIS SOFTWARE. + * + * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was + * conceived and contributed by Rob Butler. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE + * USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DLZ_DLOPEN_DRIVER_H +#define DLZ_DLOPEN_DRIVER_H + +isc_result_t +dlz_dlopen_init(void); + +void +dlz_dlopen_clear(void); + +#define DLZ_DLOPEN_VERSION 1 + +#endif diff --git a/contrib/dlz/drivers/rules.in b/contrib/dlz/drivers/rules.in index 9caabcb431..e3b64b3fe9 100644 --- a/contrib/dlz/drivers/rules.in +++ b/contrib/dlz/drivers/rules.in @@ -12,7 +12,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: rules.in,v 1.2 2005/09/05 00:10:57 marka Exp $ +# $Id: rules.in,v 1.3 2010/12/18 01:56:21 each Exp $ dlz_drivers.@O@: ${DLZ_DRIVER_DIR}/dlz_drivers.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_drivers.h ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_drivers.c @@ -42,6 +42,9 @@ dlz_odbc_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_odbc_driver.c ${DLZ_DRIVER_DIR}/inclu dlz_postgres_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_postgres_driver.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_postgres_driver.h ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_postgres_driver.c +dlz_dlopen_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_dlopen_driver.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_dlopen_driver.h + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_dlopen_driver.c + dlz_stub_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_stub_driver.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_stub_driver.h ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_stub_driver.c diff --git a/contrib/dlz/example/Makefile b/contrib/dlz/example/Makefile new file mode 100644 index 0000000000..b8509aaf11 --- /dev/null +++ b/contrib/dlz/example/Makefile @@ -0,0 +1,16 @@ +# for building the dlz_example driver we don't use +# the bind9 build structure as the aim is to provide an +# example that is separable from the bind9 source tree + +# this means this Makefile is not portable, so the testsuite +# skips this test on platforms where it doesn't build + +CFLAGS=-fPIC -g + +all: dlz_example.so + +dlz_example.so: dlz_example.o + $(CC) $(CFLAGS) -shared -o dlz_example.so dlz_example.o + +clean: + rm -f dlz_example.o dlz_example.so diff --git a/contrib/dlz/example/dlz_example.c b/contrib/dlz/example/dlz_example.c new file mode 100644 index 0000000000..c8e468010a --- /dev/null +++ b/contrib/dlz/example/dlz_example.c @@ -0,0 +1,482 @@ +/* + * Copyright (C) 2010 Andrew Tridgell + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE + * USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + this provides a very simple example of an external loadable DLZ + driver, with update support + */ + +#include +#include +#include +#include +#include +#include + +#include "dlz_minimal.h" + + +/* for this simple example, use fixed sized strings */ +struct record { + char name[100]; + char type[10]; + char data[200]; + uint32_t ttl; +}; + +#define MAX_RECORDS 100 + +struct dlz_example_data { + char *zone_name; + + /* an example driver doesn't need good memory management :-) */ + struct record current[MAX_RECORDS]; + struct record adds[MAX_RECORDS]; + struct record deletes[MAX_RECORDS]; + + bool transaction_started; + + /* helper functions from the dlz_dlopen driver */ + void (*log)(int level, const char *fmt, ...); + isc_result_t (*putrr)(dns_sdlzlookup_t *handle, const char *type, + dns_ttl_t ttl, const char *data); + isc_result_t (*putnamedrr)(dns_sdlzlookup_t *handle, const char *name, + const char *type, dns_ttl_t ttl, const char *data); + isc_result_t (*writeable_zone)(dns_view_t *view, const char *zone_name); +}; + +static bool single_valued(const char *type) +{ + const char *single[] = { "soa", "cname", NULL }; + int i; + for (i=0; single[i]; i++) { + if (strcasecmp(single[i], type) == 0) { + return true; + } + } + return false; +} + +/* + add a record to a list + */ +static isc_result_t add_name(struct dlz_example_data *state, + struct record *list, const char *name, const char *type, + uint32_t ttl, const char *data) +{ + int i; + bool single = single_valued(type); + int first_empty = -1; + + for (i=0; ilog(ISC_LOG_ERROR, "dlz_example: out of record space"); + return ISC_R_FAILURE; + } + strcpy(list[i].name, name); + strcpy(list[i].type, type); + strcpy(list[i].data, data); + list[i].ttl = ttl; + return ISC_R_SUCCESS; +} + +/* + delete a record from a list + */ +static isc_result_t del_name(struct dlz_example_data *state, + struct record *list, const char *name, const char *type, + uint32_t ttl, const char *data) +{ + int i; + for (i=0; ilog = ptr; + } + if (strcmp(helper_name, "putrr") == 0) { + state->putrr = ptr; + } + if (strcmp(helper_name, "putnamedrr") == 0) { + state->putnamedrr = ptr; + } + if (strcmp(helper_name, "writeable_zone") == 0) { + state->writeable_zone = ptr; + } +} + + +/* + called to initialise the driver + */ +isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], + void **dbdata, ...) +{ + struct dlz_example_data *state; + const char *helper_name; + va_list ap; + char soa_data[200]; + + state = calloc(1, sizeof(struct dlz_example_data)); + if (state == NULL) { + return ISC_R_NOMEMORY; + } + + /* fill in the helper functions */ + va_start(ap, dbdata); + while ((helper_name = va_arg(ap, const char *)) != NULL) { + b9_add_helper(state, helper_name, va_arg(ap, void*)); + } + va_end(ap); + + if (argc < 2) { + state->log(ISC_LOG_ERROR, "dlz_example: please specify a zone name"); + return ISC_R_FAILURE; + } + + state->zone_name = strdup(argv[1]); + + sprintf(soa_data, "%s hostmaster.%s 123 900 600 86400 3600", + state->zone_name, state->zone_name); + + add_name(state, &state->current[0], state->zone_name, "soa", 3600, soa_data); + add_name(state, &state->current[0], state->zone_name, "ns", 3600, state->zone_name); + add_name(state, &state->current[0], state->zone_name, "a", 1800, "10.53.0.1"); + + state->log(ISC_LOG_INFO, "dlz_example: started for zone %s", state->zone_name); + + *dbdata = state; + return ISC_R_SUCCESS; +} + +/* + shutdown the backend + */ +void dlz_destroy(void *dbdata) +{ + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + state->log(ISC_LOG_INFO, "dlz_example: shutting down zone %s", state->zone_name); + free(state->zone_name); + free(state); +} + + +/* + see if we handle a given zone + */ +isc_result_t dlz_findzonedb(void *dbdata, const char *name) +{ + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + if (strcasecmp(state->zone_name, name) == 0) { + return ISC_R_SUCCESS; + } + return ISC_R_NOTFOUND; +} + + + +/* + lookup one record + */ +isc_result_t dlz_lookup(const char *zone, const char *name, + void *dbdata, dns_sdlzlookup_t *lookup) +{ + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + int i; + bool found = false; + char full_name[100]; + + if (strcmp(name, "@") == 0) { + strcpy(full_name, state->zone_name); + } else { + sprintf(full_name, "%s.%s", name, state->zone_name); + } + for (i=0; icurrent[i].name, full_name) == 0) { + isc_result_t result; + found = true; + result = state->putrr(lookup, state->current[i].type, + state->current[i].ttl, state->current[i].data); + if (result != ISC_R_SUCCESS) { + return result; + } + } + } + if (!found) { + return ISC_R_NOTFOUND; + } + return ISC_R_SUCCESS; +} + + +/* + see if a zone transfer is allowed + */ +isc_result_t dlz_allowzonexfr(void *dbdata, const char *name, const char *client) +{ + /* just say yes for all our zones */ + return dlz_findzonedb(dbdata, name); +} + +/* + perform a zone transfer + */ +isc_result_t dlz_allnodes(const char *zone, void *dbdata, + dns_sdlzallnodes_t *allnodes) +{ + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + int i; + + for (i=0; icurrent[i].name) == 0) { + continue; + } + result = state->putnamedrr(allnodes, state->current[i].name, state->current[i].type, + state->current[i].ttl, state->current[i].data); + if (result != ISC_R_SUCCESS) { + return result; + } + } + + return ISC_R_SUCCESS; +} + + +/* + start a transaction + */ +isc_result_t dlz_newversion(const char *zone, void *dbdata, void **versionp) +{ + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + if (state->transaction_started) { + state->log(ISC_LOG_INFO, "dlz_example: transaction already started for zone %s", zone); + return ISC_R_FAILURE; + } + + state->transaction_started = true; + + *versionp = (void *) &state->transaction_started; + + return ISC_R_SUCCESS; +} + +/* + end a transaction + */ +void dlz_closeversion(const char *zone, isc_boolean_t commit, void *dbdata, void **versionp) +{ + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + if (!state->transaction_started) { + state->log(ISC_LOG_INFO, "dlz_example: transaction not started for zone %s", zone); + *versionp = NULL; + return; + } + + state->transaction_started = false; + + *versionp = NULL; + + if (commit) { + int i; + state->log(ISC_LOG_INFO, "dlz_example: committing transaction on zone %s", zone); + for (i=0; iadds[i].name) > 0) { + add_name(state, &state->current[0], + state->adds[i].name, + state->adds[i].type, + state->adds[i].ttl, + state->adds[i].data); + } + } + for (i=0; ideletes[i].name) > 0) { + del_name(state, &state->current[0], + state->deletes[i].name, + state->deletes[i].type, + state->deletes[i].ttl, + state->deletes[i].data); + } + } + } else { + state->log(ISC_LOG_INFO, "dlz_example: cancelling transaction on zone %s", zone); + } + memset(state->adds, 0, sizeof(state->adds)); + memset(state->deletes, 0, sizeof(state->deletes)); +} + + +/* + configure a writeable zone + */ +isc_result_t dlz_configure(dns_view_t *view, void *dbdata) +{ + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + isc_result_t result; + + + state->log(ISC_LOG_INFO, "dlz_example: starting configure"); + if (state->writeable_zone == NULL) { + state->log(ISC_LOG_INFO, "dlz_example: no writeable_zone method available"); + return ISC_R_FAILURE; + } + + result = state->writeable_zone(view, state->zone_name); + if (result != ISC_R_SUCCESS) { + state->log(ISC_LOG_ERROR, "dlz_example: failed to configure zone %s", state->zone_name); + return result; + } + + state->log(ISC_LOG_INFO, "dlz_example: configured writeable zone %s", state->zone_name); + return ISC_R_SUCCESS; +} + +/* + authorize a zone update + */ +isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, + const char *type, const char *key, uint32_t keydatalen, uint8_t *keydata, + void *dbdata) +{ + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + if (strncmp(name, "deny.", 5) == 0) { + state->log(ISC_LOG_INFO, "dlz_example: denying update of name=%s by %s", + name, signer); + return false; + } + state->log(ISC_LOG_INFO, "dlz_example: allowing update of name=%s by %s", + name, signer); + return true; +} + + +static isc_result_t modrdataset(struct dlz_example_data *state, const char *name, const char *rdatastr, + struct record *list) +{ + char *full_name, *dclass, *type, *data, *ttlstr; + char *buf = strdup(rdatastr); + isc_result_t result; + char *saveptr = NULL; + + /* + the format is: + FULLNAME\tTTL\tDCLASS\tTYPE\tDATA + + The DATA field is space separated, and is in the data format + for the type used by dig + */ + + full_name = strtok_r(buf, "\t", &saveptr); + if (full_name == NULL) return ISC_R_FAILURE; + ttlstr = strtok_r(NULL, "\t", &saveptr); + if (ttlstr == NULL) return ISC_R_FAILURE; + dclass = strtok_r(NULL, "\t", &saveptr); + if (dclass == NULL) return ISC_R_FAILURE; + type = strtok_r(NULL, "\t", &saveptr); + if (type == NULL) return ISC_R_FAILURE; + data = strtok_r(NULL, "\t", &saveptr); + if (data == NULL) return ISC_R_FAILURE; + + result = add_name(state, list, name, type, strtoul(ttlstr, NULL, 10), data); + free(buf); + return result; +} + + +isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata, void *version) +{ + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + if (version != (void *) &state->transaction_started) { + return ISC_R_FAILURE; + } + + state->log(ISC_LOG_INFO, "dlz_example: adding rdataset %s '%s'", name, rdatastr); + + return modrdataset(state, name, rdatastr, &state->adds[0]); +} + +isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata, void *version) +{ + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + if (version != (void *) &state->transaction_started) { + return ISC_R_FAILURE; + } + + state->log(ISC_LOG_INFO, "dlz_example: subtracting rdataset %s '%s'", name, rdatastr); + + return modrdataset(state, name, rdatastr, &state->deletes[0]); +} + + +isc_result_t dlz_delrdataset(const char *name, const char *type, void *dbdata, void *version) +{ + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + if (version != (void *) &state->transaction_started) { + return ISC_R_FAILURE; + } + + state->log(ISC_LOG_INFO, "dlz_example: deleting rdataset %s of type %s", name, type); + + return ISC_R_SUCCESS; +} diff --git a/contrib/dlz/example/dlz_minimal.h b/contrib/dlz/example/dlz_minimal.h new file mode 100644 index 0000000000..923c63a90c --- /dev/null +++ b/contrib/dlz/example/dlz_minimal.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2010 Andrew Tridgell + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE + * USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + This header provides a minimal set of defines and typedefs needed + for building an external DLZ module for bind9. When creating a new + external DLZ driver, please copy this header into your own source + tree. + */ +typedef unsigned int isc_result_t; +typedef bool isc_boolean_t; +typedef uint32_t dns_ttl_t; + +#define DLZ_DLOPEN_VERSION 1 + +/* return this in flags to dlz_version() if thread safe */ +#define DNS_SDLZFLAG_THREADSAFE 0x00000001U + +/* result codes */ +#define ISC_R_SUCCESS 0 +#define ISC_R_NOMEMORY 1 +#define ISC_R_NOTFOUND 23 +#define ISC_R_FAILURE 25 + +/* log levels */ +#define ISC_LOG_INFO (-1) +#define ISC_LOG_NOTICE (-2) +#define ISC_LOG_WARNING (-3) +#define ISC_LOG_ERROR (-4) +#define ISC_LOG_CRITICAL (-5) + +/* some opaque structures */ +typedef void *dns_sdlzlookup_t; +typedef void *dns_sdlzallnodes_t; +typedef void *dns_view_t; + +/* + * prototypes for the functions you can include in your driver + */ + + +/* + * dlz_version() is required for all DLZ external drivers. It should + * return DLZ_DLOPEN_VERSION + */ +int dlz_version(unsigned int *flags); + +/* + * dlz_create() is required for all DLZ external drivers. + */ +isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, ...); + +/* + * dlz_destroy() is optional, and will be called when the driver is + * unloaded if supplied + */ +void dlz_destroy(void *dbdata); + +/* + dlz_findzonedb is required for all DLZ external drivers + */ +isc_result_t dlz_findzonedb(void *dbdata, const char *name); + +/* + dlz_lookup is required for all DLZ external drivers + */ +isc_result_t dlz_lookup(const char *zone, const char *name, + void *dbdata, dns_sdlzlookup_t *lookup); + +/* + dlz_allowzonexfr() is optional, and should be supplied if you want + to support zone transfers + */ +isc_result_t dlz_allowzonexfr(void *dbdata, const char *name, const char *client); + + +/* + dlz_allnodes() is optional, but must be supplied if supply a + dlz_allowzonexfr() function + */ +isc_result_t dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes); + +/* + dlz_newversion() is optional. It should be supplied if you want to + support dynamic updates. + */ +isc_result_t dlz_newversion(const char *zone, void *dbdata, void **versionp); + +/* + dlz_closeversion() is optional, but must be supplied if you supply + a dlz_newversion() function + */ +void dlz_closeversion(const char *zone, isc_boolean_t commit, void *dbdata, void **versionp); + +/* + dlz_configure() is optional, but must be supplied if you want to + support dynamic updates + */ +isc_result_t dlz_configure(dns_view_t *view, void *dbdata); + +/* + dlz_ssumatch() is optional, but must be supplied if you want to + support dynamic updates + */ +isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, + const char *type, const char *key, uint32_t keydatalen, uint8_t *keydata, + void *dbdata); + +/* + dlz_addrdataset() is optional, but must be supplied if you want to + support dynamic updates + */ +isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata, void *version); + +/* + dlz_subrdataset() is optional, but must be supplied if you want to + support dynamic updates + */ +isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata, void *version); + +/* + dlz_delrdataset() is optional, but must be supplied if you want to + support dynamic updates + */ +isc_result_t dlz_delrdataset(const char *name, const char *type, void *dbdata, void *version); diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 2f9f6fcbfa..916401c93a 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + BIND 9 Administrator Reference Manual @@ -1792,8 +1792,9 @@ controls { - The tkey-gssapi-credential and - tkey-domain clauses in the + The tkey-gssapi-credential, + tkey-gssapi-keytab + and tkey-domain clauses in the options statement enable the server to negotiate keys that can be matched against those in update-policy or @@ -4973,6 +4974,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] key-directory path_name; managed-keys-directory path_name; named-xfer path_name; + tkey-gssapi-keytab path_name; tkey-gssapi-credential principal; tkey-domain domainname; tkey-dhkey key_name key_tag; @@ -5329,6 +5331,18 @@ badresp:1,adberr:0,findfail:0,valfail:0] + + tkey-gssapi-keytab + + + The KRB5 keytab file to use for GSS-TSIG updates. If + this option is set and tkey-gssapi-credential is not + set, then updates will be allowed with any key + matching a principal in the specified keytab. + + + + tkey-gssapi-credential @@ -5336,13 +5350,15 @@ badresp:1,adberr:0,findfail:0,valfail:0] The security credential with which the server should authenticate keys requested by the GSS-TSIG protocol. Currently only Kerberos 5 authentication is available - and the credential is a Kerberos principal which - the server can acquire through the default system - key file, normally /etc/krb5.keytab. - Normally this principal is of the form - "DNS/server.domain". - To use GSS-TSIG, tkey-domain - must also be set. + and the credential is a Kerberos principal which the + server can acquire through the default system key + file, normally /etc/krb5.keytab. + The location keytab file can be overridden using the + tkey-gssapi-keytab option. Normally this principal is + of the form "DNS/server.domain". + To use GSS-TSIG, tkey-domain must + also be set if a specific keytab is not set with + tkey-gssapi-keytab. @@ -5364,7 +5380,8 @@ badresp:1,adberr:0,findfail:0,valfail:0] should be the server's domain name, or an otherwise non-existent subdomain like "_tkey.domainname". If you are - using GSS-TSIG, this variable must be defined. + using GSS-TSIG, this variable must be defined, unless + you specify a specific keytab using tkey-gssapi-keytab. diff --git a/doc/misc/options b/doc/misc/options index 23a2b4d2df..87f24c1381 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -217,6 +217,7 @@ options { tkey-dhkey ; tkey-domain ; tkey-gssapi-credential ; + tkey-gssapi-keytab ; topology { ; ... }; // not implemented transfer-format ( many-answers | one-answer ); transfer-source ( | * ) [ port ( | * ) ]; @@ -511,7 +512,7 @@ view { update-policy ( local | { ( grant | deny ) ( name | subdomain | wildcard | self | selfsub | selfwild | krb5-self | ms-self | krb5-subdomain | ms-subdomain | - tcp-self | 6to4-self | zonesub ) [ ] + tcp-self | 6to4-self | zonesub | external ) [ ] ; ... }; use-alt-transfer-source ; zero-no-soa-ttl ; @@ -594,7 +595,7 @@ zone { update-policy ( local | { ( grant | deny ) ( name | subdomain | wildcard | self | selfsub | selfwild | krb5-self | ms-self | krb5-subdomain | ms-subdomain | tcp-self | 6to4-self - | zonesub ) [ ] ; ... }; + | zonesub | external ) [ ] ; ... }; use-alt-transfer-source ; zero-no-soa-ttl ; zone-statistics ; diff --git a/lib/dns/dlz.c b/lib/dns/dlz.c index 66c8fc514d..242f61961d 100644 --- a/lib/dns/dlz.c +++ b/lib/dns/dlz.c @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dlz.c,v 1.7 2009/01/17 23:47:42 tbox Exp $ */ +/* $Id: dlz.c,v 1.8 2010/12/18 01:56:22 each Exp $ */ /*! \file */ @@ -64,6 +64,8 @@ #include #include #include +#include +#include #include @@ -230,6 +232,10 @@ dns_dlzdestroy(dns_dlzdb_t **dbp) { */ REQUIRE(dbp != NULL && DNS_DLZ_VALID(*dbp)); + if ((*dbp)->ssutable != NULL) { + dns_ssutable_detach(&(*dbp)->ssutable); + } + /* call the drivers destroy method */ if ((*dbp) != NULL) { mctx = (*dbp)->mctx; @@ -499,7 +505,7 @@ dns_dlzunregister(dns_dlzimplementation_t **dlzimp) { mctx = dlz_imp->mctx; /* - * return the memory back to the available memory pool and + * Return the memory back to the available memory pool and * remove it from the memory context. */ isc_mem_put(mctx, dlz_imp, sizeof(dns_dlzimplementation_t)); @@ -508,3 +514,142 @@ dns_dlzunregister(dns_dlzimplementation_t **dlzimp) { /* Unlock the dlz_implementations list. */ RWUNLOCK(&dlz_implock, isc_rwlocktype_write); } + + +/* + * Create a writeable DLZ zone. This can be called by DLZ drivers + * during configure() to create a zone that can be updated. The zone + * type is set to dns_zone_dlz, which is equivalent to a master zone + * + * This function uses a callback setup in dns_dlzconfigure() to call + * into the server zone code to setup the remaining pieces of server + * specific functionality on the zone + */ +isc_result_t +dns_dlz_writeablezone(dns_view_t *view, const char *zone_name) { + dns_zone_t *zone = NULL; + dns_zone_t *dupzone = NULL; + isc_result_t result; + isc_buffer_t buffer; + dns_fixedname_t fixorigin; + dns_name_t *origin; + dns_rdataclass_t zclass; + dns_dlzdb_t *dlzdatabase; + + REQUIRE(DNS_DLZ_VALID(view->dlzdatabase)); + + dlzdatabase = view->dlzdatabase; + + REQUIRE(dlzdatabase->configure_callback != NULL); + + isc_buffer_init(&buffer, zone_name, strlen(zone_name)); + isc_buffer_add(&buffer, strlen(zone_name)); + dns_fixedname_init(&fixorigin); + result = dns_name_fromtext(dns_fixedname_name(&fixorigin), + &buffer, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + origin = dns_fixedname_name(&fixorigin); + + zclass = view->rdclass; + + /* See if the zone already exists */ + result = dns_view_findzone(view, origin, &dupzone); + if (result == ISC_R_SUCCESS) { + dns_zone_detach(&dupzone); + result = ISC_R_EXISTS; + goto cleanup; + } + INSIST(dupzone == NULL); + + /* Create it */ + result = dns_zone_create(&zone, view->mctx); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_zone_setorigin(zone, origin); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_zone_setview(zone, view); + + dns_zone_setadded(zone, ISC_TRUE); + + if (dlzdatabase->ssutable == NULL) { + result = dns_ssutable_createdlz(dlzdatabase->mctx, + &dlzdatabase->ssutable, + view->dlzdatabase); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + dns_zone_setssutable(zone, dlzdatabase->ssutable); + + result = dlzdatabase->configure_callback(view, zone); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* + * Add the zone to its view in the new view list. + */ + result = dns_view_addzone(view, zone); + + result = ISC_R_SUCCESS; + + cleanup: + if (zone != NULL) + dns_zone_detach(&zone); + + return (result); +} + +/*% + * Configure a DLZ driver. This is optional, and if supplied gives + * the backend an opportunity to configure parameters related to DLZ. + */ +isc_result_t +dns_dlzconfigure(dns_view_t *view, isc_result_t (*callback)(dns_view_t *, + dns_zone_t *)) +{ + dns_dlzimplementation_t *impl; + dns_dlzdb_t *dlzdatabase; + isc_result_t result; + + REQUIRE(view != NULL); + REQUIRE(DNS_DLZ_VALID(view->dlzdatabase)); + REQUIRE(view->dlzdatabase->implementation != NULL); + + dlzdatabase = view->dlzdatabase; + impl = dlzdatabase->implementation; + + if (impl->methods->configure == NULL) + return (ISC_R_SUCCESS); + + dlzdatabase->configure_callback = callback; + + result = impl->methods->configure(impl->driverarg, + dlzdatabase->dbdata, view); + return (result); +} + +isc_boolean_t +dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase, + dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr, + dns_rdatatype_t type, const dst_key_t *key) +{ + dns_dlzimplementation_t *impl; + isc_boolean_t r; + + REQUIRE(dlzdatabase != NULL); + REQUIRE(dlzdatabase->implementation != NULL); + REQUIRE(dlzdatabase->implementation->methods != NULL); + impl = dlzdatabase->implementation; + + if (impl->methods->ssumatch == NULL) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_DLZ, ISC_LOG_INFO, + "No ssumatch method for DLZ database"); + return (ISC_FALSE); + } + + r = impl->methods->ssumatch(signer, name, tcpaddr, type, key, + impl->driverarg, dlzdatabase->dbdata); + return (r); +} diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c index 81ed8bb486..231e30965d 100644 --- a/lib/dns/dst_api.c +++ b/lib/dns/dst_api.c @@ -31,7 +31,7 @@ /* * Principal Author: Brian Wellington - * $Id: dst_api.c,v 1.53 2010/12/09 00:54:33 marka Exp $ + * $Id: dst_api.c,v 1.54 2010/12/18 01:56:22 each Exp $ */ /*! \file */ @@ -700,9 +700,10 @@ dst_key_getgssctx(const dst_key_t *key) isc_result_t dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, - dst_key_t **keyp) + dst_key_t **keyp, isc_region_t *intoken) { dst_key_t *key; + isc_result_t result; REQUIRE(gssctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); @@ -712,9 +713,21 @@ dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, if (key == NULL) return (ISC_R_NOMEMORY); + if (intoken != NULL) { + /* + * Keep the token for use by external ssu rules. They may need + * to examine the PAC in the kerberos ticket. + */ + RETERR(isc_buffer_allocate(key->mctx, &key->key_tkeytoken, + intoken->length)); + RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken)); + } + key->keydata.gssctx = gssctx; *keyp = key; - return (ISC_R_SUCCESS); + result = ISC_R_SUCCESS; +out: + return result; } isc_result_t @@ -1054,6 +1067,9 @@ dst_key_free(dst_key_t **keyp) { isc_mem_free(mctx, key->label); dns_name_free(key->key_name, mctx); isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); + if (key->key_tkeytoken) { + isc_buffer_free(&key->key_tkeytoken); + } memset(key, 0, sizeof(dst_key_t)); isc_mem_put(mctx, key, sizeof(dst_key_t)); *keyp = NULL; @@ -1149,7 +1165,7 @@ dst_key_setflags(dst_key_t *key, isc_uint32_t flags) { } void -dst_key_format(dst_key_t *key, char *cp, unsigned int size) { +dst_key_format(const dst_key_t *key, char *cp, unsigned int size) { char namestr[DNS_NAME_FORMATSIZE]; char algstr[DNS_NAME_FORMATSIZE]; @@ -1709,3 +1725,8 @@ dst__entropy_status(void) { return (0); #endif } + +isc_buffer_t * +dst_key_tkeytoken(const dst_key_t *key) { + return (key->key_tkeytoken); +} diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h index 994b9867c7..5ba2094510 100644 --- a/lib/dns/dst_internal.h +++ b/lib/dns/dst_internal.h @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dst_internal.h,v 1.25 2010/12/09 04:31:57 tbox Exp $ */ +/* $Id: dst_internal.h,v 1.26 2010/12/18 01:56:22 each Exp $ */ #ifndef DST_DST_INTERNAL_H #define DST_DST_INTERNAL_H 1 @@ -128,6 +128,7 @@ struct dst_key { int fmt_minor; /*%< private key format, minor version */ dst_func_t * func; /*%< crypto package specific functions */ + isc_buffer_t *key_tkeytoken; /*%< TKEY token data */ }; struct dst_context { diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c index 3a25e09c9b..111dffa6dd 100644 --- a/lib/dns/gssapictx.c +++ b/lib/dns/gssapictx.c @@ -15,16 +15,18 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: gssapictx.c,v 1.18 2010/07/09 05:13:15 each Exp $ */ +/* $Id: gssapictx.c,v 1.19 2010/12/18 01:56:22 each Exp $ */ #include +#include #include #include #include #include #include +#include #include #include #include @@ -201,9 +203,12 @@ log_cred(const gss_cred_id_t cred) { * - tkey-gssapi-credential doesn't start with DNS/ * - the default realm in /etc/krb5.conf and the * tkey-gssapi-credential bind config option don't match + * + * Note that if tkey-gssapi-keytab is set then these configure checks + * are not performed, and runtime errors from gssapi are used instead */ static void -dst_gssapi_check_config(const char *gss_name) { +check_config(const char *gss_name) { const char *p; krb5_context krb5_ctx; char *krb5_realm = NULL; @@ -263,7 +268,7 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, * here when we're in the acceptor role, which would let us * default the hostname and use a compiled in default service * name of "DNS", giving one less thing to configure in - * named.conf. Unfortunately, this creates a circular + * named.conf. Unfortunately, this creates a circular * dependency due to DNS-based realm lookup in at least one * GSSAPI implementation (Heimdal). Oh well. */ @@ -273,7 +278,7 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname); if (gret != GSS_S_COMPLETE) { - dst_gssapi_check_config((char *)array); + check_config((char *)array); gss_log(3, "failed gss_import_name: %s", gss_error_tostring(gret, minor, buf, @@ -306,7 +311,7 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, initiate ? "initiate" : "accept", (char *)gnamebuf.value, gss_error_tostring(gret, minor, buf, sizeof(buf))); - dst_gssapi_check_config((char *)array); + check_config((char *)array); return (ISC_R_FAILURE); } @@ -361,7 +366,7 @@ dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name, rname += 2; /* - * Find the host portion of the signer's name. We do this by + * Find the host portion of the signer's name. We do this by * searching for the first / character. We then check to make * certain the instance name is "host" * @@ -440,7 +445,7 @@ dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name, return (isc_boolean_false); /* - * Find the host portion of the signer's name. Zero out the $ so + * Find the host portion of the signer's name. Zero out the $ so * it terminates the signer's name, and skip past the @ for * the realm. * @@ -454,7 +459,7 @@ dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name, /* * Find the first . in the target name, and make it the end of - * the string. The rest of the name has to match the realm. + * the string. The rest of the name has to match the realm. */ if (name != NULL) { nname = strchr(nbuf, '.'); @@ -510,9 +515,110 @@ dst_gssapi_releasecred(gss_cred_id_t *cred) { #endif } +#ifdef GSSAPI +/* + * GSSAPI with krb5 doesn't have a way to set the default realm, as it + * doesn't offer any access to the krb5 context that it uses. The only + * way to do an nsupdate call on a realm that isn't the default realm in + * /etc/krb5.conf is to create a temporary krb5.conf and put the right + * realm in there as the default realm, then set KRB5_CONFIG to point + * at that temporary krb5.conf. This is a disgusting hack, but it is + * the best we can do with GSSAPI. + * + * To try to reduce the impact, this routine checks if the default + * realm is already correct. If it is, then we don't need to do + * anything. If not, then we create the temporary krb5.conf. + */ +static void +check_zone(dns_name_t *zone, isc_mem_t *mctx, char **tmpfile) { + krb5_context ctx; + int kret; + char *realm; + char buf[1024]; + isc_result_t ret; + FILE *fp = NULL; + char *p, *template; + + if (getenv("KRB5_CONFIG") != NULL) { + /* the user has specifically set a KRB5_CONFIG to + use. Don't override it, as they may know what they are + doing */ + return; + } + + dns_name_format(zone, buf, sizeof(buf)); + + /* gssapi wants the realm in upper case */ + for (p=buf; *p; p++) { + if (islower((int)*p)) + *p = toupper((int)*p); + } + + kret = krb5_init_context(&ctx); + if (kret != 0) + return; + + kret = krb5_get_default_realm(ctx, &realm); + if (kret == 0 && strcmp(buf, realm) == 0) { + /* the krb5.conf is correct. */ + krb5_free_context(ctx); + return; + } + + gss_log(3, "zone '%s' doesn't match KRB5 default realm '%s'", + buf, realm); + + template = isc_mem_strdup(mctx, "/tmp/krb5.conf.XXXXXX"); + if (template == NULL) { + krb5_free_context(ctx); + return; + } + + ret = isc_file_openunique(template, &fp); + if (ret != ISC_R_SUCCESS) { + krb5_free_context(ctx); + return; + } + + fprintf(fp, "[libdefaults]\n"); + fprintf(fp, "\tdefault_realm = %s\n", buf); + fprintf(fp, "\tdns_lookup_kdc = true\n"); + fclose(fp); + + setenv("KRB5_CONFIG", template, 1); + + *tmpfile = template; + + krb5_free_context(ctx); +} + +/* + * Format a gssapi error message info into a char ** on the given memory + * context. This is used to return gssapi error messages back up the + * call chain for reporting to the user. + */ +static void +gss_err_message(isc_mem_t *mctx, isc_uint32_t major, isc_uint32_t minor, + char **err_message) +{ + char buf[1024]; + char *estr; + + if (err_message == NULL || mctx == NULL) { + /* the caller doesn't want any error messages */ + return; + } + + estr = gss_error_tostring(major, minor, buf, sizeof(buf)); + if (estr) + (*err_message) = isc_mem_strdup(mctx, estr); +} +#endif + isc_result_t dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, - isc_buffer_t *outtoken, gss_ctx_id_t *gssctx) + isc_buffer_t *outtoken, gss_ctx_id_t *gssctx, + dns_name_t *zone, isc_mem_t *mctx, char **err_message) { #ifdef GSSAPI isc_region_t r; @@ -523,10 +629,15 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, isc_result_t result; gss_buffer_desc gnamebuf; unsigned char array[DNS_NAME_MAXTEXT + 1]; - char buf[1024]; + char *tmpfile = NULL; /* Client must pass us a valid gss_ctx_id_t here */ REQUIRE(gssctx != NULL); + REQUIRE(mctx != NULL); + + if (zone != NULL && mctx != NULL) { + check_zone(zone, mctx, &tmpfile); + } isc_buffer_init(&namebuf, array, sizeof(array)); name_to_gbuffer(name, &namebuf, &gnamebuf); @@ -534,6 +645,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, /* Get the name as a GSS name */ gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname); if (gret != GSS_S_COMPLETE) { + gss_err_message(mctx, gret, minor, err_message); result = ISC_R_FAILURE; goto out; } @@ -550,8 +662,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, * Note that we don't set GSS_C_SEQUENCE_FLAG as Windows DNS * servers don't like it. */ - flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG | - GSS_C_INTEG_FLAG; + flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG; gret = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, gssctx, gname, GSS_SPNEGO_MECHANISM, flags, @@ -559,9 +670,9 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, NULL, &gouttoken, &ret_flags, NULL); if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) { - gss_log(3, "Failure initiating security context"); - gss_log(3, "%s", gss_error_tostring(gret, minor, - buf, sizeof(buf))); + gss_err_message(mctx, gret, minor, err_message); + gss_log(3, "Failure initiating security context: %s", + *err_message); result = ISC_R_FAILURE; goto out; } @@ -587,12 +698,20 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, result = DNS_R_CONTINUE; out: + if (tmpfile) { + unsetenv("KRB5_CONFIG"); + isc_file_remove(tmpfile); + isc_mem_free(mctx, tmpfile); + } return (result); #else UNUSED(name); UNUSED(intoken); UNUSED(outtoken); UNUSED(gssctx); + UNUSED(zone); + UNUSED(mctx); + UNUSED(err_message); return (ISC_R_NOTIMPLEMENTED); #endif @@ -600,6 +719,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, isc_result_t dst_gssapi_acceptctx(gss_cred_id_t cred, + const char *gssapi_keytab, isc_region_t *intoken, isc_buffer_t **outtoken, gss_ctx_id_t *ctxout, dns_name_t *principal, isc_mem_t *mctx) @@ -626,6 +746,18 @@ dst_gssapi_acceptctx(gss_cred_id_t cred, else context = *ctxout; + if (gssapi_keytab) { + gret = gsskrb5_register_acceptor_identity(gssapi_keytab); + if (gret != GSS_S_COMPLETE) { + gss_log(3, "failed " + "gsskrb5_register_acceptor_identity(%s): %s", + gssapi_keytab, + gss_error_tostring(gret, minor, + buf, sizeof(buf))); + return (DNS_R_INVALIDTKEY); + } + } + gret = gss_accept_sec_context(&minor, &context, cred, &gintoken, GSS_C_NO_CHANNEL_BINDINGS, &gname, NULL, &gouttoken, NULL, NULL, NULL); @@ -717,6 +849,7 @@ dst_gssapi_acceptctx(gss_cred_id_t cred, return (result); #else UNUSED(cred); + UNUSED(gssapi_keytab); UNUSED(intoken); UNUSED(outtoken); UNUSED(ctxout); diff --git a/lib/dns/include/dns/dlz.h b/lib/dns/include/dns/dlz.h index 461d1620c6..d30c3e4f4f 100644 --- a/lib/dns/include/dns/dlz.h +++ b/lib/dns/include/dns/dlz.h @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dlz.h,v 1.9 2009/01/17 23:47:43 tbox Exp $ */ +/* $Id: dlz.h,v 1.10 2010/12/18 01:56:22 each Exp $ */ /*! \file dns/dlz.h */ @@ -87,6 +87,7 @@ #include #include #include +#include #include @@ -166,12 +167,37 @@ typedef isc_result_t * return a result code indicating the type of error. */ + +typedef isc_result_t +(*dns_dlzconfigure_t)(void *driverarg, void *dbdata, dns_view_t *view); +/*%< + * Method prototype. Drivers implementing the DLZ interface may + * optionally supply a configure method. If supplied, this will be + * called immediately after the create method is called. The driver + * may call configuration functions during the configure call + */ + + +typedef isc_boolean_t (*dns_dlzssumatch_t)(dns_name_t *signer, + dns_name_t *name, + isc_netaddr_t *tcpaddr, + dns_rdatatype_t type, + const dst_key_t *key, + void *driverarg, void *dbdata); +/*%< + * Method prototype. Drivers implementing the DLZ interface may + * optionally supply a ssumatch method. If supplied, this will be + * called to authorize update requests + */ + /*% the methods supplied by a DLZ driver */ typedef struct dns_dlzmethods { dns_dlzcreate_t create; dns_dlzdestroy_t destroy; dns_dlzfindzone_t findzone; dns_dlzallowzonexfr_t allowzonexfr; + dns_dlzconfigure_t configure; + dns_dlzssumatch_t ssumatch; } dns_dlzmethods_t; /*% information about a DLZ driver */ @@ -183,12 +209,16 @@ struct dns_dlzimplementation { ISC_LINK(dns_dlzimplementation_t) link; }; -/*% an instance of a DLZ driver */ +typedef isc_result_t (*dlzconfigure_callback_t)(dns_view_t *, dns_zone_t *); + +/*% An instance of a DLZ driver */ struct dns_dlzdb { unsigned int magic; isc_mem_t *mctx; dns_dlzimplementation_t *implementation; void *dbdata; + dlzconfigure_callback_t configure_callback; + dns_ssutable_t *ssutable; }; @@ -285,6 +315,30 @@ dns_dlzunregister(dns_dlzimplementation_t **dlzimp); * is called. */ + +isc_result_t +dns_dlz_writeablezone(dns_view_t *view, const char *zone_name); + +/*%< + * creates a writeable DLZ zone. Must be called from within the + * configure() method of a DLZ driver. + */ + + +isc_result_t +dns_dlzconfigure(dns_view_t *view, dlzconfigure_callback_t callback); +/*%< + * call a DLZ drivers configure method, if supplied + */ + +isc_boolean_t +dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase, + dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr, + dns_rdatatype_t type, const dst_key_t *key); +/*%< + * call a DLZ drivers ssumatch method, if supplied. Otherwise return ISC_FALSE + */ + ISC_LANG_ENDDECLS #endif /* DLZ_H */ diff --git a/lib/dns/include/dns/sdlz.h b/lib/dns/include/dns/sdlz.h index c452f463fc..39ccd30a53 100644 --- a/lib/dns/include/dns/sdlz.h +++ b/lib/dns/include/dns/sdlz.h @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdlz.h,v 1.9 2009/01/17 23:47:43 tbox Exp $ */ +/* $Id: sdlz.h,v 1.10 2010/12/18 01:56:22 each Exp $ */ /*! \file dns/sdlz.h */ @@ -74,11 +74,10 @@ typedef struct dns_sdlzlookup dns_sdlzlookup_t; /* A simple DLZ database traversal in progress. */ typedef struct dns_sdlzallnodes dns_sdlzallnodes_t; - -typedef isc_result_t -(*dns_sdlzallnodesfunc_t)(const char *zone, void *driverarg, void *dbdata, - dns_sdlzallnodes_t *allnodes); - +typedef isc_result_t (*dns_sdlzallnodesfunc_t)(const char *zone, + void *driverarg, + void *dbdata, + dns_sdlzallnodes_t *allnodes); /*%< * Method prototype. Drivers implementing the SDLZ interface may * supply an all nodes method. This method is called when the DNS @@ -92,9 +91,9 @@ typedef isc_result_t * does not have to implement an all nodes method. */ -typedef isc_result_t -(*dns_sdlzallowzonexfr_t)(void *driverarg, void *dbdata, const char *name, - const char *client); +typedef isc_result_t (*dns_sdlzallowzonexfr_t)(void *driverarg, + void *dbdata, const char *name, + const char *client); /*%< * Method prototype. Drivers implementing the SDLZ interface may @@ -117,9 +116,9 @@ typedef isc_result_t * error. */ -typedef isc_result_t -(*dns_sdlzauthorityfunc_t)(const char *zone, void *driverarg, void *dbdata, - dns_sdlzlookup_t *lookup); +typedef isc_result_t (*dns_sdlzauthorityfunc_t)(const char *zone, + void *driverarg, void *dbdata, + dns_sdlzlookup_t *lookup); /*%< * Method prototype. Drivers implementing the SDLZ interface may @@ -131,9 +130,9 @@ typedef isc_result_t * method. */ -typedef isc_result_t -(*dns_sdlzcreate_t)(const char *dlzname, unsigned int argc, char *argv[], - void *driverarg, void **dbdata); +typedef isc_result_t (*dns_sdlzcreate_t)(const char *dlzname, + unsigned int argc, char *argv[], + void *driverarg, void **dbdata); /*%< * Method prototype. Drivers implementing the SDLZ interface may @@ -142,8 +141,7 @@ typedef isc_result_t * does not have to implement a create method. */ -typedef void -(*dns_sdlzdestroy_t)(void *driverarg, void *dbdata); +typedef void (*dns_sdlzdestroy_t)(void *driverarg, void *dbdata); /*%< * Method prototype. Drivers implementing the SDLZ interface may @@ -198,6 +196,87 @@ typedef isc_result_t * lookup method. */ +typedef isc_result_t (*dns_sdlznewversion_t)(const char *zone, + void *driverarg, void *dbdata, + void **versionp); +/*%< + * Method prototype. Drivers implementing the SDLZ interface may + * supply a newversion method. This method is called to start a + * write transaction on a zone and should only be implemented by + * writeable backends. + * When implemented, the driver should create a new transaction, and + * fill *versionp with a pointer to the transaction state. The + * closeversion function will be called to close the transaction. + */ + +typedef void (*dns_sdlzcloseversion_t)(const char *zone, isc_boolean_t commit, + void *driverarg, void *dbdata, + void **versionp); +/*%< + * Method prototype. Drivers implementing the SDLZ interface must + * supply a closeversion method if they supply a newversion method. + * When implemented, the driver should close the given transaction, + * committing changes if 'commit' is ISC_TRUE. If 'commit' is not true + * then all changes should be discarded and the database rolled back. + * If the call is successful then *versionp should be set to NULL + */ + +typedef isc_result_t (*dns_sdlzconfigure_t)(dns_view_t *view, void *driverarg, + void *dbdata); +/*%< + * Method prototype. Drivers implementing the SDLZ interface may + * supply a configure method. When supplied, it will be called + * immediately after the create method to give the driver a chance + * to configure writeable zones + */ + + +typedef isc_boolean_t (*dns_sdlzssumatch_t)(const char *signer, + const char *name, + const char *tcpaddr, + const char *type, + const char *key, + uint32_t keydatalen, + uint8_t *keydata, + void *driverarg, + void *dbdata); + +/*%< + * Method prototype. Drivers implementing the SDLZ interface may + * supply a ssumatch method. If supplied, then ssumatch will be + * called to authorize any zone updates. The driver should return + * ISC_TRUE to allow the update, and ISC_FALSE to deny it. For a DLZ + * controlled zone, this is the only access control on updates. + */ + + +typedef isc_result_t (*dns_sdlzmodrdataset_t)(const char *name, + const char *rdatastr, + void *driverarg, void *dbdata, + void *version); +/*%< + * Method prototype. Drivers implementing the SDLZ interface may + * supply addrdataset and subtractrdataset methods. If supplied, then these + * will be called when rdatasets are added/subtracted during + * updates. The version parameter comes from a call to the sdlz + * newversion() method from the driver. The rdataset parameter is a + * linearise string representation of the rdataset change. The format + * is the same as used by dig when displaying records. The fields are + * tab delimited. + */ + +typedef isc_result_t (*dns_sdlzdelrdataset_t)(const char *name, + const char *type, + void *driverarg, void *dbdata, + void *version); +/*%< + * Method prototype. Drivers implementing the SDLZ interface may + * supply a delrdataset method. If supplied, then this + * function will be called when rdatasets are deleted during + * updates. The call should remove all rdatasets of the given type for + * the specified name. + */ + typedef struct dns_sdlzmethods { dns_sdlzcreate_t create; dns_sdlzdestroy_t destroy; @@ -206,6 +285,13 @@ typedef struct dns_sdlzmethods { dns_sdlzauthorityfunc_t authority; dns_sdlzallnodesfunc_t allnodes; dns_sdlzallowzonexfr_t allowzonexfr; + dns_sdlznewversion_t newversion; + dns_sdlzcloseversion_t closeversion; + dns_sdlzconfigure_t configure; + dns_sdlzssumatch_t ssumatch; + dns_sdlzmodrdataset_t addrdataset; + dns_sdlzmodrdataset_t subtractrdataset; + dns_sdlzdelrdataset_t delrdataset; } dns_sdlzmethods_t; isc_result_t @@ -261,6 +347,14 @@ dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname, */ +isc_result_t +dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass, + dns_name_t *name, dns_db_t **dbp); +/*%< + * Create the database pointers for a writeable SDLZ zone + */ + + ISC_LANG_ENDDECLS #endif /* SDLZ_H */ diff --git a/lib/dns/include/dns/ssu.h b/lib/dns/include/dns/ssu.h index f013bd03ed..7e412295b7 100644 --- a/lib/dns/include/dns/ssu.h +++ b/lib/dns/include/dns/ssu.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ssu.h,v 1.24 2008/01/18 23:46:58 tbox Exp $ */ +/* $Id: ssu.h,v 1.25 2010/12/18 01:56:22 each Exp $ */ #ifndef DNS_SSU_H #define DNS_SSU_H 1 @@ -25,6 +25,7 @@ #include #include +#include ISC_LANG_BEGINDECLS @@ -40,7 +41,8 @@ ISC_LANG_BEGINDECLS #define DNS_SSUMATCHTYPE_SUBDOMAINKRB5 9 #define DNS_SSUMATCHTYPE_TCPSELF 10 #define DNS_SSUMATCHTYPE_6TO4SELF 11 -#define DNS_SSUMATCHTYPE_MAX 11 /* max value */ +#define DNS_SSUMATCHTYPE_DLZ 12 +#define DNS_SSUMATCHTYPE_MAX 12 /* max value */ isc_result_t dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table); @@ -57,6 +59,16 @@ dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table); *\li ISC_R_NOMEMORY */ +isc_result_t +dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep, + dns_dlzdb_t *dlzdatabase); +/*%< + * Create an SSU table that contains a dlzdatabase pointer, and a + * single rule with matchtype DNS_SSUMATCHTYPE_DLZ. This type of SSU + * table is used by writeable DLZ drivers to offload authorization for + * updates to the driver. + */ + void dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp); /*%< @@ -120,7 +132,7 @@ dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant, isc_boolean_t dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr, - dns_rdatatype_t type); + dns_rdatatype_t type, const dst_key_t *key); /*%< * Checks that the attempted update of (name, type) is allowed according * to the rules specified in the simple-secure-update rule table. If diff --git a/lib/dns/include/dns/tkey.h b/lib/dns/include/dns/tkey.h index 6a002a9ae5..2801c37ef8 100644 --- a/lib/dns/include/dns/tkey.h +++ b/lib/dns/include/dns/tkey.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tkey.h,v 1.28 2009/01/17 23:47:43 tbox Exp $ */ +/* $Id: tkey.h,v 1.29 2010/12/18 01:56:22 each Exp $ */ #ifndef DNS_TKEY_H #define DNS_TKEY_H 1 @@ -44,6 +44,7 @@ struct dns_tkeyctx { gss_cred_id_t gsscred; isc_mem_t *mctx; isc_entropy_t *ectx; + char *gssapi_keytab; }; isc_result_t @@ -123,7 +124,8 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name, isc_result_t dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, isc_buffer_t *intoken, isc_uint32_t lifetime, - gss_ctx_id_t *context, isc_boolean_t win2k); + gss_ctx_id_t *context, isc_boolean_t win2k, + dns_name_t *zone, isc_mem_t *mctx, char **err_message); /*%< * Builds a query containing a TKEY that will generate a GSSAPI context. * The key is requested to have the specified lifetime (in seconds). @@ -141,6 +143,7 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, *\li ISC_R_SUCCESS msg was successfully updated to include the * query to be sent *\li other an error occurred while building the message + *\li *err_message optional error message */ @@ -187,7 +190,7 @@ isc_result_t dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, dns_name_t *gname, gss_ctx_id_t *context, isc_buffer_t *outtoken, dns_tsigkey_t **outkey, - dns_tsig_keyring_t *ring); + dns_tsig_keyring_t *ring, char **err_message); /*%< * XXX */ @@ -211,12 +214,12 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg, * component of the query or response */ - isc_result_t dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, dns_name_t *server, gss_ctx_id_t *context, dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring, - isc_boolean_t win2k); + isc_boolean_t win2k, dns_name_t *zone, + char **err_message); /* * Client side negotiation of GSS-TSIG. Process the response diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index d4c90473e0..de16129325 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.181 2010/12/16 23:47:08 tbox Exp $ */ +/* $Id: zone.h,v 1.182 2010/12/18 01:56:22 each Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -42,7 +42,8 @@ typedef enum { dns_zone_slave, dns_zone_stub, dns_zone_staticstub, - dns_zone_key + dns_zone_key, + dns_zone_dlz } dns_zonetype_t; #define DNS_ZONEOPT_SERVERS 0x00000001U /*%< perform server checks */ @@ -1845,6 +1846,12 @@ dns_zone_getadded(dns_zone_t *zone); * \li 'zone' to be valid. */ +isc_result_t +dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db); +/*% + * Load the origin names for a writeable DLZ database. + */ + ISC_LANG_ENDDECLS #endif /* DNS_ZONE_H */ diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h index 4ddfaf36b9..8ee9da686d 100644 --- a/lib/dns/include/dst/dst.h +++ b/lib/dns/include/dst/dst.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dst.h,v 1.27 2010/12/09 04:31:57 tbox Exp $ */ +/* $Id: dst.h,v 1.28 2010/12/18 01:56:22 each Exp $ */ #ifndef DST_DST_H #define DST_DST_H 1 @@ -470,7 +470,7 @@ dst_key_getgssctx(const dst_key_t *key); isc_result_t dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, - dst_key_t **keyp); + dst_key_t **keyp, isc_region_t *intoken); /*%< * Converts a GSSAPI opaque context id into a DST key. * @@ -831,12 +831,21 @@ dst_key_setprivateformat(dst_key_t *key, int major, int minor); #define DST_KEY_FORMATSIZE (DNS_NAME_FORMATSIZE + DNS_SECALG_FORMATSIZE + 7) void -dst_key_format(dst_key_t *key, char *cp, unsigned int size); +dst_key_format(const dst_key_t *key, char *cp, unsigned int size); /*%< * Write the uniquely identifying information about the key (name, * algorithm, key ID) into a string 'cp' of size 'size'. */ + +isc_buffer_t * +dst_key_tkeytoken(const dst_key_t *key); +/*%< + * Return the token from the TKEY request, if any. If this key was + * not negotiated via TKEY, return NULL. + */ + + ISC_LANG_ENDDECLS #endif /* DST_DST_H */ diff --git a/lib/dns/include/dst/gssapi.h b/lib/dns/include/dst/gssapi.h index 31e454a4a1..3f6b5e462d 100644 --- a/lib/dns/include/dst/gssapi.h +++ b/lib/dns/include/dst/gssapi.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: gssapi.h,v 1.11 2009/01/17 23:47:43 tbox Exp $ */ +/* $Id: gssapi.h,v 1.12 2010/12/18 01:56:22 each Exp $ */ #ifndef DST_GSSAPI_H #define DST_GSSAPI_H 1 @@ -34,8 +34,10 @@ * MSVC does not like macros in #include lines. */ #include +#include #else #include ISC_PLATFORM_GSSAPIHEADER +#include ISC_PLATFORM_GSSAPI_KRB5_HEADER #endif #ifndef GSS_SPNEGO_MECHANISM #define GSS_SPNEGO_MECHANISM ((void*)0) @@ -90,7 +92,8 @@ dst_gssapi_releasecred(gss_cred_id_t *cred); isc_result_t dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, - isc_buffer_t *outtoken, gss_ctx_id_t *gssctx); + isc_buffer_t *outtoken, gss_ctx_id_t *gssctx, + dns_name_t *zone, isc_mem_t *mctx, char **err_message); /* * Initiates a GSS context. * @@ -108,10 +111,12 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, * ISC_R_SUCCESS msg was successfully updated to include the * query to be sent * other an error occurred while building the message + * *err_message optional error message */ isc_result_t dst_gssapi_acceptctx(gss_cred_id_t cred, + const char *gssapi_keytab, isc_region_t *intoken, isc_buffer_t **outtoken, gss_ctx_id_t *context, dns_name_t *principal, isc_mem_t *mctx); diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index 9c553c8010..3304321963 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdlz.c,v 1.25 2010/08/16 04:46:16 marka Exp $ */ +/* $Id: sdlz.c,v 1.26 2010/12/18 01:56:22 each Exp $ */ /*! \file */ @@ -108,6 +108,8 @@ struct dns_sdlz_db { isc_mutex_t refcnt_lock; /* Locked */ unsigned int references; + dns_dbversion_t *future_version; + int dummy_version; }; struct dns_sdlzlookup { @@ -164,8 +166,6 @@ typedef struct sdlz_rdatasetiter { /* This is a reasonable value */ #define SDLZ_DEFAULT_TTL (60 * 60 * 24) -static int dummy; - #ifdef __COVERITY__ #define MAYBE_LOCK(imp) LOCK(&imp->driverlock) #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock) @@ -225,11 +225,22 @@ static dns_dbiteratormethods_t dbiterator_methods = { * Utility functions */ -/*% Converts the input string to lowercase, in place. */ +/* + * Log a message at the given level + */ +static void +sdlz_log(int level, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level), + fmt, ap); + va_end(ap); +} +/*% Converts the input string to lowercase, in place. */ static void dns_sdlz_tolower(char *str) { - unsigned int len = strlen(str); unsigned int i; @@ -237,7 +248,6 @@ dns_sdlz_tolower(char *str) { if (str[i] >= 'A' && str[i] <= 'Z') str[i] += 32; } - } static inline unsigned int @@ -381,43 +391,79 @@ dump(dns_db_t *db, dns_dbversion_t *version, const char *filename, static void currentversion(dns_db_t *db, dns_dbversion_t **versionp) { + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + REQUIRE(VALID_SDLZDB(sdlz)); REQUIRE(versionp != NULL && *versionp == NULL); - UNUSED(db); - - *versionp = (void *) &dummy; + *versionp = (void *) &sdlz->dummy_version; return; } static isc_result_t newversion(dns_db_t *db, dns_dbversion_t **versionp) { - UNUSED(db); - UNUSED(versionp); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + char origin[DNS_NAME_MAXTEXT + 1]; + isc_result_t result; - return (ISC_R_NOTIMPLEMENTED); + REQUIRE(VALID_SDLZDB(sdlz)); + + if (sdlz->dlzimp->methods->newversion == NULL) + return (ISC_R_NOTIMPLEMENTED); + + dns_name_format(&sdlz->common.origin, origin, sizeof(origin)); + + result = sdlz->dlzimp->methods->newversion(origin, + sdlz->dlzimp->driverarg, + sdlz->dbdata, versionp); + if (result != ISC_R_SUCCESS) { + sdlz_log(ISC_LOG_ERROR, + "sdlz newversion on origin %s failed : %s", + origin, isc_result_totext(result)); + return (result); + } + + sdlz->future_version = *versionp; + return (ISC_R_SUCCESS); } static void attachversion(dns_db_t *db, dns_dbversion_t *source, dns_dbversion_t **targetp) { - REQUIRE(source != NULL && source == (void *) &dummy); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + + REQUIRE(VALID_SDLZDB(sdlz)); + REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version); - UNUSED(db); - UNUSED(source); - UNUSED(targetp); *targetp = source; } static void closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { - REQUIRE(versionp != NULL && *versionp == (void *) &dummy); - REQUIRE(commit == ISC_FALSE); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + char origin[DNS_NAME_MAXTEXT + 1]; - UNUSED(db); - UNUSED(commit); + REQUIRE(VALID_SDLZDB(sdlz)); + REQUIRE(versionp != NULL); - *versionp = NULL; + if (*versionp == (void *)&sdlz->dummy_version) { + *versionp = NULL; + return; + } + + REQUIRE(*versionp == sdlz->future_version); + REQUIRE(sdlz->dlzimp->methods->closeversion != NULL); + + dns_name_format(&sdlz->common.origin, origin, sizeof(origin)); + + sdlz->dlzimp->methods->closeversion(origin, commit, + sdlz->dlzimp->driverarg, + sdlz->dbdata, versionp); + if (*versionp != NULL) + sdlz_log(ISC_LOG_ERROR, + "sdlz closeversion on origin %s failed", origin); + + sdlz->future_version = NULL; } static isc_result_t @@ -506,11 +552,11 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, dns_sdlzauthorityfunc_t authority; REQUIRE(VALID_SDLZDB(sdlz)); - REQUIRE(create == ISC_FALSE); REQUIRE(nodep != NULL && *nodep == NULL); - UNUSED(name); - UNUSED(create); + if (sdlz->dlzimp->methods->newversion == NULL) { + REQUIRE(create == ISC_FALSE); + } isc_buffer_init(&b, namestr, sizeof(namestr)); if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) { @@ -558,7 +604,7 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, * if the host (namestr) was not found, try to lookup a * "wildcard" host. */ - if (result != ISC_R_SUCCESS) { + if (result != ISC_R_SUCCESS && !create) { result = sdlz->dlzimp->methods->lookup(zonestr, "*", sdlz->dlzimp->driverarg, sdlz->dbdata, node); @@ -566,7 +612,7 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, MAYBE_UNLOCK(sdlz->dlzimp); - if (result != ISC_R_SUCCESS && !isorigin) { + if (result != ISC_R_SUCCESS && !isorigin && !create) { destroynode(node); return (result); } @@ -584,6 +630,23 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, } } + if (node->name == NULL) { + node->name = isc_mem_get(sdlz->common.mctx, + sizeof(dns_name_t)); + if (node->name == NULL) { + destroynode(node); + return (ISC_R_NOMEMORY); + } + dns_name_init(node->name, NULL); + result = dns_name_dup(name, sdlz->common.mctx, node->name); + if (result != ISC_R_SUCCESS) { + isc_mem_put(sdlz->common.mctx, node->name, + sizeof(dns_name_t)); + destroynode(node); + return (result); + } + } + *nodep = node; return (ISC_R_SUCCESS); } @@ -778,7 +841,7 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, REQUIRE(VALID_SDLZDB(sdlz)); REQUIRE(nodep == NULL || *nodep == NULL); - REQUIRE(version == NULL || version == (void *) &dummy); + REQUIRE(version == NULL || version == (void*)&sdlz->dummy_version); UNUSED(options); UNUSED(sdlz); @@ -920,9 +983,14 @@ static isc_result_t allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) { + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) db; sdlz_rdatasetiter_t *iterator; - REQUIRE(version == NULL || version == &dummy); + REQUIRE(VALID_SDLZDB(sdlz)); + + REQUIRE(version == NULL || + version == (void*)&sdlz->dummy_version || + version == sdlz->future_version); UNUSED(version); UNUSED(now); @@ -944,48 +1012,140 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, return (ISC_R_SUCCESS); } +static isc_result_t +modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + dns_rdataset_t *rdataset, unsigned int options, + dns_sdlzmodrdataset_t mod_function) +{ + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + dns_master_style_t *style = NULL; + isc_result_t result; + isc_buffer_t *buffer = NULL; + isc_mem_t *mctx; + dns_sdlznode_t *sdlznode; + char *rdatastr = NULL; + char name[DNS_NAME_MAXTEXT + 1]; + + REQUIRE(VALID_SDLZDB(sdlz)); + + if (mod_function == NULL) + return (ISC_R_NOTIMPLEMENTED); + + sdlznode = (dns_sdlznode_t *)node; + + UNUSED(options); + + dns_name_format(sdlznode->name, name, sizeof(name)); + + mctx = sdlz->common.mctx; + + result = isc_buffer_allocate(mctx, &buffer, 1024); + if (result != ISC_R_SUCCESS) + return (result); + + result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, mctx); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_master_rdatasettotext(sdlznode->name, rdataset, + style, buffer); + if (result != ISC_R_SUCCESS) + goto cleanup; + + if (isc_buffer_usedlength(buffer) < 1) { + result = ISC_R_BADADDRESSFORM; + goto cleanup; + } + + rdatastr = isc_buffer_base(buffer); + if (rdatastr == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + rdatastr[isc_buffer_usedlength(buffer) - 1] = 0; + + MAYBE_LOCK(sdlz->dlzimp); + result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg, + sdlz->dbdata, version); + MAYBE_UNLOCK(sdlz->dlzimp); + +cleanup: + isc_buffer_free(&buffer); + if (style != NULL) + dns_master_styledestroy(&style, mctx); + + return (result); +} + static isc_result_t addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, dns_rdataset_t *addedrdataset) { - UNUSED(db); - UNUSED(node); - UNUSED(version); - UNUSED(now); - UNUSED(rdataset); - UNUSED(options); - UNUSED(addedrdataset); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + isc_result_t result; - return (ISC_R_NOTIMPLEMENTED); + UNUSED(now); + UNUSED(addedrdataset); + REQUIRE(VALID_SDLZDB(sdlz)); + + if (sdlz->dlzimp->methods->addrdataset == NULL) + return (ISC_R_NOTIMPLEMENTED); + + result = modrdataset(db, node, version, rdataset, options, + sdlz->dlzimp->methods->addrdataset); + return (result); } + static isc_result_t subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdataset_t *rdataset, unsigned int options, dns_rdataset_t *newrdataset) { - UNUSED(db); - UNUSED(node); - UNUSED(version); - UNUSED(rdataset); - UNUSED(options); - UNUSED(newrdataset); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + isc_result_t result; - return (ISC_R_NOTIMPLEMENTED); + UNUSED(newrdataset); + REQUIRE(VALID_SDLZDB(sdlz)); + + if (sdlz->dlzimp->methods->subtractrdataset == NULL) { + return (ISC_R_NOTIMPLEMENTED); + } + + result = modrdataset(db, node, version, rdataset, options, + sdlz->dlzimp->methods->subtractrdataset); + return (result); } static isc_result_t deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdatatype_t type, dns_rdatatype_t covers) { - UNUSED(db); - UNUSED(node); - UNUSED(version); - UNUSED(type); + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + char name[DNS_NAME_MAXTEXT + 1]; + char b_type[DNS_RDATATYPE_FORMATSIZE]; + dns_sdlznode_t *sdlznode; + isc_result_t result; + UNUSED(covers); - return (ISC_R_NOTIMPLEMENTED); + REQUIRE(VALID_SDLZDB(sdlz)); + + if (sdlz->dlzimp->methods->delrdataset == NULL) + return (ISC_R_NOTIMPLEMENTED); + + sdlznode = (dns_sdlznode_t *)node; + dns_name_format(sdlznode->name, name, sizeof(name)); + dns_rdatatype_format(type, b_type, sizeof(b_type)); + + MAYBE_LOCK(sdlz->dlzimp); + result = sdlz->dlzimp->methods->delrdataset(name, b_type, + sdlz->dlzimp->driverarg, + sdlz->dbdata, version); + MAYBE_UNLOCK(sdlz->dlzimp); + + return (result); } static isc_boolean_t @@ -1021,6 +1181,26 @@ settask(dns_db_t *db, isc_task_t *task) { } +/* + * getoriginnode() is used by the update code to find the + * dns_rdatatype_dnskey record for a zone + */ +static isc_result_t +getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { + dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; + isc_result_t result; + + REQUIRE(VALID_SDLZDB(sdlz)); + if (sdlz->dlzimp->methods->newversion == NULL) + return (ISC_R_NOTIMPLEMENTED); + + result = findnode(db, &sdlz->common.origin, ISC_FALSE, nodep); + if (result != ISC_R_SUCCESS) + sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed : %s", + isc_result_totext(result)); + return (result); +} + static dns_dbmethods_t sdlzdb_methods = { attach, detach, @@ -1049,7 +1229,7 @@ static dns_dbmethods_t sdlzdb_methods = { ispersistent, overmem, settask, - NULL, + getoriginnode, NULL, NULL, NULL, @@ -1371,9 +1551,7 @@ dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc, isc_result_t result = ISC_R_NOTFOUND; /* Write debugging message to log */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), - "Loading SDLZ driver."); + sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver."); /* * Performs checks to make sure data is as we expect it to be. @@ -1395,15 +1573,12 @@ dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc, /* Write debugging message to log */ if (result == ISC_R_SUCCESS) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), - "SDLZ driver loaded successfully."); + sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully."); } else { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, - "SDLZ driver failed to load."); + sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load."); } + sdlz_log(ISC_LOG_INFO, "%s: done", __FUNCTION__); return (result); } @@ -1414,9 +1589,7 @@ dns_sdlzdestroy(void *driverdata, void **dbdata) dns_sdlzimplementation_t *imp; /* Write debugging message to log */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), - "Unloading SDLZ driver."); + sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver."); imp = driverdata; @@ -1472,11 +1645,97 @@ dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx, return (result); } + +static isc_result_t +dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view) +{ + isc_result_t result; + dns_sdlzimplementation_t *imp; + + REQUIRE(driverarg != NULL); + + imp = (dns_sdlzimplementation_t *) driverarg; + + /* Call SDLZ driver's configure method */ + if (imp->methods->configure != NULL) { + MAYBE_LOCK(imp); + result = imp->methods->configure(view, imp->driverarg, dbdata); + MAYBE_UNLOCK(imp); + } else { + result = ISC_R_SUCCESS; + } + + return (result); +} + +static isc_boolean_t +dns_sdlzssumatch(dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr, + dns_rdatatype_t type, const dst_key_t *key, void *driverarg, + void *dbdata) +{ + dns_sdlzimplementation_t *imp; + char b_signer[DNS_NAME_FORMATSIZE]; + char b_name[DNS_NAME_FORMATSIZE]; + char b_addr[ISC_NETADDR_FORMATSIZE]; + char b_type[DNS_RDATATYPE_FORMATSIZE]; + char b_key[DST_KEY_FORMATSIZE]; + isc_buffer_t *tkey_token; + isc_region_t token_region; + uint32_t token_len = 0; + isc_boolean_t ret; + + REQUIRE(driverarg != NULL); + + imp = (dns_sdlzimplementation_t *) driverarg; + if (imp->methods->ssumatch == NULL) + return (ISC_FALSE); + + /* + * Format the request elements. sdlz operates on strings, not + * structures + */ + if (signer) + dns_name_format(signer, b_signer, sizeof(b_signer)); + else + b_signer[0] = 0; + + dns_name_format(name, b_name, sizeof(b_name)); + + if (tcpaddr) + isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr)); + else + b_addr[0] = 0; + + dns_rdatatype_format(type, b_type, sizeof(b_type)); + + if (key) + dst_key_format(key, b_key, sizeof(b_key)); + else + b_key[0] = 0; + + tkey_token = dst_key_tkeytoken(key); + + if (tkey_token) { + isc_buffer_region(tkey_token, &token_region); + token_len = token_region.length; + } + + MAYBE_LOCK(imp); + ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key, + token_len, + token_len ? token_region.base : NULL, + imp->driverarg, dbdata); + MAYBE_UNLOCK(imp); + return (ret); +} + static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate, dns_sdlzdestroy, dns_sdlzfindzone, - dns_sdlzallowzonexfr + dns_sdlzallowzonexfr, + dns_sdlzconfigure, + dns_sdlzssumatch }; /* @@ -1530,8 +1789,16 @@ dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl, ISC_LINK_INIT(rdatalist, link); ISC_LIST_APPEND(lookup->lists, rdatalist, link); } else - if (rdatalist->ttl != ttl) - return (DNS_R_BADTTL); + if (rdatalist->ttl > ttl) { + /* + * BIND9 doesn't enforce all RRs in an RRset + * having the same TTL, as per RFC 2136, + * section 7.12. If a DLZ backend has + * different TTLs, then the best + * we can do is return the lowest. + */ + rdatalist->ttl = ttl; + } rdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); if (rdata == NULL) @@ -1694,9 +1961,7 @@ dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods, DNS_SDLZFLAG_THREADSAFE)) == 0); /* Write debugging message to log */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), - "Registering SDLZ driver '%s'", drivername); + sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername); /* * Allocate memory for a sdlz_implementation object. Error if @@ -1769,9 +2034,7 @@ dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) { isc_mem_t *mctx; /* Write debugging message to log */ - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), - "Unregistering SDLZ driver."); + sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver."); /* * Performs checks to make sure data is as we expect it to be. @@ -1797,3 +2060,16 @@ dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) { *sdlzimp = NULL; } + + +isc_result_t +dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass, + dns_name_t *name, dns_db_t **dbp) +{ + isc_result_t result; + + result = dns_sdlzcreateDBP(dlzdatabase->mctx, + dlzdatabase->implementation->driverarg, + dlzdatabase->dbdata, name, rdclass, dbp); + return (result); +} diff --git a/lib/dns/spnego.c b/lib/dns/spnego.c index eda3d51e6a..cef3243b62 100644 --- a/lib/dns/spnego.c +++ b/lib/dns/spnego.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: spnego.c,v 1.12 2009/07/21 06:53:09 marka Exp $ */ +/* $Id: spnego.c,v 1.13 2010/12/18 01:56:22 each Exp $ */ /*! \file * \brief @@ -172,6 +172,8 @@ /* asn1_err.h */ /* Generated from ../../../lib/asn1/asn1_err.et */ +#ifndef ERROR_TABLE_BASE_asn1 +/* these may be brought in already via gssapi_krb5.h */ typedef enum asn1_error_number { ASN1_BAD_TIMEFORMAT = 1859794432, ASN1_MISSING_FIELD = 1859794433, @@ -186,6 +188,7 @@ typedef enum asn1_error_number { } asn1_error_number; #define ERROR_TABLE_BASE_asn1 1859794432 +#endif #define __asn1_common_definitions__ diff --git a/lib/dns/ssu.c b/lib/dns/ssu.c index ab692420a1..3dd2ee4dc8 100644 --- a/lib/dns/ssu.c +++ b/lib/dns/ssu.c @@ -17,7 +17,7 @@ /*! \file */ /* - * $Id: ssu.c,v 1.34 2008/01/18 23:46:58 tbox Exp $ + * $Id: ssu.c,v 1.35 2010/12/18 01:56:22 each Exp $ * Principal Author: Brian Wellington */ @@ -30,11 +30,13 @@ #include #include +#include #include #include #include #include +#include #define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T') #define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC) @@ -59,6 +61,7 @@ struct dns_ssutable { isc_mem_t *mctx; unsigned int references; isc_mutex_t lock; + dns_dlzdb_t *dlzdatabase; ISC_LIST(dns_ssurule_t) rules; }; @@ -345,7 +348,8 @@ stf_from_address(dns_name_t *stfself, isc_netaddr_t *tcpaddr) { isc_boolean_t dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr, - dns_rdatatype_t type) + dns_rdatatype_t type, + const dst_key_t *key) { dns_ssurule_t *rule; unsigned int i; @@ -483,10 +487,21 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer, if (!dns_name_equal(stfself, name)) continue; break; + case DNS_SSUMATCHTYPE_DLZ: + if (!dns_dlz_ssumatch(table->dlzdatabase, signer, + name, tcpaddr, type, key)) + continue; + break; } if (rule->ntypes == 0) { - if (!isusertype(type)) + /* + * If this is a DLZ rule, then the DLZ ssu + * checks will have already checked + * the type. + */ + if (rule->matchtype != DNS_SSUMATCHTYPE_DLZ && + !isusertype(type)) continue; } else { for (i = 0; i < rule->ntypes; i++) { @@ -550,3 +565,42 @@ dns_ssutable_nextrule(dns_ssurule_t *rule, dns_ssurule_t **nextrule) { *nextrule = ISC_LIST_NEXT(rule, link); return (*nextrule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE); } + +/* + * Create a specialised SSU table that points at an external DLZ database + */ +isc_result_t +dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep, + dns_dlzdb_t *dlzdatabase) +{ + isc_result_t result; + dns_ssurule_t *rule; + dns_ssutable_t *table = NULL; + + REQUIRE(tablep != NULL && *tablep == NULL); + + result = dns_ssutable_create(mctx, &table); + if (result != ISC_R_SUCCESS) + return (result); + + table->dlzdatabase = dlzdatabase; + + rule = isc_mem_get(table->mctx, sizeof(dns_ssurule_t)); + if (rule == NULL) { + dns_ssutable_detach(&table); + return (ISC_R_NOMEMORY); + } + + rule->identity = NULL; + rule->name = NULL; + rule->types = NULL; + rule->grant = ISC_TRUE; + rule->matchtype = DNS_SSUMATCHTYPE_DLZ; + rule->ntypes = 0; + rule->types = NULL; + rule->magic = SSURULEMAGIC; + + ISC_LIST_INITANDAPPEND(table->rules, rule, link); + *tablep = table; + return (ISC_R_SUCCESS); +} diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c index 16f425f8c6..8c92c785ba 100644 --- a/lib/dns/tkey.c +++ b/lib/dns/tkey.c @@ -16,7 +16,7 @@ */ /* - * $Id: tkey.c,v 1.96 2010/12/09 00:54:34 marka Exp $ + * $Id: tkey.c,v 1.97 2010/12/18 01:56:22 each Exp $ */ /*! \file */ #include @@ -99,6 +99,7 @@ dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp) tctx->dhkey = NULL; tctx->domain = NULL; tctx->gsscred = NULL; + tctx->gssapi_keytab = NULL; *tctxp = tctx; return (ISC_R_SUCCESS); @@ -121,6 +122,9 @@ dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp) { dns_name_free(tctx->domain, mctx); isc_mem_put(mctx, tctx->domain, sizeof(dns_name_t)); } + if (tctx->gssapi_keytab != NULL) { + isc_mem_free(mctx, tctx->gssapi_keytab); + } if (tctx->gsscred != NULL) dst_gssapi_releasecred(&tctx->gsscred); isc_entropy_detach(&tctx->ectx); @@ -430,9 +434,18 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin, isc_buffer_t *outtoken = NULL; gss_ctx_id_t gss_ctx = NULL; - if (tctx->gsscred == NULL) - return (ISC_R_NOPERM); - + /* + * You have to define either a gss credential (principal) to + * accept with tkey-gssapi-credential, or you have to + * configure a specific keytab (with tkey-gssapi-keytab) in + * order to use gsstkey + */ + if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) { + tkey_log("process_gsstkey(): no tkey-gssapi-credential " + "or tkey-gssapi-keytab configured"); + return (ISC_R_NOPERM); + } + if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) && !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) { tkeyout->error = dns_tsigerror_badalg; @@ -454,7 +467,11 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin, dns_fixedname_init(&principal); - result = dst_gssapi_acceptctx(tctx->gsscred, &intoken, + /* + * Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set + */ + result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab, + &intoken, &outtoken, &gss_ctx, dns_fixedname_name(&principal), tctx->mctx); @@ -479,7 +496,8 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin, #endif isc_uint32_t expire; - RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx, &dstkey)); + RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx, + &dstkey, &intoken)); /* * Limit keys to 1 hour or the context's lifetime whichever * is smaller. @@ -984,7 +1002,8 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name, isc_result_t dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, isc_buffer_t *intoken, isc_uint32_t lifetime, - gss_ctx_id_t *context, isc_boolean_t win2k) + gss_ctx_id_t *context, isc_boolean_t win2k, + dns_name_t *zone, isc_mem_t *mctx, char **err_message) { dns_rdata_tkey_t tkey; isc_result_t result; @@ -998,9 +1017,11 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, REQUIRE(name != NULL); REQUIRE(gname != NULL); REQUIRE(context != NULL); + REQUIRE(mctx != NULL); isc_buffer_init(&token, array, sizeof(array)); - result = dst_gssapi_initctx(gname, NULL, &token, context); + result = dst_gssapi_initctx(gname, NULL, &token, context, zone, + mctx, err_message); if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) return (result); @@ -1217,7 +1238,7 @@ isc_result_t dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, dns_name_t *gname, gss_ctx_id_t *context, isc_buffer_t *outtoken, dns_tsigkey_t **outkey, - dns_tsig_keyring_t *ring) + dns_tsig_keyring_t *ring, char **err_message) { dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT; dns_name_t *tkeyname; @@ -1231,6 +1252,7 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, REQUIRE(qmsg != NULL); REQUIRE(rmsg != NULL); REQUIRE(gname != NULL); + REQUIRE(ring != NULL); if (outkey != NULL) REQUIRE(*outkey == NULL); @@ -1267,10 +1289,11 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, isc_buffer_init(outtoken, array, sizeof(array)); isc_buffer_init(&intoken, rtkey.key, rtkey.keylen); - RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context)); + RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context, + NULL, ring->mctx, err_message)); RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx, - &dstkey)); + &dstkey, NULL)); RETERR(dns_tsigkey_createfromkey(tkeyname, DNS_TSIG_GSSAPI_NAME, dstkey, ISC_FALSE, NULL, @@ -1348,7 +1371,8 @@ isc_result_t dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, dns_name_t *server, gss_ctx_id_t *context, dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring, - isc_boolean_t win2k) + isc_boolean_t win2k, dns_name_t *zone, + char **err_message) { dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT; dns_name_t *tkeyname; @@ -1392,12 +1416,13 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, isc_buffer_init(&intoken, rtkey.key, rtkey.keylen); isc_buffer_init(&outtoken, array, sizeof(array)); - result = dst_gssapi_initctx(server, &intoken, &outtoken, context); + result = dst_gssapi_initctx(server, &intoken, &outtoken, context, + zone, ring->mctx, err_message); if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) return (result); RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx, - &dstkey)); + &dstkey, NULL)); /* * XXXSRA This seems confused. If we got CONTINUE from initctx, diff --git a/lib/dns/zone.c b/lib/dns/zone.c index fd3b4769d4..c1289447a7 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.579 2010/12/16 09:51:29 jinmei Exp $ */ +/* $Id: zone.c,v 1.580 2010/12/18 01:56:22 each Exp $ */ /*! \file */ @@ -3418,6 +3418,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, */ switch (zone->type) { + case dns_zone_dlz: case dns_zone_master: case dns_zone_slave: case dns_zone_stub: @@ -14189,3 +14190,16 @@ dns_zone_getadded(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); return (zone->added); } + +isc_result_t +dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) +{ + isc_time_t loadtime; + isc_result_t result; + TIME_NOW(&loadtime); + + LOCK_ZONE(zone); + result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS); + UNLOCK_ZONE(zone); + return result; +} diff --git a/lib/isc/include/isc/buffer.h b/lib/isc/include/isc/buffer.h index 2a02d88e4e..d83f93b823 100644 --- a/lib/isc/include/isc/buffer.h +++ b/lib/isc/include/isc/buffer.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: buffer.h,v 1.53 2008/09/25 04:02:39 tbox Exp $ */ +/* $Id: buffer.h,v 1.54 2010/12/18 01:56:22 each Exp $ */ #ifndef ISC_BUFFER_H #define ISC_BUFFER_H 1 @@ -623,7 +623,7 @@ isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base, * */ -void +void isc__buffer_putstr(isc_buffer_t *b, const char *source); /*!< * \brief Copy 'source' into 'b', not including terminating NUL. diff --git a/lib/isc/include/isc/platform.h.in b/lib/isc/include/isc/platform.h.in index 02b8d868c6..03c2710bac 100644 --- a/lib/isc/include/isc/platform.h.in +++ b/lib/isc/include/isc/platform.h.in @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: platform.h.in,v 1.55 2010/06/03 23:51:05 tbox Exp $ */ +/* $Id: platform.h.in,v 1.56 2010/12/18 01:56:23 each Exp $ */ #ifndef ISC_PLATFORM_H #define ISC_PLATFORM_H 1 @@ -219,6 +219,12 @@ */ @ISC_PLATFORM_GSSAPIHEADER@ +/* + * Defined to or for how to + * include the GSSAPI KRB5 header. + */ +@ISC_PLATFORM_GSSAPI_KRB5_HEADER@ + /* * Defined to or for how to include * the KRB5 header. diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 8ea63bb842..5bd2b21ae9 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.c,v 1.125 2010/12/16 09:51:30 jinmei Exp $ */ +/* $Id: namedconf.c,v 1.126 2010/12/18 01:56:23 each Exp $ */ /*! \file */ @@ -879,6 +879,7 @@ options_clauses[] = { { "tcp-listen-queue", &cfg_type_uint32, 0 }, { "tkey-dhkey", &cfg_type_tkey_dhkey, 0 }, { "tkey-gssapi-credential", &cfg_type_qstring, 0 }, + { "tkey-gssapi-keytab", &cfg_type_qstring, 0 }, { "tkey-domain", &cfg_type_qstring, 0 }, { "transfers-per-ns", &cfg_type_uint32, 0 }, { "transfers-in", &cfg_type_uint32, 0 },