Wie finde ich heraus, ob mein Sudoer-Privileg abgelaufen ist?

Wie finde ich heraus, ob mein Sudoer-Privileg abgelaufen ist?

Ich arbeite an einem Skript, das einen Befehl als sudo ausführt und NUR dann eine Textzeile wiedergibt, wenn meine Sudo-Berechtigungen abgelaufen sind, also nur, wenn mein Benutzer (nicht Root) bei der Ausführung eines Befehls mit sudo sein Kennwort erneut eingeben müsste.

Wie überprüfe ich das? Beachten Sie, dass $(id -u)selbst wenn ich es als sudo ausführe, meine aktuelle Benutzer-ID zurückgegeben wird, sodass nicht überprüft werden kann, ob sie mit 0 übereinstimmt ...

Ich brauche eine Methode, die dies stillschweigend überprüft.

Antwort1

Nutzen Sie die Möglichkeit -nzu prüfen, ob Sie noch über Privilegien verfügen; von man sudo:

-N,--nicht interaktiv

Fordern Sie den Benutzer nicht zu Eingaben jeglicher Art auf. Wenn zur Ausführung des Befehls ein Kennwort erforderlich ist, zeigt sudo eine Fehlermeldung an und beendet das Programm.

Zum Beispiel,

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

Beachten Sie, dass die Berechtigungen zwischen der Überprüfung sudo -n trueund der tatsächlichen Verwendung möglicherweise ablaufen. Sie können es direkt mit versuchen sudo -n command...und im Fehlerfall eine Meldung anzeigen und möglicherweise die sudointeraktive Ausführung erneut versuchen.

Bearbeiten: Siehe auch Ruakhs Kommentar unten.

Antwort2

Laufen:

sudo -nv

Wenn Ihre Sudo-Berechtigungen abgelaufen sind, wird dies mit einem Exitcode von 1 und der Ausgabe beendet:

sudo: a password is required

Wenn Sie über gültige zwischengespeicherte Anmeldeinformationen verfügen, ist dieser Befehl erfolgreich und gibt nichts aus.

Um das Ganze zusammenzufassen, hier ist ein Scriptlet, dasschweigendÜberprüfen Sie, ob Sie über gültige zwischengespeicherte Anmeldeinformationen verfügen:

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

Wie in anderen Antworten/Kommentaren erwähnt, -verneuert die Option („validieren“) von sudo stillschweigend zwischengespeicherte Anmeldeinformationen, wenn welche vorhanden sind, oder es erfolgt eine Authentifizierungsaufforderung, um zwischengespeicherte Anmeldeinformationen zu generieren, und die -nOption („nicht interaktiv“) verhindert, dass sudo interaktive Eingabeaufforderungen, wie etwa die Authentifizierungsaufforderung, generiert.

Antwort3

sudo -nvfunktioniert einwandfrei, verunreinigt aber die Systemprotokolle mit Sudo-Fehlern und PAM-Authentifizierungsinformationen. Ich musste die Sudo-Berechtigungen für meine Bash-Eingabeaufforderung überprüfen, daher wurde sie ziemlich oft ausgeführt und meine Protokolle bestanden fast nur aus diesem Rauschen.

Es ist möglich, die Sudo-Zeitstempeldatei direkt zu analysieren – ich habe dafür ein kleines C-Dienstprogramm geschrieben:

/* 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;
}

verwandte Informationen