source: trunk/src/sh_gpg.c @ 474

Last change on this file since 474 was 474, checked in by katerina, 7 years ago

Fix for ticket #372 (Replace obsolete smatch by clang in test suite).

File size: 35.1 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20#include "config_xor.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24
25
26#if defined(WITH_GPG) || defined(WITH_PGP)
27
28#include <unistd.h>
29#include <fcntl.h>
30#include <signal.h>
31#if defined(SH_WITH_SERVER)
32#include <pwd.h>
33#endif
34#include <sys/stat.h>
35#include <sys/types.h>
36#include <errno.h>
37#include <sys/wait.h>
38
39#include <string.h>
40#ifdef HAVE_MEMORY_H
41#include <memory.h>
42#endif
43
44
45#if !defined(O_NONBLOCK)
46#if defined(O_NDELAY)
47#define O_NONBLOCK  O_NDELAY
48#else
49#define O_NONBLOCK  0
50#endif
51#endif
52
53
54#include "samhain.h"
55#include "sh_utils.h"
56#include "sh_error.h"
57#include "sh_tiger.h"
58#if defined(SH_WITH_SERVER)
59#define SH_NEED_PWD_GRP 1
60#include "sh_static.h"
61#endif
62
63static struct {
64  char     conf_id[SH_MINIBUF+1];
65  char     conf_fp[SH_MINIBUF+1];
66  char     data_id[SH_MINIBUF+1];
67  char     data_fp[SH_MINIBUF+1];
68} gp;
69
70typedef struct {
71  pid_t    pid;
72  FILE   * pipe;
73} sh_gpg_popen_t;
74
75#define SH_GPG_OK      0
76#define SH_GPG_BAD     1
77#define SH_GPG_BADSIGN 2
78
79/* replace #if 0 by #if 1 and set an appropriate path in front of '/pdbg.'
80 * for debugging
81 */
82#if 0
83#define PDGBFILE "/pdbg."
84#endif
85
86#if defined(PDGBFILE)
87FILE * pdbg;
88FILE * pdbgc;
89#define PDBG_OPEN    pdbg = fopen(PDGBFILE"main",  "a") 
90#define PDBG_CLOSE   sl_fclose (FIL__, __LINE__, pdbg)
91#define PDBG(arg)    fprintf(pdbg,  "PDBG: step %d\n", arg); fflush(pdbg)
92#define PDBG_D(arg)  fprintf(pdbg,  "PDBG: %d\n", arg); fflush(pdbg)
93#define PDBG_S(arg)  fprintf(pdbg,  "PDBG: %s\n", arg); fflush(pdbg)
94
95#define PDBGC_OPEN   pdbgc = fopen(PDGBFILE"child", "a") 
96#define PDBGC_CLOSE  sl_fclose (FIL__, __LINE__, pdbgc)
97#define PDBGC(arg)   fprintf(pdbgc, "PDBG: step %d\n", arg); fflush(pdbgc)
98#define PDBGC_D(arg) fprintf(pdbgc, "PDBG: %d\n", arg); fflush(pdbgc)
99#define PDBGC_S(arg) fprintf(pdbgc, "PDBG: %s\n", arg); fflush(pdbgc)
100#else
101#define PDBG_OPEN   
102#define PDBG_CLOSE   
103#define PDBG(arg)   
104#define PDBG_D(arg) 
105#define PDBG_S(arg) 
106#define PDBGC_OPEN   
107#define PDBGC_CLOSE   
108#define PDBGC(arg)   
109#define PDBGC_D(arg) 
110#define PDBGC_S(arg) 
111#endif
112
113#undef  FIL__
114#define FIL__  _("sh_gpg.c")
115
116#ifdef GPG_HASH
117
118static int sh_gpg_checksum (SL_TICKET checkfd, int flag)
119{
120  char * test_gpg;
121  char * test_ptr1 = NULL;
122  char * test_ptr2 = NULL;
123  char   wstrip1[128];
124  char   wstrip2[128];
125  int    i, k;
126#include "sh_gpg_chksum.h"
127
128  SL_ENTER(_("sh_gpg_checksum"));
129
130#if defined(WITH_PGP)
131  test_gpg = sh_tiger_hash_gpg (DEFAULT_PGP_PATH, checkfd, TIGER_NOLIM);
132#else
133  test_gpg = sh_tiger_hash_gpg (DEFAULT_GPG_PATH, checkfd, TIGER_NOLIM);
134#endif
135 
136  test_ptr1 = strchr(GPG_HASH, ':');
137  if (test_gpg != NULL)
138    test_ptr2 = strchr(test_gpg, ':');
139 
140  if (test_ptr2 != NULL)
141    test_ptr2 += 2;
142  else
143    test_ptr2 = test_gpg;
144  if (test_ptr1 != NULL)
145    test_ptr1 += 2;
146  else
147    test_ptr1 = GPG_HASH;
148
149  /* Tue Jun 24 23:11:54 CEST 2003 (1.7.9) -- strip whitespace
150   */
151  k = 0;
152  for (i = 0; i < 127; ++i)
153    {
154      if (test_ptr1[i] == '\0')
155        break;
156      if (test_ptr1[i] != ' ')
157        {
158          wstrip1[k] = test_ptr1[i];
159          ++k;
160        }
161    }
162  wstrip1[k] = '\0';
163
164  for(i = 0; i < KEY_LEN; ++i)
165    {
166      if (gpgchk[i] != wstrip1[i]) 
167        {
168          sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_E_GPG_CHK, 
169                          gpgchk, wstrip1);
170          break;
171        }
172    }
173
174  k = 0;
175  if (test_ptr2)
176    {
177      for (i = 0; i < 127; ++i)
178        {
179          if (test_ptr2[i] == '\0')
180            break;
181          if (test_ptr2[i] != ' ')
182            {
183              wstrip2[k] = test_ptr2[i];
184              ++k;
185            }
186        }
187    }
188  wstrip2[k] = '\0';
189
190  if (0 != sl_strncmp(wstrip1, wstrip2, 127))
191    {
192      TPT(((0), FIL__, __LINE__, _("msg=<pgp checksum: %s>\n"), test_gpg));
193      TPT(((0), FIL__, __LINE__, _("msg=<Compiled-in : %s>\n"), GPG_HASH));
194      TPT(((0), FIL__, __LINE__, _("msg=<wstrip1     : %s>\n"), wstrip1));
195      TPT(((0), FIL__, __LINE__, _("msg=<wstrip2     : %s>\n"), wstrip2));
196      if (flag == 1)
197        sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_GPG, 
198                        GPG_HASH, test_gpg);
199      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);
200      SH_FREE(test_gpg);
201      SL_RETURN((-1), _("sh_gpg_checksum"));
202    }
203  SH_FREE(test_gpg);
204  SL_RETURN( (0), _("sh_gpg_checksum"));
205}
206#endif
207
208struct startup_info {
209  long   line;
210  char * program;
211  long   uid;
212  char * path;
213  char * key_uid;
214  char * key_id;
215};
216
217static struct startup_info startInfo = { 0, NULL, 0, NULL, NULL, NULL };
218
219void sh_gpg_log_startup (void)
220{
221  if (startInfo.program != NULL)
222    {
223      sh_error_handle ((-1), FIL__, startInfo.line, 0, MSG_START_GH,
224                       startInfo.program, startInfo.uid,
225                       startInfo.path,
226                       startInfo.key_uid, startInfo.key_id);
227    }
228  return;
229}
230
231static void sh_gpg_fill_startup (long line, char * program, long uid, char * path, 
232                                 char * key_uid, char * key_id)
233{
234  startInfo.line    = line;
235  startInfo.program = sh_util_strdup(program);
236  startInfo.uid     = uid;
237  startInfo.path    = sh_util_strdup(path);
238  startInfo.key_uid = sh_util_strdup(key_uid);
239  startInfo.key_id  = sh_util_strdup(key_id);
240  return;
241}
242
243static FILE * sh_gpg_popen (sh_gpg_popen_t  *source, int fd, 
244                            int mode, char * id, char * homedir)
245{
246  extern int flag_err_debug;
247  int pipedes[2];
248  FILE * outf = NULL;
249  char * envp[2];
250  size_t len;
251  char   path[256];
252  char   cc1[32];
253  char   cc2[32];
254#if defined(WITH_PGP)
255  char   cc3[32];
256  char   cc0[3] = "-f";
257#endif
258#if defined(WITH_GPG)
259  char   cc0[2] = "-";
260  char   cc3[32];
261  char   cc4[SH_PATHBUF+32];
262  char   cc5[32];
263#endif
264
265  char * arg[9];
266
267#if defined(HAVE_GPG_CHECKSUM)
268  SL_TICKET   checkfd = -1;
269  int         myrand;
270  int         i;
271#if defined(__linux__)
272  int         get_the_fd(SL_TICKET);
273  char        pname[128];
274  int         pfd;
275  int         val_return;
276#endif
277#endif
278
279  SL_ENTER(_("sh_gpg_popen"));
280
281#if defined(WITH_GPG)
282  /* -- GnuPG -- */
283  sl_strlcpy (path,  DEFAULT_GPG_PATH,  256);
284  sl_strlcpy (cc1,   _("--status-fd"),  32);
285  sl_strlcpy (cc2,   _("--verify"),     32);
286  sl_strlcpy (cc3,   _("--homedir"),    32);
287  /* sl_strlcpy (cc4,   sh.effective.home, SH_PATHBUF+32); */
288  sl_strlcpy (cc4,   homedir,           SH_PATHBUF+32);
289  sl_strlcat (cc4,   _("/.gnupg"),      SH_PATHBUF+32);
290  sl_strlcpy (cc5,   _("--no-tty"),     32);
291
292  /* fprintf(stderr, "YULE: homedir=%s\n", homedir); */
293
294#if defined(SH_WITH_SERVER)
295  if (0 == sl_ret_euid())   /* privileges not dropped yet */
296    {
297      struct stat lbuf;
298      int         status_stat = 0;
299#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
300      struct passwd    pwd;
301      char          *  buffer = SH_ALLOC(SH_PWBUF_SIZE);
302      struct passwd *  tempres;
303      sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
304#else
305      struct passwd * tempres = sh_getpwnam(DEFAULT_IDENT);
306#endif
307
308      if (!tempres)
309        {
310          dlog(1, FIL__, __LINE__, 
311               _("User %s does not exist. Please add the user to your system.\n"), 
312               DEFAULT_IDENT);
313          status_stat = -1;
314        }
315      if (!tempres->pw_dir || tempres->pw_dir[0] == '\0')
316        {
317          dlog(1, FIL__, __LINE__, 
318               _("User %s does not have a home directory.\nPlease add the home directory for this user to your system.\n"), 
319               DEFAULT_IDENT);
320          status_stat = -2;
321        }
322      if (status_stat == 0)
323        {
324          sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32); 
325          sl_strlcat (cc4,   _("/.gnupg"),      SH_PATHBUF+32); 
326          status_stat =  retry_lstat(FIL__, __LINE__, cc4, &lbuf);
327          if (status_stat == -1)
328            {
329              dlog(1, FIL__, __LINE__, 
330                   _("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"),
331                   cc4, DEFAULT_IDENT);
332              status_stat = -3;
333            }
334        }
335      if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid)
336        {
337          dlog(1, FIL__, __LINE__, 
338               _("Gnupg directory %s\nis not owned by user %s.\n"), 
339               cc4, DEFAULT_IDENT);
340          status_stat = -4;
341        }
342      if (status_stat == 0)
343        {
344          sl_strlcat (cc4,   _("/pubring.gpg"),      SH_PATHBUF+32); 
345          status_stat =  retry_lstat(FIL__, __LINE__, cc4, &lbuf);
346          if (status_stat == -1)
347            {
348              dlog(1, FIL__, __LINE__, 
349                   _("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"),
350                   cc4, DEFAULT_IDENT);
351              status_stat = -5;
352            }
353        }
354      if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid)
355        {
356          dlog(1, FIL__, __LINE__, 
357               _("Gnupg public keyring %s\nis not owned by user %s.\n"), 
358               cc4, DEFAULT_IDENT);
359          status_stat = -6;
360        }
361      if (status_stat != 0)
362        {
363          sh_error_handle((-1), FIL__, __LINE__, status_stat, MSG_EXIT_ABORT1, 
364                          sh.prg_name);
365          aud_exit (FIL__, __LINE__, EXIT_FAILURE);
366        }
367      sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32); 
368      sl_strlcat (cc4,   _("/.gnupg"),      SH_PATHBUF+32); 
369#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
370      SH_FREE(buffer);
371#endif
372    }
373#endif
374
375  arg[0] = path; 
376  arg[1] = cc1;
377  arg[2] = "1";
378  arg[3] = cc2;
379  arg[4] = cc3;
380  arg[5] = cc4;
381  arg[6] = cc5;
382  arg[7] = cc0;
383  arg[8] = NULL;
384
385  /* catch 'unused parameter' compiler warning
386   */
387  (void) mode;
388  (void) id;
389#elif defined(WITH_PGP)
390  /* -- PGP -- */
391  sl_strlcpy (path,  DEFAULT_PGP_PATH, 256);
392  if (mode == 0)
393    {
394      sl_strlcpy (cc1,   _("+language=en"),  32);
395      sl_strlcpy (cc2,   _("-o"),     32);
396      sl_strlcpy (cc3,   _("/dev/null"),     32);
397     
398      arg[0] = path; 
399      arg[1] = cc1;
400      arg[2] = cc2; 
401      arg[3] = cc3; 
402      arg[4] = cc0;
403      arg[5] = NULL;
404    }
405  else
406    {
407      sl_strlcpy (cc1,   _("+language=en"),  32);
408      sl_strlcpy (cc2,   _("-kvc"),     32);       
409     
410      arg[0] = path; 
411      arg[1] = cc1;
412      arg[2] = cc2;
413      arg[3] = id;
414      arg[4] = NULL;
415      arg[5] = NULL;
416    }
417#endif
418
419  /* use homedir of effective user
420   */
421  len = sl_strlen(sh.effective.home) + 6;
422  envp[0] = calloc(1, len); /* free() ok   */
423  if (envp[0] != NULL)
424        sl_snprintf (envp[0], len, _("HOME=%s"), sh.effective.home); 
425  envp[1] = NULL;
426
427  /* Create the pipe
428   */
429  if (aud_pipe(FIL__, __LINE__, pipedes) < 0) 
430    {
431      if (envp[0] != NULL) 
432        free(envp[0]);
433      SL_RETURN( (NULL), _("sh_gpg_popen"));
434    }
435
436  fflush (NULL);
437 
438  source->pid = aud_fork(FIL__, __LINE__);
439 
440  /* Failure
441   */
442  if (source->pid == (pid_t) - 1) 
443    {
444      sl_close_fd(FIL__, __LINE__, pipedes[0]);
445      sl_close_fd(FIL__, __LINE__, pipedes[1]);
446      if (envp[0] != NULL) 
447        free(envp[0]);
448      SL_RETURN( (NULL), _("sh_gpg_popen"));
449    }
450
451  if (source->pid == (pid_t) 0) 
452    {
453
454      /* child - make read side of the pipe stdout
455       */
456      if (retry_aud_dup2(FIL__, __LINE__,
457                        pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
458        {
459          TPT(((0), FIL__, __LINE__, _("msg=<dup2 on pipe failed>\n")));
460          dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
461          aud__exit(FIL__, __LINE__, EXIT_FAILURE);
462        }
463     
464      /* close the pipe descriptors
465       */
466      sl_close_fd (FIL__, __LINE__, pipedes[STDIN_FILENO]);
467      sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
468     
469
470#if defined(WITH_PGP)
471      if (mode == 0) 
472        {
473          if (retry_aud_dup2(FIL__, __LINE__, fd, STDIN_FILENO) < 0)
474            {
475              TPT(((0), FIL__, __LINE__, _("msg=<dup2 on fd failed>\n")));
476              dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
477              aud__exit(FIL__, __LINE__, EXIT_FAILURE);
478            }
479        }
480#else
481      if (retry_aud_dup2(FIL__, __LINE__, fd, STDIN_FILENO) < 0)
482        {
483          TPT(((0), FIL__, __LINE__, _("msg=<dup2 on fd failed>\n")));
484          dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
485          aud__exit(FIL__, __LINE__, EXIT_FAILURE);
486        }
487#endif
488 
489      /* don't leak file descriptors
490       */
491      sh_unix_closeall (3, -1, SL_TRUE); /* in child process */
492
493      if (flag_err_debug != SL_TRUE)
494        {
495          if (NULL == freopen(_("/dev/null"), "r+", stderr))
496            {
497              dlog(1, FIL__, __LINE__, _("Internal error: freopen failed\n"));
498              aud__exit(FIL__, __LINE__, EXIT_FAILURE);
499            }
500        }
501
502
503      /* We should become privileged if SUID,
504       * to be able to read the keyring.
505       * We have checked that gpg is OK,
506       * AND that only a trusted user could overwrite
507       * gpg.
508       */
509      memset (skey, '\0', sizeof(sh_key_t));
510      aud_setuid(FIL__, __LINE__, geteuid());
511     
512      PDBGC_OPEN;
513      PDBGC_D((int)getuid());
514      PDBGC_D((int)geteuid());
515
516      {
517        int i = 0;
518        while (arg[i] != NULL)
519          {
520            PDBGC_S(arg[i]);
521            ++i;
522          }
523      }
524      PDBGC_CLOSE;
525
526      /* exec the program */
527
528#if defined(__linux__) && defined(HAVE_GPG_CHECKSUM)
529      /*
530       * --  emulate an fexecve with checksum testing
531       */
532#if defined(WITH_PGP)
533      checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_PGP_PATH, SL_NOPRIV);
534#else
535      checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_NOPRIV);
536#endif
537
538      if (0 != sh_gpg_checksum(checkfd, 0))
539        {
540          sl_close(checkfd);
541          aud__exit(FIL__, __LINE__, EXIT_FAILURE);
542        }
543
544      pfd = get_the_fd(checkfd);
545      do {
546        val_return = dup (pfd);
547      } while (val_return < 0 && errno == EINTR);
548      pfd = val_return;
549      sl_close(checkfd);
550      /* checkfd = -1; *//* never read */
551
552      sl_snprintf(pname, sizeof(pname), _("/proc/self/fd/%d"), pfd);
553      if (0 == access(pname, R_OK|X_OK))               /* flawfinder: ignore */
554
555        {
556          fcntl  (pfd, F_SETFD, FD_CLOEXEC);
557          retry_aud_execve (FIL__, __LINE__,  pname, arg, envp);
558             
559          dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
560               pname);
561          /* failed
562           */
563          aud__exit(FIL__, __LINE__, EXIT_FAILURE);
564        }
565         
566      /* procfs not working, go ahead
567       */
568#endif
569
570#if defined(HAVE_GPG_CHECKSUM)
571      /* This is an incredibly ugly kludge to prevent an attacker
572       * from knowing when it is safe to slip in a fake executable
573       * between the integrity check and the execve
574       */
575      myrand = (int) taus_get ();
576
577      myrand = (myrand < 0) ? (-myrand) : myrand;
578      myrand = (myrand % 32) + 2;
579
580      for (i = 0; i < myrand; ++i)
581        {
582#if defined(WITH_PGP)
583          checkfd = sl_open_fastread(FIL__, __LINE__, DEFAULT_PGP_PATH, SL_NOPRIV);
584#else
585          checkfd = sl_open_fastread(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_NOPRIV);
586#endif
587          if (0 != sh_gpg_checksum(checkfd, 0)) {
588            aud__exit(FIL__, __LINE__, EXIT_FAILURE);
589          }
590          sl_close(checkfd);
591        }
592#endif
593                               
594
595#if defined(WITH_GPG)
596      retry_aud_execve (FIL__, __LINE__, DEFAULT_GPG_PATH, arg, envp);
597      dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
598           DEFAULT_GPG_PATH);
599#elif defined(WITH_PGP)
600      retry_aud_execve (FIL__, __LINE__, DEFAULT_PGP_PATH, arg, envp);
601#endif
602     
603      /* failed
604       */
605      TPT(((0), FIL__, __LINE__, _("msg=<execve failed>\n")));
606      dlog(1, FIL__, __LINE__, _("Unexpected error: execve failed\n"));
607      aud__exit(FIL__, __LINE__, EXIT_FAILURE);
608    }
609
610  /* parent
611   */
612
613  if (envp[0] != NULL) 
614    free(envp[0]);
615
616  sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
617  retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
618  retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFL,  O_NONBLOCK);
619
620  outf = fdopen (pipedes[STDIN_FILENO], "r");
621 
622  if (outf == NULL) 
623    {
624      aud_kill (FIL__, __LINE__, source->pid, SIGKILL);
625      sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
626      waitpid (source->pid, NULL, 0);
627      source->pid = 0;
628      SL_RETURN( (NULL), _("sh_gpg_popen"));
629    }
630 
631  SL_RETURN( (outf), _("sh_gpg_popen"));
632}
633
634
635static int sh_gpg_pclose (sh_gpg_popen_t *source)
636{
637  int status = 0;
638 
639  SL_ENTER(_("sh_gpg_pclose"));
640
641  status = sl_fclose(FIL__, __LINE__, source->pipe);
642  if (status)
643    SL_RETURN( (-1), _("sh_gpg_pclose"));
644 
645  if (waitpid(source->pid, NULL, 0) != source->pid)
646    status = -1;
647 
648  source->pipe = NULL;
649  source->pid = 0;
650  SL_RETURN( (status), _("sh_gpg_pclose"));
651}
652 
653static
654int sh_gpg_check_file_sign(int fd, char * sign_id, char * sign_fp, 
655                           char * homedir, int whichfile)
656{
657  struct stat buf;
658  char line[256];
659  sh_gpg_popen_t  source;
660  int have_id = BAD, have_fp = BAD, status = 0;
661#ifdef WITH_PGP
662  char *ptr;
663#endif
664
665#ifdef HAVE_GPG_CHECKSUM
666  SL_TICKET checkfd;
667#endif
668
669  SL_ENTER(_("sh_gpg_check_file_sign"));
670
671  /* check whether GnuPG exists and has the correct checksum
672   */
673#if defined(WITH_GPG)
674
675  TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
676  TPT(((0), FIL__, __LINE__, _("msg=<gpg is %s>\n"), DEFAULT_GPG_PATH));
677
678  if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_GPG_PATH, &buf))
679    {
680      char errbuf[SH_ERRBUF_SIZE];
681
682      status = errno;
683      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT,
684                      sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_GPG_PATH);
685      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
686    }
687
688  if (0 != tf_trust_check (DEFAULT_GPG_PATH, SL_YESPRIV))
689    SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
690
691#ifdef HAVE_GPG_CHECKSUM
692  checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_YESPRIV);
693
694  if (0 != sh_gpg_checksum(checkfd, 1))
695    {
696      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
697                      _("Checksum mismatch"), 
698                      _("gpg_check_file_sign"));
699      sl_close(checkfd);
700      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
701    }
702  sl_close(checkfd);
703#endif
704
705#elif defined(WITH_PGP)
706
707  TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
708  TPT(((0), FIL__, __LINE__, _("msg=<pgp is %s>\n"), DEFAULT_PGP_PATH));
709
710  if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_PGP_PATH, &buf))
711    {
712      char errbuf[SH_ERRBUF_SIZE];
713
714      status = errno;
715      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT,
716                      sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_PGP_PATH);
717      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
718    }
719  if (0 != tf_trust_check (DEFAULT_PGP_PATH, SL_YESPRIV))
720    SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
721
722#ifdef HAVE_GPG_CHECKSUM
723  checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_PGP_PATH, SL_YESPRIV);
724
725  if (0 != sh_gpg_checksum(checkfd, 1))
726    {
727      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
728                      _("Checksum mismatch"), 
729                      _("gpg_check_file_sign"));
730      sl_close(checkfd);
731      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
732    }
733  sl_close(checkfd);
734#endif
735
736#endif
737
738  TPT(((0), FIL__, __LINE__, _("msg=<Open pipe to check signature>\n")));
739
740  fflush(NULL);
741 
742  source.pipe   = sh_gpg_popen  ( &source, fd, 0, NULL, homedir );
743
744  if (NULL == source.pipe)
745    {
746      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
747                      _("Could not open pipe"), 
748                      _("gpg_check_file_sign"));
749      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
750    }
751
752  TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
753
754 xagain:
755
756  errno = 0;
757
758  while (NULL != fgets(line, sizeof(line), source.pipe))
759    {
760
761      TPT(((0), FIL__, __LINE__, _("msg=<gpg out: %s>\n"), line));
762      if (line[strlen(line)-1] == '\n')
763        line[strlen(line)-1] = ' ';
764      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
765                      line, 
766                      _("gpg_check_file_sign"));
767
768      if (sl_strlen(line) < 18) 
769        continue;
770#if defined(WITH_GPG)
771      /* Sun May 27 18:40:05 CEST 2001
772       */
773      if (0 == sl_strncmp(_("BADSIG"), &line[9], 6) ||
774          0 == sl_strncmp(_("ERRSIG"), &line[9], 6) ||
775          0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6) ||
776          0 == sl_strncmp(_("NODATA"), &line[9], 6) ||
777          0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6))
778        {
779          if      (0 == sl_strncmp(_("BADSIG"), &line[9], 6)) {
780            dlog(1, FIL__, __LINE__, 
781                 _("%s file is signed, but the signature is invalid."),
782                 ((whichfile == 1) ? _("Configuration") : _("Database")));
783          } 
784          else if (0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6)) {
785            dlog(1, FIL__, __LINE__, 
786                 _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."), 
787                 ((whichfile == 1) ? _("Configuration") : _("Database")),
788                 homedir);
789          }
790          else if (0 == sl_strncmp(_("ERRSIG"), &line[9], 6)) {
791            dlog(1, FIL__, __LINE__, 
792                 _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."), 
793                 ((whichfile == 1) ? _("Configuration") : _("Database")),
794                 homedir);
795          }
796          else if (0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6)) {
797            dlog(1, FIL__, __LINE__, 
798                 _("%s file is signed, but the public key to verify the signature has expired."), 
799                 ((whichfile == 1) ? _("Configuration") : _("Database")));
800          }
801          else if (0 == sl_strncmp(_("NODATA"), &line[9], 6)) {
802            dlog(1, FIL__, __LINE__, 
803                 _("%s file is not signed."), 
804                 ((whichfile == 1) ? _("Configuration") : _("Database")));
805          }
806
807          have_fp = BAD; have_id = BAD;
808          break;
809        }
810      if (0 == sl_strncmp(_("GOODSIG"), &line[9], 7))
811        {
812          sl_strlcpy (sign_id, &line[25], SH_MINIBUF+1);
813          if (sign_id)
814            sign_id[sl_strlen(sign_id)-1] = '\0';  /* remove trailing '"' */
815          have_id = GOOD;
816        } 
817      if (0 == sl_strncmp(_("VALIDSIG"), &line[9], 8))
818        {
819          strncpy (sign_fp, &line[18], 40);
820          sign_fp[40] = '\0';
821          have_fp = GOOD;
822        }
823#elif defined(WITH_PGP)
824      if (0 == sl_strncmp(_("Bad signature"), line, 13) ||
825          0 == sl_strncmp(_("Error"), line, 5) ||
826          0 == sl_strncmp(_("Malformed"), line, 9) ||
827          0 == sl_strncmp(_("WARNING"), line, 7) ||
828          0 == sl_strncmp(_("ERROR"), line, 5) 
829          )
830        {
831          have_fp = BAD; have_id = BAD;
832          break;
833        }
834      if (0 == sl_strncmp(_("Good signature"), line, 14))
835        {
836          ptr = strchr ( line, '"');
837          ++ptr;
838          if (ptr)
839            {
840              sl_strlcpy (sign_id, ptr, SH_MINIBUF+1);
841              sign_id[sl_strlen(sign_id)-1] = '\0'; /* remove trailing dot */
842              sign_id[sl_strlen(sign_id)-2] = '\0'; /* remove trailing '"' */
843            }
844          else
845            {
846              sl_strlcpy (sign_id, _("(null)"), SH_MINIBUF+1);
847            }
848          have_id = GOOD;
849        }
850#endif
851    }
852
853  if (ferror(source.pipe) && errno == EAGAIN) 
854    {
855      retry_msleep(0,10); /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
856      clearerr(source.pipe);
857      goto xagain;
858    }
859 
860  sh_gpg_pclose (&source);
861
862  TPT(((0), FIL__, __LINE__, _("msg=<Close pipe>\n")));
863
864#ifdef WITH_PGP
865  /* get the fingerprint */
866
867  source.pipe   = sh_gpg_popen  ( &source, fd, 1,  sign_id, homedir);
868  if (NULL == source.pipe)
869    {
870      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
871                      _("Could not open pipe for fp"), 
872                      _("gpg_check_file_sign"));
873      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
874    }
875
876  TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
877
878 yagain:
879
880  errno = 0;
881
882  while (NULL != fgets(line, sizeof(line), source.pipe))
883    {
884#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
885      char * saveptr = NULL;
886#endif
887      if (line[strlen(line)-1] == '\n')
888        line[strlen(line)-1] = ' ';
889      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
890                      line, 
891                      _("gpg_check_file_sign"));
892
893      if (sl_strlen(line) < 18) 
894        continue;
895#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
896      ptr = strtok_r (line, " ", &saveptr);
897#else
898      ptr = strtok (line, " ");
899#endif
900      while (ptr)
901        {
902#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
903          ptr = strtok_r (NULL, " ", &saveptr);
904#else
905          ptr = strtok (NULL, " ");
906#endif
907          if (ptr && 0 == sl_strncmp (ptr, _("fingerprint"), 11))
908            {
909#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
910              ptr = strtok_r (NULL, " ", &saveptr); /* to '=' */
911#else
912              ptr = strtok (NULL, " "); /* to '=' */
913#endif
914              sign_fp[0] = '\0';
915              while (ptr)
916                {
917#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
918                  ptr = strtok_r (NULL, " ", &saveptr); /* part of fingerprint */
919#else
920                  ptr = strtok (NULL, " "); /* part of fingerprint */
921#endif
922                  sl_strlcat (sign_fp, ptr, SH_MINIBUF+1);
923                }
924              /* sign_fp[sl_strlen(sign_fp)-1] = '\0'; remove trailing '\n' */
925              if (sl_strlen(sign_fp) > 0) 
926                have_fp = GOOD;
927              break;
928            } 
929        } 
930    }
931
932  if (ferror(source.pipe) && errno == EAGAIN) 
933    {
934      retry_msleep(0,10); /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
935      clearerr(source.pipe);
936      goto yagain;
937    }
938 
939  sh_gpg_pclose (&source);
940#endif
941
942  if (have_id == GOOD)
943    {
944      TPT(((0), FIL__, __LINE__, _("msg=<Got signator ID>\n")));
945      ;
946    }
947  if (have_fp == GOOD)
948    {
949      TPT(((0), FIL__, __LINE__, _("msg=<Got fingerprint>\n")));
950      ;
951    }
952
953  if (have_id == GOOD && have_fp == GOOD)
954    SL_RETURN( SH_GPG_OK, _("sh_gpg_check_file_sign"));
955  else
956    {
957      if (have_id == BAD)
958        sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
959                        _("No good signature"), 
960                        _("gpg_check_file_sign"));
961      else
962        sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
963                        _("No fingerprint for key"), 
964                        _("gpg_check_file_sign"));
965      SL_RETURN( SH_GPG_BADSIGN, _("sh_gpg_check_file_sign"));
966    }
967}
968
969int get_the_fd(SL_TICKET file_1);
970
971int sh_gpg_check_sign (long file_1, long file_2, int what)
972{
973  int status = SH_GPG_BAD;
974  int fd1 = 0;
975  int fd2 = 0;
976  static int smsg = S_FALSE;
977  char  * tmp;
978  char  * tmp2;
979
980  char  * homedir = sh.effective.home;
981#if defined(SH_WITH_SERVER)
982  struct passwd * tempres;
983#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
984  struct passwd    pwd;
985  char           * buffer = SH_ALLOC(SH_PWBUF_SIZE);
986#endif
987#endif
988
989#ifdef USE_FINGERPRINT
990#include "sh_gpg_fp.h"
991#endif
992
993  SL_ENTER(_("sh_gpg_check_sign"));
994
995
996  if (what == 0 || what == 1)
997    fd1 = get_the_fd(file_1);
998  if (what == 0 || what == 2)
999    fd2 = get_the_fd(file_2);
1000
1001
1002  if (fd1 < 0 || fd2 < 0)
1003    {
1004      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD1 = %d>\n"), fd1));
1005      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD2 = %d>\n"), fd2));
1006      dlog(1, FIL__, __LINE__, 
1007           _("This looks like an unexpected internal error.\n"));
1008      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name);
1009      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1010#if defined(SH_WITH_SERVER)
1011#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1012      SH_FREE(buffer);
1013#endif
1014#endif
1015      SL_RETURN( (-1), _("sh_gpg_check_sign"));
1016    }
1017 
1018  if (what == 0 || what == 1)
1019    {
1020      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD1 = %d>\n"), fd1));
1021#if defined(SH_WITH_SERVER)
1022#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1023      sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
1024#else
1025      tempres = sh_getpwnam(DEFAULT_IDENT);
1026#endif
1027
1028      if ((tempres != NULL) && (0 == sl_ret_euid()))
1029        {
1030          /* privileges not dropped yet*/
1031          homedir = tempres->pw_dir;
1032        }
1033#endif
1034      status = sh_gpg_check_file_sign(fd1, gp.conf_id, gp.conf_fp, homedir, 1);
1035      TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGUSR: |%s|>\n"), gp.conf_id));
1036      TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGFP:  |%s|>\n"), gp.conf_fp));
1037    }
1038
1039  if ((what == 0 && SH_GPG_OK == status) || what == 2)
1040    {
1041      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD2 = %d>\n"), fd2));
1042#if defined(SH_WITH_SERVER)
1043#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1044      sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
1045#else
1046      tempres = sh_getpwnam(DEFAULT_IDENT);
1047#endif
1048
1049      if ((tempres != NULL) && (0 == sl_ret_euid()))
1050        {
1051          /* privileges not dropped yet*/
1052          homedir = tempres->pw_dir;
1053        }
1054#endif
1055      status = sh_gpg_check_file_sign(fd2, gp.data_id, gp.data_fp, homedir, 2);
1056      TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGUSR: |%s|>\n"), gp.data_id));
1057      TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGFP:  |%s|>\n"), gp.data_fp));
1058    }
1059 
1060  if (SH_GPG_OK == status && what == 1)
1061    {
1062#ifdef USE_FINGERPRINT
1063      if ((sl_strcmp(SH_GPG_FP, gp.conf_fp) == 0))
1064        {
1065          int i;
1066
1067          for(i = 0; i < (int) sl_strlen(gp.conf_fp); ++i)
1068            {
1069              if (gpgfp[i] != gp.conf_fp[i]) 
1070                {
1071                  sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
1072                                  MSG_E_GPG_FP, 
1073                                  gpgfp, gp.conf_fp);
1074                  break;
1075                }
1076            }
1077
1078          if (smsg == S_FALSE)
1079            {
1080              tmp  = sh_util_safe_name(gp.conf_id);
1081              sh_gpg_fill_startup (__LINE__,
1082                                   /* sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH, */
1083                               sh.prg_name, sh.real.uid,
1084                               (sh.flag.hidefile == S_TRUE) ? 
1085                               _("(hidden)") : file_path('C', 'R'), 
1086                               tmp, 
1087                               gp.conf_fp);
1088              SH_FREE(tmp);
1089            }
1090          smsg = S_TRUE;
1091#if defined(SH_WITH_SERVER)
1092#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1093          SH_FREE(buffer);
1094#endif
1095#endif
1096          SL_RETURN(0, _("sh_gpg_check_sign"));
1097        }
1098      else
1099        {
1100          /* fp mismatch
1101           */
1102          dlog(1, FIL__, __LINE__, 
1103               _("The fingerprint of the signing key: %s\ndoes not match the compiled-in fingerprint: %s.\nTherefore the signature could not be verified.\n"), 
1104               gp.conf_fp, SH_GPG_FP);
1105          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
1106                      _("Fingerprint mismatch"), 
1107                      _("gpg_check_sign"));
1108          status = SH_GPG_BADSIGN;
1109        }
1110#else
1111      if (smsg == S_FALSE)
1112        {
1113          tmp = sh_util_safe_name(gp.conf_id);
1114          sh_gpg_fill_startup (__LINE__,
1115          /* sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH, */
1116                           sh.prg_name, sh.real.uid,
1117                           (sh.flag.hidefile == S_TRUE) ? 
1118                           _("(hidden)") : file_path('C', 'R'), 
1119                           tmp, 
1120                           gp.conf_fp);
1121          SH_FREE(tmp);
1122        }
1123      smsg = S_TRUE;
1124#if defined(SH_WITH_SERVER)
1125#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1126      SH_FREE(buffer);
1127#endif
1128#endif
1129      SL_RETURN(0, _("sh_gpg_check_sign"));
1130#endif
1131    }
1132 
1133  else if (SH_GPG_OK == status && (what == 2 || what == 0))
1134    {
1135      if ((sl_strcmp(gp.data_id, gp.conf_id) == 0) &&
1136          (sl_strcmp(gp.data_fp, gp.conf_fp) == 0))
1137        {
1138#if defined(SH_WITH_SERVER)
1139#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1140          SH_FREE(buffer);
1141#endif
1142#endif
1143          SL_RETURN(0, _("sh_gpg_check_sign"));
1144        }
1145      else
1146        {
1147          /* ID or fp not equal
1148           */
1149          dlog(1, FIL__, __LINE__, 
1150               _("The fingerprint or ID of the signing key is not the same for the\nconfiguration file and the file signature database.\nTherefore the signature could not be verified.\n"));
1151          tmp  = sh_util_safe_name (gp.conf_id);
1152          tmp2 = sh_util_safe_name (gp.data_id);
1153          sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH2,
1154                           sh.prg_name, sh.real.uid,
1155                           (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'),
1156                           tmp,  gp.conf_fp,
1157                           (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('D', 'R'),
1158                           tmp2, gp.data_fp);
1159          SH_FREE(tmp);
1160          SH_FREE(tmp2);
1161        }
1162    }
1163
1164  if (status != SH_GPG_OK) 
1165    {
1166      uid_t   e_uid  = sl_ret_euid();
1167      char  * e_home = sh.effective.home;
1168
1169#if defined(SH_WITH_SERVER)
1170#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1171      struct passwd    e_pwd;
1172      char          *  e_buffer = SH_ALLOC(SH_PWBUF_SIZE);
1173      struct passwd *  e_tempres;
1174      sh_getpwnam_r(DEFAULT_IDENT, &e_pwd, e_buffer, SH_PWBUF_SIZE, &e_tempres);
1175#else
1176      struct passwd * e_tempres = sh_getpwnam(DEFAULT_IDENT);
1177#endif
1178
1179      if ((e_tempres != NULL) && (0 == sl_ret_euid()))   
1180        {
1181          /* privileges not dropped yet */
1182          e_uid  = e_tempres->pw_uid;
1183          e_home = e_tempres->pw_dir;
1184        }
1185#endif
1186      dlog(1, FIL__, __LINE__, 
1187           _("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"),
1188#if defined(WITH_GPG)
1189           DEFAULT_GPG_PATH,
1190#else
1191           DEFAULT_PGP_PATH,
1192#endif
1193           (int) e_uid, e_home);
1194
1195#if defined(SH_WITH_SERVER)
1196#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1197      SH_FREE(e_buffer);
1198#endif
1199#endif
1200    }
1201
1202  TPT(((0), FIL__, __LINE__, _("msg=<Status = %d>\n"), status));
1203
1204  sh_error_handle((-1), FIL__, __LINE__, status, MSG_EXIT_ABORT1, sh.prg_name);
1205  aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1206
1207  return (-1); /* make compiler happy */
1208} 
1209
1210#define FGETS_BUF 16384
1211
1212SL_TICKET sh_gpg_extract_signed(SL_TICKET fd)
1213{
1214  FILE * fin_cp = NULL;
1215  char * buf    = NULL;
1216  int    bufc;
1217  int    flag_pgp    = S_FALSE;
1218  int    flag_nohead = S_FALSE;
1219  SL_TICKET fdTmp = (-1);
1220  SL_TICKET open_tmp (void);
1221
1222  /* extract the data and copy to temporary file
1223   */
1224  fdTmp = open_tmp();
1225
1226  fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
1227  buf = SH_ALLOC(FGETS_BUF);
1228
1229  while (NULL != fgets(buf, FGETS_BUF, fin_cp))
1230    {
1231      bufc = 0; 
1232      while (bufc < FGETS_BUF) { 
1233        if (buf[bufc] == '\n') { ++bufc; break; }
1234        ++bufc;
1235      }
1236
1237      if (flag_pgp == S_FALSE &&
1238          (0 == sl_strcmp(buf, _("-----BEGIN PGP SIGNED MESSAGE-----\n"))||
1239           0 == sl_strcmp(buf, _("-----BEGIN PGP MESSAGE-----\n")))
1240          )
1241        {
1242          flag_pgp = S_TRUE;
1243          sl_write(fdTmp, buf, bufc);
1244          continue;
1245        }
1246     
1247      if (flag_pgp == S_TRUE && flag_nohead == S_FALSE)
1248        {
1249          if (buf[0] == '\n')
1250            {
1251              flag_nohead = S_TRUE;
1252              sl_write(fdTmp, buf, 1);
1253              continue;
1254            }
1255          else if (0 == sl_strncmp(buf, _("Hash:"), 5) ||
1256                   0 == sl_strncmp(buf, _("NotDashEscaped:"), 15))
1257            {
1258              sl_write(fdTmp, buf, bufc);
1259              continue;
1260            }
1261          else
1262            continue;
1263        }
1264   
1265      if (flag_pgp == S_TRUE && buf[0] == '\n')
1266        {
1267          sl_write(fdTmp, buf, 1);
1268        }
1269      else if (flag_pgp == S_TRUE)
1270        {
1271          /* sl_write_line(fdTmp, buf, bufc); */
1272          sl_write(fdTmp, buf, bufc);
1273        }
1274     
1275      if (flag_pgp == S_TRUE && 
1276          0 == sl_strcmp(buf, _("-----END PGP SIGNATURE-----\n")))
1277        break;
1278    }
1279  SH_FREE(buf);
1280  sl_fclose(FIL__, __LINE__, fin_cp); /* fin_cp = fdopen(dup(), "rb"); */
1281  sl_rewind (fdTmp);
1282
1283  return fdTmp;
1284}
1285
1286/* #ifdef WITH_GPG */
1287#endif
1288
1289
1290
1291
1292
1293
1294
1295
Note: See TracBrowser for help on using the repository browser.