2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 09:57:41 +00:00

iolog_parse_loginfo() now opens the log file itself.

This commit is contained in:
Todd C. Miller 2020-03-29 05:05:08 -06:00
parent 9ab8efa8f4
commit a644c1d1d2
5 changed files with 49 additions and 51 deletions

View File

@ -109,7 +109,7 @@ bool expand_iolog_path(const char *inpath, char *path, size_t pathlen, const str
bool iolog_parse_timing(const char *line, struct timing_closure *timing);
char *iolog_parse_delay(const char *cp, struct timespec *delay, const char *decimal_point);
int iolog_read_timing_record(struct iolog_file *iol, struct timing_closure *timing);
struct iolog_info *iolog_parse_loginfo(FILE *fp, const char *iolog_dir);
struct iolog_info *iolog_parse_loginfo(int dfd, const char *iolog_dir);
void iolog_adjust_delay(struct timespec *delay, struct timespec *max_delay, double scale_factor);
void iolog_free_loginfo(struct iolog_info *li);

View File

@ -61,14 +61,32 @@
static int timing_event_adj;
struct iolog_info *
iolog_parse_loginfo(FILE *fp, const char *logfile)
iolog_parse_loginfo(int dfd, const char *iolog_dir)
{
char *buf = NULL, *cp, *ep;
const char *errstr;
size_t bufsize = 0, cwdsize = 0, cmdsize = 0;
struct iolog_info *li = NULL;
FILE *fp = NULL;
int fd = -1;
debug_decl(iolog_parse_loginfo, SUDO_DEBUG_UTIL);
if (dfd == -1) {
if ((dfd = open(iolog_dir, O_RDONLY)) == -1) {
sudo_warn("%s", iolog_dir);
goto bad;
}
fd = openat(dfd, "log", O_RDONLY, 0);
close(dfd);
} else {
fd = openat(dfd, "log", O_RDONLY, 0);
}
if (fd == -1 || (fp = fdopen(fd, "r")) == NULL) {
sudo_warn("%s/log", iolog_dir);
goto bad;
}
fd = -1;
/*
* Info file has three lines:
* 1) a log info line
@ -80,9 +98,11 @@ iolog_parse_loginfo(FILE *fp, const char *logfile)
if (getdelim(&buf, &bufsize, '\n', fp) == -1 ||
getdelim(&li->cwd, &cwdsize, '\n', fp) == -1 ||
getdelim(&li->cmd, &cmdsize, '\n', fp) == -1) {
sudo_warn(U_("%s: invalid log file"), logfile);
sudo_warn(U_("%s: invalid log file"), iolog_dir);
goto bad;
}
fclose(fp);
fp = NULL;
/* Strip the newline from the cwd and command. */
li->cwd[strcspn(li->cwd, "\n")] = '\0';
@ -98,20 +118,20 @@ iolog_parse_loginfo(FILE *fp, const char *logfile)
/* timestamp */
if ((ep = strchr(cp, ':')) == NULL) {
sudo_warn(U_("%s: time stamp field is missing"), logfile);
sudo_warn(U_("%s: time stamp field is missing"), iolog_dir);
goto bad;
}
*ep = '\0';
li->tstamp = sudo_strtonum(cp, 0, TIME_T_MAX, &errstr);
if (errstr != NULL) {
sudo_warn(U_("%s: time stamp %s: %s"), logfile, cp, errstr);
sudo_warn(U_("%s: time stamp %s: %s"), iolog_dir, cp, errstr);
goto bad;
}
/* submit user */
cp = ep + 1;
if ((ep = strchr(cp, ':')) == NULL) {
sudo_warn(U_("%s: user field is missing"), logfile);
sudo_warn(U_("%s: user field is missing"), iolog_dir);
goto bad;
}
if ((li->user = strndup(cp, (size_t)(ep - cp))) == NULL)
@ -120,7 +140,7 @@ iolog_parse_loginfo(FILE *fp, const char *logfile)
/* runas user */
cp = ep + 1;
if ((ep = strchr(cp, ':')) == NULL) {
sudo_warn(U_("%s: runas user field is missing"), logfile);
sudo_warn(U_("%s: runas user field is missing"), iolog_dir);
goto bad;
}
if ((li->runas_user = strndup(cp, (size_t)(ep - cp))) == NULL)
@ -129,7 +149,7 @@ iolog_parse_loginfo(FILE *fp, const char *logfile)
/* runas group */
cp = ep + 1;
if ((ep = strchr(cp, ':')) == NULL) {
sudo_warn(U_("%s: runas group field is missing"), logfile);
sudo_warn(U_("%s: runas group field is missing"), iolog_dir);
goto bad;
}
if (cp != ep) {
@ -156,14 +176,14 @@ iolog_parse_loginfo(FILE *fp, const char *logfile)
li->lines = sudo_strtonum(cp, 1, INT_MAX, &errstr);
if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: tty lines %s: %s", logfile, cp, errstr);
"%s: tty lines %s: %s", iolog_dir, cp, errstr);
}
if (ep != NULL) {
cp = ep + 1;
li->cols = sudo_strtonum(cp, 1, INT_MAX, &errstr);
if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: tty cols %s: %s", logfile, cp, errstr);
"%s: tty cols %s: %s", iolog_dir, cp, errstr);
}
}
}
@ -171,6 +191,10 @@ iolog_parse_loginfo(FILE *fp, const char *logfile)
debug_return_ptr(li);
bad:
if (fd != -1)
close(fd);
if (fp != NULL)
fclose(fp);
free(buf);
iolog_free_loginfo(li);
debug_return_ptr(NULL);

