GNU/Linux >> Linux Esercitazione >  >> Linux

Come creare una voce PAM condizionale

Ecco una soluzione che funziona per me. Il mio /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

E /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; }'

Ottengo questo comportamento:

$ 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$

La prima riga aggiunta al pam.d/sudo predefinito chiama pam_exec e, se ha successo, salta la voce successiva. La seconda riga nega l'accesso incondizionatamente.

In /tmp/test-pam Chiamo last per ottenere l'indirizzo IP associato al TTY pam da cui è stato richiamato. ${PAM_TTY#/dev/} rimuove /dev/ dalla parte anteriore del valore, perché last non riconosce il percorso completo del dispositivo. Il -i flag rende last mostra l'indirizzo IP o il segnaposto 0.0.0.0 se non c'è un indirizzo IP; per impostazione predefinita mostra una stringa di informazioni che è molto più difficile da controllare. Questo è anche il motivo per cui ho usato last invece di who o w; quelli non hanno un'opzione simile. Il -p now l'opzione non è strettamente necessaria, come vedremo awk controlla solo la prima riga dell'output, ma limita last per mostrare solo gli utenti che sono attualmente connessi.

Il awk command controlla solo la prima riga e se il terzo campo non è 0.0.0.0 esce con un errore. Poiché questo è l'ultimo comando in /tmp/test-pam , il codice di uscita di awk diventa il codice di uscita per lo script.

Sul mio sistema, nessuno dei test che stavi provando nel tuo deny-ssh-user.sh funzionerebbe. Se inserisci env > /tmp/test-pam.log nella parte superiore del tuo script, vedrai che l'ambiente è stato rimosso, quindi nessuna delle tue variabili SSH_FOO verrà impostata. E $PPID potrebbe puntare a qualsiasi numero di processi. Ad esempio, esegui perl -e 'system("sudo cat /etc/passwd")' e vedi che $PPID fa riferimento a perl processo.

Questo è Arch Linux, kernel 4.16.11-1-ARCH , nel caso sia importante. Non penso che dovrebbe, però.


Beh, si scopre che in realtà sono un idiota, il pam_exec.so module va benissimo per creare condizionali PAM.

Tim Smith aveva ragione nel valutare che entrambi i test nel mio /etc/security/deny-ssh-user.sh script non impostavano MAI la variabile SSH_SESSION a vero. Non l'ho preso in considerazione perché lo script funziona in una shell normale, ma il contesto dell'ambiente viene rimosso quando viene eseguito da pam_exec.so .

Ho finito per riscrivere lo script per usare il last proprio come il suo esempio, tuttavia ho dovuto modificarne alcune perché le opzioni per last differiscono da Arch Linux a RedHat.

Ecco lo script rivisto in /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

Contenuto di /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. Come creare un Playbook Ansible

  2. Come creare tag Git

  3. Come creare un sottodominio

  4. Come creare un sottodominio

  5. Come creare un collegamento a una directory

Come creare uno StatefulSet in Kubernetes

Come creare una coda SQS su AWS

Come creare una tabella DynamoDB in AWS

Come creare collegamenti su desktop Linux

Come creare alias SSH in Linux

Come creare un alias in Linux