From b565d7d9c47ca1ec5af0effd828431ee96027d60 Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Mon, 27 May 2024 22:00:00 +0200 Subject: Rename project from wireframe to packeteer Decided on the name after weighing alternatives in NAMES.md: packeteer (packet + -eer, "one who wields packets") fit the project's actual scope better than the wire/frame pun once it had grown into full L2-L7 dissection, reassembly, checksums, privilege dropping, and dual TUI/GUI frontends. No existing packet-capture project uses the name; the one real-world collision (Packeteer, Inc., a networking company acquired and folded into Blue Coat/Symantec by 2008) is long defunct. Mechanical rename throughout: CMake project/target names, the wireframe:: namespace and include/wireframe/ directory (git mv, history preserved), every #include path, CLI/GUI help text, and the project's own working directory. NAMES.md rewritten to record the decision instead of leaving stale self-referential etymology behind from the blind rename pass. Verified after every step: full rebuild (all four targets, no warnings) and the full test suite (128/128 cases, 366/366 assertions) both from a fresh reconfigure and again after the directory move. --- include/wireframe/privileges.hpp | 87 ---------------------------------------- 1 file changed, 87 deletions(-) delete mode 100644 include/wireframe/privileges.hpp (limited to 'include/wireframe/privileges.hpp') diff --git a/include/wireframe/privileges.hpp b/include/wireframe/privileges.hpp deleted file mode 100644 index 69df725..0000000 --- a/include/wireframe/privileges.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#ifndef _WIN32 -#include -#include -#endif - -#include -#include -#include -#include -#include - -// After pcap_open_live() succeeds, the process has gotten everything -// CAP_NET_RAW exists for - running the rest of the program (decoding -// untrusted packet bytes, an interactive TUI/GUI event loop) as root -// from that point on is unnecessary exposure, and PLAN.md says as much -// directly: "Drop privileges immediately after opening the capture -// handle; use CAP_NET_RAW via file capabilities instead of running as -// root." -// -// The recommended path doesn't need this file at all: run -// `sudo setcap cap_net_raw+ep ` once, then invoke the binary -// directly, unprivileged, forever after - CAP_NET_RAW alone is enough -// for pcap_open_live(), no root required at any point. This exists for -// the case someone still runs the binary via sudo (out of habit, or -// because setcap isn't available/permitted in some environments): drop -// straight back to the invoking user immediately, so the rest of the -// process's lifetime - including any -w output file, which then ends -// up owned by that user instead of root - runs unprivileged either way. -namespace wireframe { - -// Drops from root to the user who actually invoked the program, via -// sudo's SUDO_UID/SUDO_GID (which sudo always sets). A no-op if not -// currently root, or if SUDO_UID isn't set (e.g. a genuine root login, -// not sudo - there's no "real" user to drop to in that case). -// -// setuid() to a nonzero UID also clears the process's Linux capability -// sets as a kernel-level side effect, so this covers both "running as -// root via sudo" and "root's own CAP_NET_RAW" the same way, without a -// separate libcap dependency. -// -// Returns an error message on failure. The drop is safety-critical: a -// failure here should be treated as fatal by the caller, not silently -// ignored while the process keeps running as root. -inline std::optional drop_privileges_if_root() { -#ifdef _WIN32 - return std::nullopt; // no POSIX privilege model to drop from -#else - if (geteuid() != 0) return std::nullopt; // already unprivileged - - const char* sudo_uid = std::getenv("SUDO_UID"); - const char* sudo_gid = std::getenv("SUDO_GID"); - if (sudo_uid == nullptr || sudo_gid == nullptr) { - return std::nullopt; // no safe target to drop to - } - - uid_t target_uid = static_cast(std::strtoul(sudo_uid, nullptr, 10)); - gid_t target_gid = static_cast(std::strtoul(sudo_gid, nullptr, 10)); - - // Order matters: groups and GID need root to change, so they must - // be dropped before UID - once UID is gone, so is the privilege - // to change the others. - if (setgroups(1, &target_gid) == -1) { - return "setgroups failed: " + std::string(std::strerror(errno)); - } - if (setgid(target_gid) == -1) { - return "setgid failed: " + std::string(std::strerror(errno)); - } - if (setuid(target_uid) == -1) { - return "setuid failed: " + std::string(std::strerror(errno)); - } - - // Defense in depth (standard advice from setuid-privilege-drop - // write-ups): confirm root can't be reclaimed. If the saved-UID - // was somehow left at 0, this would succeed and silently undo the - // drop - so a *successful* setuid(0) here means something is - // wrong, and is treated as the failure case. - if (setuid(0) != -1) { - return "failed to permanently drop root (setuid(0) unexpectedly succeeded)"; - } - - return std::nullopt; -#endif -} - -} // namespace wireframe -- cgit v1.2.3