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
- GetKeyOwner
- VerifySignAndExplodeFile
- GetKeyID
1 /***************************************
2 $Revision: 1.30 $
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 VerifySignAndExplodeFile(EPNodePtr ptr);
73 static void GetKeyID(struct ImportKeyObject *iKO);
74
75
76 /**************************************
77 *
78 * API functions
79 *
80 **************************************/
81
82
83 /*++++++++++++++++++++++++++++
84
85 Verify a detached PGP signature.
86
87 struct VerifySignObject *vSO The signed object structure to be verified.
88
89 ++++++++++++++++++++++++++++*/
90
91 void PA_VerifySignature(struct VerifySignObject *vSO) {
/* [<][>][^][v][top][bottom][index][help] */
92 char *strArgs[10];
93 char Args0[100];
94 char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
95 Args6[100], Args7[100];
96 int gpg_pid;
97 int gpg_in_fd, out_fd, err_fd;
98 int status;
99 /* static int nMsgs = 0; */
100 char txt[LINE_LENGTH];
101 char *keyStr;
102 /* int childRC; */
103
104 vSO->type = vSO_Type_Signed;
105
106 strcpy(Args0, "--no-secmem-warning");
107 strcpy(Args1, "--keyring");
108 strcpy(Args2, vSO->keyRing);
109 strcpy(Args3, "-o");
110 if (!strcmp(vSO->iSigFilename, "")) {
111 strcpy(Args4, vSO->oStream);
112 strcpy(Args5, "-d");
113 strcpy(Args6, vSO->iDocSigFilename);
114 strArgs[6] = Args6;
115 strArgs[7] = (char *)0;
116 } else {
117 strcpy(Args5, "--verify");
118 strcpy(Args6, vSO->iSigFilename);
119 strcpy(Args7, vSO->iDocSigFilename);
120
121 strArgs[6] = Args6;
122 strArgs[7] = Args7;
123 strArgs[8] = (char *)0;
124 strcpy(vSO->oStream, vSO->iDocSigFilename);
125 }
126
127 strArgs[0] = Args0;
128 strArgs[1] = Args1;
129 strArgs[2] = Args2;
130 strArgs[3] = Args3;
131 strArgs[4] = Args4;
132 strArgs[5] = Args5;
133
134 gpg_in_fd = INPUT_FD;
135 out_fd = OUTPUT_FD;
136 err_fd = ERROR_FD;
137 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
138 &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
139 {
140 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
141 exit(1);
142 }
143
144 if (waitpid (gpg_pid, &status, 0) < 0)
145 {
146 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
147 exit(1);
148 }
149 if (WIFEXITED(status) == 0)
150 {
151 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
152 exit(1);
153 } else {
154 /* Child exited, checking return code */
155 /* childRC = (status & 0xF00) >> 8;
156 if (childRC == 1) {
157 fprintf (stderr, "Fatal: gpg child return code: %d\n", childRC);
158 printf ("gpg failure\n");
159 exit(1);
160 } */
161 }
162
163
164 /* Parsing gpg output */
165 vSO->isValid = vSO_KO;
166 while (fgets (txt, LINE_LENGTH - 1, stdin) != NULL)
167 {
168 /* printf ( "GPG output : %s\n", txt ); */
169 if (strstr(txt, "Good signature") != NULL)
170 vSO->isValid = vSO_IS_VALID;
171
172 if (strstr(txt, "CRC error") != NULL)
173 vSO->isValid = vSO_CRC_ERROR;
174
175 if (strstr(txt, "public key not found") != NULL)
176 vSO->isValid = vSO_NO_PUBLIC_KEY;
177
178 if (strstr(txt, "no valid OpenPGP data found") != NULL)
179 vSO->isValid = vSO_NO_OPENPGP_DATA;
180
181 if ((keyStr = strstr(txt, "key ID")) != NULL) {
182 keyStr += 7;
183 sscanf(keyStr, "%8X\n", &vSO->keyID);
184 }
185 }
186
187 if (sd1[0] != 0) close ( sd1[0] );
188 }
189
190
191
192 /*++++++++++++++++++++++++++++
193
194 Decrypt a PGP-encrypted file.
195
196 struct ReadCryptedObject *rDO The object to be decrypted
197
198
199 Note:
200 This functions is not used by PA/EP/MM
201 It can be useful in the future.... (FP)
202
203 ++++++++++++++++++++++++++++*/
204
205 void PA_Decrypt(struct ReadCryptedObject *rDO) {
/* [<][>][^][v][top][bottom][index][help] */
206
207 char *strArgs[9];
208 char clearTextExtension[4] = ".gpg";
209 char Args0[100];
210 char Args1[100];
211 char Args2[100];
212 char Args3[100];
213 char Args4[100];
214 char Args5[100];
215 char Args6[100];
216 int gpg_pid;
217 int gpg_in_fd, out_fd, err_fd;
218 int status;
219 char txt[LINE_LENGTH];
220 int childRC;
221
222 strcpy(Args0, "--no-tty");
223 strcpy(Args1, "--no-secmem-warning");
224 strcpy(Args2, "--keyring");
225 strcpy(Args3, rDO->keyRing);
226 strcpy(Args4, "--output");
227 strcpy(Args5, strcat(rDO->iFilename, clearTextExtension));
228 strcpy(Args6, rDO->iFilename);
229
230 strArgs[0] = Args0;
231 strArgs[1] = Args1;
232 strArgs[2] = Args2;
233 strArgs[3] = Args3;
234 strArgs[4] = Args4;
235 strArgs[5] = Args5;
236 strArgs[6] = Args6;
237 strArgs[7] = (char *) 0;
238
239 gpg_in_fd = INPUT_FD;
240 out_fd = OUTPUT_FD;
241 err_fd = ERROR_FD;
242 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
243 &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
244 {
245 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
246 exit(1);
247 }
248
249 if (waitpid (gpg_pid, &status, 0) < 0)
250 {
251 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
252 exit(1);
253 }
254 if (WIFEXITED(status) == 0)
255 {
256 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
257 exit(1);
258 } else {
259 /* Child exited, checking return code */
260 childRC = (status & 0xF00) >> 8;
261 if (childRC == 1) {
262 ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
263 exit(1);
264 }
265 }
266
267
268 /* Parsing gpg output */
269 while (fgets (txt, STRING_LENGTH - 1, stdin) != NULL)
270 {
271
272 }
273
274 if (sd1[0] != 0) close ( sd1[0] );
275 }
276
277
278
279 /*++++++++++++++++++++++++++++
280
281 Import a PGP key.
282
283 struct ImportKeyObject *iKO The structure where the imported key goes
284
285 ++++++++++++++++++++++++++++*/
286
287 void PA_ImportKey(struct ImportKeyObject *iKO) {
/* [<][>][^][v][top][bottom][index][help] */
288
289 char *strArgs[9];
290 char Args0[100];
291 char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
292 int gpg_pid;
293 int gpg_in_fd, out_fd, err_fd;
294 int status;
295 char txt[LINE_LENGTH];
296 char *keyStr, *pos;
297 const char lockFilename[] = ".PAlock";
298 char keyRingLockFile[1000], keyRingPath[1000];
299 time_t lockBirthDate;
300 FILE *mystdin;
301 int childRC;
302
303 iKO->rc = iKO_GENERALFAILURE;
304
305 strcpy(Args0, "--no-tty");
306 strcpy(Args1, "--no-secmem-warning");
307 strcpy(Args2, "--keyring");
308 strcpy(Args3, iKO->keyRing);
309 strcpy(Args4, "--import");
310 strcpy(Args5, iKO->iFilename);
311
312 strArgs[0] = Args0;
313 strArgs[1] = Args1;
314 strArgs[2] = Args2;
315 strArgs[3] = Args3;
316 strArgs[4] = Args4;
317 strArgs[5] = Args5;
318 strArgs[6] = (char *)0;
319
320 gpg_in_fd = INPUT_FD;
321 out_fd = OUTPUT_FD;
322 err_fd = ERROR_FD;
323
324 /* create lock file filenames for NFS */
325
326 strcpy(keyRingLockFile, iKO->keyRing);
327 if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
328 strcpy(pos + 1, lockFilename);
329 strcpy(keyRingPath, keyRingLockFile);
330 keyRingPath[pos - keyRingLockFile] = 0;
331 } else {
332 strcpy(keyRingLockFile, lockFilename);
333 strcpy(keyRingPath, "");
334 }
335
336 lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
337
338 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
339 &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
340 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
341 exit(1);
342 }
343
344 if (waitpid (gpg_pid, &status, 0) < 0)
345 {
346 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
347 nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
348 exit(1);
349 }
350
351 nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
352
353 if (WIFEXITED(status) == 0)
354 {
355 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
356 } else {
357 /* Child exited, checking return code */
358 childRC = (status & 0xF00) >> 8;
359 if (childRC == 1) {
360 ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
361 exit(1);
362 }
363 }
364
365
366 /* Parsing gpg output */
367 /* while (read(0, txt, 1000) != 0)
368 fprintf(stderr, "child read %s\n", txt); */
369
370 mystdin = fdopen(0, "r");
371 iKO->rc = iKO_GENERALFAILURE;
372 while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
373 {
374 /* printf ( "GPG output : %s\n", txt ); */
375
376 if ((keyStr = strstr(txt, "imported")) != NULL) {
377 iKO->rc = iKO_OK;
378 }
379
380 if ((keyStr = strstr(txt, "CRC error")) != NULL) {
381 iKO->rc = iKO_CRC_ERROR;
382 }
383
384 if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL) {
385 iKO->rc = iKO_NO_OPENPGP_DATA;
386 }
387
388 if (((keyStr = strstr(txt, "unchanged")) != NULL) ||
389 ((keyStr = strstr(txt, "not changed")) != NULL)) {
390 iKO->rc = iKO_UNCHANGED;
391 }
392
393 if ((keyStr = strstr(txt, "key")) != NULL) {
394 keyStr += 4;
395 sscanf(keyStr, "%8X\n", &iKO->keyID);
396 }
397 }
398
399 if (sd1[0] != 0) close ( sd1[0] );
400
401 /* Get the finger print */
402
403 GetFingerPrint(iKO);
404 GetKeyOwner(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 Get the owner of a PGP key.
787
788 ImportKeyObject *iKO The imported key object
789
790 ++++++++++++++++++++++++++++*/
791
792 void GetKeyOwner(struct ImportKeyObject *iKO) {
/* [<][>][^][v][top][bottom][index][help] */
793
794 char *strArgs[9];
795 char Args0[100] ;
796 char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
797 int gpg_pid;
798 int gpg_in_fd, out_fd, err_fd;
799 int status;
800 char txt[LINE_LENGTH];
801 char *keyStr;
802 FILE *mystdin;
803 int childRC;
804
805 strcpy(Args0, "--no-tty");
806 strcpy(Args1, "--no-secmem-warning");
807 strcpy(Args2, "--keyring");
808 strcpy(Args3, iKO->keyRing);
809 strcpy(Args4, "--fingerprint");
810 sprintf(Args5, "%08X", iKO->keyID);
811
812 strArgs[0] = Args0;
813 strArgs[1] = Args1;
814 strArgs[2] = Args2;
815 strArgs[3] = Args3;
816 strArgs[4] = Args4;
817 strArgs[5] = Args5;
818 strArgs[6] = (char *)0;
819
820 gpg_in_fd = INPUT_FD;
821 out_fd = OUTPUT_FD;
822 err_fd = ERROR_FD;
823
824 /* create lock file filenames for NFS */
825
826 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
827 &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
828 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
829 exit(1);
830 }
831
832 if (waitpid (gpg_pid, &status, 0) < 0)
833 {
834 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
835 exit(1);
836 }
837
838 if (WIFEXITED(status) == 0)
839 {
840 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
841 exit(1);
842 } else {
843 /* Child exited, checking return code */
844 childRC = (status & 0xF00) >> 8;
845 if (childRC == 1) {
846 ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
847 exit(1);
848 }
849 }
850
851
852 mystdin = fdopen(0, "r");
853 while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
854 {
855 /* printf ( "GPG output : %s\n", txt ); */
856
857 if ((keyStr = strstr(txt, "pub "/*"Key fingerprint ="*/)) == txt /*!= NULL*/) {
858 strcpy(iKO->keyOwner, keyStr + 30);
859 iKO->keyOwner[strlen(iKO->keyOwner)-1] = 0;
860 }
861
862 if ((keyStr = strstr(txt, "key")) != NULL) {
863 keyStr += 4;
864 sscanf(keyStr, "%8X\n", &iKO->keyID);
865 }
866 }
867
868 if (sd1[0] != 0) close ( sd1[0] );
869 }
870
871
872
873
874 /*++++++++++++++++++++++++++++
875
876 Verify the PGP signature and extract the signed part in a file.
877
878 EPNodePtr ptr The pointer to the EP treenode containing the originating file
879
880 ++++++++++++++++++++++++++++*/
881
882 void VerifySignAndExplodeFile(EPNodePtr ptr) {
/* [<][>][^][v][top][bottom][index][help] */
883 char *strArgs[10];
884 char Args0[100];
885 char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
886 Args6[100];
887 int gpg_pid;
888 int gpg_in_fd, out_fd, err_fd;
889 int status;
890 char txt[LINE_LENGTH];
891 /* char hostname[MAXHOSTNAMELEN]; */
892 char oFile[FILENAME_LENGTH];
893 char *keyStr;
894 /* int childRC; */
895
896 sprintf(oFile, "%s.%d.exp", ptr->file, ptr->nodeID);
897
898 strcpy(Args0, "--no-secmem-warning");
899 strcpy(Args1, "--keyring");
900 strcpy(Args2, EP_keyRing);
901 strcpy(Args3, "-o");
902 strcpy(Args4, oFile);
903 strcpy(Args5, "-d");
904 strcpy(Args6, ptr->file);
905 strArgs[6] = Args6;
906 strArgs[7] = (char *)0;
907
908 strArgs[0] = Args0;
909 strArgs[1] = Args1;
910 strArgs[2] = Args2;
911 strArgs[3] = Args3;
912 strArgs[4] = Args4;
913 strArgs[5] = Args5;
914
915 gpg_in_fd = INPUT_FD;
916 out_fd = OUTPUT_FD;
917 err_fd = ERROR_FD;
918 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
919 &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
920 {
921 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
922 exit(1);
923 }
924
925 if (waitpid (gpg_pid, &status, 0) < 0)
926 {
927 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
928 exit(1);
929 }
930 if (WIFEXITED(status) == 0)
931 {
932 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
933 exit(1);
934 } else {
935 /* Child exited, checking return code */
936 /* childRC = (status & 0xF00) >> 8;
937 if (childRC == 1) {
938 fprintf (stderr, "Fatal: gpg child return code: %d\n", childRC);
939 printf ("gpg failure\n");
940 exit(1);
941 } */
942 }
943
944
945 /* Parsing gpg output */
946 ptr->isValidPGPSignature = vS_KO;
947 while (fgets (txt, LINE_LENGTH - 1, stdin) != NULL)
948 {
949 /* printf ( "GPG output : %s\n", txt ); */
950 if (strstr(txt, "Good signature") != NULL)
951 ptr->isValidPGPSignature = vS_IS_VALID;
952
953 if (strstr(txt, "CRC error") != NULL)
954 ptr->isValidPGPSignature = vS_CRC_ERROR;
955
956 if (strstr(txt, "public key not found") != NULL)
957 ptr->isValidPGPSignature = vS_NO_PUBLIC_KEY;
958
959 if (strstr(txt, "no valid OpenPGP data found") != NULL)
960 ptr->isValidPGPSignature = vS_NO_OPENPGP_DATA;
961
962 if ((keyStr = strstr(txt, "key ID")) != NULL) {
963 keyStr += 7;
964 sscanf(keyStr, "%8X\n", &ptr->keyID);
965 }
966 }
967
968 unlink(ptr->file);
969 free(ptr->file);
970 ptr->file = strdup(oFile);
971 if (sd1[0] != 0) close ( sd1[0] );
972 }
973
974
975 /*++++++++++++++++++++++++++++
976
977 Get the KeyID of a PGP key.
978
979 struct ImportKeyObject *iKO The structure containing the key of which we want the KeyID
980
981 ++++++++++++++++++++++++++++*/
982
983 void GetKeyID(struct ImportKeyObject *iKO) {
/* [<][>][^][v][top][bottom][index][help] */
984
985 char *strArgs[9];
986 char Args0[100];
987 char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
988 int gpg_pid;
989 int gpg_in_fd, out_fd, err_fd;
990 int status;
991 char txt[LINE_LENGTH];
992 char *keyStr, *pos;
993 const char lockFilename[] = ".PAlock";
994 char keyRingLockFile[1000], keyRingPath[1000];
995 time_t lockBirthDate;
996 FILE *mystdin;
997 int childRC;
998
999 iKO->rc = iKO_GENERALFAILURE;
1000
1001 strcpy(Args0, "--no-tty");
1002 strcpy(Args1, "--no-secmem-warning");
1003 strcpy(Args2, "--keyring");
1004 strcpy(Args3, iKO->keyRing);
1005 strcpy(Args4, "--import");
1006 strcpy(Args5, iKO->iFilename);
1007
1008 strArgs[0] = Args0;
1009 strArgs[1] = Args1;
1010 strArgs[2] = Args2;
1011 strArgs[3] = Args3;
1012 strArgs[4] = Args4;
1013 strArgs[5] = Args5;
1014 strArgs[6] = (char *)0;
1015
1016 gpg_in_fd = INPUT_FD;
1017 out_fd = OUTPUT_FD;
1018 err_fd = ERROR_FD;
1019
1020 /* create lock file filenames for NFS */
1021
1022 strcpy(keyRingLockFile, iKO->keyRing);
1023 if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
1024 strcpy(pos + 1, lockFilename);
1025 strcpy(keyRingPath, keyRingLockFile);
1026 keyRingPath[pos - keyRingLockFile] = 0;
1027 } else {
1028 strcpy(keyRingLockFile, lockFilename);
1029 strcpy(keyRingPath, "");
1030 }
1031
1032 lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
1033
1034 if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
1035 &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
1036 ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
1037 exit(1);
1038 }
1039
1040 if (waitpid (gpg_pid, &status, 0) < 0)
1041 {
1042 ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
1043 nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
1044 exit(1);
1045 }
1046
1047 nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
1048
1049 if (WIFEXITED(status) == 0)
1050 {
1051 ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
1052 exit(1);
1053 } else {
1054 /* Child exited, checking return code */
1055 childRC = (status & 0xF00) >> 8;
1056 if (childRC == 1) {
1057 ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
1058 exit(1);
1059 }
1060 }
1061
1062
1063 /* Parsing gpg output */
1064 /* while (read(0, txt, 1000) != 0)
1065 fprintf(stderr, "child read %s\n", txt); */
1066
1067 mystdin = fdopen(0, "r");
1068 iKO->rc = iKO_GENERALFAILURE;
1069 while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
1070 {
1071 /* printf ( "GPG output : %s\n", txt ); */
1072
1073 if ((keyStr = strstr(txt, "imported")) != NULL) {
1074 iKO->rc = iKO_OK;
1075 }
1076
1077 if ((keyStr = strstr(txt, "CRC error")) != NULL) {
1078 iKO->rc = iKO_CRC_ERROR;
1079 }
1080
1081 if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL) {
1082 iKO->rc = iKO_NO_OPENPGP_DATA;
1083 }
1084
1085 if (((keyStr = strstr(txt, "unchanged")) != NULL) ||
1086 ((keyStr = strstr(txt, "not changed")) != NULL)) {
1087 iKO->rc = iKO_UNCHANGED;
1088 }
1089
1090 if ((keyStr = strstr(txt, "gpg: key ")) != NULL) {
1091 keyStr += 9;
1092 sscanf(keyStr, "%8X\n", &iKO->keyID);
1093 }
1094 }
1095
1096 if (sd1[0] != 0) close ( sd1[0] );
1097
1098 }
1099