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