1 | /***************************************
2 | $Revision: 1.43 $
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,2002 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 |
51 | extern int EP_TreeHeight;
52 | extern int EP_Node_ID;
53 | extern int EP_Debug;
54 |
55 |
56 | /* static int parseMailBlock_nMsg;
57 | static int parseRecursionLevel; */
58 |
59 | extern int sd1[2];
60 | extern int spawn_job (char *path, char *argv[],
61 | int *in_fd, int *out_fd, int *err_fd);
62 | extern time_t nfslock(char *path, char *namelock, int max_age, int notify);
63 | extern int nfsunlock(char *path, char *namelock, int max_age, time_t birth);
64 |
65 |
66 | static char* outputPrefix = NULL;
67 | static char* keyRing = NULL;
68 | static char* gpgCmd = NULL;
69 | static char *tmpdir = NULL;
70 |
71 | static void VerifySignAndExplodeFile(EPNodePtr ptr);
72 | static void GetKeyID(struct ImportKeyObject *iKO);
73 |
74 |
75 | /**************************************
76 | *
77 | * API functions
78 | *
79 | **************************************/
80 |
81 | /*++++++++++++++++++++++++++++
82 |
83 | Copies a string with memory allocation care.
84 |
85 | char* dest The destination string
86 | char* orig The origin string
87 |
88 |
89 | ++++++++++++++++++++++++++++*/
90 |
91 | void pa_strcpy(char** dest, char* orig) {
92 | if (*dest) {
93 | free(*dest);
94 | }
95 |
96 | *dest = malloc(strlen(orig) + 1);
97 | strcpy(*dest, orig);
98 | }
99 |
100 | /*++++++++++++++++++++++++++++
101 |
102 | Set the GPG temporary directory.
103 |
104 | char* dir The directory
105 |
106 |
107 | This memory allocated is never freed, maybe a PA_end function?
108 |
109 | ++++++++++++++++++++++++++++*/
110 |
111 | void PA_SetTmpDir(char* dir) {
112 | pa_strcpy(&tmpdir, dir);
113 | }
114 |
115 | /*++++++++++++++++++++++++++++
116 |
117 | Set the GPG command line.
118 |
119 | char* path The path including command name
120 |
121 |
122 | This memory allocated is never freed, maybe a PA_end function?
123 |
124 | ++++++++++++++++++++++++++++*/
125 |
126 | void PA_SetGPGCmd(char* path) {
127 | pa_strcpy(&gpgCmd, path);
128 | }
129 |
130 | /*++++++++++++++++++++++++++++
131 |
132 | Set the path to the Keyring.
133 |
134 | char* path The path including file name
135 |
136 | ++++++++++++++++++++++++++++*/
137 |
138 | void PA_SetKeyRing(char* path) {
139 | pa_strcpy(&keyRing, path);
140 | }
141 |
142 | /*++++++++++++++++++++++++++++
143 |
144 | Set the path to the output file.
145 |
146 | char* path The path including file name
147 |
148 | ++++++++++++++++++++++++++++*/
149 |
150 | void PA_SetOutputPrefix(char* path) {
151 | pa_strcpy(&outputPrefix, path);
152 | }
153 |
154 | /*++++++++++++++++++++++++++++
155 |
156 | Verify a detached PGP signature.
157 |
158 | struct VerifySignObject *vSO The signed object structure to be verified.
159 |
160 | ++++++++++++++++++++++++++++*/
161 |
162 | void PA_VerifySignature(struct VerifySignObject *vSO) {
163 | char *strArgs[10];
164 | char Args0[100];
165 | char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
166 | Args6[100], Args7[100];
167 | int gpg_pid;
168 | int gpg_in_fd, out_fd, err_fd;
169 | int status;
170 | /* static int nMsgs = 0; */
171 | char txt[LINE_LENGTH];
172 | char *keyStr;
173 | /* int childRC; */
174 |
175 | int fIn,fOut;
176 | char tmpFileName[100],lfcrStr[10],strIn[10];
177 | char prevChar;
178 | FILE *mystdin;
179 |
180 | vSO->type = vSO_Type_Signed;
181 |
182 | strcpy(Args0, "--no-secmem-warning");
183 | strcpy(Args1, "--keyring");
184 | strcpy(Args2, keyRing);
185 | strcpy(Args3, "-o");
186 | if (!strcmp(vSO->iSigFilename, "")) {
187 | strcpy(Args4, vSO->oStream);
188 | strcpy(Args5, "-d");
189 | strcpy(Args6, vSO->iDocSigFilename);
190 | strArgs[6] = Args6;
191 | strArgs[7] = (char *)0;
192 | } else {
193 | /* change <cr> to <lf>+<cr> to be related-rfc compliant */
194 | fIn=open(vSO->iDocSigFilename,O_RDONLY);
195 | if (fIn==-1) {
196 | ER_perror(FAC_PA, PA_CANTREAD, "can't open %s for reading", vSO->iDocSigFilename);
197 | exit(1);
198 | }
199 | strcpy(tmpFileName,tmpdir);
200 | strcat(tmpFileName,"/patmpXXXXXXX");
201 | fOut=mkstemp(tmpFileName);
202 | if (fOut==-1) {
203 | ER_perror(FAC_PA, PA_NOTEMP, "%s", tmpFileName);
204 | exit(1);
205 | }
206 | prevChar=0;
207 | sprintf(lfcrStr,"%c%c%c",13,10,0);
208 | while(read(fIn,strIn,1)>0)
209 | {
210 | if ((strIn[0]==10)&&(prevChar!=13)) {
211 | write(fOut,lfcrStr,2);
212 | } else {
213 | write(fOut,strIn,1);
214 | }
215 | prevChar=strIn[0];
216 | }
217 | close(fOut);
218 | close(fIn);
219 | /* end change <cr> to <lf>+<cr> to be related-rfc compliant */
220 |
221 | strcpy(Args5, "--verify");
222 | strcpy(Args6, vSO->iSigFilename);
223 | strcpy(Args7, tmpFileName);
224 |
225 | strArgs[6] = Args6;
226 | strArgs[7] = Args7;
227 | strArgs[8] = (char *)0;
228 | strcpy(vSO->oStream, vSO->iDocSigFilename);
229 | }
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 |
238 | gpg_in_fd = INPUT_FD;
239 | out_fd = OUTPUT_FD;
240 | err_fd = ERROR_FD;
241 | if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
242 | &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
243 | {
244 | ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
245 | exit(1);
246 | }
247 |
248 | if (waitpid (gpg_pid, &status, 0) < 0)
249 | {
250 | ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
251 | exit(1);
252 | }
253 | unlink(tmpFileName);
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 | fprintf (stderr, "Fatal: gpg child return code: %d\n", childRC);
263 | printf ("gpg failure\n");
264 | exit(1);
265 | } */
266 | }
267 |
268 |
269 | /* Parsing gpg output */
270 | mystdin = fdopen(0, "r");
271 | vSO->isValid = vSO_KO;
272 | while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
273 | {
274 | /* printf ( "GPG output : %s\n", txt ); */
275 | if (strstr(txt, "Good signature") != NULL)
276 | vSO->isValid = vSO_IS_VALID;
277 |
278 | if (strstr(txt, "CRC error") != NULL)
279 | vSO->isValid = vSO_CRC_ERROR;
280 |
281 | if (strstr(txt, "public key not found") != NULL)
282 | vSO->isValid = vSO_NO_PUBLIC_KEY;
283 |
284 | if (strstr(txt, "no valid OpenPGP data found") != NULL)
285 | vSO->isValid = vSO_NO_OPENPGP_DATA;
286 |
287 | if ((keyStr = strstr(txt, "key ID")) != NULL) {
288 | keyStr += 7;
289 | sscanf(keyStr, "%8X\n", &vSO->keyID);
290 | }
291 | }
292 |
293 | if (sd1[0] != 0) close ( sd1[0] );
294 | }
295 |
296 |
297 |
298 | /*++++++++++++++++++++++++++++
299 |
300 | Decrypt a PGP-encrypted file.
301 |
302 | struct ReadCryptedObject *rDO The object to be decrypted
303 |
304 |
305 | Note:
306 | This functions is not used by PA/EP/MM
307 | It can be useful in the future.... (FP)
308 |
309 | ++++++++++++++++++++++++++++*/
310 |
311 | void PA_Decrypt(struct ReadCryptedObject *rDO) {
312 |
313 | char *strArgs[9];
314 | char clearTextExtension[4] = ".gpg";
315 | char Args0[100];
316 | char Args1[100];
317 | char Args2[100];
318 | char Args3[100];
319 | char Args4[100];
320 | char Args5[100];
321 | char Args6[100];
322 | int gpg_pid;
323 | int gpg_in_fd, out_fd, err_fd;
324 | int status;
325 | char txt[LINE_LENGTH];
326 | int childRC;
327 | FILE *mystdin;
328 |
329 | strcpy(Args0, "--no-tty");
330 | strcpy(Args1, "--no-secmem-warning");
331 | strcpy(Args2, "--keyring");
332 | strcpy(Args3, rDO->keyRing);
333 | strcpy(Args4, "--output");
334 | strcpy(Args5, strcat(rDO->iFilename, clearTextExtension));
335 | strcpy(Args6, rDO->iFilename);
336 |
337 | strArgs[0] = Args0;
338 | strArgs[1] = Args1;
339 | strArgs[2] = Args2;
340 | strArgs[3] = Args3;
341 | strArgs[4] = Args4;
342 | strArgs[5] = Args5;
343 | strArgs[6] = Args6;
344 | strArgs[7] = (char *) 0;
345 |
346 | gpg_in_fd = INPUT_FD;
347 | out_fd = OUTPUT_FD;
348 | err_fd = ERROR_FD;
349 | if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
350 | &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
351 | {
352 | ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
353 | exit(1);
354 | }
355 |
356 | if (waitpid (gpg_pid, &status, 0) < 0)
357 | {
358 | ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
359 | exit(1);
360 | }
361 | if (WIFEXITED(status) == 0)
362 | {
363 | ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
364 | exit(1);
365 | } else {
366 | /* Child exited, checking return code */
367 | childRC = (status & 0xF00) >> 8;
368 | if (childRC == 1) {
369 | ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
370 | exit(1);
371 | }
372 | }
373 |
374 |
375 | /* Parsing gpg output */
376 | mystdin = fdopen(0, "r");
377 | while (fgets (txt, STRING_LENGTH - 1, mystdin) != NULL)
378 | {
379 |
380 | }
381 |
382 | if (sd1[0] != 0) close ( sd1[0] );
383 | }
384 |
385 |
386 |
387 | /*++++++++++++++++++++++++++++
388 |
389 | Import a PGP key.
390 |
391 | struct ImportKeyObject *iKO The structure where the imported key goes
392 |
393 | ++++++++++++++++++++++++++++*/
394 |
395 | void PA_ImportKey(struct ImportKeyObject *iKO) {
396 |
397 | char *strArgs[9];
398 | char Args0[100];
399 | char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
400 | int gpg_pid;
401 | int gpg_in_fd, out_fd, err_fd;
402 | int status;
403 | char txt[LINE_LENGTH];
404 | char *keyStr, *pos;
405 | const char lockFilename[] = ".PAlock";
406 | char keyRingLockFile[1000], keyRingPath[1000];
407 | time_t lockBirthDate;
408 | FILE *mystdin;
409 | int childRC;
410 | int key_count;
411 | GList *key_list = NULL;
412 | GList *next = NULL;
413 | struct ImportKeyObject iKO_toBeRemoved;
414 |
415 | iKO->rc = iKO_GENERALFAILURE;
416 |
417 | strcpy(Args0, "--no-tty");
418 | strcpy(Args1, "--no-secmem-warning");
419 | strcpy(Args2, "--keyring");
420 | strcpy(Args3, iKO->keyRing);
421 | strcpy(Args4, "--import");
422 | strcpy(Args5, iKO->iFilename);
423 |
424 | strArgs[0] = Args0;
425 | strArgs[1] = Args1;
426 | strArgs[2] = Args2;
427 | strArgs[3] = Args3;
428 | strArgs[4] = Args4;
429 | strArgs[5] = Args5;
430 | strArgs[6] = (char *)0;
431 |
432 | gpg_in_fd = INPUT_FD;
433 | out_fd = OUTPUT_FD;
434 | err_fd = ERROR_FD;
435 |
436 | /* create lock file filenames for NFS */
437 |
438 | strcpy(keyRingLockFile, iKO->keyRing);
439 | if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
440 | strcpy(pos + 1, lockFilename);
441 | strcpy(keyRingPath, keyRingLockFile);
442 | keyRingPath[pos - keyRingLockFile] = 0;
443 | } else {
444 | strcpy(keyRingLockFile, lockFilename);
445 | strcpy(keyRingPath, "");
446 | }
447 |
448 | lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
449 |
450 | if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
451 | &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
452 | ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
453 | exit(1);
454 | }
455 |
456 | if (waitpid (gpg_pid, &status, 0) < 0)
457 | {
458 | ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
459 | nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
460 | exit(1);
461 | }
462 |
463 | nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
464 |
465 | if (WIFEXITED(status) == 0)
466 | {
467 | ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
468 | }
469 | else
470 | {
471 | /* Child exited, checking return code */
472 | childRC = (status & 0xF00) >> 8;
473 | if (tracing)
474 | printf("TRACING: PA_ImportKey child return code [%d]\n", childRC);
475 | if (childRC == 1)
476 | {
477 | ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
478 | /* exit(1); */
479 | }
480 | }
481 |
482 |
483 | /* Parsing gpg output */
484 | /* while (read(0, txt, 1000) != 0)
485 | fprintf(stderr, "child read %s\n", txt); */
486 |
487 | mystdin = fdopen(0, "r");
488 | iKO->rc = iKO_GENERALFAILURE;
489 | key_count = 0;
490 | while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
491 | {
492 | /* printf ( "GPG output : %s\n", txt ); */
493 |
494 | if ((keyStr = strstr(txt, "imported")) != NULL)
495 | {
496 | iKO->rc = iKO_OK;
497 | }
498 |
499 | if ((keyStr = strstr(txt, "CRC error")) != NULL)
500 | {
501 | iKO->rc = iKO_CRC_ERROR;
502 | }
503 |
504 | if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL)
505 | {
506 | iKO->rc = iKO_NO_OPENPGP_DATA;
507 | }
508 |
509 | if ((keyStr = strstr(txt, "invalid armor header")) != NULL)
510 | {
511 | iKO->rc = iKO_INVALID_ARMOR_HEADER;
512 | }
513 |
514 | if (((keyStr = strstr(txt, "unchanged")) != NULL) ||
515 | ((keyStr = strstr(txt, "not changed")) != NULL))
516 | {
517 | iKO->rc = iKO_UNCHANGED;
518 | }
519 |
520 | if ((keyStr = strstr(txt, "key")) != NULL)
521 | {
522 | keyStr += 4;
523 | sscanf(keyStr, "%8X\n", &iKO->keyID);
524 | key_count++;
525 | /* and put the key ID into the keys list (if it was new to the keyring)*/
526 | if(strstr(txt, "imported") != NULL)
527 | {
528 | key_list = g_list_append(key_list, GINT_TO_POINTER(iKO->keyID));
529 | }
530 | }
531 | }
532 |
533 | if (sd1[0] != 0) close ( sd1[0] );
534 |
535 | if(key_count > 1){/* if there were more than one keys imported */
536 | iKO->rc = iKO_MULTIPLE_KEYS; /* this is an error */
537 | /* now, roll-back, remove the added keys from key-ring */
538 | for( next = key_list; next != NULL; next = g_list_next(next) ){
539 | strcpy(iKO_toBeRemoved.keyRing,
540 | iKO->keyRing);
541 | iKO_toBeRemoved.keyID = (u32)(next->data);
542 | PA_RemoveKey_withKeyID(&iKO_toBeRemoved);
543 | }
544 |
545 | }else{
546 | /* Get the finger print */
547 | GetFingerPrint(iKO);
548 | GetKeyOwner(iKO);
549 | }
550 | }
551 |
552 |
553 |
554 | /*++++++++++++++++++++++++++++
555 |
556 | Remove a PGP key.
557 |
558 | struct ImportKeyObject *iKO The structure containing the key to be removed
559 |
560 | ++++++++++++++++++++++++++++*/
561 |
562 | void PA_RemoveKey(struct ImportKeyObject *iKO) {
563 |
564 | char *strArgs[9];
565 | char Args0[100]= "gpg";
566 | char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100], Args6[100], Args7[100];
567 | int gpg_pid;
568 | int gpg_in_fd, out_fd, err_fd;
569 | int status;
570 | char txt[LINE_LENGTH];
571 | char *keyStr, *pos;
572 | const char lockFilename[] = ".PAlock";
573 | char keyRingLockFile[1000], keyRingPath[1000];
574 | time_t lockBirthDate;
575 | FILE *mystdin;
576 | int childRC;
577 |
578 | iKO->rc = iKO_GENERALFAILURE;
579 |
580 | GetKeyID(iKO); /* getting key-id */
581 |
582 | /* printf("Key id = %08lX\n", iKO->keyID); */
583 |
584 | if ((iKO->rc == iKO_OK) || (iKO->rc == iKO_UNCHANGED)) {
585 | strcpy(Args1, "--batch");
586 | strcpy(Args2, "--yes");
587 | strcpy(Args3, "--no-secmem-warning");
588 | strcpy(Args4, "--keyring");
589 | strcpy(Args5, iKO->keyRing);
590 | strcpy(Args6, "--delete-key");
591 | sprintf(Args7, "%08X", iKO->keyID);
592 |
593 | strArgs[0] = Args0;
594 | strArgs[1] = Args1;
595 | strArgs[2] = Args2;
596 | strArgs[3] = Args3;
597 | strArgs[4] = Args4;
598 | strArgs[5] = Args5;
599 | strArgs[6] = Args6;
600 | strArgs[7] = Args7;
601 | strArgs[8] = (char *)0;
602 |
603 |
604 | gpg_in_fd = INPUT_FD;
605 | out_fd = OUTPUT_FD;
606 | err_fd = ERROR_FD;
607 |
608 | /* create lock file filenames for NFS */
609 |
610 | strcpy(keyRingLockFile, iKO->keyRing);
611 | if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
612 | strcpy(pos + 1, lockFilename);
613 | strcpy(keyRingPath, keyRingLockFile);
614 | keyRingPath[pos - keyRingLockFile] = 0;
615 | } else {
616 | strcpy(keyRingLockFile, lockFilename);
617 | strcpy(keyRingPath, "");
618 | }
619 |
620 | lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
621 |
622 | if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
623 | &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
624 | ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
625 | exit(1);
626 | }
627 |
628 | /* printf("Child pid = %d\n", gpg_pid); */
629 |
630 | if (waitpid (gpg_pid, &status, 0) < 0)
631 | {
632 | ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
633 | exit(1);
634 | }
635 |
636 | nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
637 |
638 | if (WIFEXITED(status) == 0)
639 | {
640 | ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
641 | exit(1);
642 | }
643 | else
644 | {
645 | /* Child exited, checking return code */
646 | childRC = (status & 0xF00) >> 8;
647 | if (childRC == 1)
648 | {
649 | ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
650 | }
651 | }
652 |
653 |
654 | mystdin = fdopen(0, "r");
655 | iKO->rc = iKO_OK;
656 | while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
657 | {
658 | /* printf ( "GPG output : %s\n", txt ); */
659 |
660 | if ((keyStr = strstr(txt, "delete key failed")) != NULL)
661 | {
662 | iKO->rc = iKO_GENERALFAILURE;
663 | }
664 | if ((keyStr = strstr(txt, "there is a secret key for this public key")) != NULL)
665 | {
666 | iKO->rc = iKO_SECRET_KEY_PRESENT;
667 | }
668 | }
669 |
670 | if (sd1[0] != 0) close ( sd1[0] );
671 | }
672 | }
673 |
674 | /*++++++++++++++++++++++++++++
675 |
676 | Remove a PGP key, using its KeyID (otherwise it's the same as PA_RemoveKey
677 |
678 | struct ImportKeyObject *iKO The structure containing the key to be removed
679 |
680 | ++++++++++++++++++++++++++++*/
681 |
682 | void PA_RemoveKey_withKeyID(struct ImportKeyObject *iKO) {
683 |
684 | char *strArgs[9];
685 | char Args0[100]= "gpg";
686 | char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100], Args6[100], Args7[100];
687 | int gpg_pid;
688 | int gpg_in_fd, out_fd, err_fd;
689 | int status;
690 | char txt[LINE_LENGTH];
691 | char *keyStr, *pos;
692 | const char lockFilename[] = ".PAlock";
693 | char keyRingLockFile[1000], keyRingPath[1000];
694 | time_t lockBirthDate;
695 | FILE *mystdin;
696 | int childRC;
697 |
698 | iKO->rc = iKO_GENERALFAILURE;
699 |
700 |
701 | strcpy(Args1, "--batch");
702 | strcpy(Args2, "--yes");
703 | strcpy(Args3, "--no-secmem-warning");
704 | strcpy(Args4, "--keyring");
705 | strcpy(Args5, iKO->keyRing);
706 | strcpy(Args6, "--delete-key");
707 | sprintf(Args7, "%08X", iKO->keyID);
708 |
709 | strArgs[0] = Args0;
710 | strArgs[1] = Args1;
711 | strArgs[2] = Args2;
712 | strArgs[3] = Args3;
713 | strArgs[4] = Args4;
714 | strArgs[5] = Args5;
715 | strArgs[6] = Args6;
716 | strArgs[7] = Args7;
717 | strArgs[8] = (char *)0;
718 |
719 |
720 | gpg_in_fd = INPUT_FD;
721 | out_fd = OUTPUT_FD;
722 | err_fd = ERROR_FD;
723 |
724 | /* create lock file filenames for NFS */
725 |
726 | strcpy(keyRingLockFile, iKO->keyRing);
727 | if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
728 | strcpy(pos + 1, lockFilename);
729 | strcpy(keyRingPath, keyRingLockFile);
730 | keyRingPath[pos - keyRingLockFile] = 0;
731 | } else {
732 | strcpy(keyRingLockFile, lockFilename);
733 | strcpy(keyRingPath, "");
734 | }
735 |
736 | lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
737 |
738 |
739 | if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
740 | &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
741 | ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
742 | exit(1);
743 | }
744 |
745 | /* printf("Child pid = %d\n", gpg_pid); */
746 |
747 | if (waitpid (gpg_pid, &status, 0) < 0)
748 | {
749 | ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
750 | exit(1);
751 | }
752 |
753 | nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
754 |
755 | if (WIFEXITED(status) == 0)
756 | {
757 | ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
758 | exit(1);
759 | } else {
760 | /* Child exited, checking return code */
761 | childRC = (status & 0xF00) >> 8;
762 | if (childRC == 1) {
763 | ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
764 | }
765 | }
766 |
767 |
768 | mystdin = fdopen(0, "r");
769 | iKO->rc = iKO_OK;
770 | while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
771 | {
772 | /* printf ( "GPG output : %s\n", txt ); */
773 |
774 | if ((keyStr = strstr(txt, "delete key failed")) != NULL) {
775 | iKO->rc = iKO_GENERALFAILURE;
776 | }
777 | if ((keyStr = strstr(txt, "there is a secret key for this public key")) != NULL) {
778 | iKO->rc = iKO_SECRET_KEY_PRESENT;
779 | }
780 |
781 | }
782 |
783 | if (sd1[0] != 0) close ( sd1[0] );
784 |
785 | }
786 |
787 |
788 |
789 |
790 | /*++++++++++++++++++++++++++++
791 |
792 | Parse a file and look for PGP-signed elements inside.
793 |
794 | EPNodePtr ptr The pointer to the EP treenode containing the file to be parsed.
795 |
796 | ++++++++++++++++++++++++++++*/
797 |
798 | EPNodePtr PA_ParseMessage(EPNodePtr ptr) {
799 |
800 | /* Assumptions:
801 | - ptr is describing a text file, not MIME
802 | - input file is broken down to pieces, plain text or PGP blocks
803 | - if input file is doesn't have any PGP block, this is a leaf
804 | - otherwise send each block to the proper handler.
805 | */
806 |
807 | FILE *fin, *fout;
808 | char txt[MAX_LINE_BUF], *strptr;
809 | /* char blockFilename[LINE_LENGTH]; */
810 | const char PGP_prefix_msg[] = "-----BEGIN PGP MESSAGE";
811 | const char PGP_suffix_msg[] = "-----END PGP MESSAGE";
812 | const char PGP_prefix_signed[] = "-----BEGIN PGP SIGNED MESSAGE";
813 | const char PGP_suffix_signature[] = "-----END PGP SIGNATURE";
814 | int found_prefix = 0, found_suffix = 0;
815 | EPNodePtr p = ptr, prev = ptr;
816 | int end_of_fin = 0, text_block = 1;
817 |
818 |
819 | ER_dbg_va (FAC_PA, ASP_PA_GEN, "Entering PA_ParseMessage...");
820 |
821 |
822 | if ((fin = fopen(ptr->file, "r")) != NULL) {
823 |
824 | do {
825 | /* this is needed because a text block parser ends when it finds
826 | a PGP prefix, so we already have a txt buffer. */
827 |
828 | if (!text_block || (prev == ptr)) {
829 | strptr = fgets(txt, MAX_LINE_BUF, fin);
830 | if (strptr == NULL ) end_of_fin = 1;
831 | }
832 |
833 | if (!end_of_fin && (found_prefix || (strstr(txt, PGP_prefix_msg) != NULL) ||
834 | (strstr(txt, PGP_prefix_signed) != NULL))) {
835 | /* PGP block */
836 | found_prefix = 1;
837 | text_block = 0;
838 |
839 | p = EP_DefineNewNode(++EP_Node_ID, vS_TO_BE_PGPVERIFIED,
840 | ptr->MIMEContentType, ptr->strMIMEContentType, 0);
841 |
842 | if (prev != ptr)
843 | prev->next = p;
844 | else
845 | ptr->inner = p;
846 |
847 | if ((fout = fopen(p->file, "w")) != NULL ) {
848 | fputs(txt, fout);
849 | /* To be replaced by fwrite(), more efficient */
850 | while ((found_prefix != found_suffix) &&
851 | ((strptr = fgets(txt, MAX_LINE_BUF, fin)) != NULL)) {
852 | if (strstr(txt, PGP_prefix_msg) != NULL) found_prefix++;
853 | if (strstr(txt, PGP_prefix_signed) != NULL) found_prefix++;
854 | if (strstr(txt, PGP_suffix_msg) != NULL) found_suffix++;
855 | if (strstr(txt, PGP_suffix_signature) != NULL) found_suffix++;
856 | fputs(txt, fout);
857 | }
858 | if (strptr == NULL ) end_of_fin = 1;
859 |
860 | fclose(fout);
861 |
862 | if (found_prefix == found_suffix) {
863 | found_prefix = found_suffix = 0;
864 |
865 | VerifySignAndExplodeFile(p);
866 |
867 | /* Called form EP_ParseMail or EP_PArseText ? */
868 |
869 | if (strstr(outputPrefix, "EPMtmp") != NULL)
870 | {
871 | ER_dbg_va (FAC_PA, ASP_PA_GEN, "Found prefix and suffix; calling EP_MIMEParse...");
872 | EP_MIMEParse(p);
873 | }
874 | else {
875 | PA_ParseMessage(p);
876 | }
877 | prev = p;
878 | } else {
879 | /* Wrong PGP delimiters order. */
880 | p->isValidPGPSignature = vS_UNMATCHED_PGP_DELIMITERS;
881 | }
882 | } else {
883 | p->isValidPGPSignature = vS_UNABLE_TO_WRITE_FILE;
884 | return p;
885 | }
886 |
887 | } else {
888 | /* Clear text block */
889 |
890 | text_block = 1;
891 |
892 | if (strptr == NULL) end_of_fin = 1;
893 | else {
894 | p = EP_DefineNewNode(++EP_Node_ID, vS_IS_NOT_PGP,
895 | ptr->MIMEContentType,
896 | ptr->strMIMEContentType, 0);
897 |
898 | if (prev != ptr)
899 | prev->next = p;
900 | else
901 | ptr->inner = p;
902 |
903 | if ((fout = fopen(p->file, "w")) != NULL ) {
904 | fputs(txt, fout);
905 | /* To be replaced by fwrite(), more efficient */
906 | while ((!found_prefix &&
907 | (strptr = fgets(txt, MAX_LINE_BUF, fin)) != NULL)) {
908 | if ((strstr(txt, PGP_prefix_msg) != NULL) ||
909 | (strstr(txt, PGP_prefix_signed) != NULL)) found_prefix++;
910 | else
911 | fputs(txt, fout);
912 | }
913 | if (strptr == NULL ) end_of_fin = 1;
914 |
915 | fclose(fout);
916 |
917 | /* Check if the blockfile is finished and this is the first
918 | segment. If so this is a text leaf */
919 | if (found_prefix || (prev != p)) {
920 | if (prev->MIMEContentType == -1)
921 | {
922 | if (strstr(outputPrefix, "EPMtmp") != NULL)
923 | {
924 | ER_dbg_va (FAC_PA, ASP_PA_GEN, "PA_ParseMessage: sending to EP_MIMEParse");
925 | EP_MIMEParse(p);
926 | }
927 | else {
928 | PA_ParseMessage(p);
929 | }
930 | }
931 |
932 | prev = p;
933 | }
934 |
935 | } else {
936 | p->isValidPGPSignature = vS_UNABLE_TO_WRITE_FILE;
937 | return p;
938 | }
939 | }
940 | }
941 | } while (!end_of_fin);
942 | } else {
943 | p->isValidPGPSignature = vS_NO_IN_FILES;
944 | }
945 |
946 | return ptr;
947 | }
948 |
949 |
950 | /**************************************
951 | *
952 | * Internal functions
953 | *
954 | **************************************/
955 |
956 |
957 |
958 | /*++++++++++++++++++++++++++++
959 |
960 | Get the fingerprint of a PGP key.
961 |
962 | ImportKeyObject *iKO The imported key object
963 |
964 | ++++++++++++++++++++++++++++*/
965 |
966 | void GetFingerPrint(struct ImportKeyObject *iKO) {
967 |
968 | char *strArgs[9];
969 | char Args0[100] ;
970 | char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
971 | int gpg_pid;
972 | int gpg_in_fd, out_fd, err_fd;
973 | int status;
974 | char txt[LINE_LENGTH];
975 | char *keyStr;
976 | FILE *mystdin;
977 | int childRC;
978 |
979 | strcpy(Args0, "--no-tty");
980 | strcpy(Args1, "--no-secmem-warning");
981 | strcpy(Args2, "--keyring");
982 | strcpy(Args3, iKO->keyRing);
983 | strcpy(Args4, "--fingerprint");
984 | sprintf(Args5, "%08X", iKO->keyID);
985 |
986 | strArgs[0] = Args0;
987 | strArgs[1] = Args1;
988 | strArgs[2] = Args2;
989 | strArgs[3] = Args3;
990 | strArgs[4] = Args4;
991 | strArgs[5] = Args5;
992 | strArgs[6] = (char *)0;
993 |
994 | gpg_in_fd = INPUT_FD;
995 | out_fd = OUTPUT_FD;
996 | err_fd = ERROR_FD;
997 |
998 | /* create lock file filenames for NFS */
999 |
1000 | if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
1001 | &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
1002 | ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
1003 | exit(1);
1004 | }
1005 |
1006 | if (waitpid (gpg_pid, &status, 0) < 0)
1007 | {
1008 | ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
1009 | exit(1);
1010 | }
1011 |
1012 | if (WIFEXITED(status) == 0)
1013 | {
1014 | ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
1015 | exit(1);
1016 | } else {
1017 | /* Child exited, checking return code */
1018 | childRC = (status & 0xF00) >> 8;
1019 | if (childRC == 1) {
1020 | ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
1021 | exit(1);
1022 | }
1023 | }
1024 |
1025 |
1026 | mystdin = fdopen(0, "r");
1027 | while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
1028 | {
1029 | /* printf ( "GPG output : %s\n", txt ); */
1030 |
1031 | if ((keyStr = strstr(txt, "Key fingerprint =")) != NULL) {
1032 | strcpy(iKO->fingerPrint, keyStr + 18);
1033 | iKO->fingerPrint[strlen(iKO->fingerPrint)-1] = 0;
1034 | }
1035 |
1036 | if ((keyStr = strstr(txt, "key")) != NULL) {
1037 | keyStr += 4;
1038 | sscanf(keyStr, "%8X\n", &iKO->keyID);
1039 | }
1040 | }
1041 |
1042 | if (sd1[0] != 0) close ( sd1[0] );
1043 | }
1044 |
1045 |
1046 |
1047 | /*++++++++++++++++++++++++++++
1048 |
1049 | Get the owner of a PGP key.
1050 |
1051 | ImportKeyObject *iKO The imported key object
1052 |
1053 | ++++++++++++++++++++++++++++*/
1054 |
1055 | void GetKeyOwner(struct ImportKeyObject *iKO) {
1056 |
1057 | char *strArgs[9];
1058 | char Args0[100] ;
1059 | char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
1060 | int gpg_pid;
1061 | int gpg_in_fd, out_fd, err_fd;
1062 | int status;
1063 | char txt[LINE_LENGTH];
1064 | char *keyStr;
1065 | FILE *mystdin;
1066 | int childRC;
1067 |
1068 | strcpy(Args0, "--no-tty");
1069 | strcpy(Args1, "--no-secmem-warning");
1070 | strcpy(Args2, "--keyring");
1071 | strcpy(Args3, iKO->keyRing);
1072 | strcpy(Args4, "--fingerprint");
1073 | sprintf(Args5, "%08X", iKO->keyID);
1074 |
1075 | strArgs[0] = Args0;
1076 | strArgs[1] = Args1;
1077 | strArgs[2] = Args2;
1078 | strArgs[3] = Args3;
1079 | strArgs[4] = Args4;
1080 | strArgs[5] = Args5;
1081 | strArgs[6] = (char *)0;
1082 |
1083 | gpg_in_fd = INPUT_FD;
1084 | out_fd = OUTPUT_FD;
1085 | err_fd = ERROR_FD;
1086 |
1087 | /* create lock file filenames for NFS */
1088 |
1089 | if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
1090 | &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
1091 | ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
1092 | exit(1);
1093 | }
1094 |
1095 | if (waitpid (gpg_pid, &status, 0) < 0)
1096 | {
1097 | ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
1098 | exit(1);
1099 | }
1100 |
1101 | if (WIFEXITED(status) == 0)
1102 | {
1103 | ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
1104 | exit(1);
1105 | } else {
1106 | /* Child exited, checking return code */
1107 | childRC = (status & 0xF00) >> 8;
1108 | if (childRC == 1) {
1109 | ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
1110 | exit(1);
1111 | }
1112 | }
1113 |
1114 |
1115 | mystdin = fdopen(0, "r");
1116 | while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
1117 | {
1118 | /* printf ( "GPG output : %s\n", txt ); */
1119 |
1120 | if ((keyStr = strstr(txt, "pub "/*"Key fingerprint ="*/)) == txt /*!= NULL*/) {
1121 | strcpy(iKO->keyOwner, keyStr + 30);
1122 | iKO->keyOwner[strlen(iKO->keyOwner)-1] = 0;
1123 | }
1124 |
1125 | if ((keyStr = strstr(txt, "key")) != NULL) {
1126 | keyStr += 4;
1127 | sscanf(keyStr, "%8X\n", &iKO->keyID);
1128 | }
1129 | }
1130 |
1131 | if (sd1[0] != 0) close ( sd1[0] );
1132 | }
1133 |
1134 |
1135 |
1136 | /*++++++++++++++++++++++++++++
1137 |
1138 | Verify the PGP signature and extract the signed part in a file.
1139 |
1140 | EPNodePtr ptr The pointer to the EP treenode containing the originating file
1141 |
1142 | ++++++++++++++++++++++++++++*/
1143 |
1144 | void VerifySignAndExplodeFile(EPNodePtr ptr) {
1145 | char *strArgs[10];
1146 | char Args0[100];
1147 | char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
1148 | Args6[100];
1149 | int gpg_pid;
1150 | int gpg_in_fd, out_fd, err_fd;
1151 | int status;
1152 | char txt[LINE_LENGTH];
1153 | /* char hostname[MAXHOSTNAMELEN]; */
1154 | char oFile[FILENAME_LENGTH];
1155 | char *keyStr;
1156 | /* int childRC; */
1157 | FILE *mystdin;
1158 |
1159 | sprintf(oFile, "%s.%d.exp", ptr->file, ptr->nodeID);
1160 |
1161 | strcpy(Args0, "--no-secmem-warning");
1162 | strcpy(Args1, "--keyring");
1163 | strcpy(Args2, keyRing);
1164 | strcpy(Args3, "-o");
1165 | strcpy(Args4, oFile);
1166 | strcpy(Args5, "-d");
1167 | strcpy(Args6, ptr->file);
1168 | strArgs[6] = Args6;
1169 | strArgs[7] = (char *)0;
1170 |
1171 | strArgs[0] = Args0;
1172 | strArgs[1] = Args1;
1173 | strArgs[2] = Args2;
1174 | strArgs[3] = Args3;
1175 | strArgs[4] = Args4;
1176 | strArgs[5] = Args5;
1177 |
1178 | gpg_in_fd = INPUT_FD;
1179 | out_fd = OUTPUT_FD;
1180 | err_fd = ERROR_FD;
1181 |
1182 | if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
1183 | &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
1184 | ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
1185 | exit(1);
1186 | }
1187 |
1188 | if (waitpid (gpg_pid, &status, 0) < 0) {
1189 | ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
1190 | exit(1);
1191 | }
1192 | if (WIFEXITED(status) == 0) {
1193 | ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
1194 | exit(1);
1195 | }
1196 | else {
1197 | }
1198 |
1199 |
1200 | /* Parsing gpg output */
1201 | mystdin = fdopen(0, "r");
1202 | ptr->isValidPGPSignature = vS_KO;
1203 | while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
1204 | {
1205 | /* printf ( "GPG output : %s\n", txt ); */
1206 | if (strstr(txt, "Good signature") != NULL)
1207 | ptr->isValidPGPSignature = vS_IS_VALID;
1208 |
1209 | if (strstr(txt, "CRC error") != NULL)
1210 | ptr->isValidPGPSignature = vS_CRC_ERROR;
1211 |
1212 | if (strstr(txt, "public key not found") != NULL)
1213 | ptr->isValidPGPSignature = vS_NO_PUBLIC_KEY;
1214 |
1215 | if (strstr(txt, "no valid OpenPGP data found") != NULL)
1216 | ptr->isValidPGPSignature = vS_NO_OPENPGP_DATA;
1217 |
1218 | if ((keyStr = strstr(txt, "key ID")) != NULL) {
1219 | keyStr += 7;
1220 | sscanf(keyStr, "%8X\n", &ptr->keyID);
1221 | }
1222 | }
1223 |
1224 | if (ptr->isValidPGPSignature == vS_NO_OPENPGP_DATA) {
1225 | FILE* f;
1226 | f= fopen(oFile, "w");
1227 | fprintf(f, " \n");
1228 | fclose(f);
1229 | }
1230 |
1231 | unlink(ptr->file);
1232 | UT_free(ptr->file);
1233 | ptr->file = UT_strdup(oFile);
1234 | if (sd1[0] != 0) close ( sd1[0] );
1235 | }
1236 |
1237 |
1238 | /*++++++++++++++++++++++++++++
1239 |
1240 | Get the KeyID of a PGP key.
1241 |
1242 | struct ImportKeyObject *iKO The structure containing the key of which we want the KeyID
1243 |
1244 | ++++++++++++++++++++++++++++*/
1245 |
1246 | void GetKeyID(struct ImportKeyObject *iKO) {
1247 |
1248 | char *strArgs[9];
1249 | char Args0[100];
1250 | char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
1251 | int gpg_pid;
1252 | int gpg_in_fd, out_fd, err_fd;
1253 | int status;
1254 | char txt[LINE_LENGTH];
1255 | char *keyStr, *pos;
1256 | const char lockFilename[] = ".PAlock";
1257 | char keyRingLockFile[1000], keyRingPath[1000];
1258 | time_t lockBirthDate;
1259 | FILE *mystdin;
1260 | int childRC;
1261 |
1262 | iKO->rc = iKO_GENERALFAILURE;
1263 |
1264 | strcpy(Args0, "--no-tty");
1265 | strcpy(Args1, "--no-secmem-warning");
1266 | strcpy(Args2, "--keyring");
1267 | strcpy(Args3, iKO->keyRing);
1268 | strcpy(Args4, "--import");
1269 | strcpy(Args5, iKO->iFilename);
1270 |
1271 | strArgs[0] = Args0;
1272 | strArgs[1] = Args1;
1273 | strArgs[2] = Args2;
1274 | strArgs[3] = Args3;
1275 | strArgs[4] = Args4;
1276 | strArgs[5] = Args5;
1277 | strArgs[6] = (char *)0;
1278 |
1279 | gpg_in_fd = INPUT_FD;
1280 | out_fd = OUTPUT_FD;
1281 | err_fd = ERROR_FD;
1282 |
1283 | /* create lock file filenames for NFS */
1284 |
1285 | strcpy(keyRingLockFile, iKO->keyRing);
1286 | if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
1287 | strcpy(pos + 1, lockFilename);
1288 | strcpy(keyRingPath, keyRingLockFile);
1289 | keyRingPath[pos - keyRingLockFile] = 0;
1290 | } else {
1291 | strcpy(keyRingLockFile, lockFilename);
1292 | strcpy(keyRingPath, "");
1293 | }
1294 |
1295 | lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
1296 |
1297 | if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
1298 | &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
1299 | ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
1300 | exit(1);
1301 | }
1302 |
1303 | if (waitpid (gpg_pid, &status, 0) < 0)
1304 | {
1305 | ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
1306 | nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
1307 | exit(1);
1308 | }
1309 |
1310 | nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
1311 |
1312 | if (WIFEXITED(status) == 0)
1313 | {
1314 | ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
1315 | exit(1);
1316 | } else {
1317 | /* Child exited, checking return code */
1318 | childRC = (status & 0xF00) >> 8;
1319 | if (childRC == 1) {
1320 | ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
1321 | exit(1);
1322 | }
1323 | }
1324 |
1325 |
1326 | /* Parsing gpg output */
1327 | /* while (read(0, txt, 1000) != 0)
1328 | fprintf(stderr, "child read %s\n", txt); */
1329 |
1330 | mystdin = fdopen(0, "r");
1331 | iKO->rc = iKO_GENERALFAILURE;
1332 | while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
1333 | {
1334 | /* printf ( "GPG output : %s\n", txt ); */
1335 |
1336 | if ((keyStr = strstr(txt, "imported")) != NULL) {
1337 | iKO->rc = iKO_OK;
1338 | }
1339 |
1340 | if ((keyStr = strstr(txt, "CRC error")) != NULL) {
1341 | iKO->rc = iKO_CRC_ERROR;
1342 | }
1343 |
1344 | if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL) {
1345 | iKO->rc = iKO_NO_OPENPGP_DATA;
1346 | }
1347 |
1348 | if (((keyStr = strstr(txt, "unchanged")) != NULL) ||
1349 | ((keyStr = strstr(txt, "not changed")) != NULL)) {
1350 | iKO->rc = iKO_UNCHANGED;
1351 | }
1352 |
1353 | if ((keyStr = strstr(txt, "gpg: key ")) != NULL) {
1354 | keyStr += 9;
1355 | sscanf(keyStr, "%8X\n", &iKO->keyID);
1356 | }
1357 | }
1358 |
1359 | if (sd1[0] != 0) close ( sd1[0] );
1360 |
1361 | }
1362 |