diff --git a/plugins/sample/sample_plugin.c b/plugins/sample/sample_plugin.c index a7f13a50f..c337637d4 100644 --- a/plugins/sample/sample_plugin.c +++ b/plugins/sample/sample_plugin.c @@ -423,8 +423,8 @@ policy_close(int exit_status, int error) static int io_open(unsigned int version, sudo_conv_t conversation, sudo_printf_t sudo_printf, char * const settings[], - char * const user_info[], int argc, char * const argv[], - char * const user_env[]) + char * const user_info[], char * const command_info[], + int argc, char * const argv[], char * const user_env[]) { int fd; char path[PATH_MAX]; diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c index 3c9a98e07..955e88087 100644 --- a/plugins/sudoers/iolog.c +++ b/plugins/sudoers/iolog.c @@ -148,37 +148,71 @@ io_nextid(void) } static int -build_idpath(char *pathbuf, size_t pathsize) +build_idpath(const char *iolog_dir, const char *sessid, char *pathbuf, size_t pathsize) { struct stat sb; + char *cp; int i, len; - if (sudo_user.sessid[0] == '\0') + if (sessid[0] == '\0') log_error(0, "tried to build a session id path without a session id"); - /* - * Path is of the form /var/log/sudo-io/00/00/01. - */ - len = snprintf(pathbuf, pathsize, "%s/%c%c/%c%c/%c%c", def_iolog_dir, - sudo_user.sessid[0], sudo_user.sessid[1], sudo_user.sessid[2], - sudo_user.sessid[3], sudo_user.sessid[4], sudo_user.sessid[5]); - if (len <= 0 && len >= pathsize) { - errno = ENAMETOOLONG; - log_error(USE_ERRNO, "%s/%s", def_iolog_dir, sudo_user.sessid); - } - - /* - * Create the intermediate subdirs as needed. - */ - for (i = 6; i > 0; i -= 3) { - pathbuf[len - i] = '\0'; - if (stat(pathbuf, &sb) != 0) { - if (mkdir(pathbuf, S_IRWXU) != 0) - log_error(USE_ERRNO, "Can't mkdir %s", pathbuf); - } else if (!S_ISDIR(sb.st_mode)) { - log_error(0, "%s: %s", pathbuf, strerror(ENOTDIR)); + /* Check whether or not we have a real session ID. */ + for (i = 0; i < 6; i++) { + switch (sessid[i]) { + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': case 'A': case 'B': + case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': + case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': + case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + break; + default: + goto checked; } - pathbuf[len - i] = '/'; + } +checked: + if (i == 6 && sessid[6] == '\0') { + /* Path is of the form /var/log/sudo-io/00/00/01. */ + len = snprintf(pathbuf, pathsize, "%s/%c%c/%c%c/%c%c", iolog_dir, + sessid[0], sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]); + if (len <= 0 && len >= pathsize) { + errno = ENAMETOOLONG; + log_error(USE_ERRNO, "%s/%s", iolog_dir, sessid); + } + + /* Create the intermediate subdirs as needed. */ + for (i = 6; i > 0; i -= 3) { + pathbuf[len - i] = '\0'; + if (stat(pathbuf, &sb) != 0) { + if (mkdir(pathbuf, S_IRWXU) != 0) + log_error(USE_ERRNO, "Can't mkdir %s", pathbuf); + } else if (!S_ISDIR(sb.st_mode)) { + log_error(0, "%s: %s", pathbuf, strerror(ENOTDIR)); + } + pathbuf[len - i] = '/'; + } + } else { + /* Not a session ID, just append dir + file. */ + len = snprintf(pathbuf, pathsize, "%s/%s", iolog_dir, sessid); + if (len <= 0 && len >= pathsize) { + errno = ENAMETOOLONG; + log_error(USE_ERRNO, "%s/%s", iolog_dir, sessid); + } + + /* Create the intermediate subdirs as needed. */ + cp = &pathbuf[strlen(iolog_dir)]; + do { + *cp = '\0'; + if (stat(pathbuf, &sb) != 0) { + if (mkdir(pathbuf, S_IRWXU) != 0) + log_error(USE_ERRNO, "Can't mkdir %s", pathbuf); + } else if (!S_ISDIR(sb.st_mode)) { + log_error(0, "%s: %s", pathbuf, strerror(ENOTDIR)); + } + *cp++ = '/'; + cp = strchr(cp, '/'); + } while (cp != NULL); } return(len); @@ -208,10 +242,12 @@ open_io_fd(char *pathbuf, int len, const char *suffix, int docompress) static int sudoers_io_open(unsigned int version, sudo_conv_t conversation, sudo_printf_t plugin_printf, char * const settings[], - char * const user_info[], int argc, char * const argv[], - char * const user_env[]) + char * const user_info[], char * const command_info[], + int argc, char * const argv[], char * const user_env[]) { char pathbuf[PATH_MAX]; + const char *iolog_dir, *iolog_file = NULL; + char * const *cur; FILE *io_logfile; int len; @@ -224,14 +260,30 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation, if (argc == 0) return TRUE; - if (!def_log_input && !def_log_output && !def_use_pty) + /* + * Pull iolog_dir and iolog_file out of command_info, if present, + * falling back to policy module info if not. + */ + iolog_dir = def_iolog_dir; + for (cur = command_info; *cur != NULL; cur++) { + if (**cur != 'i') + continue; + if (strncmp(*cur, "iolog_file=", sizeof("iolog_file=") - 1) == 0) { + iolog_file = *cur + sizeof("iolog_file=") - 1; + } else if (strncmp(*cur, "iolog_dir=", sizeof("iolog_dir=") - 1) == 0) { + iolog_dir = *cur + sizeof("iolog_dir=") - 1; + } + } + + /* If no I/O log file defined there is nothing to do. */ + if (iolog_file == NULL) return FALSE; /* * Build a path containing the session id split into two-digit subdirs, * so ID 000001 becomes /var/log/sudo-io/00/00/01. */ - len = build_idpath(pathbuf, sizeof(pathbuf)); + len = build_idpath(iolog_dir, iolog_file, pathbuf, sizeof(pathbuf)); if (len == -1) return -1; diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 0156d893d..bdc32296a 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -499,8 +499,12 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], validate_env_vars(sudo_user.env_vars); } - if (ISSET(sudo_mode, (MODE_RUN| MODE_EDIT)) && (def_log_input || def_log_output)) + if (ISSET(sudo_mode, (MODE_RUN| MODE_EDIT)) && (def_log_input || def_log_output)) { io_nextid(); + command_info[info_len++] = fmt_string("iolog_dir", def_iolog_dir); + command_info[info_len++] = fmt_string("iolog_file", sudo_user.sessid); + } + log_allowed(validated); if (ISSET(sudo_mode, MODE_CHECK)) rval = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);