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