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.
{
struct stat sb;
char *slash = path;
+ debug_decl(mkdir_parents, SUDO_DEBUG_UTIL)
for (;;) {
if ((slash = strchr(slash + 1, '/')) == NULL)
*slash = '\0';
if (stat(path, &sb) != 0) {
if (mkdir(path, S_IRWXU) != 0)
- log_error(USE_ERRNO, "Can't mkdir %s", path);
+ log_fatal(USE_ERRNO, _("unable to mkdir %s"), path);
} else if (!S_ISDIR(sb.st_mode)) {
- log_error(0, "%s: %s", path, strerror(ENOTDIR));
+ log_fatal(0, _("%s: %s"), path, strerror(ENOTDIR));
}
*slash = '/';
}
+ debug_return;
}
/*
* 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;
ssize_t nread;
char pathbuf[PATH_MAX];
static const char b36char[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ debug_decl(io_nextid, SUDO_DEBUG_UTIL)
/*
* Create I/O log directory if it doesn't already exist.
mkdir_parents(iolog_dir);
if (stat(iolog_dir, &sb) != 0) {
if (mkdir(iolog_dir, S_IRWXU) != 0)
- log_error(USE_ERRNO, "Can't mkdir %s", iolog_dir);
+ log_fatal(USE_ERRNO, _("unable to mkdir %s"), iolog_dir);
} else if (!S_ISDIR(sb.st_mode)) {
- log_error(0, "%s exists but is not a directory (0%o)",
+ log_fatal(0, _("%s exists but is not a directory (0%o)"),
iolog_dir, (unsigned int) sb.st_mode);
}
len = snprintf(pathbuf, sizeof(pathbuf), "%s/seq", iolog_dir);
if (len <= 0 || len >= sizeof(pathbuf)) {
errno = ENAMETOOLONG;
- log_error(USE_ERRNO, "%s/seq", pathbuf);
+ log_fatal(USE_ERRNO, "%s/seq", pathbuf);
}
fd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
if (fd == -1)
- log_error(USE_ERRNO, "cannot open %s", pathbuf);
+ 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_error(USE_ERRNO, "cannot read %s", pathbuf);
- id = strtoul(buf, &ep, 36);
- if (buf == ep || id >= SESSID_MAX)
- log_error(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++;
}
buf[6] = '\n';
- /* Stash id logging purposes */
+ /* Stash id for logging purposes. */
memcpy(sessid, buf, 6);
sessid[6] = '\0';
/* Rewind and overwrite old seq file. */
- if (lseek(fd, 0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7)
- log_error(USE_ERRNO, "Can't write to %s", pathbuf);
+ 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);
+
+ debug_return;
}
/*
mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize)
{
size_t len;
+ debug_decl(mkdir_iopath, SUDO_DEBUG_UTIL)
len = strlcpy(pathbuf, iolog_path, pathsize);
if (len >= pathsize) {
errno = ENAMETOOLONG;
- log_error(USE_ERRNO, "%s", iolog_path);
+ log_fatal(USE_ERRNO, "%s", iolog_path);
}
/*
mkdir_parents(pathbuf);
if (len >= 6 && strcmp(&pathbuf[len - 6], "XXXXXX") == 0) {
if (mkdtemp(pathbuf) == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf);
} else {
if (mkdir(pathbuf, S_IRWXU) != 0)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf);
}
- return len;
+ debug_return_size_t(len);
}
/*
* Append suffix to pathbuf after len chars and open the resulting file.
* Note that the size of pathbuf is assumed to be PATH_MAX.
- * Uses zlib if docompress is TRUE.
+ * Uses zlib if docompress is true.
* Returns the open file handle which has the close-on-exec flag set.
*/
static void *
-open_io_fd(char *pathbuf, size_t len, const char *suffix, int docompress)
+open_io_fd(char *pathbuf, size_t len, const char *suffix, bool docompress)
{
void *vfd = NULL;
int fd;
+ debug_decl(open_io_fd, SUDO_DEBUG_UTIL)
pathbuf[len] = '\0';
strlcat(pathbuf, suffix, PATH_MAX);
#endif
vfd = fdopen(fd, "w");
}
- return vfd;
+ debug_return_ptr(vfd);
}
/*
unsigned long ulval;
uid_t runas_uid = 0;
gid_t runas_gid = 0;
+ debug_decl(iolog_deserialize_info, SUDO_DEBUG_UTIL)
memset(details, 0, sizeof(*details));
continue;
}
if (strncmp(*cur, "iolog_stdin=", sizeof("iolog_stdin=") - 1) == 0) {
- if (atobool(*cur + sizeof("iolog_stdin=") - 1) == TRUE)
- details->iolog_stdin = TRUE;
+ if (atobool(*cur + sizeof("iolog_stdin=") - 1) == true)
+ details->iolog_stdin = true;
continue;
}
if (strncmp(*cur, "iolog_stdout=", sizeof("iolog_stdout=") - 1) == 0) {
- if (atobool(*cur + sizeof("iolog_stdout=") - 1) == TRUE)
- details->iolog_stdout = TRUE;
+ if (atobool(*cur + sizeof("iolog_stdout=") - 1) == true)
+ details->iolog_stdout = true;
continue;
}
if (strncmp(*cur, "iolog_stderr=", sizeof("iolog_stderr=") - 1) == 0) {
- if (atobool(*cur + sizeof("iolog_stderr=") - 1) == TRUE)
- details->iolog_stderr = TRUE;
+ if (atobool(*cur + sizeof("iolog_stderr=") - 1) == true)
+ details->iolog_stderr = true;
continue;
}
if (strncmp(*cur, "iolog_ttyin=", sizeof("iolog_ttyin=") - 1) == 0) {
- if (atobool(*cur + sizeof("iolog_ttyin=") - 1) == TRUE)
- details->iolog_ttyin = TRUE;
+ if (atobool(*cur + sizeof("iolog_ttyin=") - 1) == true)
+ details->iolog_ttyin = true;
continue;
}
if (strncmp(*cur, "iolog_ttyout=", sizeof("iolog_ttyout=") - 1) == 0) {
- if (atobool(*cur + sizeof("iolog_ttyout=") - 1) == TRUE)
- details->iolog_ttyout = TRUE;
+ if (atobool(*cur + sizeof("iolog_ttyout=") - 1) == true)
+ details->iolog_ttyout = true;
continue;
}
if (strncmp(*cur, "iolog_compress=", sizeof("iolog_compress=") - 1) == 0) {
- if (atobool(*cur + sizeof("iolog_compress=") - 1) == TRUE)
- iolog_compress = TRUE; /* must be global */
+ if (atobool(*cur + sizeof("iolog_compress=") - 1) == true)
+ iolog_compress = true; /* must be global */
continue;
}
break;
details->runas_gr = sudo_fakegrnam(id);
}
}
+ debug_return;
}
static int
sudoers_io_open(unsigned int version, sudo_conv_t conversation,
sudo_printf_t plugin_printf, char * const settings[],
char * const user_info[], char * const command_info[],
- int argc, char * const argv[], char * const user_env[])
+ int argc, char * const argv[], char * const user_env[], char * const args[])
{
struct iolog_details details;
char pathbuf[PATH_MAX], sessid[7];
char *tofree = NULL;
char * const *cur;
+ const char *debug_flags = NULL;
FILE *io_logfile;
size_t len;
int rval = -1;
+ debug_decl(sudoers_io_open, SUDO_DEBUG_PLUGIN)
if (!sudo_conv)
sudo_conv = conversation;
/* If we have no command (because -V was specified) just return. */
if (argc == 0)
- return TRUE;
+ debug_return_bool(true);
if (sigsetjmp(error_jmp, 1)) {
- /* called via error(), errorx() or log_error() */
+ /* called via error(), errorx() or log_fatal() */
rval = -1;
goto done;
}
+ bindtextdomain("sudoers", LOCALEDIR);
+
sudo_setpwent();
sudo_setgrent();
+ /*
+ * Check for debug flags in settings list.
+ */
+ for (cur = settings; *cur != NULL; cur++) {
+ if (strncmp(*cur, "debug_flags=", sizeof("debug_flags=") - 1) == 0)
+ debug_flags = *cur + sizeof("debug_flags=") - 1;
+ }
+ if (debug_flags != NULL)
+ sudo_debug_init(NULL, debug_flags);
+
/*
* Pull iolog settings out of command_info, if any.
*/
if (!details.iolog_stdin && !details.iolog_ttyin &&
!details.iolog_stdout && !details.iolog_stderr &&
!details.iolog_ttyout) {
- rval = FALSE;
+ rval = false;
goto done;
}
/* 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]);
/*
* We create 7 files: a log file, a timing file and 5 for input/output.
*/
- io_logfile = open_io_fd(pathbuf, len, "/log", FALSE);
+ io_logfile = open_io_fd(pathbuf, len, "/log", false);
if (io_logfile == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf);
io_fds[IOFD_TIMING].v = open_io_fd(pathbuf, len, "/timing",
iolog_compress);
if (io_fds[IOFD_TIMING].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf);
if (details.iolog_ttyin) {
io_fds[IOFD_TTYIN].v = open_io_fd(pathbuf, len, "/ttyin",
iolog_compress);
if (io_fds[IOFD_TTYIN].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf);
} else {
sudoers_io.log_ttyin = NULL;
}
io_fds[IOFD_STDIN].v = open_io_fd(pathbuf, len, "/stdin",
iolog_compress);
if (io_fds[IOFD_STDIN].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf);
} else {
sudoers_io.log_stdin = NULL;
}
io_fds[IOFD_TTYOUT].v = open_io_fd(pathbuf, len, "/ttyout",
iolog_compress);
if (io_fds[IOFD_TTYOUT].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf);
} else {
sudoers_io.log_ttyout = NULL;
}
io_fds[IOFD_STDOUT].v = open_io_fd(pathbuf, len, "/stdout",
iolog_compress);
if (io_fds[IOFD_STDOUT].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf);
} else {
sudoers_io.log_stdout = NULL;
}
io_fds[IOFD_STDERR].v = open_io_fd(pathbuf, len, "/stderr",
iolog_compress);
if (io_fds[IOFD_STDERR].v == NULL)
- log_error(USE_ERRNO, "Can't create %s", pathbuf);
+ log_fatal(USE_ERRNO, _("unable to create %s"), pathbuf);
} else {
sudoers_io.log_stderr = NULL;
}
fputc('\n', io_logfile);
fputs(details.command ? details.command : "unknown", io_logfile);
for (cur = &argv[1]; *cur != NULL; cur++) {
- if (cur != &argv[1])
- fputc(' ', io_logfile);
+ fputc(' ', io_logfile);
fputs(*cur, io_logfile);
}
fputc('\n', io_logfile);
fclose(io_logfile);
- rval = TRUE;
+ rval = true;
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();
- return rval;
+ debug_return_bool(rval);
}
static void
sudoers_io_close(int exit_status, int error)
{
int i;
+ debug_decl(sudoers_io_close, SUDO_DEBUG_PLUGIN)
if (sigsetjmp(error_jmp, 1)) {
- /* called via error(), errorx() or log_error() */
- return;
+ /* called via error(), errorx() or log_fatal() */
+ debug_return;
}
for (i = 0; i < IOFD_MAX; i++) {
#endif
fclose(io_fds[i].f);
}
+ debug_return;
}
static int
sudoers_io_version(int verbose)
{
+ debug_decl(sudoers_io_version, SUDO_DEBUG_PLUGIN)
+
if (sigsetjmp(error_jmp, 1)) {
- /* called via error(), errorx() or log_error() */
- return -1;
+ /* called via error(), errorx() or log_fatal() */
+ debug_return_bool(-1);
}
sudo_printf(SUDO_CONV_INFO_MSG, "Sudoers I/O plugin version %s\n",
PACKAGE_VERSION);
- return TRUE;
+ debug_return_bool(true);
}
/*
sudoers_io_log(const char *buf, unsigned int len, int idx)
{
struct timeval now, delay;
+ debug_decl(sudoers_io_version, SUDO_DEBUG_PLUGIN)
gettimeofday(&now, NULL);
if (sigsetjmp(error_jmp, 1)) {
- /* called via error(), errorx() or log_error() */
- return -1;
+ /* called via error(), errorx() or log_fatal() */
+ debug_return_bool(-1);
}
#ifdef HAVE_ZLIB_H
if (iolog_compress)
- gzwrite(io_fds[idx].g, buf, len);
+ ignore_result(gzwrite(io_fds[idx].g, (const voidp)buf, len));
else
#endif
- fwrite(buf, 1, len, io_fds[idx].f);
+ ignore_result(fwrite(buf, 1, len, io_fds[idx].f));
delay.tv_sec = now.tv_sec;
delay.tv_usec = now.tv_usec;
timevalsub(&delay, &last_time);
last_time.tv_sec = now.tv_sec;
last_time.tv_usec = now.tv_usec;
- return TRUE;
+ debug_return_bool(true);
}
static int
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,