mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-13 01:36:15 +02:00
isAllowedURI: Extract function and test
This commit is contained in:
parent
5c917c3204
commit
91ba7b2307
3 changed files with 124 additions and 5 deletions
|
@ -599,21 +599,29 @@ void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value &
|
||||||
mkStorePathString(storePath, v);
|
mkStorePathString(storePath, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalState::checkURI(const std::string & uri)
|
bool isAllowedURI(std::string_view uri, const Strings & allowedUris)
|
||||||
{
|
{
|
||||||
if (!evalSettings.restrictEval) return;
|
|
||||||
|
|
||||||
/* 'uri' should be equal to a prefix, or in a subdirectory of a
|
/* 'uri' should be equal to a prefix, or in a subdirectory of a
|
||||||
prefix. Thus, the prefix https://github.co does not permit
|
prefix. Thus, the prefix https://github.co does not permit
|
||||||
access to https://github.com. Note: this allows 'http://' and
|
access to https://github.com. Note: this allows 'http://' and
|
||||||
'https://' as prefixes for any http/https URI. */
|
'https://' as prefixes for any http/https URI. */
|
||||||
for (auto & prefix : evalSettings.allowedUris.get())
|
for (auto & prefix : allowedUris) {
|
||||||
if (uri == prefix ||
|
if (uri == prefix ||
|
||||||
(uri.size() > prefix.size()
|
(uri.size() > prefix.size()
|
||||||
&& prefix.size() > 0
|
&& prefix.size() > 0
|
||||||
&& hasPrefix(uri, prefix)
|
&& hasPrefix(uri, prefix)
|
||||||
&& (prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/')))
|
&& (prefix[prefix.size() - 1] == '/' || uri[prefix.size()] == '/')))
|
||||||
return;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvalState::checkURI(const std::string & uri)
|
||||||
|
{
|
||||||
|
if (!evalSettings.restrictEval) return;
|
||||||
|
|
||||||
|
if (isAllowedURI(uri, evalSettings.allowedUris.get())) return;
|
||||||
|
|
||||||
/* If the URI is a path, then check it against allowedPaths as
|
/* If the URI is a path, then check it against allowedPaths as
|
||||||
well. */
|
well. */
|
||||||
|
|
|
@ -837,6 +837,11 @@ std::string showType(const Value & v);
|
||||||
*/
|
*/
|
||||||
SourcePath resolveExprPath(SourcePath path);
|
SourcePath resolveExprPath(SourcePath path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a URI is allowed, assuming restrictEval is enabled
|
||||||
|
*/
|
||||||
|
bool isAllowedURI(std::string_view uri, const Strings & allowedPaths);
|
||||||
|
|
||||||
struct InvalidPathError : EvalError
|
struct InvalidPathError : EvalError
|
||||||
{
|
{
|
||||||
Path path;
|
Path path;
|
||||||
|
|
106
tests/unit/libexpr/eval.cc
Normal file
106
tests/unit/libexpr/eval.cc
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "eval.hh"
|
||||||
|
#include "tests/libexpr.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
TEST(nix_isAllowedURI, http_example_com) {
|
||||||
|
Strings allowed;
|
||||||
|
allowed.push_back("http://example.com");
|
||||||
|
|
||||||
|
ASSERT_TRUE(isAllowedURI("http://example.com", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("http://example.com/foo", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("http://example.com/foo/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.co", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.como", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.org", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.org/foo", allowed));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(nix_isAllowedURI, http_example_com_foo) {
|
||||||
|
Strings allowed;
|
||||||
|
allowed.push_back("http://example.com/foo");
|
||||||
|
|
||||||
|
ASSERT_TRUE(isAllowedURI("http://example.com/foo", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("http://example.com/foo/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/foo", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.com", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.como", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.org/foo", allowed));
|
||||||
|
// Broken?
|
||||||
|
// ASSERT_TRUE(isAllowedURI("http://example.com/foo?ok=1", allowed));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(nix_isAllowedURI, http) {
|
||||||
|
Strings allowed;
|
||||||
|
allowed.push_back("http://");
|
||||||
|
|
||||||
|
ASSERT_TRUE(isAllowedURI("http://", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("http://example.com", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("http://example.com/foo", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("http://example.com/foo/", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("http://example.com", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("https://", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http:foo", allowed));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(nix_isAllowedURI, https) {
|
||||||
|
Strings allowed;
|
||||||
|
allowed.push_back("https://");
|
||||||
|
|
||||||
|
ASSERT_TRUE(isAllowedURI("https://example.com", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("https://example.com/foo", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.com", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.com/https:", allowed));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(nix_isAllowedURI, absolute_path) {
|
||||||
|
Strings allowed;
|
||||||
|
allowed.push_back("/var/evil"); // bad idea
|
||||||
|
|
||||||
|
ASSERT_TRUE(isAllowedURI("/var/evil", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("/var/evil/", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("/var/evil/foo", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("/var/evil/foo/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/var/evi", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/var/evilo", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/var/evilo/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/var/evilo/foo", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.com/var/evil", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.com//var/evil", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.com//var/evil/foo", allowed));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(nix_isAllowedURI, file_url) {
|
||||||
|
Strings allowed;
|
||||||
|
allowed.push_back("file:///var/evil"); // bad idea
|
||||||
|
|
||||||
|
ASSERT_TRUE(isAllowedURI("file:///var/evil", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("file:///var/evil/", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("file:///var/evil/foo", allowed));
|
||||||
|
ASSERT_TRUE(isAllowedURI("file:///var/evil/foo/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/var/evi", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/var/evilo", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/var/evilo/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("/var/evilo/foo", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.com/var/evil", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.com//var/evil", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://example.com//var/evil/foo", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://var/evil", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http:///var/evil", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("http://var/evil/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("file:///var/evi", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("file:///var/evilo", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("file:///var/evilo/", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("file:///var/evilo/foo", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("file:///", allowed));
|
||||||
|
ASSERT_FALSE(isAllowedURI("file://", allowed));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nix
|
Loading…
Reference in a new issue