Index: trunk/src/depend-gen.c
===================================================================
--- trunk/src/depend-gen.c	(revision 549)
+++ trunk/src/depend-gen.c	(revision 550)
@@ -245,5 +245,5 @@
 	   *
 	   **************************************************/
-	  if (0 == strcmp(p, "sh_gpg_chksum.h") ||
+	  if (0 == strcmp(p, "sh_sig_chksum.h") ||
 	      0 == strcmp(p, "sh_gpg_fp.h"))
 	    {
Index: trunk/src/samhain.c
===================================================================
--- trunk/src/samhain.c	(revision 549)
+++ trunk/src/samhain.c	(revision 550)
@@ -77,5 +77,5 @@
 
 #include "sh_tiger.h"
-#include "sh_gpg.h"
+#include "sh_sig.h"
 #include "sh_mem.h"
 #include "sh_xfer.h"
@@ -1907,7 +1907,7 @@
 #if defined(SH_WITH_SERVER) && !defined(SH_WITH_CLIENT)
 
-#if (defined(WITH_GPG) || defined(WITH_PGP))
+#if defined(WITH_GPG)
   /* log startup */
-  sh_gpg_log_startup ();
+  sh_sig_log_startup ();
 #else
   sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_1H,
@@ -1930,7 +1930,7 @@
   if (sh.flag.checkSum == SH_CHECK_CHECK) 
     {
-#if (defined(WITH_GPG) || defined(WITH_PGP))
+#if defined(WITH_GPG)
       /* log startup */
-      sh_gpg_log_startup ();
+      sh_sig_log_startup ();
 #else
       sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_2H,
@@ -1942,7 +1942,7 @@
   else
     {
-#if (defined(WITH_GPG) || defined(WITH_PGP))
+#if defined(WITH_GPG)
       /* log startup */
-      sh_gpg_log_startup ();
+      sh_sig_log_startup ();
 #else
       sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_1H,
Index: trunk/src/sh_calls.c
===================================================================
--- trunk/src/sh_calls.c	(revision 549)
+++ trunk/src/sh_calls.c	(revision 550)
@@ -533,6 +533,6 @@
 
 long int retry_aud_execve  (const char * file, int line, 
-			    const  char *dateiname, char * argv[],
-			    char * envp[])
+			    const  char *dateiname, char *const argv[],
+			    char *const envp[])
 {
   uid_t a = geteuid();
Index: trunk/src/sh_dbIO.c
===================================================================
--- trunk/src/sh_dbIO.c	(revision 549)
+++ trunk/src/sh_dbIO.c	(revision 550)
@@ -31,5 +31,5 @@
 #include "sh_hash.h"
 #include "sh_dbIO.h"
-#include "sh_gpg.h"
+#include "sh_sig.h"
 #include "sh_tiger.h"
 #include "sh_xfer.h"
@@ -852,10 +852,10 @@
 static SL_TICKET verify_data (SL_TICKET fd)
 {
-#if defined(WITH_GPG) || defined(WITH_PGP)
+#if defined(WITH_SIG)
   SL_TICKET fdTmp;
 
   /* extract the data and copy to temporary file
    */
-  fdTmp = sh_gpg_extract_signed(fd);
+  fdTmp = sh_sig_extract_signed(fd);
 
   if (sig_termfast == 1)  /* SIGTERM */
@@ -871,5 +871,5 @@
   /* Validate signature of open file.
    */
-  if (0 != sh_gpg_check_sign (fd, SIG_DATA))
+  if (0 != sh_sig_check_signature (fd, SIG_DATA))
     {
       sl_close(fd);
@@ -877,4 +877,8 @@
     }
   sl_rewind (fd);
+
+  fdTmp = sh_sig_extract_signed_data(fd);
+  sl_close(fd);
+  fd = fdTmp;  
 #endif
 
Index: trunk/src/sh_getopt.c
===================================================================
--- trunk/src/sh_getopt.c	(revision 549)
+++ trunk/src/sh_getopt.c	(revision 550)
@@ -481,8 +481,8 @@
 #ifdef WITH_GPG
   if (num > 0) fputc ('\n', stdout);
-  printf (_(" GnuPG signatures (%s)"), DEFAULT_GPG_PATH); ++num;
-#ifdef HAVE_GPG_CHECKSUM
-  if (num > 0) fputc ('\n', stdout);
-  printf (_("   -- GnuPG checksum:  %s"), GPG_HASH); ++num;
+  printf (_(" GnuPG signatures (%s)"), DEFAULT_SIG_PATH); ++num;
+#ifdef HAVE_SIG_CHECKSUM
+  if (num > 0) fputc ('\n', stdout);
+  printf (_("   -- GnuPG checksum:  %s"), SIG_HASH); ++num;
 #endif
 #ifdef USE_FINGERPRINT
Index: trunk/src/sh_gpg.c
===================================================================
--- trunk/src/sh_gpg.c	(revision 549)
+++ 	(revision )
@@ -1,1035 +1,0 @@
-/* SAMHAIN file system integrity testing                                   */
-/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
-/*                                                                         */
-/*  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.              */
-
-#include "config_xor.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-
-#if defined(WITH_GPG) || defined(WITH_PGP)
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#if defined(SH_WITH_SERVER)
-#include <pwd.h>
-#endif
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <sys/wait.h>
-
-#include <string.h>
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-
-
-#if !defined(O_NONBLOCK)
-#if defined(O_NDELAY)
-#define O_NONBLOCK  O_NDELAY
-#else
-#define O_NONBLOCK  0
-#endif
-#endif
-
-
-#include "samhain.h"
-#include "sh_utils.h"
-#include "sh_error.h"
-#include "sh_tiger.h"
-#if defined(SH_WITH_SERVER)
-#define SH_NEED_PWD_GRP 1
-#include "sh_static.h"
-#endif
-#include "sh_gpg.h"
-
-static struct {
-  char     conf_id[SH_MINIBUF+1];
-  char     conf_fp[SH_MINIBUF+1];
-  char     data_id[SH_MINIBUF+1];
-  char     data_fp[SH_MINIBUF+1];
-} gp;
-
-typedef struct {
-  pid_t    pid;
-  FILE   * pipe;
-} sh_gpg_popen_t;
-
-#define SH_GPG_OK      0
-#define SH_GPG_BAD     1
-#define SH_GPG_BADSIGN 2
-
-/* replace #if 0 by #if 1 and set an appropriate path in front of '/pdbg.'
- * for debugging
- */
-#if 0
-#define PDGBFILE "/pdbg."
-#endif
-
-#if defined(PDGBFILE)
-FILE * pdbg;
-FILE * pdbgc;
-#define PDBG_OPEN    pdbg = fopen(PDGBFILE"main",  "a")  
-#define PDBG_CLOSE   sl_fclose (FIL__, __LINE__, pdbg)
-#define PDBG(arg)    fprintf(pdbg,  "PDBG: step %d\n", arg); fflush(pdbg)
-#define PDBG_D(arg)  fprintf(pdbg,  "PDBG: %d\n", arg); fflush(pdbg)
-#define PDBG_S(arg)  fprintf(pdbg,  "PDBG: %s\n", arg); fflush(pdbg)
-
-#define PDBGC_OPEN   pdbgc = fopen(PDGBFILE"child", "a")  
-#define PDBGC_CLOSE  sl_fclose (FIL__, __LINE__, pdbgc)
-#define PDBGC(arg)   fprintf(pdbgc, "PDBG: step %d\n", arg); fflush(pdbgc)
-#define PDBGC_D(arg) fprintf(pdbgc, "PDBG: %d\n", arg); fflush(pdbgc)
-#define PDBGC_S(arg) fprintf(pdbgc, "PDBG: %s\n", arg); fflush(pdbgc)
-#else
-#define PDBG_OPEN    
-#define PDBG_CLOSE   
-#define PDBG(arg)    
-#define PDBG_D(arg)  
-#define PDBG_S(arg)  
-#define PDBGC_OPEN    
-#define PDBGC_CLOSE   
-#define PDBGC(arg)    
-#define PDBGC_D(arg)  
-#define PDBGC_S(arg)  
-#endif
-
-#undef  FIL__
-#define FIL__  _("sh_gpg.c")
-
-#ifdef GPG_HASH
-
-static int sh_gpg_checksum (SL_TICKET checkfd, int flag)
-{
-  char * test_gpg;
-  char * test_ptr1 = NULL;
-  char * test_ptr2 = NULL;
-  char   wstrip1[128];
-  char   wstrip2[128];
-  int    i, k;
-#include "sh_gpg_chksum.h"
-
-  SL_ENTER(_("sh_gpg_checksum"));
-
-  test_gpg = sh_tiger_hash_gpg (DEFAULT_GPG_PATH, checkfd, TIGER_NOLIM);
-  
-  test_ptr1 = strchr(GPG_HASH, ':');
-  if (test_gpg != NULL)
-    test_ptr2 = strchr(test_gpg, ':');
-  
-  if (test_ptr2 != NULL)
-    test_ptr2 += 2;
-  else
-    test_ptr2 = test_gpg;
-  if (test_ptr1 != NULL)
-    test_ptr1 += 2;
-  else
-    test_ptr1 = GPG_HASH;
-
-  /* Tue Jun 24 23:11:54 CEST 2003 (1.7.9) -- strip whitespace
-   */
-  k = 0;
-  for (i = 0; i < 127; ++i)
-    {
-      if (test_ptr1[i] == '\0')
-	break;
-      if (test_ptr1[i] != ' ')
-	{
-	  wstrip1[k] = test_ptr1[i];
-	  ++k;
-	}
-    }
-  wstrip1[k] = '\0';
-
-  for(i = 0; i < KEY_LEN; ++i)
-    {
-      if (gpgchk[i] != wstrip1[i]) 
-	{
-	  sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_E_GPG_CHK, 
-			  gpgchk, wstrip1);
-	  break;
-	}
-    }
-
-  k = 0;
-  if (test_ptr2)
-    {
-      for (i = 0; i < 127; ++i)
-	{
-	  if (test_ptr2[i] == '\0')
-	    break;
-	  if (test_ptr2[i] != ' ')
-	    {
-	      wstrip2[k] = test_ptr2[i];
-	      ++k;
-	    }
-	}
-    }
-  wstrip2[k] = '\0';
-
-  if (0 != sl_strncmp(wstrip1, wstrip2, 127))
-    {
-      TPT(((0), FIL__, __LINE__, _("msg=<pgp checksum: %s>\n"), test_gpg));
-      TPT(((0), FIL__, __LINE__, _("msg=<Compiled-in : %s>\n"), GPG_HASH));
-      TPT(((0), FIL__, __LINE__, _("msg=<wstrip1     : %s>\n"), wstrip1));
-      TPT(((0), FIL__, __LINE__, _("msg=<wstrip2     : %s>\n"), wstrip2));
-      if (flag == 1)
-	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_GPG, 
-			GPG_HASH, test_gpg);
-      dlog(1, FIL__, __LINE__, _("The compiled-in checksum of the gpg binary\n(%s)\ndoes not match the actual checksum\n(%s).\nYou need to recompile with the correct checksum."), wstrip1, wstrip2);
-      SH_FREE(test_gpg);
-      SL_RETURN((-1), _("sh_gpg_checksum"));
-    }
-  SH_FREE(test_gpg);
-  SL_RETURN( (0), _("sh_gpg_checksum"));
-}
-#endif
-
-struct startup_info {
-  long   line;
-  char * program;
-  long   uid;
-  char * path;
-  char * key_uid;
-  char * key_id;
-};
-
-static struct startup_info startInfo = { 0, NULL, 0, NULL, NULL, NULL };
-
-void sh_gpg_log_startup (void)
-{
-  if (startInfo.program != NULL)
-    {
-      sh_error_handle ((-1), FIL__, startInfo.line, 0, MSG_START_GH,
-		       startInfo.program, startInfo.uid,
-		       startInfo.path,
-		       startInfo.key_uid, startInfo.key_id);
-    }
-  return;
-}
-
-static void sh_gpg_fill_startup (long line, char * program, long uid, char * path, 
-				 char * key_uid, char * key_id)
-{
-  startInfo.line    = line;
-  startInfo.program = sh_util_strdup(program);
-  startInfo.uid     = uid;
-  startInfo.path    = sh_util_strdup(path);
-  startInfo.key_uid = sh_util_strdup(key_uid);
-  startInfo.key_id  = sh_util_strdup(key_id);
-  return;
-}
-
-static FILE * sh_gpg_popen (sh_gpg_popen_t  *source, int fd, 
-			    int mode, char * id, char * homedir)
-{
-  extern int flag_err_debug;
-  int pipedes[2];
-  FILE * outf = NULL;
-  char * envp[2];
-  size_t len;
-  char   path[256];
-  char   cc1[32];
-  char   cc2[32];
-
-  char   cc0[2] = "-";
-  char   cc3[32];
-  char   cc4[SH_PATHBUF+32];
-  char   cc5[32];
-
-
-  char * arg[9];
-
-#if defined(HAVE_GPG_CHECKSUM)
-  SL_TICKET   checkfd = -1;
-  int         myrand;
-  int         i;
-#if defined(__linux__)
-  int         get_the_fd(SL_TICKET);
-  char        pname[128];
-  int         pfd;
-  int         val_return;
-#endif
-#endif
-
-  SL_ENTER(_("sh_gpg_popen"));
-
-  /* -- GnuPG -- */
-  sl_strlcpy (path,  DEFAULT_GPG_PATH,  256);
-  sl_strlcpy (cc1,   _("--status-fd"),  32);
-  sl_strlcpy (cc2,   _("--verify"),     32);
-  sl_strlcpy (cc3,   _("--homedir"),    32);
-  /* sl_strlcpy (cc4,   sh.effective.home, SH_PATHBUF+32); */
-  sl_strlcpy (cc4,   homedir,           SH_PATHBUF+32);
-  sl_strlcat (cc4,   _("/.gnupg"),      SH_PATHBUF+32);
-  sl_strlcpy (cc5,   _("--no-tty"),     32);
-
-  /* fprintf(stderr, "YULE: homedir=%s\n", homedir); */
-
-#if defined(SH_WITH_SERVER)
-  if (0 == sl_ret_euid())   /* privileges not dropped yet */
-    {
-      struct stat lbuf;
-      int         status_stat = 0;
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
-      struct passwd    pwd;
-      char          *  buffer = SH_ALLOC(SH_PWBUF_SIZE);
-      struct passwd *  tempres;
-      sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
-#else
-      struct passwd * tempres = sh_getpwnam(DEFAULT_IDENT);
-#endif
-
-      if (!tempres)
-	{
-	  dlog(1, FIL__, __LINE__, 
-	       _("User %s does not exist. Please add the user to your system.\n"), 
-	       DEFAULT_IDENT);
-	  status_stat = -1;
-	}
-      if (!tempres->pw_dir || tempres->pw_dir[0] == '\0')
-	{
-	  dlog(1, FIL__, __LINE__, 
-	       _("User %s does not have a home directory.\nPlease add the home directory for this user to your system.\n"), 
-	       DEFAULT_IDENT);
-	  status_stat = -2;
-	}
-      if (status_stat == 0)
-	{
-	  sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32); 
-	  sl_strlcat (cc4,   _("/.gnupg"),      SH_PATHBUF+32); 
-	  status_stat =  retry_lstat(FIL__, __LINE__, cc4, &lbuf);
-	  if (status_stat == -1)
-	    {
-	      dlog(1, FIL__, __LINE__, 
-		   _("Gnupg directory %s for user %s\ndoes not exist or is not accessible.\nPlease add the directory and put the keyring (pubring.gpg) there\nto verify the configuration file.\n"),
-		   cc4, DEFAULT_IDENT);
-	      status_stat = -3;
-	    }
-	}
-      if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid)
-	{
-	  dlog(1, FIL__, __LINE__, 
-	       _("Gnupg directory %s\nis not owned by user %s.\n"), 
-	       cc4, DEFAULT_IDENT);
-	  status_stat = -4;
-	}
-      if (status_stat == 0)
-	{
-	  sl_strlcat (cc4,   _("/pubring.gpg"),      SH_PATHBUF+32); 
-	  status_stat =  retry_lstat(FIL__, __LINE__, cc4, &lbuf);
-	  if (status_stat == -1)
-	    {
-	      dlog(1, FIL__, __LINE__, 
-		   _("Gnupg public keyring %s for user %s\ndoes not exist or is not accessible.\nPlease add the directory and put the keyring (pubring.gpg) there\nto verify the configuration file.\n"),
-		   cc4, DEFAULT_IDENT);
-	      status_stat = -5;
-	    }
-	}
-      if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid)
-	{
-	  dlog(1, FIL__, __LINE__, 
-	       _("Gnupg public keyring %s\nis not owned by user %s.\n"), 
-	       cc4, DEFAULT_IDENT);
-	  status_stat = -6;
-	}
-      if (status_stat != 0)
-	{
-	  sh_error_handle((-1), FIL__, __LINE__, status_stat, MSG_EXIT_ABORT1, 
-			  sh.prg_name);
-	  aud_exit (FIL__, __LINE__, EXIT_FAILURE);
-	}
-      sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32); 
-      sl_strlcat (cc4,   _("/.gnupg"),      SH_PATHBUF+32); 
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
-      SH_FREE(buffer);
-#endif
-    }
-#endif
-
-  arg[0] = path; 
-  arg[1] = cc1;
-  arg[2] = "1";
-  arg[3] = cc2;
-  arg[4] = cc3;
-  arg[5] = cc4;
-  arg[6] = cc5;
-  arg[7] = cc0;
-  arg[8] = NULL;
-
-  /* catch 'unused parameter' compiler warning
-   */
-  (void) mode;
-  (void) id;
-
-  /* use homedir of effective user
-   */
-  len = sl_strlen(sh.effective.home) + 6;
-  envp[0] = calloc(1, len); /* free() ok   */
-  if (envp[0] != NULL)
-	sl_snprintf (envp[0], len, _("HOME=%s"), sh.effective.home); 
-  envp[1] = NULL;
-
-  /* Create the pipe 
-   */
-  if (aud_pipe(FIL__, __LINE__, pipedes) < 0) 
-    {
-      if (envp[0] != NULL) 
-	free(envp[0]);
-      SL_RETURN( (NULL), _("sh_gpg_popen"));
-    }
-
-  fflush (NULL);
-  
-  source->pid = aud_fork(FIL__, __LINE__);
-  
-  /* Failure
-   */
-  if (source->pid == (pid_t) - 1) 
-    {
-      sl_close_fd(FIL__, __LINE__, pipedes[0]);
-      sl_close_fd(FIL__, __LINE__, pipedes[1]);
-      if (envp[0] != NULL) 
-	free(envp[0]);
-      SL_RETURN( (NULL), _("sh_gpg_popen"));
-    }
-
-  if (source->pid == (pid_t) 0) 
-    {
-
-      /* child - make read side of the pipe stdout 
-       */
-      if (retry_aud_dup2(FIL__, __LINE__,
-			pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
-	{
-	  TPT(((0), FIL__, __LINE__, _("msg=<dup2 on pipe failed>\n")));
-	  dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
-	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
-	}
-      
-      /* close the pipe descriptors 
-       */
-      sl_close_fd (FIL__, __LINE__, pipedes[STDIN_FILENO]);
-      sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
-      
-      if (retry_aud_dup2(FIL__, __LINE__, fd, STDIN_FILENO) < 0)
-	{
-	  TPT(((0), FIL__, __LINE__, _("msg=<dup2 on fd failed>\n")));
-	  dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
-	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
-	}
- 
-      /* don't leak file descriptors
-       */
-      sh_unix_closeall (3, -1, S_TRUE); /* in child process */
-
-      if (flag_err_debug != S_TRUE)
-	{
-	  if (NULL == freopen(_("/dev/null"), "r+", stderr))
-	    {
-	      dlog(1, FIL__, __LINE__, _("Internal error: freopen failed\n"));
-	      aud__exit(FIL__, __LINE__, EXIT_FAILURE);
-	    }
-	}
-
-
-      /* We should become privileged if SUID,
-       * to be able to read the keyring.
-       * We have checked that gpg is OK,
-       * AND that only a trusted user could overwrite
-       * gpg.
-       */
-      memset (skey, 0, sizeof(sh_key_t));
-      aud_setuid(FIL__, __LINE__, geteuid());
-      
-      PDBGC_OPEN;
-      PDBGC_D((int)getuid());
-      PDBGC_D((int)geteuid());
-
-      {
-	int i = 0;
-	while (arg[i] != NULL)
-	  {
-	    PDBGC_S(arg[i]);
-	    ++i;
-	  }
-      }
-      PDBGC_CLOSE;
-
-      /* exec the program */
-
-#if defined(__linux__) && defined(HAVE_GPG_CHECKSUM)
-      /* 
-       * --  emulate an fexecve with checksum testing
-       */
-      checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_NOPRIV);
-
-      if (0 != sh_gpg_checksum(checkfd, 0))
-	{
-	  sl_close(checkfd);
-	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
-	}
-
-      pfd = get_the_fd(checkfd);
-      do {
-	val_return = dup (pfd);
-      } while (val_return < 0 && errno == EINTR);
-      pfd = val_return;
-      sl_close(checkfd);
-      /* checkfd = -1; *//* never read */
-
-      sl_snprintf(pname, sizeof(pname), _("/proc/self/fd/%d"), pfd);
-      if (0 == access(pname, R_OK|X_OK))               /* flawfinder: ignore */
-
-	{
-	  fcntl  (pfd, F_SETFD, FD_CLOEXEC);
-	  retry_aud_execve (FIL__, __LINE__,  pname, arg, envp);
-	      
-	  dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
-	       pname);
-	  /* failed 
-	   */
-	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
-	}
-	  
-      /* procfs not working, go ahead 
-       */
-#endif
-
-#if defined(HAVE_GPG_CHECKSUM)
-      /* This is an incredibly ugly kludge to prevent an attacker
-       * from knowing when it is safe to slip in a fake executable
-       * between the integrity check and the execve
-       */
-      myrand = (int) taus_get ();
-
-      myrand = (myrand < 0) ? (-myrand) : myrand;
-      myrand = (myrand % 32) + 2;
-
-      for (i = 0; i < myrand; ++i)
-	{
-	  checkfd = sl_open_fastread(FIL__, __LINE__, 
-				     DEFAULT_GPG_PATH, SL_NOPRIV);
-
-	  if (0 != sh_gpg_checksum(checkfd, 0)) {
-	    aud__exit(FIL__, __LINE__, EXIT_FAILURE);
-	  }
-	  sl_close(checkfd);
-	}
-#endif
-
-      retry_aud_execve (FIL__, __LINE__, DEFAULT_GPG_PATH, arg, envp);
-      dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
-	   DEFAULT_GPG_PATH);
-      
-      /* failed 
-       */
-      TPT(((0), FIL__, __LINE__, _("msg=<execve failed>\n")));
-      dlog(1, FIL__, __LINE__, _("Unexpected error: execve failed\n"));
-      aud__exit(FIL__, __LINE__, EXIT_FAILURE);
-    }
-
-  /* parent
-   */
-
-  if (envp[0] != NULL) 
-    free(envp[0]);
-
-  sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
-  retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
-  retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFL,  O_NONBLOCK);
-
-  outf = fdopen (pipedes[STDIN_FILENO], "r");
-  
-  if (outf == NULL) 
-    {
-      aud_kill (FIL__, __LINE__, source->pid, SIGKILL);
-      sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
-      waitpid (source->pid, NULL, 0);
-      source->pid = 0;
-      SL_RETURN( (NULL), _("sh_gpg_popen"));
-    }
-  
-  SL_RETURN( (outf), _("sh_gpg_popen"));
-}
-
-
-static int sh_gpg_pclose (sh_gpg_popen_t *source)
-{
-  int status = 0;
-  
-  SL_ENTER(_("sh_gpg_pclose"));
-
-  status = sl_fclose(FIL__, __LINE__, source->pipe);
-  if (status)
-    SL_RETURN( (-1), _("sh_gpg_pclose"));
-  
-  if (waitpid(source->pid, NULL, 0) != source->pid)
-    status = -1;
-  
-  source->pipe = NULL;
-  source->pid = 0;
-  SL_RETURN( (status), _("sh_gpg_pclose"));
-}
- 
-static
-int sh_gpg_check_file_sign(int fd, char * sign_id, char * sign_fp, 
-			   char * homedir, int whichfile)
-{
-  struct stat buf;
-  char line[256];
-  sh_gpg_popen_t  source;
-  int have_id = BAD, have_fp = BAD, status = 0;
-
-#ifdef HAVE_GPG_CHECKSUM
-  SL_TICKET checkfd;
-#endif
-
-  SL_ENTER(_("sh_gpg_check_file_sign"));
-
-  /* check whether GnuPG exists and has the correct checksum
-   */
-  TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
-  TPT(((0), FIL__, __LINE__, _("msg=<gpg is %s>\n"), DEFAULT_GPG_PATH));
-
-  if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_GPG_PATH, &buf))
-    {
-      char errbuf[SH_ERRBUF_SIZE];
-
-      status = errno;
-      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT,
-		      sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_GPG_PATH);
-      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
-    }
-
-  if (0 != tf_trust_check (DEFAULT_GPG_PATH, SL_YESPRIV))
-    SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
-
-#ifdef HAVE_GPG_CHECKSUM
-  checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_YESPRIV);
-
-  if (0 != sh_gpg_checksum(checkfd, 1))
-    {
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-		      _("Checksum mismatch"), 
-		      _("gpg_check_file_sign"));
-      sl_close(checkfd);
-      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
-    }
-  sl_close(checkfd);
-#endif
-
-  TPT(((0), FIL__, __LINE__, _("msg=<Open pipe to check signature>\n")));
-
-  fflush(NULL);
- 
-  source.pipe   = sh_gpg_popen  ( &source, fd, 0, NULL, homedir );
-
-  if (NULL == source.pipe)
-    {
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-		      _("Could not open pipe"), 
-		      _("gpg_check_file_sign"));
-      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
-    }
-
-  TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
-
- xagain:
-
-  errno = 0;
-
-  while (NULL != fgets(line, sizeof(line), source.pipe))
-    {
-
-      TPT(((0), FIL__, __LINE__, _("msg=<gpg out: %s>\n"), line));
-      if (line[strlen(line)-1] == '\n')
-	line[strlen(line)-1] = ' ';
-      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-		      line, 
-		      _("gpg_check_file_sign"));
-
-      if (sl_strlen(line) < 18) 
-	continue;
-
-      /* Sun May 27 18:40:05 CEST 2001
-       */
-      if (0 == sl_strncmp(_("BADSIG"), &line[9], 6) ||
-	  0 == sl_strncmp(_("ERRSIG"), &line[9], 6) ||
-	  0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6) ||
-	  0 == sl_strncmp(_("NODATA"), &line[9], 6) ||
-	  0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6))
-	{
-	  if      (0 == sl_strncmp(_("BADSIG"), &line[9], 6)) {
-	    dlog(1, FIL__, __LINE__, 
-		 _("%s file is signed, but the signature is invalid."),
-		 ((whichfile == 1) ? _("Configuration") : _("Database")));
-	  } 
-	  else if (0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6)) {
-	    dlog(1, FIL__, __LINE__, 
-		 _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."), 
-		 ((whichfile == 1) ? _("Configuration") : _("Database")),
-		 homedir);
-	  }
-	  else if (0 == sl_strncmp(_("ERRSIG"), &line[9], 6)) {
-	    dlog(1, FIL__, __LINE__, 
-		 _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."), 
-		 ((whichfile == 1) ? _("Configuration") : _("Database")),
-		 homedir);
-	  }
-	  else if (0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6)) {
-	    dlog(1, FIL__, __LINE__, 
-		 _("%s file is signed, but the public key to verify the signature has expired."), 
-		 ((whichfile == 1) ? _("Configuration") : _("Database")));
-	  }
-	  else if (0 == sl_strncmp(_("NODATA"), &line[9], 6)) {
-	    dlog(1, FIL__, __LINE__, 
-		 _("%s file is not signed."), 
-		 ((whichfile == 1) ? _("Configuration") : _("Database")));
-	  }
-
-	  have_fp = BAD; have_id = BAD;
-	  break;
-	}
-      if (0 == sl_strncmp(_("GOODSIG"), &line[9], 7))
-	{
-	  sl_strlcpy (sign_id, &line[25], SH_MINIBUF+1);
-	  if (sign_id)
-	    sign_id[sl_strlen(sign_id)-1] = '\0';  /* remove trailing '"' */
-	  have_id = GOOD;
-	} 
-      if (0 == sl_strncmp(_("VALIDSIG"), &line[9], 8))
-	{
-	  strncpy (sign_fp, &line[18], 40);
-	  sign_fp[40] = '\0';
-	  have_fp = GOOD;
-	}
-    }
-
-  if (ferror(source.pipe) && errno == EAGAIN) 
-    {
-      /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
-      retry_msleep(0,10); 
-      clearerr(source.pipe);
-      goto xagain;
-    }
- 
-  sh_gpg_pclose (&source);
-
-  TPT(((0), FIL__, __LINE__, _("msg=<Close pipe>\n")));
-
-  if (have_id == GOOD)
-    {
-      TPT(((0), FIL__, __LINE__, _("msg=<Got signator ID>\n")));
-    }
-  if (have_fp == GOOD)
-    {
-      TPT(((0), FIL__, __LINE__, _("msg=<Got fingerprint>\n")));
-    }
-
-  if (have_id == GOOD && have_fp == GOOD)
-    SL_RETURN( SH_GPG_OK, _("sh_gpg_check_file_sign"));
-  else
-    {
-      if (have_id == BAD)
-	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-			_("No good signature"), 
-			_("gpg_check_file_sign"));
-      else
-	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-			_("No fingerprint for key"), 
-			_("gpg_check_file_sign"));
-      SL_RETURN( SH_GPG_BADSIGN, _("sh_gpg_check_file_sign"));
-    }
-}
-
-int get_the_fd(SL_TICKET file_1);
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && \
-  defined(HAVE_GETPWNAM_R)
-#define USE_GETPWNAM_R 1
-#endif
-
-int sh_gpg_check_sign (long file, int what)
-{
-  int status = SH_GPG_BAD;
-  int fd = 0;
-
-  static int smsg = S_FALSE;
-  char  * tmp;
-
-  char  * sig_id;
-  char  * sig_fp;
-
-  char  * homedir = sh.effective.home;
-#if defined(SH_WITH_SERVER)
-  struct passwd * tempres;
-#if defined(USE_GETPWNAM_R)
-  struct passwd    pwd;
-  char           * buffer = SH_ALLOC(SH_PWBUF_SIZE);
-#endif
-#endif
-
-#ifdef USE_FINGERPRINT
-#include "sh_gpg_fp.h"
-#endif
-
-  SL_ENTER(_("sh_gpg_check_sign"));
-
-
-  if (what == SIG_CONF)
-    fd = get_the_fd(file);
-  if (what == SIG_DATA)
-    fd = get_the_fd(file);
-
-
-  if (fd < 0)
-    {
-      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
-      dlog(1, FIL__, __LINE__, 
-	   _("This looks like an unexpected internal error.\n"));
-#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
-      SH_FREE(buffer);
-#endif
-      SL_RETURN( (-1), _("sh_gpg_check_sign"));
-    }
-  
-#if defined(SH_WITH_SERVER)
-#if defined(USE_GETPWNAM_R)
-      sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
-#else
-      tempres = sh_getpwnam(DEFAULT_IDENT);
-#endif
-      if ((tempres != NULL) && (0 == sl_ret_euid()))
-	{
-	  /* privileges not dropped yet*/
-	  homedir = tempres->pw_dir;
-	}
-#endif
-
-  if (what == SIG_CONF)
-    {
-      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
-      status = sh_gpg_check_file_sign(fd, gp.conf_id, gp.conf_fp, homedir, 1);
-      TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGUSR: |%s|>\n"), gp.conf_id));
-      TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGFP:  |%s|>\n"), gp.conf_fp));
-      sig_id =  gp.conf_id; sig_fp = gp.conf_fp;
-    }
-
-  if (what == SIG_DATA)
-    {
-      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
-      status = sh_gpg_check_file_sign(fd, gp.data_id, gp.data_fp, homedir, 2);
-      TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGUSR: |%s|>\n"), gp.data_id));
-      TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGFP:  |%s|>\n"), gp.data_fp));
-      sig_id =  gp.data_id; sig_fp = gp.data_fp;
-    }
-  
-  if (SH_GPG_OK == status)
-    {
-#ifdef USE_FINGERPRINT
-      if ((sl_strcmp(SH_GPG_FP, sig_fp) == 0))
-	{
-	  int i;
-
-	  for(i = 0; i < (int) sl_strlen(sig_fp); ++i) {
-	      if (gpgfp[i] != sig_fp[i]) {
-		sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
-				MSG_E_GPG_FP, gpgfp, sig_fp);
-		break; }
-	  }
-
-	  if (smsg == S_FALSE) {
-	    tmp  = sh_util_safe_name(sig_id);
-	    sh_gpg_fill_startup (__LINE__, sh.prg_name, sh.real.uid,
-				 (sh.flag.hidefile == S_TRUE) ? 
-				 _("(hidden)") : file_path('C', 'R'), 
-				 tmp, 
-				 sig_fp);
-	    SH_FREE(tmp); }
-	  smsg = S_TRUE;
-
-#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
-	  SH_FREE(buffer);
-#endif
-	  SL_RETURN(0, _("sh_gpg_check_sign"));
-	}
-      else
-	{
-	  /* fp mismatch */
-	  dlog(1, FIL__, __LINE__, 
-	       _("The fingerprint of the signing key: %s\ndoes not match the compiled-in fingerprint: %s.\nTherefore the signature could not be verified.\n"), 
-	       sig_fp, SH_GPG_FP);
-	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-		      _("Fingerprint mismatch"), _("gpg_check_sign"));
-	  status = SH_GPG_BADSIGN;
-	}
-#else /* ifdef USE_FINGERPRINT */
-      if (smsg == S_FALSE)
-	{
-	  tmp = sh_util_safe_name(sig_id);
-	  sh_gpg_fill_startup (__LINE__,
-			       sh.prg_name, sh.real.uid,
-			       (sh.flag.hidefile == S_TRUE) ? 
-			       _("(hidden)") : file_path('C', 'R'), 
-			       tmp,  sig_fp);
-	  SH_FREE(tmp);
-	}
-      smsg = S_TRUE;
-
-#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
-      SH_FREE(buffer);
-#endif
-
-      SL_RETURN(0, _("sh_gpg_check_sign"));
-#endif /* !ifdef USE_FINGERPRINT */
-    }
-
-  if (status != SH_GPG_OK) 
-    {
-      uid_t   e_uid  = sl_ret_euid();
-      char  * e_home = sh.effective.home;
-
-#if defined(SH_WITH_SERVER)
-#if defined(USE_GETPWNAM_R)
-      struct passwd    e_pwd;
-      char          *  e_buffer = SH_ALLOC(SH_PWBUF_SIZE);
-      struct passwd *  e_tempres;
-      sh_getpwnam_r(DEFAULT_IDENT, &e_pwd, e_buffer, SH_PWBUF_SIZE, &e_tempres);
-#else
-      struct passwd * e_tempres = sh_getpwnam(DEFAULT_IDENT);
-#endif
-
-      if ((e_tempres != NULL) && (0 == sl_ret_euid()))   
-	{
-	  /* privileges not dropped yet */
-	  e_uid  = e_tempres->pw_uid;
-	  e_home = e_tempres->pw_dir;
-	}
-#endif
-      dlog(1, FIL__, __LINE__, 
-	   _("The signature of the configuration file or the file signature database\ncould not be verified. Possible reasons are:\n - gpg binary (%s) not found\n - invalid signature\n - the signature key is not in the private keyring of UID %d,\n - there is no keyring in %s/.gnupg, or\n - the file is not signed - did you move /filename.asc to /filename ?\nTo create a signed file, use (remove old signatures before):\n   gpg -a --clearsign --not-dash-escaped FILE\n   mv FILE.asc FILE\n"),
-	   DEFAULT_GPG_PATH,
-	   (int) e_uid, e_home);
-
-#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
-      SH_FREE(e_buffer);
-#endif
-    }
-
-  TPT(((0), FIL__, __LINE__, _("msg=<Status = %d>\n"), status));
-
-  return (-1); /* make compiler happy */
-}  
-
-#define FGETS_BUF 16384
-
-SL_TICKET sh_gpg_extract_signed(SL_TICKET fd)
-{
-  FILE * fin_cp = NULL;
-  char * buf    = NULL;
-  int    bufc;
-  int    flag_pgp    = S_FALSE;
-  int    flag_nohead = S_FALSE;
-  SL_TICKET fdTmp = (-1);
-  SL_TICKET open_tmp (void);
-
-  /* extract the data and copy to temporary file
-   */
-  fdTmp = open_tmp();
-  if (SL_ISERROR(fdTmp))
-    {
-      dlog(1, FIL__, __LINE__, _("Error opening temporary file.\n")); 
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-		      _("Error opening temporary file."), 
-		      _("sh_gpg_extract_signed"));
-      return -1;
-    }
-
-  fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
-  buf = SH_ALLOC(FGETS_BUF);
-
-  while (NULL != fgets(buf, FGETS_BUF, fin_cp))
-    {
-      bufc = 0; 
-      while (bufc < FGETS_BUF) { 
-	if (buf[bufc] == '\n') { ++bufc; break; }
-	++bufc;
-      }
-
-      if (flag_pgp == S_FALSE &&
-	  (0 == sl_strcmp(buf, _("-----BEGIN PGP SIGNED MESSAGE-----\n"))||
-	   0 == sl_strcmp(buf, _("-----BEGIN PGP MESSAGE-----\n")))
-	  )
-	{
-	  flag_pgp = S_TRUE;
-	  sl_write(fdTmp, buf, bufc);
-	  continue;
-	}
-      
-      if (flag_pgp == S_TRUE && flag_nohead == S_FALSE)
-	{
-	  if (buf[0] == '\n')
-	    {
-	      flag_nohead = S_TRUE;
-	      sl_write(fdTmp, buf, 1);
-	      continue;
-	    }
-	  else if (0 == sl_strncmp(buf, _("Hash:"), 5) ||
-		   0 == sl_strncmp(buf, _("NotDashEscaped:"), 15))
-	    {
-	      sl_write(fdTmp, buf, bufc);
-	      continue;
-	    }
-	  else
-	    continue;
-	}
-    
-      if (flag_pgp == S_TRUE && buf[0] == '\n')
-	{
-	  sl_write(fdTmp, buf, 1);
-	}
-      else if (flag_pgp == S_TRUE)
-	{
-	  /* sl_write_line(fdTmp, buf, bufc); */
-	  sl_write(fdTmp, buf, bufc);
-	}
-      
-      if (flag_pgp == S_TRUE && 
-	  0 == sl_strcmp(buf, _("-----END PGP SIGNATURE-----\n")))
-	break;
-    }
-  SH_FREE(buf);
-  sl_fclose(FIL__, __LINE__, fin_cp); /* fin_cp = fdopen(dup(), "rb"); */
-  sl_rewind (fdTmp);
-
-  return fdTmp;
-}
-
-/* #ifdef WITH_GPG */
-#endif
-
-
-
-
-
-
-
-
Index: trunk/src/sh_hash.c
===================================================================
--- trunk/src/sh_hash.c	(revision 549)
+++ trunk/src/sh_hash.c	(revision 550)
@@ -54,5 +54,5 @@
 #include "sh_error.h"
 #include "sh_tiger.h"
