#!/bin/bash # # Datenbank-Wartung. # function info { echo -e ' SYNTAX: tw_service [-c ext] [-u Obj1,Obj2,...] [-UbBrRfiId] -c Wählt die Konfiguration "tw.config-ext" an. -u Aktualisiert zugehörige Datenbankeinträge. -U Frontend für Abstimmungsarbeiten an der Schildkonfiguration. -b Sichert die mit BACKUP markierten Objekte. ([!|=] Objekt [Auswahlmaske] [#Kommentar [BACKUP]]) -B Wie "-b" aber mit Menü und anschließendem Update. (st_atime-Problem) -r Rückübertragen des Archivinhalts ins System. -R Wie "-r" aber mit Menü und anschließendem Update. (st_ino, st_ctime, ...) -f Schaltet Überschreibschutz für jüngere Systemdateien aus. (Vorsicht!) -i Interaktive Aktualisierung der betreffenden Datenbank. -I Wie "-i" aber mit Menü zur Datenbankanwahl. -d Restauriert die Datenbank.\n' } . ${0%/*}/tw_conf ; . ${0%/*}/tw_lib cf=$DESTDIR/tw.config db=$DATADIR/$DATABASE dbsig=$DBSIGDIR/$DBSIG dbback=$BACKUPDIR/$DATABASE function error { echo "--> ${0##*/}: $*" ; exit 1 } function check_config { if ! [ -e $cf$ext ] || ! [ -e $db$ext ] || ! [ -e $dbsig$ext ]; then error 'Keine gültige Konfiguration!' elif [ "$(< $dbsig$ext)" != "$($DESTDIR/siggen -7 $db$ext)" ]; then error 'Datenbank manipuliert!' fi } function go { # Update! local new_db="./databases/$DATABASE" \ conf="--cfgfile $cf$ext --dbfile $db$ext" end check_config [ -e $new_db ] && mv $new_db $new_db.tmp $DESTDIR/tripwire --quiet ${ext:+$conf} $* >/dev/null 2>&1 if [ $? = 1 ]; then [ -e $new_db.tmp ] && mv $new_db.tmp $new_db error 'Laufzeitfehler beim Update!' fi # Datenbank installieren! if [ -e $new_db ]; then cp -v $new_db $db$ext # Arbeitskopie... $DESTDIR/siggen -7 $new_db >$dbsig$ext #...zug. Signatur... gzip -1 -c $new_db >$dbback$ext.gz ; gzip -t $dbback$ext.gz # ...und Sicherheitskopie der Datenbank. chmod 600 $db$ext $dbsig$ext $dbback$ext.gz end=".old" fi [ -e $new_db.tmp ] && mv $new_db.tmp $new_db$end } function reconfigure { function strip { sed "s/[$SEP]*#.*$//g;s/[$SEP]\+/ /g" $1 } # Konfiguration berichtigen! local conf=$cf$ext path news ! [ -e $conf ] && error 'Kann Konfigurationsdatei nicht finden!' cp $conf $conf.old ; $EDITCOM $conf [ $conf.old -nt $conf ] && { rm -f $conf.old; return; } # Neues? declare -i n=0 m=0 for path in $(diff <(strip $conf.old) <(strip $conf) | grep '^[<>]' | \ sed "s/^..[\=\!]\?//g;s/[$SEP].*$//g" | sort -u); do if grep -q "^$path.*#.*FLAG" $conf; then troj_path[$n]=$path ; n=$((n+1)) else main_path[$m]=$path ; m=$((m+1)) fi news=yes done [ -z "$news" ] && { rm -f $conf.old; return; } # Update! if scat_dummies "${troj_path[@]}"; then rm -f $conf.old go --update ${main_path[*]} ${troj_path[*]} else error "Kein Schreibrecht in $scat_dir!" fi rm -f ${troj_path[*]} } function backup { # Backup-Volumen integer? local conf=$cf$ext type=${ext#-} int_sec arch=$BACKUPDIR/$ARCHIVES$ext.gz ! [ -e $conf ] && error 'Kann Konfigurationsdatei nicht finden!' set_entry BACKUP <$conf || error 'Keine Einträge zur Datensicherung markiert!' $DESTDIR/tw_check ${type:+-c $type} >/dev/null 2>&1 [ $? = 1 ] && error 'Laufzeitfehler beim Integritätstest!' tail +"$(grep -n 'Folgende Ver' $REPORT | tail -1 | sed -e 's/:.*//g')" $REPORT | \ sed '/^[^adct]/d;/^$/d' >$REPORT.new int_sec=$(for path in ${entry[*]}; do echo "$(grep $path $REPORT.new)"; done) if [ -n "$int_sec" ]; then rm -f $REPORT.new echo -e "--> ${0##*/}: Backup abgebrochen, da Inkonsistenzen vorhanden!\n$int_sec" | \ sed '/^$/d;s/^\([adct].*\)$/ -> \1/g' | less exit 1 fi rm -f $REPORT.new # Backup! eval find ${entry[*]} | cpio -oV -H crc -M 'Kapazität des Backup-Mediums %d erschöpft!' | \ gzip >$arch # Erzeugt ein SVR4-Archiv in BACKUPDIR. gzip -t $arch ; chmod 600 $arch # Update zur st_atime-Korrektur? if [ "$1" ]; then go --update ${entry[*]} fi } function restore { # Archiv vorhanden? local arch=$BACKUPDIR/$ARCHIVES$ext.gz cp_cmd vol=/tmp/v.$$ list ! [ -e $arch ] && error 'Kann Archiv nicht finden!' # Rückübertragen! if [ -z "$replace_mode" ]; then cp_cmd='cpio -imv 2>&1' else cp_cmd='cpio -imvu 2>&1' # Dieses Kommando überschreibt auch jüngere Dateien und kann deshalb benutzt werden, um # manipulierte Systemdateien etwa nach einer Kompromittierung des Rechners unschädlich zu # machen. Unglücklicherweise gehen dabei auch frische Veränderungen administrativer Art # verloren. Um die Vorzüge des "restore"-Mechanismus voll ausschöpfen zu können, ist es daher # erforderlich, Korrekturen an der Systemkonfiguration von Zeit zu Zeit mit "tw_service -B" # ins Backup-Volumen zu übernehmen! fi gzip -d -c $arch | eval $cp_cmd | tee $vol | grep '^/' | sed 's/^.*$/\./g' | tr -dc '.' echo ; grep '^[0-9]' $vol # Update korrespondierender Datenbankeinträge? if [ "$1" ]; then list=$(grep '^/' $vol) [ -n "$list" ] && go --update $list fi rm -f $vol } function restore_db { local local_db=$db$ext new_db=$dbback$ext.gz ! [ -e $new_db ] && error 'Kann Sicherheitskopie der Datenbank nicht finden!' [ -e $local_db ] && mv $local_db $local_db.dead gzip -d -c $new_db >$local_db chmod 600 $local_db } function ask_op { function set_ext { ext="-$1" [ $1 = $DEFDBNAME ] && unset ext } local list=$(databases) cfg declare -i num_db=$(echo $list | wc -w | tr -d ' ') case $num_db in 0) error 'Keine Konfigurationsdatei!';; 1) set_ext $list ; eval "$*";; *) PS3='Datenbank? ' select cfg in $list; do if [ "$cfg" ]; then set_ext $cfg ; eval "$*" read -p 'Abbrechen? (j/n) ' [ "$REPLY" != 'n' ] && exit 0 fi done;; esac } # Anweisungsteil if [ -z "$*" ]; then info ; exit 1 fi while getopts "c:fu:UbBrRiIdh" opt; do case $opt in c) ext="-$OPTARG";; f) replace_mode=true;; u) cmd_obj=${OPTARG//,/ } ; cmd=upd;; U) cmd=Upd;; b) cmd=back;; B) cmd=Back;; r) cmd=rest;; R) cmd=Rest;; i) cmd=intact;; I) cmd=Intact;; d) cmd=rest_db;; h) info ; exit 0;; *) exit 1;; esac done case $cmd in upd ) go --update $cmd_obj;; Upd ) ask_op 'reconfigure';; back ) backup;; Back ) ask_op 'backup and_update';; rest ) restore;; Rest ) ask_op 'restore and_update';; intact ) go --interactive;; Intact ) ask_op 'go --interactive';; rest_db) restore_db;; esac