static int iolog_compress;
static struct timeval last_time;
static union io_fd io_fds[IOFD_MAX];
-extern struct io_plugin sudoers_io;
+extern __dso_public struct io_plugin sudoers_io;
/*
* Create parent directories for path as needed, but not path itself.
* Uses file locking to avoid sequence number collisions.
*/
void
-io_nextid(char *iolog_dir, char sessid[7])
+io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
{
struct stat sb;
char buf[32], *ep;
log_fatal(USE_ERRNO, _("unable to open %s"), pathbuf);
lock_file(fd, SUDO_LOCK);
- /* Read seq number (base 36). */
- nread = read(fd, buf, sizeof(buf));
- if (nread != 0) {
- if (nread == -1)
- log_fatal(USE_ERRNO, _("unable to read %s"), pathbuf);
- id = strtoul(buf, &ep, 36);
- if (buf == ep || id >= SESSID_MAX)
- log_fatal(0, _("invalid sequence number %s"), pathbuf);
+ /*
+ * If there is no seq file in iolog_dir and a fallback dir was
+ * specified, look for seq in the fallback dir. This is to work
+ * around a bug in sudo 1.8.5 and older where iolog_dir was not
+ * expanded before the sequence number was updated.
+ */
+ if (iolog_dir_fallback != NULL && fstat(fd, &sb) == 0 && sb.st_size == 0) {
+ char fallback[PATH_MAX];
+
+ len = snprintf(fallback, sizeof(fallback), "%s/seq",
+ iolog_dir_fallback);
+ if (len > 0 && len < sizeof(fallback)) {
+ int fd2 = open(fallback, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
+ if (fd2 != -1) {
+ nread = read(fd2, buf, sizeof(buf));
+ if (nread > 0) {
+ id = strtoul(buf, &ep, 36);
+ if (buf == ep || id >= SESSID_MAX)
+ id = 0;
+ }
+ close(fd2);
+ }
+ }
+ }
+
+ /* Read current seq number (base 36). */
+ if (id == 0) {
+ nread = read(fd, buf, sizeof(buf));
+ if (nread != 0) {
+ if (nread == -1)
+ log_fatal(USE_ERRNO, _("unable to read %s"), pathbuf);
+ id = strtoul(buf, &ep, 36);
+ if (buf == ep || id >= SESSID_MAX)
+ log_fatal(0, _("invalid sequence number %s"), pathbuf);
+ }
}
id++;
sessid[6] = '\0';
/* Rewind and overwrite old seq file. */
- if (lseek(fd, 0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7)
+ if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7)
log_fatal(USE_ERRNO, _("unable to write to %s"), pathbuf);
close(fd);
/* Get next session ID and convert it into a path. */
tofree = emalloc(sizeof(_PATH_SUDO_IO_LOGDIR) + sizeof(sessid) + 2);
memcpy(tofree, _PATH_SUDO_IO_LOGDIR, sizeof(_PATH_SUDO_IO_LOGDIR));
- io_nextid(tofree, sessid);
+ io_nextid(tofree, NULL, sessid);
snprintf(tofree + sizeof(_PATH_SUDO_IO_LOGDIR), sizeof(sessid) + 2,
"%c%c/%c%c/%c%c", sessid[0], sessid[1], sessid[2], sessid[3],
sessid[4], sessid[5]);
done:
efree(tofree);
if (details.runas_pw)
- pw_delref(details.runas_pw);
+ sudo_pw_delref(details.runas_pw);
sudo_endpwent();
if (details.runas_gr)
- gr_delref(details.runas_gr);
+ sudo_gr_delref(details.runas_gr);
sudo_endgrent();
debug_return_bool(rval);
return sudoers_io_log(buf, len, IOFD_STDERR);
}
-struct io_plugin sudoers_io = {
+__dso_public struct io_plugin sudoers_io = {
SUDO_IO_PLUGIN,
SUDO_API_VERSION,
sudoers_io_open,