내 sudoer 권한이 만료되었는지 어떻게 확인하나요?

내 sudoer 권한이 만료되었는지 어떻게 확인하나요?

sudo로 명령을 실행하고 sudo 권한이 시간 초과될 때만 텍스트 줄을 에코하는 스크립트를 작성 중입니다. 따라서 sudo로 명령을 실행하려면 사용자(루트 아님)가 비밀번호를 다시 입력해야 합니다.

이를 어떻게 확인하나요? sudo로 실행 해도 $(id -u)현재 사용자 ID가 반환되므로 0과 일치하는지 확인할 방법이 없습니다.

조용히 확인할 방법이 필요해요.

답변1

-n다음의 권한이 아직 있는지 확인하려면 이 옵션을 사용하세요 man sudo.

-N,--비대화형

사용자에게 어떤 유형의 입력도 요청하지 마세요. 명령을 실행하는 데 비밀번호가 필요한 경우 sudo는 오류 메시지를 표시하고 종료됩니다.

예를 들어,

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

sudo -n true확인 후 실제 사용 사이에 권한이 만료될 수 있습니다. 직접 시도해보고 sudo -n command...실패할 경우 메시지를 표시하고 sudo대화형으로 다시 실행해 볼 수도 있습니다.

편집: 아래 ruakh의 의견도 참조하세요.

답변2

달리기:

sudo -nv

sudo 권한이 만료된 경우 종료 코드 1로 종료되고 다음이 출력됩니다.

sudo: a password is required

유효한 캐시된 자격 증명이 있는 경우 이 명령은 성공하고 아무것도 출력하지 않습니다.

모든 것을 종합하면 다음과 같은 스크립트가 있습니다.아무 말 않고유효한 캐시된 자격 증명이 있는지 확인하세요.

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

다른 답변/댓글에서 언급했듯이 -vsudo의 옵션("인증")은 캐시된 자격 증명을 생성하기 위한 인증 프롬프트가 있는 경우 캐시된 자격 증명을 자동으로 업데이트하고 -n옵션("비대화형")은 sudo가 다음과 같은 대화형 프롬프트를 생성하는 것을 방지합니다. 인증 프롬프트로.

답변3

sudo -nv잘 작동하지만 sudo 오류 및 pam 인증 메시지로 시스템 로그를 오염시킵니다. sudo 권한에 대한 bash 프롬프트를 확인해야 하므로 매우 자주 실행되고 내 로그에는 거의 이러한 소음만 포함됩니다.

sudo 타임스탬프 파일을 직접 구문 분석하는 것이 가능합니다. 이를 위해 작은 C 유틸리티를 작성했습니다.

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

관련 정보