Unix & Linux Asked by Nathaniel M. Beaver on November 16, 2021
I can add the status of a sudo session to the bash prompt like this:
function sudo_active() {
if sudo -n /bin/true 2> /dev/null
then
printf '(sudo) '
fi
}
PS1="$PS1"'$(sudo_active)'
This way I can run a series of sudo commands
and afterward I’ll know if the sudo session is still active or not.
I can end the session early with sudo -k
,
close the shell,
or just remember to be careful.
One issue with this approach
is that every time a new prompt runs without sudo privileges
it adds a message like this to the system log:
sudo[25653]: myusername : a password is required ; TTY=pts/13 ; PWD=/home/myusername/ ; USER=root ; COMMAND=/bin/true
The other problem is that because this runs a sudo
command
in the prompt every time,
it will re-extend the timeout every time I run a command
(depending on the value of passwd_timeout
),
even if I don’t run a command that requires sudo
.
Is there a way I can test if the sudo session is still active
and show this in the bash prompt
without continually re-extending the session as a side effect?
You can use the timestamp file that sudo creates per-user to find how long ago a sudo command was used by that user; if it is further than the configured timestamp_timeout
(default 5 minutes), then a new sudo will need a password.
The per-user file is created under /var/run/sudo/ts/
(on my system). Its format is partially described in man sudoers
and you can see from the sources timestamp.c and check.h that it consists of several records described by the struct struct timestamp_entry_v1
or the newer struct timestamp_entry
.
The git version is newer than the sources corresponding to my old-ish system so I'm using the older struct, version 1. You may need need the newer version 2 with an extra field.
Here's a minimal C program to dump the records for a hard-wired user:
/* https://unix.stackexchange.com/a/595473/119298
* struct from
* https://github.com/sudo-project/sudo/blob/master/plugins/sudoers/check.h
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define TS_VERSION 1
/* Time stamp entry types */
#define TS_GLOBAL 0x01
#define TS_TTY 0x02
#define TS_PPID 0x03
#define TS_LOCKEXCL 0x04
/* Time stamp flags */
#define TS_DISABLED 0x01 /* entry disabled */
#define TS_ANYUID 0x02 /* ignore uid, only valid in the key */
struct timestamp_entry {
unsigned short version; /* version number */
unsigned short size; /* entry size */
unsigned short type; /* TS_GLOBAL, TS_TTY, TS_PPID */
unsigned short flags; /* TS_DISABLED, TS_ANYUID */
uid_t auth_uid; /* uid to authenticate as */
pid_t sid; /* session ID associated with tty/ppid */
struct timespec ts; /* timestamp (CLOCK_MONOTONIC) */
union {
dev_t ttydev; /* tty device number */
pid_t ppid; /* parent pid */
} u;
};
void main(int argc, char **argv){
struct timestamp_entry entry;
struct timespec now;
int fd = open("/var/run/sudo/ts/meuh",O_RDONLY);
if(fd<0)exit(1);
clock_gettime(CLOCK_MONOTONIC, &now);
while(read(fd,&entry,sizeof(entry))==sizeof(entry)){
printf("type=%d flags=%d uid=%d sid=%d elapsedtime=%dn",
entry.type, entry.flags, entry.auth_uid, entry.sid,
entry.ts.tv_sec-now.tv_sec);
}
exit(0);
}
Compiling and running this setuid root on my system gave me lines like
type=4 flags=0 uid=0 sid=0 elapsedtime=-4763540
type=2 flags=1 uid=1000 sid=7003 elapsedtime=-4763540
type=2 flags=0 uid=1000 sid=4378 elapsedtime=-12
The first entry of type 4 is used to lock the records. The other lines can be per-tty and so on. flags of 1 are for a disabled entry (for example due to sudo -k
). The last line was for my uid 1000 having done a sudo command 12 seconds ago from process 4378. Since this is less than 5*60 seconds, further sudo's do not yet need a password.
Answered by meuh on November 16, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP