modules/pa/gpg.c

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

FUNCTIONS

This source file includes following functions.
  1. PA_VerifySignature
  2. PA_Decrypt
  3. PA_ImportKey
  4. PA_RemoveKey
  5. PA_ParseMessage
  6. GetFingerPrint
  7. GetKeyOwner
  8. VerifySignAndExplodeFile
  9. GetKeyID

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

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