-#include "sh_gpg.h"
+#include "sh_sig.h"
 #include "sh_unix.h"
 #include "sh_files.h"
Index: trunk/src/sh_readconf.c
===================================================================
--- trunk/src/sh_readconf.c	(revision 549)
+++ trunk/src/sh_readconf.c	(revision 550)
@@ -34,5 +34,5 @@
 #include "sh_files.h"
 #include "sh_xfer.h"
-#include "sh_gpg.h"
+#include "sh_sig.h"
 #include "sh_hash.h"
 #include "sh_dbIO.h"
@@ -352,6 +352,6 @@
   SL_TICKET    fdTmp = -1;
 #endif
-#if defined(WITH_GPG) || defined(WITH_PGP)
-  SL_TICKET    fdGpg = -1;
+#if defined(WITH_SIG) 
+  SL_TICKET    fdSIG = -1;
 #endif
   char * tmp;
@@ -369,5 +369,5 @@
   char   local_flag = 'R';
 
-#if defined(WITH_GPG) || defined(WITH_PGP)
+#if defined(WITH_SIG)
   int    signed_content = S_FALSE;
   int    true_content   = S_FALSE;
@@ -470,6 +470,6 @@
 	sl_write_line(fdTmp, line_in, sl_strlen(line_in));
       }
