summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoanna Hulboj <joanna.hulboj@isode.com>2019-05-24 09:30:14 (GMT)
committerJoanna Hulboj <joanna.hulboj@isode.com>2019-05-28 15:14:50 (GMT)
commitf4b6bfbf4c1573e9914185e2ef170f47838ea11a (patch)
treeb87b2442cda92bb70be95a64b3b8295c37fe8d9f
parent09d8ac653493a0bd16cb69664ca28fbfe3c61bbb (diff)
downloadswift-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.cpp41
-rw-r--r--Swiften/JID/JID.h1
-rw-r--r--Swiften/JID/UnitTest/JIDTest.cpp46
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
@@ -13,6 +13,7 @@
13#include <Swiften/Base/String.h> 13#include <Swiften/Base/String.h>
14#include <Swiften/IDN/IDNConverter.h> 14#include <Swiften/IDN/IDNConverter.h>
15#include <Swiften/JID/JID.h> 15#include <Swiften/JID/JID.h>
16#include <Swiften/Network/HostAddress.h>
16 17
17#ifndef SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER 18#ifndef SWIFTEN_JID_NO_DEFAULT_IDN_CONVERTER
18#include <memory> 19#include <memory>
@@ -97,14 +98,47 @@ void JID::initializeFromString(const std::string& jid) {
97 } 98 }
98} 99}
99 100
101void JID::setComponents(const std::string& node, const std::string& domain, const std::string& resource) {
102 domain_ = domain;
103 try {
104 node_ = idnConverter->getStringPrepared(node, IDNConverter::XMPPNodePrep);
105 resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep);
106 }
107 catch (...) {
108 valid_ = false;
109 return;
110 }
111}
100 112
101void JID::nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource) { 113void JID::nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource) {
102 if (domain.empty() || !idnConverter->getIDNAEncoded(domain)) { 114 if (domain.empty() || (hasResource_ && resource.empty())) {
103 valid_ = false; 115 valid_ = false;
104 return; 116 return;
105 } 117 }
106 118
107 if (hasResource_ && resource.empty()) { 119 // Handling IPv6 addresses according to RFC 3986 rules
120 // saying that they are enclosed in square brackets
121 // which we have to remove when passing to HostAddress
122 if (domain.size() > 2 && domain.front() == '[' && domain.back() == ']') {
123 auto inner = std::string(domain.begin() + 1, domain.end() - 1);
124 auto hostAddress = HostAddress::fromString(inner);
125 if (hostAddress && hostAddress->isValid()) {
126 setComponents(node, domain, resource);
127 return;
128 }
129 }
130
131 const auto isAnyOfNonNumericAndNotDot = std::any_of(std::begin(domain), std::end(domain), [](char c) {return !::isdigit(c) && c != '.'; });
132
133 if (!isAnyOfNonNumericAndNotDot) {
134 auto hostAddress = HostAddress::fromString(domain);
135 if (hostAddress && hostAddress->isValid()) {
136 setComponents(node, domain, resource);
137 return;
138 }
139 }
140
141 if (!isAnyOfNonNumericAndNotDot || !idnConverter->getIDNAEncoded(domain)) {
108 valid_ = false; 142 valid_ = false;
109 return; 143 return;
110 } 144 }
@@ -118,7 +152,8 @@ void JID::nameprepAndSetComponents(const std::string& node, const std::string& d
118 domain_ = idnConverter->getStringPrepared(domain, IDNConverter::NamePrep); 152 domain_ = idnConverter->getStringPrepared(domain, IDNConverter::NamePrep);
119 } 153 }
120 resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep); 154 resource_ = idnConverter->getStringPrepared(resource, IDNConverter::XMPPResourcePrep);
121 } catch (...) { 155 }
156 catch (...) {
122 valid_ = false; 157 valid_ = false;
123 return; 158 return;
124 } 159 }
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
@@ -184,6 +184,7 @@ namespace Swift {
184 184
185 private: 185 private:
186 void nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource); 186 void nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource);
187 void setComponents(const std::string& node, const std::string& domain, const std::string& resource);
187 void initializeFromString(const std::string&); 188 void initializeFromString(const std::string&);
188 189
189 private: 190 private:
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
@@ -71,6 +71,12 @@ class JIDTest : public CppUnit::TestFixture
71 CPPUNIT_TEST(testGetUnescapedNode); 71 CPPUNIT_TEST(testGetUnescapedNode);
72 CPPUNIT_TEST(testGetUnescapedNode_XEP106Examples); 72 CPPUNIT_TEST(testGetUnescapedNode_XEP106Examples);
73 CPPUNIT_TEST(testStringPrepFailures); 73 CPPUNIT_TEST(testStringPrepFailures);
74 CPPUNIT_TEST(testConstructorWithString_DomainIPv4);
75 CPPUNIT_TEST(testConstructorWithString_DomainNOTIPv4);
76 CPPUNIT_TEST(testConstructorWithString_ValidDomainNOTIPv4);
77 CPPUNIT_TEST(testConstructorWithString_DomainIPv6);
78 CPPUNIT_TEST(testConstructorWithString_DomainInvalidIPv6);
79 CPPUNIT_TEST(testConstructorWithString_DomainIPv6NoBrackets);
74 CPPUNIT_TEST_SUITE_END(); 80 CPPUNIT_TEST_SUITE_END();
75 81
76 public: 82 public:
@@ -492,6 +498,46 @@ class JIDTest : public CppUnit::TestFixture
492 CPPUNIT_ASSERT_EQUAL(std::string("c:\\cool stuff"), JID("c\\3a\\cool\\20stuff@example.com").getUnescapedNode()); 498 CPPUNIT_ASSERT_EQUAL(std::string("c:\\cool stuff"), JID("c\\3a\\cool\\20stuff@example.com").getUnescapedNode());
493 CPPUNIT_ASSERT_EQUAL(std::string("c:\\5commas"), JID("c\\3a\\5c5commas@example.com").getUnescapedNode()); 499 CPPUNIT_ASSERT_EQUAL(std::string("c:\\5commas"), JID("c\\3a\\5c5commas@example.com").getUnescapedNode());
494 } 500 }
501
502 void testConstructorWithString_DomainIPv4() {
503 JID testling("foo@192.34.12.1/resource");
504
505 CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode());
506 CPPUNIT_ASSERT_EQUAL(std::string("192.34.12.1"), testling.getDomain());
507 CPPUNIT_ASSERT_EQUAL(std::string("resource"), testling.getResource());
508 CPPUNIT_ASSERT(!testling.isBare());
509 CPPUNIT_ASSERT(testling.isValid());
510 }
511
512 void testConstructorWithString_DomainNOTIPv4() {
513 JID testling("foo@500.34.12.1/resource");
514 CPPUNIT_ASSERT(!testling.isValid());
515 }
516
517 void testConstructorWithString_ValidDomainNOTIPv4() {
518 JID testling("foo@500.34.12.1a/resource");
519 CPPUNIT_ASSERT(testling.isValid());
520 }
521
522 void testConstructorWithString_DomainIPv6() {
523 JID testling("foo@[fe80::a857:33ff:febd:3580]/resource");
524
525 CPPUNIT_ASSERT_EQUAL(std::string("foo"), testling.getNode());
526 CPPUNIT_ASSERT_EQUAL(std::string("[fe80::a857:33ff:febd:3580]"), testling.getDomain());
527 CPPUNIT_ASSERT_EQUAL(std::string("resource"), testling.getResource());
528 CPPUNIT_ASSERT(!testling.isBare());
529 CPPUNIT_ASSERT(testling.isValid());
530 }
531
532 void testConstructorWithString_DomainInvalidIPv6() {
533 JID testling("foo@[1111::a1111:1111:111!:!!!!]/resource");
534 CPPUNIT_ASSERT(!testling.isValid());
535 }
536
537 void testConstructorWithString_DomainIPv6NoBrackets() {
538 JID testling("foo@fe80::a857:33ff:febd:3580/resource");
539 CPPUNIT_ASSERT(!testling.isValid());
540 }
495}; 541};
496 542
497CPPUNIT_TEST_SUITE_REGISTRATION(JIDTest); 543CPPUNIT_TEST_SUITE_REGISTRATION(JIDTest);