View File

@ -1487,8 +1487,7 @@ main(int argc, char *argv[])
struct timespec elapsed = { 0, 0 };
const char *iolog_id = NULL;
const char *open_mode = "r";
int ch, sock, iolog_dir_fd, fd;
FILE *fp;
int ch, sock, iolog_dir_fd;
debug_decl_vars(main, SUDO_DEBUG_MAIN);
#if defined(SUDO_DEVEL) && defined(__OpenBSD__)
@ -1582,12 +1581,7 @@ main(int argc, char *argv[])
}
/* Parse I/O log info file. */
fd = openat(iolog_dir_fd, "log", O_RDONLY, 0);
if (fd == -1 || (fp = fdopen(fd, "r")) == NULL) {
sudo_warn("%s/log", iolog_dir);
goto bad;
}
if ((log_info = iolog_parse_loginfo(fp, iolog_dir)) == NULL)
if ((log_info = iolog_parse_loginfo(iolog_dir_fd, iolog_dir)) == NULL)
goto bad;
if ((evbase = sudo_ev_base_alloc()) == NULL)

View File

@ -82,22 +82,15 @@ sudo_printf_int(int msg_type, const char *fmt, ...)
}
bool
validate_iolog_info(const char *logfile)
validate_iolog_info(const char *log_dir)
{
struct iolog_info *info;
time_t now;
FILE *fp;
time(&now);
/* Parse log file. */
if ((fp = fopen(logfile, "r")) == NULL) {
sudo_warn("%s", logfile);
return false;
}
info = iolog_parse_loginfo(fp, logfile);
fclose(fp);
if (info == NULL)
if ((info = iolog_parse_loginfo(-1, log_dir)) == NULL)
return false;
if (strcmp(info->cwd, "/") != 0) {
@ -262,8 +255,7 @@ test_endpoints(int *ntests, int *nerrors, const char *iolog_dir, char *envp[])
/* Validate I/O log info file. */
(*ntests)++;
snprintf(iolog_path, sizeof(iolog_path), "%s/log", iolog_dir);
if (!validate_iolog_info(iolog_path))
if (!validate_iolog_info(iolog_dir))
(*nerrors)++;
/* Test log_ttyout endpoint. */

View File

@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2009-2019 Todd C. Miller <Todd.Miller@sudo.ws>
* Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -207,7 +207,7 @@ __dso_public int main(int argc, char *argv[]);
int
main(int argc, char *argv[])
{
int ch, fd, i, iolog_dir_fd, len, exitcode = EXIT_FAILURE;
int ch, i, iolog_dir_fd, len, exitcode = EXIT_FAILURE;
bool def_filter = true, listonly = false;
bool interactive = true, suspend_wait = false, resize = true;
const char *decimal, *id, *user = NULL, *pattern = NULL, *tty = NULL;
@ -215,7 +215,6 @@ main(int argc, char *argv[])
struct iolog_info *li;
struct timespec max_delay_storage, *max_delay = NULL;
double dval;
FILE *fp;
debug_decl(main, SUDO_DEBUG_MAIN);
#if defined(SUDO_DEVEL) && defined(__OpenBSD__)
@ -363,12 +362,8 @@ main(int argc, char *argv[])
}
/* Parse log file. */
fd = openat(iolog_dir_fd, "log", O_RDONLY, 0);
if (fd == -1 || (fp = fdopen(fd, "r")) == NULL)
sudo_fatal(U_("unable to open %s/%s"), iolog_dir, "log");
if ((li = iolog_parse_loginfo(fp, iolog_dir)) == NULL)
if ((li = iolog_parse_loginfo(iolog_dir_fd, iolog_dir)) == NULL)
goto done;
fclose(fp);
printf(_("Replaying sudo session: %s"), li->cmd);
/* Setup terminal if appropriate. */
@ -1306,28 +1301,23 @@ match_expr(struct search_node_list *head, struct iolog_info *log, bool last_matc
}
static int
list_session(char *logfile, regex_t *re, const char *user, const char *tty)
list_session(char *log_dir, regex_t *re, const char *user, const char *tty)
{
char idbuf[7], *idstr, *cp;
struct iolog_info *li = NULL;
const char *timestr;
int ret = -1;
FILE *fp;
debug_decl(list_session, SUDO_DEBUG_UTIL);
if ((fp = fopen(logfile, "r")) == NULL) {
sudo_warn("%s", logfile);
goto done;
}
if ((li = iolog_parse_loginfo(fp, logfile)) == NULL)
if ((li = iolog_parse_loginfo(-1, log_dir)) == NULL)
goto done;
/* Match on search expression if there is one. */
if (!STAILQ_EMPTY(&search_expr) && !match_expr(&search_expr, li, true))
goto done;
/* Convert from /var/log/sudo-sessions/00/00/01/log to 000001 */
cp = logfile + strlen(session_dir) + 1;
/* Convert from /var/log/sudo-sessions/00/00/01 to 000001 */
cp = log_dir + strlen(session_dir) + 1;
if (IS_IDLOG(cp)) {
idbuf[0] = cp[0];
idbuf[1] = cp[1];
@ -1338,8 +1328,7 @@ list_session(char *logfile, regex_t *re, const char *user, const char *tty)
idbuf[6] = '\0';
idstr = idbuf;
} else {
/* Not an id, just use the iolog_file portion. */
cp[strlen(cp) - 4] = '\0';
/* Not an id, use as-is. */
idstr = cp;
}
/* XXX - print lines + cols? */
@ -1354,8 +1343,6 @@ list_session(char *logfile, regex_t *re, const char *user, const char *tty)
ret = 0;
done:
if (fp != NULL)
fclose(fp);
iolog_free_loginfo(li);
debug_return_int(ret);
}
@ -1445,9 +1432,10 @@ find_sessions(const char *dir, regex_t *re, const char *user, const char *tty)
/* Check for dir with a log file. */
if (lstat(pathbuf, &sb) == 0 && S_ISREG(sb.st_mode)) {
pathbuf[sdlen + len - 4] = '\0';
list_session(pathbuf, re, user, tty);
} else {
/* Strip off "/log" and recurse if a dir. */
/* Strip off "/log" and recurse if a non-log dir. */
pathbuf[sdlen + len - 4] = '\0';
if (checked_type ||
(lstat(pathbuf, &sb) == 0 && S_ISDIR(sb.st_mode)))