bashsudo

Need a test to see if sudo is already active (cached)


I need a bash script to check if 'sudo' WOULD be able to works without prompting for a password.

How do you best test for sudo as being ready to go and not needing a password because its session has not yet timed out?

Something like that:

if ! sudo -vnN >/dev/null 2>&1; then

  echo "Need to do something before a password prompt"

fi
sudo bash -c 'ls /var/log/*'

Was trying to do some prep work at the bash/csh level before executing sudo.


Solution

  • Looking for cache in sudo's man page:

    man -P"sed -ne 'H;/^[[:space:]]*$/{ x;/cache/{ s/\n$//;p}};'" sudo
    

    In order to reduce number of lines, I've ran this command in a 273 columns width terminal:

     Security policies may support credential caching to allow the user to run sudo again for a period of time without requiring authentication.  By default, the sudoers policy caches credentials on a per-terminal basis for 15 minutes.  See the timestamp_type and
     timestamp_timeout options in sudoers(5) for more information.  By running sudo with the -v option, a user can update the cached credentials without running a command.
    
     -K, --remove-timestamp
             Similar to the -k option, except that it removes every cached credential for the user, regardless of the terminal or parent process ID.  The next time sudo is run, a password must be entered if the security policy requires authentication.  It is not
             possible to use the -K option in conjunction with a command or other option.  This option does not require a password.  Not all security policies support credential caching.
    
     -k, --reset-timestamp
             When used without a command, invalidates the user's cached credentials for the current session.  The next time sudo is run in the session, a password must be entered if the security policy requires authentication.  By default, the sudoers policy uses a
             separate record in the credential cache for each terminal (or parent process ID if no terminal is present).  This prevents the -k option from interfering with sudo commands run in a different terminal session.  See the timestamp_type option in
             sudoers(5) for more information.  This option does not require a password, and was added to allow a user to revoke sudo permissions from a .logout file.
    
             When used in conjunction with a command or an option that may require a password, this option will cause sudo to ignore the user's cached credentials.  As a result, sudo will prompt for a password (if one is required by the security policy) and will not
             update the user's cached credentials.
    
     -N, --no-update
             Do not update the user's cached credentials, even if the user successfully authenticates.  Unlike the -k flag, existing cached credentials are used if they are valid.  To detect when the user's cached credentials are valid (or when no authentication is
             required), the following can be used:
                   sudo -Nnv
    
     -v, --validate
             Update the user's cached credentials, authenticating the user if necessary.  For the sudoers plugin, this extends the sudo timeout for another 15 minutes by default, but does not run a command.  Not all security policies support cached credentials.
    

    There seem not to be more than your tries. Anyway, I recommend using 2>&1 then store result:

    #!/bin/bash
    
    die() {
         echo >&2 "ERROR ${*}";
         exit 1
    }
    doing_some_prep_for_password() {
        local sudo_msg sudo_ready
        sudo_msg=$( LANG=C sudo -Nnv 2>&1 )
        sudo_ready=$(( $? == 0 ))
    
        if ! (( sudo_ready )); then
            case $sudo_msg in
                *may\ not\ run\ sudo* )
                    die $sudo_msg
                    ;;
                *'password is required'* )
                    echo "Need to do something before a password prompt"
                    : ---  You should add your code here...  ---
                    ;;
                * )
                    printf 'Warning: unhandled sudo answer:\n  '%s'\n' "$sudo_msg"
                    exit 1
                    ;;
            esac
        fi
    }
    doing_some_prep_for_password
    
    sudo SUDO_SCRIPT="${0##*/}" /bin/bash <<"EOSudo"
        printf '%s as UID=%s(%s) begin here...\n' "$SUDO_SCRIPT" $EUID $UID
        ls /var/log/*
    EOSudo
    

    First run

    superuser@smallserv:~$ ./testSudo.sh 
    Need to do something before a password prompt
    [sudo] password for superuser: 
    testSudo.sh as UID=0(0) begin here...
    

    Second run:

    superuser@smallserv:~$ ./testSudo.sh
    testSudo.sh as UID=0(0) begin here...
    

    In another normal user environment:

    john@smallserv:~$ ./testSudo.sh
    ERROR Sorry, user john may not run sudo on smallserv.