source: branches/samhain_3_1/src/sh_gpg.c@ 567

Last change on this file since 567 was 474, checked in by katerina, 9 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.