isalnum((unsigned char)(s)[3]) && isalnum((unsigned char)(s)[4]) && \
isalnum((unsigned char)(s)[5]) && (s)[6] == '\0')
+#define IS_IDLOG(s) ( \
+ isalnum((unsigned char)(s)[0]) && isalnum((unsigned char)(s)[1]) && \
+ (s)[2] == '/' && \
+ isalnum((unsigned char)(s)[3]) && isalnum((unsigned char)(s)[4]) && \
+ (s)[5] == '/' && \
+ isalnum((unsigned char)(s)[6]) && isalnum((unsigned char)(s)[7]) && \
+ (s)[8] == '/' && (s)[9] == 'l' && (s)[10] == 'o' && (s)[11] == 'g' && \
+ (s)[9] == '\0')
+
int
main(argc, argv)
int argc;
if (argc != 1)
usage(1);
- /* 6 digit ID in base 36, e.g. 01G712AB */
+ /* 6 digit ID in base 36, e.g. 01G712AB or free-form name */
id = argv[0];
- if (!VALID_ID(id))
- errorx(1, "invalid ID %s", id);
-
- plen = snprintf(path, sizeof(path), "%s/%.2s/%.2s/%.2s/timing",
- session_dir, id, &id[2], &id[4]);
- if (plen <= 0 || plen >= sizeof(path))
- errorx(1, "%s/%.2s/%.2s/%.2s/timing: %s", session_dir,
- id, &id[2], &id[4], strerror(ENAMETOOLONG));
+ if (VALID_ID(id)) {
+ plen = snprintf(path, sizeof(path), "%s/%.2s/%.2s/%.2s/timing",
+ session_dir, id, &id[2], &id[4]);
+ if (plen <= 0 || plen >= sizeof(path))
+ errorx(1, "%s/%.2s/%.2s/%.2s/timing: %s", session_dir,
+ id, &id[2], &id[4], strerror(ENAMETOOLONG));
+ } else {
+ plen = snprintf(path, sizeof(path), "%s/%s/timing",
+ session_dir, id);
+ if (plen <= 0 || plen >= sizeof(path))
+ errorx(1, "%s/%s/timing: %s", session_dir,
+ id, strerror(ENAMETOOLONG));
+ }
plen -= 7;
/* Open files for replay, applying replay filter for the -f flag. */
}
static int
-list_session_dir(pathbuf, re, user, tty)
- char *pathbuf;
+list_session(logfile, re, user, tty)
+ char *logfile;
REGEX_T *re;
const char *user;
const char *tty;
{
FILE *fp;
- DIR *d;
- struct dirent *dp;
- char *buf = NULL, *cmd = NULL, *cwd = NULL, idstr[7], *cp;
+ char *buf = NULL, *cmd = NULL, *cwd = NULL, idbuf[7], *idstr, *cp;
struct log_info li;
- size_t bufsize = 0, cwdsize = 0, cmdsize = 0, plen;
+ size_t bufsize = 0, cwdsize = 0, cmdsize = 0;
+ int rval = -1;
- plen = strlen(pathbuf);
- d = opendir(pathbuf);
- if (d == NULL && errno != ENOTDIR) {
- warning("cannot opendir %s", pathbuf);
- return -1;
+ fp = fopen(logfile, "r");
+ if (fp == NULL) {
+ warning("unable to open %s", logfile);
+ goto done;
}
- while ((dp = readdir(d)) != NULL) {
- if (NAMLEN(dp) != 2 || !isalnum((unsigned char)dp->d_name[0]) ||
- !isalnum((unsigned char)dp->d_name[1]))
- continue;
- /* open log file, print id and command */
- pathbuf[plen + 0] = '/';
- pathbuf[plen + 1] = dp->d_name[0];
- pathbuf[plen + 2] = dp->d_name[1];
- pathbuf[plen + 3] = '/';
- pathbuf[plen + 4] = 'l';
- pathbuf[plen + 5] = 'o';
- pathbuf[plen + 6] = 'g';
- pathbuf[plen + 7] = '\0';
- fp = fopen(pathbuf, "r");
- if (fp == NULL) {
- warning("unable to open %s", pathbuf);
- continue;
- }
+ /*
+ * ID file has three lines:
+ * 1) a log info line
+ * 2) cwd
+ * 3) command with args
+ */
+ if (getline(&buf, &bufsize, fp) == -1 ||
+ getline(&cwd, &cwdsize, fp) == -1 ||
+ getline(&cmd, &cmdsize, fp) == -1) {
+ goto done;
+ }
- /*
- * ID file has three lines:
- * 1) a log info line
- * 2) cwd
- * 3) command with args
- */
- if (getline(&buf, &bufsize, fp) == -1 ||
- getline(&cwd, &cwdsize, fp) == -1 ||
- getline(&cmd, &cmdsize, fp) == -1) {
- fclose(fp);
- continue;
- }
- fclose(fp);
+ /* crack the log line: timestamp:user:runas_user:runas_group:tty */
+ buf[strcspn(buf, "\n")] = '\0';
+ if ((li.tstamp = atoi(buf)) == 0)
+ goto done;
+
+ if ((cp = strchr(buf, ':')) == NULL)
+ goto done;
+ *cp++ = '\0';
+ li.user = cp;
+
+ if ((cp = strchr(cp, ':')) == NULL)
+ goto done;
+ *cp++ = '\0';
+ li.runas_user = cp;
+
+ if ((cp = strchr(cp, ':')) == NULL)
+ goto done;
+ *cp++ = '\0';
+ li.runas_group = cp;
+
+ if ((cp = strchr(cp, ':')) == NULL)
+ goto done;
+ *cp++ = '\0';
+ li.tty = cp;
+
+ cwd[strcspn(cwd, "\n")] = '\0';
+ li.cwd = cwd;
+
+ cmd[strcspn(cmd, "\n")] = '\0';
+ li.cmd = cmd;
+
+ /* Match on search expression if there is one. */
+ if (search_expr && !match_expr(search_expr, &li))
+ goto done;
+
+ /* Convert from /var/log/sudo-sessions/00/00/01/log to 000001 */
+ cp = logfile + strlen(session_dir) + 1;
+ if (IS_IDLOG(cp)) {
+ idbuf[0] = cp[7];
+ idbuf[1] = cp[6];
+ idbuf[2] = cp[4];
+ idbuf[3] = cp[3];
+ idbuf[4] = cp[1];
+ idbuf[5] = cp[0];
+ idbuf[6] = '\0';
+ idstr = idbuf;
+ } else {
+ /* Not an id, just use the iolog_file portion. */
+ cp[strlen(cp) - 4] = '\0';
+ idstr = cp;
+ }
+ printf("%s : %s : TTY=%s ; CWD=%s ; USER=%s ; ",
+ get_timestr(li.tstamp, 1), li.user, li.tty, li.cwd, li.runas_user);
+ if (*li.runas_group)
+ printf("GROUP=%s ; ", li.runas_group);
+ printf("TSID=%s ; COMMAND=%s\n", idstr, li.cmd);
- /* crack the log line: timestamp:user:runas_user:runas_group:tty */
- buf[strcspn(buf, "\n")] = '\0';
- if ((li.tstamp = atoi(buf)) == 0)
- continue;
+ rval = 0;
- if ((cp = strchr(buf, ':')) == NULL)
- continue;
- *cp++ = '\0';
- li.user = cp;
+done:
+ fclose(fp);
+ return rval;
+}
- if ((cp = strchr(cp, ':')) == NULL)
- continue;
- *cp++ = '\0';
- li.runas_user = cp;
+static int
+find_sessions(dir, re, user, tty)
+ const char *dir;
+ REGEX_T *re;
+ const char *user;
+ const char *tty;
+{
+ DIR *d;
+ struct dirent *dp;
+ struct stat sb;
+ size_t sdlen;
+ int len;
+ char pathbuf[PATH_MAX];
- if ((cp = strchr(cp, ':')) == NULL)
- continue;
- *cp++ = '\0';
- li.runas_group = cp;
+ d = opendir(dir);
+ if (d == NULL)
+ error(1, "unable to open %s", dir);
- if ((cp = strchr(cp, ':')) == NULL)
+ /* XXX - would be faster to chdir and use relative names */
+ sdlen = strlcpy(pathbuf, dir, sizeof(pathbuf));
+ if (sdlen + 1 >= sizeof(pathbuf)) {
+ errno = ENAMETOOLONG;
+ error(1, "%s/", dir);
+ }
+ pathbuf[sdlen++] = '/';
+ pathbuf[sdlen] = '\0';
+ while ((dp = readdir(d)) != NULL) {
+ /* Skip "." and ".." */
+ if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
continue;
- *cp++ = '\0';
- li.tty = cp;
- cwd[strcspn(cwd, "\n")] = '\0';
- li.cwd = cwd;
-
- cmd[strcspn(cmd, "\n")] = '\0';
- li.cmd = cmd;
-
- /* Match on search expression if there is one. */
- if (search_expr && !match_expr(search_expr, &li))
- continue;
+ len = snprintf(&pathbuf[sdlen], sizeof(pathbuf) - sdlen,
+ "%s/log", dp->d_name);
+ if (len <= 0 || len >= sizeof(pathbuf) - sdlen) {
+ errno = ENAMETOOLONG;
+ error(1, "%s/%s/log", dir, dp->d_name);
+ }
- /* Convert from /var/log/sudo-sessions/00/00/01 to 000001 */
- idstr[0] = pathbuf[plen - 5];
- idstr[1] = pathbuf[plen - 4];
- idstr[2] = pathbuf[plen - 2];
- idstr[3] = pathbuf[plen - 1];
- idstr[4] = pathbuf[plen + 1];
- idstr[5] = pathbuf[plen + 2];
- idstr[6] = '\0';
- printf("%s : %s : TTY=%s ; CWD=%s ; USER=%s ; ",
- get_timestr(li.tstamp, 1), li.user, li.tty, li.cwd, li.runas_user);
- if (*li.runas_group)
- printf("GROUP=%s ; ", li.runas_group);
- printf("TSID=%s ; COMMAND=%s\n", idstr, li.cmd);
+ /* Check for dir with a log file. */
+ if (lstat(pathbuf, &sb) == 0 && S_ISREG(sb.st_mode)) {
+ list_session(pathbuf, re, user, tty);
+ } else {
+ /* Strip off "/log" and recurse if a dir. */
+ pathbuf[sdlen + len - 4] = '\0';
+ if (lstat(pathbuf, &sb) == 0 && S_ISDIR(sb.st_mode))
+ find_sessions(pathbuf, re, user, tty);
+ }
}
+ closedir(d);
+
return 0;
}
const char *user;
const char *tty;
{
- DIR *d1, *d2;
- struct dirent *dp1, *dp2;
REGEX_T rebuf, *re = NULL;
- size_t sdlen;
- char pathbuf[PATH_MAX];
/* Parse search expression if present */
parse_expr(&search_expr, argv);
- d1 = opendir(session_dir);
- if (d1 == NULL)
- error(1, "unable to open %s", session_dir);
-
#ifdef HAVE_REGCOMP
/* optional regex */
if (pattern) {
re = (char *) pattern;
#endif /* HAVE_REGCOMP */
- sdlen = strlcpy(pathbuf, session_dir, sizeof(pathbuf));
- if (sdlen + sizeof("/00/00/00/log") >= sizeof(pathbuf)) {
- errno = ENAMETOOLONG;
- error(1, "%s/00/00/00/log", session_dir);
- }
-
- /*
- * Three levels of directory, e.g. 00/00/00 .. ZZ/ZZ/ZZ
- * We do a depth-first traversal.
- */
- while ((dp1 = readdir(d1)) != NULL) {
- if (NAMLEN(dp1) != 2 || !isalnum((unsigned char)dp1->d_name[0]) ||
- !isalnum((unsigned char)dp1->d_name[1]))
- continue;
-
- pathbuf[sdlen + 0] = '/';
- pathbuf[sdlen + 1] = dp1->d_name[0];
- pathbuf[sdlen + 2] = dp1->d_name[1];
- pathbuf[sdlen + 3] = '\0';
- d2 = opendir(pathbuf);
- if (d2 == NULL)
- continue;
-
- while ((dp2 = readdir(d2)) != NULL) {
- if (NAMLEN(dp2) != 2 || !isalnum((unsigned char)dp2->d_name[0]) ||
- !isalnum((unsigned char)dp2->d_name[1]))
- continue;
-
- pathbuf[sdlen + 3] = '/';
- pathbuf[sdlen + 4] = dp2->d_name[0];
- pathbuf[sdlen + 5] = dp2->d_name[1];
- pathbuf[sdlen + 6] = '\0';
- list_session_dir(pathbuf, re, user, tty);
- }
- closedir(d2);
- }
- closedir(d1);
- return 0;
+ return find_sessions(session_dir, re, user, tty);
}
/*