From: Todd C. Miller Date: Thu, 22 Oct 2009 23:50:16 +0000 (+0000) Subject: First pass at zlib support for transcript data files X-Git-Tag: SUDO_1_7_3~209 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=602a62c01e6fca20c24a555c05c5e7a431783be9;p=sudo First pass at zlib support for transcript data files --- diff --git a/INSTALL b/INSTALL index 38e0e981c..6cfd6e12b 100644 --- a/INSTALL +++ b/INSTALL @@ -601,6 +601,17 @@ The following options are also configurable at runtime: /usr/log/sudo-transcript. If DIR is specified, transcripts will be stored in the indicated directory instead. + --disable-zlib + Disable the use of the zlib compress library when storing + transcript files. + + --enable-zlib[=DIR] + Enable the use of the zlib compress library when storing + transcript files. If specified, DIR is the base directory + containing the zlib include and lib directories. By default + zlib is used if it is found on the system and transcript + support is not disabled. + Shadow password and C2 support ============================== diff --git a/configure b/configure index d5f2a1a6c..16f7221d7 100755 --- a/configure +++ b/configure @@ -839,6 +839,7 @@ LDAP REPLAY LOGINCAP_USAGE NONUNIX_GROUPS_IMPL +ZLIB timedir timeout password_timeout @@ -1513,6 +1514,7 @@ Optional Features: --disable-libtool-lock avoid locking (might break parallel builds) --disable-sia Disable SIA on Digital UNIX --disable-pam-session Disable PAM session support + --enable-zlib=PATH Whether to enable or disable zlib Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -2124,6 +2126,7 @@ echo "$as_me: Configuring Sudo version $PACKAGE_VERSION" >&6;} + timeout=5 @@ -2166,6 +2169,7 @@ REPLAY="#" BAMAN='.\" ' LCMAN='.\" ' SEMAN='.\" ' +ZLIB= AUTH_OBJS= AUTH_REG= AUTH_EXCL= @@ -6467,7 +6471,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 6470 "configure"' > conftest.$ac_ext + echo '#line 6474 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -8331,11 +8335,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8334: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8338: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8338: \$? = $ac_status" >&5 + echo "$as_me:8342: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -8621,11 +8625,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8624: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8628: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8628: \$? = $ac_status" >&5 + echo "$as_me:8632: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -8725,11 +8729,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8728: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8732: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8732: \$? = $ac_status" >&5 + echo "$as_me:8736: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -11085,7 +11089,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <>confdefs.h <<\_ACEOF +#define HAVE_ZLIB 1 +_ACEOF + + ZLIB="-lz" + ;; + no) ;; + *) cat >>confdefs.h <<\_ACEOF +#define HAVE_ZLIB 1 +_ACEOF + + CPPFLAGS="${CPPFLAGS} -I${enableval}/include" + + if test X"$with_rpath" = X"yes"; then + ZLIB="${ZLIB} -L$enableval/lib -R$enableval/lib" + else + ZLIB="${ZLIB} -L$enableval/lib" + fi + if test X"$blibpath" != X"" -a "ZLIB" = "SUDO_LDFLAGS"; then + blibpath_add="${blibpath_add}:$enableval/lib" + fi + + ZLIB="${ZLIB} -lz" + ;; + esac + +fi + + if test X"$enable_zlib" = X""; then + { echo "$as_me:$LINENO: checking for gzdopen in -lz" >&5 +echo $ECHO_N "checking for gzdopen in -lz... $ECHO_C" >&6; } +if test "${ac_cv_lib_z_gzdopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gzdopen (); +int +main () +{ +return gzdopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_z_gzdopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_z_gzdopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_z_gzdopen" >&5 +echo "${ECHO_T}$ac_cv_lib_z_gzdopen" >&6; } +if test $ac_cv_lib_z_gzdopen = yes; then + + cat >>confdefs.h <<\_ACEOF +#define HAVE_ZLIB 1 +_ACEOF + + ZLIB="-lz" + +fi + + fi + else { echo "$as_me:$LINENO: WARNING: Disabling transcript support due to lack of tcsetpgrp function" >&5 @@ -26582,6 +26691,7 @@ LDAP!$LDAP$ac_delim REPLAY!$REPLAY$ac_delim LOGINCAP_USAGE!$LOGINCAP_USAGE$ac_delim NONUNIX_GROUPS_IMPL!$NONUNIX_GROUPS_IMPL$ac_delim +ZLIB!$ZLIB$ac_delim timedir!$timedir$ac_delim timeout!$timeout$ac_delim password_timeout!$password_timeout$ac_delim @@ -26603,7 +26713,6 @@ badpass_message!$badpass_message$ac_delim fqdn!$fqdn$ac_delim runas_default!$runas_default$ac_delim env_editor!$env_editor$ac_delim -passwd_tries!$passwd_tries$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -26645,6 +26754,7 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +passwd_tries!$passwd_tries$ac_delim tty_tickets!$tty_tickets$ac_delim insults!$insults$ac_delim root_sudo!$root_sudo$ac_delim @@ -26689,7 +26799,7 @@ KRB5CONFIG!$KRB5CONFIG$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 42; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 43; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 @@ -27314,6 +27424,8 @@ fi + + diff --git a/configure.in b/configure.in index e36805c12..d085e37c8 100644 --- a/configure.in +++ b/configure.in @@ -52,6 +52,7 @@ AC_SUBST(LDAP) AC_SUBST(REPLAY) AC_SUBST(LOGINCAP_USAGE) AC_SUBST(NONUNIX_GROUPS_IMPL) +AC_SUBST(ZLIB) dnl dnl Variables that get substituted in docs (not overridden by environment) dnl @@ -133,6 +134,7 @@ REPLAY="#" BAMAN='.\" ' LCMAN='.\" ' SEMAN='.\" ' +ZLIB= AUTH_OBJS= AUTH_REG= AUTH_EXCL= @@ -2604,6 +2606,27 @@ if test "${enable_transcript-yes}" != "no"; then SUDO_OBJS="${SUDO_OBJS} pty.o script.o" PROGS="$PROGS sudoreplay" REPLAY="" + + AC_ARG_ENABLE(zlib, + [AS_HELP_STRING([--enable-zlib[[=PATH]]], [Whether to enable or disable zlib])], + [ case "$enableval" in + yes) AC_DEFINE(HAVE_ZLIB) + ZLIB="-lz" + ;; + no) ;; + *) AC_DEFINE(HAVE_ZLIB) + CPPFLAGS="${CPPFLAGS} -I${enableval}/include" + SUDO_APPEND_LIBPATH(ZLIB, [$enableval/lib]) + ZLIB="${ZLIB} -lz" + ;; + esac + ]) + if test X"$enable_zlib" = X""; then + AC_CHECK_LIB(z, gzdopen, [ + AC_DEFINE(HAVE_ZLIB) + ZLIB="-lz" + ]) + fi ], [ AC_MSG_WARN([Disabling transcript support due to lack of tcsetpgrp function]) enable_transcript=no @@ -2772,6 +2795,7 @@ AH_TEMPLATE(WITHOUT_PASSWD, [Define to avoid using the passwd/shadow file for au AH_TEMPLATE(sig_atomic_t, [Define to `int' if does not define.]) AH_TEMPLATE(__signed, [Define to `signed' or nothing if compiler does not support a signed type qualifier.]) AH_TEMPLATE(USING_NONUNIX_GROUPS, [Define to 1 if using a non-Unix group lookup implementation.]) +AH_TEMPLATE(HAVE_ZLIB, [Define to 1 if you the `zlib' library.]) dnl dnl Bits to copy verbatim into config.h.in diff --git a/script.c b/script.c index 0f57ece5b..017172375 100644 --- a/script.c +++ b/script.c @@ -67,6 +67,9 @@ #ifdef HAVE_SELINUX # include #endif +#ifdef HAVE_ZLIB +# include +#endif #include "sudo.h" @@ -104,7 +107,7 @@ static void sigchild __P((int s)); static void sigtstp __P((int s)); static void sigwinch __P((int s)); static void flush_output __P((struct script_buf *output, struct timeval *then, - struct timeval *now, FILE *ofile, FILE *tfile)); + struct timeval *now, void *ofile, void *tfile)); extern int get_pty __P((int *master, int *slave, char *name, size_t namesz)); @@ -315,15 +318,29 @@ log_output(buf, n, then, now, ofile, tfile) int n; struct timeval *then; struct timeval *now; +#ifdef HAVE_ZLIB + gzFile ofile; + gzFile tfile; +#else FILE *ofile; FILE *tfile; +#endif { struct timeval tv; +#ifdef HAVE_ZLIB + gzwrite(ofile, buf, n); +#else fwrite(buf, 1, n, ofile); +#endif timersub(now, then, &tv); +#ifdef HAVE_ZLIB + gzprintf(tfile, "%f %d\n", + tv.tv_sec + ((double)tv.tv_usec / 1000000), n); +#else fprintf(tfile, "%f %d\n", tv.tv_sec + ((double)tv.tv_usec / 1000000), n); +#endif then->tv_sec = now->tv_sec; then->tv_usec = now->tv_usec; } @@ -352,7 +369,12 @@ script_execv(path, argv) struct timeval now, then; int n, nready, exitcode = 1; fd_set *fdsr, *fdsw; + FILE *idfile; +#ifdef HAVE_ZLIB + gzFile ofile, tfile; +#else FILE *idfile, *ofile, *tfile; +#endif int rbac_enabled = 0; #ifdef HAVE_SELINUX @@ -402,10 +424,17 @@ script_execv(path, argv) if ((idfile = fdopen(script_fds[SFD_LOG], "w")) == NULL) log_error(USE_ERRNO, "fdopen"); +#ifdef HAVE_ZLIB + if ((ofile = gzdopen(script_fds[SFD_OUTPUT], "w")) == NULL) + log_error(USE_ERRNO, "gzdopen"); + if ((tfile = gzdopen(script_fds[SFD_TIMING], "w")) == NULL) + log_error(USE_ERRNO, "gzdopen"); +#else if ((ofile = fdopen(script_fds[SFD_OUTPUT], "w")) == NULL) log_error(USE_ERRNO, "fdopen"); if ((tfile = fdopen(script_fds[SFD_TIMING], "w")) == NULL) log_error(USE_ERRNO, "fdopen"); +#endif gettimeofday(&then, NULL); @@ -452,8 +481,19 @@ script_execv(path, argv) zero_bytes(fdsw, howmany(script_fds[SFD_MASTER] + 1, NFDBITS) * sizeof(fd_mask)); zero_bytes(fdsr, howmany(script_fds[SFD_MASTER] + 1, NFDBITS) * sizeof(fd_mask)); - if (input.len != sizeof(input.buf)) - FD_SET(script_fds[SFD_USERTTY], fdsr); + if (input.len != sizeof(input.buf)) { + /* Only check for input if master pty is writable. */ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_SET(script_fds[SFD_MASTER], fdsw); + do { + n = select(script_fds[SFD_MASTER] + 1, NULL, fdsw, NULL, &tv); + } while (n == -1 && errno == EINTR); + if (n == 1) + FD_SET(script_fds[SFD_USERTTY], fdsr); + FD_CLR(script_fds[SFD_MASTER], fdsw); + } if (output.len != sizeof(output.buf)) FD_SET(script_fds[SFD_MASTER], fdsr); if (output.len > output.off) @@ -556,6 +596,14 @@ script_execv(path, argv) } flush_output(&output, &then, &now, ofile, tfile); +#ifdef HAVE_ZLIB + gzclose(ofile); + gzclose(tfile); +#else + fclose(ofile); + fclose(tfile); +#endif + do { n = term_restore(script_fds[SFD_USERTTY]); } while (!n && errno == EINTR); @@ -687,8 +735,8 @@ flush_output(output, then, now, ofile, tfile) struct script_buf *output; struct timeval *then; struct timeval *now; - FILE *ofile; - FILE *tfile; + void *ofile; + void *tfile; { int n; diff --git a/sudoreplay.c b/sudoreplay.c index e99302361..eae9d43f5 100644 --- a/sudoreplay.c +++ b/sudoreplay.c @@ -76,6 +76,9 @@ #ifdef HAVE_REGCOMP # include #endif +#ifdef HAVE_ZLIB +# include +#endif #include #include @@ -179,7 +182,12 @@ main(argc, argv) int ch, plen, ttyfd, interactive = 0, listonly = 0; const char *id, *user = NULL, *pattern = NULL, *tty = NULL; char path[PATH_MAX], buf[LINE_MAX], *cp, *ep; - FILE *tfile, *sfile, *lfile; + FILE *lfile; +#ifdef HAVE_ZLIB + gzFile tfile, sfile; +#else + FILE *tfile, *sfile; +#endif sigaction_t sa; unsigned long nbytes; size_t len, nread; @@ -242,13 +250,21 @@ main(argc, argv) id, &id[2], &id[4], strerror(ENAMETOOLONG)); /* timing file */ +#ifdef HAVE_ZLIB + tfile = gzopen(path, "r"); +#else tfile = fopen(path, "r"); +#endif if (tfile == NULL) error(1, "unable to open %s", path); /* script file */ memcpy(&path[plen - 3], "scr", 3); +#ifdef HAVE_ZLIB + sfile = gzopen(path, "r"); +#else sfile = fopen(path, "r"); +#endif if (sfile == NULL) error(1, "unable to open %s", path); @@ -290,7 +306,11 @@ main(argc, argv) /* * Timing file consists of line of the format: "%f %d\n" */ +#ifdef HAVE_ZLIB + while (gzgets(tfile, buf, sizeof(buf)) != NULL) { +#else while (fgets(buf, sizeof(buf), tfile) != NULL) { +#endif errno = 0; seconds = strtod(buf, &ep); if (errno != 0 || !isspace((unsigned char) *ep)) @@ -316,7 +336,11 @@ main(argc, argv) len = sizeof(buf); else len = nbytes; +#ifdef HAVE_ZLIB + nread = gzread(sfile, buf, len); +#else nread = fread(buf, 1, len, sfile); +#endif nbytes -= nread; do { /* no stdio, must be unbuffered */