セッションを拡張せずにPS1にsudoセッション状態を追加する

セッションを拡張せずにPS1にsudoセッション状態を追加する

次のように、bashプロンプトにsudoセッション状態を追加できます。

function sudo_active() {
    if sudo -n /bin/true 2> /dev/null
    then
        printf '(sudo) '
    fi
}

PS1="$PS1"'$(sudo_active)'

これにより、一連の sudo コマンドを実行でき、sudo セッションがまだアクティブであることを確認できます。セッションを早く終了したりsudo -k、シェルを閉じたり、注意事項を覚えたりするなどの方法を使用できます。

このアプローチの問題の1つは、sudo権限なしで新しいプロンプトが実行されるたびに、システムログに次のメッセージが追加されることです。

sudo[25653]: myusername : a password is required ; TTY=pts/13 ; PWD=/home/myusername/ ; USER=root ; COMMAND=/bin/true

別の問題は、これがsudo毎回プロンプトでコマンドを実行するため、passwd_timeout必要なコマンドを実行しなくても、コマンドを実行するたびに(値に応じて)タイムアウトが再び延長されることですsudo

sudoセッションがまだアクティブであることをテストし、副作用としてセッションを継続的に再拡張せずにbashプロンプトに表示する方法はありますか?

答え1

sudoが各ユーザーに対して生成するタイムスタンプファイルを使用して、そのユーザーがsudoコマンドを使用した時間を見つけることができます。設定された時間(デフォルトは5分)より長い場合は、timestamp_timeout新しいsudoにパスワードが必要です。

各ユーザーのファイルは/var/run/sudo/ts/(私のシステムでは)下に作成されます。man sudoersソースが示すように、フォーマットはセクションで説明されています。タイムスタンプ.cそしてcheck.hこれは、struct timestamp_entry_v1structまたは最新のstructで記述された複数のレコードで構成されていますstruct timestamp_entry

Gitバージョンは古いシステムの対応するソースよりも最新であるため、以前の構造バージョン1を使用しています。追加フィールドを持つ新しいバージョン2が必要になる場合があります。

以下は、ハードワイヤードユーザーの履歴をダンプする最小限のCプログラムです。

/* 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=%d\n",
               entry.type, entry.flags, entry.auth_uid, entry.sid,
               entry.ts.tv_sec-now.tv_sec);
    }
    exit(0);
}

私のシステムでこのsetuidルートをコンパイルして実行すると、次の行が表示されます。

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

タイプ 4 の最初の項目は、レコードをロックするために使用されます。他の行はttyごとにすることができます。フラグ1は、アイテムが無効になっていることを示します(例:のためsudo -k)。最後の行は、12秒前にプロセス4378でsudoコマンドを実行したuid 1000です。 5*60秒未満なので、追加のsudoにはまだパスワードは必要ありません。

関連情報