source: trunk/src/sh_gpg.c@ 390

Last change on this file since 390 was 383, checked in by katerina, 13 years ago

Fix for ticket #281 (warnings from clang static analyzer).

File size: 35.0 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 clearerr(source.pipe);
863 goto xagain;
864 }
865
866 sh_gpg_pclose (&source);
867
868 TPT(((0), FIL__, __LINE__, _("msg=<Close pipe>\n")));
869
870#ifdef WITH_PGP
871 /* get the fingerprint */
872
873 source.pipe = sh_gpg_popen ( &source, fd, 1, sign_id, homedir);
874 if (NULL == source.pipe)
875 {
876 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
877 _("Could not open pipe for fp"),
878 _("gpg_check_file_sign"));
879 SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
880 }
881
882 TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
883
884 yagain:
885
886 errno = 0;
887
888 while (NULL != fgets(line, sizeof(line), source.pipe))
889 {
890#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
891 char * saveptr = NULL;
892#endif
893 if (line[strlen(line)-1] == '\n')
894 line[strlen(line)-1] = ' ';
895 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
896 line,
897 _("gpg_check_file_sign"));
898
899 if (sl_strlen(line) < 18)
900 continue;
901#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
902 ptr = strtok_r (line, " ", &saveptr);
903#else
904 ptr = strtok (line, " ");
905#endif
906 while (ptr)
907 {
908#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
909 ptr = strtok_r (NULL, " ", &saveptr);
910#else
911 ptr = strtok (NULL, " ");
912#endif
913 if (ptr && 0 == sl_strncmp (ptr, _("fingerprint"), 11))
914 {
915#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
916 ptr = strtok_r (NULL, " ", &saveptr); /* to '=' */
917#else
918 ptr = strtok (NULL, " "); /* to '=' */
919#endif
920 sign_fp[0] = '\0';
921 while (ptr)
922 {
923#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
924 ptr = strtok_r (NULL, " ", &saveptr); /* part of fingerprint */
925#else
926 ptr = strtok (NULL, " "); /* part of fingerprint */
927#endif
928 sl_strlcat (sign_fp, ptr, SH_MINIBUF+1);
929 }
930 /* sign_fp[sl_strlen(sign_fp)-1] = '\0'; remove trailing '\n' */
931 if (sl_strlen(sign_fp) > 0)
932 have_fp = GOOD;
933 break;
934 }
935 }
936 }
937
938 if (ferror(source.pipe) && errno == EAGAIN)
939 {
940 clearerr(source.pipe);
941 goto yagain;
942 }
943
944 sh_gpg_pclose (&source);
945#endif
946
947 if (have_id == GOOD)
948 {
949 TPT(((0), FIL__, __LINE__, _("msg=<Got signator ID>\n")));
950 ;
951 }
952 if (have_fp == GOOD)
953 {
954 TPT(((0), FIL__, __LINE__, _("msg=<Got fingerprint>\n")));
955 ;
956 }
957
958 if (have_id == GOOD && have_fp == GOOD)
959 SL_RETURN( SH_GPG_OK, _("sh_gpg_check_file_sign"));
960 else
961 {
962 if (have_id == BAD)
963 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
964 _("No good signature"),
965 _("gpg_check_file_sign"));
966 else
967 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
968 _("No fingerprint for key"),
969 _("gpg_check_file_sign"));
970 SL_RETURN( SH_GPG_BADSIGN, _("sh_gpg_check_file_sign"));
971 }
972}
973
974int get_the_fd(SL_TICKET file_1);
975
976int sh_gpg_check_sign (long file_1, long file_2, int what)
977{
978 int status = SH_GPG_BAD;
979 int fd1 = 0;
980 int fd2 = 0;
981 static int smsg = S_FALSE;
982 char * tmp;
983 char * tmp2;
984
985 char * homedir = sh.effective.home;
986#if defined(SH_WITH_SERVER)
987 struct passwd * tempres;
988#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
989 struct passwd pwd;
990 char * buffer = SH_ALLOC(SH_PWBUF_SIZE);
991#endif
992#endif
993
994#ifdef USE_FINGERPRINT
995#include "sh_gpg_fp.h"
996#endif
997
998 SL_ENTER(_("sh_gpg_check_sign"));
999
1000
1001 if (what == 0 || what == 1)
1002 fd1 = get_the_fd(file_1);
1003 if (what == 0 || what == 2)
1004 fd2 = get_the_fd(file_2);
1005
1006
1007 if (fd1 < 0 || fd2 < 0)
1008 {
1009 TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD1 = %d>\n"), fd1));
1010 TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD2 = %d>\n"), fd2));
1011 dlog(1, FIL__, __LINE__,
1012 _("This looks like an unexpected internal error.\n"));
1013 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name);
1014 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1015#if defined(SH_WITH_SERVER)
1016#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1017 SH_FREE(buffer);
1018#endif
1019#endif
1020 SL_RETURN( (-1), _("sh_gpg_check_sign"));
1021 }
1022
1023 if (what == 0 || what == 1)
1024 {
1025 TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD1 = %d>\n"), fd1));
1026#if defined(SH_WITH_SERVER)
1027#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1028 sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
1029#else
1030 tempres = sh_getpwnam(DEFAULT_IDENT);
1031#endif
1032
1033 if ((tempres != NULL) && (0 == sl_ret_euid()))
1034 {
1035 /* privileges not dropped yet*/
1036 homedir = tempres->pw_dir;
1037 }
1038#endif
1039 status = sh_gpg_check_file_sign(fd1, gp.conf_id, gp.conf_fp, homedir, 1);
1040 TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGUSR: |%s|>\n"), gp.conf_id));
1041 TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGFP: |%s|>\n"), gp.conf_fp));
1042 }
1043
1044 if ((what == 0 && SH_GPG_OK == status) || what == 2)
1045 {
1046 TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD2 = %d>\n"), fd2));
1047#if defined(SH_WITH_SERVER)
1048#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1049 sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
1050#else
1051 tempres = sh_getpwnam(DEFAULT_IDENT);
1052#endif
1053
1054 if ((tempres != NULL) && (0 == sl_ret_euid()))
1055 {
1056 /* privileges not dropped yet*/
1057 homedir = tempres->pw_dir;
1058 }
1059#endif
1060 status = sh_gpg_check_file_sign(fd2, gp.data_id, gp.data_fp, homedir, 2);
1061 TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGUSR: |%s|>\n"), gp.data_id));
1062 TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGFP: |%s|>\n"), gp.data_fp));
1063 }
1064
1065 if (SH_GPG_OK == status && what == 1)
1066 {
1067#ifdef USE_FINGERPRINT
1068 if ((sl_strcmp(SH_GPG_FP, gp.conf_fp) == 0))
1069 {
1070 int i;
1071
1072 for(i = 0; i < (int) sl_strlen(gp.conf_fp); ++i)
1073 {
1074 if (gpgfp[i] != gp.conf_fp[i])
1075 {
1076 sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0,
1077 MSG_E_GPG_FP,
1078 gpgfp, gp.conf_fp);
1079 break;
1080 }
1081 }
1082
1083 if (smsg == S_FALSE)
1084 {
1085 tmp = sh_util_safe_name(gp.conf_id);
1086 sh_gpg_fill_startup (__LINE__,
1087 /* sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH, */
1088 sh.prg_name, sh.real.uid,
1089 (sh.flag.hidefile == S_TRUE) ?
1090 _("(hidden)") : file_path('C', 'R'),
1091 tmp,
1092 gp.conf_fp);
1093 SH_FREE(tmp);
1094 }
1095 smsg = S_TRUE;
1096#if defined(SH_WITH_SERVER)
1097#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1098 SH_FREE(buffer);
1099#endif
1100#endif
1101 SL_RETURN(0, _("sh_gpg_check_sign"));
1102 }
1103 else
1104 {
1105 /* fp mismatch
1106 */
1107 dlog(1, FIL__, __LINE__,
1108 _("The fingerprint of the signing key: %s\ndoes not match the compiled-in fingerprint: %s.\nTherefore the signature could not be verified.\n"),
1109 gp.conf_fp, SH_GPG_FP);
1110 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
1111 _("Fingerprint mismatch"),
1112 _("gpg_check_sign"));
1113 status = SH_GPG_BADSIGN;
1114 }
1115#else
1116 if (smsg == S_FALSE)
1117 {
1118 tmp = sh_util_safe_name(gp.conf_id);
1119 sh_gpg_fill_startup (__LINE__,
1120 /* sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH, */
1121 sh.prg_name, sh.real.uid,
1122 (sh.flag.hidefile == S_TRUE) ?
1123 _("(hidden)") : file_path('C', 'R'),
1124 tmp,
1125 gp.conf_fp);
1126 SH_FREE(tmp);
1127 }
1128 smsg = S_TRUE;
1129#if defined(SH_WITH_SERVER)
1130#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1131 SH_FREE(buffer);
1132#endif
1133#endif
1134 SL_RETURN(0, _("sh_gpg_check_sign"));
1135#endif
1136 }
1137
1138 else if (SH_GPG_OK == status && (what == 2 || what == 0))
1139 {
1140 if ((sl_strcmp(gp.data_id, gp.conf_id) == 0) &&
1141 (sl_strcmp(gp.data_fp, gp.conf_fp) == 0))
1142 {
1143#if defined(SH_WITH_SERVER)
1144#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1145 SH_FREE(buffer);
1146#endif
1147#endif
1148 SL_RETURN(0, _("sh_gpg_check_sign"));
1149 }
1150 else
1151 {
1152 /* ID or fp not equal
1153 */
1154 dlog(1, FIL__, __LINE__,
1155 _("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"));
1156 tmp = sh_util_safe_name (gp.conf_id);
1157 tmp2 = sh_util_safe_name (gp.data_id);
1158 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH2,
1159 sh.prg_name, sh.real.uid,
1160 (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'),
1161 tmp, gp.conf_fp,
1162 (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('D', 'R'),
1163 tmp2, gp.data_fp);
1164 SH_FREE(tmp);
1165 SH_FREE(tmp2);
1166 }
1167 }
1168
1169 if (status != SH_GPG_OK)
1170 {
1171 uid_t e_uid = sl_ret_euid();
1172 char * e_home = sh.effective.home;
1173
1174#if defined(SH_WITH_SERVER)
1175#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1176 struct passwd e_pwd;
1177 char * e_buffer = SH_ALLOC(SH_PWBUF_SIZE);
1178 struct passwd * e_tempres;
1179 sh_getpwnam_r(DEFAULT_IDENT, &e_pwd, e_buffer, SH_PWBUF_SIZE, &e_tempres);
1180#else
1181 struct passwd * e_tempres = sh_getpwnam(DEFAULT_IDENT);
1182#endif
1183
1184 if ((e_tempres != NULL) && (0 == sl_ret_euid()))
1185 {
1186 /* privileges not dropped yet */
1187 e_uid = e_tempres->pw_uid;
1188 e_home = e_tempres->pw_dir;
1189 }
1190#endif
1191 dlog(1, FIL__, __LINE__,
1192 _("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"),
1193#if defined(WITH_GPG)
1194 DEFAULT_GPG_PATH,
1195#else
1196 DEFAULT_PGP_PATH,
1197#endif
1198 (int) e_uid, e_home);
1199
1200#if defined(SH_WITH_SERVER)
1201#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1202 SH_FREE(e_buffer);
1203#endif
1204#endif
1205 }
1206
1207 TPT(((0), FIL__, __LINE__, _("msg=<Status = %d>\n"), status));
1208
1209 sh_error_handle((-1), FIL__, __LINE__, status, MSG_EXIT_ABORT1, sh.prg_name);
1210 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1211
1212 return (-1); /* make compiler happy */
1213}
1214
1215#define FGETS_BUF 16384
1216
1217SL_TICKET sh_gpg_extract_signed(SL_TICKET fd)
1218{
1219 FILE * fin_cp = NULL;
1220 char * buf = NULL;
1221 int bufc;
1222 int flag_pgp = S_FALSE;
1223 int flag_nohead = S_FALSE;
1224 SL_TICKET fdTmp = (-1);
1225 SL_TICKET open_tmp (void);
1226
1227 /* extract the data and copy to temporary file
1228 */
1229 fdTmp = open_tmp();
1230
1231 fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
1232 buf = SH_ALLOC(FGETS_BUF);
1233
1234 while (NULL != fgets(buf, FGETS_BUF, fin_cp))
1235 {
1236 bufc = 0;
1237 while (bufc < FGETS_BUF) {
1238 if (buf[bufc] == '\n') { ++bufc; break; }
1239 ++bufc;
1240 }
1241
1242 if (flag_pgp == S_FALSE &&
1243 (0 == sl_strcmp(buf, _("-----BEGIN PGP SIGNED MESSAGE-----\n"))||
1244 0 == sl_strcmp(buf, _("-----BEGIN PGP MESSAGE-----\n")))
1245 )
1246 {
1247 flag_pgp = S_TRUE;
1248 sl_write(fdTmp, buf, bufc);
1249 continue;
1250 }
1251
1252 if (flag_pgp == S_TRUE && flag_nohead == S_FALSE)
1253 {
1254 if (buf[0] == '\n')
1255 {
1256 flag_nohead = S_TRUE;
1257 sl_write(fdTmp, buf, 1);
1258 continue;
1259 }
1260 else if (0 == sl_strncmp(buf, _("Hash:"), 5) ||
1261 0 == sl_strncmp(buf, _("NotDashEscaped:"), 15))
1262 {
1263 sl_write(fdTmp, buf, bufc);
1264 continue;
1265 }
1266 else
1267 continue;
1268 }
1269
1270 if (flag_pgp == S_TRUE && buf[0] == '\n')
1271 {
1272 sl_write(fdTmp, buf, 1);
1273 }
1274 else if (flag_pgp == S_TRUE)
1275 {
1276 /* sl_write_line(fdTmp, buf, bufc); */
1277 sl_write(fdTmp, buf, bufc);
1278 }
1279
1280 if (flag_pgp == S_TRUE &&
1281 0 == sl_strcmp(buf, _("-----END PGP SIGNATURE-----\n")))
1282 break;
1283 }
1284 SH_FREE(buf);
1285 sl_fclose(FIL__, __LINE__, fin_cp); /* fin_cp = fdopen(dup(), "rb"); */
1286 sl_rewind (fdTmp);
1287
1288 return fdTmp;
1289}
1290
1291/* #ifdef WITH_GPG */
1292#endif
1293
1294
1295
1296
1297
1298
1299
1300
Note: See TracBrowser for help on using the repository browser.