2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-31 05:55:28 +00:00

[#1680] added check for execurtable permissions

This commit is contained in:
Razvan Becheriu
2021-04-28 20:36:41 +03:00
parent ad206e2f00
commit 8f6d994d8d
6 changed files with 64 additions and 3 deletions

View File

@@ -4,6 +4,7 @@ AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
AM_CPPFLAGS += -I$(top_builddir)/src/hooks/dhcp/run_script -I$(top_srcdir)/src/hooks/dhcp/run_script
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CPPFLAGS += -DLIBRUN_SCRIPT_SO=\"$(abs_top_builddir)/src/hooks/dhcp/run_script/.libs/libdhcp_run_script.so\"
AM_CPPFLAGS += -DRUN_SCRIPT_TEST_SH=\"$(abs_top_builddir)/src/hooks/dhcp/run_script/tests/run_script_test.sh\"
AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
AM_CXXFLAGS = $(KEA_CXXFLAGS)

View File

@@ -75,7 +75,7 @@ public:
TEST_F(LibLoadTest, validLoad) {
// Prepare parameters for the callout parameters library.
ElementPtr params = Element::createMap();
ElementPtr name = Element::create("test_script.sh");
ElementPtr name = Element::create(RUN_SCRIPT_TEST_SH);
params->set("name", name);
ElementPtr sync = Element::create(false);
params->set("sync", sync);
@@ -104,12 +104,16 @@ TEST_F(LibLoadTest, invalidLoad) {
params->set("name", name);
EXPECT_FALSE(loadLibs());
// Use valid name parameter type but use invalid sync parameter type.
// Use invalid name parameter.
name = Element::create("script_name.sh");
params->set("name", name);
EXPECT_FALSE(loadLibs());
// Use valid name parameter type but use invalid sync parameter type.
name = Element::create(RUN_SCRIPT_TEST_SH);
params->set("name", name);
ElementPtr sync = Element::create("data");
params->set("sync", sync);
EXPECT_FALSE(loadLibs());
}

View File

@@ -32,6 +32,15 @@ RunScriptImpl::configure(LibraryHandle& handle) {
if (name->getType() != Element::string) {
isc_throw(InvalidParameter, "The 'name' parameter must be a string");
}
IOServicePtr io_service(new asiolink::IOService());
try {
ProcessSpawn process(io_service, name->stringValue());
if (!process.checkPermissions()) {
isc_throw(InvalidParameter, "The 'name' parameter must point to an executable");
}
} catch (const isc::Exception& ex) {
isc_throw(InvalidParameter, "Invalid 'name' parameter: " << ex.what());
}
setName(name->stringValue());
ConstElementPtr sync = handle.getParameter("sync");
if (sync) {

View File

@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
using namespace std;
@@ -131,6 +132,12 @@ public:
/// @param pid A process pid.
void clearState(const pid_t pid);
/// @brief Check executable permissions.
///
/// @return true if file has executable permissions, false otherwise.
/// @throw ProcessSpawnError if file does not exist.
bool checkPermissions() const;
private:
/// @brief Copies the argument specified as a C++ string to the new
@@ -357,6 +364,18 @@ ProcessSpawn::ProcessSpawn(IOServicePtr io_service,
: impl_(new ProcessSpawnImpl(io_service, executable, args, vars)) {
}
bool
ProcessSpawnImpl::checkPermissions() const {
struct stat st;
if (stat(executable_.c_str(), &st)) {
isc_throw(ProcessSpawnError, "File not found: " << executable_);
}
if (st.st_mode & S_IEXEC) {
return (true);
}
return (false);
}
std::string
ProcessSpawn::getCommandLine() const {
return (impl_->getCommandLine());
@@ -387,5 +406,10 @@ ProcessSpawn::clearState(const pid_t pid) {
return (impl_->clearState(pid));
}
bool
ProcessSpawn::checkPermissions() const {
return (impl_->checkPermissions());
}
} // namespace asiolink
} // namespace isc

View File

@@ -137,6 +137,12 @@ public:
/// @param pid A process pid.
void clearState(const pid_t pid);
/// @brief Check executable permissions.
///
/// @return true if file has executable permissions, false otherwise.
/// @throw ProcessSpawnError if file does not exist.
bool checkPermissions() const;
private:
/// @brief A smart pointer to the implementation of this class.

View File

@@ -16,6 +16,8 @@
#include <sys/types.h>
#include <unistd.h>
#include <testutils/gtest_utils.h>
namespace {
using namespace isc;
@@ -343,4 +345,19 @@ TEST_F(ProcessSpawnTest, isRunning) {
ASSERT_EQ(SIGCHLD, processed_signals_[0]);
}
// This test verifies that the checkPermissions function throws if the file does
// not exist and returns true or false if the file is or it is not executable.
TEST_F(ProcessSpawnTest, checkPermissions) {
ProcessSpawn no_process(io_service_, "no-file");
EXPECT_THROW_MSG(no_process.checkPermissions(), ProcessSpawnError,
"File not found: no-file");
std::string name = TEST_SCRIPT_SH;
name += ".in";
ProcessSpawn invalid_process(io_service_, name);
ASSERT_FALSE(invalid_process.checkPermissions());
ProcessSpawn process(io_service_, TEST_SCRIPT_SH);
ASSERT_TRUE(process.checkPermissions());
}
} // end of anonymous namespace