
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 -n
zu 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 true
und 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 sudo
interaktive 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, -v
erneuert die Option („validieren“) von sudo stillschweigend zwischengespeicherte Anmeldeinformationen, wenn welche vorhanden sind, oder es erfolgt eine Authentifizierungsaufforderung, um zwischengespeicherte Anmeldeinformationen zu generieren, und die -n
Option („nicht interaktiv“) verhindert, dass sudo interaktive Eingabeaufforderungen, wie etwa die Authentifizierungsaufforderung, generiert.
Antwort3
sudo -nv
funktioniert 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, ¤t_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(×tamp_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, ¤t_time, &time_since_sudo);
found = time_since_sudo.tv_sec < TIMEOUT * 60;
break;
}
}
offset += timestamp_entry_header[1];
}
fclose(timestamp_fd);
return !found;
}