1    | #include <stdio.h>
2    | #include <stdlib.h>
3    | #include <string.h>
4    | #include <sys/wait.h>
5    | #include <unistd.h>
6    | #include <errno.h>
7    | #include <sys/types.h>
8    | #include <sys/stat.h>
9    | #include <fcntl.h>
10   | #include <time.h>
11   | 
12   | #include "gpg.h"
13   | 
14   | extern int sd1[2];
15   | extern int spawn_job (char *path, char *argv[], 
16   | 		      int *in_fd, int *out_fd, int *err_fd);
17   | extern time_t nfslock(char *path, char *namelock, int max_age, int notify);
18   | extern int nfsunlock(char *path, char *namelock, int max_age, time_t birth);
19   | 
20   | void ParseInputFile(struct VerifySignObject *vSO) {
21   |   FILE *fin, *fout;
22   |   char txt[LINE_LENGTH];
23   |   char keyRing[LINE_LENGTH];
24   |   char outputPath[LINE_LENGTH];
25   |   const char PGP_prefix[] = "-----BEGIN PGP ";
26   |   const char PGP_suffix[] = "-----END PGP ";
27   |   int found_prefix = 0, nMsgs = 0, outFileOpened = 0, clearTextBlock = 1;
28   |   char foutName[100];
29   |   struct VerifySignObject *vSOList = vSO;
30   |   
31   |   strcpy(keyRing, vSO->keyRing);
32   |   strcpy(outputPath, vSO->outputPath);
33   | 
34   |   if (!strcmp(vSOList->iSigFilename, "")) {
35   |     if ((fin = fopen(vSOList->iDocSigFilename, "r")) != NULL) { 
36   | 
37   |       while (fgets (txt, LINE_LENGTH - 1, fin) != NULL) {
38   | 
39   |       /* Looking for PGP prefix */
40   | 	if ((strstr(txt, PGP_prefix) != NULL) && !found_prefix) {
41   | 	  clearTextBlock = 0;
42   | 	  found_prefix = 1;
43   | 	  /* remember to delete those files */
44   | 	  sprintf(foutName, "/tmp/PAtmp.%d.%d", (int)getpid(), nMsgs);
45   | 	  if ((fout = fopen(foutName, "w")) == NULL ) {
46   | 	    vSOList->isValid = vSO_NO_OUT_FILES;
47   | 	    return;
48   | 	  }
49   | 	  outFileOpened = 1;
50   | 	  vSOList->next = malloc(sizeof(struct VerifySignObject));
51   | 	  vSOList = vSOList->next;
52   | 	  strcpy(vSOList->iDocSigFilename, foutName);
53   | 	  strcpy(vSOList->keyRing, keyRing);
54   | 	  strcpy(vSOList->outputPath, outputPath);
55   | 	  vSOList->next = NULL;
56   | 	} else
57   | 	  if ((strstr(txt, PGP_suffix) != NULL ) && found_prefix) {
58   | 	    found_prefix = 0;
59   | 	    clearTextBlock = 1;
60   | 	    fputs(txt, fout);
61   | 	    fclose(fout);
62   | 	    outFileOpened = 0;
63   | 	    nMsgs++;
64   | 	  } else 
65   | 	    if (clearTextBlock && !outFileOpened) {
66   | 	      sprintf(foutName, "/tmp/PAtmp.%d.%d", (int)getpid(), nMsgs);
67   | 	      if ((fout = fopen(foutName, "w")) == NULL ) {
68   | 		vSOList->isValid = vSO_NO_OUT_FILES;
69   | 		return;
70   | 	      }
71   | 	      outFileOpened = 1;
72   | 	      vSOList->next = malloc(sizeof(struct VerifySignObject));
73   | 	      vSOList = vSOList->next;
74   | 	      strcpy(vSOList->iDocSigFilename, foutName);
75   | 	      strcpy(vSOList->keyRing, keyRing);
76   | 	      strcpy(vSOList->outputPath, outputPath);
77   | 	      vSOList->next = NULL;
78   | 	    }
79   | 	if (outFileOpened) {
80   | 	  fputs(txt, fout);
81   | 	}       
82   |       }
83   |       if (outFileOpened) {
84   | 	fclose(fout);
85   |       }
86   |       fclose(fin);
87   |     } else {
88   |       vSOList->isValid = vSO_NO_IN_FILES;
89   |     }
90   |   }
91   | }
92   | 
93   | void VerifySignature(struct VerifySignObject *vSO) {
94   |   char *strArgs[10];
95   |   char Args0[100];
96   |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
97   |     Args6[100], Args7[100];
98   |   int gpg_pid;
99   |   int gpg_in_fd, out_fd, err_fd;
100  |   int status;
101  |   static int nMsgs = 0;
102  |   char txt[LINE_LENGTH];
103  |   char *keyStr;
104  |   struct VerifySignObject *pvSO = vSO->next, *ptmp;
105  | 
106  |   while (pvSO != NULL) {
107  |     nMsgs++;
108  |     /* Copy the incoming object on the internal global object */
109  |     /* memmove( &verifySignObj, pvSO, sizeof(struct VerifySignObject) ); */
110  | 
111  |     sprintf(pvSO->oStream, "%s/PAtmp.%ld.%ld.%d", pvSO->outputPath, 
112  | 	    labs(gethostid()), getpid(), nMsgs);
113  | 
114  |     strcpy(Args0, "--no-secmem-warning");
115  |     strcpy(Args1, "--keyring");
116  |     strcpy(Args2, pvSO->keyRing);
117  |     strcpy(Args3, "-o");
118  |     strcpy(Args4, pvSO->oStream);
119  |     strcpy(Args5, "-d");
120  |     if (!strcmp(pvSO->iSigFilename, "")) {
121  |       strcpy(Args6, pvSO->iDocSigFilename);
122  |       strArgs[6] = Args6;
123  |       strArgs[7] = (char *)0;
124  |     } else {
125  |       strcpy(Args6, pvSO->iSigFilename);
126  |       strcpy(Args7, pvSO->iDocSigFilename);
127  |       strArgs[6] = Args6;
128  |       strArgs[7] = Args7;
129  |       strArgs[8] = (char *)0;
130  |     }
131  | 
132  |     strArgs[0] = Args0;
133  |     strArgs[1] = Args1;  
134  |     strArgs[2] = Args2;  
135  |     strArgs[3] = Args3;
136  |     strArgs[4] = Args4;
137  |     strArgs[5] = Args5;
138  |   
139  |     gpg_in_fd = INPUT_FD;
140  |     out_fd = OUTPUT_FD;
141  |     err_fd = ERROR_FD;
142  |     if ( ( gpg_pid = spawn_job ("gpg", strArgs,
143  | 				&gpg_in_fd, &out_fd, &err_fd) ) < 0 )
144  |       {
145  | 	printf ("could not spawn gpg");
146  |       }
147  |   
148  |     if (waitpid (gpg_pid, &status, 0) < 0)
149  |       {
150  | 	fprintf (stderr, "Error reaping child\t%s\n", ERRSTRING);
151  | 	printf ("could not reap gpg process");
152  |       }
153  |     if (WIFEXITED(status) == 0)
154  |       {
155  | 	fprintf (stderr, "Bad child status: %d\t%s\n", status, ERRSTRING);
156  | 	printf ("gpg failure\n");
157  |       }
158  | 
159  | 
160  |     /* Parsing gpg output */
161  |     pvSO->isValid = vSO_KO;
162  |     while (fgets (txt, LINE_LENGTH - 1, stdin) != NULL)
163  |       {
164  | 	/* 	printf ( "GPG output : %s\n", txt );  */
165  | 	if (strstr(txt, "Good signature") != NULL)
166  | 	  pvSO->isValid = vSO_IS_VALID;
167  | 
168  | 	if (strstr(txt, "CRC error") != NULL)
169  | 	  pvSO->isValid = vSO_CRC_ERROR;
170  | 
171  | 	if (strstr(txt, "public key not found") != NULL)
172  | 	  pvSO->isValid = vSO_NO_PUBLIC_KEY;
173  | 
174  | 	if (strstr(txt, "no valid OpenPGP data found") != NULL)
175  | 	  pvSO->isValid = vSO_NO_OPENPGP_DATA;
176  | 
177  | 	if ((keyStr = strstr(txt, "key ID")) != NULL) {
178  | 	  keyStr += 7;
179  | 	  sscanf(keyStr, "%8X\n", &pvSO->keyID);
180  | 	}
181  |       }
182  |     
183  |     unlink(pvSO->iDocSigFilename);
184  |     pvSO = pvSO->next;
185  |   }
186  |   if (sd1[0] != 0)  close ( sd1[0] ); 
187  | }
188  | 
189  | 
190  | /* ------------------------------------------------- */
191  | void PA_VerifySignature(struct VerifySignObject *vSO) {
192  |   
193  |   /* split input file if there are multiple signed messages */
194  |   ParseInputFile( vSO );
195  | 
196  |   /* Verify each single PGP mesg */
197  |   VerifySignature( vSO );
198  | 
199  | }
200  | 
201  | /* ------------------------------------------------- */
202  | void PA_Decrypt(struct ReadCryptedObject *rDO) {
203  |   
204  |   char *strArgs[9];
205  |   char clearTextExtension[4] = ".gpg";
206  |   char Args0[100] = "abracadabra";
207  |   char Args1[100];
208  |   char Args2[100];
209  |   char Args3[100];
210  |   char Args4[100];
211  |   char Args5[100];
212  |   char Args6[100];
213  |   int gpg_pid;
214  |   int gpg_in_fd, out_fd, err_fd;
215  |   int status;
216  |   char txt[LINE_LENGTH];
217  | 
218  | 
219  |   strcpy(Args0, "--no-tty");
220  |   strcpy(Args1, "--no-secmem-warning");
221  |   strcpy(Args2, "--keyring");
222  |   strcpy(Args3, rDO->keyRing);
223  |   strcpy(Args4, "--output");
224  |   strcpy(Args5, strcat(rDO->iFilename, clearTextExtension));
225  |   strcpy(Args6, rDO->iFilename);
226  |   
227  |   strArgs[0] = Args0;
228  |   strArgs[1] = Args1;  
229  |   strArgs[2] = Args2;  
230  |   strArgs[3] = Args3;  
231  |   strArgs[4] = Args4;  
232  |   strArgs[5] = Args5;  
233  |   strArgs[6] = Args6;  
234  |   strArgs[7] = (char *) 0;   
235  | 
236  |   gpg_in_fd = INPUT_FD;
237  |   out_fd = OUTPUT_FD;
238  |   err_fd = ERROR_FD;
239  |   if ( ( gpg_pid = spawn_job ("gpg", strArgs,
240  | 			      &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
241  |     {
242  |       printf ("could not spawn gpg");
243  |     }
244  |   
245  |   if (waitpid (gpg_pid, &status, 0) < 0)
246  |     {
247  |       fprintf (stderr, "Error reaping child\t%s\n", ERRSTRING);
248  |       printf ("could not reap gpg process");
249  |     }
250  |   if (WIFEXITED(status) == 0)
251  |     {
252  |       fprintf (stderr, "Bad child status: %d\t%s\n", status, ERRSTRING);
253  |       printf ("gpg failure");
254  |     }
255  | 
256  | 
257  |   /* Parsing gpg output */
258  |   while (fgets (txt, STRING_LENGTH - 1, stdin) != NULL)
259  |     {
260  |       
261  |     }
262  |   
263  |   if (sd1[0] != 0)  close ( sd1[0] ); 
264  | }
265  | 
266  | 
267  | /* ------------------------------------------------- */
268  | void PA_ImportKey(struct ImportKeyObject *iKO) {
269  |   
270  |   char *strArgs[9];
271  |   char Args0[100] = "abracadabra";
272  |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
273  |   int gpg_pid;
274  |   int gpg_in_fd, out_fd, err_fd;
275  |   int status;
276  |   char txt[LINE_LENGTH];
277  |   char *keyStr, *pos;
278  |   const char lockFilename[] = ".PAlock";
279  |   char keyRingLockFile[1000], keyRingPath[1000];
280  |   time_t lockBirthDate;
281  |   FILE *mystdin;
282  | 
283  |   iKO->rc = iKO_GENERALFAILURE;
284  | 
285  |   strcpy(Args0, "--no-tty");
286  |   strcpy(Args1, "--no-secmem-warning");
287  |   strcpy(Args2, "--keyring");
288  |   strcpy(Args3, iKO->keyRing);
289  |   strcpy(Args4, "--import");
290  |   strcpy(Args5, iKO->iFilename);
291  | 
292  |   strArgs[0] = Args0;  
293  |   strArgs[1] = Args1;  
294  |   strArgs[2] = Args2;  
295  |   strArgs[3] = Args3;  
296  |   strArgs[4] = Args4;  
297  |   strArgs[5] = Args5;
298  |   strArgs[6] = (char *)0;
299  | 
300  |   gpg_in_fd = INPUT_FD;
301  |   out_fd = OUTPUT_FD;
302  |   err_fd = ERROR_FD;
303  | 
304  |   /* create lock file filenames for NFS */
305  | 
306  |   strcpy(keyRingLockFile, iKO->keyRing);
307  |   if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
308  |     strcpy(pos + 1, lockFilename);
309  |     strcpy(keyRingPath, keyRingLockFile);
310  |     keyRingPath[pos - keyRingLockFile] = 0;
311  |   } else {
312  |     strcpy(keyRingLockFile, lockFilename);
313  |     strcpy(keyRingPath, "");
314  |   }
315  |   
316  |   lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
317  | 
318  |   if ( ( gpg_pid = spawn_job ("gpg", strArgs,
319  | 			      &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
320  |     printf ("could not spawn gpg");
321  |   }
322  |   
323  |   if (waitpid (gpg_pid, &status, 0) < 0)
324  |     {
325  |       fprintf (stderr, "Error reaping child\t%s\n", ERRSTRING);
326  |       printf ("could not reap gpg process");
327  |     }
328  | 
329  |   nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
330  | 
331  |   if (WIFEXITED(status) == 0)
332  |     {
333  |       fprintf (stderr, "Bad child status: %d\t%s\n", status, ERRSTRING);
334  |       printf ("gpg failure");
335  |     }
336  | 
337  | 
338  |   /* Parsing gpg output */
339  |   /*   while (read(0, txt, 1000) != 0)
340  |        fprintf(stderr, "child read %s\n", txt); */
341  | 
342  |   mystdin = fdopen(0, "r");
343  |   iKO->rc = iKO_GENERALFAILURE;
344  |   while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
345  |     {
346  |           printf ( "GPG output : %s\n", txt );     
347  | 
348  |       if ((keyStr = strstr(txt, "imported")) != NULL) {
349  | 	iKO->rc = iKO_OK;
350  |       }
351  | 
352  |       if ((keyStr = strstr(txt, "CRC error")) != NULL) {
353  | 	iKO->rc = iKO_CRC_ERROR;
354  |       }
355  | 
356  |       if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL) {
357  | 	iKO->rc = iKO_NO_OPENPGP_DATA;
358  |       }
359  | 
360  |       if ((keyStr = strstr(txt, "unchanged")) != NULL) {
361  | 	iKO->rc = iKO_UNCHANGED;
362  |       }
363  | 
364  |       if ((keyStr = strstr(txt, "key")) != NULL) {
365  | 	 keyStr += 4;
366  | 	 sscanf(keyStr, "%8X\n", &iKO->keyID); 
367  |       } 
368  |     }
369  | 
370  |   if (sd1[0] != 0)  close ( sd1[0] ); 
371  | }
372  | 
373  |