Browse Source

[2387] Permit missing key data in DNSKEY RDATA

Mukund Sivaraman 12 years ago
parent
commit
dfd5516cd8
2 changed files with 25 additions and 21 deletions
  1. 16 14
      src/lib/dns/rdata/generic/dnskey_48.cc
  2. 9 7
      src/lib/dns/tests/rdata_dnskey_unittest.cc

+ 16 - 14
src/lib/dns/rdata/generic/dnskey_48.cc

@@ -98,14 +98,16 @@ DNSKEY::DNSKEY(InputBuffer& buffer, size_t rdata_len) {
     const uint16_t algorithm = buffer.readUint8();
 
     rdata_len -= 4;
-    // Though the size of the public key is algorithm-dependent, we
-    // assume that it should not be empty.
-    if (rdata_len < 1) {
-        isc_throw(InvalidRdataLength, "DNSKEY keydata too short");
-    }
 
-    vector<uint8_t> keydata(rdata_len);
-    buffer.readData(&keydata[0], rdata_len);
+    vector<uint8_t> keydata;
+    // If key data is missing, it's OK. BIND 9 seems to accept such
+    // cases. What we should do could be debatable, but since this field
+    // is algorithm dependent and our implementation doesn't reject
+    // unknown algorithms, we are lenient here.
+    if (rdata_len > 0) {
+        keydata.resize(rdata_len);
+        buffer.readData(&keydata[0], rdata_len);
+    }
 
     // See RFC 4034 appendix B.1 for why the key data has to be at least
     // 3 bytes long with RSA/MD5.
@@ -178,14 +180,14 @@ DNSKEY::constructFromLexer(MasterLexer& lexer) {
 
     lexer.ungetToken();
 
-    // Check that some key data was read before end of input was
-    // reached.
-    if (keydata_str.size() == 0) {
-        isc_throw(InvalidRdataText, "Missing DNSKEY digest");
-    }
-
     vector<uint8_t> keydata;
-    decodeBase64(keydata_str, keydata);
+    // If key data is missing, it's OK. BIND 9 seems to accept such
+    // cases. What we should do could be debatable, but since this field
+    // is algorithm dependent and our implementation doesn't reject
+    // unknown algorithms, we are lenient here.
+    if (keydata_str.size() > 0) {
+        decodeBase64(keydata_str, keydata);
+    }
 
     // See RFC 4034 appendix B.1 for why the key data has to be at least
     // 3 bytes long with RSA/MD5.

+ 9 - 7
src/lib/dns/tests/rdata_dnskey_unittest.cc

@@ -99,8 +99,8 @@ TEST_F(Rdata_DNSKEY_Test, fromText) {
     // Delimited number in key data is OK
     checkFromText_None("257 3 5 YmluZDEwLmlzYy 5 vcmc=");
 
-    // Key data missing
-    checkFromText_InvalidText("257 3 5");
+    // Missing keydata is OK
+    EXPECT_NO_THROW(const generic::DNSKEY rdata_dnskey3("257 3 5"));
 
     // Flags field out of range
     checkFromText_InvalidText("65536 3 5 YmluZDEwLmlzYy5vcmc=");
@@ -171,11 +171,13 @@ TEST_F(Rdata_DNSKEY_Test, createFromWire) {
     EXPECT_EQ(0, rdata_dnskey.compare(
                   *rdataFactoryFromFile(RRType("DNSKEY"), RRClass("IN"),
                                         "rdata_dnskey_fromWire.wire")));
-    // Empty keydata should throw
-    EXPECT_THROW(rdataFactoryFromFile
-                 (RRType("DNSKEY"), RRClass("IN"),
-                  "rdata_dnskey_empty_keydata_fromWire.wire"),
-                 InvalidRdataLength);
+
+    // Missing keydata is OK
+    const generic::DNSKEY rdata_dnskey_missing_keydata("257 3 5");
+    EXPECT_EQ(0, rdata_dnskey_missing_keydata.compare(
+        *rdataFactoryFromFile(RRType("DNSKEY"), RRClass("IN"),
+                              "rdata_dnskey_empty_keydata_fromWire.wire")));
+
     // Short keydata for RSA/MD5 should throw
     EXPECT_THROW(rdataFactoryFromFile
                  (RRType("DNSKEY"), RRClass("IN"),