[ldns-users] [PATCH 1/3] Add an anchor keyword to the resolver configuration

Simon Vallet svallet at genoscope.cns.fr
Mon May 14 10:16:00 UTC 2007


this one adds an anchor keyword to the resolver configuration, allowing
for trust anchors in ldns.

Simon

Index: ldns/resolver.h
===================================================================
--- ldns/resolver.h	(revision 2344)
+++ ldns/resolver.h	(working copy)
@@ -39,8 +39,9 @@
 #define LDNS_RESOLV_SEARCH	2
 #define LDNS_RESOLV_SORTLIST	3
 #define LDNS_RESOLV_OPTIONS	4
+#define LDNS_RESOLV_ANCHOR	5
 
-#define LDNS_RESOLV_KEYWORDS    5
+#define LDNS_RESOLV_KEYWORDS    6
 
 #define LDNS_RESOLV_INETANY		0
 #define LDNS_RESOLV_INET		1
@@ -62,8 +63,8 @@
 	/** Number of nameservers in \c _nameservers */
 	size_t _nameserver_count; /* how many do we have */
 
-        /**  Round trip time; 0 -> infinity. Unit: ms? */
-        size_t *_rtt;
+	/**  Round trip time; 0 -> infinity. Unit: ms? */
+	size_t *_rtt;
 
 	/**  Wether or not to be recursive */
 	bool _recursive;
@@ -89,6 +90,8 @@
 	bool _dnssec;
 	/**  Whether to set the CD bit on DNSSEC requests */
 	bool _dnssec_cd;
+	/** Optional trust anchors for complete DNSSEC validation */
+	ldns_rr_list * _dnssec_anchors;
 	/**  Whether to use tcp or udp (tcp if the value is true)*/
 	bool _usevc;
 	/**  Whether to ignore the tc bit */
@@ -209,6 +212,12 @@
  */
 bool ldns_resolver_dnssec_cd(const ldns_resolver *r);
 /**
+ * Get the resolver's DNSSEC anchors
+ * \param[in] r the resolver
+ * \return an rr_list containg trusted DNSSEC anchors
+ */
+ldns_rr_list * ldns_resolver_dnssec_anchors(const ldns_resolver *r);
+/**
  * Does the resolver ignore the TC bit (truncated)
  * \param[in] r the resolver
  * \return true: yes, false: no
@@ -409,6 +418,21 @@
  */
 void ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool b);
 /**
+ * Set the resolver's DNSSEC anchor list directly. RRs should be of type DS or DNSKEY.
+ * \param[in] r the resolver
+ * \param[in] l the list of RRs to use as trust anchors
+ */
+void ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l);
+
+/**
+ * Push a new trust anchor to the resolver. It must be a DS or DNSKEY rr
+ * \param[in] r the resolver.
+ * \param[in] rr the RR to add as a trust anchor.
+ * \return a status
+ */
+ldns_status ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr);
+
+/**
  * Set the resolver retrans timeout (in seconds)
  * \param[in] r the resolver
  * \param[in] re the retransmission interval in seconds
@@ -655,4 +679,20 @@
  */
 void ldns_resolver_nameservers_randomize(ldns_resolver *r);
 
+/** 
+ * Returns true if at least one of the provided keys is a trust anchor
+ * \param[in] r the current resolver
+ * \param[in] keys the keyset to check
+ * \param[out] trusted_keys the subset of trusted keys in the 'keys' rrset
+ * \return true if at least one of the provided keys is a configured trust anchor
+ */
+bool ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys);
+
+/**
+ * Instantiates a DNSKEY or DS RR from file.
+ * \param[in] filename the file to read the record from
+ * \return the corresponding RR, or NULL if the parsing failed
+ */
+ldns_rr * ldns_read_anchor_file(const char *filename);
+
 #endif  /* LDNS_RESOLVER_H */
Index: resolver.c
===================================================================
--- resolver.c	(revision 2344)
+++ resolver.c	(working copy)
@@ -116,7 +116,34 @@
 	return r->_dnssec_cd;
 }
 
+ldns_rr_list *
+ldns_resolver_dnssec_anchors(const ldns_resolver *r)
+{
+    return r->_dnssec_anchors;
+}
+
 bool
+ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
+{
+  unsigned int i; bool result = false;
+  ldns_rr_list * trust_anchors = ldns_resolver_dnssec_anchors(r);
+  ldns_rr * cur_rr;
+
+  if (!r || !trust_anchors || !keys) { return false; }
+
+  for (i=0; i< ldns_rr_list_rr_count(keys); i++) {
+
+    cur_rr = ldns_rr_list_rr(keys, i);
+    if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) {      
+      if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); }
+      result = true;
+    }
+  }
+
+  return result;
+}
+
+bool
 ldns_resolver_igntc(const ldns_resolver *r)
 {
 	return r->_igntc;
@@ -316,6 +343,29 @@
 }
 
 void
+ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
+{
+  r->_dnssec_anchors = l;
+}
+
+ldns_status
+ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr)
+{
+  ldns_rr_list * trust_anchors;
+
+  if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY)) {
+    return LDNS_STATUS_ERR;
+  }
+
+  if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */
+    trust_anchors = ldns_rr_list_new();
+    ldns_resolver_set_dnssec_anchors(r, trust_anchors);
+  }
+
+  return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
+}
+
+void
 ldns_resolver_set_igntc(ldns_resolver *r, bool i)
 {
 	r->_igntc = i;
@@ -519,6 +569,7 @@
 	ldns_resolver_set_edns_udp_size(r, 0);
 	ldns_resolver_set_dnssec(r, false);
 	ldns_resolver_set_dnssec_cd(r, false);
+	ldns_resolver_set_dnssec_anchors(r, NULL);
 	ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY);
 
 	/* randomize the nameserver to be queried
@@ -557,6 +608,7 @@
 	int8_t expect;
 	uint8_t i;
 	ldns_rdf *tmp;
+	ldns_rr *tmp_rr;
 	ssize_t gtr;
 	ldns_buffer *b;
 
@@ -574,6 +626,7 @@
 	/* these two are read but not used atm TODO */
 	keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
 	keyword[LDNS_RESOLV_OPTIONS] = "options";
+	keyword[LDNS_RESOLV_ANCHOR] = "anchor";
 	expect = LDNS_RESOLV_KEYWORD;
 
 	r = ldns_resolver_new();
@@ -687,6 +740,18 @@
 				/* options not implemented atm */
 				expect = LDNS_RESOLV_KEYWORD;
 				break;
+			case LDNS_RESOLV_ANCHOR:
+				/* a file containing a DNSSEC trust anchor */
+				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
+				if (gtr == 0) {
+					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
+				}
+
+				tmp_rr = ldns_read_anchor_file(word);
+				ldns_resolver_push_dnssec_anchor(r, tmp_rr);
+				ldns_rr_free(tmp_rr);
+				expect = LDNS_RESOLV_KEYWORD;
+				break;
 		}
 	}
 	
@@ -766,6 +831,9 @@
 		if (res->_rtt) {
 			LDNS_FREE(res->_rtt);
 		}
+		if (res->_dnssec_anchors) {
+			ldns_rr_list_deep_free(res->_dnssec_anchors);
+		}
 		LDNS_FREE(res);
 	}
 }
@@ -1073,3 +1141,41 @@
 	}
 	ldns_resolver_set_nameservers(r, ns);
 }
+
+ldns_rr *
+ldns_read_anchor_file(const char *filename)
+{
+  FILE *fp;
+  char line[LDNS_MAX_PACKETLEN];
+  int c;
+  size_t i = 0;
+  ldns_rr *r;
+  ldns_status status;
+
+  fp = fopen(filename, "r");
+  if (!fp) {
+    fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
+    return NULL;
+  }
+	
+  while ((c = fgetc(fp)) && i < LDNS_MAX_PACKETLEN && c != EOF) {
+    line[i] = c;
+    i++;
+  }
+  line[i] = '\0';
+	
+  fclose(fp);
+	
+  if (i <= 0) {
+    fprintf(stderr, "nothing read from %s", filename);
+    return NULL;
+  } else {
+    status = ldns_rr_new_frm_str(&r, line, 0, NULL, NULL);
+    if (status == LDNS_STATUS_OK && (ldns_rr_get_type(r) == LDNS_RR_TYPE_DNSKEY || ldns_rr_get_type(r) == LDNS_RR_TYPE_DS)) {
+      return r;
+    } else {
+      fprintf(stderr, "Error creating DNSKEY or DS rr from %s: %s\n", filename, ldns_get_errorstr_by_id(status));
+      return NULL;
+    }
+  }
+}



More information about the ldns-users mailing list