-#if defined(WITH_GPG) || defined(WITH_PGP)
-    if (0 == sl_strncmp(line_in, _("-----END PGP SIGNATURE-----"), 25))
+#if defined(WITH_SIG)
+    if (S_TRUE == sh_sig_data_end(line_in))
       break;
 #else
@@ -485,16 +485,16 @@
 #endif
 
-#if defined(WITH_GPG) || defined(WITH_PGP)
+#if defined(WITH_SIG)
 
   /* extract the data and copy to temporary file
    */
-  fdGpg = sh_gpg_extract_signed(fd);
+  fdSIG = sh_sig_extract_signed(fd);
 
   sl_close(fd);
-  fd = fdGpg;
+  fd = fdSIG;
 
   /* Validate signature of open file.
    */
-  if (0 != sh_gpg_check_sign (fd, SIG_CONF))
+  if (0 != sh_sig_check_signature (fd, SIG_CONF))
     {
       SH_FREE(line_in);
@@ -520,24 +520,17 @@
     /* Sun May 27 18:40:05 CEST 2001
      */
-#if defined(WITH_GPG) || defined(WITH_PGP)
+#if defined(WITH_SIG)
     if (signed_content == S_FALSE)
       { 
-	if (0 == sl_strcmp(line, _("-----BEGIN PGP SIGNED MESSAGE-----")))
+	if (S_TRUE == sh_sig_msg_start(line))
 	  signed_content = S_TRUE;
 	else 
 	  continue;
       }
-    else if (true_content == S_FALSE)
-      {
-	if (line[0] == '\n')
-	  true_content = S_TRUE;
-	else
-	  continue;
-      }
-    else if (signed_content == S_TRUE)
+    else /* if (signed_content == S_TRUE) */
       { 
-	if (0 == sl_strcmp(line, _("-----BEGIN PGP SIGNATURE-----")))
+	if (S_TRUE == sh_sig_msg_end(line))
 	  break;
-	else if (0 == sl_strcmp(line, _("-----BEGIN PGP SIGNED MESSAGE-----")))
+	else if (S_TRUE == sh_sig_msg_start(line))
 	  {
 	    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
@@ -551,4 +544,12 @@
 	    aud_exit (FIL__, __LINE__,EXIT_FAILURE);
 	  }
+      }
+
+    if (true_content == S_FALSE) /* continue if in header */
+      {
+	if (S_TRUE == sh_sig_msg_startdata(line))
+	  true_content = S_TRUE;
+	else
+	  continue;
       }
 #endif
Index: trunk/src/sh_sig.c
===================================================================
--- trunk/src/sh_sig.c	(revision 550)
+++ trunk/src/sh_sig.c	(revision 550)
@@ -0,0 +1,1761 @@
+/* SAMHAIN file system integrity testing                                   */
+/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
+/*                                                                         */
+/*  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.              */
+
+#include "config_xor.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#if defined(WITH_SIG)
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#if defined(SH_WITH_SERVER)
+#include <pwd.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+#include <string.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+
+#if !defined(O_NONBLOCK)
+#if defined(O_NDELAY)
+#define O_NONBLOCK  O_NDELAY
+#else
+#define O_NONBLOCK  0
+#endif
+#endif
+
+
+#include "samhain.h"
+#include "sh_utils.h"
+#include "sh_error.h"
+#include "sh_tiger.h"
+#if defined(SH_WITH_SERVER)
+#define SH_NEED_PWD_GRP 1
+#include "sh_static.h"
+#endif
+#include "sh_sig.h"
+
+int get_the_fd(SL_TICKET file_1);
+
+#if defined(WITH_GPG)
+static struct {
+  char     conf_id[SH_MINIBUF+1];
+  char     conf_fp[SH_MINIBUF+1];
+  char     data_id[SH_MINIBUF+1];
+  char     data_fp[SH_MINIBUF+1];
+} gp;
+#endif
+
+typedef struct {
+  pid_t    pid;
+  FILE   * pipe;
+} sh_gpg_popen_t;
+
+#define SH_SIG_OK      0
+#define SH_SIG_BAD     1
+#define SH_SIG_BADSIGN 2
+
+/* replace #if 0 by #if 1 and set an appropriate path in front of '/pdbg.'
+ * for debugging
+ */
+#if 0
+#define PDGBFILE "/pdbg."
+#endif
+
+#if defined(PDGBFILE)
+FILE * pdbg;
+FILE * pdbgc;
+#define PDBG_OPEN    pdbg = fopen(PDGBFILE"main",  "a")  
+#define PDBG_CLOSE   sl_fclose (FIL__, __LINE__, pdbg)
+#define PDBG(arg)    fprintf(pdbg,  "PDBG: step %d\n", arg); fflush(pdbg)
+#define PDBG_D(arg)  fprintf(pdbg,  "PDBG: %d\n", arg); fflush(pdbg)
+#define PDBG_S(arg)  fprintf(pdbg,  "PDBG: %s\n", arg); fflush(pdbg)
+
+#define PDBGC_OPEN   pdbgc = fopen(PDGBFILE"child", "a")  
+#define PDBGC_CLOSE  sl_fclose (FIL__, __LINE__, pdbgc)
+#define PDBGC(arg)   fprintf(pdbgc, "PDBG: step %d\n", arg); fflush(pdbgc)
+#define PDBGC_D(arg) fprintf(pdbgc, "PDBG: %d\n", arg); fflush(pdbgc)
+#define PDBGC_S(arg) fprintf(pdbgc, "PDBG: %s\n", arg); fflush(pdbgc)
+#else
+#define PDBG_OPEN    
+#define PDBG_CLOSE   
+#define PDBG(arg)    
+#define PDBG_D(arg)  
+#define PDBG_S(arg)  
+#define PDBGC_OPEN    
+#define PDBGC_CLOSE   
+#define PDBGC(arg)    
+#define PDBGC_D(arg)  
+#define PDBGC_S(arg)  
+#endif
+
+#undef  FIL__
+#define FIL__  _("sh_sig.c")
+
+#if defined(SIG_HASH) || defined(SIG_KEY_HASH)
+
+typedef enum { SIG_HASH_REPORT, SIG_HASH_REPORTFULL, SIG_HASH_OTHER } checksum_flag;
+
+static int sh_sig_checksum (SL_TICKET checkfd, checksum_flag flag, const char * expected_in, const char * path)
+{
+  char * test_sig;
+  char * expected = NULL;
+  char * test_ptr1 = NULL;
+  char * test_ptr2 = NULL;
+  char   wstrip1[128];
+  char   wstrip2[128];
+  int    i, k;
+#include "sh_sig_chksum.h"
+
+  SL_ENTER(_("sh_sig_checksum"));
+
+  
+  if (flag == SIG_HASH_OTHER)
+    expected = sh_util_strdup(expected_in);
+  
+  if (flag == SIG_HASH_OTHER)
+    test_sig = sh_tiger_hash_gpg (path, checkfd, TIGER_NOLIM);
+  else
+    test_sig = sh_tiger_hash_gpg (DEFAULT_SIG_PATH, checkfd, TIGER_NOLIM);
+  
+  test_ptr1 = (flag == SIG_HASH_OTHER) ? strchr(expected, ':') : strchr(SIG_HASH, ':');
+  if (test_ptr1 != NULL)
+    test_ptr1 += 2;
+  else
+    test_ptr1 = (flag == SIG_HASH_OTHER) ? expected : SIG_HASH;
+
+  if (test_sig != NULL)
+    test_ptr2 = strchr(test_sig, ':');
+  if (test_ptr2 != NULL)
+    test_ptr2 += 2;
+  else
+    test_ptr2 = test_sig;
+
+  /* Tue Jun 24 23:11:54 CEST 2003 (1.7.9) -- strip whitespace
+   */
+  k = 0;
+  for (i = 0; i < 127; ++i)
+    {
+      if (test_ptr1[i] == '\0')
+	break;
+      if (test_ptr1[i] != ' ')
+	{
+	  wstrip1[k] = test_ptr1[i];
+	  ++k;
+	}
+    }
+  wstrip1[k] = '\0';
+
+  if (flag != SIG_HASH_OTHER)
+    {
+      for(i = 0; i < KEY_LEN; ++i)
+	{
+	  if (sigchk[i] != wstrip1[i]) 
+	    {
+	      sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_E_GPG_CHK, 
+			      sigchk, wstrip1);
+	      break;
+	    }
+	}
+    }
+
+  k = 0;
+  if (test_ptr2)
+    {
+      for (i = 0; i < 127; ++i)
+	{
+	  if (test_ptr2[i] == '\0')
+	    break;
+	  if (test_ptr2[i] != ' ')
+	    {
+	      wstrip2[k] = test_ptr2[i];
+	      ++k;
+	    }
+	}
+    }
+  wstrip2[k] = '\0';
+
+  if (0 != sl_strncmp(wstrip1, wstrip2, 127))
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<sig checksum: %s>\n"), test_sig));
+      TPT(((0), FIL__, __LINE__, _("msg=<compiled in : %s>\n"), (flag == SIG_HASH_OTHER) ? expected : SIG_HASH));
+      TPT(((0), FIL__, __LINE__, _("msg=<wstrip1     : %s>\n"), wstrip1));
+      TPT(((0), FIL__, __LINE__, _("msg=<wstrip2     : %s>\n"), wstrip2));
+      if (flag == SIG_HASH_REPORTFULL)
+	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_GPG, 
+			SIG_HASH, test_sig);
+      if (flag == SIG_HASH_OTHER)
+	dlog(1, FIL__, __LINE__, _("The compiled-in checksum of the public key %s\n(%s)\ndoes not match the actual checksum\n(%s).\nYou need to recompile with the correct checksum."), path, wstrip1, wstrip2);
+      else
+	dlog(1, FIL__, __LINE__, _("The compiled-in checksum of the signature checking binary %s\n(%s)\ndoes not match the actual checksum\n(%s).\nYou need to recompile with the correct checksum."), DEFAULT_SIG_PATH, wstrip1, wstrip2);
+      SH_FREE(test_sig);
+      if (expected)
+	SH_FREE(expected);
+      SL_RETURN((-1), _("sh_sig_checksum"));
+    }
+  SH_FREE(test_sig);
+  if (expected)
+    SH_FREE(expected);
+  SL_RETURN( (0), _("sh_sig_checksum"));
+}
+#endif
+
+struct startup_info {
+  long   line;
+  char * program;
+  long   uid;
+  char * path;
+  char * key_uid;
+  char * key_id;
+};
+
+static struct startup_info startInfo = { 0, NULL, 0, NULL, NULL, NULL };
+
+static void sh_sig_fill_startup (long line, char * program, long uid, char * path, 
+				 char * key_uid, char * key_id)
+{
+  startInfo.line    = line;
+  startInfo.program = sh_util_strdup(program);
+  startInfo.uid     = uid;
+  startInfo.path    = sh_util_strdup(path);
+  if (key_uid)
+    startInfo.key_uid = sh_util_strdup(key_uid);
+  else
+    startInfo.key_uid = sh_util_strdup(_("(not given)"));
+  if (key_id)
+    startInfo.key_id  = sh_util_strdup(key_id);
+  else
+    startInfo.key_id  = sh_util_strdup(_("(not given)"));
+  return;
+}
+
+typedef enum { SIG_DATASIG, SIG_DATAONLY } extractlevel;
+
+
+static FILE * sh_sig_popen (char *const argv[], sh_gpg_popen_t  *source, int fd);
+
+
+static FILE * sh_sig_popen (char *const arg[], sh_gpg_popen_t  *source, int fd)
+{
+  size_t len;
+  extern int flag_err_debug;
+  int pipedes[2];
+  FILE * outf = NULL;
+  char * envp[2];
+
+#if defined(HAVE_SIG_CHECKSUM)
+  SL_TICKET   checkfd = -1;
+  int         myrand;
+  int         i;
+#if defined(__linux__)
+  int         get_the_fd(SL_TICKET);
+  char        pname[128];
+  int         pfd;
+  int         val_return;
+#endif
+#endif
+
+  SL_ENTER(_("sh_sig_popen"));
+
+  /* use homedir of effective user
+   */
+  len = sl_strlen(sh.effective.home) + 6;
+  envp[0] = calloc(1, len); /* free() ok   */
+  if (envp[0] != NULL)
+	sl_snprintf (envp[0], len, _("HOME=%s"), sh.effective.home); 
+  envp[1] = NULL;
+
+  /* Create the pipe 
+   */
+  if (aud_pipe(FIL__, __LINE__, pipedes) < 0) 
+    {
+      if (envp[0] != NULL) 
+	free(envp[0]);
+      SL_RETURN( (NULL), _("sh_gpg_popen"));
+    }
+
+  fflush (NULL);
+  
+  source->pid = aud_fork(FIL__, __LINE__);
+  
+  /* Failure
+   */
+  if (source->pid == (pid_t) - 1) 
+    {
+      sl_close_fd(FIL__, __LINE__, pipedes[0]);
+      sl_close_fd(FIL__, __LINE__, pipedes[1]);
+      if (envp[0] != NULL) 
+	free(envp[0]);
+      SL_RETURN( (NULL), _("sh_sig_popen"));
+    }
+
+  if (source->pid == (pid_t) 0) 
+    {
+
+      /* child - make read side of the pipe stdout 
+       */
+      if (retry_aud_dup2(FIL__, __LINE__,
+			pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
+	{
+	  TPT(((0), FIL__, __LINE__, _("msg=<dup2 on pipe failed>\n")));
+	  dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
+	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+	}
+      
+      /* close the pipe descriptors 
+       */
+      sl_close_fd (FIL__, __LINE__, pipedes[STDIN_FILENO]);
+      sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
+      
+      if (retry_aud_dup2(FIL__, __LINE__, fd, STDIN_FILENO) < 0)
+	{
+	  TPT(((0), FIL__, __LINE__, _("msg=<dup2 on fd failed>\n")));
+	  dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
+	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+	}
+ 
+      /* don't leak file descriptors
+       */
+      sh_unix_closeall (3, -1, S_TRUE); /* in child process */
+
+      if (flag_err_debug != S_TRUE)
+	{
+	  if (NULL == freopen(_("/dev/null"), "r+", stderr))
+	    {
+	      dlog(1, FIL__, __LINE__, _("Internal error: freopen failed\n"));
+	      aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+	    }
+	}
+
+
+      /* We should become privileged if SUID,
+       * to be able to read the keyring.
+       * We have checked that gpg is OK,
+       * AND that only a trusted user could overwrite
+       * gpg.
+       */
+      memset (skey, 0, sizeof(sh_key_t));
+      aud_setuid(FIL__, __LINE__, geteuid());
+      
+      PDBGC_OPEN;
+      PDBGC_D((int)getuid());
+      PDBGC_D((int)geteuid());
+
+      {
+	int i = 0;
+	while (arg[i] != NULL)
+	  {
+	    PDBGC_S(arg[i]);
+	    ++i;
+	  }
+      }
+      PDBGC_CLOSE;
+
+      /* exec the program */
+
+#if defined(__linux__) && defined(HAVE_SIG_CHECKSUM)
+      /* 
+       * --  emulate an fexecve with checksum testing
+       */
+      checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_SIG_PATH, SL_NOPRIV);
+
+      if (0 != sh_sig_checksum(checkfd, SIG_HASH_REPORT, NULL, NULL))
+	{
+	  sl_close(checkfd);
+	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+	}
+
+      pfd = get_the_fd(checkfd);
+      do {
+	val_return = dup (pfd);
+      } while (val_return < 0 && errno == EINTR);
+      pfd = val_return;
+      sl_close(checkfd);
+      /* checkfd = -1; *//* never read */
+
+      sl_snprintf(pname, sizeof(pname), _("/proc/self/fd/%d"), pfd);
+      if (0 == access(pname, R_OK|X_OK))               /* flawfinder: ignore */
+
+	{
+	  fcntl  (pfd, F_SETFD, FD_CLOEXEC);
+	  retry_aud_execve (FIL__, __LINE__,  pname, arg, envp);
+	      
+	  dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
+	       pname);
+	  /* failed 
+	   */
+	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+	}
+	  
+      /* procfs not working, go ahead 
+       */
+#endif
+
+#if defined(HAVE_SIG_CHECKSUM)
+      /* This is an incredibly ugly kludge to prevent an attacker
+       * from knowing when it is safe to slip in a fake executable
+       * between the integrity check and the execve
+       */
+      myrand = (int) taus_get ();
+
+      myrand = (myrand < 0) ? (-myrand) : myrand;
+      myrand = (myrand % 32) + 2;
+
+      for (i = 0; i < myrand; ++i)
+	{
+	  checkfd = sl_open_fastread(FIL__, __LINE__, 
+				     DEFAULT_SIG_PATH, SL_NOPRIV);
+
+	  if (0 != sh_sig_checksum(checkfd, SIG_HASH_REPORT, NULL, NULL)) {
+	    aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+	  }
+	  sl_close(checkfd);
+	}
+#endif
+
+      retry_aud_execve (FIL__, __LINE__, DEFAULT_SIG_PATH, arg, envp);
+      dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
+	   DEFAULT_SIG_PATH);
+      
+      /* failed 
+       */
+      TPT(((0), FIL__, __LINE__, _("msg=<execve failed>\n")));
+      dlog(1, FIL__, __LINE__, _("Unexpected error: execve failed\n"));
+      aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+
+  /* parent
+   */
+
+  if (envp[0] != NULL) 
+    free(envp[0]);
+
+  sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
+  retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
+  retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFL,  O_NONBLOCK);
+
+  outf = fdopen (pipedes[STDIN_FILENO], "r");
+  
+  if (outf == NULL) 
+    {
+      aud_kill (FIL__, __LINE__, source->pid, SIGKILL);
+      sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
+      waitpid (source->pid, NULL, 0);
+      source->pid = 0;
+      SL_RETURN( (NULL), _("sh_sig_popen"));
+    }
+  
+  SL_RETURN( (outf), _("sh_sig_popen"));
+}
+
+
+static int sh_sig_pclose (sh_gpg_popen_t *source)
+{
+  int status = 0;
+  
+  SL_ENTER(_("sh_sig_pclose"));
+
+  status = sl_fclose(FIL__, __LINE__, source->pipe);
+  if (status)
+    SL_RETURN( (-1), _("sh_sig_pclose"));
+  
+  if (waitpid(source->pid, NULL, 0) != source->pid)
+    status = -1;
+  
+  source->pipe = NULL;
+  source->pid = 0;
+  SL_RETURN( (status), _("sh_sig_pclose"));
+}
+
+/* This is signify specific stuff 
+ */
+#if defined(WITH_SIGNIFY)
+
+#include <ctype.h>
+
+static
+int sh_signify_comp_comm(const char * line, size_t * commlen)
+{
+  /* check for a valid comment line: not exceeding 1023 chars and 
+   * starting with 'untrusted comment: ' */
+  static char   cmp[SH_MINIBUF];
+  static size_t cmp_len = 0;
+
+  size_t len = sl_strlen(line);
+  
+  if (cmp_len == 0) {
+    sl_strlcpy(cmp, _("untrusted comment: "), sizeof(cmp));
+    cmp_len = strlen(cmp);
+  }
+
+  if (line[len-1] == '\n') {
+    /* signify will replace the '\n' with '\0', so 1024 -> 1023, which fits */
+    if (len > 1024) return S_FALSE;
+    else            *commlen = len;
+  } else {
+    if (len > 1023) return S_FALSE;
+    else            *commlen = (len+1);
+  }
+
+  if (len >= cmp_len && 0 == strncmp(cmp, line, cmp_len))
+    return S_TRUE;
+  return S_FALSE;
+}
+
+static const char bto64_0[] = N_("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
+static char bto64[65] = { '\0' };
+
+static
+int sh_signify_comp_sig(const char * line, size_t commlen)
+{
+  char   cmp[128];
+  char   out[128];
+  size_t len = sl_strlen(line);
+  size_t i, j = 0;
+  int padf = 0;
+
+  if (bto64[0] == '\0')
+    memcpy(bto64, _(bto64_0), 65);
+  
+  if (line[len-1] == '\n') {
+    if ((len+commlen) > 2047) return S_FALSE;
+  } else {
+    if ((len+commlen) > 2046) return S_FALSE;
+  }
+
+  for (i = 0; i < len; ++i)
+    {
+      if (isspace(line[i])) {
+	/* signify will skip arbitrary space, using isspace() */
+	continue;
+      }
+      if (line[i] == '=') {
+	if (padf > 1) /* more than two padding '=' */
+	  return S_FALSE;
+	else
+	  ++padf;
+      } else if (!strchr(bto64, line[i]) || (line[i] == '=' && padf > 0)) {
+	return S_FALSE;
+      }
+      if (j < sizeof(cmp)) {
+	  cmp[j] = line[i]; ++j;
+      }
+    }
+
+  /* signature is 'Ed' + 8 byte random + 64 bytes = 74 bytes
+   * => 1 pad byte => 75 bytes => 100 b64 bytes */
+  if (j != 100 || padf != 1)
+    return S_FALSE;
+  
+  cmp[j] = '\0'; /* j == 100 */
+  sh_util_base64_dec((unsigned char *) out, (unsigned char *) cmp, j);
+  if(out[0] == 'E' && out[1] == 'd')
+    return S_TRUE;
+  
+  return S_FALSE;
+}
+static
+int sh_signify_msg_start(const char * line)
+{
+  static int  step = 0;
+  static size_t commlen = 0;
+
+  if (step == 0) {
+    if (S_TRUE == sh_signify_comp_comm(line, &commlen))
+      ++step;
+  }
+  else if (step == 1) {
+    if (S_TRUE == sh_signify_comp_sig(line, commlen)) {
+      ++step;
+    }
+    else {
+      step = 0; commlen = 0;
+    }
+  }
+  else if (step == 2) {
+    step = 0; commlen = 0;
+    return S_TRUE;
+  }
+  return S_FALSE;
+}
+
+static
+int sh_signify_msg_startdata(const char * line)
+{
+  (void) line;
+  return S_TRUE;
+}
+ 
+static
+int sh_signify_msg_end(const char * line)
+{
+  if (line[0] != '\0')
+    return S_FALSE;
+  return S_TRUE;
+}
+
+static
+int sh_signify_data_end(const char * line)
+{
+  if (line[0] == '[' && line[1] == 'E' && line[2] == 'O' &&
+      line[3] == 'F' && line[4] == ']')
+    return S_TRUE;
+  else if (line[0] != '\0')
+    return S_FALSE;
+  return S_TRUE;
+}
+
+static
+SL_TICKET sh_signify_extract_signed(SL_TICKET fd, extractlevel extract_level)
+{
+  const  int fgets_buf_size = 16384;
+  FILE * fin_cp = NULL;
+  char * buf    = NULL;
+  int    bufc;
+  char * comment = NULL;
+  size_t commlen = 0;
+  
+  int    flag_comm = S_FALSE;
+  int    flag_sig  = S_FALSE;
+  SL_TICKET fdTmp  = (-1);
+  SL_TICKET open_tmp (void);
+
+  /* extract the data and copy to temporary file
+   */
+  fdTmp = open_tmp();
+  if (SL_ISERROR(fdTmp))
+    {
+      dlog(1, FIL__, __LINE__, _("Error opening temporary file.\n")); 
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Error opening temporary file."), 
+		      _("sh_signify_extract_signed"));
+      return -1;
+    }
+
+  fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
+  buf = SH_ALLOC(fgets_buf_size);
+
+  while (NULL != fgets(buf, fgets_buf_size, fin_cp))
+    {
+      
+      bufc = 0; 
+      while (bufc < fgets_buf_size) { 
+	if (buf[bufc] == '\n') { ++bufc; break; }
+	++bufc;
+      }
+
+      if (flag_comm == S_FALSE)
+	{
+	  if (sh_signify_comp_comm(buf, &commlen) == S_TRUE)
+	    {
+	      flag_comm = S_TRUE;
+	      if (extract_level == SIG_DATASIG)
+		{
+		  comment = sh_util_strdup(buf);
+		  commlen = bufc;
+		}
+	    }
+	  continue;
+	}
+      else if (flag_comm == S_TRUE && flag_sig == S_FALSE)
+	{
+	  if (sh_signify_comp_sig(buf, commlen) == S_TRUE)
+	    {
+	      flag_sig = S_TRUE;
+	      if (extract_level == SIG_DATASIG)
+		{
+		  sl_write(fdTmp, comment, commlen);
+		  sl_write(fdTmp, buf, bufc);
+		}
+	      if (comment != NULL)
+		SH_FREE(comment);
+	      comment = NULL;
+	    }
+	  else
+	    {
+	      if (comment != NULL)
+		SH_FREE(comment);
+	      comment = NULL; commlen = 0; flag_comm = 0;
+	    }
+	  continue;
+	}
+      
+      if (flag_sig == S_TRUE)
+	{
+	  sl_write(fdTmp, buf, bufc); 
+	}
+    }
+  if (comment != NULL)
+    SH_FREE(comment);
+  sl_fclose(FIL__, __LINE__, fin_cp);
+  sl_rewind (fdTmp);
+
+#if 0
+  fin_cp = fdopen(dup(get_the_fd(fdTmp)), "rb");
+  FILE * fout = fopen("xxx.out", "w+");
+  while (NULL != fgets(buf, fgets_buf_size, fin_cp))
+    {
+      fputs(buf, fout);
+    }
+  fclose(fout);
+  sl_rewind(fdTmp);
+#endif
+  
+  SH_FREE(buf);
+  return fdTmp;
+}
+
+
+static FILE * sh_signify_popen (sh_gpg_popen_t  *source, int fd, char * homedir)
+{
+  char   path[256];
+  char   cc1[32];
+  char   cc2[32];
+  char   cc3[32];
+  char   cc4[SH_PATHBUF+32];
+  char   cc5[32];
+  char   cc6[32];
+  char * argv[9];
+  FILE * retval = NULL;
+
+  struct stat lbuf;
+  int         status_stat = 0;
+
+#ifdef HAVE_SIG_KEY_HASH
+  SL_TICKET checkfd;
+#endif
+
+
+  SL_ENTER(_("sh_signify_popen"));
+
+  sl_strlcpy (path,  DEFAULT_SIG_PATH,  256);
+
+  sl_strlcpy (cc1,   _("-Vem"),         32);
+  sl_strlcpy (cc2,   _("/dev/null"),    32);
+
+  sl_strlcpy (cc3,   _("-p"),           32);
+  sl_strlcpy (cc4,   homedir,           SH_PATHBUF+32);
+  sl_strlcat (cc4,   _("/.signify/"),   SH_PATHBUF+32);
+  sl_strlcat (cc4,   SH_INSTALL_NAME,   SH_PATHBUF+32);
+  sl_strlcat (cc4,   _(".pub"),         SH_PATHBUF+32);
+
+  /* read signed message from stdin */
+  sl_strlcpy (cc5,   _("-x"),           32);
+  sl_strlcpy (cc6,   _("-"),            32);
+
+  status_stat =  retry_lstat(FIL__, __LINE__, cc4, &lbuf);
+  if (status_stat == -1)
+    {
+      dlog(1, FIL__, __LINE__, 
+	   _("Signify public key %s\ndoes not exist or is not accessible.\nPlease add the directory and put the key there\nto allow signature verification.\n"),
+	   cc4);
+      sh_error_handle((-1), FIL__, __LINE__, status_stat, MSG_EXIT_ABORT1, 
+		      sh.prg_name);
+      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+    }
+#ifdef HAVE_SIG_KEY_HASH
+  checkfd = sl_open_read(FIL__, __LINE__, cc4, SL_YESPRIV);
+
+  if (0 != sh_sig_checksum(checkfd, SIG_HASH_OTHER, SIG_KEY_HASH, cc4))
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Checksum mismatch for signify public key"), 
+		      _("signify_popen"));
+      sl_close(checkfd);
+      sh_error_handle((-1), FIL__, __LINE__, status_stat, MSG_EXIT_ABORT1, 
+		      sh.prg_name);
+      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+    }
+  sl_close(checkfd);
+#endif
+ 
+  argv[0] = path; 
+  argv[1] = cc1;
+  argv[2] = cc2;
+  argv[3] = cc3;
+  argv[4] = cc4;
+  argv[5] = cc5;
+  argv[6] = cc6;
+  argv[7] = NULL;
+
+  retval = sh_sig_popen(argv, source, fd);
+  SL_RETURN((retval), _("sh_signify_popen")); 
+}
+
+static
+int sh_signify_check_file_sign(int fd, char * homedir)
+{
+  struct stat buf;
+  char line[256];
+  sh_gpg_popen_t  source;
+  int status = 0;
+  unsigned int n_goodsig  = 0;
+  unsigned int n_lines    = 0;
+  
+#ifdef HAVE_SIG_CHECKSUM
+  SL_TICKET checkfd;
+#endif
+
+  SL_ENTER(_("sh_signify_check_file_sign"));
+
+  /* check whether signify exists and has the correct checksum
+   */
+  TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
+  TPT(((0), FIL__, __LINE__, _("msg=<signify is %s>\n"), DEFAULT_SIG_PATH));
+
+  if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_SIG_PATH, &buf))
+    {
+      char errbuf[SH_ERRBUF_SIZE];
+
+      status = errno;
+      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT,
+		      sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_SIG_PATH);
+      SL_RETURN( SH_SIG_BAD, _("sh_signify_check_file_sign"));
+    }
+
+  if (0 != tf_trust_check (DEFAULT_SIG_PATH, SL_YESPRIV))
+    SL_RETURN( SH_SIG_BAD, _("sh_signify_check_file_sign"));
+
+#ifdef HAVE_SIG_CHECKSUM
+  checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_SIG_PATH, SL_YESPRIV);
+
+  if (0 != sh_sig_checksum(checkfd, SIG_HASH_REPORTFULL, NULL, NULL))
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Checksum mismatch"), 
+		      _("signify_check_file_sign"));
+      sl_close(checkfd);
+      SL_RETURN( SH_SIG_BAD, _("sh_signify_check_file_sign"));
+    }
+  sl_close(checkfd);
+#endif
+
+  TPT(((0), FIL__, __LINE__, _("msg=<Open pipe to check signature>\n")));
+
+  fflush(NULL);
+ 
+  source.pipe   = sh_signify_popen  ( &source, fd, homedir );
+
+  if (NULL == source.pipe)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Could not open pipe"), 
+		      _("signify_check_file_sign"));
+      SL_RETURN( SH_SIG_BAD, _("sh_signify_check_file_sign"));
+    }
+
+  TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
+
+ xagain:
+
+  errno = 0;
+
+  while (NULL != fgets(line, sizeof(line), source.pipe))
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<signify out: %s>\n"), line));
+      if (line[strlen(line)-1] == '\n')
+	line[strlen(line)-1] = ' ';
+      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      line, 
+		      _("signify_check_file_sign"));
+
+      ++n_lines;
+
+      /* the '\n' has been replaced with ' ' for logging */ 
+      if (0 == sl_strcmp(_("Signature Verified "), line))
+	{
+	  ++n_goodsig;
+	} 
+    }
+
+  if (ferror(source.pipe) && errno == EAGAIN) 
+    {
+      /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
+      retry_msleep(0,10); 
+      clearerr(source.pipe);
+      goto xagain;
+    }
+ 
+  if (0 != sh_sig_pclose (&source))
+    {
+	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+			_("Error on closing process pipe"), 
+			_("signify_check_file_sign"));
+	n_goodsig = 0;
+    }
+
+  TPT(((0), FIL__, __LINE__, _("msg=<Close pipe>\n")));
+
+  if (n_goodsig == 1 && n_lines == 1)
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<Signature Verified>\n")));
+      SL_RETURN( SH_SIG_OK, _("sh_signature_check_file_sign"));
+    }
+  else
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Error verifying file signature"), 
+		      _("signify_check_file_sign"));
+    }
+  SL_RETURN( SH_SIG_BADSIGN, _("sh_signature_check_file_sign"));
+}
+
+
+int sh_signify_check_signature (SL_TICKET file, ShSigFile what)
+{
+  int status = SH_SIG_BAD;
+  int fd = 0;
+
+  static int smsg = S_FALSE;
+
+  char  * homedir = sh.effective.home;
+  char  * home_alloc = NULL;
+#if defined(SH_WITH_SERVER)
+  struct passwd * tempres;
+#if defined(USE_GETPWNAM_R)
+  struct passwd    pwd;
+  char           * buffer = SH_ALLOC(SH_PWBUF_SIZE);
+#endif
+#endif
+
+  SL_ENTER(_("sh_signify_check_sign"));
+
+  (void) what;
+  
+  fd = get_the_fd(file);
+
+  if (fd < 0)
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
+      dlog(1, FIL__, __LINE__, 
+	   _("This looks like an unexpected internal error.\n"));
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+      SH_FREE(buffer);
+#endif
+      SL_RETURN( (-1), _("sh_signify_check_sign"));
+    }
+  
+#if defined(SH_WITH_SERVER)
+#if defined(USE_GETPWNAM_R)
+  sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
+#else
+  tempres = sh_getpwnam(DEFAULT_IDENT);
+#endif
+  if ((tempres != NULL) && (0 == sl_ret_euid()))
+    {
+      /* privileges not dropped yet*/
+      homedir = tempres->pw_dir;
+    }
+#endif
+
+  home_alloc = sh_util_strdup(homedir);
+  
+  TPT(((0), FIL__, __LINE__, _("msg=<SIGNIFY_CHECK: FD = %d>\n"), fd));
+  status = sh_signify_check_file_sign(fd, homedir);
+  
+  if (status != SH_SIG_OK) 
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<Status = %d>\n"), status));
+      dlog(1, FIL__, __LINE__, 
+	   _("The signature of the configuration file or the file signature database\ncould not be verified. Possible reasons are:\n - signify binary (%s) not found\n - invalid signature\n - there is no keyfile in %s/.signify/%s.pub, or\n - the file is not signed - did you move /filename.sig to /filename ?\nTo create a signed file, use (remove old signatures before):\n   signify|signify-openbsd -Se -s KEYNAME.sec -m FILE\n   mv FILE.sig FILE\n"),
+	   DEFAULT_SIG_PATH, home_alloc, SH_INSTALL_NAME);
+      SH_FREE(home_alloc);
+      SL_RETURN( (-1), _("sh_signify_check_sign"));
+    }
+
+  if (smsg == S_FALSE)
+    {
+      sh_sig_fill_startup (__LINE__,
+			   sh.prg_name, sh.real.uid,
+			   (sh.flag.hidefile == S_TRUE) ? 
+			   _("(hidden)") : file_path('C', 'R'), 
+			   NULL,  NULL);
+    }
+  smsg = S_TRUE;
+
+  SH_FREE(home_alloc);
+  SL_RETURN(0, _("sh_signify_check_sign"));
+}  
+
+/* This is GPG specific stuff 
+ */
+#elif defined(WITH_GPG)
+static FILE * sh_gpg_popen (sh_gpg_popen_t  *source, int fd, char * homedir)
+{
+  char   path[256];
+  char   cc1[32];
+  char   cc2[32];
+
+  char   cc0[2] = "-";
+  char   cc3[32];
+  char   cc4[SH_PATHBUF+32];
+  char   cc5[32];
+  char * argv[9];
+  FILE * retval = NULL;
+
+
+  SL_ENTER(_("sh_gpg_popen"));
+
+  /* -- GnuPG -- */
+  sl_strlcpy (path,  DEFAULT_SIG_PATH,  256);
+  sl_strlcpy (cc1,   _("--status-fd"),  32);
+  sl_strlcpy (cc2,   _("--verify"),     32);
+  sl_strlcpy (cc3,   _("--homedir"),    32);
+  /* sl_strlcpy (cc4,   sh.effective.home, SH_PATHBUF+32); */
+  sl_strlcpy (cc4,   homedir,           SH_PATHBUF+32);
+  sl_strlcat (cc4,   _("/.gnupg"),      SH_PATHBUF+32);
+  sl_strlcpy (cc5,   _("--no-tty"),     32);
+
+#if defined(SH_WITH_SERVER)
+  if (0 == sl_ret_euid())   /* privileges not dropped yet */
+    {
+      struct stat lbuf;
+      int         status_stat = 0;
+#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
+      struct passwd    pwd;
+      char          *  buffer = SH_ALLOC(SH_PWBUF_SIZE);
+      struct passwd *  tempres;
+      sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
+#else
+      struct passwd * tempres = sh_getpwnam(DEFAULT_IDENT);
+#endif
+
+      if (!tempres)
+	{
+	  dlog(1, FIL__, __LINE__, 
+	       _("User %s does not exist. Please add the user to your system.\n"), 
+	       DEFAULT_IDENT);
+	  status_stat = -1;
+	}
+      if (!tempres->pw_dir || tempres->pw_dir[0] == '\0')
+	{
+	  dlog(1, FIL__, __LINE__, 
+	       _("User %s does not have a home directory.\nPlease add the home directory for this user to your system.\n"), 
+	       DEFAULT_IDENT);
+	  status_stat = -2;
+	}
+      if (status_stat == 0)
+	{
+	  sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32); 
+	  sl_strlcat (cc4,   _("/.gnupg"),      SH_PATHBUF+32); 
+	  status_stat =  retry_lstat(FIL__, __LINE__, cc4, &lbuf);
+	  if (status_stat == -1)
+	    {
+	      dlog(1, FIL__, __LINE__, 
+		   _("Gnupg directory %s for user %s\ndoes not exist or is not accessible.\nPlease add the directory and put the keyring (pubring.gpg) there\nto verify the configuration file.\n"),
+		   cc4, DEFAULT_IDENT);
+	      status_stat = -3;
+	    }
+	}
+      if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid)
+	{
+	  dlog(1, FIL__, __LINE__, 
+	       _("Gnupg directory %s\nis not owned by user %s.\n"), 
+	       cc4, DEFAULT_IDENT);
+	  status_stat = -4;
+	}
+      if (status_stat == 0)
+	{
+	  sl_strlcat (cc4,   _("/pubring.gpg"),      SH_PATHBUF+32); 
+	  status_stat =  retry_lstat(FIL__, __LINE__, cc4, &lbuf);
+	  if (status_stat == -1)
+	    {
+	      dlog(1, FIL__, __LINE__, 
+		   _("Gnupg public keyring %s for user %s\ndoes not exist or is not accessible.\nPlease add the directory and put the keyring (pubring.gpg) there\nto verify the configuration file.\n"),
+		   cc4, DEFAULT_IDENT);
+	      status_stat = -5;
+	    }
+	}
+      if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid)
+	{
+	  dlog(1, FIL__, __LINE__, 
+	       _("Gnupg public keyring %s\nis not owned by user %s.\n"), 
+	       cc4, DEFAULT_IDENT);
+	  status_stat = -6;
+	}
+      if (status_stat != 0)
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, status_stat, MSG_EXIT_ABORT1, 
+			  sh.prg_name);
+	  aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+	}
+      sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32); 
+      sl_strlcat (cc4,   _("/.gnupg"),      SH_PATHBUF+32); 
+#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
+      SH_FREE(buffer);
+#endif
+    }
+#endif
+
+  argv[0] = path; 
+  argv[1] = cc1;
+  argv[2] = "1";
+  argv[3] = cc2;
+  argv[4] = cc3;
+  argv[5] = cc4;
+  argv[6] = cc5;
+  argv[7] = cc0;
+  argv[8] = NULL;
+
+  retval = sh_sig_popen(argv, source, fd);
+  SL_RETURN((retval), _("sh_gpg_popen")); 
+}
+
+static
+int sh_gpg_check_file_sign(int fd, char * sign_id, char * sign_fp, 
+			   char * homedir, ShSigFile whichfile)
+{
+  struct stat buf;
+  char line[256];
+  sh_gpg_popen_t  source;
+  int have_id = BAD, have_fp = BAD, status = 0;
+  unsigned int n_newsig   = 0;
+  unsigned int n_goodsig  = 0;
+  unsigned int n_validsig = 0;
+  
+#ifdef HAVE_SIG_CHECKSUM
+  SL_TICKET checkfd;
+#endif
+
+  SL_ENTER(_("sh_gpg_check_file_sign"));
+
+  /* check whether GnuPG exists and has the correct checksum
+   */
+  TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
+  TPT(((0), FIL__, __LINE__, _("msg=<gpg is %s>\n"), DEFAULT_SIG_PATH));
+
+  if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_SIG_PATH, &buf))
+    {
+      char errbuf[SH_ERRBUF_SIZE];
+
+      status = errno;
+      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT,
+		      sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_SIG_PATH);
+      SL_RETURN( SH_SIG_BAD, _("sh_gpg_check_file_sign"));
+    }
+
+  if (0 != tf_trust_check (DEFAULT_SIG_PATH, SL_YESPRIV))
+    SL_RETURN( SH_SIG_BAD, _("sh_gpg_check_file_sign"));
+
+#ifdef HAVE_SIG_CHECKSUM
+  checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_SIG_PATH, SL_YESPRIV);
+
+  if (0 != sh_sig_checksum(checkfd, SIG_HASH_REPORTFULL, NULL, NULL))
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Checksum mismatch"), 
+		      _("gpg_check_file_sign"));
+      sl_close(checkfd);
+      SL_RETURN( SH_SIG_BAD, _("sh_gpg_check_file_sign"));
+    }
+  sl_close(checkfd);
+#endif
+
+  TPT(((0), FIL__, __LINE__, _("msg=<Open pipe to check signature>\n")));
+
+  fflush(NULL);
+ 
+  source.pipe   = sh_gpg_popen  ( &source, fd, homedir );
+
+  if (NULL == source.pipe)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Could not open pipe"), 
+		      _("gpg_check_file_sign"));
+      SL_RETURN( SH_SIG_BAD, _("sh_gpg_check_file_sign"));
+    }
+
+  TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
+
+ xagain:
+
+  errno = 0;
+
+  while (NULL != fgets(line, sizeof(line), source.pipe))
+    {
+
+      TPT(((0), FIL__, __LINE__, _("msg=<gpg out: %s>\n"), line));
+      if (line[strlen(line)-1] == '\n')
+	line[strlen(line)-1] = ' ';
+      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      line, 
+		      _("gpg_check_file_sign"));
+
+      if (sl_strlen(line) < 12) 
+	continue;
+
+      /* Sun May 27 18:40:05 CEST 2001
+       */
+      if (0 == sl_strncmp(_("BADSIG"),     &line[9], 6) ||
+	  0 == sl_strncmp(_("ERRSIG"),     &line[9], 6) ||
+	  0 == sl_strncmp(_("NO_PUBKEY"),  &line[9], 6) ||
+	  0 == sl_strncmp(_("NODATA"),     &line[9], 6) ||
+	  0 == sl_strncmp(_("ERROR"),      &line[9], 5) ||
+	  0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6))
+	{
+	  if      (0 == sl_strncmp(_("BADSIG"), &line[9], 6)) {
+	    dlog(1, FIL__, __LINE__, 
+		 _("%s file is signed, but the signature is invalid."),
+		 ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")));
+	  } 
+	  else if (0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6)) {
+	    dlog(1, FIL__, __LINE__, 
+		 _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."), 
+		 ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")),
+		 homedir);
+	  }
+	  else if (0 == sl_strncmp(_("ERRSIG"), &line[9], 6)) {
+	    dlog(1, FIL__, __LINE__, 
+		 _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."), 
+		 ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")),
+		 homedir);
+	  }
+	  else if (0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6)) {
+	    dlog(1, FIL__, __LINE__, 
+		 _("%s file is signed, but the public key to verify the signature has expired."), 
+		 ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")));
+	  }
+	  else if (0 == sl_strncmp(_("NODATA"), &line[9], 6)) {
+	    dlog(1, FIL__, __LINE__, 
+		 _("%s file is not signed."), 
+		 ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")));
+	  }
+	  else if (0 == sl_strncmp(_("ERROR"), &line[9], 5)) {
+	    dlog(1, FIL__, __LINE__, 
+		 _("%s file is not correctly signed. An error occured while verifying the signature."), 
+		 ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")));
+	  }
+
+	  have_fp = BAD; have_id = BAD;
+	  break;
+	}
+      if (0 == sl_strncmp(_("GOODSIG"), &line[9], 7))
+	{
+	  ++n_goodsig;
+	  sl_strlcpy (sign_id, &line[25], SH_MINIBUF+1);
+	  if (sign_id)
+	    sign_id[sl_strlen(sign_id)-1] = '\0';  /* remove trailing '"' */
+	  have_id = GOOD;
+	} 
+      else if (0 == sl_strncmp(_("VALIDSIG"), &line[9], 8))
+	{
+	  ++n_validsig;
+	  strncpy (sign_fp, &line[18], 40);
+	  sign_fp[40] = '\0';
+	  have_fp = GOOD;
+	}
+      else if (0 == sl_strncmp(_("NEWSIG"), &line[9], 6))
+	{
+	  ++n_newsig;
+	}
+      
+    }
+
+  if (ferror(source.pipe) && errno == EAGAIN) 
+    {
+      /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
+      retry_msleep(0,10); 
+      clearerr(source.pipe);
+      goto xagain;
+    }
+ 
+  if (0 != sh_sig_pclose (&source))
+    {
+	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+			_("Error on closing process pipe"), 
+			_("gpg_check_file_sign"));
+	have_id = BAD;
+    }
+
+  TPT(((0), FIL__, __LINE__, _("msg=<Close pipe>\n")));
+
+  if (n_newsig != n_goodsig || n_newsig != n_validsig || n_newsig > 1)
+    {
+	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+			_("Too many or invalid signatures"), 
+			_("gpg_check_file_sign"));
+	have_id = BAD;
+    }
+  
+  if (have_id == GOOD)
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<Got signator ID>\n")));
+    }
+  if (have_fp == GOOD)
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<Got fingerprint>\n")));
+    }
+
+  if (have_id == GOOD && have_fp == GOOD)
+    SL_RETURN( SH_SIG_OK, _("sh_gpg_check_file_sign"));
+  else
+    {
+      if (have_id == BAD)
+	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+			_("No good signature"), 
+			_("gpg_check_file_sign"));
+      else
+	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+			_("No fingerprint for key"), 
+			_("gpg_check_file_sign"));
+      SL_RETURN( SH_SIG_BADSIGN, _("sh_gpg_check_file_sign"));
+    }
+}
+
+#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && \
+  defined(HAVE_GETPWNAM_R)
+#define USE_GETPWNAM_R 1
+#endif
+
+static
+int sh_gpg_check_signature (SL_TICKET file, ShSigFile what)
+{
+  int status = SH_SIG_BAD;
+  int fd = 0;
+
+  static int smsg = S_FALSE;
+  char  * tmp;
+
+  char  * sig_id;
+  char  * sig_fp;
+
+  char  * homedir = sh.effective.home;
+#if defined(SH_WITH_SERVER)
+  struct passwd * tempres;
+#if defined(USE_GETPWNAM_R)
+  struct passwd    pwd;
+  char           * buffer = SH_ALLOC(SH_PWBUF_SIZE);
+#endif
+#endif
+
+#ifdef USE_FINGERPRINT
+#include "sh_gpg_fp.h"
+#endif
+
+  SL_ENTER(_("sh_gpg_check_sign"));
+
+
+  if (what == SIG_CONF)
+    fd = get_the_fd(file);
+  if (what == SIG_DATA)
+    fd = get_the_fd(file);
+
+
+  if (fd < 0)
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
+      dlog(1, FIL__, __LINE__, 
+	   _("This looks like an unexpected internal error.\n"));
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+      SH_FREE(buffer);
+#endif
+      SL_RETURN( (-1), _("sh_gpg_check_sign"));
+    }
+  
+#if defined(SH_WITH_SERVER)
+#if defined(USE_GETPWNAM_R)
+      sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
+#else
+      tempres = sh_getpwnam(DEFAULT_IDENT);
+#endif
+      if ((tempres != NULL) && (0 == sl_ret_euid()))
+	{
+	  /* privileges not dropped yet*/
+	  homedir = tempres->pw_dir;
+	}
+#endif
+
+  if (what == SIG_CONF)
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
+      status = sh_gpg_check_file_sign(fd, gp.conf_id, gp.conf_fp, homedir, SIG_CONF);
+      TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGUSR: |%s|>\n"), gp.conf_id));
+      TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGFP:  |%s|>\n"), gp.conf_fp));
+      sig_id =  gp.conf_id; sig_fp = gp.conf_fp;
+    }
+
+  if (what == SIG_DATA)
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
+      status = sh_gpg_check_file_sign(fd, gp.data_id, gp.data_fp, homedir, SIG_DATA);
+      TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGUSR: |%s|>\n"), gp.data_id));
+      TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGFP:  |%s|>\n"), gp.data_fp));
+      sig_id =  gp.data_id; sig_fp = gp.data_fp;
+    }
+  
+  if (SH_SIG_OK == status)
+    {
+#ifdef USE_FINGERPRINT
+      if ((sl_strcmp(SH_GPG_FP, sig_fp) == 0))
+	{
+	  int i;
+
+	  for(i = 0; i < (int) sl_strlen(sig_fp); ++i) {
+	      if (gpgfp[i] != sig_fp[i]) {
+		sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
+				MSG_E_GPG_FP, gpgfp, sig_fp);
+		break; }
+	  }
+
+	  if (smsg == S_FALSE) {
+	    tmp  = sh_util_safe_name(sig_id);
+	    sh_sig_fill_startup (__LINE__, sh.prg_name, sh.real.uid,
+				 (sh.flag.hidefile == S_TRUE) ? 
+				 _("(hidden)") : file_path('C', 'R'), 
+				 tmp, 
+				 sig_fp);
+	    SH_FREE(tmp); }
+	  smsg = S_TRUE;
+
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+	  SH_FREE(buffer);
+#endif
+	  SL_RETURN(0, _("sh_gpg_check_sign"));
+	}
+      else
+	{
+	  /* fp mismatch */
+	  dlog(1, FIL__, __LINE__, 
+	       _("The fingerprint of the signing key: %s\ndoes not match the compiled-in fingerprint: %s.\nTherefore the signature could not be verified.\n"), 
+	       sig_fp, SH_GPG_FP);
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Fingerprint mismatch"), _("gpg_check_sign"));
+	  status = SH_SIG_BADSIGN;
+	}
+#else /* ifdef USE_FINGERPRINT */
+      if (smsg == S_FALSE)
+	{
+	  tmp = sh_util_safe_name(sig_id);
+	  sh_sig_fill_startup (__LINE__,
+			       sh.prg_name, sh.real.uid,
+			       (sh.flag.hidefile == S_TRUE) ? 
+			       _("(hidden)") : file_path('C', 'R'), 
+			       tmp,  sig_fp);
+	  SH_FREE(tmp);
+	}
+      smsg = S_TRUE;
+
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+      SH_FREE(buffer);
+#endif
+
+      /* status == OK and no fp checking */
+      SL_RETURN(0, _("sh_gpg_check_sign"));
+#endif /* !ifdef USE_FINGERPRINT */
+    }
+
+  if (status != SH_SIG_OK) 
+    {
+      uid_t   e_uid  = sl_ret_euid();
+      char  * e_home = sh.effective.home;
+
+#if defined(SH_WITH_SERVER)
+#if defined(USE_GETPWNAM_R)
+      struct passwd    e_pwd;
+      char          *  e_buffer = SH_ALLOC(SH_PWBUF_SIZE);
+      struct passwd *  e_tempres;
+      sh_getpwnam_r(DEFAULT_IDENT, &e_pwd, e_buffer, SH_PWBUF_SIZE, &e_tempres);
+#else
+      struct passwd * e_tempres = sh_getpwnam(DEFAULT_IDENT);
+#endif
+
+      if ((e_tempres != NULL) && (0 == sl_ret_euid()))   
+	{
+	  /* privileges not dropped yet */
+	  e_uid  = e_tempres->pw_uid;
+	  e_home = e_tempres->pw_dir;
+	}
+#endif
+      dlog(1, FIL__, __LINE__, 
+	   _("The signature of the configuration file or the file signature database\ncould not be verified. Possible reasons are:\n - gpg binary (%s) not found\n - invalid signature\n - the signature key is not in the private keyring of UID %d,\n - there is no keyring in %s/.gnupg, or\n - the file is not signed - did you move /filename.asc to /filename ?\nTo create a signed file, use (remove old signatures before):\n   gpg -a --clearsign --not-dash-escaped FILE\n   mv FILE.asc FILE\n"),
+	   DEFAULT_SIG_PATH,
+	   (int) e_uid, e_home);
+
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+      SH_FREE(e_buffer);
+#endif
+    }
+
+  TPT(((0), FIL__, __LINE__, _("msg=<Status = %d>\n"), status));
+
+  SL_RETURN(-1, _("sh_gpg_check_sign")); /* make compiler happy */
+}  
+
+static int sh_gpg_comp(const char * line, const char * cmp)
+{
+  int retval = S_FALSE;
+
+  if (line && line[0] == '-' && line[1] == '-')
+    {
+      char * dup = sh_util_strdup(line);
+      char * tmp = dup + sl_strlen( dup );
+      --tmp;
+      if (*tmp == '\n') { *tmp = '\0'; --tmp; }
+      while( (*tmp == '\t' || *tmp == ' ' || *tmp == '\r' ) && tmp >= dup ) *tmp-- = '\0';
+
+      if (0 == sl_strcmp(dup, cmp))
+	retval = S_TRUE;
+      SH_FREE(dup);
+    }
+  return retval;
+}
+
+static
+int sh_gpg_msg_start(const char * line)
+{
+  static char cmp[SH_MINIBUF];
+  static int  initialized = 0;
+
+  if (initialized == 0) {
+    sl_strlcpy(cmp, _("-----BEGIN PGP SIGNED MESSAGE-----"), sizeof(cmp));
+    initialized = 1;
+  }
+  return sh_gpg_comp(line, cmp);
+}
+
+static
+int sh_gpg_msg_startdata(const char * line)
+{
+  if (line[0] == '\n')
+    return S_TRUE;
+  return S_FALSE;
+}
+
+static
+int sh_gpg_msg_end(const char * line)
+{
+  static char cmp[SH_MINIBUF];
+  static int  initialized = 0;
+
+  if (initialized == 0) {
+    sl_strlcpy(cmp, _("-----BEGIN PGP SIGNATURE-----"), sizeof(cmp));
+    initialized = 1;
+  }
+  return sh_gpg_comp(line, cmp);
+}
+
+static
+int sh_gpg_sig_end(const char * line)
+{
+  static char cmp[SH_MINIBUF];
+  static int  initialized = 0;
+
+  if (initialized == 0) {
+    sl_strlcpy(cmp, _("-----END PGP SIGNATURE-----"), sizeof(cmp));
+    initialized = 1;
+  }
+  return sh_gpg_comp(line, cmp);
+}
+
+static
+SL_TICKET sh_gpg_extract_signed(SL_TICKET fd, extractlevel extract_level)
+{
+  const  int fgets_buf_size = 16384;
+  FILE * fin_cp = NULL;
+  char * buf    = NULL;
+  int    bufc;
+  int    flag_pgp    = S_FALSE;
+  int    flag_nohead = S_FALSE;
+  SL_TICKET fdTmp = (-1);
+  SL_TICKET open_tmp (void);
+
+  /* extract the data and copy to temporary file
+   */
+  fdTmp = open_tmp();
+  if (SL_ISERROR(fdTmp))
+    {
+      dlog(1, FIL__, __LINE__, _("Error opening temporary file.\n")); 
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Error opening temporary file."), 
+		      _("sh_gpg_extract_signed"));
+      return -1;
+    }
+
+  fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
+  buf = SH_ALLOC(fgets_buf_size);
+
+  while (NULL != fgets(buf, fgets_buf_size, fin_cp))
+    {
+      bufc = 0; 
+      while (bufc < fgets_buf_size) { 
+	if (buf[bufc] == '\n') { ++bufc; break; }
+	++bufc;
+      }
+
+      if (flag_pgp == S_FALSE && sh_gpg_msg_start(buf) == S_TRUE)
+	{
+	  flag_pgp = S_TRUE;
+	  if (extract_level == SIG_DATASIG)
+	    sl_write(fdTmp, buf, bufc);
+	  continue;
+	}
+      
+      if (flag_pgp == S_TRUE && flag_nohead == S_FALSE)
+	{
+	  /* Header finished */
+	  if (buf[0] == '\n')
+	    {
+	      flag_nohead = S_TRUE;
+	      if (extract_level == SIG_DATASIG)
+		sl_write(fdTmp, buf, 1);
+	      continue;
+	    }
+	  /* copy these headers */
+	  else if (0 == sl_strncmp(buf, _("Hash:"), 5) ||
+		   0 == sl_strncmp(buf, _("NotDashEscaped:"), 15))
+	    {
+	      if (extract_level == SIG_DATASIG)
+		sl_write(fdTmp, buf, bufc);
+	      continue;
+	    }
+	  /* ignore other headers */
+	  else
+	    continue;
+	}
+    
+      if (flag_pgp == S_TRUE && buf[0] == '\n')
+	{
+	  sl_write(fdTmp, buf, 1);
+	}
+      else if (flag_pgp == S_TRUE)
+	{
+	  if (extract_level == SIG_DATASIG) {
+	    sl_write(fdTmp, buf, bufc); 
+	  }
+	  else {
+	    if (sh_gpg_msg_end(buf) == S_TRUE)
+	      break;
+	    else
+	      sl_write(fdTmp, buf, bufc);
+	  }
+	}
+
+      /* This is after the copy has been done. */
+      if (flag_pgp == S_TRUE && sh_gpg_sig_end(buf) == S_TRUE)
+	break;
+    }
+  SH_FREE(buf);
+  sl_fclose(FIL__, __LINE__, fin_cp);
+  sl_rewind (fdTmp);
+
+  return fdTmp;
+}
+#endif
+
+/*********************************************************************
+ *
+ * Exported functions
+ *
+ *********************************************************************/
+
+int sh_sig_check_signature (SL_TICKET file, ShSigFile what)
+{
+#if defined(WITH_GPG)
+  return sh_gpg_check_signature (file, what);
+#elif defined(WITH_SIGNIFY)
+  return sh_signify_check_signature (file, what);
+#endif
+}
+
+SL_TICKET sh_sig_extract_signed(SL_TICKET fd)
+{
+#if defined(WITH_GPG)
+  return sh_gpg_extract_signed(fd, SIG_DATASIG);
+#elif defined(WITH_SIGNIFY)
+  return sh_signify_extract_signed(fd, SIG_DATASIG);
+#endif
+}
+
+SL_TICKET sh_sig_extract_signed_data(SL_TICKET fd)
+{
+#if defined(WITH_GPG)
+  return sh_gpg_extract_signed(fd, SIG_DATAONLY);
+#elif defined(WITH_SIGNIFY)
+  return sh_signify_extract_signed(fd, SIG_DATAONLY);
+#endif
+}
+
+int sh_sig_msg_start(const char * line)
+{
+#if defined(WITH_GPG)
+  return sh_gpg_msg_start(line);
+#elif defined(WITH_SIGNIFY)
+  return sh_signify_msg_start(line);
+#endif
+}
+
+int sh_sig_msg_startdata(const char * line)
+{
+#if defined(WITH_GPG)
+  return sh_gpg_msg_startdata(line);
+#elif defined(WITH_SIGNIFY)
+  return sh_signify_msg_startdata(line);
+#endif
+}
+
+int sh_sig_msg_end(const char * line)
+{
+#if defined(WITH_GPG)
+  return sh_gpg_msg_end(line);
+#elif defined(WITH_SIGNIFY)
+  return sh_signify_msg_end(line);
+#endif
+}
+
+int sh_sig_data_end(const char * line)
+{
+#if defined(WITH_GPG)
+  return sh_gpg_sig_end(line);
+#elif defined(WITH_SIGNIFY)
+  return sh_signify_data_end(line);
+#endif
+}
+
+void sh_sig_log_startup (void)
+{
+  if (startInfo.program != NULL)
+    {
+      sh_error_handle ((-1), FIL__, startInfo.line, 0, MSG_START_GH,
+		       startInfo.program, startInfo.uid,
+		       startInfo.path,
+		       startInfo.key_uid, startInfo.key_id);
+    }
+  return;
+}
+
+/* #ifdef WITH_SIG */
+#endif
+
+
+
+
+
+
+
+
Index: trunk/src/sh_tools.c
===================================================================
--- trunk/src/sh_tools.c	(revision 549)
+++ trunk/src/sh_tools.c	(revision 550)
@@ -2075,5 +2075,5 @@
 #endif
 
