Come faccio a sapere se il mio privilegio sudoer è scaduto?


20

Sto lavorando a uno script che esegue un comando come sudo e fa eco a una riga di testo SOLO se i miei privilegi sudo sono scaduti, quindi solo se l'esecuzione di un comando con sudo richiederebbe al mio utente (non root) di digitare nuovamente la sua password.

Come posso verificarlo? Tieni presente che $(id -u)anche quando esegui come sudo restituirà il mio ID utente corrente in modo che non possa essere verificato per abbinarlo a 0 ...

Ho bisogno di un metodo per verificarlo con calma.

Risposte:


28

Utilizzare l'opzione -nper verificare se si dispone ancora di privilegi; da man sudo:

-n , --non-interattivo

Evitare di richiedere all'utente l'immissione di qualsiasi tipo. Se è richiesta una password per l'esecuzione del comando, sudo visualizzerà un messaggio di errore e uscirà.

Per esempio,

sudo -n true 2>/dev/null && echo Privileges active || echo Privileges inactive

Tenere presente che è possibile che i privilegi scadano tra il controllo sudo -n truee il loro effettivo utilizzo. Si consiglia di provare direttamente con sudo -n command...e in caso di errore visualizzare un messaggio ed eventualmente riprovare a eseguire in modo sudointerattivo.

Modifica: vedi anche il commento di Ruakh di seguito.


Grazie, ho provato qualcosa di simile prima, ma non riuscivo a farlo funzionare come volevo.
TonyMorello,

3
Ri: "Essere consapevoli del fatto che è possibile che i privilegi scadano tra il controllo sudo -n truee il loro utilizzo effettivo": la documentazione è un po 'vaga su questo punto, ma penso che l'esecuzione di un sudocomando, anche solo sudo -n true, ripristinerà il timeout orologio. Ad ogni modo, -vè esplicitamente documentato come farlo, ed sudo -n -vè probabilmente più appropriato che sudo -n trueper questo scopo comunque.
Ruakh,

Anche se questo sarà davvero in silenzio, registrerà l'errore al giornale di sistema se non ci sono privilegi: hostname sudo[8870]: username : a password is required ; TTY=pts/0 ; PWD=/home/username ; USER=root ; COMMAND=/usr/bin/true. Se lo usi nel prompt di bash, ad esempio, genererà molti messaggi di errore.
Rogach,

E se ci sono privilegi, ci sarà la registrazione del debug da pam_unix e l'esecuzione del comando sudo.
Rogach,

8

Correre:

sudo -nv

Se i tuoi privilegi sudo sono scaduti, questo uscirà con un codice di uscita 1 e produrrà:

sudo: a password is required

Se si dispone di credenziali memorizzate nella cache valide, questo comando avrà esito positivo e non genererà nulla.

Quindi, per mettere tutto insieme, ecco uno scriptlet che verificherà silenziosamente se hai credenziali memorizzate nella cache valide:

if sudo -nv 2>/dev/null; then
  echo "no sudo password required"
else
  echo "sudo password expired"
fi

Come menzionato in altre risposte / commenti, l' -vopzione ("convalida") di sudo rinnova silenziosamente le credenziali memorizzate nella cache in presenza di richieste per l'autenticazione al fine di generare credenziali memorizzate nella cache e l' -nopzione ("non interattiva") impedisce la generazione di sudo eventuali prompt interattivi, come il prompt di autenticazione.


Questa è una buona soluzione ... L'ho provato prima, ma la risposta di AlexP fa esattamente quello che mi serviva ... Penso di aver frainteso il parametro -n prima
TonyMorello,

1

sudo -nvfunziona bene, ma inquina i log di sistema con errori sudo e informazioni di autenticazione pam. Avevo bisogno di controllare i privilegi di sudo per il mio prompt di bash, quindi veniva eseguito abbastanza spesso e i miei log consistevano quasi solo di questo rumore.

È possibile analizzare direttamente il file timestamp sudo - per questo ho scritto un piccolo C util:

/* compile and set permissions: */
/* $ gcc checksudo.c -o checksudo -std=gnu99 -O2 */
/* $ chown root:root checksudo */
/* $ chmod +s checksudo */

#define USERNAME "replace-with-your-username"
#define TIMEOUT 5

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <time.h>

void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result) {
    if ((stop->tv_nsec - start->tv_nsec) < 0) {
        result->tv_sec = stop->tv_sec - start->tv_sec - 1;
        result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;
    } else {
        result->tv_sec = stop->tv_sec - start->tv_sec;
        result->tv_nsec = stop->tv_nsec - start->tv_nsec;
    }
    return;
}

int main(int argc, char** argv) {
  if (geteuid() != 0) {
    printf("uid is not 0 - checksudo must be owned by uid 0 and have the setuid bit set\n");
    return 2;
  }

  struct timespec current_time;
  if (clock_gettime(CLOCK_BOOTTIME, &current_time) != 0) {
    printf("Unable to get current time: %s\n", strerror(errno));
    return 2;
  }

  struct stat ttypath_stat;
  if (stat(ttyname(0), &ttypath_stat) != 0) {
    printf("Unable to stat current tty: %s\n", strerror(errno));
    return 2;
  }

  FILE* timestamp_fd = fopen("/var/run/sudo/ts/" USERNAME, "rb");
  if (timestamp_fd == NULL) {
    printf("Unable to open sudo timestamp file: %s\n", strerror(errno));
    return 2;
  }

  long offset = 0;
  int found = 0;

  while (1) {
    if (fseek(timestamp_fd, offset, SEEK_SET) != 0) {
      printf("Failed to seek timestamp file: %s\n", strerror(errno));
      return 2;
    }
    unsigned short timestamp_entry_header[4];
    if (feof(timestamp_fd)) {
      printf("matching timestamp not found\n");
      return 2;
    }
    if (fread(&timestamp_entry_header, sizeof(unsigned short), 4, timestamp_fd) < 4) {
      break;
    }
    if (ferror(timestamp_fd)) {
      printf("IO error when reading timestamp file\n");
      return 2;
    }

    // read tty device id
    if (timestamp_entry_header[2] == 2 && timestamp_entry_header[3] == 0) {
      if (fseek(timestamp_fd, offset + 32, SEEK_SET) != 0) {
        printf("Failed to seek timestamp file: %s\n", strerror(errno));
        return 2;
      }
      dev_t tty_dev_id;
      if (fread(&tty_dev_id, sizeof(dev_t), 1, timestamp_fd) < 1) {
        printf("EOF when reading tty device id\n");
        return 2;
      }
      if (tty_dev_id == ttypath_stat.st_rdev) {
        // read timestamp
        if (fseek(timestamp_fd, offset + 16, SEEK_SET) != 0) {
          printf("Failed to seek timestamp file: %s\n", strerror(errno));
          return 2;
        }
        struct timespec sudo_time;
        if (fread(&sudo_time, sizeof(struct timespec), 1, timestamp_fd) < 1) {
          printf("EOF when reading timestamp\n");
          return 2;
        }

        struct timespec time_since_sudo;
        timespec_diff(&sudo_time, &current_time, &time_since_sudo);
        found = time_since_sudo.tv_sec < TIMEOUT * 60;
        break;
      }
    }

    offset += timestamp_entry_header[1];
  }

  fclose(timestamp_fd);

  return !found;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.