mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
libstore: Reallow unbracketed IPv6 addresses in store references
This implements a special back-compat shim to specifically allow unbracketed IPv6 addresses in store references. This is something that is relied upon in the wild and the old parsing logic accepted both ways (brackets were optional). This patch restores this behavior. As always, we didn't have any tests for this. Addresses #13937.
This commit is contained in:
parent
12db0726e9
commit
7cc654afa9
6 changed files with 91 additions and 2 deletions
|
|
@ -0,0 +1 @@
|
|||
ssh://::1
|
||||
|
|
@ -0,0 +1 @@
|
|||
ssh://userinfo@fea5:23e1:3916:fc24:cb52:2837:2ecb:ea8e
|
||||
|
|
@ -0,0 +1 @@
|
|||
ssh://userinfo@fea5:23e1:3916:fc24:cb52:2837:2ecb:ea8e?a=b&c=d
|
||||
|
|
@ -148,4 +148,39 @@ URI_TEST(
|
|||
.params = {},
|
||||
}))
|
||||
|
||||
static StoreReference sshLoopbackIPv6{
|
||||
.variant =
|
||||
StoreReference::Specified{
|
||||
.scheme = "ssh",
|
||||
.authority = "[::1]",
|
||||
},
|
||||
};
|
||||
|
||||
URI_TEST_READ(ssh_unbracketed_ipv6_1, sshLoopbackIPv6)
|
||||
|
||||
static StoreReference sshIPv6AuthorityWithUserinfo{
|
||||
.variant =
|
||||
StoreReference::Specified{
|
||||
.scheme = "ssh",
|
||||
.authority = "userinfo@[fea5:23e1:3916:fc24:cb52:2837:2ecb:ea8e]",
|
||||
},
|
||||
};
|
||||
|
||||
URI_TEST_READ(ssh_unbracketed_ipv6_2, sshIPv6AuthorityWithUserinfo)
|
||||
|
||||
static StoreReference sshIPv6AuthorityWithUserinfoAndParams{
|
||||
.variant =
|
||||
StoreReference::Specified{
|
||||
.scheme = "ssh",
|
||||
.authority = "userinfo@[fea5:23e1:3916:fc24:cb52:2837:2ecb:ea8e]",
|
||||
},
|
||||
.params =
|
||||
{
|
||||
{"a", "b"},
|
||||
{"c", "d"},
|
||||
},
|
||||
};
|
||||
|
||||
URI_TEST_READ(ssh_unbracketed_ipv6_3, sshIPv6AuthorityWithUserinfoAndParams)
|
||||
|
||||
} // namespace nix
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ boost = dependency(
|
|||
'container',
|
||||
# Shouldn't list, because can header-only, and Meson currently looks for libs
|
||||
#'regex',
|
||||
'url',
|
||||
],
|
||||
include_type : 'system',
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
#include <regex>
|
||||
|
||||
#include "nix/util/error.hh"
|
||||
#include "nix/util/split.hh"
|
||||
#include "nix/util/url.hh"
|
||||
#include "nix/store/store-reference.hh"
|
||||
#include "nix/util/file-system.hh"
|
||||
#include "nix/util/util.hh"
|
||||
|
||||
#include <boost/url/ipv6_address.hpp>
|
||||
|
||||
namespace nix {
|
||||
|
||||
static bool isNonUriPath(const std::string & spec)
|
||||
|
|
@ -43,6 +44,29 @@ std::string StoreReference::render(bool withParams) const
|
|||
return res;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct SchemeAndAuthorityWithPath
|
||||
{
|
||||
std::string_view scheme;
|
||||
std::string_view authority;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* Return the 'scheme' and remove the '://' or ':' separator.
|
||||
*/
|
||||
static std::optional<SchemeAndAuthorityWithPath> splitSchemePrefixTo(std::string_view string)
|
||||
{
|
||||
auto scheme = splitPrefixTo(string, ':');
|
||||
if (!scheme)
|
||||
return std::nullopt;
|
||||
|
||||
splitPrefix(string, "//");
|
||||
return SchemeAndAuthorityWithPath{.scheme = *scheme, .authority = string};
|
||||
}
|
||||
|
||||
StoreReference StoreReference::parse(const std::string & uri, const StoreReference::Params & extraParams)
|
||||
{
|
||||
auto params = extraParams;
|
||||
|
|
@ -90,6 +114,32 @@ StoreReference StoreReference::parse(const std::string & uri, const StoreReferen
|
|||
},
|
||||
.params = std::move(params),
|
||||
};
|
||||
} else if (auto schemeAndAuthority = splitSchemePrefixTo(baseURI)) {
|
||||
/* Back-compatibility shim to accept unbracketed IPv6 addresses after the scheme.
|
||||
* Old versions of nix allowed that. Note that this is ambiguous and does not allow
|
||||
* specifying the port number. For that the address must be bracketed, otherwise it's
|
||||
* greedily assumed to be the part of the host address. */
|
||||
auto authorityString = schemeAndAuthority->authority;
|
||||
auto userinfo = splitPrefixTo(authorityString, '@');
|
||||
auto maybeIpv6 = boost::urls::parse_ipv6_address(authorityString);
|
||||
if (maybeIpv6) {
|
||||
std::string fixedAuthority;
|
||||
if (userinfo) {
|
||||
fixedAuthority += *userinfo;
|
||||
fixedAuthority += '@';
|
||||
}
|
||||
fixedAuthority += '[';
|
||||
fixedAuthority += authorityString;
|
||||
fixedAuthority += ']';
|
||||
return {
|
||||
.variant =
|
||||
Specified{
|
||||
.scheme = std::string(schemeAndAuthority->scheme),
|
||||
.authority = fixedAuthority,
|
||||
},
|
||||
.params = std::move(params),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue