diff options
Diffstat (limited to 'contrib/bind/bin/named/db_update.c')
-rw-r--r-- | contrib/bind/bin/named/db_update.c | 141 |
1 files changed, 101 insertions, 40 deletions
diff --git a/contrib/bind/bin/named/db_update.c b/contrib/bind/bin/named/db_update.c index ab70663..ea0176e 100644 --- a/contrib/bind/bin/named/db_update.c +++ b/contrib/bind/bin/named/db_update.c @@ -1,6 +1,6 @@ #if !defined(lint) && !defined(SABER) -static char sccsid[] = "@(#)db_update.c 4.28 (Berkeley) 3/21/91"; -static char rcsid[] = "$Id: db_update.c,v 8.23 1998/02/13 20:01:38 halley Exp $"; +static const char sccsid[] = "@(#)db_update.c 4.28 (Berkeley) 3/21/91"; +static const char rcsid[] = "$Id: db_update.c,v 8.39 1999/10/15 19:48:59 vixie Exp $"; #endif /* not lint */ /* @@ -57,7 +57,7 @@ static char rcsid[] = "$Id: db_update.c,v 8.23 1998/02/13 20:01:38 halley Exp $" */ /* - * Portions Copyright (c) 1996, 1997 by Internet Software Consortium. + * Portions Copyright (c) 1996-1999 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 @@ -78,6 +78,7 @@ static char rcsid[] = "$Id: db_update.c,v 8.23 1998/02/13 20:01:38 halley Exp $" #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> +#include <sys/un.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -116,7 +117,7 @@ isRefByNS(const char *name, struct hashbuf *htp) { dp->d_class == C_HS) && dp->d_type == T_NS && !dp->d_rcode && - !strcasecmp(name, (char *)dp->d_data)) { + ns_samename(name, (char *)dp->d_data) == 1) { return (1); } } @@ -153,21 +154,18 @@ findMyZone(struct namebuf *np, int class) { * the cache or an authoritative zone, depending). */ for (dp = np->n_data; dp; dp = dp->d_next) - if (match(dp, class, T_SOA)) + if (match(dp, class, T_SOA) && dp->d_type == T_SOA) return (dp->d_zone); /* if we find an NS at some node without having seen an SOA * (above), then we're out in the cache somewhere. */ for (dp = np->n_data; dp; dp = dp->d_next) - if (match(dp, class, T_NS)) + if (match(dp, class, T_NS) && dp->d_type == T_NS) return (DB_Z_CACHE); } - /* getting all the way to the root without finding an NS or SOA - * probably means that we are in deep dip, but we'll treat it as - * being in the cache. (XXX?) - */ + /* The cache has not yet been primed. */ return (DB_Z_CACHE); } @@ -226,12 +224,11 @@ db_update(const char *name, struct namebuf *np; int zn, isHintNS; int check_ttl = 0; + int deleted_something = 0; const char *fname; #ifdef BIND_UPDATE - int i, found_other_ns = 0; + int found_other_ns = 0; struct databuf *tmpdp; - u_char *cp1, *cp2; - u_int32_t dp_serial, newdp_serial; #endif ns_debug(ns_log_db, 3, "db_update(%s, %#x, %#x, %#x, 0%o, %#x)%s", @@ -320,6 +317,7 @@ db_update(const char *name, dp->d_zone = DB_Z_CACHE; dp->d_flags = DB_F_HINT; dp->d_cred = DB_C_CACHE; + dp->d_secure = odp->d_secure; /* BEW - this should be ok */ dp->d_clev = 0; if (db_update(name, dp, dp, NULL, @@ -337,7 +335,7 @@ db_update(const char *name, pdp = NULL; for (dp = np->n_data; dp != NULL; ) { - if (!match(dp, odp->d_class, odp->d_type)) { + if (!rrmatch(name, dp, odp)) { /* {class,type} doesn't match. these are * the aggregation cases. */ @@ -368,6 +366,9 @@ db_update(const char *name, ns_info(ns_log_db, "%s has CNAME and other data (invalid)", name); + if (zones[odp->d_zone].z_type == + Z_PRIMARY) + return (CNAMEANDOTHER); goto skip; } if (!newdp || newdp->d_class != dp->d_class) @@ -394,7 +395,7 @@ db_update(const char *name, return (AUTH); #endif - /* if the new data is authoritative but + /* if the new data is authoritative * but isn't as credible, reject it. */ if (newdp->d_cred == DB_C_ZONE && @@ -406,6 +407,11 @@ db_update(const char *name, * upper zone's file and is therefore * glue. */ + + /* BEW/OG: we see no reason to override + * these rules with new security based + * rules. + */ if (newdp->d_clev < dp->d_clev) { if (!ISVALIDGLUE(newdp)) { ns_info(ns_log_db, @@ -431,7 +437,8 @@ db_update(const char *name, /* process NXDOMAIN */ /* policy */ if (newdp->d_rcode == NXDOMAIN) { - if (dp->d_cred < DB_C_AUTH) + if (dp->d_cred < DB_C_AUTH && + newdp->d_secure >= dp->d_secure) goto delete; else return (DATAEXISTS); @@ -455,24 +462,37 @@ db_update(const char *name, db_cmp(dp, odp)); if (newdp) { ns_debug(ns_log_db, 4, - "credibility for %s is %d(%d) from [%s].%d, is %d(%d) in cache", +"credibility for %s is %d(%d)(sec %d) from [%s].%d, is %d(%d)(sec %d) in cache", *name ? name : ".", newdp->d_cred, newdp->d_clev, + newdp->d_secure, inet_ntoa(from.sin_addr), ntohs(from.sin_port), dp->d_cred, + dp->d_secure, dp->d_clev); - if (newdp->d_cred > dp->d_cred) { - /* better credibility. + if ((newdp->d_secure > dp->d_secure) || + (newdp->d_secure == dp->d_secure && + (newdp->d_cred > dp->d_cred))) + { + /* better credibility / security. * remove the old datum. */ goto delete; } - if (newdp->d_cred < dp->d_cred) { - /* credibility is worse. ignore it. */ + if ((newdp->d_secure < dp->d_secure) || + (newdp->d_secure == dp->d_secure && + (newdp->d_cred < dp->d_cred))) + { + /* credibility / security is worse. + * ignore it. + */ return (AUTH); } + /* BEW/OG: from above, we know the security + * levels are the same. + */ if (newdp->d_cred == DB_C_ZONE && dp->d_cred == DB_C_ZONE ) { /* Both records are from a zone file. @@ -566,8 +586,19 @@ db_update(const char *name, INT32SZ + sizeof(u_char))) goto delete; if (dp->d_type == T_CNAME && - !NS_OPTION_P(OPTION_MULTIPLE_CNAMES)) - goto delete; + !NS_OPTION_P(OPTION_MULTIPLE_CNAMES) && + db_cmp(dp, odp) != 0) + if ((flags & DB_REPLACE) == 0 && + zones[dp->d_zone].z_type == + Z_PRIMARY) { + ns_info(ns_log_db, + "%s has multiple CNAMES", + name); + return (CNAMEANDOTHER); + } else + goto delete; +#if 0 +/* BEW - this _seriously_ breaks DNSSEC. Is it necessary for dynamic update? */ #ifdef BIND_UPDATE if (dp->d_type == T_SIG) /* @@ -576,6 +607,20 @@ db_update(const char *name, */ goto delete; #endif +#endif + if (dp->d_type == T_NXT) { + goto delete; + } + if (dp->d_type == T_SIG && + SIG_COVERS(dp) == T_NXT) { + struct sig_record *sr1, *sr2; + + sr1 = (struct sig_record *) dp->d_data; + sr2 = (struct sig_record *) + newdp->d_data; + if (sr1->sig_alg_n == sr2->sig_alg_n) + goto delete; + } if (check_ttl) { if (newdp->d_ttl != dp->d_ttl) ns_warning(ns_log_db, @@ -621,11 +666,13 @@ db_update(const char *name, goto skip; if (odp->d_clev < dp->d_clev) goto skip; - if (odp->d_cred < dp->d_cred) + if ((odp->d_secure < dp->d_secure) || + ((odp->d_secure == dp->d_secure) && + (odp->d_cred < dp->d_cred))) goto skip; #ifdef BIND_UPDATE - if (!strcasecmp(name, zones[dp->d_zone].z_origin) && - !newdp) { + if (ns_samename(name, zones[dp->d_zone].z_origin) == 1 + && newdp == NULL) { /* do not delete SOA or NS records as a set */ /* XXXRTH isn't testing d_size unnecessary? */ if ((odp->d_size == 0) && @@ -677,6 +724,7 @@ db_update(const char *name, if (savedpp != NULL) foundRR = 1; #endif + deleted_something = 1; dp = rm_datum(dp, np, pdp, savedpp); } else { skip: pdp = dp; @@ -690,10 +738,16 @@ db_update(const char *name, return (NODATA); } } - /* XXX: delete a terminal namebuf also if all databuf's - * underneath of it have been deleted) */ - if (newdp == NULL) + if (newdp == NULL) { + if (deleted_something) { + while (np->n_data == NULL && np->n_hash == NULL) { + np = purge_node(htp, np); + if (np == NULL) + break; + } + } return (OK); + } /* XXX: empty nodes bypass credibility checks above; should check * response source address here if flags&NOTAUTH. */ @@ -790,7 +844,10 @@ db_cmp(const struct databuf *dp1, const struct databuf *dp2) { case T_MG: case T_MR: /* Only a domain name */ - return (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data)); + if (ns_samename((char *)dp1->d_data, (char *)dp2->d_data) == 1) + return (0); + else + return (1); case T_SIG: /* Binary data, a domain name, more binary data */ @@ -800,8 +857,8 @@ db_cmp(const struct databuf *dp1, const struct databuf *dp2) { return (1); len = NS_SIG_SIGNER + strlen((char *)dp1->d_data + NS_SIG_SIGNER); - if (strcasecmp((char *)dp1->d_data + NS_SIG_SIGNER, - (char *)dp2->d_data + NS_SIG_SIGNER)) + if (ns_samename((char *)dp1->d_data + NS_SIG_SIGNER, + (char *)dp2->d_data + NS_SIG_SIGNER) != 1) return (1); return (memcmp(dp1->d_data + len, dp2->d_data + len, @@ -809,7 +866,7 @@ db_cmp(const struct databuf *dp1, const struct databuf *dp2) { case T_NXT: /* First a domain name, then binary data */ - if (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data)) + if (ns_samename((char *)dp1->d_data, (char *)dp2->d_data) != 1) return (1); len = strlen((char *)dp1->d_data)+1; return (memcmp(dp1->d_data + len, @@ -837,14 +894,14 @@ db_cmp(const struct databuf *dp1, const struct databuf *dp2) { case T_SOA: case T_MINFO: case T_RP: - if (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data)) + if (ns_samename((char *)dp1->d_data, (char *)dp2->d_data) != 1) return (1); cp1 = dp1->d_data + strlen((char *)dp1->d_data) + 1; cp2 = dp2->d_data + strlen((char *)dp2->d_data) + 1; - if (dp1->d_type != T_SOA) - return (strcasecmp((char *)cp1, (char *)cp2)); - if (strcasecmp((char *)cp1, (char *)cp2)) + if (ns_samename((char *)cp1, (char *)cp2) != 1) return (1); + if (dp1->d_type != T_SOA) + return (0); cp1 += strlen((char *)cp1) + 1; cp2 += strlen((char *)cp2) + 1; return (memcmp(cp1, cp2, INT32SZ * 5)); @@ -907,18 +964,22 @@ db_cmp(const struct databuf *dp1, const struct databuf *dp2) { if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* port */ return (1); } - return (strcasecmp((char *)cp1, (char *)cp2)); + if (ns_samename((char *)cp1, (char *)cp2) != 1) + return (1); + return (0); case T_PX: cp1 = dp1->d_data; cp2 = dp2->d_data; if (*cp1++ != *cp2++ || *cp1++ != *cp2++) /* cmp prio */ return (1); - if (strcasecmp((char *)cp1, (char *)cp2)) + if (ns_samename((char *)cp1, (char *)cp2) != 1) return (1); cp1 += strlen((char *)cp1) + 1; cp2 += strlen((char *)cp2) + 1; - return (strcasecmp((char *)cp1, (char *)cp2)); + if (ns_samename((char *)cp1, (char *)cp2) != 1) + return (1); + return (0); case T_TXT: case T_X25: |