diff --git a/script.c b/script.c index b7ba121db..0ec626fcf 100644 --- a/script.c +++ b/script.c @@ -106,26 +106,24 @@ fdcompar(v1, v2) return(*(int *)v1 - *(int *)v2); } -static int -next_seq(pathbuf) - char *pathbuf; +void +script_nextid() { - struct stat sb; - char buf[32], *cp, *ep; + char buf[32], *ep; int fd, i, ch; unsigned long id = 0; - size_t len; + int len; ssize_t nread; + char pathbuf[PATH_MAX]; /* * Open sequence file */ - len = strlen(pathbuf); - if (len + sizeof("/00/00/00") > PATH_MAX) { + len = snprintf(pathbuf, sizeof(pathbuf), "%s/seq", _PATH_SUDO_SESSDIR); + if (len <= 0 || len >= sizeof(pathbuf)) { errno = ENAMETOOLONG; log_error(USE_ERRNO, "%s/seq", pathbuf); } - strlcat(pathbuf, "/seq", PATH_MAX); fd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); if (fd == -1) log_error(USE_ERRNO, "cannot open %s", pathbuf); @@ -143,24 +141,17 @@ next_seq(pathbuf) id++; /* - * Convert id to a string (buf) and also append to pathbuf. + * Convert id to a string and stash in sudo_user.sessid. * Note that that least significant digits go at the end of the string. */ - len += sizeof("/00/00/00") - 1; for (i = 5; i >= 0; i--) { ch = id % 36; id /= 36; buf[i] = ch < 10 ? ch + '0' : ch - 10 + 'A'; - - /* Append to pathbuf, separating every two digits with a /. */ - if (i & 1) - pathbuf[len--] = '/'; - pathbuf[len--] = buf[i]; } buf[6] = '\n'; - len += sizeof("/00/00/00") - 1; - /* For logging purposes */ + /* Stash id logging purposes */ memcpy(sudo_user.sessid, buf, 6); sudo_user.sessid[6] = '\0'; @@ -168,9 +159,27 @@ next_seq(pathbuf) if (lseek(fd, 0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7) log_error(USE_ERRNO, "Can't write to %s", pathbuf); close(fd); +} + +static int +build_idpath(pathbuf) + char *pathbuf; +{ + struct stat sb; + int i, len; + + /* + * Path is of the form /var/log/sudo-session/00/00/01. + */ + len = snprintf(pathbuf, PATH_MAX, "%s/%c%c/%c%c/%c%c", _PATH_SUDO_SESSDIR, + 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 >= PATH_MAX) { + errno = ENAMETOOLONG; + log_error(USE_ERRNO, "%s/%s", _PATH_SUDO_SESSDIR, sudo_user.sessid); + } /* - * Path is of the form /var/log/sudo-session/00/00/00 * Create the intermediate subdirs as needed. */ for (i = 6; i > 0; i -= 3) { @@ -183,7 +192,6 @@ next_seq(pathbuf) } pathbuf[len - i] = '/'; } - pathbuf[len] = '\0'; return(len); } @@ -222,12 +230,10 @@ script_setup() } /* - * Get the next ID from the sequence file and append it to pathbuf. - * The log files are split into two-digit subdirs, so ID 000001 - * becomes /var/log/sudo-session/00/00/01. + * Build a path containing the session id split into two-digit subdirs, + * so ID 000001 becomes /var/log/sudo-session/00/00/01. */ - strlcpy(pathbuf, _PATH_SUDO_SESSDIR, sizeof(pathbuf)); - len = next_seq(pathbuf); + len = build_idpath(pathbuf); /* * We create 3 files: a log file, one for the raw session data, @@ -298,6 +304,7 @@ script_execv(path, argv) runas_pw->pw_name, runas_gr ? runas_gr->gr_name : "", user_tty); fprintf(idfile, "%s%s%s\n", user_cmnd, user_args ? " " : "", user_args ? user_args : ""); + fclose(idfile); n = fcntl(script_fds[SFD_MASTER], F_GETFL, 0); if (n != -1) { diff --git a/sudo.c b/sudo.c index bcaab7d71..e6e20dea5 100644 --- a/sudo.c +++ b/sudo.c @@ -461,9 +461,9 @@ main(argc, argv, envp) validate_env_vars(sudo_user.env_vars); } - /* Open tty and session ID as needed */ + /* Get next session ID so we can log it. */ if (def_script) - script_setup(); + script_nextid(); log_allowed(validated); if (ISSET(sudo_mode, MODE_CHECK)) @@ -503,6 +503,10 @@ main(argc, argv, envp) /* Must audit before uid change. */ audit_success(NewArgv); + /* Open tty as needed */ + if (def_script) + script_setup(); + /* Become specified user or root if executing a command. */ if (ISSET(sudo_mode, MODE_RUN)) set_perms(PERM_FULL_RUNAS); diff --git a/sudo.h b/sudo.h index ecfe82f12..34b9e663d 100644 --- a/sudo.h +++ b/sudo.h @@ -326,6 +326,7 @@ void selinux_exec __P((char *, char *, char **, int)); void aix_setlimits __P((char *)); #endif int script_execv __P((const char *, char * const *)); +void script_nextid __P((void)); void script_setup __P((void)); int term_cbreak __P((int)); int term_copy __P((int, int));