diff options
author | Joanna Hulboj <joanna.hulboj@isode.com> | 2019-05-24 09:30:14 (GMT) |
---|---|---|
committer | Joanna Hulboj <joanna.hulboj@isode.com> | 2019-05-28 15:14:50 (GMT) |
commit | f4b6bfbf4c1573e9914185e2ef170f47838ea11a (patch) | |
tree | b87b2442cda92bb70be95a64b3b8295c37fe8d9f | |
parent | 09d8ac653493a0bd16cb69664ca28fbfe3c61bbb (diff) | |
download | swift-f4b6bfbf4c1573e9914185e2ef170f47838ea11a.zip swift-f4b6bfbf4c1573e9914185e2ef170f47838ea11a.tar.bz2 |
Add check if IPv4, IPv6 are valid JID domain part
When creating a JID we were not checking if a
domain part is a valid IPv4, IPv6 addresses. We were
only checking if the domain is correct according to
internationalized domain name rules which was failing
for IPv6 addresses.
Test-Information:
Unit tests pass on Windows 10 and Ubuntu 18.04.1 LTS
Change-Id: Ia1b67089f6edfdc6a0ebf2d26a7eaab9ce8171c0
-rw-r--r-- | Swiften/JID/JID.cpp | 41 | ||||
-rw-r--r-- | Swiften/JID/JID.h | 1 | ||||
-rw-r--r-- | Swiften/JID/UnitTest/JIDTest.cpp | 46 |
3 files changed, 85 insertions, 3 deletions
diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp index fff88e9..5c6ea9d 100644 --- a/Swiften/JID/JID.cpp +++ b/Swiften/JID/JID.cpp @@ -15,2 +15,3 @@ #include <Swiften/JID/JID.h> +#include <Swiften/Network/HostAddress.h> @@ -99,5 +100,16 @@ void JID::initializeFromString(const std::string& jid) { +void JID::setComponents(const std::string& node, const std::string& domain, const std::string& resource) { + domain_ = domain; + try { + node_ = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep); + resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); + } + catch (...) { + valid_ = false; + return; + } +} void JID::nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource) { - if (domain.empty() || !idnConverter->getIDNAEncoded(domain)) { + if (domain.empty() || (hasResource_ && resource.empty())) { valid_ = false; @@ -106,3 +118,25 @@ void JID::nameprepAndSetComponents(const std::string& node, const std::string& d - if (hasResource_ && resource.empty()) { + // Handling IPv6 addresses according to RFC 3986 rules + // saying that they are enclosed in square brackets + // which we have to remove when passing to HostAddress + if (domain.size() > 2 && domain.front() == '[' && domain.back() == ']') { + auto inner = std::string(domain.begin() + 1, domain.end() - 1); + auto hostAddress = HostAddress::fromString(inner); + if (hostAddress && hostAddress->isValid()) { + setComponents(node, domain, resource); + return; + } + } + + const auto isAnyOfNonNumericAndNotDot = std::any_of(std::begin(domain), std::end(domain), [](char c) {return !::isdigit(c) && c != '.'; }); + + if (!isAnyOfNonNumericAndNotDot) { + auto hostAddress = HostAddress::fromString(domain); + if (hostAddress && hostAddress->isValid()) { + setComponents(node, domain, resource); + return; + } + } + + if (!isAnyOfNonNumericAndNotDot || !idnConverter->getIDNAEncoded(domain)) { valid_ = false; @@ -120,3 +154,4 @@ void JID::nameprepAndSetComponents(const std::string& node, const std::string& d resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); - } catch (...) { + } + catch (...) { valid_ = false; diff --git a/Swiften/JID/JID.h b/Swiften/JID/JID.h index dc92f53..e98b796 100644 --- a/Swiften/JID/JID.h +++ b/Swiften/JID/JID.h @@ -186,2 +186,3 @@ namespace Swift { void nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource); + void setComponents(const std::string& node, const std::string& domain, const std::string& resource); void initializeFromString(const std::string&); diff --git a/Swiften/JID/UnitTest/JIDTest.cpp b/Swiften/JID/UnitTest/JIDTest.cpp index 0753fb5..894378d 100644 --- a/Swiften/JID/UnitTest/JIDTest.cpp +++ b/Swiften/JID/UnitTest/JIDTest.cpp @@ -73,2 +73,8 @@ class JIDTest : public CppUnit::TestFixture CPPUNIT_TEST(testStringPrepFailures); + CPPUNIT_TEST(testConstructorWithString_DomainIPv4); + CPPUNIT_TEST(testConstructorWithString_DomainNOTIPv4); + CPPUNIT_TEST(testConstructorWithString_ValidDomainNOTIPv4); + CPPUNIT_TEST(testConstructorWithString_DomainIPv6); + CPPUNIT_TEST(testConstructorWithString_DomainInvalidIPv6); + CPPUNIT_TEST(testConstructorWithString_DomainIPv6NoBrackets); CPPUNIT_TEST_SUITE_END(); @@ -494,2 +500,42 @@ class JIDTest : public CppUnit::TestFixture } + + void testConstructorWithString_DomainIPv4() { + JID testling("foo@192.34.12.1/resource"); + + CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("192.34.12.1"), testling.getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("resource"), testling.getResource()); + CPPUNIT_ASSERT(!testling.isBare()); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_DomainNOTIPv4() { + JID testling("foo@500.34.12.1/resource"); + CPPUNIT_ASSERT(!testling.isValid()); + } + + void testConstructorWithString_ValidDomainNOTIPv4() { + JID testling("foo@500.34.12.1a/resource"); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_DomainIPv6() { + JID testling("foo@[fe80::a857:33ff:febd:3580]/resource"); + + CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("[fe80::a857:33ff:febd:3580]"), testling.getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("resource"), testling.getResource()); + CPPUNIT_ASSERT(!testling.isBare()); + CPPUNIT_ASSERT(testling.isValid()); + } + + void testConstructorWithString_DomainInvalidIPv6() { + JID testling("foo@[1111::a1111:1111:111!:!!!!]/resource"); + CPPUNIT_ASSERT(!testling.isValid()); + } + + void testConstructorWithString_DomainIPv6NoBrackets() { + JID testling("foo@fe80::a857:33ff:febd:3580/resource"); + CPPUNIT_ASSERT(!testling.isValid()); + } }; |