source: trunk/src/sh_gpg.c@ 394

Last change on this file since 394 was 391, checked in by katerina, 13 years ago

Fix for ticket #288 (the --with-gpg option can cause startup to hang).

File size: 35.2 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 if (sh.effective.home != NULL)
422 {
423 len = sl_strlen(sh.effective.home) + 6;
424 envp[0] = malloc (len); /* free() ok */
425 if (envp[0] != NULL)
426 sl_snprintf (envp[0], len, _("HOME=%s"), sh.effective.home);
427 envp[1] = NULL;
428 }
429 else
430 {
431 envp[0] = NULL;
432 }
433
434 /* Create the pipe
435 */
436 if (aud_pipe(FIL__, __LINE__, pipedes) < 0)
437 {
438 if (envp[0] != NULL)
439 free(envp[0]);
440 SL_RETURN( (NULL), _("sh_gpg_popen"));
441 }
442
443 fflush (NULL);
444
445 source->pid = aud_fork(FIL__, __LINE__);
446
447 /* Failure
448 */
449 if (source->pid == (pid_t) - 1)
450 {
451 sl_close_fd(FIL__, __LINE__, pipedes[0]);
452 sl_close_fd(FIL__, __LINE__, pipedes[1]);
453 if (envp[0] != NULL)
454 free(envp[0]);
455 SL_RETURN( (NULL), _("sh_gpg_popen"));
456 }
457
458 if (source->pid == (pid_t) 0)
459 {
460
461 /* child - make read side of the pipe stdout
462 */
463 if (retry_aud_dup2(FIL__, __LINE__,
464 pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
465 {
466 TPT(((0), FIL__, __LINE__, _("msg=<dup2 on pipe failed>\n")));
467 dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
468 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
469 }
470
471 /* close the pipe descriptors
472 */
473 sl_close_fd (FIL__, __LINE__, pipedes[STDIN_FILENO]);
474 sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
475
476
477#if defined(WITH_PGP)
478 if (mode == 0)
479 {
480 if (retry_aud_dup2(FIL__, __LINE__, fd, STDIN_FILENO) < 0)
481 {
482 TPT(((0), FIL__, __LINE__, _("msg=<dup2 on fd failed>\n")));
483 dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
484 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
485 }
486 }
487#else
488 if (retry_aud_dup2(FIL__, __LINE__, fd, STDIN_FILENO) < 0)
489 {
490 TPT(((0), FIL__, __LINE__, _("msg=<dup2 on fd failed>\n")));
491 dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
492 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
493 }
494#endif
495
496 /* don't leak file descriptors
497 */
498 sh_unix_closeall (3, -1, SL_TRUE); /* in child process */
499
500 if (flag_err_debug != SL_TRUE)
501 {
502 if (NULL == freopen(_("/dev/null"), "r+", stderr))
503 {
504 dlog(1, FIL__, __LINE__, _("Internal error: freopen failed\n"));
505 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
506 }
507 }
508
509
510 /* We should become privileged if SUID,
511 * to be able to read the keyring.
512 * We have checked that gpg is OK,
513 * AND that only a trusted user could overwrite
514 * gpg.
515 */
516 memset (skey, '\0', sizeof(sh_key_t));
517 aud_setuid(FIL__, __LINE__, geteuid());
518
519 PDBGC_OPEN;
520 PDBGC_D((int)getuid());
521 PDBGC_D((int)geteuid());
522
523 {
524 int i = 0;
525 while (arg[i] != NULL)
526 {
527 PDBGC_S(arg[i]);
528 ++i;
529 }
530 }
531 PDBGC_CLOSE;
532
533 /* exec the program */
534
535#if defined(__linux__) && defined(HAVE_GPG_CHECKSUM)
536 /*
537 * -- emulate an fexecve with checksum testing
538 */
539#if defined(WITH_PGP)
540 checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_PGP_PATH, SL_NOPRIV);
541#else
542 checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_NOPRIV);
543#endif
544
545 if (0 != sh_gpg_checksum(checkfd, 0))
546 {
547 sl_close(checkfd);
548 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
549 }
550
551 pfd = get_the_fd(checkfd);
552 do {
553 val_return = dup (pfd);
554 } while (val_return < 0 && errno == EINTR);
555 pfd = val_return;
556 sl_close(checkfd);
557 /* checkfd = -1; *//* never read */
558
559 sl_snprintf(pname, sizeof(pname), _("/proc/self/fd/%d"), pfd);
560 if (0 == access(pname, R_OK|X_OK)) /* flawfinder: ignore */
561
562 {
563 fcntl (pfd, F_SETFD, FD_CLOEXEC);
564 retry_aud_execve (FIL__, __LINE__, pname, arg, envp);
565
566 dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
567 pname);
568 /* failed
569 */
570 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
571 }
572
573 /* procfs not working, go ahead
574 */
575#endif
576
577#if defined(HAVE_GPG_CHECKSUM)
578 /* This is an incredibly ugly kludge to prevent an attacker
579 * from knowing when it is safe to slip in a fake executable
580 * between the integrity check and the execve
581 */
582 myrand = (int) taus_get ();
583
584 myrand = (myrand < 0) ? (-myrand) : myrand;
585 myrand = (myrand % 32) + 2;
586
587 for (i = 0; i < myrand; ++i)
588 {
589#if defined(WITH_PGP)
590 checkfd = sl_open_fastread(FIL__, __LINE__, DEFAULT_PGP_PATH, SL_NOPRIV);
591#else
592 checkfd = sl_open_fastread(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_NOPRIV);
593#endif
594 if (0 != sh_gpg_checksum(checkfd, 0)) {
595 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
596 }
597 sl_close(checkfd);
598 }
599#endif
600
601
602#if defined(WITH_GPG)
603 retry_aud_execve (FIL__, __LINE__, DEFAULT_GPG_PATH, arg, envp);
604 dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
605 DEFAULT_GPG_PATH);
606#elif defined(WITH_PGP)
607 retry_aud_execve (FIL__, __LINE__, DEFAULT_PGP_PATH, arg, envp);
608#endif
609
610 /* failed
611 */
612 TPT(((0), FIL__, __LINE__, _("msg=<execve failed>\n")));
613 dlog(1, FIL__, __LINE__, _("Unexpected error: execve failed\n"));
614 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
615 }
616
617 /* parent
618 */
619
620 if (envp[0] != NULL)
621 free(envp[0]);
622
623 sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
624 retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
625 retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFL, O_NONBLOCK);
626
627 outf = fdopen (pipedes[STDIN_FILENO], "r");
628
629 if (outf == NULL)
630 {
631 aud_kill (FIL__, __LINE__, source->pid, SIGKILL);
632 sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
633 waitpid (source->pid, NULL, 0);
634 source->pid = 0;
635 SL_RETURN( (NULL), _("sh_gpg_popen"));
636 }
637
638 SL_RETURN( (outf), _("sh_gpg_popen"));
639}
640
641
642static int sh_gpg_pclose (sh_gpg_popen_t *source)
643{
644 int status = 0;
645
646 SL_ENTER(_("sh_gpg_pclose"));
647
648 status = sl_fclose(FIL__, __LINE__, source->pipe);
649 if (status)
650 SL_RETURN( (-1), _("sh_gpg_pclose"));
651
652 if (waitpid(source->pid, NULL, 0) != source->pid)
653 status = -1;
654
655 source->pipe = NULL;
656 source->pid = 0;
657 SL_RETURN( (status), _("sh_gpg_pclose"));
658}
659
660static
661int sh_gpg_check_file_sign(int fd, char * sign_id, char * sign_fp,
662 char * homedir, int whichfile)
663{
664 struct stat buf;
665 char line[256];
666 sh_gpg_popen_t source;
667 int have_id = BAD, have_fp = BAD, status = 0;
668#ifdef WITH_PGP
669 char *ptr;
670#endif
671
672#ifdef HAVE_GPG_CHECKSUM
673 SL_TICKET checkfd;
674#endif
675
676 SL_ENTER(_("sh_gpg_check_file_sign"));
677
678 /* check whether GnuPG exists and has the correct checksum
679 */
680#if defined(WITH_GPG)
681
682 TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
683 TPT(((0), FIL__, __LINE__, _("msg=<gpg is %s>\n"), DEFAULT_GPG_PATH));
684
685 if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_GPG_PATH, &buf))
686 {
687 char errbuf[SH_ERRBUF_SIZE];
688
689 status = errno;
690 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT,
691 sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_GPG_PATH);
692 SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
693 }
694
695 if (0 != tf_trust_check (DEFAULT_GPG_PATH, SL_YESPRIV))
696 SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
697
698#ifdef HAVE_GPG_CHECKSUM
699 checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_YESPRIV);
700
701 if (0 != sh_gpg_checksum(checkfd, 1))
702 {
703 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
704 _("Checksum mismatch"),
705 _("gpg_check_file_sign"));
706 sl_close(checkfd);
707 SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
708 }
709 sl_close(checkfd);
710#endif
711
712#elif defined(WITH_PGP)
713
714 TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
715 TPT(((0), FIL__, __LINE__, _("msg=<pgp is %s>\n"), DEFAULT_PGP_PATH));
716
717 if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_PGP_PATH, &buf))
718 {
719 char errbuf[SH_ERRBUF_SIZE];
720
721 status = errno;
722 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT,
723 sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_PGP_PATH);
724 SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
725 }
726 if (0 != tf_trust_check (DEFAULT_PGP_PATH, SL_YESPRIV))
727 SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
728
729#ifdef HAVE_GPG_CHECKSUM
730 checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_PGP_PATH, SL_YESPRIV);
731
732 if (0 != sh_gpg_checksum(checkfd, 1))
733 {
734 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
735 _("Checksum mismatch"),
736 _("gpg_check_file_sign"));
737 sl_close(checkfd);
738 SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
739 }
740 sl_close(checkfd);
741#endif
742
743#endif
744
745 TPT(((0), FIL__, __LINE__, _("msg=<Open pipe to check signature>\n")));
746
747 fflush(NULL);
748
749 source.pipe = sh_gpg_popen ( &source, fd, 0, NULL, homedir );
750
751 if (NULL == source.pipe)
752 {
753 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
754 _("Could not open pipe"),
755 _("gpg_check_file_sign"));
756 SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
757 }
758
759 TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
760
761 xagain:
762
763 errno = 0;
764
765 while (NULL != fgets(line, sizeof(line), source.pipe))
766 {
767
768 TPT(((0), FIL__, __LINE__, _("msg=<gpg out: %s>\n"), line));
769 if (line[strlen(line)-1] == '\n')
770 line[strlen(line)-1] = ' ';
771 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
772 line,
773 _("gpg_check_file_sign"));
774
775 if (sl_strlen(line) < 18)
776 continue;
777#if defined(WITH_GPG)
778 /* Sun May 27 18:40:05 CEST 2001
779 */
780 if (0 == sl_strncmp(_("BADSIG"), &line[9], 6) ||
781 0 == sl_strncmp(_("ERRSIG"), &line[9], 6) ||
782 0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6) ||
783 0 == sl_strncmp(_("NODATA"), &line[9], 6) ||
784 0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6))
785 {
786 if (0 == sl_strncmp(_("BADSIG"), &line[9], 6)) {
787 dlog(1, FIL__, __LINE__,
788 _("%s file is signed, but the signature is invalid."),
789 ((whichfile == 1) ? _("Configuration") : _("Database")));
790 }
791 else if (0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6)) {
792 dlog(1, FIL__, __LINE__,
793 _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."),
794 ((whichfile == 1) ? _("Configuration") : _("Database")),
795 homedir);
796 }
797 else if (0 == sl_strncmp(_("ERRSIG"), &line[9], 6)) {
798 dlog(1, FIL__, __LINE__,
799 _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."),
800 ((whichfile == 1) ? _("Configuration") : _("Database")),
801 homedir);
802 }
803 else if (0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6)) {
804 dlog(1, FIL__, __LINE__,
805 _("%s file is signed, but the public key to verify the signature has expired."),
806 ((whichfile == 1) ? _("Configuration") : _("Database")));
807 }
808 else if (0 == sl_strncmp(_("NODATA"), &line[9], 6)) {
809 dlog(1, FIL__, __LINE__,
810 _("%s file is not signed."),
811 ((whichfile == 1) ? _("Configuration") : _("Database")));
812 }
813
814 have_fp = BAD; have_id = BAD;
815 break;
816 }
817 if (0 == sl_strncmp(_("GOODSIG"), &line[9], 7))
818 {
819 sl_strlcpy (sign_id, &line[25], SH_MINIBUF+1);
820 if (sign_id)
821 sign_id[sl_strlen(sign_id)-1] = '\0'; /* remove trailing '"' */
822 have_id = GOOD;
823 }
824 if (0 == sl_strncmp(_("VALIDSIG"), &line[9], 8))
825 {
826 strncpy (sign_fp, &line[18], 40);
827 sign_fp[40] = '\0';
828 have_fp = GOOD;
829 }
830#elif defined(WITH_PGP)
831 if (0 == sl_strncmp(_("Bad signature"), line, 13) ||
832 0 == sl_strncmp(_("Error"), line, 5) ||
833 0 == sl_strncmp(_("Malformed"), line, 9) ||
834 0 == sl_strncmp(_("WARNING"), line, 7) ||
835 0 == sl_strncmp(_("ERROR"), line, 5)
836 )
837 {
838 have_fp = BAD; have_id = BAD;
839 break;
840 }
841 if (0 == sl_strncmp(_("Good signature"), line, 14))
842 {
843 ptr = strchr ( line, '"');
844 ++ptr;
845 if (ptr)
846 {
847 sl_strlcpy (sign_id, ptr, SH_MINIBUF+1);
848 sign_id[sl_strlen(sign_id)-1] = '\0'; /* remove trailing dot */
849 sign_id[sl_strlen(sign_id)-2] = '\0'; /* remove trailing '"' */
850 }
851 else
852 {
853 sl_strlcpy (sign_id, _("(null)"), SH_MINIBUF+1);
854 }
855 have_id = GOOD;
856 }
857#endif
858 }
859
860 if (ferror(source.pipe) && errno == EAGAIN)
861 {
862 retry_msleep(0,10); /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
863 clearerr(source.pipe);
864 goto xagain;
865 }
866
867 sh_gpg_pclose (&source);
868
869 TPT(((0), FIL__, __LINE__, _("msg=<Close pipe>\n")));
870
871#ifdef WITH_PGP
872 /* get the fingerprint */
873
874 source.pipe = sh_gpg_popen ( &source, fd, 1, sign_id, homedir);
875 if (NULL == source.pipe)
876 {
877 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
878 _("Could not open pipe for fp"),
879 _("gpg_check_file_sign"));
880 SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
881 }
882
883 TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
884
885 yagain:
886
887 errno = 0;
888
889 while (NULL != fgets(line, sizeof(line), source.pipe))
890 {
891#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
892 char * saveptr = NULL;
893#endif
894 if (line[strlen(line)-1] == '\n')
895 line[strlen(line)-1] = ' ';
896 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
897 line,
898 _("gpg_check_file_sign"));
899
900 if (sl_strlen(line) < 18)
901 continue;
902#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
903 ptr = strtok_r (line, " ", &saveptr);
904#else
905 ptr = strtok (line, " ");
906#endif
907 while (ptr)
908 {
909#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
910 ptr = strtok_r (NULL, " ", &saveptr);
911#else
912 ptr = strtok (NULL, " ");
913#endif
914 if (ptr && 0 == sl_strncmp (ptr, _("fingerprint"), 11))
915 {
916#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
917 ptr = strtok_r (NULL, " ", &saveptr); /* to '=' */
918#else
919 ptr = strtok (NULL, " "); /* to '=' */
920#endif
921 sign_fp[0] = '\0';
922 while (ptr)
923 {
924#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
925 ptr = strtok_r (NULL, " ", &saveptr); /* part of fingerprint */
926#else
927 ptr = strtok (NULL, " "); /* part of fingerprint */
928#endif
929 sl_strlcat (sign_fp, ptr, SH_MINIBUF+1);
930 }
931 /* sign_fp[sl_strlen(sign_fp)-1] = '\0'; remove trailing '\n' */
932 if (sl_strlen(sign_fp) > 0)
933 have_fp = GOOD;
934 break;
935 }
936 }
937 }
938
939 if (ferror(source.pipe) && errno == EAGAIN)
940 {
941 retry_msleep(0,10); /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
942 clearerr(source.pipe);
943 goto yagain;
944 }
945
946 sh_gpg_pclose (&source);
947#endif
948
949 if (have_id == GOOD)
950 {
951 TPT(((0), FIL__, __LINE__, _("msg=<Got signator ID>\n")));
952 ;
953 }
954 if (have_fp == GOOD)
955 {
956 TPT(((0), FIL__, __LINE__, _("msg=<Got fingerprint>\n")));
957 ;
958 }
959
960 if (have_id == GOOD && have_fp == GOOD)
961 SL_RETURN( SH_GPG_OK, _("sh_gpg_check_file_sign"));
962 else
963 {
964 if (have_id == BAD)
965 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
966 _("No good signature"),
967 _("gpg_check_file_sign"));
968 else
969 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
970 _("No fingerprint for key"),
971 _("gpg_check_file_sign"));
972 SL_RETURN( SH_GPG_BADSIGN, _("sh_gpg_check_file_sign"));
973 }
974}
975
976int get_the_fd(SL_TICKET file_1);
977
978int sh_gpg_check_sign (long file_1, long file_2, int what)
979{
980 int status = SH_GPG_BAD;
981 int fd1 = 0;
982 int fd2 = 0;
983 static int smsg = S_FALSE;
984 char * tmp;
985 char * tmp2;
986
987 char * homedir = sh.effective.home;
988#if defined(SH_WITH_SERVER)
989 struct passwd * tempres;
990#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
991 struct passwd pwd;
992 char * buffer = SH_ALLOC(SH_PWBUF_SIZE);
993#endif
994#endif
995
996#ifdef USE_FINGERPRINT
997#include "sh_gpg_fp.h"
998#endif
999
1000 SL_ENTER(_("sh_gpg_check_sign"));
1001
1002
1003 if (what == 0 || what == 1)
1004 fd1 = get_the_fd(file_1);
1005 if (what == 0 || what == 2)
1006 fd2 = get_the_fd(file_2);
1007
1008
1009 if (fd1 < 0 || fd2 < 0)
1010 {
1011 TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD1 = %d>\n"), fd1));
1012 TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD2 = %d>\n"), fd2));
1013 dlog(1, FIL__, __LINE__,
1014 _("This looks like an unexpected internal error.\n"));
1015 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name);
1016 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1017#if defined(SH_WITH_SERVER)
1018#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1019 SH_FREE(buffer);
1020#endif
1021#endif
1022 SL_RETURN( (-1), _("sh_gpg_check_sign"));
1023 }
1024
1025 if (what == 0 || what == 1)
1026 {
1027 TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD1 = %d>\n"), fd1));
1028#if defined(SH_WITH_SERVER)
1029#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1030 sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
1031#else
1032 tempres = sh_getpwnam(DEFAULT_IDENT);
1033#endif
1034
1035 if ((tempres != NULL) && (0 == sl_ret_euid()))
1036 {
1037 /* privileges not dropped yet*/
1038 homedir = tempres->pw_dir;
1039 }
1040#endif
1041 status = sh_gpg_check_file_sign(fd1, gp.conf_id, gp.conf_fp, homedir, 1);
1042 TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGUSR: |%s|>\n"), gp.conf_id));
1043 TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGFP: |%s|>\n"), gp.conf_fp));
1044 }
1045
1046 if ((what == 0 && SH_GPG_OK == status) || what == 2)
1047 {
1048 TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD2 = %d>\n"), fd2));
1049#if defined(SH_WITH_SERVER)
1050#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1051 sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
1052#else
1053 tempres = sh_getpwnam(DEFAULT_IDENT);
1054#endif
1055
1056 if ((tempres != NULL) && (0 == sl_ret_euid()))
1057 {
1058 /* privileges not dropped yet*/
1059 homedir = tempres->pw_dir;
1060 }
1061#endif
1062 status = sh_gpg_check_file_sign(fd2, gp.data_id, gp.data_fp, homedir, 2);
1063 TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGUSR: |%s|>\n"), gp.data_id));
1064 TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGFP: |%s|>\n"), gp.data_fp));
1065 }
1066
1067 if (SH_GPG_OK == status && what == 1)
1068 {
1069#ifdef USE_FINGERPRINT
1070 if ((sl_strcmp(SH_GPG_FP, gp.conf_fp) == 0))
1071 {
1072 int i;
1073
1074 for(i = 0; i < (int) sl_strlen(gp.conf_fp); ++i)
1075 {
1076 if (gpgfp[i] != gp.conf_fp[i])
1077 {
1078 sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0,
1079 MSG_E_GPG_FP,
1080 gpgfp, gp.conf_fp);
1081 break;
1082 }
1083 }
1084
1085 if (smsg == S_FALSE)
1086 {
1087 tmp = sh_util_safe_name(gp.conf_id);
1088 sh_gpg_fill_startup (__LINE__,
1089 /* sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH, */
1090 sh.prg_name, sh.real.uid,
1091 (sh.flag.hidefile == S_TRUE) ?
1092 _("(hidden)") : file_path('C', 'R'),
1093 tmp,
1094 gp.conf_fp);
1095 SH_FREE(tmp);
1096 }
1097 smsg = S_TRUE;
1098#if defined(SH_WITH_SERVER)
1099#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1100 SH_FREE(buffer);
1101#endif
1102#endif
1103 SL_RETURN(0, _("sh_gpg_check_sign"));
1104 }
1105 else
1106 {
1107 /* fp mismatch
1108 */
1109 dlog(1, FIL__, __LINE__,
1110 _("The fingerprint of the signing key: %s\ndoes not match the compiled-in fingerprint: %s.\nTherefore the signature could not be verified.\n"),
1111 gp.conf_fp, SH_GPG_FP);
1112 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
1113 _("Fingerprint mismatch"),
1114 _("gpg_check_sign"));
1115 status = SH_GPG_BADSIGN;
1116 }
1117#else
1118 if (smsg == S_FALSE)
1119 {
1120 tmp = sh_util_safe_name(gp.conf_id);
1121 sh_gpg_fill_startup (__LINE__,
1122 /* sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH, */
1123 sh.prg_name, sh.real.uid,
1124 (sh.flag.hidefile == S_TRUE) ?
1125 _("(hidden)") : file_path('C', 'R'),
1126 tmp,
1127 gp.conf_fp);
1128 SH_FREE(tmp);
1129 }
1130 smsg = S_TRUE;
1131#if defined(SH_WITH_SERVER)
1132#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1133 SH_FREE(buffer);
1134#endif
1135#endif
1136 SL_RETURN(0, _("sh_gpg_check_sign"));
1137#endif
1138 }
1139
1140 else if (SH_GPG_OK == status && (what == 2 || what == 0))
1141 {
1142 if ((sl_strcmp(gp.data_id, gp.conf_id) == 0) &&
1143 (sl_strcmp(gp.data_fp, gp.conf_fp) == 0))
1144 {
1145#if defined(SH_WITH_SERVER)
1146#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1147 SH_FREE(buffer);
1148#endif
1149#endif
1150 SL_RETURN(0, _("sh_gpg_check_sign"));
1151 }
1152 else
1153 {
1154 /* ID or fp not equal
1155 */
1156 dlog(1, FIL__, __LINE__,
1157 _("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"));
1158 tmp = sh_util_safe_name (gp.conf_id);
1159 tmp2 = sh_util_safe_name (gp.data_id);
1160 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH2,
1161 sh.prg_name, sh.real.uid,
1162 (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'),
1163 tmp, gp.conf_fp,
1164 (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('D', 'R'),
1165 tmp2, gp.data_fp);
1166 SH_FREE(tmp);
1167 SH_FREE(tmp2);
1168 }
1169 }
1170
1171 if (status != SH_GPG_OK)
1172 {
1173 uid_t e_uid = sl_ret_euid();
1174 char * e_home = sh.effective.home;
1175
1176#if defined(SH_WITH_SERVER)
1177#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1178 struct passwd e_pwd;
1179 char * e_buffer = SH_ALLOC(SH_PWBUF_SIZE);
1180 struct passwd * e_tempres;
1181 sh_getpwnam_r(DEFAULT_IDENT, &e_pwd, e_buffer, SH_PWBUF_SIZE, &e_tempres);
1182#else
1183 struct passwd * e_tempres = sh_getpwnam(DEFAULT_IDENT);
1184#endif
1185
1186 if ((e_tempres != NULL) && (0 == sl_ret_euid()))
1187 {
1188 /* privileges not dropped yet */
1189 e_uid = e_tempres->pw_uid;
1190 e_home = e_tempres->pw_dir;
1191 }
1192#endif
1193 dlog(1, FIL__, __LINE__,
1194 _("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"),
1195#if defined(WITH_GPG)
1196 DEFAULT_GPG_PATH,
1197#else
1198 DEFAULT_PGP_PATH,
1199#endif
1200 (int) e_uid, e_home);
1201
1202#if defined(SH_WITH_SERVER)
1203#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1204 SH_FREE(e_buffer);
1205#endif
1206#endif
1207 }
1208
1209 TPT(((0), FIL__, __LINE__, _("msg=<Status = %d>\n"), status));
1210
1211 sh_error_handle((-1), FIL__, __LINE__, status, MSG_EXIT_ABORT1, sh.prg_name);
1212 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1213
1214 return (-1); /* make compiler happy */
1215}
1216
1217#define FGETS_BUF 16384
1218
1219SL_TICKET sh_gpg_extract_signed(SL_TICKET fd)
1220{
1221 FILE * fin_cp = NULL;
1222 char * buf = NULL;
1223 int bufc;
1224 int flag_pgp = S_FALSE;
1225 int flag_nohead = S_FALSE;
1226 SL_TICKET fdTmp = (-1);
1227 SL_TICKET open_tmp (void);
1228
1229 /* extract the data and copy to temporary file
1230 */
1231 fdTmp = open_tmp();
1232
1233 fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
1234 buf = SH_ALLOC(FGETS_BUF);
1235
1236 while (NULL != fgets(buf, FGETS_BUF, fin_cp))
1237 {
1238 bufc = 0;
1239 while (bufc < FGETS_BUF) {
1240 if (buf[bufc] == '\n') { ++bufc; break; }
1241 ++bufc;
1242 }
1243
1244 if (flag_pgp == S_FALSE &&
1245 (0 == sl_strcmp(buf, _("-----BEGIN PGP SIGNED MESSAGE-----\n"))||
1246 0 == sl_strcmp(buf, _("-----BEGIN PGP MESSAGE-----\n")))
1247 )
1248 {
1249 flag_pgp = S_TRUE;
1250 sl_write(fdTmp, buf, bufc);
1251 continue;
1252 }
1253
1254 if (flag_pgp == S_TRUE && flag_nohead == S_FALSE)
1255 {
1256 if (buf[0] == '\n')
1257 {
1258 flag_nohead = S_TRUE;
1259 sl_write(fdTmp, buf, 1);
1260 continue;
1261 }
1262 else if (0 == sl_strncmp(buf, _("Hash:"), 5) ||
1263 0 == sl_strncmp(buf, _("NotDashEscaped:"), 15))
1264 {
1265 sl_write(fdTmp, buf, bufc);
1266 continue;
1267 }
1268 else
1269 continue;
1270 }
1271
1272 if (flag_pgp == S_TRUE && buf[0] == '\n')
1273 {
1274 sl_write(fdTmp, buf, 1);
1275 }
1276 else if (flag_pgp == S_TRUE)
1277 {
1278 /* sl_write_line(fdTmp, buf, bufc); */
1279 sl_write(fdTmp, buf, bufc);
1280 }
1281
1282 if (flag_pgp == S_TRUE &&
1283 0 == sl_strcmp(buf, _("-----END PGP SIGNATURE-----\n")))
1284 break;
1285 }
1286 SH_FREE(buf);
1287 sl_fclose(FIL__, __LINE__, fin_cp); /* fin_cp = fdopen(dup(), "rb"); */
1288 sl_rewind (fdTmp);
1289
1290 return fdTmp;
1291}
1292
1293/* #ifdef WITH_GPG */
1294#endif
1295
1296
1297
1298
1299
1300
1301
1302
Note: See TracBrowser for help on using the repository browser.