modules/pa/gpg.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- PA_VerifySignature
- PA_Decrypt
- PA_ImportKey
- PA_RemoveKey
- PA_ParseMessage
- GetFingerPrint
- VerifySignAndExplodeFile
- GetKeyID
1 /***************************************
2 $Revision: 1.28 $
3
4 gpg.c - core of the PA module. Contains functions that are used
5 to check the PGP authentication in a message.
6
7 Status: COMPLETE, REVUED, TESTED
8
9 ******************/ /******************
10 Filename : gpg.c
11 Authors : Filippo Portera, Daniele Arena
12 OSs Tested : Solaris 7
13 ******************/ /******************
14 Copyright (c) 2000 RIPE NCC
15
16 All Rights Reserved
17
18 Permission to use, copy, modify, and distribute this software and its
19 documentation for any purpose and without fee is hereby granted,
20 provided that the above copyright notice appear in all copies and that
21 both that copyright notice and this permission notice appear in
22 supporting documentation, and that the name of the author not be
23 used in advertising or publicity pertaining to distribution of the
24 software without specific, written prior permission.
25
26 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 ***************************************/
33
34
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/wait.h>
40 #include <unistd.h>
41 #include <errno.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45 #include <time.h>
46 #include <signal.h>
47 #include <sys/time.h>
48 #include <sys/param.h>
49
50 #include "mm.h"
51 /*#include "misc.h"*/ /* isMIME functions need case insensitive string search()*/
52 #include "gpg.h"
53 #include "erroutines.h"
54
55 extern char EP_outputPrefix[FILENAME_LENGTH];
56 extern char EP_keyRing[FILENAME_LENGTH];
57 extern char EP_gpgcmd[FILENAME_LENGTH];
58 extern int EP_TreeHeight;
59 extern int EP_Node_ID;
60 extern int EP_Debug;
61
62 /* static int parseMailBlock_nMsg;
63 static int parseRecursionLevel; */
64
65 extern int sd1[2];
66 extern int spawn_job (char *path, char *argv[],
67 int *in_fd, int *out_fd, int *err_fd);
68 extern time_t nfslock(char *path, char *namelock, int max_age, int notify);
69 extern int nfsunlock(char *path, char *namelock, int max_age, time_t birth);
70
71
72 static void GetFingerPrint(struct ImportKeyObject *iKO);
73 static void VerifySignAndExplodeFile(EPNodePtr ptr);
74 static void GetKeyID(struct ImportKeyObject *iKO);
75
76
77 /**************************************
78 *
79 * API functions
80 *
81 **************************************/
82
83
84 /*++++++++++++++++++++++++++++
85
86 Verify a detached PGP signature.
87
88 struct VerifySignObject *vSO The signed object structure to be verified.
89
90 ++++++++++++++++++++++++++++*/
91
92 void PA_VerifySignature(struct VerifySignObject *vSO) {
/* [<][>][^][v][top][bottom][index][help] */
93 char *strArgs[10];
94 char Args0[100];
95 char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
96 Args6[100], Args7[100];
97 int gpg_pid;
98 int gpg_in_fd, out_fd, err_fd;
99 int status;
100 /* static int nMsgs = 0; */
101 char txt[LINE_LENGTH];
102 char *keyStr;
103 /* int childRC; */
104
105 vSO->type = vSO_Type_Signed;
106
107 strcpy(Args0, "--no-secmem-warning");
108 strcpy(Args1, "--keyring");
109 strcpy(Args2, vSO->keyRing);
110 strcpy(Args3, "-o");
111 if (!strcmp(vSO->iSigFilename, "")) {
112 strcpy(Args4, vSO->oStream);
113 strcpy(Args5, "-d");
114 strcpy(Args6, vSO->iDocSigFilename);
115 strArgs[6] = Args6;
116 strArgs[7] = (char *)0;
117 } else {
118 strcpy(Args5, "--verify");
119 strcpy(Args6, vSO->iSigFilename);
120 strcpy(Args7, vSO->iDocSigFilename);
121
122 strArgs[6] = Args6;
123 strArgs[7] = Args7;
124 strArgs[8] = (char *)0;
125 strcpy(vSO->oStream, vSO->iDocSigFilename);
126 }
127
128 strArgs[0] = Args0;
129 strArgs[1] = Args1;
130 strArgs[2] = Args2;
131 strArgs[3] = Args3;
132 strArgs[4] = Args4;
133 strArgs[5] = Args5;
134
135 gpg_in_fd = INPUT_FD;
136 out_fd = OUTPUT_FD;
137 err_fd = ERROR_FD;
138 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
139 &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
140 {
141 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
142 exit(1);
143 }
144
145 if (waitpid (gpg_pid, &status, 0) < 0)
146 {
147 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
148 exit(1);
149 }
150 if (WIFEXITED(status) == 0)
151 {
152 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
153 exit(1);
154 } else {
155 /* Child exited, checking return code */
156 /* childRC = (status & 0xF00) >> 8;
157 if (childRC == 1) {
158 fprintf (stderr, "Fatal: gpg child return code: %d\n", childRC);
159 printf ("gpg failure\n");
160 exit(1);
161 } */
162 }
163
164
165 /* Parsing gpg output */
166 vSO->isValid = vSO_KO;
167 while (fgets (txt, LINE_LENGTH - 1, stdin) != NULL)
168 {
169 /* printf ( "GPG output : %s\n", txt ); */
170 if (strstr(txt, "Good signature") != NULL)
171 vSO->isValid = vSO_IS_VALID;
172
173 if (strstr(txt, "CRC error") != NULL)
174 vSO->isValid = vSO_CRC_ERROR;
175
176 if (strstr(txt, "public key not found") != NULL)
177 vSO->isValid = vSO_NO_PUBLIC_KEY;
178
179 if (strstr(txt, "no valid OpenPGP data found") != NULL)
180 vSO->isValid = vSO_NO_OPENPGP_DATA;
181
182 if ((keyStr = strstr(txt, "key ID")) != NULL) {
183 keyStr += 7;
184 sscanf(keyStr, "%8X\n", &vSO->keyID);
185 }
186 }
187
188 if (sd1[0] != 0) close ( sd1[0] );
189 }
190
191
192
193 /*++++++++++++++++++++++++++++
194
195 Decrypt a PGP-encrypted file.
196
197 struct ReadCryptedObject *rDO The object to be decrypted
198
199
200 Note:
201 This functions is not used by PA/EP/MM
202 It can be useful in the future.... (FP)
203
204 ++++++++++++++++++++++++++++*/
205
206 void PA_Decrypt(struct ReadCryptedObject *rDO) {
/* [<][>][^][v][top][bottom][index][help] */
207
208 char *strArgs[9];
209 char clearTextExtension[4] = ".gpg";
210 char Args0[100];
211 char Args1[100];
212 char Args2[100];
213 char Args3[100];
214 char Args4[100];
215 char Args5[100];
216 char Args6[100];
217 int gpg_pid;
218 int gpg_in_fd, out_fd, err_fd;
219 int status;
220 char txt[LINE_LENGTH];
221 int childRC;
222
223 strcpy(Args0, "--no-tty");
224 strcpy(Args1, "--no-secmem-warning");
225 strcpy(Args2, "--keyring");
226 strcpy(Args3, rDO->keyRing);
227 strcpy(Args4, "--output");
228 strcpy(Args5, strcat(rDO->iFilename, clearTextExtension));
229 strcpy(Args6, rDO->iFilename);
230
231 strArgs[0] = Args0;
232 strArgs[1] = Args1;
233 strArgs[2] = Args2;
234 strArgs[3] = Args3;
235 strArgs[4] = Args4;
236 strArgs[5] = Args5;
237 strArgs[6] = Args6;
238 strArgs[7] = (char *) 0;
239
240 gpg_in_fd = INPUT_FD;
241 out_fd = OUTPUT_FD;
242 err_fd = ERROR_FD;
243 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
244 &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
245 {
246 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
247 exit(1);
248 }
249
250 if (waitpid (gpg_pid, &status, 0) < 0)
251 {
252 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
253 exit(1);
254 }
255 if (WIFEXITED(status) == 0)
256 {
257 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
258 exit(1);
259 } else {
260 /* Child exited, checking return code */
261 childRC = (status & 0xF00) >> 8;
262 if (childRC == 1) {
263 ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
264 exit(1);
265 }
266 }
267
268
269 /* Parsing gpg output */
270 while (fgets (txt, STRING_LENGTH - 1, stdin) != NULL)
271 {
272
273 }
274
275 if (sd1[0] != 0) close ( sd1[0] );
276 }
277
278
279
280 /*++++++++++++++++++++++++++++
281
282 Import a PGP key.
283
284 struct ImportKeyObject *iKO The structure where the imported key goes
285
286 ++++++++++++++++++++++++++++*/
287
288 void PA_ImportKey(struct ImportKeyObject *iKO) {
/* [<][>][^][v][top][bottom][index][help] */
289
290 char *strArgs[9];
291 char Args0[100];
292 char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
293 int gpg_pid;
294 int gpg_in_fd, out_fd, err_fd;
295 int status;
296 char txt[LINE_LENGTH];
297 char *keyStr, *pos;
298 const char lockFilename[] = ".PAlock";
299 char keyRingLockFile[1000], keyRingPath[1000];
300 time_t lockBirthDate;
301 FILE *mystdin;
302 int childRC;
303
304 iKO->rc = iKO_GENERALFAILURE;
305
306 strcpy(Args0, "--no-tty");
307 strcpy(Args1, "--no-secmem-warning");
308 strcpy(Args2, "--keyring");
309 strcpy(Args3, iKO->keyRing);
310 strcpy(Args4, "--import");
311 strcpy(Args5, iKO->iFilename);
312
313 strArgs[0] = Args0;
314 strArgs[1] = Args1;
315 strArgs[2] = Args2;
316 strArgs[3] = Args3;
317 strArgs[4] = Args4;
318 strArgs[5] = Args5;
319 strArgs[6] = (char *)0;
320
321 gpg_in_fd = INPUT_FD;
322 out_fd = OUTPUT_FD;
323 err_fd = ERROR_FD;
324
325 /* create lock file filenames for NFS */
326
327 strcpy(keyRingLockFile, iKO->keyRing);
328 if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
329 strcpy(pos + 1, lockFilename);
330 strcpy(keyRingPath, keyRingLockFile);
331 keyRingPath[pos - keyRingLockFile] = 0;
332 } else {
333 strcpy(keyRingLockFile, lockFilename);
334 strcpy(keyRingPath, "");
335 }
336
337 lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
338
339 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
340 &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
341 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
342 exit(1);
343 }
344
345 if (waitpid (gpg_pid, &status, 0) < 0)
346 {
347 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
348 nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
349 exit(1);
350 }
351
352 nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
353
354 if (WIFEXITED(status) == 0)
355 {
356 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
357 } else {
358 /* Child exited, checking return code */
359 childRC = (status & 0xF00) >> 8;
360 if (childRC == 1) {
361 ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
362 exit(1);
363 }
364 }
365
366
367 /* Parsing gpg output */
368 /* while (read(0, txt, 1000) != 0)
369 fprintf(stderr, "child read %s\n", txt); */
370
371 mystdin = fdopen(0, "r");
372 iKO->rc = iKO_GENERALFAILURE;
373 while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
374 {
375 /* printf ( "GPG output : %s\n", txt ); */
376
377 if ((keyStr = strstr(txt, "imported")) != NULL) {
378 iKO->rc = iKO_OK;
379 }
380
381 if ((keyStr = strstr(txt, "CRC error")) != NULL) {
382 iKO->rc = iKO_CRC_ERROR;
383 }
384
385 if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL) {
386 iKO->rc = iKO_NO_OPENPGP_DATA;
387 }
388
389 if (((keyStr = strstr(txt, "unchanged")) != NULL) ||
390 ((keyStr = strstr(txt, "not changed")) != NULL)) {
391 iKO->rc = iKO_UNCHANGED;
392 }
393
394 if ((keyStr = strstr(txt, "key")) != NULL) {
395 keyStr += 4;
396 sscanf(keyStr, "%8X\n", &iKO->keyID);
397 }
398 }
399
400 if (sd1[0] != 0) close ( sd1[0] );
401
402 /* Get the finger print */
403
404 GetFingerPrint(iKO);
405 }
406
407
408
409 /*++++++++++++++++++++++++++++
410
411 Remove a PGP key.
412
413 struct ImportKeyObject *iKO The structure containing the key to be removed
414
415 ++++++++++++++++++++++++++++*/
416
417 void PA_RemoveKey(struct ImportKeyObject *iKO) {
/* [<][>][^][v][top][bottom][index][help] */
418
419 char *strArgs[9];
420 char Args0[100]= "gpg";
421 char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100], Args6[100], Args7[100];
422 int gpg_pid;
423 int gpg_in_fd, out_fd, err_fd;
424 int status;
425 char txt[LINE_LENGTH];
426 char *keyStr, *pos;
427 const char lockFilename[] = ".PAlock";
428 char keyRingLockFile[1000], keyRingPath[1000];
429 time_t lockBirthDate;
430 FILE *mystdin;
431 int childRC;
432
433 iKO->rc = iKO_GENERALFAILURE;
434
435 GetKeyID(iKO); /* getting key-id */
436
437 /* printf("Key id = %08lX\n", iKO->keyID); */
438
439 if ((iKO->rc == iKO_OK) || (iKO->rc == iKO_UNCHANGED)) {
440 strcpy(Args1, "--batch");
441 strcpy(Args2, "--yes");
442 strcpy(Args3, "--no-secmem-warning");
443 strcpy(Args4, "--keyring");
444 strcpy(Args5, iKO->keyRing);
445 strcpy(Args6, "--delete-key");
446 sprintf(Args7, "%08X", iKO->keyID);
447
448 strArgs[0] = Args0;
449 strArgs[1] = Args1;
450 strArgs[2] = Args2;
451 strArgs[3] = Args3;
452 strArgs[4] = Args4;
453 strArgs[5] = Args5;
454 strArgs[6] = Args6;
455 strArgs[7] = Args7;
456 strArgs[8] = (char *)0;
457
458
459 gpg_in_fd = INPUT_FD;
460 out_fd = OUTPUT_FD;
461 err_fd = ERROR_FD;
462
463 /* create lock file filenames for NFS */
464
465 strcpy(keyRingLockFile, iKO->keyRing);
466 if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
467 strcpy(pos + 1, lockFilename);
468 strcpy(keyRingPath, keyRingLockFile);
469 keyRingPath[pos - keyRingLockFile] = 0;
470 } else {
471 strcpy(keyRingLockFile, lockFilename);
472 strcpy(keyRingPath, "");
473 }
474
475 lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
476
477 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
478 &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
479 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
480 exit(1);
481 }
482
483 /* printf("Child pid = %d\n", gpg_pid); */
484
485 if (waitpid (gpg_pid, &status, 0) < 0)
486 {
487 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
488 exit(1);
489 }
490
491 nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
492
493 if (WIFEXITED(status) == 0)
494 {
495 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
496 exit(1);
497 } else {
498 /* Child exited, checking return code */
499 childRC = (status & 0xF00) >> 8;
500 if (childRC == 1) {
501 ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
502 exit(1);
503 }
504 }
505
506
507 mystdin = fdopen(0, "r");
508 iKO->rc = iKO_OK;
509 while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
510 {
511 /* printf ( "GPG output : %s\n", txt ); */
512
513 if ((keyStr = strstr(txt, "delete key failed")) != NULL) {
514 iKO->rc = iKO_GENERALFAILURE;
515 }
516 if ((keyStr = strstr(txt, "there is a secret key for this public key")) != NULL) {
517 iKO->rc = iKO_SECRET_KEY_PRESENT;
518 }
519
520 }
521
522 if (sd1[0] != 0) close ( sd1[0] );
523 }
524 }
525
526
527
528 /*++++++++++++++++++++++++++++
529
530 Parse a file and look for PGP-signed elements inside.
531
532 EPNodePtr ptr The pointer to the EP treenode containing the file to be parsed.
533
534 ++++++++++++++++++++++++++++*/
535
536 EPNodePtr PA_ParseMessage(EPNodePtr ptr) {
/* [<][>][^][v][top][bottom][index][help] */
537
538 /* Assumptions:
539 - ptr is describing a text file, not MIME
540 - input file is broken down to pieces, plain text or PGP blocks
541 - if input file is doesn't have any PGP block, this is a leaf
542 - otherwise send each block to the proper handler.
543 */
544
545 FILE *fin, *fout;
546 char txt[MAX_LINE_BUF], *strptr;
547 /* char blockFilename[LINE_LENGTH]; */
548 const char PGP_prefix_msg[] = "-----BEGIN PGP MESSAGE";
549 const char PGP_suffix_msg[] = "-----END PGP MESSAGE";
550 const char PGP_prefix_signed[] = "-----BEGIN PGP SIGNED MESSAGE";
551 const char PGP_suffix_signature[] = "-----END PGP SIGNATURE";
552 int found_prefix = 0, found_suffix = 0;
553 EPNodePtr p = ptr, prev = ptr;
554 int end_of_fin = 0, text_block = 1;
555
556
557 ER_dbg_va (FAC_PA, ASP_PA_GEN, "Entering PA_ParseMessage...");
558
559
560 if ((fin = fopen(ptr->file, "r")) != NULL) {
561
562 do {
563 /* this is needed because a text block parser ends when it finds
564 a PGP prefix, so we already have a txt buffer. */
565
566 if (!text_block || (prev == ptr)) {
567 strptr = fgets(txt, MAX_LINE_BUF, fin);
568 if (strptr == NULL ) end_of_fin = 1;
569 }
570
571 if (!end_of_fin && (found_prefix || (strstr(txt, PGP_prefix_msg) != NULL) ||
572 (strstr(txt, PGP_prefix_signed) != NULL))) {
573 /* PGP block */
574 found_prefix = 1;
575 text_block = 0;
576
577 p = EP_DefineNewNode(++EP_Node_ID, vS_TO_BE_PGPVERIFIED,
578 ptr->MIMEContentType, ptr->strMIMEContentType, 0);
579
580 if (prev != ptr)
581 prev->next = p;
582 else
583 ptr->inner = p;
584
585 if ((fout = fopen(p->file, "w")) != NULL ) {
586 fputs(txt, fout);
587 /* To be replaced by fwrite(), more efficient */
588 while ((found_prefix != found_suffix) &&
589 ((strptr = fgets(txt, MAX_LINE_BUF, fin)) != NULL)) {
590 if (strstr(txt, PGP_prefix_msg) != NULL) found_prefix++;
591 if (strstr(txt, PGP_prefix_signed) != NULL) found_prefix++;
592 if (strstr(txt, PGP_suffix_msg) != NULL) found_suffix++;
593 if (strstr(txt, PGP_suffix_signature) != NULL) found_suffix++;
594 fputs(txt, fout);
595 }
596 if (strptr == NULL ) end_of_fin = 1;
597
598 fclose(fout);
599
600 if (found_prefix == found_suffix) {
601 found_prefix = found_suffix = 0;
602
603 VerifySignAndExplodeFile(p);
604
605 /* Called form EP_ParseMail or EP_PArseText ? */
606
607 if (strstr(EP_outputPrefix, "EPMtmp") != NULL)
608 {
609 ER_dbg_va (FAC_PA, ASP_PA_GEN, "Found prefix and suffix; calling EP_MIMEParse...");
610 EP_MIMEParse(p);
611 }
612 else
613 PA_ParseMessage(p);
614
615 prev = p;
616 } else {
617 /* Wrong PGP delimiters order. */
618 p->isValidPGPSignature = vS_UNMATCHED_PGP_DELIMITERS;
619 }
620 } else {
621 p->isValidPGPSignature = vS_UNABLE_TO_WRITE_FILE;
622 return p;
623 }
624
625 } else {
626 /* Clear text block */
627
628 text_block = 1;
629
630 if (strptr == NULL) end_of_fin = 1;
631 else {
632 p = EP_DefineNewNode(++EP_Node_ID, vS_IS_NOT_PGP,
633 ptr->MIMEContentType,
634 ptr->strMIMEContentType, 0);
635
636 if (prev != ptr)
637 prev->next = p;
638 else
639 ptr->inner = p;
640
641 if ((fout = fopen(p->file, "w")) != NULL ) {
642 fputs(txt, fout);
643 /* To be replaced by fwrite(), more efficient */
644 while ((!found_prefix &&
645 (strptr = fgets(txt, MAX_LINE_BUF, fin)) != NULL)) {
646 if ((strstr(txt, PGP_prefix_msg) != NULL) ||
647 (strstr(txt, PGP_prefix_signed) != NULL)) found_prefix++;
648 else
649 fputs(txt, fout);
650 }
651 if (strptr == NULL ) end_of_fin = 1;
652
653 fclose(fout);
654
655 /* Check if the blockfile is finished and this is the first
656 segment. If so this is a text leaf */
657 if (found_prefix || (prev != p)) {
658 if (prev->MIMEContentType == -1)
659 {
660 if (strstr(EP_outputPrefix, "EPMtmp") != NULL)
661 {
662 ER_dbg_va (FAC_PA, ASP_PA_GEN, "PA_ParseMessage: sending to EP_MIMEParse");
663 EP_MIMEParse(p);
664 }
665 else
666 PA_ParseMessage(p);
667 }
668
669 prev = p;
670 }
671
672 } else {
673 p->isValidPGPSignature = vS_UNABLE_TO_WRITE_FILE;
674 return p;
675 }
676 }
677 }
678 } while (!end_of_fin);
679 } else {
680 p->isValidPGPSignature = vS_NO_IN_FILES;
681 }
682
683 return ptr;
684 }
685
686
687 /**************************************
688 *
689 * Internal functions
690 *
691 **************************************/
692
693
694
695 /*++++++++++++++++++++++++++++
696
697 Get the fingerprint of a PGP key.
698
699 ImportKeyObject *iKO The imported key object
700
701 ++++++++++++++++++++++++++++*/
702
703 void GetFingerPrint(struct ImportKeyObject *iKO) {
/* [<][>][^][v][top][bottom][index][help] */
704
705 char *strArgs[9];
706 char Args0[100] ;
707 char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
708 int gpg_pid;
709 int gpg_in_fd, out_fd, err_fd;
710 int status;
711 char txt[LINE_LENGTH];
712 char *keyStr;
713 FILE *mystdin;
714 int childRC;
715
716 strcpy(Args0, "--no-tty");
717 strcpy(Args1, "--no-secmem-warning");
718 strcpy(Args2, "--keyring");
719 strcpy(Args3, iKO->keyRing);
720 strcpy(Args4, "--fingerprint");
721 sprintf(Args5, "%08X", iKO->keyID);
722
723 strArgs[0] = Args0;
724 strArgs[1] = Args1;
725 strArgs[2] = Args2;
726 strArgs[3] = Args3;
727 strArgs[4] = Args4;
728 strArgs[5] = Args5;
729 strArgs[6] = (char *)0;
730
731 gpg_in_fd = INPUT_FD;
732 out_fd = OUTPUT_FD;
733 err_fd = ERROR_FD;
734
735 /* create lock file filenames for NFS */
736
737 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
738 &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
739 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
740 exit(1);
741 }
742
743 if (waitpid (gpg_pid, &status, 0) < 0)
744 {
745 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
746 exit(1);
747 }
748
749 if (WIFEXITED(status) == 0)
750 {
751 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
752 exit(1);
753 } else {
754 /* Child exited, checking return code */
755 childRC = (status & 0xF00) >> 8;
756 if (childRC == 1) {
757 ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
758 exit(1);
759 }
760 }
761
762
763 mystdin = fdopen(0, "r");
764 while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
765 {
766 /* printf ( "GPG output : %s\n", txt ); */
767
768 if ((keyStr = strstr(txt, "Key fingerprint =")) != NULL) {
769 strcpy(iKO->fingerPrint, keyStr + 18);
770 iKO->fingerPrint[strlen(iKO->fingerPrint)-1] = 0;
771 }
772
773 if ((keyStr = strstr(txt, "key")) != NULL) {
774 keyStr += 4;
775 sscanf(keyStr, "%8X\n", &iKO->keyID);
776 }
777 }
778
779 if (sd1[0] != 0) close ( sd1[0] );
780 }
781
782
783
784 /*++++++++++++++++++++++++++++
785
786 Verify the PGP signature and extract the signed part in a file.
787
788 EPNodePtr ptr The pointer to the EP treenode containing the originating file
789
790 ++++++++++++++++++++++++++++*/
791
792 void VerifySignAndExplodeFile(EPNodePtr ptr) {
/* [<][>][^][v][top][bottom][index][help] */
793 char *strArgs[10];
794 char Args0[100];
795 char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
796 Args6[100];
797 int gpg_pid;
798 int gpg_in_fd, out_fd, err_fd;
799 int status;
800 char txt[LINE_LENGTH];
801 /* char hostname[MAXHOSTNAMELEN]; */
802 char oFile[FILENAME_LENGTH];
803 char *keyStr;
804 /* int childRC; */
805
806 sprintf(oFile, "%s.%d.exp", ptr->file, ptr->nodeID);
807
808 strcpy(Args0, "--no-secmem-warning");
809 strcpy(Args1, "--keyring");
810 strcpy(Args2, EP_keyRing);
811 strcpy(Args3, "-o");
812 strcpy(Args4, oFile);
813 strcpy(Args5, "-d");
814 strcpy(Args6, ptr->file);
815 strArgs[6] = Args6;
816 strArgs[7] = (char *)0;
817
818 strArgs[0] = Args0;
819 strArgs[1] = Args1;
820 strArgs[2] = Args2;
821 strArgs[3] = Args3;
822 strArgs[4] = Args4;
823 strArgs[5] = Args5;
824
825 gpg_in_fd = INPUT_FD;
826 out_fd = OUTPUT_FD;
827 err_fd = ERROR_FD;
828 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
829 &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
830 {
831 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
832 exit(1);
833 }
834
835 if (waitpid (gpg_pid, &status, 0) < 0)
836 {
837 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
838 exit(1);
839 }
840 if (WIFEXITED(status) == 0)
841 {
842 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
843 exit(1);
844 } else {
845 /* Child exited, checking return code */
846 /* childRC = (status & 0xF00) >> 8;
847 if (childRC == 1) {
848 fprintf (stderr, "Fatal: gpg child return code: %d\n", childRC);
849 printf ("gpg failure\n");
850 exit(1);
851 } */
852 }
853
854
855 /* Parsing gpg output */
856 ptr->isValidPGPSignature = vS_KO;
857 while (fgets (txt, LINE_LENGTH - 1, stdin) != NULL)
858 {
859 /* printf ( "GPG output : %s\n", txt ); */
860 if (strstr(txt, "Good signature") != NULL)
861 ptr->isValidPGPSignature = vS_IS_VALID;
862
863 if (strstr(txt, "CRC error") != NULL)
864 ptr->isValidPGPSignature = vS_CRC_ERROR;
865
866 if (strstr(txt, "public key not found") != NULL)
867 ptr->isValidPGPSignature = vS_NO_PUBLIC_KEY;
868
869 if (strstr(txt, "no valid OpenPGP data found") != NULL)
870 ptr->isValidPGPSignature = vS_NO_OPENPGP_DATA;
871
872 if ((keyStr = strstr(txt, "key ID")) != NULL) {
873 keyStr += 7;
874 sscanf(keyStr, "%8X\n", &ptr->keyID);
875 }
876 }
877
878 unlink(ptr->file);
879 free(ptr->file);
880 ptr->file = strdup(oFile);
881 if (sd1[0] != 0) close ( sd1[0] );
882 }
883
884
885 /*++++++++++++++++++++++++++++
886
887 Get the KeyID of a PGP key.
888
889 struct ImportKeyObject *iKO The structure containing the key of which we want the KeyID
890
891 ++++++++++++++++++++++++++++*/
892
893 void GetKeyID(struct ImportKeyObject *iKO) {
/* [<][>][^][v][top][bottom][index][help] */
894
895 char *strArgs[9];
896 char Args0[100];
897 char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
898 int gpg_pid;
899 int gpg_in_fd, out_fd, err_fd;
900 int status;
901 char txt[LINE_LENGTH];
902 char *keyStr, *pos;
903 const char lockFilename[] = ".PAlock";
904 char keyRingLockFile[1000], keyRingPath[1000];
905 time_t lockBirthDate;
906 FILE *mystdin;
907 int childRC;
908
909 iKO->rc = iKO_GENERALFAILURE;
910
911 strcpy(Args0, "--no-tty");
912 strcpy(Args1, "--no-secmem-warning");
913 strcpy(Args2, "--keyring");
914 strcpy(Args3, iKO->keyRing);
915 strcpy(Args4, "--import");
916 strcpy(Args5, iKO->iFilename);
917
918 strArgs[0] = Args0;
919 strArgs[1] = Args1;
920 strArgs[2] = Args2;
921 strArgs[3] = Args3;
922 strArgs[4] = Args4;
923 strArgs[5] = Args5;
924 strArgs[6] = (char *)0;
925
926 gpg_in_fd = INPUT_FD;
927 out_fd = OUTPUT_FD;
928 err_fd = ERROR_FD;
929
930 /* create lock file filenames for NFS */
931
932 strcpy(keyRingLockFile, iKO->keyRing);
933 if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
934 strcpy(pos + 1, lockFilename);
935 strcpy(keyRingPath, keyRingLockFile);
936 keyRingPath[pos - keyRingLockFile] = 0;
937 } else {
938 strcpy(keyRingLockFile, lockFilename);
939 strcpy(keyRingPath, "");
940 }
941
942 lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
943
944 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
945 &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
946 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
947 exit(1);
948 }
949
950 if (waitpid (gpg_pid, &status, 0) < 0)
951 {
952 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
953 nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
954 exit(1);
955 }
956
957 nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
958
959 if (WIFEXITED(status) == 0)
960 {
961 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
962 exit(1);
963 } else {
964 /* Child exited, checking return code */
965 childRC = (status & 0xF00) >> 8;
966 if (childRC == 1) {
967 ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
968 exit(1);
969 }
970 }
971
972
973 /* Parsing gpg output */
974 /* while (read(0, txt, 1000) != 0)
975 fprintf(stderr, "child read %s\n", txt); */
976
977 mystdin = fdopen(0, "r");
978 iKO->rc = iKO_GENERALFAILURE;
979 while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
980 {
981 /* printf ( "GPG output : %s\n", txt ); */
982
983 if ((keyStr = strstr(txt, "imported")) != NULL) {
984 iKO->rc = iKO_OK;
985 }
986
987 if ((keyStr = strstr(txt, "CRC error")) != NULL) {
988 iKO->rc = iKO_CRC_ERROR;
989 }
990
991 if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL) {
992 iKO->rc = iKO_NO_OPENPGP_DATA;
993 }
994
995 if (((keyStr = strstr(txt, "unchanged")) != NULL) ||
996 ((keyStr = strstr(txt, "not changed")) != NULL)) {
997 iKO->rc = iKO_UNCHANGED;
998 }
999
1000 if ((keyStr = strstr(txt, "gpg: key ")) != NULL) {
1001 keyStr += 9;
1002 sscanf(keyStr, "%8X\n", &iKO->keyID);
1003 }
1004 }
1005
1006 if (sd1[0] != 0) close ( sd1[0] );
1007
1008 }
1009