-#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) || defined(SH_STEALTH) || defined(WITH_GPG) || defined(WITH_PGP)
+#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) || defined(SH_STEALTH) || defined(WITH_SIG)
 
 /* --------- secure temporary file ------------ */
Index: trunk/src/sh_unix.c
===================================================================
--- trunk/src/sh_unix.c	(revision 549)
+++ trunk/src/sh_unix.c	(revision 550)
@@ -5407,4 +5407,5 @@
 {
   int                  add_off = 0, llen;
+  unsigned long        bread;
   static unsigned long off_data   = 0;
   static unsigned long max_data   = 0;
@@ -5454,6 +5455,11 @@
   /* --- Read one line. ---
    */
-  add_off   = hideout_hex_block(fd, (unsigned char *) str, len, &bytes_read);
-  off_data += add_off;
+  add_off   = hideout_hex_block(fd, (unsigned char *) str, len, &bread);
+  if (add_off > 0)
+    off_data += add_off;
+  bytes_read += bread;
+
+  if (bread == 0 || add_off <= 0) /* EOF */
+    str[0] = '\0';
 
   llen = sl_strlen(str);
@@ -5477,4 +5483,6 @@
   ASSERT_RET((len > 1), _("len > 1"), (0));
 
+  str[0] = '\0';
+  *bytes_read = 0;
   --len;
 
@@ -5494,12 +5502,15 @@
 	      do {
 		do {
+		  errno = 0;
 		  num = sl_read (fd, &c, 1);
 		} while (num == 0 && errno == EINTR);
 		if (num > 0)
 		  ++here;
-		else if (num == 0)
-		  SL_RETURN((0), _("hideout_hex_block"));
-		else 
+		else if (num == 0) {
 		  SL_RETURN((-1), _("hideout_hex_block"));
+		}
+		else {
+		  SL_RETURN((-1), _("hideout_hex_block"));
+		}
 	      } while (c == '\n' || c == '\t' || c == '\r' || 
 		       c == ' ');
@@ -5523,6 +5534,8 @@
   if (i != 0)
     str[i] = '\0';
+  else if (str[0] == '\n')
+    str[i+1] = '\0'; /* keep newline and terminate */
   else
-    str[i+1] = '\0'; /* keep newline and terminate */
+    str[0] = '\0';
   retval += here;
   *bytes_read += (bread/8);
