commit 89d049ba7a66e7ebd080ae011a6f886af5b4521c Author: Seán Healy Date: Sat Jan 10 22:22:36 2026 +0000 Initial commit diff --git a/build/build-deb.sh b/build/build-deb.sh new file mode 100755 index 0000000..f5daf62 --- /dev/null +++ b/build/build-deb.sh @@ -0,0 +1,38 @@ +#!/bin/bash +set -e +mkdir -p debian +BUILD_DIR="$(dirname "$0")" +DEBIAN_DIR="$BUILD_DIR/../debian" +DIST_DIR="$BUILD_DIR/../dist" +UNINSTALL="$BUILD_DIR/uninstall.sh" +POST_INSTALL="$BUILD_DIR/post_install.sh" +echo "$(cat "$UNINSTALL")" > "$DEBIAN_DIR/prerm" +echo "#DEBHELPER#" >> "$DEBIAN_DIR/prerm" +echo "$(cat "$POST_INSTALL")" > "$DEBIAN_DIR/postinst" +echo "#DEBHELPER#" >> "$DEBIAN_DIR/postinst" +if [ ! -f "$DEBIAN_DIR/control" ]; then + echo "Error: $DEBIAN_DIR/control not found." + exit 1 +fi +if ! command -v docker >/dev/null 2>&1; then + echo "Error: Docker not found. Please install Docker." + exit 1 +fi +if ! docker info >/dev/null 2>&1; then + echo "Starting Docker daemon..." + if command -v systemctl >/dev/null 2>&1; then + sudo systemctl start docker + elif command -v rc-service >/dev/null 2>&1; then + sudo rc-service docker start + else + echo "Error: Unable to determine init system. Please start Docker manually." + exit 1 + fi + sleep 2 +fi +docker run --rm -v "$(pwd)":/src -v "$DIST_DIR":/dist -w /src debian:latest bash -c " + apt update && apt install -y debhelper devscripts && + dpkg-buildpackage -us -uc && + mv /*.deb /dist/ +" +echo "Package built: $(ls "$DIST_DIR"/sudo-nopasswd_*.deb | head -n 1)" \ No newline at end of file diff --git a/build/build-gentoo.sh b/build/build-gentoo.sh new file mode 100755 index 0000000..280f456 --- /dev/null +++ b/build/build-gentoo.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Script to build and install the sudo-nopasswd package on Gentoo +set -e +# Check if we're in the project directory +if [ ! -f "gentoo/app-admin/sudo-nopasswd/sudo-nopasswd-1.0.ebuild" ]; then + echo "Error: ebuild not found. Run this script from the project root." + exit 1 +fi +# Check for emerge command +if ! command -v emerge >/dev/null 2>&1; then + echo "Error: emerge command not found. Ensure portage is installed." + exit 1 +fi +# Set up local repository +echo "Setting up local repository..." +sudo mkdir -p /etc/portage/repos.conf +sudo tee /etc/portage/repos.conf/local.conf > /dev/null </dev/null 2>&1; then + cp "$SRC/$SERVICE_FILE" "$SYSTEMD_DIR/" +elif command -v rc-update >/dev/null 2>&1; then + cp "$SRC/$INIT_FILE" "$INITD_DIR/" +else + echo "Unsupported init system." +fi +"$(dirname "$0")/post_install.sh" \ No newline at end of file diff --git a/build/post_install.sh b/build/post_install.sh new file mode 100755 index 0000000..2875f7c --- /dev/null +++ b/build/post_install.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -e +[ "$EUID" -eq 0 ] || { echo "Please run as root"; exit 1; } +SHARE_DIR="/usr/share/sudo-nopasswd" +CONSTANTS="sudo_no_passwd_constants.sh" +source "$SHARE_DIR/$CONSTANTS" +[ -f "$ETC_FILE" ] || touch "$ETC_FILE" +if command -v systemctl >/dev/null 2>&1; then + systemctl enable "$SERVICE_FILE" + if [ -d /run/systemd/system ]; then + systemctl daemon-reload + systemctl start "$SERVICE_FILE" + fi +elif command -v rc-update >/dev/null 2>&1; then + chmod +x "$INITD_DIR/$INIT_FILE" + rc-update add "$INIT_FILE" default + rc-service "$INIT_FILE" start +else + echo "Unsupported init system." +fi \ No newline at end of file diff --git a/build/test-deb.sh b/build/test-deb.sh new file mode 100755 index 0000000..0cf4e70 --- /dev/null +++ b/build/test-deb.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e +if ! command -v docker >/dev/null 2>&1; then + echo "Error: Docker not found." + exit 1 +fi +if ! docker info >/dev/null 2>&1; then + echo "Starting Docker..." + if command -v systemctl >/dev/null 2>&1; then + sudo systemctl start docker + elif command -v rc-service >/dev/null 2>&1; then + sudo rc-service docker start + else + echo "Error: Unable to start Docker." + exit 1 + fi + sleep 2 +fi +DEB_FILE=$(ls ./*.deb 2>/dev/null | head -1) +if [ -z "$DEB_FILE" ]; then + echo "Error: No .deb file found in current directory. Run build-deb.sh first." + exit 1 +fi +echo "Found .deb file: $DEB_FILE" +CONTAINER_NAME="test-debian-sudo" +echo "Starting detached Debian container..." +CONTAINER_ID=$(docker run -d --name "$CONTAINER_NAME" debian:latest tail -f /dev/null) +echo "Container started with ID: $CONTAINER_ID" +echo "Copying .deb file into container..." +docker cp "$DEB_FILE" "$CONTAINER_NAME:/root/" +echo "Setup complete." +echo "To enter the container: docker exec -it $CONTAINER_NAME /bin/bash" +echo "To stop the container: docker stop $CONTAINER_NAME && docker rm $CONTAINER_NAME" \ No newline at end of file diff --git a/build/uninstall.sh b/build/uninstall.sh new file mode 100755 index 0000000..f2f1b17 --- /dev/null +++ b/build/uninstall.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e +SHARE_DIR="/usr/share/sudo-nopasswd" +[ -e "$SHARE_DIR" ] || { echo "sudo-nopasswd is not installed."; exit 1; } +source "$SHARE_DIR/sudo_no_passwd_constants.sh" +[ "$EUID" -eq 0 ] || { sudo "$0" "$@"; exit $?; } +if command -v systemctl >/dev/null 2>&1; then + systemctl stop "$SERVICE_FILE" 2>/dev/null || true + systemctl disable "$SERVICE_FILE" 2>/dev/null || true + rm -f "$SYSTEMD_DIR/$SERVICE_FILE" + systemctl daemon-reload +elif command -v rc-update >/dev/null 2>&1; then + rc-service "$INIT_FILE" stop 2>/dev/null || true + rc-update del "$INIT_FILE" 2>/dev/null || true + rm -f "$INITD_DIR/$INIT_FILE" +else + echo "Unsupported init system." +fi +rm -f "$BIN_DIR/$UPDATE_COMMAND" +rm -f "$BIN_DIR/$WATCH_COMMAND" +rm -rf "$SHARE_DIR" +if [ -f "$ETC_FILE" ] && [ ! -s "$ETC_FILE" ]; then + rm -f "$ETC_FILE" +fi +echo "Uninstallation complete." \ No newline at end of file diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..c2e6f25 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,19 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: sudo-nopasswd +Source: + +Files: * +Copyright: 2026 Seán Healy +License: GPL-3+ + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see . diff --git a/debian/install b/debian/install new file mode 100644 index 0000000..7fab5fc --- /dev/null +++ b/debian/install @@ -0,0 +1,5 @@ +src/sudo_no_passwd_constants.sh usr/share/sudo-nopasswd/ +src/update-sudo-nopasswd usr/bin/ +src/watch-sudo-nopasswd usr/bin/ +src/watch-sudo-nopasswd.service lib/systemd/system/ +src/watch-sudo-nopasswd.init etc/init.d/ diff --git a/gentoo/app-admin/sudo-nopasswd/Manifest b/gentoo/app-admin/sudo-nopasswd/Manifest new file mode 100644 index 0000000..8a000b0 --- /dev/null +++ b/gentoo/app-admin/sudo-nopasswd/Manifest @@ -0,0 +1 @@ +EBUILD sudo-nopasswd-1.0.ebuild 789 BLAKE2B 87e99e2b601960139f7e0e3f518c9903218af968b1f94480565bde51506091feba94e89f2aa77f7f7183089b2dc723e3a687506294cbbd5717879e8b82f1371f SHA512 3cbf2bccf1a6eb3c195cbf2412ae7e1e7f8a727a1681a3a405191ac75234ab900ef37f5d8e1066e4514ca54807e2d15e1c08b7792cca69da5b4fafe0c697b662 diff --git a/gentoo/app-admin/sudo-nopasswd/sudo-nopasswd-1.0.ebuild b/gentoo/app-admin/sudo-nopasswd/sudo-nopasswd-1.0.ebuild new file mode 100755 index 0000000..7f5822b --- /dev/null +++ b/gentoo/app-admin/sudo-nopasswd/sudo-nopasswd-1.0.ebuild @@ -0,0 +1,34 @@ +EAPI=8 + +DESCRIPTION="A tool for managing sudo commands without password prompts" +HOMEPAGE="" +SRC_URI="" + +LICENSE="GPL-3" +SLOT="0" +KEYWORDS="~amd64 ~x86" + +RDEPEND="app-admin/sudo + sys-process/inotify-tools" +DEPEND="${RDEPEND}" + +src_install() { + dobin src/update-sudo-nopasswd + dobin src/watch-sudo-nopasswd + + insinto /usr/share/sudo-nopasswd + doins src/sudo_no_passwd_constants.sh + newinitd "${FILESDIR}"/watch-sudo-nopasswd.init watch-sudo-nopasswd + systemd_dounit src/watch-sudo-nopasswd.service +} + +pkg_postinst() { + if [ ! -f "${ROOT}/etc/sudo-nopasswd" ]; then + touch "${ROOT}/etc/sudo-nopasswd" + elog "Created empty ${ROOT}/etc/sudo-nopasswd" + fi + + elog "To enable the service:" + elog " systemctl enable watch-sudo-nopasswd (systemd)" + elog " rc-update add watch-sudo-nopasswd default (OpenRC)" +} diff --git a/gentoo/metadata/layout.conf b/gentoo/metadata/layout.conf new file mode 100644 index 0000000..fded726 --- /dev/null +++ b/gentoo/metadata/layout.conf @@ -0,0 +1 @@ +masters = gentoo \ No newline at end of file diff --git a/src/sudo-nopasswd.init b/src/sudo-nopasswd.init new file mode 100644 index 0000000..7ce3e74 --- /dev/null +++ b/src/sudo-nopasswd.init @@ -0,0 +1,11 @@ +#!/sbin/openrc-run +description="Watch for changes to sudo-nopasswd and update sudoers" +command="/usr/bin/watch-sudo-nopasswd" +command_background=yes +pidfile="/run/watch-sudo-nopasswd.pid" +start_stop_daemon_args="--quiet" +stop() { + ebegin "Stopping watch-sudo-nopasswd" + start-stop-daemon --stop --pidfile /run/watch-sudo-nopasswd.pid + eend $? +} \ No newline at end of file diff --git a/src/sudo-nopasswd.service b/src/sudo-nopasswd.service new file mode 100644 index 0000000..ab038f5 --- /dev/null +++ b/src/sudo-nopasswd.service @@ -0,0 +1,12 @@ +[Unit] +Description=Watch for changes to /etc/sudo-nopasswd and update sudoers NOPASSWD +After=network.target + +[Service] +ExecStart=/usr/bin/watch-sudo-nopasswd +Restart=always +User=root +Type=simple + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/src/sudo_no_passwd_constants.sh b/src/sudo_no_passwd_constants.sh new file mode 100644 index 0000000..95a095a --- /dev/null +++ b/src/sudo_no_passwd_constants.sh @@ -0,0 +1,19 @@ +#!/bin/bash +ETC_FILE="/etc/sudo-nopasswd" +SUDOERS_FILE="/etc/sudoers" +SUDOERS_BAK="/etc/sudoers.bak" +BEFORE_COMMANDS="/tmp/sudo-nopasswd-before" +AFTER_COMMANDS="/tmp/sudo-nopasswd-after" +SCRIPT_NAME="update-sudo-nopasswd" + +# Installation paths +BIN_DIR="/usr/bin" +SERVICE_FILE="sudo-nopasswd.service" +INIT_FILE="sudo-nopasswd.init" +SYSTEMD_DIR="/etc/systemd/system" +INITD_DIR="/etc/init.d" + +UPDATE_COMMAND="update-sudo-nopasswd" +WATCH_COMMAND="watch-sudo-nopasswd" + +SHARE_DIR="/usr/share/sudo-nopasswd" \ No newline at end of file diff --git a/src/update-sudo-nopasswd b/src/update-sudo-nopasswd new file mode 100755 index 0000000..6014c02 --- /dev/null +++ b/src/update-sudo-nopasswd @@ -0,0 +1,44 @@ +#!/bin/bash +set -e +SHARE_DIR="/usr/share/sudo-nopasswd" +CONSTANTS="sudo_no_passwd_constants.sh" +source "$SHARE_DIR/$CONSTANTS" +[ "$EUID" -eq 0 ] || { sudo "$0" "$@"; exit $?; } +cp "$SUDOERS_FILE" "$SUDOERS_BAK" + +if grep -q "^%sudo.*NOPASSWD" "$SUDOERS_FILE"; then + grep "%sudo.*NOPASSWD" "$SUDOERS_FILE" | + sed -E 's/.*NOPASSWD: //;s/([^\\]),/\1\n/g;s/\\\\//g' > "$BEFORE_COMMANDS" +else + touch "$BEFORE_COMMANDS" +fi +output="$( + cat "$ETC_FILE" | + awk -F' ' '{"command -v "$1 | getline program; $1=program; print}' | + sed -E 's/([:,#])/\\\\\1/g' | + paste -sd, +)" +sep=$(printf '\001') +if [ "$output" ]; then + if grep -q "^%sudo.*NOPASSWD" "$SUDOERS_FILE"; then + sed -i "s${sep}^%sudo.*NOPASSWD: .*${sep}%sudo ALL=(ALL:ALL) NOPASSWD: $output${sep}" "$SUDOERS_FILE" + else + sed -i "/^%sudo/a %sudo ALL=(ALL:ALL) NOPASSWD: $output" "$SUDOERS_FILE" + fi +else + sed -i "/^%sudo.*NOPASSWD/d" "$SUDOERS_FILE" +fi +if ! visudo -c "$SUDOERS_FILE" >/dev/null 2>&1; then + cat "$SUDOERS_BAK" | grep "%sudo.*NOPASSWD" + cp "$SUDOERS_BAK" "$SUDOERS_FILE" + echo "Syntax error detected in $SUDOERS_FILE. Reverted to backup." + exit 1 +else + rm "$SUDOERS_BAK" +fi +cat "$ETC_FILE" | + awk -F' ' '{"command -v "$1 | getline program; $1=program; print}' > "$AFTER_COMMANDS" +diff -u "$BEFORE_COMMANDS" "$AFTER_COMMANDS" --color=always | + grep $'^\x1b\\[[0-9;]*m[+-]' | + grep -Ev $'^\x1b\\[[0-9;]*m([+][+][+]|[-][-][-])' +rm "$BEFORE_COMMANDS" "$AFTER_COMMANDS" \ No newline at end of file diff --git a/src/watch-sudo-nopasswd b/src/watch-sudo-nopasswd new file mode 100755 index 0000000..1d4201a --- /dev/null +++ b/src/watch-sudo-nopasswd @@ -0,0 +1,11 @@ +#!/bin/bash +set -e +[ "$EUID" -eq 0 ] || { sudo "$0" "$@"; exit $?; } +SHARE_DIR="/usr/share/sudo-nopasswd" +CONSTANTS="sudo_no_passwd_constants.sh" +source "$SHARE_DIR/$CONSTANTS" +while [ 1 ]; do + while ! inotifywait -e close_write "$ETC_FILE"; do + "$UPDATE_COMMAND" + done +done