Simplify SSH access via dedicated cli user
This commit is contained in:
parent
a87f0a9651
commit
460d625f60
|
|
@ -1,87 +0,0 @@
|
||||||
/*
|
|
||||||
* libnss_toes - NSS module that resolves unknown usernames to a shared account.
|
|
||||||
*
|
|
||||||
* Any username not found in /etc/passwd gets mapped to a toes-cli entry
|
|
||||||
* with home=/home/toes-cli and shell=/usr/local/bin/toes.
|
|
||||||
*
|
|
||||||
* Build:
|
|
||||||
* gcc -shared -o libnss_toes.so.2 libnss_toes.c -fPIC
|
|
||||||
*
|
|
||||||
* Install:
|
|
||||||
* cp libnss_toes.so.2 /lib/
|
|
||||||
* # Add "toes" to passwd line in /etc/nsswitch.conf
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <nss.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#define GUEST_UID 3001
|
|
||||||
#define GUEST_GID 3001
|
|
||||||
#define GUEST_HOME "/home/toes-cli"
|
|
||||||
#define GUEST_SHELL "/usr/local/bin/toes"
|
|
||||||
#define GUEST_GECOS "Toes CLI"
|
|
||||||
|
|
||||||
static const char *skip_users[] = {
|
|
||||||
"root", "toes", "toes-cli", "nobody", "daemon", "bin", "sys", "sync",
|
|
||||||
"games", "man", "lp", "mail", "news", "uucp", "proxy",
|
|
||||||
"www-data", "backup", "list", "irc", "gnats", "systemd-network",
|
|
||||||
"systemd-resolve", "messagebus", "sshd", "_apt",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static int should_skip(const char *name) {
|
|
||||||
for (const char **p = skip_users; *p; p++) {
|
|
||||||
if (strcmp(name, *p) == 0) return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum nss_status fill_passwd(const char *name, struct passwd *pw,
|
|
||||||
char *buf, size_t buflen, int *errnop) {
|
|
||||||
size_t namelen = strlen(name) + 1;
|
|
||||||
size_t gecoslen = strlen(GUEST_GECOS) + 1;
|
|
||||||
size_t homelen = strlen(GUEST_HOME) + 1;
|
|
||||||
size_t shelllen = strlen(GUEST_SHELL) + 1;
|
|
||||||
size_t needed = namelen + gecoslen + homelen + shelllen + 1; /* +1 for pw_passwd "" */
|
|
||||||
|
|
||||||
if (buflen < needed) {
|
|
||||||
*errnop = ERANGE;
|
|
||||||
return NSS_STATUS_TRYAGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *ptr = buf;
|
|
||||||
|
|
||||||
pw->pw_name = ptr;
|
|
||||||
memcpy(ptr, name, namelen);
|
|
||||||
ptr += namelen;
|
|
||||||
|
|
||||||
pw->pw_passwd = ptr;
|
|
||||||
*ptr++ = '\0';
|
|
||||||
|
|
||||||
pw->pw_uid = GUEST_UID;
|
|
||||||
pw->pw_gid = GUEST_GID;
|
|
||||||
|
|
||||||
pw->pw_gecos = ptr;
|
|
||||||
memcpy(ptr, GUEST_GECOS, gecoslen);
|
|
||||||
ptr += gecoslen;
|
|
||||||
|
|
||||||
pw->pw_dir = ptr;
|
|
||||||
memcpy(ptr, GUEST_HOME, homelen);
|
|
||||||
ptr += homelen;
|
|
||||||
|
|
||||||
pw->pw_shell = ptr;
|
|
||||||
memcpy(ptr, GUEST_SHELL, shelllen);
|
|
||||||
|
|
||||||
return NSS_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum nss_status _nss_toes_getpwnam_r(const char *name, struct passwd *pw,
|
|
||||||
char *buf, size_t buflen, int *errnop) {
|
|
||||||
if (!name || !*name || should_skip(name)) {
|
|
||||||
return NSS_STATUS_NOTFOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fill_passwd(name, pw, buf, buflen, errnop);
|
|
||||||
}
|
|
||||||
|
|
@ -1,67 +1,50 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# setup-ssh.sh - Configure SSH so any user gets the toes CLI
|
# setup-ssh.sh - Configure SSH for the toes CLI user
|
||||||
#
|
#
|
||||||
# This script:
|
# This script:
|
||||||
# 1. Compiles and installs the NSS module
|
# 1. Creates a `cli` system user with /usr/local/bin/toes as shell
|
||||||
# 2. Adds "toes" to nsswitch.conf passwd line
|
# 2. Sets an empty password on `cli` for passwordless SSH
|
||||||
# 3. Configures PAM to accept any password (home network appliance)
|
# 3. Adds a Match block in sshd_config to allow empty passwords for `cli`
|
||||||
# 4. Ensures PasswordAuthentication is enabled in sshd
|
# 4. Adds /usr/local/bin/toes to /etc/shells
|
||||||
# 5. Adds /usr/local/bin/toes to /etc/shells
|
# 5. Restarts sshd
|
||||||
# 6. Restarts sshd
|
|
||||||
#
|
#
|
||||||
# Run as root on the toes machine.
|
# Run as root on the toes machine.
|
||||||
|
# Usage: ssh cli@toes.local
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
||||||
|
|
||||||
echo "==> Setting up SSH auto-CLI for toes"
|
|
||||||
|
|
||||||
# 1. Compile and install NSS module
|
|
||||||
echo " Compiling NSS module..."
|
|
||||||
gcc -shared -o /tmp/libnss_toes.so.2 "$SCRIPT_DIR/nss/libnss_toes.c" -fPIC
|
|
||||||
cp /tmp/libnss_toes.so.2 /lib/
|
|
||||||
ldconfig
|
|
||||||
echo " Installed libnss_toes.so.2"
|
|
||||||
|
|
||||||
# 2. Add toes to nsswitch.conf
|
|
||||||
if ! grep -q 'passwd:.*toes' /etc/nsswitch.conf; then
|
|
||||||
sed -i 's/^passwd:.*/& toes/' /etc/nsswitch.conf
|
|
||||||
echo " Added toes to nsswitch.conf"
|
|
||||||
else
|
|
||||||
echo " nsswitch.conf already configured"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 3. Configure PAM - accept any password for SSH
|
|
||||||
if ! grep -q 'pam_permit.so.*# toes' /etc/pam.d/sshd; then
|
|
||||||
# Comment out existing auth and replace with pam_permit
|
|
||||||
sed -i '/^@include common-auth/s/^/# /' /etc/pam.d/sshd
|
|
||||||
sed -i '/^auth/s/^/# /' /etc/pam.d/sshd
|
|
||||||
# Add pam_permit after the commented lines
|
|
||||||
echo 'auth sufficient pam_permit.so # toes' >> /etc/pam.d/sshd
|
|
||||||
echo " Configured PAM for passwordless SSH"
|
|
||||||
else
|
|
||||||
echo " PAM already configured"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 4. Ensure PasswordAuthentication yes in sshd_config
|
|
||||||
SSHD_CONFIG="/etc/ssh/sshd_config"
|
|
||||||
if grep -q '^PasswordAuthentication no' "$SSHD_CONFIG"; then
|
|
||||||
sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' "$SSHD_CONFIG"
|
|
||||||
echo " Enabled PasswordAuthentication"
|
|
||||||
elif grep -q '^#PasswordAuthentication' "$SSHD_CONFIG"; then
|
|
||||||
sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication yes/' "$SSHD_CONFIG"
|
|
||||||
echo " Enabled PasswordAuthentication"
|
|
||||||
elif ! grep -q '^PasswordAuthentication yes' "$SSHD_CONFIG"; then
|
|
||||||
echo 'PasswordAuthentication yes' >> "$SSHD_CONFIG"
|
|
||||||
echo " Added PasswordAuthentication yes"
|
|
||||||
else
|
|
||||||
echo " PasswordAuthentication already enabled"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 5. Ensure /usr/local/bin/toes is in /etc/shells
|
|
||||||
TOES_SHELL="/usr/local/bin/toes"
|
TOES_SHELL="/usr/local/bin/toes"
|
||||||
|
SSHD_CONFIG="/etc/ssh/sshd_config"
|
||||||
|
|
||||||
|
echo "==> Setting up SSH CLI user for toes"
|
||||||
|
|
||||||
|
# 1. Create cli system user
|
||||||
|
if ! id cli &>/dev/null; then
|
||||||
|
useradd --system --home-dir /home/cli --shell "$TOES_SHELL" --create-home cli
|
||||||
|
echo " Created cli user"
|
||||||
|
else
|
||||||
|
echo " cli user already exists"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Set empty password
|
||||||
|
passwd -d cli
|
||||||
|
echo " Set empty password on cli"
|
||||||
|
|
||||||
|
# 3. Add Match block for cli user in sshd_config
|
||||||
|
if ! grep -q 'Match User cli' "$SSHD_CONFIG"; then
|
||||||
|
cat >> "$SSHD_CONFIG" <<EOF
|
||||||
|
|
||||||
|
# toes CLI: allow passwordless SSH for the cli user
|
||||||
|
Match User cli
|
||||||
|
PermitEmptyPasswords yes
|
||||||
|
EOF
|
||||||
|
echo " Added Match User cli block to sshd_config"
|
||||||
|
else
|
||||||
|
echo " sshd_config already has Match User cli block"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Ensure /usr/local/bin/toes is in /etc/shells
|
||||||
if ! grep -q "^${TOES_SHELL}$" /etc/shells; then
|
if ! grep -q "^${TOES_SHELL}$" /etc/shells; then
|
||||||
echo "$TOES_SHELL" >> /etc/shells
|
echo "$TOES_SHELL" >> /etc/shells
|
||||||
echo " Added $TOES_SHELL to /etc/shells"
|
echo " Added $TOES_SHELL to /etc/shells"
|
||||||
|
|
@ -69,31 +52,14 @@ else
|
||||||
echo " $TOES_SHELL already in /etc/shells"
|
echo " $TOES_SHELL already in /etc/shells"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure the toes binary exists (symlink to bun entry point)
|
# Warn if toes binary doesn't exist yet
|
||||||
if [ ! -f "$TOES_SHELL" ]; then
|
if [ ! -f "$TOES_SHELL" ]; then
|
||||||
echo " WARNING: $TOES_SHELL does not exist yet"
|
echo " WARNING: $TOES_SHELL does not exist yet"
|
||||||
echo " Create it with: ln -sf /path/to/toes/cli $TOES_SHELL"
|
echo " Create it with: ln -sf /path/to/toes/cli $TOES_SHELL"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create toes-cli system user for guest SSH sessions
|
# 5. Restart sshd
|
||||||
if ! id toes-cli &>/dev/null; then
|
|
||||||
useradd --system --uid 3001 --home-dir /home/toes-cli --shell /usr/local/bin/toes --create-home toes-cli
|
|
||||||
echo " Created toes-cli user"
|
|
||||||
else
|
|
||||||
echo " toes-cli user already exists"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Ensure /home/toes-cli exists for guest sessions
|
|
||||||
if [ ! -d /home/toes-cli ]; then
|
|
||||||
mkdir -p /home/toes-cli
|
|
||||||
chmod 755 /home/toes-cli
|
|
||||||
echo " Created /home/toes-cli"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 6. Restart sshd
|
|
||||||
echo " Restarting sshd..."
|
echo " Restarting sshd..."
|
||||||
systemctl restart sshd || service ssh restart || true
|
systemctl restart sshd || service ssh restart || true
|
||||||
|
|
||||||
echo "==> Done. Any SSH user will now get the toes CLI."
|
echo "==> Done. Connect with: ssh cli@toes.local"
|
||||||
echo " SSH users are mapped to the toes-cli account (UID 3001)."
|
|
||||||
echo " toes@toes.local still gets a regular shell."
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
#!/usr/bin/env bun
|
#!/usr/bin/env bun
|
||||||
import { program } from './setup'
|
import { program } from './setup'
|
||||||
|
|
||||||
const isSSH = !!process.env.SSH_CONNECTION
|
const isCliUser = process.env.USER === 'cli'
|
||||||
const noArgs = process.argv.length <= 2
|
const noArgs = process.argv.length <= 2
|
||||||
const isTTY = !!process.stdin.isTTY
|
const isTTY = !!process.stdin.isTTY
|
||||||
|
|
||||||
if (isSSH && noArgs && isTTY) {
|
if (isCliUser && noArgs && isTTY) {
|
||||||
const { shell } = await import('./shell')
|
const { shell } = await import('./shell')
|
||||||
await shell()
|
await shell()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user