## modules/pa/gpg.c

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. GetFingerPrint
2. VerifySignAndExplodeFile
3. PA_VerifySignature
4. PA_Decrypt
5. PA_ImportKey
6. GetKeyID
7. PA_RemoveKey
8. GetLineFromFile3
9. GetLineFromFile2
10. PA_ParseMessage

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

/* [<][>][^][v][top][bottom][index][help] */