GNU/Linux >> Znalost Linux >  >> Linux

Jak vytvořit podmíněnou položku PAM

Zde je řešení, které pro mě funguje. Můj /etc/pam.d/sudo :

#%PAM-1.0
auth            [success=1]     pam_exec.so    /tmp/test-pam
auth            required        pam_deny.so
auth            include         system-auth
account         include         system-auth
session         include         system-auth

A /tmp/test-pam :

#! /bin/bash
/bin/last -i -p now ${PAM_TTY#/dev/} | \
    /bin/awk 'NR==1 { if ($3 != "0.0.0.0") exit 9; exit 0; }'

Chápu toto chování:

$ sudo date
[sudo] password for jdoe:
Thu Jun 28 23:51:58 MDT 2018
$ ssh localhost
Last login: Thu Jun 28 23:40:23 2018 from ::1
valli$ sudo date
/tmp/test-pam failed: exit code 9
[sudo] password for jdoe:
sudo: PAM authentication error: System error
valli$

První řádek přidán k výchozímu pam.d/sudo volání pam_exec a pokud uspěje, přeskočí další položku. Druhý řádek pouze bezpodmínečně odepře přístup.

V /tmp/test-pam Volám last získat IP adresu spojenou s TTY pam byla vyvolána. ${PAM_TTY#/dev/} odstraní /dev/ od začátku hodnoty, protože last nerozpozná celou cestu k zařízení. -i příznak dělá last zobrazit buď IP adresu, nebo zástupný symbol 0.0.0.0 pokud neexistuje žádná IP adresa; ve výchozím nastavení zobrazuje informační řetězec, který je mnohem obtížnější zkontrolovat. To je také důvod, proč jsem použil last místo who nebo w; ti podobnou možnost nemají. -p now volba není nezbytně nutná, jak uvidíme awk kontroluje pouze první řádek výstupu, ale omezuje last zobrazit pouze uživatele, kteří jsou aktuálně přihlášeni.

awk příkaz pouze zkontroluje první řádek a pokud třetí pole není 0.0.0.0 ukončí se s chybou. Protože toto je poslední příkaz v /tmp/test-pam , výstupní kód awk se stane výstupním kódem pro skript.

V mém systému žádný z testů, které jste zkoušeli v deny-ssh-user.sh by fungovalo. Pokud zadáte env > /tmp/test-pam.log v horní části skriptu uvidíte, že prostředí bylo odstraněno, takže nebude nastavena žádná z vašich proměnných SSH_FOO. A $PPID může ukazovat na libovolný počet procesů. Spusťte například perl -e 'system("sudo cat /etc/passwd")' a uvidíte, že $PPID odkazuje na perl proces.

Toto je Arch Linux, jádro 4.16.11-1-ARCH , v případě, že na tom záleží. Nemyslím si však, že by mělo.


No, ukázalo se, že jsem vlastně idiot, pam_exec.so modul je naprosto v pořádku pro vytváření podmínek PAM.

Tim Smith měl pravdu, když vyhodnotil oba testy v mém /etc/security/deny-ssh-user.sh skript NIKDY nenastavoval proměnnou SSH_SESSION na pravdu. Nebral jsem to v úvahu, protože skript funguje v normálním prostředí, ale kontext prostředí je při spuštění pomocí pam_exec.so odstraněn .

Nakonec jsem skript přepsal tak, aby používal last utility stejně jako jeho příklad, ale některé jsem musel změnit, protože přepínače pro last se liší od Arch Linuxu a RedHat.

Zde je upravený skript na /etc/security/deny-ssh-user.sh:

#!/bin/bash
# Returns 1 if the user is logged in through SSH
# Returns 0 if the user is not logged in through SSH
SSH_SESSION=false

function isSshSession {
    local terminal="${1}"
    if $(/usr/bin/last -i | 
        /usr/bin/grep "${terminal}" |
        /usr/bin/grep 'still logged in' |
        /usr/bin/awk '{print $3}' |
        /usr/bin/grep -q --invert-match '0\.0\.0\.0'); then
        echo true
    else
        echo false
    fi
}

function stripTerminal {
    local terminal="${1}"

    # PAM_TTY is in the form /dev/pts/X
    # Last utility displays TTY in the form pts/x
    # Returns the first five characters stripped from TTY
    echo "${terminal:5}"
}

lastTerminal=$( stripTerminal "${PAM_TTY}")
SSH_SESSION=$(isSshSession "${lastTerminal}")

if "${SSH_SESSION}"; then
    exit 1
else
    exit 0
fi

Obsah /etc/pam.d/sudo

....
auth    [success=ok default=1]    pam_exec.so /etc/security/deny-ssh-user.sh
auth    sufficient    pam_module_to_skip.so
....

Linux
  1. Jak vytvořit skript příkazu Linux

  2. Jak vytvořit subdoménu

  3. Jak vytvořit odkaz na adresář

  1. Jak vytvořit Ansible Playbook

  2. Jak vytvořit Git Tagy

  3. Jak vytvořit subdoménu

  1. Jak spustit MongoDB na Kubernetes

  2. Jak vytvořit symbolické odkazy v Linuxu

  3. Jak vytvořit aliasy Bash