2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-31 14:25:15 +00:00

Add support for selecting by pattern and tty when listing.

This commit is contained in:
Todd C. Miller
2009-08-23 13:33:26 +00:00
parent 30cfb7160e
commit 9efd18b1bb

View File

@@ -73,6 +73,9 @@
# include <ndir.h>
# endif
#endif
#ifdef HAVE_REGCOMP
# include <regex.h>
#endif
#include <pathnames.h>
@@ -93,11 +96,24 @@ const char *session_dir = _PATH_SUDO_SESSDIR;
void usage __P((void));
void delay __P((double));
int list_sessions __P((int, char **));
int list_sessions __P((int, char **, const char *, const char *));
#ifdef HAVE_REGCOMP
# define REGEX_T regex_t
#else
# define REGEX_T char
#endif
/*
* TODO: expand ability to scan for session files:
* scan by command (regex?), user, tty, provide summary
* Things to think about:
* use a unique, inrementing id but break things up into lots of
* sub dirs like squid? Means keeping a seq file to track the next id.
* Just use a random uuid with multiple dirs?
* 550e8400-e29b-41d4-a716-446655440000
* Being able to select by user without opening all files is handy.
* Selecting by time could also be useful so an id that consists of a
* timestamp + random bits + username might be good.
*/
int
@@ -109,7 +125,7 @@ main(argc, argv)
int listonly = 0;
char path[PATH_MAX];
char buf[BUFSIZ];
const char *user, *id, *tty = NULL;
const char *user, *id, *pattern = NULL, *tty = NULL;
char *cp, *ep;
FILE *tfile, *sfile, *lfile;
double seconds;
@@ -120,7 +136,8 @@ main(argc, argv)
Argc = argc;
Argv = argv;
while ((ch = getopt(argc, argv, "d:ls:t:")) != -1) {
/* XXX - timestamp option? (begin,end) */
while ((ch = getopt(argc, argv, "d:lp:s:t:")) != -1) {
switch(ch) {
case 'd':
session_dir = optarg;
@@ -128,6 +145,9 @@ main(argc, argv)
case 'l':
listonly = 1;
break;
case 'p':
pattern = optarg;
break;
case 's':
errno = 0;
speed = strtod(optarg, &ep);
@@ -147,7 +167,7 @@ main(argc, argv)
argv += optind;
if (listonly) {
exit(list_sessions(argc, argv));
exit(list_sessions(argc, argv, pattern, tty));
}
if (argc != 2 && argc != 3)
@@ -177,9 +197,9 @@ main(argc, argv)
if (lfile == NULL)
error(1, "unable to open %s", path);
/* XXX - better */
fgets(buf, sizeof(buf), lfile); /* XXX - ignore first line */
fgets(buf, sizeof(buf), lfile);
if (!fgets(buf, sizeof(buf), lfile) || !fgets(buf, sizeof(buf), lfile))
errorx(1, "incomplete log file: %s", path);
fclose(lfile);
printf("Replaying sudo session: %s", buf);
/*
@@ -264,50 +284,124 @@ delay(secs)
}
int
list_sessions(argc, argv)
int argc;
char **argv;
list_user_sessions(user, re, tty)
const char *user;
REGEX_T *re;
const char *tty;
{
FILE *fp;
DIR *sess_d, *user_d;
DIR *user_d;
struct dirent *dp;
char path[PATH_MAX];
char buf[BUFSIZ];
char path[PATH_MAX], buf[BUFSIZ], cmd[BUFSIZ];
char *cmd_tty;
time_t tstamp;
int len, plen;
plen = snprintf(path, sizeof(path), "%s/%s/", session_dir, user);
if (plen <= 0 || plen >= sizeof(path)) {
warning("%s/%s/: %s", session_dir, user, strerror(ENAMETOOLONG));
return(-1);
}
path[--plen] = '\0'; /* chop off the '/' for now */
user_d = opendir(path);
if (user_d == NULL && errno != ENOTDIR) {
warning("cannot opendir %s", path);
return(-1);
}
while ((dp = readdir(user_d)) != NULL) {
/* base session (log) file name is 10 characters */
len = NAMLEN(dp);
if (len != 10)
continue;
/* open log file, print id and command */
path[plen] = '/'; /* restore dir separator */
strlcpy(path + plen + 1, dp->d_name, sizeof(path) - plen - 1); /* XXX - check */
fp = fopen(path, "r");
if (fp == NULL) {
warning("unable to open %s", path);
continue;
}
/*
* ID file has two lines:
* timestamp tty
* command
*/
/* XXX - BUFSIZ might not be enough, implement getline? */
if (!fgets(buf, sizeof(buf), fp) || !fgets(cmd, sizeof(cmd), fp)) {
fclose(fp);
continue;
}
fclose(fp);
buf[strcspn(buf, "\n")] = '\0';
cmd[strcspn(cmd, "\n")] = '\0';
tstamp = atoi(buf);
cmd_tty = strchr(buf, ' ');
if (tstamp == 0 || cmd_tty == NULL)
continue;
cmd_tty++;
/*
* Select based on tty and/or regex if applicable.
*/
if (tty && strcmp(tty, cmd_tty) == 0)
continue;
if (re) {
#ifdef HAVE_REGCOMP
int rc = regexec(re, cmd, 0, NULL, 0);
if (rc) {
if (rc == REG_NOMATCH)
continue;
regerror(rc, re, buf, sizeof(buf));
errorx(1, "%s", buf);
}
#else
if (strstr(cmd, re) == NULL)
continue;
#endif /* HAVE_REGCOMP */
}
printf("%s: %s\n", dp->d_name, cmd);
}
return(0);
}
int
list_sessions(argc, argv, pattern, tty)
int argc;
char **argv;
const char *pattern;
const char *tty;
{
DIR *sess_d;
struct dirent *dp;
REGEX_T rebuf, *re = NULL;
const char *user = NULL;
sess_d = opendir(session_dir);
if (sess_d == NULL)
error(1, "unable to open %s", session_dir);
/* XXX - ignores optional user and tty for now */
#ifdef HAVE_REGCOMP
/* optional regex */
if (pattern) {
re = &rebuf;
if (regcomp(re, pattern, REG_EXTENDED|REG_NOSUB) != 0)
errorx(1, "invalid regex: %s", pattern);
}
#else
re = (char *) pattern;
#endif /* HAVE_REGCOMP */
/* optional user */
if (argc == 1) {
user = argv[0];
return(list_user_sessions(user, re, tty));
}
while ((dp = readdir(sess_d)) != NULL) {
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
continue;
plen = snprintf(path, sizeof(path), "%s/%s/", session_dir, dp->d_name);
if (plen <= 0 || plen >= sizeof(path)) {
/* XXX - warn */
continue;
}
path[--plen] = '\0'; /* chop off the '/' for now */
user_d = opendir(path);
if (user_d == NULL && errno != ENOTDIR) {
warning("cannot opendir %s", path);
continue;
}
while ((dp = readdir(user_d)) != NULL) {
/* base session (log) file name is 10 characters */
len = NAMLEN(dp);
if (len != 10)
continue;
/* open log file, print id and command */
path[plen] = '/'; /* restore dir separator */
strlcpy(path + plen + 1, dp->d_name, sizeof(path) - plen - 1); /* XXX - check */
fp = fopen(path, "r");
fgets(buf, sizeof(buf), fp); /* XXX - ignore first line */
fgets(buf, sizeof(buf), fp);
printf("%s: %s", dp->d_name, buf);
}
list_user_sessions(dp->d_name, re, tty);
}
closedir(sess_d);
return(0);
@@ -316,7 +410,11 @@ list_sessions(argc, argv)
void
usage()
{
fprintf(stderr, "usage: %s [-d directory] username ID [speed_factor]\n",
fprintf(stderr,
"usage: %s [-d directory] [-s speed_factor] username ID\n",
getprogname());
fprintf(stderr,
"usage: %s [-d directory] [-l] [-p pattern] [-t tty] [username]\n",
getprogname());
exit(1);
}