Index: trunk/scripts/samhainadmin-gpg.pl.in
===================================================================
--- trunk/scripts/samhainadmin-gpg.pl.in	(revision 550)
+++ trunk/scripts/samhainadmin-gpg.pl.in	(revision 550)
@@ -0,0 +1,726 @@
+#! /usr/bin/perl
+
+# Copyright Rainer Wichmann (2004)
+#
+# License Information:
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+use warnings;
+use strict;
+use Getopt::Long;
+use File::Basename;
+use File::Copy;
+use File::stat;
+use File::Temp qw/ tempfile tempdir unlink0 /;
+use IO::Handle;
+use Fcntl qw(:DEFAULT :flock);
+use Tie::File;
+
+# Do I/O to the data file in binary mode (so it 
+# wouldn't complain about invalid UTF-8 characters).
+use bytes;
+
+File::Temp->safe_level( File::Temp::HIGH );
+
+my %opts = ();
+my $action;
+my $file1;
+my $file2;
+my $passphrase;
+my $secretkeyring;
+my $return_from_sign = 0;
+my $no_print_examine = 0;
+my $no_remove_lock   = 0;
+my $base = basename($0);
+
+my $cfgfile  = "@myconffile@";
+my $datafile = "@mydatafile@";
+my $daemon   = "@sbindir@/@install_name@";
+my $gpg      = "@mygpg@";
+
+my $TARGETKEYID = "@mykeyid@";
+my $KEYTAG      = "@mykeytag@";
+
+$cfgfile  =~ s/^REQ_FROM_SERVER//;
+$datafile =~ s/^REQ_FROM_SERVER//;
+
+$gpg = "gpg" if ($gpg eq "");
+
+sub check_gpg_agent() {
+    my  $gpgconf = "$ENV{'HOME'}/.gnupg/gpg.conf";
+
+    if (!-f "$gpgconf") {
+	$gpgconf = "$ENV{'HOME'}/.gnupg/options";
+    }
+
+    if (-f $gpgconf) {
+
+	my @array = ();
+	tie @array, 'Tie::File', $gpgconf or die "Cannot tie ${gpgconf}: $!";
+	my @grep = grep(/^\s*use-agent/, @array);
+	
+	# print "matches = $#grep\n";
+	
+	if ($#grep >= 0)
+	{
+	    if (exists $ENV{'GPG_AGENT_INFO'})
+	    {
+		my $socke = $ENV{'GPG_AGENT_INFO'};
+		$socke =~ s/:.*//;
+		
+		# print "socke = $socke\n";
+		
+		if (! -S $socke)
+		{
+		    print "--------------------------------------------------\n";
+		    print "\n";
+		    print " GPG is set to use gpg-agent, but GPG agent is";
+		    print " not running, though GPG_AGENT_INFO is defined.\n\n";
+		    print " Please restart gpg-agent, or remove the use-agent\n";
+		    print " option from ${gpgconf} and unset GPG_AGENT_INFO\n\n";
+		    print "--------------------------------------------------\n";
+		    print "\n";
+		    exit 1;
+		}
+	    }
+	    else
+	    {
+		print "--------------------------------------------------\n";
+		print "\n";
+		print " GPG is set to use gpg-agent, but ";
+		print " GPG_AGENT_INFO is not defined.\n\n";
+		print " Please start gpg-agent, or remove the use-agent\n";
+		print " option from ${gpgconf}\n\n";
+		print "--------------------------------------------------\n";
+		print "\n";
+		exit 1;
+	    }
+	}
+	untie @array;
+    }
+}
+
+
+sub usage() {
+    print "Usage:\n";
+    print "  $base { -m F | --create-cfgfile }    [options] [in.cfgfile]\n";
+    print "    Sign the configuration file. If in.cfgfile is given, sign it\n";
+    print "    and install it as configuration file.\n\n";
+
+    print "  $base { -m f | --print-cfgfile }     [options] \n";
+    print "    Print the configuration file to stdout. Signatures are removed.\n\n";
+
+    print "  $base { -m D | --create-datafile }   [options] [in.datafile]\n";
+    print "    Sign the database file. If in.datafile is given, sign it\n";
+    print "    and install it as database file.\n\n";
+
+    print "  $base { -m d | --print-datafile }    [options] \n";
+    print "    Print the database file to stdout. Signatures are removed. Use\n";
+    print "    option --list to list files in database rather than printing the raw file.\n\n";
+
+    print "  $base { -m R | --remove-signature }  [options] file1 [file2 ...]\n";
+    print "    Remove cleartext signature from input file(s). The file\n";
+    print "    is replaced by the non-signed file.\n\n";
+
+    print "  $base { -m E | --sign }              [options] file1 [file2 ...]\n";
+    print "    Sign file(s) with a cleartext signature. The file\n";
+    print "    is replaced by the signed file.\n\n";
+
+    print "  $base { -m e | --examine }           [options] file1 [file2 ...]\n";
+    print "    Report signature status of file(s).\n\n";
+
+    print "  $base { -m G | --generate-keys }     [options] \n";
+    print "    Generate a PGP keypair to use for signing.\n\n";
+
+    print "Options:\n";
+    print "  -c cfgfile    --cfgfile cfgfile\n";
+    print "    Select an alternate configuration file.\n\n";
+
+    print "  -d datafile   --datafile datafile\n";
+    print "    Select an alternate database file.\n\n";
+
+    print "  -p passphrase --passphrase passphrase\n";
+    print "    Set the passphrase for gpg. By default, gpg will ask.\n\n";
+
+    print "  -s gnupg_homedir --secretkeyring gnupg_homedir\n";
+    print "    Select an alternate gpg homedirectory to locate the secret keyring.\n";
+    print "    Will use '$ENV{'HOME'}/.gnupg/' by default.\n\n";
+
+    print "  -k keyid      --keyid keyid\n";
+    print "   Select the keyid to use for signing.\n\n";
+
+    print "  -l            --list\n";
+    print "    List the files in database rather than printing the raw file.\n\n";
+
+    print "  -v            --verbose\n";
+    print "    Verbose output.\n\n";
+    return;
+}
+
+sub check_gpg_uid () {
+    if (0 != $>) {
+	print "--------------------------------------------------\n";
+	print "\n";
+	print " You are not root. Please remember that samhain/yule\n";
+	print " will use the public keyring of root to verify a signature.\n";
+	print "\n";
+	print "--------------------------------------------------\n";
+    } else {
+	if (!("@yulectl_prg@" =~ //)) {
+	    print "--------------------------------------------------\n";
+	    print "\n";
+	    print " Please remember that yule will drop root after startup. Signature\n";
+	    print " verification on SIGHUP will fail if you do not import the public key\n";
+	    print " into the keyring of the non-root yule user.\n";
+	    print "\n";
+	    print "--------------------------------------------------\n";
+	}
+    }
+}
+    
+sub check_gpg_sign () {
+    if ( defined($secretkeyring)) {
+        if ( (!-d "$secretkeyring")){
+            print "--------------------------------------------------\n";
+            print "\n";
+            print " Secret keyring $secretkeyring not found!\n";
+            print "\n";
+            print " Please check the path/name of the alternate secret keyring.\n";
+            print "\n";
+            print "--------------------------------------------------\n";
+            print "\n";
+            exit;
+        }
+    } else {
+        if ( (!-d "$ENV{'HOME'}/.gnupg") || (!-e "$ENV{'HOME'}/.gnupg/secring.gpg")) {
+	    print "--------------------------------------------------\n";
+	    print "\n";
+	    if (!-d "$ENV{'HOME'}/.gnupg") {
+	        print " Directory \$HOME/.gnupg not found!\n";
+	    } else {
+	        print " Secret keyring \$HOME/.gnupg/secring.gpg not found!\n";
+	    }
+	    print "\n";
+	    print " This indicates that you have never created a \n";
+	    print " public/private keypair, and thus cannot sign.\n";
+	    print " \n";
+	    print " Please use $0 --generate-keys or gpg --gen-key\n";
+	    print " to generate a public/private keypair first.\n";
+	    print "\n";
+	    print "--------------------------------------------------\n";
+	    print "\n";
+	    exit;
+        }
+    }
+}
+
+sub check_gpg_verify () {
+    if ( (!-d "$ENV{'HOME'}/.gnupg") || (!-e "$ENV{'HOME'}/.gnupg/pubring.gpg")) {
+	print "--------------------------------------------------\n";
+	print "\n";
+	if (!-d "$ENV{'HOME'}/.gnupg") {
+	    print " Directory \$HOME/.gnupg not found!\n";
+	} else {
+	    print " Public keyring \$HOME/.gnupg/pubring.gpg not found!\n";
+	}
+	print "\n";
+	print " This indicates that you have never used gpg before \n";
+	print " and/or have no public keys to verify signatures.\n";
+	print " \n";
+	print " Please use 'gpg --export key_id' to export the public\n";
+	print " signing key of the user who is signing the\n";
+	print " configuration/database files.\n\n";
+	print " Then you can use 'gpg --import keyfile' to import the key\n";
+	print " into this user's public keyring.\n";
+	print "\n";
+	print "--------------------------------------------------\n";
+	print "\n";
+	exit;
+    }
+}
+
+
+sub generate () {
+    my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --gen-key";
+    check_gpg_uid();
+    system ($command) == 0 
+	or die "system $command failed: $?";
+    exit;
+}
+
+sub examine () {
+    my $iscfg = 0;
+    my $have_fp  = 0;
+    my $have_sig = 0;
+    my $message = '';
+    my $retval  = 9;
+    my $fh;
+    my $filename;
+
+    if (!($file1 =~ /^\-$/)) {
+	die ("Cannot open $file1 for read: $!") unless ((-e $file1) && (-r _));
+    }
+    open FIN,  "<$file1" or die "Cannot open $file1 for read: $!";
+
+    my $dir = tempdir( CLEANUP => 1 );
+    $filename = $dir . "/exa_jhfdbilw." . $$;
+    open $fh, ">$filename" or die "Cannot open $filename";
+    autoflush $fh 1;
+
+    while (<FIN>) {
+	print $fh $_;
+	if ($_ =~ /^\s*\[Misc\]/) {
+	    $iscfg = 1;
+	}
+    }
+    if ($iscfg == 1) {
+	$message .=  "File $file1 is a configuration file\n\n";
+    } else {
+	$message .=  "File $file1 is a database file\n\n";
+    }
+
+
+    my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --status-fd 1 ";
+    $command .= "--verbose " if (defined($opts{'v'}));
+    $command .= "--verify $filename ";
+    if (defined($opts{'v'})) {
+	$command .= "2>&1";
+    } else {
+	$command .= "2>/dev/null";
+    }
+
+    print STDOUT "Using: $command\n\n" if (defined($opts{'v'}));
+    open  GPGIN, "$command |" or die "Cannot fork: $!";
+
+    while (<GPGIN>) {
+	if ($_ =~ /^\[GNUPG:\] GOODSIG ([0-9A-F]+) (.*)$/) {
+	    $message .= "GOOD signature with key: $1\n";
+	    $message .= "Key owner:               $2\n";
+	    $have_sig = 1;
+	    $retval   = 0;
+	}
+	if ($_ =~ /^\[GNUPG:\] VALIDSIG ([0-9A-F]+) ([0-9\-]+)\s/) {
+	    $message .= "Key fingerprint:         $1\n";
+	    $message .= "Signature generated on:  $2\n\n";
+	    $have_fp = 1;
+	    $message .=  "This file is signed with a valid signature.\n" 
+		if ($have_sig == 1);
+	    $have_sig = 1;
+	    $have_fp = 1;
+	}
+	if ($_ =~ /^\[GNUPG:\] NODATA 1/) {
+	    $message .=  "NO signature found.\n\n";
+	    $message .=  "This file is not signed !!!\n";
+	    $have_sig = 1;
+	    $have_fp = 1;
+	    $retval  = 2;
+	}
+	if ($_ =~ /^\[GNUPG:\] BADSIG ([0-9A-F]+) (.*)$/) {
+	    $message .=  "BAD signature with key: $1\n";
+	    $message .=  "Key owner:              $2\n\n";
+	    $message .=  "This file is signed with an invalid signature !!!\n";
+	    $have_sig = 1;
+	    $have_fp = 1;
+	    $retval = 1;
+	}
+	if ($_ =~ /^\[GNUPG:\] NO_PUBKEY ([0-9A-F]+)/) {
+	    $message .=  "NOT CHECKED signature with key: $1\n\n";
+	    $message .=  "The signature of this file cannot be checked: no public key available !!!\n";
+	    $have_sig = 1;
+	    $have_fp = 1;
+	    $retval  = 1;
+	}
+	print STDOUT $_ if (defined($opts{'v'}));
+    }
+    close (GPGIN);
+    print STDOUT "\n" if (defined($opts{'v'}));
+    if ($have_sig == 0) {
+	$message .=  "NO valid signature found\n";
+    } 
+    elsif ($have_fp == 0) {
+	$message .=  "NO fingerprint found\n";
+    }
+    close (FIN);
+    if ($no_print_examine == 0) {
+	print STDOUT $message;
+    }
+    unlink0( $fh, $filename ) or die "Cannot unlink $filename safely";
+    return $retval;
+}
+
+sub remove () {
+    my $bodystart = 1;
+    my $sigstart  = 0;
+    my $sigend    = 0;
+    my $filename  = "";
+    my $fh;
+    my $stats;
+
+    open FH, "<$file1" or die "Cannot open file $file1 for read: $!";
+    if (!($file1 =~ /^\-$/)) {
+	flock(FH, LOCK_EX) unless ($no_remove_lock == 1);
+	my $dir = tempdir( CLEANUP => 1 ) or die "Tempdir failed";
+	$filename = $dir . "/rem_iqegBCQb." . $$;
+	open $fh, ">$filename" or die "Cannot open $filename";
+	$stats = stat($file1);
+	# ($fh, $filename) = tempfile(UNLINK => 1);
+    } else {
+	open $fh, ">$file1" or die "Cannot open file $file1 for write: $!";
+    }
+    autoflush $fh 1;
+    while (<FH>) {
+	if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) {
+	    $sigstart = 1;
+	    $bodystart = 0;
+	    next;
+	} elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) {
+	    $sigstart = 0;
+	    $bodystart = 1;
+	    next;
+	} elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) {
+	    $bodystart = 0;
+	    $sigend = 1;
+	    next;
+	} elsif (($sigend == 1) && ($_ =~ /^-----END PGP SIGNATURE-----/)) {
+	    $sigend = 0;
+	    $bodystart = 1;
+	    next;
+	}
+	if ($bodystart == 1) {
+	    print $fh $_;
+	}
+    }
+    if (!($file1 =~ /^\-$/)) {
+	copy("$filename", "$file1") 
+	    or die "Copy $filename to $file1 failed: $!";
+	chmod $stats->mode, $file1;
+	chown $stats->uid, $stats->gid, $file1;
+	flock(FH, LOCK_UN) unless ($no_remove_lock == 1);
+	close FH;
+    }
+    unlink0( $fh, $filename ) or die "Cannot unlink $filename safely";
+    return;
+}
+
+sub print_cfgfile () {
+    my $bodystart = 0;
+    my $sigstart  = 0;
+
+    if (!defined($file2)) {
+	$file2 = '-';
+    }
+
+    open FH, "<$file1" or die "Cannot open file $file1 for read: $!";
+    open FO, ">$file2" or die "Cannot open file $file2 for write: $!";
+    while (<FH>) {
+	if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) {
+	    $sigstart = 1;
+	    next;
+	} elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) {
+	    $sigstart = 0;
+	    $bodystart = 1;
+	    next;
+	} elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) {
+	    $bodystart = 0;
+	    exit;
+	}
+	if ($bodystart == 1) {
+	    print FO $_;
+	}
+    }
+    exit;
+}
+sub print_datafile () {
+    die ("Cannot find program $daemon") 
+	unless (-e $daemon);
+    if (defined($opts{'v'})) {
+	open FH, "$daemon --full-detail -d $datafile |" 
+	    or die "Cannot open datafile $datafile for read: $!";
+    } else {
+	open FH, "$daemon -d $datafile |" 
+	    or die "Cannot open datafile $datafile for read: $!";
+    }
+    while (<FH>) {
+	print $_;
+    }
+    exit;
+}
+
+sub sign_file () {
+
+    my $fileout = '';
+    my $bodystart = 1;
+    my $sigstart  = 0;
+    my $sigend    = 0;
+    my $stats;
+    my $fh1;
+    my $filename1;
+    my $flag1     = 0;
+
+    check_gpg_uid();
+    check_gpg_agent();
+
+    if (!defined($file2)) {
+	$file2 = $file1;
+    }
+
+    if ($file1 =~ /^\-$/) {
+	my $dir = tempdir( CLEANUP => 1 ) or die "Tempdir failed";
+	$filename1 = $dir . "/sig_vs8827sd." . $$;
+	open $fh1, ">$filename1" or die "Cannot open $filename1";
+	$flag1 = 1;
+	# my ($fh1, $filename1) = tempfile(UNLINK => 1);
+
+	while (<STDIN>) {
+	  if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) {
+	    $sigstart = 1;
+	    $bodystart = 0;
+	    next;
+	  } elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) {
+	    $sigstart = 0;
+	    $bodystart = 1;
+	    next;
+	  } elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) {
+	    $bodystart = 0;
+	    $sigend = 1;
+	    next;
+	  } elsif (($sigend == 1) && ($_ =~ /^-----END PGP SIGNATURE-----/)) {
+	    $sigend = 0;
+	    $bodystart = 1;
+	    next;
+	  }
+	  if ($bodystart == 1) {
+	    print $fh1 $_;
+	  }
+	  #
+	  # print $fh1 $_;
+	  #
+	}
+	$file1 = $filename1;
+	$fileout = '-';
+    } else {
+	open (LOCKFILE, "<$file1") or die "Cannot open $file1: $!";
+	flock(LOCKFILE, LOCK_EX);
+	$no_print_examine = 1;
+	$no_remove_lock   = 1;
+	if (examine() < 2) {
+	    remove();
+	}
+	$fileout = $file1 . ".asc";
+	$stats   = stat($file1)
+	    or die "No file $file1: $!";
+    }
+
+    if (defined($passphrase)) {
+	local $SIG{PIPE} = 'IGNORE';
+	my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --passphrase-fd 0 -a ${KEYTAG} ${TARGETKEYID} --clearsign -o $fileout --not-dash-escaped ";
+        $command .= "--secret-keyring $secretkeyring " if (defined($opts{'s'}));
+	$command .= "$file1";
+	open (FH, "|$command")  or die "can't fork: $!";
+	print FH "$passphrase"  or die "can't write: $!";
+	close FH                or die "can't close: status=$?";
+    } else {
+	my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg                   -a ${KEYTAG} ${TARGETKEYID} --clearsign -o $fileout --not-dash-escaped ";
+        $command .= "--secret-keyring $secretkeyring " if (defined($opts{'s'}));
+	$command .= "$file1";
+	system("$command") == 0 
+	    or die "system $command failed: $?";
+    }
+
+    if (!($fileout =~ /^\-$/)) {
+	my $st_old = stat($file1) 
+	    or die "No file $file1: $!";
+	my $st_new = stat($fileout) 
+	    or die "No file $fileout: $!";
+	die ("Signed file is smaller than unsigned file") 
+	    unless ($st_new->size > $st_old->size);
+	move("$fileout", "$file2") 
+	    or die "Move $fileout to $file2 failed: $!";
+	chmod $stats->mode, $file2;
+	chown $stats->uid, $stats->gid, $file2;
+	flock(LOCKFILE, LOCK_UN);
+    }
+
+    if ($flag1 == 1) {
+	unlink0( $fh1, $filename1 ) or die "Cannot unlink $filename1 safely";
+    }
+    if ($return_from_sign == 1) {
+	return;
+    }
+    exit;
+}
+
+Getopt::Long::Configure ("posix_default");
+Getopt::Long::Configure ("bundling");
+# Getopt::Long::Configure ("debug");
+
+GetOptions (\%opts, 'm=s', 'h|help', 'v|verbose', 'l|list',
+	    'c|cfgfile=s',
+	    'd|datafile=s',
+	    'p|passphrase=s',
+	    's|secretkeyring=s',
+            'k|keyid=s',
+	    'create-cfgfile',  # -m F
+	    'print-cfgfile',   # -m f
+	    'create-datafile', # -m D
+	    'print-datafile',  # -m d
+	    'remove-signature',# -m R
+	    'sign',            # -m E
+	    'examine',         # -m e
+	    'generate-keys');  # -m G
+
+if (defined ($opts{'h'})) {
+    usage();
+    exit;
+}
+
+if (defined($opts{'k'})) {
+    $TARGETKEYID = $opts{'k'};
+    $KEYTAG = "--default-key";
+}
+if (defined($opts{'c'})) {
+    $cfgfile = $opts{'c'};
+}
+if (defined($opts{'d'})) {
+    $datafile = $opts{'d'};
+}
+if (defined($opts{'p'})) {
+    $passphrase = $opts{'p'};
+}
+if (defined($opts{'s'})) {
+    $secretkeyring = $opts{'s'};
+}
+
+if (defined ($opts{'m'}) && ($opts{'m'} =~ /[FfDdREeG]{1}/) ) {
+    $action = $opts{'m'};
+}
+elsif (defined ($opts{'create-cfgfile'})) {
+    $action = 'F';
+}
+elsif (defined ($opts{'print-cfgfile'})) {
+    $action = 'f';
+}
+elsif (defined ($opts{'create-datafile'})) {
+    $action = 'D';
+}
+elsif (defined ($opts{'print-datafile'})) {
+    $action = 'd';
+}
+elsif (defined ($opts{'remove-signature'})) {
+    $action = 'R';
+}
+elsif (defined ($opts{'sign'})) {
+    $action = 'E';
+}
+elsif (defined ($opts{'examine'})) {
+    $action = 'e';
+}
+elsif (defined ($opts{'generate-keys'})) {
+    $action = 'G';
+}
+else {
+    usage();
+    die ("No valid action specified !");
+}
+
+if (defined($ARGV[0])) {
+    $file1 = $ARGV[0];
+} 
+if (defined($ARGV[1])) {
+    $file2 = $ARGV[1];
+} 
+
+
+if (($action =~ /[REe]{1}/) && !defined($file1)) {
+    usage();
+    die("Option -m $action requires a filename (or '-' for stdio)\n");
+}
+
+if ($action =~ /^F$/) {
+    if (!defined($file1)) {
+	$file1 = $cfgfile;
+    }
+    $file2 = $cfgfile;
+    sign_file ();
+}
+
+if ($action =~ /^D$/) {
+    if (!defined($file1)) {
+	$file1 = $datafile;
+    }
+    $file2 = $datafile;
+    sign_file ();
+}
+
+if ($action =~ /^R$/) {
+    # $file1 defined
+    my $i = 0;
+    while (defined($ARGV[$i])) {
+	$file1 = $ARGV[$i];
+	remove ();
+	++$i;
+    }
+}
+
+if ($action =~ /^E$/) {
+    # $file1 defined
+    # default: $file2 = $file1
+    check_gpg_sign();
+    my $i = 0;
+    while (defined($ARGV[$i])) {
+	$file1 = $ARGV[$i];
+	$file2 = $file1;
+	$return_from_sign = 1;
+	sign_file ();
+	++$i;
+    }
+}
+
+if ($action =~ /^e$/) {
+    # $file1 defined
+    # default: $file2 = stdout
+    check_gpg_verify();
+    my $i = 0;
+    my $ret = 0;
+    while (defined($ARGV[$i])) {
+	print "\n";
+	$file1 = $ARGV[$i];
+	$ret += examine ();
+	++$i;
+	print "\n--------------------------------\n" if (defined($ARGV[$i]));
+    }
+    exit($ret);
+}
+
+if ($action =~ /^f$/) {
+    $file1 = $cfgfile;
+    $file2 = "-";
+    print_cfgfile ();
+}
+
+if ($action =~ /^d$/) {
+    # $file1 irrelevant
+    if (defined($opts{'l'})) {
+	print_datafile ();
+    } else {
+	$file1 = $datafile;
+	$file2 = "-";
+	print_cfgfile ();
+    }
+}
+
+
+
Index: trunk/scripts/samhainadmin-sig.pl.in
===================================================================
--- trunk/scripts/samhainadmin-sig.pl.in	(revision 550)
+++ trunk/scripts/samhainadmin-sig.pl.in	(revision 550)
@@ -0,0 +1,636 @@
+#! /usr/bin/perl
+
+# Copyright Rainer Wichmann (2004)
+#
+# License Information:
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+use warnings;
+use strict;
+use Getopt::Long;
+use File::Basename;
+use File::Copy;
+use File::stat;
+use File::Temp qw/ tempfile tempdir unlink0 /;
+use IO::Handle;
+use Fcntl qw(:DEFAULT :flock);
+use Tie::File;
+
+# Do I/O to the data file in binary mode (so it 
+# wouldn't complain about invalid UTF-8 characters).
+use bytes;
+
+File::Temp->safe_level( File::Temp::HIGH );
+
+my %opts = ();
+my $action;
+my $file1;
+my $file2;
+my $passphrase;
+my $secretkey;
+my $return_from_sign = 0;
+my $no_print_examine = 0;
+my $no_remove_lock   = 0;
+my $base = basename($0);
+
+my $cfgfile  = "@myconffile@";
+my $datafile = "@mydatafile@";
+my $daemon   = "@sbindir@/@install_name@";
+my $signify  = "@mysignify@";
+
+my $SIGDIR   = "$ENV{'HOME'}/.signify";
+my $KEYID    = "@install_name@";
+
+$cfgfile  =~ s/^REQ_FROM_SERVER//;
+$datafile =~ s/^REQ_FROM_SERVER//;
+
+$signify = "signify-openbsd" if ($signify eq "");
+
+sub usage() {
+    print "Usage:\n";
+    print "  $base { -m F | --create-cfgfile }    [options] [in.cfgfile]\n";
+    print "    Sign the configuration file. If in.cfgfile is given, sign it\n";
+    print "    and install it as configuration file.\n\n";
+
+    print "  $base { -m f | --print-cfgfile }     [options] \n";
+    print "    Print the configuration file to stdout. Signatures are removed.\n\n";
+
+    print "  $base { -m D | --create-datafile }   [options] [in.datafile]\n";
+    print "    Sign the database file. If in.datafile is given, sign it\n";
+    print "    and install it as database file.\n\n";
+
+    print "  $base { -m d | --print-datafile }    [options] \n";
+    print "    Print the database file to stdout. Signatures are removed. Use\n";
+    print "    option --list to list files in database rather than printing the raw file.\n\n";
+
+    print "  $base { -m R | --remove-signature }  [options] file1 [file2 ...]\n";
+    print "    Remove cleartext signature from input file(s). The file\n";
+    print "    is replaced by the non-signed file.\n\n";
+
+    print "  $base { -m E | --sign }              [options] file1 [file2 ...]\n";
+    print "    Sign file(s) with a cleartext signature. The file\n";
+    print "    is replaced by the signed file.\n\n";
+
+    print "  $base { -m e | --examine }           [options] file1 [file2 ...]\n";
+    print "    Report signature status of file(s).\n\n";
+
+    print "  $base { -m G | --generate-keys }     [options] \n";
+    print "    Generate a signify keypair to use for signing.\n\n";
+
+    print "Options:\n";
+    print "  -c cfgfile    --cfgfile cfgfile\n";
+    print "    Select an alternate configuration file.\n\n";
+
+    print "  -d datafile   --datafile datafile\n";
+    print "    Select an alternate database file.\n\n";
+
+    print "  -p passphrase --passphrase passphrase\n";
+    print "    Set the passphrase for signify. By default, signify will ask.\n\n";
+
+    print "  -s signify_dir --signify-dir signify_dir\n";
+    print "    Select an alternate directory to locate the secret keyring.\n";
+    print "    Will use '$ENV{'HOME'}/.signify/' by default.\n\n";
+
+    print "  -k keyid      --keyid keyid\n";
+    print "   Select the keyid to use for signing.\n\n";
+
+    print "  -l            --list\n";
+    print "    List the files in database rather than printing the raw file.\n\n";
+
+    print "  -v            --verbose\n";
+    print "    Verbose output.\n\n";
+    return;
+}
+
+sub check_signify_uid () {
+    if (0 != $>) {
+	print "--------------------------------------------------\n";
+	print "\n";
+	print " You are not root. Please remember that samhain/yule\n";
+	print " will use the public key of root to verify a signature.\n";
+	print "\n";
+	print "--------------------------------------------------\n";
+    } else {
+	if (!("@yulectl_prg@" =~ //)) {
+	    print "--------------------------------------------------\n";
+	    print "\n";
+	    print " Please remember that yule will drop root after startup. Signature\n";
+	    print " verification on SIGHUP will fail if you do not import the public key\n";
+	    print " into the ~/.signify/ directory of the non-root yule user.\n";
+	    print "\n";
+	    print "--------------------------------------------------\n";
+	}
+    }
+}
+    
+sub check_signify_sign () {
+    if ( defined($secretkey)) {
+        if ( (!-d "$secretkey")){
+            print "--------------------------------------------------\n";
+            print "\n";
+            print " Secret key $secretkey not found!\n";
+            print "\n";
+            print " Please check the path/name of the alternate secret key.\n";
+            print "\n";
+            print "--------------------------------------------------\n";
+            print "\n";
+            exit;
+        }
+    } else {
+        if ( (!-d "$SIGDIR") || (!-e "${SIGDIR}/${KEYID}.sec")) {
+	    print "--------------------------------------------------\n";
+	    print "\n";
+	    if (!-d "$SIGDIR") {
+	        print " Directory $SIGDIR not found!\n";
+	    } else {
+	        print " Secret key ${SIGDIR}/${KEYID}.sec not found!\n";
+	    }
+	    print "\n";
+	    print " This indicates that you have never created a \n";
+	    print " public/private keypair, and thus cannot sign.\n";
+	    print " \n";
+	    print " Please use $0 --generate-keys or\n";
+	    print " $signify -G -s ${SIGDIR}/${KEYID}.sec -p ${SIGDIR}/${KEYID}.pub\n";
+	    print " to generate a public/private keypair first.\n";
+	    print "\n";
+	    print "--------------------------------------------------\n";
+	    print "\n";
+	    exit;
+        }
+    }
+}
+
+sub check_signify_verify () {
+    if ( (!-d "${SIGDIR}") || (!-e "${SIGDIR}/${KEYID}.pub")) {
+	print "--------------------------------------------------\n";
+	print "\n";
+	if (!-d "$SIGDIR") {
+	    print " Directory $SIGDIR not found!\n";
+	} else {
+	    print " Public key ${SIGDIR}/${KEYID}.pub not found!\n";
+	}
+	print "\n";
+	print " This indicates that you have no public key\n";
+	print " to verify signatures.\n";
+	print " \n";
+	print " Please copy the public key ${KEYID}.pub of\n";
+	print " the user who is signing the configuration/database files\n";
+	print " into the directory $SIGDIR.\n";
+	print "\n";
+	print "--------------------------------------------------\n";
+	print "\n";
+	exit;
+    }
+}
+
+
+sub generate () {
+    my $command = "$signify -G -s ${SIGDIR}/${KEYID}.sec -p ${SIGDIR}/${KEYID}.pub";
+    if (!-d "${SIGDIR}") {
+	unless(mkdir "$SIGDIR", 0750) {
+	    die "Creating directory $SIGDIR failed: $?";
+	}
+    }
+    check_signify_uid();
+    system ($command) == 0 
+	or die "system $command failed: $?";
+    exit;
+}
+
+sub examine () {
+    my $iscfg = 0;
+    my $have_fp  = 0;
+    my $have_sig = 0;
+    my $message = '';
+    my $retval  = 9;
+    my $fh;
+    my $filename;
+
+    if (!($file1 =~ /^\-$/)) {
+	die ("Cannot open $file1 for read: $!") unless ((-e $file1) && (-r _));
+    }
+    open FIN,  "<$file1" or die "Cannot open $file1 for read: $!";
+
+    my $dir = tempdir( CLEANUP => 1 );
+    $filename = $dir . "/exa_jhfdbilw." . $$;
+    open $fh, ">$filename" or die "Cannot open $filename";
+    autoflush $fh 1;
+
+    while (<FIN>) {
+	print $fh $_;
+	if ($_ =~ /^\s*\[Misc\]/) {
+	    $iscfg = 1;
+	}
+    }
+    if ($iscfg == 1) {
+	$message .=  "File $file1 is a configuration file\n\n";
+    } else {
+	$message .=  "File $file1 is a database file\n\n";
+    }
+
+
+    my $command = "$signify -Vem /dev/null -p ${SIGDIR}/${KEYID}.pub ";
+    $command .= "-x $filename ";
+    if (defined($opts{'v'})) {
+	$command .= "2>&1";
+    } else {
+	$command .= "2>/dev/null";
+    }
+
+    print STDOUT "Using: $command\n\n" if (defined($opts{'v'}));
+    open  SIGIN, "$command |" or die "Cannot fork: $!";
+
+    while (<SIGIN>) {
+	chomp ($_);
+	if ($_ =~ /^Signature Verified$/) {
+	    $message .= "GOOD signature with key: ${SIGDIR}/${KEYID}.pub\n";
+	    $have_sig = 1;
+	    $retval   = 0;
+	}
+	print STDOUT $_ if (defined($opts{'v'}));
+    }
+    close (SIGIN);
+    print STDOUT "\n" if (defined($opts{'v'}));
+    if ($have_sig == 0) {
+	$message .=  "NO valid signature found\n";
+    }
+    close (FIN);
+    if ($no_print_examine == 0) {
+	print STDOUT $message;
+    }
+    unlink0( $fh, $filename ) or die "Cannot unlink $filename safely";
+    return $retval;
+}
+
+sub wstrip ($) {
+    $_ = shift;
+    $_ =~ s/\s+//g;
+    return $_;
+}
+
+sub remove () {
+    my $bodystart = 1;
+    my $sigstart  = 0;
+    my $sigend    = 0;
+    my $filename  = "";
+    my $fh;
+    my $stats;
+
+    open FH, "<$file1" or die "Cannot open file $file1 for read: $!";
+    if (!($file1 =~ /^\-$/)) {
+	flock(FH, LOCK_EX) unless ($no_remove_lock == 1);
+	my $dir = tempdir( CLEANUP => 1 ) or die "Tempdir failed";
+	$filename = $dir . "/rem_iqegBCQb." . $$;
+	open $fh, ">$filename" or die "Cannot open $filename";
+	$stats = stat($file1);
+    } else {
+	open $fh, ">$file1" or die "Cannot open file $file1 for write: $!";
+    }
+    autoflush $fh 1;
+    while (<FH>) {
+	if ($_ =~ /^untrusted comment: /) {
+	    $sigstart = 1;
+	    $bodystart = 0;
+	    next;
+	} elsif (($sigstart == 1) && (wstrip($_) =~ m{^(?: [A-Za-z0-9+/]{4} )*(?:[A-Za-z0-9+/]{2} [AEIMQUYcgkosw048]=|[A-Za-z0-9+/][AQgw]==)?$}xm )) {
+	    $sigstart = 0;
+	    $bodystart = 1;
+	    next;
+	} elsif (($sigstart == 1) && ($bodystart == 0)) {
+	    # comment NOT followed by signature
+	    $sigstart = 0;
+	    next;
+	}
+
+	if ($bodystart == 1) {
+	    print $fh $_;
+	}
+    }
+    if (!($file1 =~ /^\-$/)) {
+	copy("$filename", "$file1") 
+	    or die "Copy $filename to $file1 failed: $!";
+	chmod $stats->mode, $file1;
+	chown $stats->uid, $stats->gid, $file1;
+	flock(FH, LOCK_UN) unless ($no_remove_lock == 1);
+	close FH;
+    }
+    unlink0( $fh, $filename ) or die "Cannot unlink $filename safely";
+    return;
+}
+
+sub print_cfgfile () {
+    my $bodystart = 0;
+    my $sigstart  = 0;
+
+    if (!defined($file2)) {
+	$file2 = '-';
+    }
+
+    open FH, "<$file1" or die "Cannot open file $file1 for read: $!";
+    open FO, ">$file2" or die "Cannot open file $file2 for write: $!";
+    while (<FH>) {
+	if ($_ =~ /^untrusted comment: /) {
+	    $sigstart = 1;
+	    $bodystart = 0;
+	    next;
+	} elsif (($sigstart == 1) && (wstrip($_) =~ m{^(?: [A-Za-z0-9+/]{4} )*(?:[A-Za-z0-9+/]{2} [AEIMQUYcgkosw048]=|[A-Za-z0-9+/][AQgw]==)?$}xm )) {
+	    $sigstart = 0;
+	    $bodystart = 1;
+	    next;
+	} elsif (($sigstart == 1) && ($bodystart == 0)) {
+	    # comment NOT followed by signature 
+	    $sigstart = 0;
+	    next;
+	}
+	if ($bodystart == 1) {
+	    print FO $_;
+	}
+    }
+    exit;
+}
+
+sub print_datafile () {
+    die ("Cannot find program $daemon") 
+	unless (-e $daemon);
+    if (defined($opts{'v'})) {
+	open FH, "$daemon --full-detail -d $datafile |" 
+	    or die "Cannot open datafile $datafile for read: $!";
+    } else {
+	open FH, "$daemon -d $datafile |" 
+	    or die "Cannot open datafile $datafile for read: $!";
+    }
+    while (<FH>) {
+	print $_;
+    }
+    exit;
+}
+
+sub sign_file () {
+
+    my $fileout = '';
+    my $bodystart = 1;
+    my $sigstart  = 0;
+    my $sigend    = 0;
+    my $stats;
+    my $fh1;
+    my $filename1;
+    my $flag1     = 0;
+
+    check_signify_uid();
+
+    if (!defined($file2)) {
+	$file2 = $file1;
+    }
+
+    if ($file1 =~ /^\-$/) {
+	my $dir = tempdir( CLEANUP => 1 ) or die "Tempdir failed";
+	$filename1 = $dir . "/sig_vs8827sd." . $$;
+	open $fh1, ">$filename1" or die "Cannot open $filename1";
+	$flag1 = 1;
+	# my ($fh1, $filename1) = tempfile(UNLINK => 1);
+
+	while (<STDIN>) {
+	    if ($_ =~ /^untrusted comment: /) {
+		$sigstart = 1;
+		$bodystart = 0;
+		next;
+	    } elsif (($sigstart == 1) && (wstrip($_) =~ m{^(?: [A-Za-z0-9+/]{4} )*(?:[A-Za-z0-9+/]{2} [AEIMQUYcgkosw048]=|[A-Za-z0-9+/][AQgw]==)?$}xm )) {
+		$sigstart = 0;
+		$bodystart = 1;
+		next;
+	    } elsif (($sigstart == 1) && ($bodystart == 0)) {
+		#comment NOT followed by signature 
+		$sigstart = 0;
+		next;
+	    }
+
+	    if ($bodystart == 1) {
+		print $fh1 $_;
+	    }
+	}
+	$file1 = $filename1;
+	$fileout = '-';
+    } else {
+	open (LOCKFILE, "<$file1") or die "Cannot open $file1: $!";
+	flock(LOCKFILE, LOCK_EX);
+	$no_print_examine = 1;
+	$no_remove_lock   = 1;
+	if (examine() < 2) {
+	    remove();
+	}
+	$fileout = $file1 . ".sig";
+	$stats   = stat($file1)
+	    or die "No file $file1: $!";
+    }
+
+    my $command = "$signify -Se ";
+    $command .= "-s ${SIGDIR}/${KEYID}.sec ";
+    $command .= "-x ${fileout} ";
+    $command .= "-m $file1";
+
+    if (defined($passphrase)) {
+	local $SIG{PIPE} = 'IGNORE';
+	open (FH, "|$command")  or die "can't fork: $!";
+	print FH "$passphrase"  or die "can't write: $!";
+	close FH                or die "can't close: status=$?";
+    } else {
+	system("$command") == 0 
+	    or die "system $command failed: $?";
+    }
+
+    if (!($fileout =~ /^\-$/)) {
+	my $st_old = stat($file1) 
+	    or die "No file $file1: $!";
+	my $st_new = stat($fileout) 
+	    or die "No file $fileout: $!";
+	die ("Signed file is smaller than unsigned file") 
+	    unless ($st_new->size > $st_old->size);
+	move("$fileout", "$file2") 
+	    or die "Move $fileout to $file2 failed: $!";
+	chmod $stats->mode, $file2;
+	chown $stats->uid, $stats->gid, $file2;
+	flock(LOCKFILE, LOCK_UN);
+    }
+
+    if ($flag1 == 1) {
+	unlink0( $fh1, $filename1 ) or die "Cannot unlink $filename1 safely";
+    }
+    if ($return_from_sign == 1) {
+	return;
+    }
+    exit;
+}
+
+Getopt::Long::Configure ("posix_default");
+Getopt::Long::Configure ("bundling");
+# Getopt::Long::Configure ("debug");
+
+GetOptions (\%opts, 'm=s', 'h|help', 'v|verbose', 'l|list',
+	    'c|cfgfile=s',
+	    'd|datafile=s',
+	    'p|passphrase=s',
+	    's|secretkey=s',
+            'k|keyid=s',
+	    'create-cfgfile',  # -m F
+	    'print-cfgfile',   # -m f
+	    'create-datafile', # -m D
+	    'print-datafile',  # -m d
+	    'remove-signature',# -m R
+	    'sign',            # -m E
+	    'examine',         # -m e
+	    'generate-keys');  # -m G
+
+if (defined ($opts{'h'})) {
+    usage();
+    exit;
+}
+
+if (defined($opts{'k'})) {
+    $KEYID = $opts{'k'};
+}
+if (defined($opts{'c'})) {
+    $cfgfile = $opts{'c'};
+}
+if (defined($opts{'d'})) {
+    $datafile = $opts{'d'};
+}
+if (defined($opts{'p'})) {
+    $passphrase = $opts{'p'};
+}
+if (defined($opts{'s'})) {
+    $SIGDIR = $opts{'s'};
+}
+
+if (defined ($opts{'m'}) && ($opts{'m'} =~ /[FfDdREeG]{1}/) ) {
+    $action = $opts{'m'};
+}
+elsif (defined ($opts{'create-cfgfile'})) {
+    $action = 'F';
+}
+elsif (defined ($opts{'print-cfgfile'})) {
+    $action = 'f';
+}
+elsif (defined ($opts{'create-datafile'})) {
+    $action = 'D';
+}
+elsif (defined ($opts{'print-datafile'})) {
+    $action = 'd';
+}
+elsif (defined ($opts{'remove-signature'})) {
+    $action = 'R';
+}
+elsif (defined ($opts{'sign'})) {
+    $action = 'E';
+}
+elsif (defined ($opts{'examine'})) {
+    $action = 'e';
+}
+elsif (defined ($opts{'generate-keys'})) {
+    $action = 'G';
+}
+else {
+    usage();
+    die ("No valid action specified !");
+}
+
+if (defined($ARGV[0])) {
+    $file1 = $ARGV[0];
+} 
+if (defined($ARGV[1])) {
+    $file2 = $ARGV[1];
+} 
+
+
+if (($action =~ /[REe]{1}/) && !defined($file1)) {
+    usage();
+    die("Option -m $action requires a filename (or '-' for stdio)\n");
+}
+
+if ($action =~ /^F$/) {
+    if (!defined($file1)) {
+	$file1 = $cfgfile;
+    }
+    $file2 = $cfgfile;
+    sign_file ();
+}
+
+if ($action =~ /^D$/) {
+    if (!defined($file1)) {
+	$file1 = $datafile;
+    }
+    $file2 = $datafile;
+    sign_file ();
+}
+
+if ($action =~ /^R$/) {
+    # $file1 defined
+    my $i = 0;
+    while (defined($ARGV[$i])) {
+	$file1 = $ARGV[$i];
+	remove ();
+	++$i;
+    }
+}
+
+if ($action =~ /^E$/) {
+    # $file1 defined
+    # default: $file2 = $file1
+    check_signify_sign();
+    my $i = 0;
+    while (defined($ARGV[$i])) {
+	$file1 = $ARGV[$i];
+	$file2 = $file1;
+	$return_from_sign = 1;
+	sign_file ();
+	++$i;
+    }
+}
+
+if ($action =~ /^e$/) {
+    # $file1 defined
+    # default: $file2 = stdout
+    check_signify_verify();
+    my $i = 0;
+    my $ret = 0;
+    while (defined($ARGV[$i])) {
+	print "\n";
+	$file1 = $ARGV[$i];
+	$ret += examine ();
+	++$i;
+	print "\n--------------------------------\n" if (defined($ARGV[$i]));
+    }
+    exit($ret);
+}
+
+if ($action =~ /^f$/) {
+    $file1 = $cfgfile;
+    $file2 = "-";
+    print_cfgfile ();
+}
+
+if ($action =~ /^d$/) {
+    # $file1 irrelevant
+    if (defined($opts{'l'})) {
+	print_datafile ();
+    } else {
+	$file1 = $datafile;
+	$file2 = "-";
+	print_cfgfile ();
+    }
+}
+
+
+
Index: trunk/scripts/samhainadmin.pl.in
===================================================================
--- trunk/scripts/samhainadmin.pl.in	(revision 495)
+++ 	(revision )
@@ -1,726 +1,0 @@
-#! /usr/bin/perl
-
-# Copyright Rainer Wichmann (2004)
-#
-# License Information:
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-use warnings;
-use strict;
-use Getopt::Long;
-use File::Basename;
-use File::Copy;
-use File::stat;
-use File::Temp qw/ tempfile tempdir unlink0 /;
-use IO::Handle;
-use Fcntl qw(:DEFAULT :flock);
-use Tie::File;
-
-# Do I/O to the data file in binary mode (so it 
-# wouldn't complain about invalid UTF-8 characters).
-use bytes;
-
-File::Temp->safe_level( File::Temp::HIGH );
-
-my %opts = ();
-my $action;
-my $file1;
-my $file2;
-my $passphrase;
-my $secretkeyring;
-my $return_from_sign = 0;
-my $no_print_examine = 0;
-my $no_remove_lock   = 0;
-my $base = basename($0);
-
-my $cfgfile  = "@myconffile@";
-my $datafile = "@mydatafile@";
-my $daemon   = "@sbindir@/@install_name@";
-my $gpg      = "@mygpg@";
-
-my $TARGETKEYID = "@mykeyid@";
-my $KEYTAG      = "@mykeytag@";
-
-$cfgfile  =~ s/^REQ_FROM_SERVER//;
-$datafile =~ s/^REQ_FROM_SERVER//;
-
-$gpg = "gpg" if ($gpg eq "");
-
-sub check_gpg_agent() {
-    my  $gpgconf = "$ENV{'HOME'}/.gnupg/gpg.conf";
-
-    if (!-f "$gpgconf") {
-	$gpgconf = "$ENV{'HOME'}/.gnupg/options";
-    }
-
-    if (-f $gpgconf) {
-
-	my @array = ();
-	tie @array, 'Tie::File', $gpgconf or die "Cannot tie ${gpgconf}: $!";
-	my @grep = grep(/^\s*use-agent/, @array);
-	
-	# print "matches = $#grep\n";
-	
-	if ($#grep >= 0)
-	{
-	    if (exists $ENV{'GPG_AGENT_INFO'})
-	    {
-		my $socke = $ENV{'GPG_AGENT_INFO'};
-		$socke =~ s/:.*//;
-		
-		# print "socke = $socke\n";
-		
-		if (! -S $socke)
-		{
-		    print "--------------------------------------------------\n";
-		    print "\n";
-		    print " GPG is set to use gpg-agent, but GPG agent is";
-		    print " not running, though GPG_AGENT_INFO is defined.\n\n";
-		    print " Please restart gpg-agent, or remove the use-agent\n";
-		    print " option from ${gpgconf} and unset GPG_AGENT_INFO\n\n";
-		    print "--------------------------------------------------\n";
-		    print "\n";
-		    exit 1;
-		}
-	    }
-	    else
-	    {
-		print "--------------------------------------------------\n";
-		print "\n";
-		print " GPG is set to use gpg-agent, but ";
-		print " GPG_AGENT_INFO is not defined.\n\n";
-		print " Please start gpg-agent, or remove the use-agent\n";
-		print " option from ${gpgconf}\n\n";
-		print "--------------------------------------------------\n";
-		print "\n";
-		exit 1;
-	    }
-	}
-	untie @array;
-    }
-}
-
-
-sub usage() {
-    print "Usage:\n";
-    print "  $base { -m F | --create-cfgfile }    [options] [in.cfgfile]\n";
-    print "    Sign the configuration file. If in.cfgfile is given, sign it\n";
-    print "    and install it as configuration file.\n\n";
-
-    print "  $base { -m f | --print-cfgfile }     [options] \n";
-    print "    Print the configuration file to stdout. Signatures are removed.\n\n";
-
-    print "  $base { -m D | --create-datafile }   [options] [in.datafile]\n";
-    print "    Sign the database file. If in.datafile is given, sign it\n";
-    print "    and install it as database file.\n\n";
-
-    print "  $base { -m d | --print-datafile }    [options] \n";
-    print "    Print the database file to stdout. Signatures are removed. Use\n";
-    print "    option --list to list files in database rather than printing the raw file.\n\n";
-
-    print "  $base { -m R | --remove-signature }  [options] file1 [file2 ...]\n";
-    print "    Remove cleartext signature from input file(s). The file\n";
-    print "    is replaced by the non-signed file.\n\n";
-
-    print "  $base { -m E | --sign }              [options] file1 [file2 ...]\n";
-    print "    Sign file(s) with a cleartext signature. The file\n";
-    print "    is replaced by the signed file.\n\n";
-
-    print "  $base { -m e | --examine }           [options] file1 [file2 ...]\n";
-    print "    Report signature status of file(s).\n\n";
-
-    print "  $base { -m G | --generate-keys }     [options] \n";
-    print "    Generate a PGP keypair to use for signing.\n\n";
-
-    print "Options:\n";
-    print "  -c cfgfile    --cfgfile cfgfile\n";
-    print "    Select an alternate configuration file.\n\n";
-
-    print "  -d datafile   --datafile datafile\n";
-    print "    Select an alternate database file.\n\n";
-
-    print "  -p passphrase --passphrase passphrase\n";
-    print "    Set the passphrase for gpg. By default, gpg will ask.\n\n";
-
-    print "  -s gnupg_homedir --secretkeyring gnupg_homedir\n";
-    print "    Select an alternate gpg homedirectory to locate the secret keyring.\n";
-    print "    Will use '$ENV{'HOME'}/.gnupg/' by default.\n\n";
-
-    print "  -k keyid      --keyid keyid\n";
-    print "   Select the keyid to use for signing.\n\n";
-
-    print "  -l            --list\n";
-    print "    List the files in database rather than printing the raw file.\n\n";
-
-    print "  -v            --verbose\n";
-    print "    Verbose output.\n\n";
-    return;
-}
-
-sub check_gpg_uid () {
-    if (0 != $>) {
-	print "--------------------------------------------------\n";
-	print "\n";
-	print " You are not root. Please remember that samhain/yule\n";
-	print " will use the public keyring of root to verify a signature.\n";
-	print "\n";
-	print "--------------------------------------------------\n";
-    } else {
-	if (!("@yulectl_prg@" =~ //)) {
-	    print "--------------------------------------------------\n";
-	    print "\n";
-	    print " Please remember that yule will drop root after startup. Signature\n";
-	    print " verification on SIGHUP will fail if you do not import the public key\n";
-	    print " into the keyring of the non-root yule user.\n";
-	    print "\n";
-	    print "--------------------------------------------------\n";
-	}
-    }
-}
-    
-sub check_gpg_sign () {
-    if ( defined($secretkeyring)) {
-        if ( (!-d "$secretkeyring")){
-            print "--------------------------------------------------\n";
-            print "\n";
-            print " Secret keyring $secretkeyring not found!\n";
-            print "\n";
-            print " Please check the path/name of the alternate secret keyring.\n";
-            print "\n";
-            print "--------------------------------------------------\n";
-            print "\n";
-            exit;
-        }
-    } else {
-        if ( (!-d "$ENV{'HOME'}/.gnupg") || (!-e "$ENV{'HOME'}/.gnupg/secring.gpg")) {
-	    print "--------------------------------------------------\n";
-	    print "\n";
-	    if (!-d "$ENV{'HOME'}/.gnupg") {
-	        print " Directory \$HOME/.gnupg not found!\n";
-	    } else {
-	        print " Secret keyring \$HOME/.gnupg/secring.gpg not found!\n";
-	    }
-	    print "\n";
-	    print " This indicates that you have never created a \n";
-	    print " public/private keypair, and thus cannot sign.\n";
-	    print " \n";
-	    print " Please use $0 --generate-keys or gpg --gen-key\n";
-	    print " to generate a public/private keypair first.\n";
-	    print "\n";
-	    print "--------------------------------------------------\n";
-	    print "\n";
-	    exit;
-        }
-    }
-}
-
-sub check_gpg_verify () {
-    if ( (!-d "$ENV{'HOME'}/.gnupg") || (!-e "$ENV{'HOME'}/.gnupg/pubring.gpg")) {
-	print "--------------------------------------------------\n";
-	print "\n";
-	if (!-d "$ENV{'HOME'}/.gnupg") {
-	    print " Directory \$HOME/.gnupg not found!\n";
-	} else {
-	    print " Public keyring \$HOME/.gnupg/pubring.gpg not found!\n";
-	}
-	print "\n";
-	print " This indicates that you have never used gpg before \n";
-	print " and/or have no public keys to verify signatures.\n";
-	print " \n";
-	print " Please use 'gpg --export key_id' to export the public\n";
-	print " signing key of the user who is signing the\n";
-	print " configuration/database files.\n\n";
-	print " Then you can use 'gpg --import keyfile' to import the key\n";
-	print " into this user's public keyring.\n";
-	print "\n";
-	print "--------------------------------------------------\n";
-	print "\n";
-	exit;
-    }
-}
-
-
-sub generate () {
-    my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --gen-key";
-    check_gpg_uid();
-    system ($command) == 0 
-	or die "system $command failed: $?";
-    exit;
-}
-
-sub examine () {
-    my $iscfg = 0;
-    my $have_fp  = 0;
-    my $have_sig = 0;
-    my $message = '';
-    my $retval  = 9;
-    my $fh;
-    my $filename;
-
-    if (!($file1 =~ /^\-$/)) {
-	die ("Cannot open $file1 for read: $!") unless ((-e $file1) && (-r _));
-    }
-    open FIN,  "<$file1" or die "Cannot open $file1 for read: $!";
-
-    my $dir = tempdir( CLEANUP => 1 );
-    $filename = $dir . "/exa_jhfdbilw." . $$;
-    open $fh, ">$filename" or die "Cannot open $filename";
-    autoflush $fh 1;
-
-    while (<FIN>) {
-	print $fh $_;
-	if ($_ =~ /^\s*\[Misc\]/) {
-	    $iscfg = 1;
-	}
-    }
-    if ($iscfg == 1) {
-	$message .=  "File $file1 is a configuration file\n\n";
-    } else {
-	$message .=  "File $file1 is a database file\n\n";
-    }
-
-
-    my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --status-fd 1 ";
-    $command .= "--verbose " if (defined($opts{'v'}));
-    $command .= "--verify $filename ";
-    if (defined($opts{'v'})) {
-	$command .= "2>&1";
-    } else {
-	$command .= "2>/dev/null";
-    }
-
-    print STDOUT "Using: $command\n\n" if (defined($opts{'v'}));
-    open  GPGIN, "$command |" or die "Cannot fork: $!";
-
-    while (<GPGIN>) {
-	if ($_ =~ /^\[GNUPG:\] GOODSIG ([0-9A-F]+) (.*)$/) {
-	    $message .= "GOOD signature with key: $1\n";
-	    $message .= "Key owner:               $2\n";
-	    $have_sig = 1;
-	    $retval   = 0;
-	}
-	if ($_ =~ /^\[GNUPG:\] VALIDSIG ([0-9A-F]+) ([0-9\-]+)\s/) {
-	    $message .= "Key fingerprint:         $1\n";
-	    $message .= "Signature generated on:  $2\n\n";
-	    $have_fp = 1;
-	    $message .=  "This file is signed with a valid signature.\n" 
-		if ($have_sig == 1);
-	    $have_sig = 1;
-	    $have_fp = 1;
-	}
-	if ($_ =~ /^\[GNUPG:\] NODATA 1/) {
-	    $message .=  "NO signature found.\n\n";
-	    $message .=  "This file is not signed !!!\n";
-	    $have_sig = 1;
-	    $have_fp = 1;
-	    $retval  = 2;
-	}
-	if ($_ =~ /^\[GNUPG:\] BADSIG ([0-9A-F]+) (.*)$/) {
-	    $message .=  "BAD signature with key: $1\n";
-	    $message .=  "Key owner:              $2\n\n";
-	    $message .=  "This file is signed with an invalid signature !!!\n";
-	    $have_sig = 1;
-	    $have_fp = 1;
-	    $retval = 1;
-	}
-	if ($_ =~ /^\[GNUPG:\] NO_PUBKEY ([0-9A-F]+)/) {
-	    $message .=  "NOT CHECKED signature with key: $1\n\n";
-	    $message .=  "The signature of this file cannot be checked: no public key available !!!\n";
-	    $have_sig = 1;
-	    $have_fp = 1;
-	    $retval  = 1;
-	}
-	print STDOUT $_ if (defined($opts{'v'}));
-    }
-    close (GPGIN);
-    print STDOUT "\n" if (defined($opts{'v'}));
-    if ($have_sig == 0) {
-	$message .=  "NO valid signature found\n";
-    } 
-    elsif ($have_fp == 0) {
-	$message .=  "NO fingerprint found\n";
-    }
-    close (FIN);
-    if ($no_print_examine == 0) {
-	print STDOUT $message;
-    }
-    unlink0( $fh, $filename ) or die "Cannot unlink $filename safely";
-    return $retval;
-}
-
-sub remove () {
-    my $bodystart = 1;
-    my $sigstart  = 0;
-    my $sigend    = 0;
-    my $filename  = "";
-    my $fh;
-    my $stats;
-
-    open FH, "<$file1" or die "Cannot open file $file1 for read: $!";
-    if (!($file1 =~ /^\-$/)) {
-	flock(FH, LOCK_EX) unless ($no_remove_lock == 1);
-	my $dir = tempdir( CLEANUP => 1 ) or die "Tempdir failed";
-	$filename = $dir . "/rem_iqegBCQb." . $$;
-	open $fh, ">$filename" or die "Cannot open $filename";
-	$stats = stat($file1);
-	# ($fh, $filename) = tempfile(UNLINK => 1);
-    } else {
-	open $fh, ">$file1" or die "Cannot open file $file1 for write: $!";
-    }
-    autoflush $fh 1;
-    while (<FH>) {
-	if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) {
-	    $sigstart = 1;
-	    $bodystart = 0;
-	    next;
-	} elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) {
-	    $sigstart = 0;
-	    $bodystart = 1;
-	    next;
-	} elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) {
-	    $bodystart = 0;
-	    $sigend = 1;
-	    next;
-	} elsif (($sigend == 1) && ($_ =~ /^-----END PGP SIGNATURE-----/)) {
-	    $sigend = 0;
-	    $bodystart = 1;
-	    next;
-	}
-	if ($bodystart == 1) {
-	    print $fh $_;
-	}
-    }
-    if (!($file1 =~ /^\-$/)) {
-	copy("$filename", "$file1") 
-	    or die "Copy $filename to $file1 failed: $!";
-	chmod $stats->mode, $file1;
-	chown $stats->uid, $stats->gid, $file1;
-	flock(FH, LOCK_UN) unless ($no_remove_lock == 1);
-	close FH;
-    }
-    unlink0( $fh, $filename ) or die "Cannot unlink $filename safely";
-    return;
-}
-
-sub print_cfgfile () {
-    my $bodystart = 0;
-    my $sigstart  = 0;
-
-    if (!defined($file2)) {
-	$file2 = '-';
-    }
-
-    open FH, "<$file1" or die "Cannot open file $file1 for read: $!";
-    open FO, ">$file2" or die "Cannot open file $file2 for write: $!";
-    while (<FH>) {
-	if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) {
-	    $sigstart = 1;
-	    next;
-	} elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) {
-	    $sigstart = 0;
-	    $bodystart = 1;
-	    next;
-	} elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) {
-	    $bodystart = 0;
-	    exit;
-	}
-	if ($bodystart == 1) {
-	    print FO $_;
-	}
-    }
-    exit;
-}
-sub print_datafile () {
-    die ("Cannot find program $daemon") 
-	unless (-e $daemon);
-    if (defined($opts{'v'})) {
-	open FH, "$daemon --full-detail -d $datafile |" 
-	    or die "Cannot open datafile $datafile for read: $!";
-    } else {
-	open FH, "$daemon -d $datafile |" 
-	    or die "Cannot open datafile $datafile for read: $!";
-    }
-    while (<FH>) {
-	print $_;
-    }
-    exit;
-}
-
-sub sign_file () {
-
-    my $fileout = '';
-    my $bodystart = 1;
-    my $sigstart  = 0;
-    my $sigend    = 0;
-    my $stats;
-    my $fh1;
-    my $filename1;
-    my $flag1     = 0;
-
-    check_gpg_uid();
-    check_gpg_agent();
-
-    if (!defined($file2)) {
-	$file2 = $file1;
-    }
-
-    if ($file1 =~ /^\-$/) {
-	my $dir = tempdir( CLEANUP => 1 ) or die "Tempdir failed";
-	$filename1 = $dir . "/sig_vs8827sd." . $$;
-	open $fh1, ">$filename1" or die "Cannot open $filename1";
-	$flag1 = 1;
-	# my ($fh1, $filename1) = tempfile(UNLINK => 1);
-
-	while (<STDIN>) {
-	  if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) {
-	    $sigstart = 1;
-	    $bodystart = 0;
-	    next;
-	  } elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) {
-	    $sigstart = 0;
-	    $bodystart = 1;
-	    next;
-	  } elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) {
-	    $bodystart = 0;
-	    $sigend = 1;
-	    next;
-	  } elsif (($sigend == 1) && ($_ =~ /^-----END PGP SIGNATURE-----/)) {
-	    $sigend = 0;
-	    $bodystart = 1;
-	    next;
-	  }
-	  if ($bodystart == 1) {
-	    print $fh1 $_;
-	  }
-	  #
-	  # print $fh1 $_;
-	  #
-	}
-	$file1 = $filename1;
-	$fileout = '-';
-    } else {
-	open (LOCKFILE, "<$file1") or die "Cannot open $file1: $!";
-	flock(LOCKFILE, LOCK_EX);
-	$no_print_examine = 1;
-	$no_remove_lock   = 1;
-	if (examine() < 2) {
-	    remove();
-	}
-	$fileout = $file1 . ".asc";
-	$stats   = stat($file1)
-	    or die "No file $file1: $!";
-    }
-
-    if (defined($passphrase)) {
-	local $SIG{PIPE} = 'IGNORE';
-	my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --passphrase-fd 0 -a ${KEYTAG} ${TARGETKEYID} --clearsign -o $fileout --not-dash-escaped ";
-        $command .= "--secret-keyring $secretkeyring " if (defined($opts{'s'}));
-	$command .= "$file1";
-	open (FH, "|$command")  or die "can't fork: $!";
-	print FH "$passphrase"  or die "can't write: $!";
-	close FH                or die "can't close: status=$?";
-    } else {
-	my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg                   -a ${KEYTAG} ${TARGETKEYID} --clearsign -o $fileout --not-dash-escaped ";
-        $command .= "--secret-keyring $secretkeyring " if (defined($opts{'s'}));
-	$command .= "$file1";
-	system("$command") == 0 
-	    or die "system $command failed: $?";
-    }
-
-    if (!($fileout =~ /^\-$/)) {
-	my $st_old = stat($file1) 
-	    or die "No file $file1: $!";
-	my $st_new = stat($fileout) 
-	    or die "No file $fileout: $!";
-	die ("Signed file is smaller than unsigned file") 
-	    unless ($st_new->size > $st_old->size);
-	move("$fileout", "$file2") 
-	    or die "Move $fileout to $file2 failed: $!";
-	chmod $stats->mode, $file2;
-	chown $stats->uid, $stats->gid, $file2;
-	flock(LOCKFILE, LOCK_UN);
-    }
-
-    if ($flag1 == 1) {
-	unlink0( $fh1, $filename1 ) or die "Cannot unlink $filename1 safely";
-    }
-    if ($return_from_sign == 1) {
-	return;
-    }
-    exit;
-}
-
-Getopt::Long::Configure ("posix_default");
-Getopt::Long::Configure ("bundling");
-# Getopt::Long::Configure ("debug");
-
-GetOptions (\%opts, 'm=s', 'h|help', 'v|verbose', 'l|list',
-	    'c|cfgfile=s',
-	    'd|datafile=s',
-	    'p|passphrase=s',
-	    's|secretkeyring=s',
-            'k|keyid=s',
-	    'create-cfgfile',  # -m F
-	    'print-cfgfile',   # -m f
-	    'create-datafile', # -m D
-	    'print-datafile',  # -m d
-	    'remove-signature',# -m R
-	    'sign',            # -m E
-	    'examine',         # -m e
-	    'generate-keys');  # -m G
-
-if (defined ($opts{'h'})) {
-    usage();
-    exit;
-}
-
-if (defined($opts{'k'})) {
-    $TARGETKEYID = $opts{'k'};
-    $KEYTAG = "--default-key";
-}
-if (defined($opts{'c'})) {
-    $cfgfile = $opts{'c'};
-}
-if (defined($opts{'d'})) {
-    $datafile = $opts{'d'};
-}
-if (defined($opts{'p'})) {
-    $passphrase = $opts{'p'};
-}
-if (defined($opts{'s'})) {
-    $secretkeyring = $opts{'s'};
-}
-
-if (defined ($opts{'m'}) && ($opts{'m'} =~ /[FfDdREeG]{1}/) ) {
-    $action = $opts{'m'};
-}
-elsif (defined ($opts{'create-cfgfile'})) {
-    $action = 'F';
-}
-elsif (defined ($opts{'print-cfgfile'})) {
-    $action = 'f';
-}
-elsif (defined ($opts{'create-datafile'})) {
-    $action = 'D';
-}
-elsif (defined ($opts{'print-datafile'})) {
-    $action = 'd';
-}
-elsif (defined ($opts{'remove-signature'})) {
-    $action = 'R';
-}
-elsif (defined ($opts{'sign'})) {
-    $action = 'E';
-}
-elsif (defined ($opts{'examine'})) {
-    $action = 'e';
-}
-elsif (defined ($opts{'generate-keys'})) {
-    $action = 'G';
-}
-else {
-    usage();
-    die ("No valid action specified !");
-}
-
-if (defined($ARGV[0])) {
-    $file1 = $ARGV[0];
-} 
-if (defined($ARGV[1])) {
-    $file2 = $ARGV[1];
-} 
-
-
-if (($action =~ /[REe]{1}/) && !defined($file1)) {
-    usage();
-    die("Option -m $action requires a filename (or '-' for stdio)\n");
-}
-
-if ($action =~ /^F$/) {
-    if (!defined($file1)) {
-	$file1 = $cfgfile;
-    }
-    $file2 = $cfgfile;
-    sign_file ();
-}
-
-if ($action =~ /^D$/) {
-    if (!defined($file1)) {
-	$file1 = $datafile;
-    }
-    $file2 = $datafile;
-    sign_file ();
-}
-
-if ($action =~ /^R$/) {
-    # $file1 defined
-    my $i = 0;
-    while (defined($ARGV[$i])) {
-	$file1 = $ARGV[$i];
-	remove ();
-	++$i;
-    }
-}
-
-if ($action =~ /^E$/) {
-    # $file1 defined
-    # default: $file2 = $file1
-    check_gpg_sign();
-    my $i = 0;
-    while (defined($ARGV[$i])) {
-	$file1 = $ARGV[$i];
-	$file2 = $file1;
-	$return_from_sign = 1;
-	sign_file ();
-	++$i;
-    }
-}
-
-if ($action =~ /^e$/) {
-    # $file1 defined
-    # default: $file2 = stdout
-    check_gpg_verify();
-    my $i = 0;
-    my $ret = 0;
-    while (defined($ARGV[$i])) {
-	print "\n";
-	$file1 = $ARGV[$i];
-	$ret += examine ();
-	++$i;
-	print "\n--------------------------------\n" if (defined($ARGV[$i]));
-    }
-    exit($ret);
-}
-
-if ($action =~ /^f$/) {
-    $file1 = $cfgfile;
-    $file2 = "-";
-    print_cfgfile ();
-}
-
-if ($action =~ /^d$/) {
-    # $file1 irrelevant
-    if (defined($opts{'l'})) {
-	print_datafile ();
-    } else {
-	$file1 = $datafile;
-	$file2 = "-";
-	print_cfgfile ();
-    }
-}
-
-
-
Index: trunk/scripts/yuleadmin.pl.in
===================================================================
--- trunk/scripts/yuleadmin.pl.in	(revision 495)
+++ trunk/scripts/yuleadmin.pl.in	(revision 550)
@@ -38,15 +38,8 @@
 my $base = basename($0);
 
-#my $cfgfile  = "yulerc";
-#my $yule     = "./yule";
-#my $gpg      = "/usr/bin/gpg";
-
 my $cfgfile  = "@myconffile@";
 my $yule     = "@sbindir@/@install_name@";
-my $gpg      = "@mygpg@";
 
 $cfgfile  =~ s/^REQ_FROM_SERVER//;
-
-$gpg = "gpg" if ($gpg eq "");
 
 sub usage() {
