diff options
Diffstat (limited to 'contrib/bind/bin/named/db_load.c')
-rw-r--r-- | contrib/bind/bin/named/db_load.c | 2749 |
1 files changed, 0 insertions, 2749 deletions
diff --git a/contrib/bind/bin/named/db_load.c b/contrib/bind/bin/named/db_load.c deleted file mode 100644 index 12d01979ceff..000000000000 --- a/contrib/bind/bin/named/db_load.c +++ /dev/null @@ -1,2749 +0,0 @@ -#if !defined(lint) && !defined(SABER) -static const char sccsid[] = "@(#)db_load.c 4.38 (Berkeley) 3/2/91"; -static const char rcsid[] = "$Id: db_load.c,v 8.121 2001/11/12 21:22:22 marka Exp $"; -#endif /* not lint */ - -/* - * Copyright (c) 1986, 1988, 1990 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * 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, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION 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. - */ - -/* - * Portions Copyright (c) 1995 by International Business Machines, Inc. - * - * International Business Machines, Inc. (hereinafter called IBM) grants - * permission under its copyrights to use, copy, modify, and distribute this - * Software with or without fee, provided that the above copyright notice and - * all paragraphs of this notice appear in all copies, and that the name of IBM - * not be used in connection with the marketing of any product incorporating - * the Software or modifications thereof, without specific, written prior - * permission. - * - * To the extent it has a right to do so, IBM grants an immunity from suit - * under its patents, if any, for the use, sale or manufacture of products to - * the extent that such products are used for performing Domain Name System - * dynamic updates in TCP/IP networks by means of the Software. No immunity is - * granted for any product per se or for any other function of any product. - * - * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, - * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN - * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -/* - * Portions Copyright (c) 1996-2000 by Internet Software Consortium. - * - * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM 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. - */ - -/* - * Load zone from ASCII file on local host. Format similar to RFC 883. - */ - -/* Import. */ - -#include "port_before.h" - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include <netinet/in.h> -#include <arpa/nameser.h> -#include <arpa/inet.h> - -#include <ctype.h> -#include <errno.h> -#include <netdb.h> -#include <resolv.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <time.h> - -#include <isc/eventlib.h> -#include <isc/logging.h> -#include <isc/memcluster.h> -#include <isc/misc.h> - -#include "port_after.h" - -#include "named.h" - -/* Forward. */ - -static int gettoken(FILE *, const char *); -static int getcharstring(char *, char *, int, int, int, FILE *, - const char *); -static int genname(char *, int, const char *, char *, int); -static int getmlword(char *, size_t, FILE *, int); -static int getallwords(char *, size_t, FILE *, int); -static u_int32_t wordtouint32(char *); -static void fixup_soa(const char *fn, struct zoneinfo *zp); -static int get_nxt_types(u_char *, FILE *, const char *); - -static int parse_sig_rr(char *, int, u_char *, int, FILE *, - struct zoneinfo *, char *, u_int32_t , - enum context, enum transport, - const char **); -static int parse_key_rr(char *, int, u_char *, int, FILE *, - const char **); - -static int parse_cert_rr(char *, int, u_char *, int, FILE *, - const char **); -static int parse_nxt_rr(char *, u_char *, int, FILE *, - struct zoneinfo *, char *, enum context, - enum transport, const char **); - - -static int wordtouint32_error = 0; -static int empty_token = 0; -static int getmlword_nesting = 0; - -/* Global. */ - -static int clev; /* a zone deeper in a hierarchy has more credibility */ - -/* - * Parser token values - */ -#define CURRENT 1 -#define DOT 2 -#define AT 3 -#define DNAME 4 -#define INCLUDE 5 -#define ORIGIN 6 -#define GENERATE 7 -#define DEFAULTTTL 8 -#define ERRTOK 9 - -#define MAKENAME_OK(N) \ - do { \ - if (!makename_ok(N, origin, class, zp, \ - transport, context, \ - domain, filename, lineno, \ - data_size - ((u_char*)N - data))) { \ - errs++; \ - sprintf(buf, "bad name \"%s\"", N); \ - goto err; \ - } \ - } while (0) - -#define MAKENAME_OKZP(N, SI) \ - do { \ - if (!makename_ok(N, zp->z_origin, zp->z_class, zp, \ - transport, context, \ - domain, zp->z_source, lineno, \ - SI - ((u_char*)N - data))) { \ - errs++; \ - sprintf(buf, "bad name \"%s\"", N); \ - goto err; \ - } \ - } while (0) - -#define RANGE(x, min, max) \ - (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x))) - -/* Public. */ - -/* int - * db_load(filename, in_origin, zp, def_domain, isixfr) - * load a database from `filename' into zone `zp'. append `in_origin' - * to all nonterminal domain names in the file. `def_domain' is the - * default domain for include files or NULL for zone base files. - * returns: - * -1 = can't open file - * 0 = success - * >0 = number of errors encountered - */ -int -db_load(const char *filename, const char *in_origin, - struct zoneinfo *zp, const char *def_domain, int isixfr) -{ - static int read_soa, read_ns, rrcount; - static u_int32_t default_ttl, default_warn; - static struct filenames { - struct filenames *next; - char *name; - } *filenames, *fn; - - const char *errtype = "Database"; - char *cp; - char domain[MAXDNAME], origin[MAXDNAME], tmporigin[MAXDNAME]; - char buf[MAXDATA]; - char genlhs[MAXDNAME], genrhs[MAXDNAME]; - u_char data[MAXDATA]; - unsigned int data_size = sizeof(data); - int c, someclass, class, type, dbflags, dataflags, multiline = 0; - int slineno, i, errs, didinclude, ininclude, escape, success; - u_int32_t ttl, n, serial; - u_long tmplong; - struct databuf *dp; - FILE *fp; - struct stat sb; - struct in_addr ina; - enum transport transport; - enum context context; - struct sockaddr_in empty_from; - int genstart, genend, genstep; - char *thisfile; - void *state = NULL; - int loggenerr; - - empty_from.sin_family = AF_INET; - empty_from.sin_addr.s_addr = htonl(INADDR_ANY); - empty_from.sin_port = htons(0); - -/* - * We use an 'if' inside of the 'do' below because otherwise the Solaris - * compiler detects that the 'while' is never executed because of the 'goto' - * and complains. - */ -#define ERRTO(msg) do { if (1) { errtype = msg; goto err; } } while (0) -#define ERRTOZ(msg) do { if (1) { errtype = msg; buf[0] = '\0'; goto err; } } while (0) - - switch (zp->z_type) { - case Z_PRIMARY: - /* Any updates should be saved before we attempt to reload. */ - INSIST((zp->z_flags & (Z_NEED_DUMP|Z_NEED_SOAUPDATE)) == 0); - case Z_HINT: - if (filename == NULL) { - ns_error(ns_log_load, - "Required filename not specified for Hint zone"); - zp->z_flags |= Z_DB_BAD; - zp->z_ftime = 0; - return (0); - } - transport = primary_trans; - break; - case Z_SECONDARY: - case Z_STUB: - transport = secondary_trans; - break; - case Z_CACHE: - transport = response_trans; - break; - default: - transport = response_trans; /*guessing*/ - break; - } - errs = 0; - didinclude = 0; - ininclude = (def_domain != NULL); - if (!ininclude) { - rrcount = 0; - read_soa = 0; - read_ns = 0; - default_ttl = USE_MINIMUM; - default_warn = 1; - clev = nlabels(in_origin); - filenames = NULL; - zp->z_minimum = USE_MINIMUM; - } - ttl = default_ttl; - - ns_debug(ns_log_load, 1, "db_load(%s, %s, %d, %s, %s)", - filename, in_origin, zp - zones, - def_domain ? def_domain : "Nil", isixfr ? "IXFR" : "Normal"); - - fn = (struct filenames *)memget(sizeof *filenames); - if (fn == NULL) - ns_panic(ns_log_db, 0, "db_load: memget failed"); - thisfile = fn->name = savestr(filename, 1); - fn->next = filenames; - filenames = fn; - - strcpy(origin, in_origin); - if ((fp = fopen(filename, "r")) == NULL) { - ns_warning(ns_log_load, "db_load could not open: %s: %s", - filename, strerror(errno)); - zp->z_ftime = 0; - if (ininclude) - return (-1); - errs = -1; - goto cleanup; - } - if (zp->z_type == Z_HINT) { - dbflags = DB_NODATA | DB_NOHINTS; - dataflags = DB_F_HINT; -#ifdef STUBS - } else if (zp->z_type == Z_STUB && clev == 0) { - dbflags = DB_NODATA | DB_NOHINTS; - dataflags = DB_F_HINT; -#endif - } else { - dbflags = DB_NODATA; - dataflags = 0; - } - gettime(&tt); - if (fstat(fileno(fp), &sb) < 0) { - ns_warning(ns_log_load, "fstat failed: %s: %s", - filename, strerror(errno)); - sb.st_mtime = (int)tt.tv_sec; - } - slineno = lineno; - lineno = 1; - if (def_domain) - strcpy(domain, def_domain); - else - domain[0] = '\0'; - class = zp->z_class; - zp->z_flags &= ~(Z_INCLUDE|Z_DB_BAD); - while ((c = gettoken(fp, filename)) != EOF) { - switch (c) { - case INCLUDE: - if (isixfr) { - c = ERRTOK; - break; - } - if (!getword(buf, sizeof buf, fp, 0)) - /* file name*/ - break; - if (!getword(tmporigin, sizeof(tmporigin), fp, 1)) - strcpy(tmporigin, origin); - else { - if (makename(tmporigin, origin, - sizeof(tmporigin)) == -1) - ERRTO("$INCLUDE makename failed"); - endline(fp); - } - didinclude = 1; - i = db_load(buf, tmporigin, zp, domain, ISNOTIXFR); - errs += (i == -1) ? 1 : i; - continue; - - case ORIGIN: - (void) strcpy(buf, origin); - if (!getword(origin, sizeof(origin), fp, 1)) - break; - ns_debug(ns_log_load, 3, "db_load: origin %s, buf %s", - origin, buf); - if (makename(origin, buf, sizeof(origin)) == -1) - ERRTO("$ORIGIN makename failed"); - ns_debug(ns_log_load, 3, "db_load: origin now %s", - origin); - continue; - - case GENERATE: - if (!getword(buf, sizeof(buf), fp, 0)) - ERRTOZ("$GENERATE missing RANGE"); - n = sscanf(buf, "%d-%d/%d", &genstart, &genend, - &genstep); - if (n != 2 && n != 3) - ERRTO("$GENERATE invalid range"); - if (n == 2) - genstep = 1; - if ((genend < genstart) || (genstart < 0) || - (genstep < 0)) - ERRTO("$GENERATE invalid range"); - if (!getword(genlhs, sizeof(genlhs), fp, 2)) - ERRTOZ("$GENERATE missing LHS"); - if (!getword(buf, sizeof(buf), fp, 0)) - ERRTOZ("GENERATE missing TYPE"); - type = res_nametotype(buf, &success); - if (success == 0 || type == ns_t_any) { - ns_info(ns_log_load, - "%s: Line %d: $GENERATE unknown type: %s.", - filename, lineno, buf); - errs++; - endline(fp); - continue; - } - switch (type) { - case ns_t_ns: - case ns_t_ptr: - case ns_t_cname: - case ns_t_a: - case ns_t_aaaa: - break; - default: - ERRTO("$GENERATE unsupported type"); - } - if (!getword(genrhs, sizeof(genrhs), fp, 2)) - ERRTOZ("$GENERATE missing RHS"); - loggenerr = 1; - for (i = genstart; i <= genend; i += genstep) { - if (genname(genlhs, i, origin, domain, - sizeof domain) == -1) - ERRTOZ("$GENERATE genname LHS failed"); - if (!ns_samedomain(domain, zp->z_origin)) { - /* Log first per $GENERATE. */ - if (loggenerr) { - ns_info(ns_log_load, - "%s:%d: $GENERATE LHS out of zone (ignored)", - filename, lineno); - loggenerr = 0; - } - continue; - } - context = ns_ownercontext(type, transport); - if (!ns_nameok(NULL, domain, class, zp, transport, - context, domain, inaddr_any)) { - strcpy(buf, domain); - ERRTO("$GENERATE owner name error"); - } - switch (type) { - case ns_t_ns: - case ns_t_ptr: - case ns_t_cname: - if (genname(genrhs, i, origin, (char *)data, - sizeof data) == -1) - ERRTOZ("$GENERATE genname RHS failed"); - switch (type) { - case ns_t_ns: - context = hostname_ctx; - break; - case ns_t_ptr: - context = ns_ptrcontext(domain); - break; - case ns_t_cname: - context = domain_ctx; - break; - } - if (!ns_nameok(NULL, (char *)data, class, zp, - transport, context, - domain, inaddr_any)) { - strncpy(buf, domain, sizeof(buf)); - buf[sizeof(buf)-1] = '\0'; - ERRTO("$GENERATE name error"); - } - n = strlen((char *)data) + 1; - break; - case ns_t_a: - case ns_t_aaaa: - if (genname(genrhs, i, NULL, (char *)data, - sizeof data) == -1) - ERRTOZ("$GENERATE genname RHS failed"); - strncpy(buf, (char*)data, sizeof(buf)); - buf[sizeof(buf)-1] = '\0'; - switch (type) { - case ns_t_a: - if (!inet_aton(buf, &ina)) - ERRTO("IP Address"); - (void) ina_put(ina, data); - n = NS_INT32SZ; - break; - case ns_t_aaaa: - if (inet_pton(AF_INET6, buf, data) <= 0) - ERRTO("IPv6 Address"); - n = NS_IN6ADDRSZ; - break; - } - break; - default: - ERRTOZ("$GENERATE unsupported context"); - } - dp = savedata(class, type, (u_int32_t)ttl, - (u_char *)data, (int)n); - dp->d_zone = zp - zones; - dp->d_flags = dataflags; - dp->d_cred = DB_C_ZONE; - dp->d_clev = clev; - c = db_set_update(domain, dp, &state, dbflags, - (dataflags & DB_F_HINT) != 0 ? - &fcachetab : &hashtab, - empty_from, &rrcount, lineno, - filename); - if (c != OK) { - if (c == CNAMEANDOTHER || c == NONGLUE) - errs++; - } - db_detach(&dp); - } - endline(fp); - continue; - - case DNAME: - if (!getword(domain, sizeof(domain), fp, 1)) - break; - if (makename(domain, origin, sizeof(domain)) == -1) - ERRTO("ownername makename failed"); - goto gotdomain; - - case DEFAULTTTL: - if (getttl(fp, filename, lineno, &n, - &multiline) <= 0 || n > MAXIMUM_TTL) { - ERRTO("$TTL bad TTL value"); - } - ttl = default_ttl = n; - continue; - - case AT: - (void) strcpy(domain, origin); - goto gotdomain; - - case DOT: - domain[0] = '\0'; - /* FALLTHROUGH */ - case CURRENT: - gotdomain: - if (!getword(buf, sizeof buf, fp, 0)) { - if (c == CURRENT) - continue; - break; - } - if (ns_parse_ttl(buf, &tmplong) < 0) { - if (zp->z_type == z_master && - default_warn && - (default_ttl == USE_MINIMUM)) { - ns_warning(ns_log_load, - "Zone \"%s\" (file %s): %s", - zp->z_origin, filename, - "No default TTL ($TTL <value>) set, using SOA minimum instead"); - default_warn = 0; - } - ttl = (u_int32_t)default_ttl; - } else { - ttl = tmplong; - if (ttl > MAXIMUM_TTL) { - ns_info(ns_log_load, - "%s: Line %d: TTL > %u; converted to 0", - filename, lineno, MAXIMUM_TTL); - ttl = 0; - } - if (zp->z_type == Z_CACHE) { - /* - * This allows the cache entry to age - * while sitting on disk (powered off). - */ - if (ttl > max_cache_ttl) - ttl = max_cache_ttl; - ttl += sb.st_mtime; - } - if (!getword(buf, sizeof buf, fp, 0)) - break; - } - - /* Parse class (IN, etc) */ - someclass = res_nametoclass(buf, &success); - if (success && someclass != zp->z_class) { - ns_info(ns_log_load, - "%s: Line %d: wrong class: %s.", - filename, lineno, - p_class(someclass)); - errs++; - break; - } - if (success && someclass != C_ANY) { - class = someclass; - (void) getword(buf, sizeof buf, fp, 0); - } - - /* Parse RR type (A, MX, etc) */ - type = res_nametotype(buf, &success); - if (success == 0 || type == ns_t_any) { - ns_info(ns_log_load, - "%s: Line %d: Unknown type: %s.", - filename, lineno, buf); - errs++; - break; - } - if (ttl == USE_MINIMUM) - ttl = zp->z_minimum; - context = ns_ownercontext(type, transport); - if (!ns_nameok(NULL, domain, class, zp, transport, context, - domain, inaddr_any)) { - errs++; - ns_notice(ns_log_load, - "%s:%d: owner name error", - filename, lineno); - break; - } - context = domain_ctx; - switch (type) { - case ns_t_key: - case ns_t_sig: - case ns_t_nxt: - case ns_t_cert: - /* - * Don't do anything here for these types -- - * they read their own input separately later. - */ - goto dont_get_word; - - case ns_t_soa: - case ns_t_minfo: - case ns_t_rp: - case ns_t_ns: - case ns_t_cname: - case ns_t_mb: - case ns_t_mg: - case ns_t_mr: - case ns_t_ptr: - escape = 1; - break; - case ns_t_a: - case ns_t_md: - case ns_t_mf: - case ns_t_null: - case ns_t_hinfo: - case ns_t_mx: - case ns_t_txt: - case ns_t_afsdb: - case ns_t_x25: - case ns_t_isdn: - case ns_t_rt: - case ns_t_nsap: - case ns_t_nsap_ptr: - case ns_t_px: - case ns_t_gpos: - case ns_t_aaaa: - case ns_t_loc: - case ns_t_eid: - case ns_t_nimloc: - case ns_t_srv: - case ns_t_atma: - case ns_t_naptr: - case ns_t_kx: - case ns_t_dname: - case ns_t_sink: - escape = 0; - break; - case ns_t_opt: - case ns_t_tkey: - case ns_t_tsig: - case ns_t_ixfr: - case ns_t_axfr: - case ns_t_mailb: - case ns_t_maila: - case ns_t_any: - case ns_t_zxfr: - escape = 0; - ns_info(ns_log_load, - "%s: Line %d: meta type: %s.", - filename, lineno, p_type(type)); - errs++; - break; - case ns_t_a6: /* not implemented */ - default: - escape = 1; - break; - } - if (!getword(buf, sizeof buf, fp, escape)) - break; - ns_debug(ns_log_load, 3, - "d='%s', c=%d, t=%d, ttl=%u, data='%s'", - domain, class, type, ttl, buf); - /* - * Convert the ascii data 'buf' to the proper format - * based on the type and pack into 'data'. - */ - dont_get_word: - switch (type) { - case ns_t_a: - if (!inet_aton(buf, &ina)) - ERRTO("IP Address"); - (void) ina_put(ina, data); - n = NS_INT32SZ; - break; - - case ns_t_soa: - context = hostname_ctx; - goto soa_rp_minfo; - case ns_t_rp: - case ns_t_minfo: - context = mailname_ctx; - /* FALLTHROUGH */ - soa_rp_minfo: - (void) strcpy((char *)data, buf); - - MAKENAME_OK((char *)data); - cp = (char *)(data + strlen((char *)data) + 1); - if (!getword(cp, - (sizeof data) - - (cp - (char*)data), - fp, 1)) - ERRTO("Domain Name"); - if (type == ns_t_rp) - context = domain_ctx; - else - context = mailname_ctx; - MAKENAME_OK(cp); - cp += strlen((char *)cp) + 1; - if (type != ns_t_soa) { - n = cp - (char *)data; - break; - } - if (ns_samename(zp->z_origin, domain) != 1) { - errs++; - ns_error(ns_log_load, - "%s:%d: SOA for \"%s\" not at zone top \"%s\"", - filename, lineno, domain, - zp->z_origin); - } - c = getnonblank(fp, filename, 0); - if (c == '(') { - multiline = 1; - } else { - multiline = 0; - ungetc(c, fp); - } - serial = zp->z_serial; - zp->z_serial = getnum(fp, filename, - GETNUM_SERIAL, - &multiline); - if (getnum_error) - errs++; - n = (u_int32_t) zp->z_serial; - PUTLONG(n, cp); - if (serial != 0 && - SEQ_GT(serial, zp->z_serial)) { - ns_notice(ns_log_load, - "%s:%d: WARNING: new serial number < old (%lu < %lu)", - filename , lineno, - (unsigned long)zp->z_serial, - (unsigned long)serial); - } - if (getttl(fp, filename, lineno, &n, - &multiline) <= 0) { - errs++; - n = INIT_REFRESH; - } - PUTLONG(n, cp); - zp->z_refresh = RANGE(n, MIN_REFRESH, - MAX_REFRESH); - if (zp->z_type == Z_SECONDARY -#if defined(STUBS) - || zp->z_type == Z_STUB -#endif - ) { - ns_refreshtime(zp, MIN(sb.st_mtime, - tt.tv_sec)); - sched_zone_maint(zp); - } -#ifdef BIND_UPDATE - if ((zp->z_type == Z_PRIMARY) && - (zp->z_flags & Z_DYNAMIC)) - if ((u_int32_t)zp->z_soaincrintvl > - zp->z_refresh/3) { - ns_info(ns_log_load, - "zone soa update time truncated to 1/3rd of refresh time"); - zp->z_soaincrintvl = - zp->z_refresh / 3; - } -#endif - - if (getttl(fp, filename, lineno, &n, - &multiline) <= 0) { - errs++; - n = INIT_REFRESH; - } - PUTLONG(n, cp); - zp->z_retry = RANGE(n, MIN_RETRY, MAX_RETRY); - if (getttl(fp, filename, lineno, - &n, &multiline) <= 0) { - errs++; - n = INIT_REFRESH; - } - PUTLONG(n, cp); - zp->z_expire = RANGE(n, zp->z_refresh, - MAX_EXPIRE); - if (getttl(fp, filename, lineno, &n, - &multiline) <= 0) { - errs++; - n = 120; - } - PUTLONG(n, cp); - if (n > MAXIMUM_TTL) { - ns_info(ns_log_load, - "%s: Line %d: SOA minimum TTL > %u; converted to 0", - filename, lineno, MAXIMUM_TTL); - zp->z_minimum = 0; - } else - zp->z_minimum = n; - if (ttl == USE_MINIMUM) - ttl = n; - n = cp - (char *)data; - if (multiline) { - buf[0] = getnonblank(fp, filename, 1); - buf[1] = '\0'; - if (buf[0] != ')') - ERRTO("SOA \")\""); - multiline = 0; - endline(fp); - } - read_soa++; - if (zp->z_type == Z_PRIMARY) - fixup_soa(filename, zp); - break; - - case ns_t_wks: - /* Address */ - if (!inet_aton(buf, &ina)) - ERRTO("WKS IP Address"); - (void) ina_put(ina, data); - /* Protocol */ - data[INADDRSZ] = getprotocol(fp, filename); - /* Services */ - n = getservices(NS_INT32SZ + sizeof(char), - (char *)data, fp, filename); - break; - - case ns_t_ns: - if (ns_samename(zp->z_origin, domain) == 1) - read_ns++; - context = hostname_ctx; - goto cname_etc; - case ns_t_cname: - case ns_t_mb: - case ns_t_mg: - case ns_t_mr: - context = domain_ctx; - goto cname_etc; - case ns_t_ptr: - context = ns_ptrcontext(domain); - cname_etc: - (void) strcpy((char *)data, buf); - MAKENAME_OK((char *)data); - n = strlen((char *)data) + 1; - break; - - case ns_t_naptr: - /* Order Preference Flags Service Replacement Regexp */ - n = 0; - cp = buf; - /* Order */ - while (isdigit(*cp)) - n = n * 10 + (*cp++ - '0'); - /* catch bad values */ - if (cp == buf || n > 65535) - ERRTO("NAPTR Order"); - cp = (char *)data; - PUTSHORT((u_int16_t)n, cp); - - /* Preference */ - n = getnum(fp, filename, GETNUM_NONE, - &multiline); - if (getnum_error || n > 65536) - ERRTO("NAPTR Preference"); - PUTSHORT((u_int16_t)n, cp); - - /* Flags */ - if (!getword(buf, sizeof buf, fp, 0)) - ERRTO("NAPTR Flags"); - n = strlen(buf); - if (n > 255) - ERRTO("NAPTR Flags too big"); - *cp++ = n; - memcpy(cp, buf, (int)n); - cp += n; - - /* Service Classes */ - if (!getword(buf, sizeof buf, fp, 0)) - ERRTO("NAPTR Service Classes"); - n = strlen(buf); - if (n > 255) - ERRTO("NAPTR Service Classes too big"); - *cp++ = n; - memcpy(cp, buf, (int)n); - cp += n; - - /* Pattern */ - if (!getword(buf, sizeof buf, fp, 0)) - ERRTO("NAPTR Pattern"); - n = strlen(buf); - if (n > 255) - ERRTO("NAPTR Pattern too big"); - *cp++ = n; - memcpy(cp, buf, (int)n); - cp += n; - - /* Replacement */ - if (!getword(buf, sizeof buf, fp, 1)) - ERRTO("NAPTR Replacement"); - n = strlen(buf); - if (n > data_size - ((u_char *)cp - data)) - ERRTO("NAPTR Replacement too big"); - (void) strcpy((char *)cp, buf); - context = domain_ctx; - MAKENAME_OK(cp); - /* advance pointer to end of data */ - cp += strlen((char *)cp) +1; - - /* now save length */ - n = (cp - (char *)data); - break; - - - case ns_t_mx: - case ns_t_afsdb: - case ns_t_rt: - case ns_t_srv: - n = 0; - cp = buf; - while (isdigit(*cp)) - n = n * 10 + (*cp++ - '0'); - /* catch bad values */ - if ((cp == buf) || (n > 65535)) - ERRTO("Priority"); - cp = (char *)data; - PUTSHORT((u_int16_t)n, cp); - - if (type == ns_t_srv) { - n = getnum(fp, filename, GETNUM_NONE, - &multiline); - if (getnum_error || n > 65536) - ERRTO("SRV RR"); - PUTSHORT((u_int16_t)n, cp); - - n = getnum(fp, filename, GETNUM_NONE, - &multiline); - if (getnum_error || n > 65536) - ERRTO("SRV RR"); - PUTSHORT((u_int16_t)n, cp); - } - - if (!getword(buf, sizeof buf, fp, 1)) - ERRTO("Domain Name"); - (void) strcpy((char *)cp, buf); - context = hostname_ctx; - MAKENAME_OK(cp); - /* advance pointer to end of data */ - cp += strlen((char *)cp) +1; - - /* now save length */ - n = (cp - (char *)data); - break; - - case ns_t_px: - context = domain_ctx; - n = 0; - data[0] = '\0'; - cp = buf; - while (isdigit(*cp)) - n = n * 10 + (*cp++ - '0'); - /* catch bad values */ - if ((cp == buf) || (n > 65535)) - ERRTO("PX Priority"); - cp = (char *)data; - PUTSHORT((u_int16_t)n, cp); - - if (!getword(buf, sizeof buf, fp, 0)) - ERRTO("PX Domain1"); - (void) strcpy((char *)cp, buf); - MAKENAME_OK(cp); - /* advance pointer to next field */ - cp += strlen((char *)cp) + 1; - if (!getword(buf, sizeof buf, fp, 0)) - ERRTO("PX Domain2"); - (void) strcpy((char *)cp, buf); - MAKENAME_OK(cp); - /* advance pointer to end of data */ - cp += strlen((char *)cp) + 1; - - /* now save length */ - n = (cp - (char *)data); - break; - - case ns_t_hinfo: - n = getcharstring(buf, (char *)data, type, - 2, 2, fp, filename); - if (n == 0) - ERRTO("HINFO RR"); - break; - - case ns_t_isdn: - n = getcharstring(buf, (char *)data, type, - 1, 2, fp, filename); - if (n == 0) - ERRTO("ISDN RR"); - break; - - case ns_t_txt: - n = getcharstring(buf, (char *)data, type, - 1, 0, fp, filename); - if (n == 0) - ERRTO("TXT RR"); - break; - - - case ns_t_x25: - n = getcharstring(buf, (char *)data, type, - 1, 1, fp, filename); - if (n == 0) - ERRTO("X25 RR"); - break; - - case ns_t_nsap: - if (buf[0] != '0' || - (buf[1] != 'x' && buf[1] != 'X')) - ERRTO("NSAP RR: no leading 0x"); - n = inet_nsap_addr(buf, (u_char *)data, - sizeof data); - if (n == 0) - ERRTO("NSAP RR"); - endline(fp); - break; - - case ns_t_aaaa: - if (inet_pton(AF_INET6, buf, data) <= 0) - ERRTO("IPv4 Address"); - n = NS_IN6ADDRSZ; - endline(fp); - break; - - case ns_t_nxt: - case ns_t_key: - case ns_t_cert: - case ns_t_sig: { - const char *errmsg = NULL; - int ret; - if (ttl == USE_MINIMUM) /* no ttl set */ - ttl = 0; - ret = parse_sec_rdata(buf, sizeof(buf), 0, - data, sizeof(data), - fp, zp, domain, ttl, - type, domain_ctx, - transport, &errmsg); - if (ret < 0) { - errtype = errmsg; - goto err; - } - else - n = ret; - break; - } - - - case ns_t_loc: - cp = buf + (n = strlen(buf)); - *cp = ' '; - cp++; - n++; - while ((i = getc(fp), *cp = i, i != EOF) - && *cp != '\n' - && (n < MAXDATA)) { - cp++; n++; - } - if (*cp == '\n') /* leave \n for getword */ - ungetc(*cp, fp); - *cp = '\0'; - /* now process the whole line */ - n = loc_aton(buf, (u_char *)data); - if (n == 0) - goto err; - endline(fp); - break; - - default: - if (strcmp(buf, "\\#") != 0) - goto err; - if (!getword(buf, sizeof buf, fp, 0) || - !isdigit((unsigned char)buf[0])) - ERRTO("opaque length"); - n = strtoul(buf, &cp, 10); - if (n > 0xffff || *cp != '\0') - ERRTO("opaque length"); - multiline = 0; - i = isc_gethexstring(data, sizeof(data), n, fp, - &multiline); - if (i == -1) - ERRTO("opaque data read failed"); - if (multiline) { - buf[0] = getnonblank(fp, filename, 1); - buf[1] = '\0'; - if (buf[0] != ')') - ERRTO("\")\" expected"); - multiline = 0; - } - endline(fp); - } - /* - * Ignore data outside the zone. - */ - if (zp->z_type != Z_CACHE && - !ns_samedomain(domain, zp->z_origin)) - { - ns_info(ns_log_load, - "%s:%d: data \"%s\" outside zone \"%s\" (ignored)", - filename, lineno, domain, - zp->z_origin); - continue; - } - if (ttl == USE_MINIMUM) /* no ttl set */ - ttl = 0; - dp = savedata(class, type, (u_int32_t)ttl, - (u_char *)data, (int)n); - dp->d_zone = zp - zones; - dp->d_flags = dataflags; - dp->d_cred = DB_C_ZONE; - dp->d_clev = clev; - c = db_set_update(domain, dp, &state, dbflags, - (dataflags & DB_F_HINT) != 0 ? - &fcachetab : &hashtab, - empty_from, &rrcount, lineno, - filename); - if (c == CNAMEANDOTHER || c == NONGLUE) - errs++; - db_detach(&dp); - continue; - - case ERRTOK: - break; - } - err: - errs++; - ns_notice(ns_log_load, "%s:%d: %s error near (%s)", - filename, empty_token ? (lineno - 1) : lineno, - errtype, buf); - if (!empty_token) - endline(fp); - } - c = db_set_update(NULL, NULL, &state, dbflags, - (dataflags & DB_F_HINT) ? &fcachetab : &hashtab, - empty_from, &rrcount, lineno, filename); - if (c != OK) { - if (c == CNAMEANDOTHER || c == NONGLUE) - errs++; - } - - (void) my_fclose(fp); - lineno = slineno; - if (!ininclude) { - if (didinclude) { - zp->z_flags |= Z_INCLUDE; - zp->z_ftime = 0; - } else - zp->z_ftime = sb.st_mtime; - zp->z_lastupdate = sb.st_mtime; - if (zp->z_type != Z_CACHE && zp->z_type != Z_HINT) { - const char *msg = NULL; - - if (read_soa == 0) - msg = "no SOA RR found"; - else if (read_soa != 1) - msg = "multiple SOA RRs found"; - else if (read_ns == 0) - msg = "no NS RRs found at zone top"; - else if (!rrcount) - msg = "no relevant RRs found"; - if (msg != NULL) { - errs++; - ns_warning(ns_log_load, - "Zone \"%s\" (file %s): %s", - zp->z_origin, filename, msg); - } - } - errs += purge_nonglue(zp->z_origin, - (dataflags & DB_F_HINT) ? fcachetab : - hashtab, zp->z_class, - zp->z_type == z_master); - cleanup: - while (filenames) { - fn = filenames; - filenames = filenames->next; - fn->name = freestr(fn->name); - memput(fn, sizeof *fn); - } - if (errs != 0) { - if (errs != -1) - ns_error(ns_log_load, - "%s zone \"%s\" (%s) rejected due to errors (serial %u)", - zoneTypeString(zp->z_type), - zp->z_origin, - p_class(zp->z_class), zp->z_serial); - if ((zp->z_flags & Z_NOTIFY) != 0) - ns_stopnotify(zp->z_origin, zp->z_class); - do_reload(zp->z_origin, zp->z_type, zp->z_class, - loading); - } else - ns_info(ns_log_load, - "%s zone \"%s\" (%s) loaded (serial %u)", - zoneTypeString(zp->z_type), zp->z_origin, - p_class(zp->z_class), zp->z_serial); - } - if (errs != 0) { - zp->z_flags |= Z_DB_BAD; - zp->z_ftime = 0; - } -#ifdef BIND_NOTIFY - if (errs == 0 && (!ininclude) && (initial_configuration == 0 || - !NS_OPTION_P(OPTION_SUPNOTIFY_INITIAL)) && - (zp->z_type == z_master || zp->z_type == z_slave)) - ns_notify(zp->z_origin, zp->z_class, ns_t_soa); -#endif - return (errs); -} - -void -db_err(int err, char *domain, int type, const char *filename, int lineno) { - if (filename != NULL && err == CNAMEANDOTHER) - ns_warning(ns_log_load, "%s:%d:%s: CNAME and OTHER data error", - filename, lineno, domain); - if (err != DATAEXISTS) - ns_debug(ns_log_load, 1, "update failed %s %d", - domain, type); -} - -static int -gettoken(FILE *fp, const char *src) { - int c; - char op[32]; - - for (;;) { - c = getc(fp); - top: - switch (c) { - case EOF: - return (EOF); - - case '$': - if (getword(op, sizeof op, fp, 0)) { - if (!strcasecmp("include", op)) - return (INCLUDE); - if (!strcasecmp("origin", op)) - return (ORIGIN); - if (!strcasecmp("generate", op)) - return (GENERATE); - if (!strcasecmp("ttl", op)) - return (DEFAULTTTL); - } - ns_notice(ns_log_db, - "%s:%d: Unknown $ option: $%s", - src, lineno, op); - return (ERRTOK); - - case ';': - while ((c = getc(fp)) != EOF && c != '\n') - ; - goto top; - - case ' ': - case '\t': - return (CURRENT); - - case '.': - return (DOT); - - case '@': - return (AT); - - case '\n': - lineno++; - continue; - - case '\r': - if (NS_OPTION_P(OPTION_TREAT_CR_AS_SPACE) != 0) - return (CURRENT); - - default: - (void) ungetc(c, fp); - return (DNAME); - } - } -} - -/* int - * getword(buf, size, fp, preserve) - * get next word, skipping blanks & comments. - * '\' '\n' outside of "quotes" is considered a blank. - * parameters: - * buf - destination - * size - of destination - * fp - file to read from - * preserve - should we preserve \ before \\ and \.? - * if preserve == 2, then keep all \ - * return value: - * 0 = no word; perhaps EOL or EOF; lineno was incremented. - * 1 = word was read - */ -int -getword(char *buf, size_t size, FILE *fp, int preserve) { - char *cp = buf; - int c, spaceok, once; - - empty_token = 0; /* XXX global side effect. */ - once = 0; - while ((c = getc(fp)) != EOF) { - once++; - if (c == ';') { - /* Comment. Skip to end of line. */ - while ((c = getc(fp)) != EOF && c != '\n') - (void)NULL; - c = '\n'; - } - if (c == '\n') { - /* - * Unescaped newline. It's a terminator unless we're - * already midway into a token. - */ - if (cp != buf) - ungetc(c, fp); - else - lineno++; - break; - } - if (c == '"') { - /* "Quoted string." Gather the whole string here. */ - while ((c = getc(fp)) != EOF && c!='"' && c!='\n') { - if (c == '\\') { - if ((c = getc(fp)) == EOF) - c = '\\'; - if (preserve) - switch (c) { - default: - if (preserve == 1) - break; - case '\\': - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (cp >= buf+size-1) - break; - *cp++ = '\\'; - } - if (c == '\n') - lineno++; - } - if (cp >= buf+size-1) - break; - *cp++ = c; - } - /* - * Newline string terminators are - * not token terminators. - */ - if (c == '\n') { - lineno++; - break; - } - /* Sample following character, check for terminator. */ - if ((c = getc(fp)) != EOF) - ungetc(c, fp); - if (c == EOF || isspace(c)) { - *cp = '\0'; - return (1); - } - continue; - } - spaceok = 0; - if (c == '\\') { - /* Do escape processing. */ - if ((c = getc(fp)) == EOF) - c = '\\'; - if (preserve) - switch (c) { - default: - if (preserve == 1) - break; - case '\\': - case '#': - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (cp >= buf+size-1) - break; - *cp++ = '\\'; - } - if (c == ' ' || c == '\t') - spaceok++; - } - if (isspace(c) && !spaceok) { - /* Blank of some kind. Skip run. */ - while (isspace(c = getc(fp)) && c != '\n') - (void)NULL; - ungetc(c, fp); - /* Blank means terminator if the token is nonempty. */ - if (cp != buf) /* Trailing whitespace */ - break; - continue; /* Leading whitespace */ - } - if (cp >= buf + size - 1) - break; - *cp++ = (char)c; - } - *cp = '\0'; - if (cp == buf) - empty_token = 1; - if (!once) - lineno++; - return (cp != buf); -} - -/* - * int - * getttl(fp, fn, ln, ttl, multiline) - * read a word from the file and parse it as a TTL. - * return: - * 1 ttl found - * 0 word not read (EOF or EOL?) - * -1 word read but it wasn't a ttl - * side effects: - * *ttl is written if the return value is to be 1. - */ -int -getttl(FILE *fp, const char *fn, int lineno, u_int32_t *ttl, int *multiline) { - char buf[MAXDATA]; - u_long tmp; - int ch; - int len; - - while (!feof(fp) && !getword(buf, sizeof buf, fp, 0) && *multiline) - (void)NULL; - len = strlen(buf); - if (*multiline && len && buf[len-1] == ')') { - buf[len-1] = '\0'; - *multiline = 0; - } - if (ns_parse_ttl(buf, &tmp) < 0) { - ns_notice(ns_log_db, "%s:%d: expected a TTL, got \"%s\"", - fn, lineno, buf); - return (-1); - } - if (*multiline) { - ch = getnonblank(fp, fn, 1); - if (ch == EOF) - return (-1); - if (ch == ';') - endline(fp); - else - ungetc(ch, fp); - } - *ttl = (u_int32_t)tmp; - return (1); -} - -/* Get multiline words. Same parameters as getword. Handles any - number of leading ('s or )'s in the words it sees. - FIXME: We kludge recognition of ( and ) for multiline input. - Each paren must appear at the start of a (blank-separated) word, - which is particularly counter-intuitive for ). Good enough for now, - until Paul rewrites the parser. (gnu@toad.com, oct96) -*/ -static int -getmlword(char *buf, size_t size, FILE *fp, int preserve) { - char *p; - - do { - while (!getword (buf, size, fp, preserve)) { - /* No more words on this line. See if doing the - multiline thing. */ - if (!getmlword_nesting) { /* Nope... */ - ungetc('\n', fp); /* Push back newline */ - lineno--; /* Unbump the lineno */ - empty_token = 0; /* Undo this botch */ - return 0; - } - if (feof(fp) || ferror(fp)) - return 0; /* Error, no terminating ')' */ - /* Continue reading til we get a word... */ - } - while ('(' == *buf) { - /* Word starts with paren. Multiline mode. - Move the rest of the word down over the paren. */ - getmlword_nesting++; - p = buf; - while (0 != (p[0]=p[1])) p++; - } - while (')' == *buf) { - getmlword_nesting--; - p = buf; - while (0 != (p[0]=p[1])) p++; - } - } while (buf[0] == 0); /* loop til we get a non-( non-) word */ - - return 1; /* Got a word... */ -} - -/* Get all the remaining words on a line, concatenated into one big - long (not too long!) string, with the whitespace squeezed out. - This routine, like getword(), does not swallow the newline if words seen. - This routine, unlike getword(), never swallows the newline if no words. - Parameters are the same as getword(). Result is: - 0 got no words at all - 1 got one or more words - -1 got too many words, they don't all fit; or missing close paren -*/ -static int -getallwords(char *buf, size_t size, FILE *fp, int preserve) { - char *runningbuf = buf; - int runningsize = size; - int len; - - while (runningsize > 0) { - if (!getmlword (runningbuf, runningsize, fp, preserve)) { - return runningbuf!=buf; /* 1 or 0 */ - } - len = strlen(runningbuf); - runningbuf += len; - runningsize -= len; - } - return -1; /* Error, String too long */ -} - -int -getnum(FILE *fp, const char *src, int opt, int *multiline) { - int c, n; - int seendigit = 0; - int seendecimal = 0; - int m = 0; - int allow_dots = 0; - - getnum_error = 0; -#ifdef DOTTED_SERIAL - if (opt & GETNUM_SERIAL) - allow_dots++; -#endif - for (n = 0; (c = getc(fp)) != EOF; ) { - if (isspace(c)) { - if (c == '\n') { - if (*multiline) - lineno++; - else if (!seendigit) - goto eol; - } - if (seendigit) - break; - continue; - } - if (c == ';') { - while ((c = getc(fp)) != EOF && c != '\n') - ; - if (c == '\n') { - if (*multiline) - lineno++; - else if (!seendigit) - goto eol; - } - if (seendigit) - break; - continue; - } - if (getnum_error) - continue; - if (!isdigit(c)) { - if (c == ')' && seendigit) { - (void) ungetc(c, fp); - break; - } - if (seendigit && (opt & GETNUM_SCALED) && - strchr("KkMmGg", c) != NULL) { - switch (c) { - case 'K': case 'k': - n *= 1024; - break; - case 'M': case 'm': - n *= (1024 * 1024); - break; - case 'G': case 'g': - n *= (1024 * 1024 * 1024); - break; - } - break; - } - if (seendecimal || c != '.' || !allow_dots) { - ns_notice(ns_log_db, - "%s:%d: expected a number", - src, lineno); - getnum_error = 1; - } else { - if (!seendigit) - n = 1; -#ifdef SENSIBLE_DOTS - n *= 10000; -#else - n *= 1000; -#endif - seendigit = 1; - seendecimal = 1; - } - continue; - } -#ifdef SENSIBLE_DOTS - if (seendecimal) - m = m * 10 + (c - '0'); - else - n = n * 10 + (c - '0'); -#else - n = n * 10 + (c - '0'); -#endif - seendigit = 1; - } - if (getnum_error) - return (0); - if (m > 9999) { - ns_info(ns_log_db, - "%s:%d: number after the decimal point exceeds 9999", - src, lineno); - getnum_error = 1; - return (0); - } - if (seendecimal) { - ns_info(ns_log_db, - "%s:%d: decimal serial number interpreted as %d", - src, lineno, n+m); - } - return (n + m); - - eol: - ns_error(ns_log_db, "%s:%d: unexpected end of line", src, lineno); - getnum_error = 1; - (void) ungetc(c, fp); - return (0); -} - -#ifndef BIND_UPDATE -static -#endif -int -getnonblank(FILE *fp, const char *src, int multiline) { - int c; - - while ((c = getc(fp)) != EOF) { - if (isspace(c)) { - if (c == '\n') { - if (multiline) - lineno++; - else - goto eol; - } - continue; - } - if (c == ';') { - while ((c = getc(fp)) != EOF && c != '\n') - ; - if (c == '\n') { - if (multiline) - lineno++; - else - goto eol; - } - continue; - } - return (c); - } - ns_info(ns_log_db, "%s:%d: unexpected EOF", src, lineno); - return (EOF); - eol: - ns_error(ns_log_db, "%s:%d: unexpected end of line", src, lineno); - /* don't ungetc(c, fp); as the caller will do this. */ - return(c); -} - -/* - * Replace all single "$"'s in "name" with "it". - * ${delta} will add delta to "it" before printing. - * ${delta,width} will change print width as well, zero fill is implied - * ${delta,width,radix} will change radix as well, can be d, o, x, X. - * i.e. ${0,2,X} will produce a two digit hex (upper case) with zero fill. - * Append "origin" to name if required and validate result with makename. - * To get a "$" or "{" in the output use \ before it. - * Return 0 on no error or -1 on error. - * Resulting name stored in "buf". - */ - -static int -genname(char *name, int it, const char *origin, char *buf, int size) { - char *bp = buf; - char *eom = buf + size; - char *cp; - char numbuf[32]; - char fmt[32]; - int delta = 0; - int width; - - while (*name) { - if (*name == '$') { - if (*(++name) == '$') { - /* should be deprecated. how? */ - if (bp >= eom) - return (-1); - *bp++ = *name++; - } else { - strcpy(fmt, "%d"); - if (*name == '{') { - switch (sscanf(name, "{%d,%d,%1[doxX]}", &delta, &width, numbuf)) { - case 1: - break; - case 2: - sprintf(fmt, "%%0%dd", width); - break; - case 3: - sprintf(fmt, "%%0%d%c", width, numbuf[0]); - break; - default: - return (-1); - } - while (*name && *name++ != '}') { - continue; - } - } - sprintf(numbuf, fmt, it + delta); - cp = numbuf; - while (*cp) { - if (bp >= eom) - return (-1); - *bp++ = *cp++; - } - } - } else if (*name == '\\') { - if (*(++name) == '\0') { - if (bp >= eom) - return (-1); - *bp++ = '\\'; - } else { - switch (*name) { - case '\\': - case '.': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (bp >= eom) - return (-1); - *bp++ = '\\'; - default: - if (bp >= eom) - return (-1); - *bp++ = *name++; - } - } - } else { - if (bp >= eom) - return (-1); - *bp++ = *name++; - } - } - if (bp >= eom) - return (-1); - *bp = '\0'; - return (origin == NULL ? 0 : makename(buf, origin, size)); -} - - -/* - * Take name and fix it according to following rules: - * "." means root. - * "@" means current origin. - * "name." means no changes. - * "name" means append origin. - */ -int -makename(char *name, const char *origin, int size) { - int n; - u_char domain[MAXCDNAME]; - - switch (ns_name_pton(name, domain, sizeof(domain))) { - case -1: - return (-1); - case 1: /* FULLY QUALIFIED */ - break; - case 0: /* UNQUALIFIED */ - if (strcmp(name, "@") == 0) /* must test raw name */ - domain[0] = 0; - if ((n = dn_skipname(domain, domain+sizeof(domain))) == -1) - return (-1); - /* step back over root, append origin */ - switch (ns_name_pton(origin, domain+n-1, sizeof(domain)-n+1)) { - case -1: - return (-1); - case 0: - case 1: - break; - } - break; - } - if (ns_name_ntop(domain, name, size) == -1) - return (-1); - if (name[0] == '.') /* root */ - name[0] = '\0'; - return (0); -} - -int -makename_ok(char *name, const char *origin, int class, struct zoneinfo *zp, - enum transport transport, enum context context, - const char *owner, const char *filename, int lineno, int size) -{ - int ret = 1; - - if (makename(name, origin, size) == -1) { - ns_info(ns_log_db, "%s:%d: makename failed", - filename, lineno); - return (0); - } - if (!ns_nameok(NULL, name, class, zp, transport, context, owner, - inaddr_any)) { - ns_info(ns_log_db, "%s:%d: database naming error", - filename, lineno); - ret = 0; - } - return (ret); -} - -void -endline(FILE *fp) { - int c; - - while ((c = getc(fp)) != '\0') { - if (c == '\n') { - (void) ungetc(c,fp); - break; - } else if (c == EOF) { - break; - } - } -} - -#define MAXPORT 1024 -#define MAXLEN 24 - -#ifndef BIND_UPDATE -static -#endif -char -getprotocol(FILE *fp, const char *src) { - int k; - char b[MAXLEN]; - - (void) getword(b, sizeof(b), fp, 0); - - k = protocolnumber(b); - if (k == -1) - ns_info(ns_log_db, "%s:%d: unknown protocol: %s.", - src, lineno, b); - return ((char) k); -} - -#ifndef BIND_UPDATE -static -#endif -int -getservices(int offset, char *data, FILE *fp, const char *src) { - int j, ch, k, maxl, bracket; - char bm[MAXPORT/8]; - char b[MAXLEN]; - - for (j = 0; j < MAXPORT/8; j++) - bm[j] = 0; - maxl = 0; - bracket = 0; - while (getword(b, sizeof(b), fp, 0) || bracket) { - if (feof(fp) || ferror(fp)) - break; - if (strlen(b) == 0) - continue; - if (b[0] == '(') { - bracket++; - continue; - } - if (b[0] == ')') { - bracket = 0; - while ((ch = getc(fp)) != EOF && ch != '\n') - (void)NULL; - if (ch == '\n') - lineno++; - break; - } - k = servicenumber(b); - if (k == -1) { - ns_info(ns_log_db, - "%s:%d: Unknown service '%s'", - src, lineno, b); - continue; - } - if ((k < MAXPORT) && (k)) { - bm[k/8] |= (0x80>>(k%8)); - if (k > maxl) - maxl = k; - } else { - ns_info(ns_log_db, - "%s:%d: port no. (%d) too big", - src, lineno, k); - } - } - if (bracket) - ns_info(ns_log_db, "%s:%d: missing close paren", - src, lineno); - maxl = maxl/8+1; - memcpy(data+offset, bm, maxl); - return (maxl+offset); -} - -/* - * Converts a word to a u_int32_t. Error if any non-numeric - * characters in the word, except leading or trailing white space. - */ -static u_int32_t -wordtouint32(buf) - char *buf; -{ - u_long result; - u_int32_t res2; - char *bufend; - - wordtouint32_error = 0; - result = strtoul(buf, &bufend, 0); - if (bufend == buf) - wordtouint32_error = 1; - else - while ('\0' != *bufend) { - if (isspace(*bufend)) - bufend++; - else { - wordtouint32_error = 1; - break; - } - } - /* Check for truncation between u_long and u_int32_t */ - res2 = result; - if (res2 != result) - wordtouint32_error = 1; - return (res2); -} - -static int -getcharstring(char *buf, char *data, int type, - int minfields, int maxfields, - FILE *fp, const char *src) -{ - int nfield = 0, done = 0, n = 0, i; - char *b = buf; - - do { - nfield++; - i = strlen(buf); -#ifdef ALLOW_LONG_TXT_RDATA - b = buf; - if (type == ns_t_txt || type == ns_t_x25) { - while (i > MAXCHARSTRING - && n + MAXCHARSTRING + 1 < MAXDATA) { - data[n] = (char)MAXCHARSTRING; - memmove(data + n + 1, b, MAXCHARSTRING); - n += MAXCHARSTRING + 1; - b += MAXCHARSTRING; - i -= MAXCHARSTRING; - } - } -#endif /* ALLOW_LONG_TXT_RDATA */ - if (i > MAXCHARSTRING) { - ns_info(ns_log_db, - "%s:%d: RDATA field %d too long", - src, lineno -1, nfield); - return (0); - } - if (n + i + 1 > MAXDATA) { - ns_info(ns_log_db, - "%s:%d: total RDATA too long", - src, lineno -1); - return (0); - } - data[n] = i; - memmove(data + n + 1, b, (int)i); - n += i + 1; - done = (maxfields && nfield >= maxfields); - } while (!done && getword(buf, MAXDATA, fp, 0)); - - if (nfield < minfields) { - ns_info(ns_log_db, - "%s:%d: expected %d RDATA fields, only saw %d", - src, lineno -1, minfields, nfield); - return (0); - } - - if (done) - endline(fp); - - return (n); -} - - -/* - * get_nxt_types(): Read the list of types in the NXT record. - * - * Data is the array where the bit flags are stored; it must - * contain at least ns_t_any/NS_NXT_BITS bytes. - * FP is the input FILE *. - * Filename is the sourcefile - * - * The result is how many bytes are significant in the result. - * ogud@tis.com 1995 - */ -static int -get_nxt_types(u_char *data, FILE *fp, const char *filename) { - char b[MAXLABEL]; /* Not quite the right size, but good enough */ - int maxtype=0; - int success; - int type; - int errs = 0; - - memset(data, 0, NS_NXT_MAX/NS_NXT_BITS+1); - - while (getmlword(b, sizeof(b), fp, 0)) { - if (feof(fp) || ferror(fp)) - break; - if (strlen(b) == 0 || b[0] == '\n') - continue; - - /* Parse RR type (A, MX, etc) */ - type = res_nametotype((char *)b, &success); - if ((!success) || type == ns_t_any) { - errs++; - ns_info(ns_log_db, - "%s: Line %d: Unknown type: %s in NXT record.", - filename, lineno, b); - continue; - } - NS_NXT_BIT_SET(type, data); - if (type > maxtype) - maxtype = type; - } - if (errs) - return (0); - else - return (maxtype/NS_NXT_BITS+1); -} - -/* sanity checks PRIMARY ONLY */ -static void -fixup_soa(const char *fn, struct zoneinfo *zp) { - /* Sanity: give enough time for the zone to transfer (retry). */ - if (zp->z_expire < (zp->z_refresh + zp->z_retry)) - ns_notice(ns_log_db, - "%s: WARNING SOA expire value is less than SOA refresh+retry (%u < %u+%u)", - fn, zp->z_expire, zp->z_refresh, zp->z_retry); - - /* Sanity. */ - if (zp->z_expire < (zp->z_refresh + 10 * zp->z_retry)) - ns_warning(ns_log_db, -"%s: WARNING SOA expire value is less than refresh + 10 * retry \ -(%u < (%u + 10 * %u))", - fn, zp->z_expire, zp->z_refresh, zp->z_retry); - - /* - * Sanity: most hardware/telco faults are detected and fixed within - * a week, secondaries should continue to operate for this time. - * (minimum of 4 days for long weekends) - */ - if (zp->z_expire < (7 * 24 * 3600)) - ns_warning(ns_log_db, - "%s: WARNING SOA expire value is less than 7 days (%u)", - fn, zp->z_expire); - - /* - * Sanity: maximum down time if we havn't talked for six months - * war must have broken out. - */ - if (zp->z_expire > ( 183 * 24 * 3600)) - ns_warning(ns_log_db, - "%s: WARNING SOA expire value is greater than 6 months (%u)", - fn, zp->z_expire); - - /* Sanity. */ - if (zp->z_refresh < (zp->z_retry * 2)) - ns_warning(ns_log_db, - "%s: WARNING SOA refresh value is less than 2 * retry (%u < %u * 2)", - fn, zp->z_refresh, zp->z_retry); -} - -/* this function reads in the sig record rdata from the input file and - * returns the following codes - * > 0 length of the recrod - * ERR_EOF end of file - * - */ - -static int -parse_sig_rr(char *buf, int buf_len, u_char *data, int data_size, - FILE *fp, struct zoneinfo *zp, char *domain, u_int32_t ttl, - enum context domain_ctx, enum transport transport, - const char **errmsg) -{ -/* The SIG record looks like this in the db file: - Name Cl SIG RRtype Algid [OTTL] Texp Tsig Kfoot Signer Sig - - where: Name and Cl are as usual - SIG is a keyword - RRtype is a char string - ALGid is 8 bit u_int - Labels is 8 bit u_int - OTTL is 32 bit u_int (optionally present) - Texp is YYYYMMDDHHMMSS - Tsig is YYYYMMDDHHMMSS - Kfoot is 16-bit unsigned decimal integer - Signer is a char string - Sig is 64 to 319 base-64 digits - A missing OTTL is detected by the magnitude of the Texp value - that follows it, which is larger than any u_int. - The Labels field in the binary RR does not appear in the - text RR. - - It's too crazy to run these pages of SIG code at the right - margin. I'm exdenting them for readability. -*/ - u_int32_t sig_type; - int dateerror; - int siglen, success; - u_char *cp; - u_int32_t al, la, n; - u_int32_t signtime, exptime, timetilexp; - u_int32_t origTTL; - enum context context; - time_t now; - const char *errtype = "SIG error"; - int i, my_buf_size = MAXDATA, errs = 0; - - - /* The TTL gets checked against the Original TTL, - and bounded by the signature expiration time, which - are both under the signature. We can't let TTL drift - based on the SOA record. If defaulted, fix it now. - (It's not clear to me why USE_MINIMUM isn't eliminated - before putting ALL RR's into the database. -gnu@toad.com) */ - if (ttl == USE_MINIMUM) - ttl = zp->z_minimum; - - i = 0; - data[i] = '\0'; - - getmlword_nesting = 0; /* KLUDGE err recovery */ - - /* RRtype (char *) - * if old style inp will contain the next token - *copy that into buffer, otherwise read from file - */ - if (buf && buf_len == 0) - if (!getmlword((char*)buf, my_buf_size, fp, 0)) - ERRTO("SIG record doesn't specify type"); - sig_type = res_nametotype(buf, &success); - if (!success || sig_type == ns_t_any) { - /* - * We'll also accept a numeric RR type, - * for signing RR types that this version - * of named doesn't yet understand. - * In the ns_t_any case, we rely on wordtouint32 - * to fail when scanning the string "ANY". - */ - sig_type = wordtouint32 (buf); - if (wordtouint32_error || sig_type > 0xFFFF) - ERRTO("Unknown RR type in SIG record"); - } - cp = &data[i]; - PUTSHORT((u_int16_t)sig_type, cp); - i += 2; - - /* Algorithm id (8-bit decimal) */ - if (!getmlword(buf, my_buf_size, fp, 0)) - ERRTO("Missing algorithm ID"); - al = wordtouint32(buf); - if (0 == al || wordtouint32_error || 255 <= al) - ERRTO("Bad algorithm number"); - data[i] = (u_char) al; - i++; - - /* - * Labels (8-bit decimal) - */ - if (!getmlword(buf, my_buf_size, fp, 0)) - ERRTO("Missing label count"); - la = wordtouint32(buf); - if (wordtouint32_error || 255 <= la || - (0 == la && *domain != '\0')) - ERRTO("Bad label count number"); - data[i] = (u_char) la; - i++; - - /* - * OTTL (optional u_int32_t) and - * Texp (u_int32_t date) - */ - if (!getmlword(buf, my_buf_size, fp, 0)) - ERRTO("OTTL and expiration time missing"); - /* - * See if OTTL is missing and this is a date. - * This relies on good, silent error checking - * in ns_datetosecs. - */ - exptime = ns_datetosecs(buf, &dateerror); - if (!dateerror) { - /* Output TTL as OTTL */ - origTTL = ttl; - cp = &data[i]; - PUTLONG (origTTL, cp); - i += 4; - } else { - /* Parse and output OTTL; scan TEXP */ - origTTL = wordtouint32(buf); - if (wordtouint32_error || (origTTL > 0x7fffffffU)) - ERRTO("Original TTL value bad"); - cp = &data[i]; - PUTLONG(origTTL, cp); - i += 4; - if (!getmlword(buf, my_buf_size, fp, 0)) - ERRTO("Expiration time missing"); - exptime = ns_datetosecs(buf, &dateerror); - } - if (dateerror || exptime > 0x7fffffff || exptime <= 0) - ERRTO("Invalid expiration time"); - cp = &data[i]; - PUTLONG(exptime, cp); - i += 4; - - /* Tsig (u_int32_t) */ - if (!getmlword(buf, my_buf_size, fp, 0)) - ERRTO("Missing signature time"); - signtime = ns_datetosecs(buf, &dateerror); - if (0 == signtime || dateerror) - ERRTO("Invalid signature time"); - cp = &data[i]; - PUTLONG(signtime, cp); - i += 4; - - /* Kfootprint (unsigned_16) */ - if (!getmlword(buf, my_buf_size, fp, 0)) - ERRTO("Missing key footprint"); - n = wordtouint32(buf); - if (wordtouint32_error || n >= 0x0ffff) - ERRTO("Invalid key footprint"); - cp = &data[i]; - PUTSHORT((u_int16_t)n, cp); - i += 2; - - /* Signer's Name */ - if (!getmlword((char*)buf, my_buf_size, fp, 0)) - ERRTO("Missing signer's name"); - cp = &data[i]; - strcpy((char *)cp, buf); - context = domain_ctx; - MAKENAME_OKZP((char *)cp, data_size); - i += strlen((char *)cp) + 1; - - /* - * Signature (base64 of any length) - * We don't care what algorithm it uses or what - * the internal structure of the BASE64 data is. - */ - if (!getallwords(buf, my_buf_size, fp, 0)) { - siglen = 0; - } else { - cp = &data[i]; - siglen = b64_pton(buf, (u_char*)cp, data_size - i); - if (siglen < 0) - ERRTO("Signature block bad"); - } - - /* set total length and we're done! */ - n = i + siglen; - - /* - * Check signature time, expiration, and adjust TTL. Note - * that all time values are in GMT (UTC), *not* local time. - */ - - now = time (0); /* need to find a better place for this XXX ogud */ - /* Don't let bogus name servers increase the signed TTL */ - if (ttl > origTTL) - ERRTO("TTL is greater than signed original TTL"); - - /* Don't let bogus signers "sign" in the future. */ - if (signtime > (u_int32_t)now) - ERRTO("signature time is in the future"); - - /* Ignore received SIG RR's that are already expired. */ - if (exptime <= (u_int32_t)now) - ERRTO("expiration time is in the past"); - - /* Lop off the TTL at the expiration time. */ - timetilexp = exptime - now; - if (timetilexp < ttl) { - ns_debug(ns_log_load, 1, - "shrinking expiring %s SIG TTL from %d to %d", - p_secstodate(exptime), ttl, timetilexp); - ttl = timetilexp; - } - - /* - * Check algorithm-ID and key structure, for - * the algorithm-ID's that we know about. - */ - switch (al) { - case NS_ALG_MD5RSA: - if (siglen == 0) - ERRTO("No key for RSA algorithm"); - if (siglen < 1) - ERRTO("Signature too short"); - if (siglen > (NS_MD5RSA_MAX_BITS + 7) / 8) - ERRTO("Signature too long"); - break; - - case NS_ALG_DH: - if (siglen < 1) - ERRTO("DH Signature too short"); - break; /* need more tests here */ - - case NS_ALG_DSA: - if (siglen < NS_DSA_SIG_SIZE) - ERRTO("DSS Signature too short"); - else if (siglen > NS_DSA_SIG_SIZE) - ERRTO("DSS Signature too long "); - break; /* need more tests here */ - - case NS_ALG_EXPIRE_ONLY: - if (siglen != 0) - ERRTO( - "Signature supplied to expire-only algorithm"); - break; - case NS_ALG_PRIVATE_OID: - if (siglen == 0) - ERRTO("No ObjectID in key"); - break; - default: - ERRTO("UNKOWN SIG algorithm"); - } - - /* Should we complain about algorithm-ID's that we - don't understand? It may help debug some obscure - cases, but in general we should accept any RR whether - we could cryptographically process it or not; it - may be being published for some newer DNS clients - to validate themselves. */ - - endline(fp); /* flush the rest of the line */ - - return (n); - err: - *errmsg = errtype; - return (-1); -} - -static int -parse_nxt_rr(char *buf, u_char *data, int data_size, FILE *fp, - struct zoneinfo *zp, char *domain, enum context context, - enum transport transport, const char **errmsg) -{ - - /* The NXT record looks like: - Name Cl NXT nextname RRT1 RRT2 MX A SOA ... - - where: Name and Cl are as usual - NXT is a keyword - nextname is the next valid name in the zone after "Name". - All names between the two are known to be nonexistent. - RRT's... are a series of RR type names, which indicate that - RR's of these types are published for "Name", and - that no RR's of any other types are published for "Name". - - When a NXT record is cryptographically signed, it proves the - nonexistence of an RR (actually a whole set of RR's). - */ - int n, errs = 0, i; - u_char *cp; -/* char *origin = zp->z_origin; - int class = zp->z_class; */ - *errmsg = "NXT name error"; - - (void) strcpy((char *)data, buf); - MAKENAME_OKZP((char *)data, data_size); - n = strlen((char *)data) + 1; - cp = n + data; - i = get_nxt_types(cp, fp, zp->z_source); - if( i > 0) - return (n + i); - *errmsg = "NXT type error"; - err: - return (-1); -} - - -static int -parse_cert_rr(char *buf, int buf_len, u_char *data, int data_size, - FILE *fp, const char **errmsg) -{ - /* Cert record looks like: - * Type Key_tag Alg Cert - * Type: certification type number (16) - * Key_tag: tag of corresponding KEY RR (16) - * Alg: algorithm of the KEY RR (8) - * Cert: base64 enocded block - */ - u_char *cp; - u_int32_t cert_type, key_tag, alg; - const char *errtype = "CERT parse error"; - int certlen, i, n, success; - - i = 0; - cp = &data[i]; - cert_type = sym_ston(__p_cert_syms, buf, &success); - if (!success) { - cert_type = wordtouint32(buf); - if (wordtouint32_error || cert_type > 0xFFFF) - ERRTO("CERT type out of range"); - } - if (i + INT16SZ > data_size) - ERRTO("CERT no space"); - PUTSHORT((u_int16_t)cert_type, cp); - i += INT16SZ; - - if (!getmlword((char*)buf, buf_len, fp, 0)) - ERRTO("CERT doesn't specify type"); - - key_tag = wordtouint32(buf); - if (wordtouint32_error || key_tag > 0xFFFF) - ERRTO("CERT KEY tag out of range"); - - if (i + INT16SZ > data_size) - ERRTO("CERT no space"); - PUTSHORT((u_int16_t)key_tag, cp); - i += INT16SZ; - - if (!getmlword(buf, buf_len, fp, 0)) - ERRTO("CERT missing algorithm ID"); - - alg = sym_ston(__p_key_syms, buf, &success); - if (!success) { - alg = wordtouint32(buf); - if (wordtouint32_error || alg > 0xFF) - ERRTO("CERT KEY alg out of range"); - } - if (i + 1 > data_size) - ERRTO("CERT no space"); - data[i++] = (u_char)alg; - - if (!getallwords(buf, buf_len, fp, 0)) { - certlen = 0; - } - else { - cp = &data[i]; - certlen = b64_pton(buf, (u_char*)cp, data_size - i); - if (certlen < 0) - ERRTO("CERT blob has encoding error"); - } - /* set total length */ - n = i + certlen; - return (n); - err: - *errmsg = errtype; - return (-1); - -} - -static int -parse_key_rr(char *buf, int buf_len, u_char *data, int data_size, - FILE *fp, const char **errmsg) -{ - /* The KEY record looks like this in the db file: - * Name Cl KEY Flags Proto Algid PublicKeyData - * where: - * Name,Cl per usual - * KEY RR type - * Flags 4 digit hex value (unsigned_16) - * Proto 8 bit u_int - * Algid 8 bit u_int - * PublicKeyData - * a string of base64 digits, - * skipping any embedded whitespace. - */ - u_int32_t al, pr; - int nk, klen,i, n; - u_int32_t keyflags; - const char *errtype = "KEY error"; - u_char *cp, *expstart; - u_int expbytes, modbytes; - - i = n = 0; - data[i] = '\0'; - cp = data; - getmlword_nesting = 0; /* KLUDGE err recov. */ - - /*>>> Flags (unsigned_16) */ - keyflags = wordtouint32(buf); - if (wordtouint32_error || 0xFFFF < keyflags) - ERRTO("KEY flags error"); - if (keyflags & NS_KEY_RESERVED_BITMASK) - ERRTO("KEY Reserved Flag Bit"); - PUTSHORT(keyflags, cp); - - /*>>> Protocol (8-bit decimal) */ - if (!getmlword((char*)buf, buf_len, fp, 0)) - ERRTO("KEY Protocol Field"); - pr = wordtouint32(buf); - if (wordtouint32_error || 255 < pr) - ERRTO("KEY Protocol Field"); - *cp++ = (u_char) pr; - - /*>>> Algorithm id (8-bit decimal) */ - if (!getmlword((char*)buf, buf_len, fp, 0)) - ERRTO("KEY Algorithm ID"); - al = wordtouint32(buf); - if (wordtouint32_error || 0 == al || 255 == al || 255 < al) - ERRTO("KEY Algorithm ID"); - *cp++ = (u_char) al; - - /*>>> Extended KEY flag field in bytes 5 and 6 */ - if (NS_KEY_EXTENDED_FLAGS & keyflags) { - u_int32_t keyflags2; - - if (!getmlword((char*)buf, buf_len, fp, 0)) - ERRTO("KEY Flags Field"); - keyflags2 = wordtouint32(buf); - if (wordtouint32_error || 0xFFFF < keyflags2) - ERRTO("Extended key flags error"); - if (keyflags2 & NS_KEY_RESERVED_BITMASK2) - ERRTO("KEY Reserved Flag2 Bit"); - PUTSHORT(keyflags2, cp); - } - - /*>>> Public Key data is in BASE64. - * We don't care what algorithm it uses or what - * the internal structure of the BASE64 data is. - */ - if (!getallwords(buf, MAXDATA, fp, 0)) - klen = 0; - else { - /* Convert from BASE64 to binary. */ - klen = b64_pton(buf, (u_char*)cp, - data_size - (cp - data)); - if (klen < 0) - ERRTO("KEY Public Key"); - } - - /* set total length */ - n = klen + (cp - data); - - /* - * Now check for valid key flags & algs & etc, from the RFC. - */ - - if (NS_KEY_TYPE_NO_KEY == (keyflags & NS_KEY_TYPEMASK)) - nk = 1; /* No-key */ - else - nk = 0; /* have a key */ - - if ((keyflags & (NS_KEY_NAME_TYPE | NS_KEY_TYPEMASK)) == - (NS_KEY_NAME_ZONE | NS_KEY_TYPE_CONF_ONLY)) - /* Zone key must have Auth bit set. */ - ERRTO("KEY Zone Key Auth. bit"); - - if (al == 0 && nk == 0) - ERRTO("KEY Algorithm"); - if (al != 0 && pr == 0) - ERRTO("KEY Protocols"); - - if (nk == 1 && klen != 0) - ERRTO("KEY No-Key Flags Set"); - - if (nk == 0 && klen == 0) - ERRTO("KEY Type Spec'd"); - - /* - * Check algorithm-ID and key structure, for the algorithm-ID's - * that we know about. - */ - switch (al) { - case NS_ALG_MD5RSA: - if (klen == 0) - break; - expstart = cp; - expbytes = *expstart++; - if (expbytes == 0) - GETSHORT(expbytes, expstart); - - if (expbytes < 1) - ERRTO("Exponent too short"); - if (expbytes > (NS_MD5RSA_MAX_BITS + 7) / 8) - ERRTO("Exponent too long"); - if (*expstart == 0) - ERRTO("Exponent w/ 0"); - - modbytes = klen - (expbytes + (expstart - cp)); - if (modbytes < (NS_MD5RSA_MIN_BITS + 7) / 8) - ERRTO("Modulus too short"); - if (modbytes > (NS_MD5RSA_MAX_BITS + 7) / 8) - ERRTO("Modulus too long"); - if (*(expstart+expbytes) == 0) - ERRTO("Modulus starts w/ 0"); - break; - - case NS_ALG_DH: { - u_char *dh_cp; - u_int16_t dh_len, plen, glen, ulen; - - dh_cp = (u_char *)cp; - GETSHORT(plen, dh_cp); - if(plen < 16) - ERRTO("DH short plen"); - dh_len = 2 + plen; - if(dh_len > klen) - ERRTO("DH plen > klen"); - - GETSHORT(glen, dh_cp); - if(glen <= 0 || glen > plen) - ERRTO("DH glen bad"); - dh_len = 2 + glen; - if(dh_len > klen) - ERRTO("DH glen > klen"); - - GETSHORT(ulen, dh_cp); - if(ulen <= 0 || ulen > plen) - ERRTO("DH ulen bad"); - dh_len = 2 + ulen; - if(dh_len > klen) - ERRTO("DH ulen > klen"); - else if (dh_len < klen) - ERRTO("DH *len < klen"); - break; - } - - case NS_ALG_DSA: { - u_int8_t t; - - if ( klen == 0) - break; - t = *cp; - if (t > 8) - ERRTO("DSA T value"); - if (klen != (1 + 20 + 3 *(64+8*t))) - ERRTO("DSA length"); - break; - } - - case NS_ALG_PRIVATE_OID: - if (klen == 0) - ERRTO("No ObjectID in key"); - break; - default: - ERRTO("Unknown Key algorithm"); - } - - endline(fp); /* flush the rest of the line */ - return (n); - err: - *errmsg = errtype; - return (-1); -} /*T_KEY*/ - -/* - * function to invoke DNSSEC specific parsing routines. - * this is simpler than copying these complicated blocks into the - * multiple souce files that read files (ixfr, nsupdate etc..). - * this code should be in a library rather than in this file but - * what the heck for now (ogud@tislabs.com) - */ -int -parse_sec_rdata(char *buf, int buf_len, int buf_full, u_char *data, - int data_size, FILE *fp, struct zoneinfo *zp, - char *domain, u_int32_t ttl, int type, enum context context, - enum transport transport, const char **errmsg) -{ - int ret = -1; - - getmlword_nesting = 0; /* KLUDGE err recov. */ - if (!buf_full && buf && buf_len != 0) /* check if any data in buf */ - if (!getmlword(buf, buf_len, fp, 1)) { - *errmsg = "unexpected end of input"; - goto err; - } - - switch (type) { - case ns_t_sig: - ret = parse_sig_rr(buf, buf_len, data, data_size, fp, zp, - domain, ttl, context, transport, errmsg); - break; - case ns_t_key: - ret = parse_key_rr(buf, buf_len, data, data_size, fp, errmsg); - break; - case ns_t_nxt: - ret = parse_nxt_rr(buf, data, data_size, fp, zp, - domain, context, transport, errmsg); - break; - case ns_t_cert: - ret = parse_cert_rr(buf, buf_len, data, data_size, fp, errmsg); - break; - default: - ret = -1; - *errmsg = "parse_sec_rdata():Unsupported SEC type type"; - goto err; - } - return (ret); - err: - endline(fp); - return (ret); -} |