OpenPKG CVS Repository http://cvs.openpkg.org/ ____________________________________________________________________________
Server: cvs.openpkg.org Name: Ralf S. Engelschall Root: /e/openpkg/cvs Email: [EMAIL PROTECTED] Module: openpkg-src Date: 01-Jul-2004 18:30:26 Branch: HEAD Handle: -NONE- Added files: openpkg-src/openpkg-audit audit-rpm.c audit.sh openpkg-audit.spec Log: new package: openpkg-audit 0.9.0 (OpenPKG Administration Auditing) Summary: Revision Changes Path 1.1 +279 -0 openpkg-src/openpkg-audit/audit-rpm.c 1.1 +162 -0 openpkg-src/openpkg-audit/audit.sh 1.1 +87 -0 openpkg-src/openpkg-audit/openpkg-audit.spec ____________________________________________________________________________ patch -p0 <<'@@ .' Index: openpkg-src/openpkg-audit/audit-rpm.c ============================================================================ $ cvs diff -u -r0 -r1.1 audit-rpm.c --- /dev/null 2004-07-01 18:30:26.000000000 +0200 +++ audit-rpm.c 2004-07-01 18:30:26.000000000 +0200 @@ -0,0 +1,279 @@ +/* +** rpm.c -- OpenPKG RPM Auditing Wrapper +** Copyright (c) 2004 The OpenPKG Project <http://www.openpkg.org/> +** Copyright (c) 2004 Ralf S. Engelschall <[EMAIL PROTECTED]> +** Copyright (c) 2004 Cable & Wireless <http://www.cw.com/> +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +*/ + +/* This is a small OpenPKG RPM command wrapper which provides minimal + auditing/logging possibilities to an OpenPKG instance by writing + a <prefix>/RPM/DB/Audit logfile containing the RPM commands which + actually led to a RPM database change. */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <pwd.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/wait.h> +#include <sys/time.h> +#include <sys/resource.h> + +/* utility function for fatal program termination under error condition */ +void die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "openpkg-audit: rpm: ERROR: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} + +/* the auditing logfile */ +#ifndef LOGFILE +#define LOGFILE "/var/openpkg-audit/openpkg-audit.log" +#endif + +/* the RPM database directory and owner/permission */ +#define RPMDB_DIR "RPM/DB" + +/* list of RPM database files to check */ +static char *RPMDB_files[] = { + "Basenames", + "Conflictname", + "Depends", + "Dirnames", + "Filemd5s", + "Group", + "Installtid", + "Name", + "Packages", + "Providename", + "Provideversion", + "Pubkeys", + "Requirename", + "Requireversion", + "Sha1header", + "Sigmd5", + "Triggername" +}; + +/* utility function for making a concatenated string out of multiple arguments */ +static char *mkstr(const char *pad, const char *s1, ...) +{ + va_list ap; + va_list apbak; + int n; + const char *cp; + char *str; + + va_start(ap, s1); + va_copy(apbak, ap); + n = 0; + for (cp = s1; cp != NULL; cp = (const char *)va_arg(ap, const char *)) + n += strlen(cp); + n++; + va_copy(ap, apbak); + if ((str = (char *)malloc(n)) == NULL) + die("failed to allocate %d bytes of memory", n); + str[0] = '\0'; + for (cp = s1; cp != NULL; cp = (const char *)va_arg(ap, const char *)) { + if (pad != NULL && str[0] != '\0') + strcat(str, pad); + strcat(str, cp); + } + va_end(ap); + return str; +} + +/* utility function for making a concatenated string out of an array */ +static char *mkstra(const char *pad, char **sa) +{ + int n, i; + char *str; + + n = 0; + for (i = 0; sa[i] != NULL; i++) + n += strlen(sa[i]); + n++; + if ((str = (char *)malloc(n)) == NULL) + die("failed to allocate %d bytes of memory", n); + str[0] = '\0'; + for (i = 0; sa[i] != NULL; i++) { + if (pad != NULL && str[0] != '\0') + strcat(str, pad); + strcat(str, sa[i]); + } + return str; +} + +/* utility function for determining the maximum mtime of the RPM database */ +static time_t rpmdb_mtime(const char *cpPrefix) +{ + time_t mtime = 0; + int i; + char *cp; + struct stat sb; + + for (i = 0; i < sizeof(RPMDB_files)/sizeof(RPMDB_files[0]); i++) { + cp = mkstr(NULL, cpPrefix, "/", RPMDB_DIR, "/", RPMDB_files[i], NULL); + if (stat(cp, &sb) == 0) { + if (mtime < sb.st_mtime) + mtime = sb.st_mtime; + } + free(cp); + } + return mtime; +} + +/* main procedure */ +int main(int argc, char *argv[]) +{ + char *cpPrefix; + char *cpToolsCmdProg; + char *cpToolsCmdName; + int i, j; + char **argv2; + FILE *fp; + char *cpLogfile; + struct tm *tm; + time_t t; + struct passwd *pw; + char *cpCmd; + time_t mtime_before; + time_t mtime_after; + char *cp; + pid_t pid; + int status; + int rv; + int fd; + struct stat sb; + + /* determine OpenPKG run-time information + (provided by <prefix>/bin/openpkg execution wrapper) */ + if ((cpPrefix = getenv("OPENPKG_PREFIX")) == NULL) + die("$OPENPKG_PREFIX not set"); + if ((cpToolsCmdProg = getenv("OPENPKG_TOOLS_CMDPROG")) == NULL) + die("$OPENPKG_TOOLS_CMDPROG not set"); + if ((cpToolsCmdName = getenv("OPENPKG_TOOLS_CMDNAME")) == NULL) + die("$OPENPKG_TOOLS_CMDNAME not set"); + + /* determine argument vector for real OpenPKG RPM command + argv: <prefix>/lib/openpkg-audit/rpm <arg1> <arg2> ... + argv2: <prefix>/bin/openpkg rpm <arg1> <arg2> ... */ + if ((argv2 = (char **)malloc((2+argc+1) * sizeof(char *))) == NULL) + die("cannot malloc"); + j = 0; + argv2[j++] = cpToolsCmdProg; + argv2[j++] = cpToolsCmdName; + i = 1; + while (i < argc) + argv2[j++] = argv[i++]; + argv2[j++] = NULL; + + /* determine whether access to the RPM database is possible + and it not, short-circuit processing */ + cp = mkstr(NULL, cpPrefix, "/", RPMDB_DIR, "/", RPMDB_files[0], NULL); + if (access(cp, R_OK|W_OK) != 0) { + /* pass-through execution to real OpenPKG RPM command */ + execvp(argv2[0], argv2); + /* NEVER REACHED */ + abort(); + } + free(cp); + + /* determine maximum modification time (before operation) */ + mtime_before = rpmdb_mtime(cpPrefix); + + /* execute real OpenPKG RPM command */ + if ((pid = fork()) == 0) { + /* pass-through execution to real OpenPKG RPM command */ + execvp(argv2[0], argv2); + /* NEVER REACHED */ + abort(); + } + + /* wait for child to terminate */ + if (waitpid(pid, &status, 0) < 0) + die("failed to wait for child process with PID %d\n", pid); + + /* determine return code */ + rv = (WIFEXITED(status) ? WEXITSTATUS(status) : -1); + + /* determine maximum modification time (after operation) */ + mtime_after = rpmdb_mtime(cpPrefix); + + /* if an operation was performed which has not changed the RPM + database we short-circuit processing and exit without logging */ + if (mtime_after == mtime_before) + exit(rv); + + /* determine time */ + t = time(NULL); + if ((tm = localtime(&t)) == NULL) + die("cannot determine local time"); + + /* determine user */ + if ((pw = getpwuid(getuid())) == NULL) + die("cannot determine user information"); + + /* determine command */ + cpCmd = mkstra(" ", &argv2[1]); + + /* optionally give up any root privileges to make sure + the file is written with the OpenPKG RPM database user/group */ + cp = mkstr(NULL, cpPrefix, "/", RPMDB_DIR, "/", RPMDB_files[0], NULL); + if (stat(cp, &sb) < 0) + die("unable to stat the RPM database file %s", cp); + free(cp); + setgid(sb.st_gid); setegid(sb.st_gid); + setuid(sb.st_uid); seteuid(sb.st_uid); + + /* write entry to logfile */ + cpLogfile = mkstr(NULL, cpPrefix, "/", LOGFILE, NULL); + if ((fd = open(cpLogfile, O_CREAT|O_RDWR|O_APPEND, sb.st_mode)) == -1) + die("cannot open logfile \"%s\"", cpLogfile); + free(cpLogfile); + if ((fp = fdopen(fd, "a")) == NULL) + die("cannot open filedescriptor"); + fprintf(fp, "%04d-%02d-%02d %02d:%02d:%02d user=%s, command=\"%s\", return=%d\n", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec, + pw->pw_name, + cpCmd, rv); + fclose(fp); + close(fd); + + /* cleanup */ + free(argv2); + free(cpCmd); + + exit(0); +} + @@ . patch -p0 <<'@@ .' Index: openpkg-src/openpkg-audit/audit.sh ============================================================================ $ cvs diff -u -r0 -r1.1 audit.sh --- /dev/null 2004-07-01 18:30:26.000000000 +0200 +++ audit.sh 2004-07-01 18:30:26.000000000 +0200 @@ -0,0 +1,162 @@ [EMAIL PROTECTED]@/lib/openpkg/bash +## +## audit -- OpenPKG Tool Chain "audit" command +## Copyright (c) 2004 The OpenPKG Project <http://www.openpkg.org/> +## Copyright (c) 2004 Ralf S. Engelschall <[EMAIL PROTECTED]> +## Copyright (c) 2004 Cable & Wireless <http://www.cw.com/> +## +## Permission to use, copy, modify, and distribute this software for +## any purpose with or without fee is hereby granted, provided that +## the above copyright notice and this permission notice appear in all +## copies. +## +## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## + +# configuration +logfile="@l_prefix@/var/openpkg-audit/openpkg-audit.log" + +# command line parsing +opt_m="" +opt_r=no +opt_h=no +opt_l=no +opt_n=0 +opt_f=no +OPTIND=1 +while getopts m:rln:fh opt; do + case ${opt} in + m ) opt_m=$OPTARG ;; + r ) opt_r=yes ;; + l ) opt_l=yes ;; + n ) opt_n=$OPTARG ;; + f ) opt_f=yes ;; + h ) opt_h=yes ;; + * ) echo "openpkg:audit:ERROR: invalid option \"${opt}\"" 1>&2; exit 1 ;; + esac +done +shift $(($OPTIND - 1)) + +# dispatch into commands +if [ ".${opt_h}" = .yes ]; then + # show usage message + echo "Usage: openpkg audit [-m <message>] [-r] [-l] [-n <lines>] [-f] [-h]" 1>&2 +elif [ ".${opt_l}" = .yes ]; then + # show logfile + if [ ".${opt_f}" = .yes ]; then + tail -f ${logfile} + elif [ ".${opt_n}" != .0 ]; then + tail -n ${opt_n} ${logfile} + else + cat ${logfile} + fi +elif [ ".${opt_m}" != . ]; then + # add manual administrator entry to logfile + if [ ! -w $logfile ]; then + echo "openpkg:audit:ERROR: unsufficient privileges to write to \"$logfile\"" 1>&2 + exit 1 + fi + + # determine date and user + date=`date '+%Y-%m-%d %H:%M:%S'` + [EMAIL PROTECTED]@/lib/openpkg/shtool echo -e '%u'` + + # create logfile entry + if [ ".${opt_r}" = .yes ]; then + echo "$date user=$user, $opt_m" >>$logfile + else + echo "$date user=$user, message=\"$opt_m\"" >>$logfile + fi +fi +exit 0 + +## +## MANUAL PAGE +## + +=pod + +=head1 NAME + +B<openpkg audit> - OpenPKG Auditing Facility + +=head1 SYNOPSIS + +B<openpkg audit> [B<-m> I<message>] [B<-r>] + +B<openpkg audit> [B<-l>] [B<-n> I<lines>] [B<-f>] + +B<openpkg audit> [B<-h>] + +=head1 DESCRIPTION + +The B<openpkg audit> command is the frontend to the OpenPKG auditing +logfile which is currently written by the B<openpkg rpm> +command in case the RPM database was changed. + +=head1 OPTIONS + +The following command line options exist: + +=over 4 + +=item B<-m> I<message> + +Adds I<message> to the auditing logfile as a C<message="..."> entry. + +=item B<-r> + +In conjunction with B<-m>, adds I<message> to the auditing logfile as a +raw message. + +=item B<-l> + +Shows the auditing logfile. + +=item B<-n> I<lines> + +In conjunction with B<-l>, shows only the last I<lines> number of lines. + +=item B<-f> + +In conjunction with B<-l>, follows the logfile. + +=item B<-h> + +Shows a command usage. + +=back + +=head1 FILES + +The following paths are used by B<openpkg audit>: + +=over 4 + +=item F<@l_prefix@/bin/openpkg> + +=item F<@l_prefix@/var/openpkg-audit/openpkg-audit.log> + +=back + +=head1 SEE ALSO + +C<openpkg man rpm>. + +=head1 AUTHOR + +Ralf S. Engelschall E<lt>[EMAIL PROTECTED]<gt> + +=cut + @@ . patch -p0 <<'@@ .' Index: openpkg-src/openpkg-audit/openpkg-audit.spec ============================================================================ $ cvs diff -u -r0 -r1.1 openpkg-audit.spec --- /dev/null 2004-07-01 18:30:26.000000000 +0200 +++ openpkg-audit.spec 2004-07-01 18:30:26.000000000 +0200 @@ -0,0 +1,87 @@ +## +## openpkg-audit.spec -- OpenPKG RPM Specification +## Copyright (c) 2000-2004 The OpenPKG Project <http://www.openpkg.org/> +## Copyright (c) 2000-2004 Ralf S. Engelschall <[EMAIL PROTECTED]> +## Copyright (c) 2000-2004 Cable & Wireless <http://www.cw.com/> +## +## Permission to use, copy, modify, and distribute this software for +## any purpose with or without fee is hereby granted, provided that +## the above copyright notice and this permission notice appear in all +## copies. +## +## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## + +# package information +Name: openpkg-audit +Summary: OpenPKG Administration Auditing +URL: http://www.openpkg.org/ +Vendor: The OpenPKG Project +Packager: The OpenPKG Project +Distribution: OpenPKG +Class: EVAL +Group: Bootstrap +License: MIT-style +Version: 0.9.0 +Release: 20040701 + +# list of sources +Source0: audit.sh +Source1: audit-rpm.c + +# build information +Prefix: %{l_prefix} +BuildRoot: %{l_buildroot} +BuildPreReq: OpenPKG, openpkg >= 20040701 +PreReq: OpenPKG, openpkg >= 20040701 +AutoReq: no +AutoReqProv: no + +%description + This is the OpenPKG administration auditing package. It provides + a wrapper for the "openpkg rpm" command which logs all commands + the administrator performs on the OpenPKG instance plus a "openpkg + audit" command as a frontend to the log entries. + +%track + prog openpkg-audit = { + disabled + version = %{version} + url = ftp://ftp.openpkg.org/ + regex = .* + } + +%prep + %setup -q -T -c + +%build + %{l_cc} %{l_cflags -O} %{l_cppflags} %{l_ldflags} \ + -o rpm %{SOURCE audit-rpm.c} + +%install + rm -rf $RPM_BUILD_ROOT + %{l_shtool} mkdir -f -p -m 755 \ + $RPM_BUILD_ROOT%{l_prefix}/libexec/openpkg-audit \ + $RPM_BUILD_ROOT%{l_prefix}/var/openpkg-audit + %{l_shtool} install -c -m 755 %{l_value -s -a} \ + %{SOURCE audit.sh} $RPM_BUILD_ROOT%{l_prefix}/libexec/openpkg-audit/ + %{l_shtool} install -c -s -m 755 \ + rpm $RPM_BUILD_ROOT%{l_prefix}/libexec/openpkg-audit/ + %{l_rpmtool} files -v -ofiles -r$RPM_BUILD_ROOT %{l_files_std} + +%files -f files + +%clean + rm -rf $RPM_BUILD_ROOT + @@ . ______________________________________________________________________ The OpenPKG Project www.openpkg.org CVS Repository Commit List [EMAIL PROTECTED]