--- /dev/null
+[sec]* fdupont
+ Change the umask to no group write and no other access
+ at the entry of Kea server/agent binaries.
+ CVE:2025-32803
+ (Gitlab #3832)
+
+
+
#include <config.h>
#include <agent/ca_controller.h>
#include <exceptions/exceptions.h>
+#include <util/filesystem.h>
#include <cstdlib>
#include <iostream>
using namespace isc::process;
int main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ret = EXIT_SUCCESS;
// Launch the controller passing in command line arguments.
#include <exceptions/exceptions.h>
#include <log/logger_manager.h>
#include <log/logger_support.h>
+#include <util/filesystem.h>
#include <iostream>
/// The exit value of the program will be EXIT_SUCCESS if there were no
/// errors, EXIT_FAILURE otherwise.
int main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ret = EXIT_SUCCESS;
// Launch the controller passing in command line arguments.
#include <log/output_option.h>
#include <process/cfgrpt/config_report.h>
#include <process/daemon.h>
+#include <util/filesystem.h>
#include <boost/lexical_cast.hpp>
int
main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ch;
// The default. Any other values are useful for testing only.
int server_port_number = DHCP4_SERVER_PORT;
#include <log/output_option.h>
#include <process/cfgrpt/config_report.h>
#include <process/daemon.h>
+#include <util/filesystem.h>
#include <boost/lexical_cast.hpp>
int
main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ch;
// The default. Any other values are useful for testing only.
int server_port_number = DHCP6_SERVER_PORT;
#include <exceptions/exceptions.h>
#include <log/logger_support.h>
#include <log/logger_manager.h>
+#include <util/filesystem.h>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception_ptr.hpp>
#include <iostream>
/// The exit value of the program will be EXIT_SUCCESS if there were no
/// errors, EXIT_FAILURE otherwise.
int main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ret = EXIT_SUCCESS;
try {
// Ask scheduling to not give too much resources to LFC.
#include <config.h>
#include <exceptions/exceptions.h>
+#include <util/filesystem.h>
#include <netconf/netconf_controller.h>
#include <cstdlib>
using namespace std;
int main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ret = EXIT_SUCCESS;
// Launch the controller passing in command line arguments.
#include <config.h>
+#include <util/filesystem.h>
#include <perfdhcp/avalanche_scen.h>
#include <perfdhcp/basic_scen.h>
#include <perfdhcp/command_options.h>
int
main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ret_code = 0;
std::string diags;
bool parser_error = true;
return ((statbuf.st_mode & S_IFMT) == S_IFSOCK);
}
+void
+setUmask() {
+ // No group write and no other access.
+ mode_t mask(S_IWGRP | S_IRWXO);
+ mode_t orig = umask(mask);
+ // Handle the case where the original umask was already more restrictive.
+ if ((orig | mask) != mask) {
+ static_cast<void>(umask(orig | mask));
+ }
+}
+
Path::Path(string const& full_name) {
if (!full_name.empty()) {
bool dir_present = false;
if (filename.empty()) {
isc_throw(BadValue, "path: '" << input_path.str() << "' has no filename");
}
-
+
auto parent_path = input_path.parentPath();
if (!parent_path.empty()) {
if (!enforce_path) {
// Security set to lax, let it fly.
return (input_path_str);
}
-
+
+
// We only allow absolute path equal to default. Catch an invalid path.
if (parent_path != supported_path_copy) {
isc_throw(BadValue, "invalid path specified: '"
<< supported_path_copy << "'");
}
}
-
+
std::string valid_path(supported_path_copy + "/" + filename);
return (valid_path);
}
bool
isFile(const std::string& path);
+/// @brief Check if there is a socket at the given path.
+///
+/// @param path The path being checked.
+///
+/// @return True if the path points to a socket, false otherwise including
+/// if the pointed location does not exist.
bool
isSocket(const std::string& path);
+/// @brief Set umask (at least 0027 i.e. no group write and no other access).
+void
+setUmask();
+
/// @brief Paths on a filesystem
struct Path {
/// @brief Constructor
EXPECT_FALSE(isFile(TEST_DATA_BUILDDIR));
}
+/// @brief Test fixture class for testing operations on umask.
+struct UMaskUtilTest : ::testing::Test {
+ /// @brief Constructor.
+ ///
+ /// Cache the original umask value.
+ UMaskUtilTest() : orig_umask_(umask(S_IWGRP | S_IWOTH)) { }
+
+ /// @brief Destructor.
+ ///
+ /// Restore the original umask value.
+ virtual ~UMaskUtilTest() {
+ static_cast<void>(umask(orig_umask_));
+ }
+
+private:
+ /// @brief Original umask.
+ mode_t orig_umask_;
+};
+
+/// @brief Check setUmask from 0000.
+TEST_F(UMaskUtilTest, umask0) {
+ static_cast<void>(umask(0));
+ ASSERT_NO_THROW(setUmask());
+ EXPECT_EQ(S_IWGRP | S_IRWXO, umask(0));
+}
+
+/// @brief Check setUmask from no group access.
+TEST_F(UMaskUtilTest, umask077) {
+ static_cast<void>(umask(S_IRWXG | S_IRWXO));
+ ASSERT_NO_THROW(setUmask());
+ EXPECT_EQ(S_IRWXG | S_IRWXO, umask(0));
+}
+
/// @brief Check that the components are split correctly.
TEST(PathTest, components) {
// Complete name
EXPECT_EQ("/just/some/dir/a.b", fname.str());
}
-
-
// Verifies FileManager::validatePath() when enforce_path is true.
TEST(FileManager, validatePathEnforcePath) {
std::string def_path = std::string(TEST_DATA_BUILDDIR) + "/";
""
},
{
- // White space for file name.
+ // White space for file name.
__LINE__,
" ",
"",
""
},
{
- // White space for file name.
+ // White space for file name.
__LINE__,
" ",
"",