Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ipv6 host validation support #3250

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 61 additions & 2 deletions src/aws-cpp-sdk-core/source/utils/DNS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#include <aws/core/utils/DNS.h>
#include <aws/core/utils/StringUtils.h>

#include <cctype>
namespace Aws
{
namespace Utils
Expand Down Expand Up @@ -40,6 +40,65 @@ namespace Aws
return true;
}

bool isValidIPv6Segment(const std::string& segment) {
if (segment.empty() || segment.length() > 4){
return false;
}
return std::all_of(segment.begin(), segment.end(), isxdigit);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like all other functions from , the behavior of std::isxdigit is undefined if the argument's value is neither representable as unsigned char nor equal to EOF. To use these functions safely with plain chars (or signed chars), the argument should first be converted to unsigned char...

https://en.cppreference.com/w/cpp/string/byte/isxdigit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comment. I have raised a change to address the corner case.

}

//The assumption is this is only called with the domain part of uri
bool isValidIpv6Host(const Aws::String& host)
{
if(host.empty())
{
return false;
}
size_t segmentCount = 1;
bool doubleColonFound = false;
size_t labelStart = 0;

for(size_t i = 0; i < host.length(); ++i)
{
if(host[i] == ':')
{
// double colon check
if(i + 1 < host.length() && host[i+1] == ':')
{
if(doubleColonFound) {
return false;
}
doubleColonFound = true;
++i;
}
// single colon segment
else
{
if(!isValidIPv6Segment(host.substr(labelStart, i - labelStart))) {
return false;
}
++segmentCount;
}
labelStart = i + 1;
}
// no dots in ipv6
else if(host[i] == '.')
{
return false;
}
}

// Handle last segment
if(labelStart < host.length())
{
if(!isValidIPv6Segment(host.substr(labelStart))){
return false;
}
}
// Check if we have 8 segments or less with one double colon
return (doubleColonFound && segmentCount < 8) || (!doubleColonFound && segmentCount == 8);
}

bool IsValidHost(const Aws::String& host)
{
// Valid DNS hostnames are composed of valid DNS labels separated by a period.
Expand All @@ -49,7 +108,7 @@ namespace Aws
return false;
}

return !std::any_of(labels.begin(), labels.end(), [](const Aws::String& label){ return !IsValidDnsLabel(label); });
return !std::any_of(labels.begin(), labels.end(), [](const Aws::String& label){ return !IsValidDnsLabel(label); }) || isValidIpv6Host(host);
}
}
}
26 changes: 26 additions & 0 deletions tests/aws-cpp-sdk-core-tests/utils/DNSTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,29 @@ TEST_F(DnsTest, TestHost)
ASSERT_FALSE(IsValidHost("0123456789012345678901234567890123456789012345678901234567890123.com")); // 64 characters

}

TEST_F(DnsTest, TestIPV6)
{
Aws::Vector< std::pair<Aws::String, bool> > inputs = {
{"2001:0db8:85a3:0000:0000:8a2e:0370:7334", true},
{"2001:DB8:85A3::8A2E:370:7334", true},
{"::ffff", true},
{"::", true},
{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",true},
{"2001:db8:85a3:0:0:8a2e:370:7334",true},
{"2001:db8:85a3:0000:0000:8a2e:0370:7334:1", false},
{"2001:db8:85a3:0000", false},
{"2001:0db8:85a3:0000:0000:8a2e:0370:7334:", false},
{"g001:0db8:85a3:0000:0000:8a2e:0370:7334", false},
{"2001:db8::85a3::1", false},
{":2001:db8:85a3:0000:0000:8a2e:0370:7334", false},
{"0:0:0:0:0:0:0:0", true},
{"2001:db8::", true}
};

for(auto t : inputs)
{
ASSERT_EQ(IsValidHost(t.first), t.second);
}

}
Loading