Parcourir la source

[2124] Handle empty SSHFP fingerprints

Mukund Sivaraman il y a 12 ans
Parent
commit
3b82a4fda3

+ 18 - 14
src/lib/dns/rdata/generic/sshfp_44.cc

@@ -56,8 +56,6 @@ SSHFP::SSHFP(InputBuffer& buffer, size_t rdata_len) {
 
 SSHFP::SSHFP(const std::string& sshfp_str) {
     std::istringstream iss(sshfp_str);
-    // peekc should be of iss's char_type for isspace to work
-    std::istringstream::char_type peekc;
     std::stringbuf fingerprintbuf;
     uint32_t algorithm, fingerprint_type;
 
@@ -74,21 +72,16 @@ SSHFP::SSHFP(const std::string& sshfp_str) {
         isc_throw(InvalidRdataText, "SSHFP fingerprint type out of range");
     }
 
-    iss.read(&peekc, 1);
-    if (!iss.good() || !isspace(peekc, iss.getloc())) {
-        isc_throw(InvalidRdataText, "SSHFP presentation format error");
-    }
-
     iss >> &fingerprintbuf;
-
-    algorithm_ = algorithm;
-    fingerprint_type_ = fingerprint_type;
-
     try {
         decodeHex(fingerprintbuf.str(), fingerprint_);
     } catch (const isc::BadValue& e) {
-        isc_throw(InvalidRdataText, "Bad SSHFP fingerprint: " << e.what());
+        isc_throw(InvalidRdataText,
+                  "Bad SSHFP fingerprint: " << e.what());
     }
+
+    algorithm_ = algorithm;
+    fingerprint_type_ = fingerprint_type;
 }
 
 SSHFP::SSHFP(uint8_t algorithm, uint8_t fingerprint_type,
@@ -114,14 +107,20 @@ void
 SSHFP::toWire(OutputBuffer& buffer) const {
     buffer.writeUint8(algorithm_);
     buffer.writeUint8(fingerprint_type_);
-    buffer.writeData(&fingerprint_[0], fingerprint_.size());
+
+    if (fingerprint_.size() > 0) {
+        buffer.writeData(&fingerprint_[0], fingerprint_.size());
+    }
 }
 
 void
 SSHFP::toWire(AbstractMessageRenderer& renderer) const {
     renderer.writeUint8(algorithm_);
     renderer.writeUint8(fingerprint_type_);
-    renderer.writeData(&fingerprint_[0], fingerprint_.size());
+
+    if (fingerprint_.size() > 0) {
+        renderer.writeData(&fingerprint_[0], fingerprint_.size());
+    }
 }
 
 string
@@ -172,5 +171,10 @@ SSHFP::getSSHFPFingerprintType() const {
     return (fingerprint_type_);
 }
 
+size_t
+SSHFP::getFingerprintLen() const {
+    return (fingerprint_.size());
+}
+
 // END_RDATA_NAMESPACE
 // END_ISC_NAMESPACE

+ 1 - 0
src/lib/dns/rdata/generic/sshfp_44.h

@@ -40,6 +40,7 @@ public:
     ///
     uint8_t getSSHFPAlgorithmNumber() const;
     uint8_t getSSHFPFingerprintType() const;
+    size_t getFingerprintLen() const;
 
 private:
     /// Note: this is a prototype version; we may reconsider

+ 47 - 1
src/lib/dns/tests/rdata_sshfp_unittest.cc

@@ -41,6 +41,18 @@ class Rdata_SSHFP_Test : public RdataTest {
 
 const string sshfp_txt("2 1 123456789abcdef67890123456789abcdef67890");
 const generic::SSHFP rdata_sshfp(2, 1, "123456789abcdef67890123456789abcdef67890");
+const uint8_t rdata_sshfp_wiredata[] = {
+    // algorithm
+    0x02,
+    // fingerprint type
+    0x01,
+    // fingerprint
+    0x12, 0x34, 0x56, 0x78,
+    0x9a, 0xbc, 0xde, 0xf6,
+    0x78, 0x90, 0x12, 0x34,
+    0x56, 0x78, 0x9a, 0xbc,
+    0xde, 0xf6, 0x78, 0x90
+};
 
 TEST_F(Rdata_SSHFP_Test, createFromText) {
     // Basic test
@@ -84,7 +96,6 @@ TEST_F(Rdata_SSHFP_Test, algorithmTypes) {
 
 TEST_F(Rdata_SSHFP_Test, badText) {
     EXPECT_THROW(const generic::SSHFP rdata_sshfp("1"), InvalidRdataText);
-    EXPECT_THROW(const generic::SSHFP rdata_sshfp("1 2"), InvalidRdataText);
     EXPECT_THROW(const generic::SSHFP rdata_sshfp("BUCKLE MY SHOES"), InvalidRdataText);
     EXPECT_THROW(const generic::SSHFP rdata_sshfp("1 2 foo bar"), InvalidRdataText);
 }
@@ -147,6 +158,18 @@ TEST_F(Rdata_SSHFP_Test, toText) {
     EXPECT_TRUE(boost::iequals(sshfp_txt, rdata_sshfp.toText()));
 }
 
+TEST_F(Rdata_SSHFP_Test, toWire) {
+    this->obuffer.clear();
+    rdata_sshfp.toWire(this->obuffer);
+
+    EXPECT_EQ(22, this->obuffer.getLength());
+
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        this->obuffer.getData(),
+                        this->obuffer.getLength(),
+                        rdata_sshfp_wiredata, sizeof(rdata_sshfp_wiredata));
+}
+
 TEST_F(Rdata_SSHFP_Test, getSSHFPAlgorithmNumber) {
     EXPECT_EQ(2, rdata_sshfp.getSSHFPAlgorithmNumber());
 }
@@ -154,4 +177,27 @@ TEST_F(Rdata_SSHFP_Test, getSSHFPAlgorithmNumber) {
 TEST_F(Rdata_SSHFP_Test, getSSHFPFingerprintType) {
     EXPECT_EQ(1, rdata_sshfp.getSSHFPFingerprintType());
 }
+
+TEST_F(Rdata_SSHFP_Test, getFingerprintLen) {
+    EXPECT_EQ(20, rdata_sshfp.getFingerprintLen());
+}
+
+TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromWire) {
+    const generic::SSHFP& rdf =
+        dynamic_cast<const generic::SSHFP&>
+        (*rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"),
+                               "rdata_sshfp_fromWire12"));
+
+    EXPECT_EQ(4, rdf.getSSHFPAlgorithmNumber());
+    EXPECT_EQ(9, rdf.getSSHFPFingerprintType());
+    EXPECT_EQ(0, rdf.getFingerprintLen());
+}
+
+TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromString) {
+    const generic::SSHFP rdata_sshfp2("5 6");
+
+    EXPECT_EQ(5, rdata_sshfp2.getSSHFPAlgorithmNumber());
+    EXPECT_EQ(6, rdata_sshfp2.getSSHFPFingerprintType());
+    EXPECT_EQ(0, rdata_sshfp2.getFingerprintLen());
+}
 }

+ 1 - 1
src/lib/dns/tests/testdata/Makefile.am

@@ -136,7 +136,7 @@ EXTRA_DIST += rdata_sshfp_fromWire3.spec rdata_sshfp_fromWire4.spec
 EXTRA_DIST += rdata_sshfp_fromWire5.spec rdata_sshfp_fromWire6.spec
 EXTRA_DIST += rdata_sshfp_fromWire7.spec rdata_sshfp_fromWire8.spec
 EXTRA_DIST += rdata_sshfp_fromWire9 rdata_sshfp_fromWire10
-EXTRA_DIST += rdata_sshfp_fromWire11
+EXTRA_DIST += rdata_sshfp_fromWire11 rdata_sshfp_fromWire12
 EXTRA_DIST += rdata_afsdb_fromWire1.spec rdata_afsdb_fromWire2.spec
 EXTRA_DIST += rdata_afsdb_fromWire3.spec rdata_afsdb_fromWire4.spec
 EXTRA_DIST += rdata_afsdb_fromWire5.spec

+ 4 - 0
src/lib/dns/tests/testdata/rdata_sshfp_fromWire12

@@ -0,0 +1,4 @@
+# SSHFP RDATA, RDLEN=02
+0002
+# ALGORITHM=4 FINGERPRINT_TYPE=9
+04 09