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 |