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. VerifySignAndExplodeFile
  8. GetKeyID

   1 /***************************************
   2   $Revision: 1.28 $
   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 GetFingerPrint(struct ImportKeyObject *iKO);
  73 static void VerifySignAndExplodeFile(EPNodePtr ptr);
  74 static void GetKeyID(struct ImportKeyObject *iKO);
  75 
  76 
  77 /**************************************
  78  *
  79  * API functions
  80  *
  81  **************************************/
  82 
  83 
  84 /*++++++++++++++++++++++++++++
  85 
  86 Verify a detached PGP signature.
  87 
  88 struct VerifySignObject *vSO    The signed object structure to be verified.
  89 
  90 ++++++++++++++++++++++++++++*/
  91 
  92 void PA_VerifySignature(struct VerifySignObject *vSO) {
     /* [<][>][^][v][top][bottom][index][help] */
  93   char *strArgs[10];
  94   char Args0[100];
  95   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
  96     Args6[100], Args7[100];
  97   int gpg_pid;
  98   int gpg_in_fd, out_fd, err_fd;
  99   int status;
 100   /* static int nMsgs = 0; */
 101   char txt[LINE_LENGTH];
 102   char *keyStr;
 103   /* int childRC; */
 104 
 105   vSO->type = vSO_Type_Signed;
 106 
 107   strcpy(Args0, "--no-secmem-warning");
 108   strcpy(Args1, "--keyring");
 109   strcpy(Args2, vSO->keyRing);
 110   strcpy(Args3, "-o");
 111   if (!strcmp(vSO->iSigFilename, "")) {
 112     strcpy(Args4, vSO->oStream);
 113     strcpy(Args5, "-d");
 114     strcpy(Args6, vSO->iDocSigFilename);
 115     strArgs[6] = Args6;
 116     strArgs[7] = (char *)0;
 117   } else {
 118     strcpy(Args5, "--verify");
 119     strcpy(Args6, vSO->iSigFilename);
 120     strcpy(Args7, vSO->iDocSigFilename);
 121     
 122     strArgs[6] = Args6;
 123     strArgs[7] = Args7;
 124     strArgs[8] = (char *)0;
 125     strcpy(vSO->oStream, vSO->iDocSigFilename);
 126   }
 127 
 128   strArgs[0] = Args0;
 129   strArgs[1] = Args1;  
 130   strArgs[2] = Args2;  
 131   strArgs[3] = Args3;
 132   strArgs[4] = Args4;
 133   strArgs[5] = Args5;
 134   
 135   gpg_in_fd = INPUT_FD;
 136   out_fd = OUTPUT_FD;
 137   err_fd = ERROR_FD;
 138   if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
 139                               &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
 140     {
 141       ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
 142       exit(1);
 143     }
 144   
 145   if (waitpid (gpg_pid, &status, 0) < 0)
 146     {
 147       ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
 148       exit(1);
 149     }
 150   if (WIFEXITED(status) == 0)
 151     {
 152       ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
 153       exit(1);
 154     } else {
 155       /* Child exited, checking return code */
 156       /* childRC = (status & 0xF00) >> 8;
 157       if (childRC == 1) {
 158         fprintf (stderr, "Fatal: gpg child return code: %d\n", childRC);
 159         printf ("gpg failure\n");
 160         exit(1);
 161         } */
 162     }
 163 
 164 
 165   /* Parsing gpg output */
 166   vSO->isValid = vSO_KO;
 167   while (fgets (txt, LINE_LENGTH - 1, stdin) != NULL)
 168     {
 169       /*        printf ( "GPG output : %s\n", txt );   */
 170       if (strstr(txt, "Good signature") != NULL)
 171         vSO->isValid = vSO_IS_VALID;
 172 
 173       if (strstr(txt, "CRC error") != NULL)
 174         vSO->isValid = vSO_CRC_ERROR;
 175 
 176       if (strstr(txt, "public key not found") != NULL)
 177         vSO->isValid = vSO_NO_PUBLIC_KEY;
 178 
 179       if (strstr(txt, "no valid OpenPGP data found") != NULL)
 180         vSO->isValid = vSO_NO_OPENPGP_DATA;
 181 
 182       if ((keyStr = strstr(txt, "key ID")) != NULL) {
 183         keyStr += 7;
 184         sscanf(keyStr, "%8X\n", &vSO->keyID);
 185       }
 186     }
 187     
 188   if (sd1[0] != 0)  close ( sd1[0] ); 
 189 }
 190 
 191 
 192 
 193 /*++++++++++++++++++++++++++++
 194 
 195 Decrypt a PGP-encrypted file.
 196 
 197 struct ReadCryptedObject *rDO   The object to be decrypted
 198 
 199 
 200 Note:
 201   This functions is not used by PA/EP/MM
 202   It can be useful in the future....  (FP)
 203 
 204 ++++++++++++++++++++++++++++*/
 205 
 206 void PA_Decrypt(struct ReadCryptedObject *rDO) {
     /* [<][>][^][v][top][bottom][index][help] */
 207   
 208   char *strArgs[9];
 209   char clearTextExtension[4] = ".gpg";
 210   char Args0[100];
 211   char Args1[100];
 212   char Args2[100];
 213   char Args3[100];
 214   char Args4[100];
 215   char Args5[100];
 216   char Args6[100];
 217   int gpg_pid;
 218   int gpg_in_fd, out_fd, err_fd;
 219   int status;
 220   char txt[LINE_LENGTH];
 221   int childRC;
 222 
 223   strcpy(Args0, "--no-tty");
 224   strcpy(Args1, "--no-secmem-warning");
 225   strcpy(Args2, "--keyring");
 226   strcpy(Args3, rDO->keyRing);
 227   strcpy(Args4, "--output");
 228   strcpy(Args5, strcat(rDO->iFilename, clearTextExtension));
 229   strcpy(Args6, rDO->iFilename);
 230   
 231   strArgs[0] = Args0;
 232   strArgs[1] = Args1;  
 233   strArgs[2] = Args2;  
 234   strArgs[3] = Args3;  
 235   strArgs[4] = Args4;  
 236   strArgs[5] = Args5;  
 237   strArgs[6] = Args6;  
 238   strArgs[7] = (char *) 0;   
 239 
 240   gpg_in_fd = INPUT_FD;
 241   out_fd = OUTPUT_FD;
 242   err_fd = ERROR_FD;
 243   if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
 244                               &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
 245     {
 246       ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
 247       exit(1);
 248     }
 249   
 250   if (waitpid (gpg_pid, &status, 0) < 0)
 251     {
 252       ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
 253       exit(1);
 254     }
 255   if (WIFEXITED(status) == 0)
 256     {
 257       ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
 258       exit(1);
 259     } else {
 260       /* Child exited, checking return code */
 261       childRC = (status & 0xF00) >> 8;
 262       if (childRC == 1) {
 263         ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
 264         exit(1);
 265       } 
 266     }
 267 
 268 
 269   /* Parsing gpg output */
 270   while (fgets (txt, STRING_LENGTH - 1, stdin) != NULL)
 271     {
 272       
 273     }
 274   
 275   if (sd1[0] != 0)  close ( sd1[0] ); 
 276 }
 277 
 278 
 279 
 280 /*++++++++++++++++++++++++++++
 281 
 282 Import a PGP key.
 283 
 284 struct ImportKeyObject *iKO     The structure where the imported key goes
 285 
 286 ++++++++++++++++++++++++++++*/
 287 
 288 void PA_ImportKey(struct ImportKeyObject *iKO) {
     /* [<][>][^][v][top][bottom][index][help] */
 289   
 290   char *strArgs[9];
 291   char Args0[100];
 292   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
 293   int gpg_pid;
 294   int gpg_in_fd, out_fd, err_fd;
 295   int status;
 296   char txt[LINE_LENGTH];
 297   char *keyStr, *pos;
 298   const char lockFilename[] = ".PAlock";
 299   char keyRingLockFile[1000], keyRingPath[1000];
 300   time_t lockBirthDate;
 301   FILE *mystdin;
 302   int childRC;
 303 
 304   iKO->rc = iKO_GENERALFAILURE;
 305 
 306   strcpy(Args0, "--no-tty");
 307   strcpy(Args1, "--no-secmem-warning");
 308   strcpy(Args2, "--keyring");
 309   strcpy(Args3, iKO->keyRing);
 310   strcpy(Args4, "--import");
 311   strcpy(Args5, iKO->iFilename);
 312 
 313   strArgs[0] = Args0;  
 314   strArgs[1] = Args1;  
 315   strArgs[2] = Args2;  
 316   strArgs[3] = Args3;  
 317   strArgs[4] = Args4;  
 318   strArgs[5] = Args5;
 319   strArgs[6] = (char *)0;
 320 
 321   gpg_in_fd = INPUT_FD;
 322   out_fd = OUTPUT_FD;
 323   err_fd = ERROR_FD;
 324 
 325   /* create lock file filenames for NFS */
 326 
 327   strcpy(keyRingLockFile, iKO->keyRing);
 328   if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
 329     strcpy(pos + 1, lockFilename);
 330     strcpy(keyRingPath, keyRingLockFile);
 331     keyRingPath[pos - keyRingLockFile] = 0;
 332   } else {
 333     strcpy(keyRingLockFile, lockFilename);
 334     strcpy(keyRingPath, "");
 335   }
 336   
 337   lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
 338 
 339   if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
 340                               &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
 341     ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
 342     exit(1);
 343   }
 344   
 345   if (waitpid (gpg_pid, &status, 0) < 0)
 346     {
 347       ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
 348       nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
 349       exit(1);
 350     }
 351 
 352   nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
 353 
 354   if (WIFEXITED(status) == 0)
 355     {
 356       ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
 357     } else {
 358       /* Child exited, checking return code */
 359       childRC = (status & 0xF00) >> 8;
 360       if (childRC == 1) {
 361         ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
 362         exit(1);
 363       }
 364     }
 365 
 366 
 367   /* Parsing gpg output */
 368   /*   while (read(0, txt, 1000) != 0)
 369        fprintf(stderr, "child read %s\n", txt); */
 370 
 371   mystdin = fdopen(0, "r");
 372   iKO->rc = iKO_GENERALFAILURE;
 373   while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
 374     {
 375       /*          printf ( "GPG output : %s\n", txt );      */
 376 
 377       if ((keyStr = strstr(txt, "imported")) != NULL) {
 378         iKO->rc = iKO_OK;
 379       }
 380 
 381       if ((keyStr = strstr(txt, "CRC error")) != NULL) {
 382         iKO->rc = iKO_CRC_ERROR;
 383       }
 384 
 385       if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL) {
 386         iKO->rc = iKO_NO_OPENPGP_DATA;
 387       }
 388 
 389       if (((keyStr = strstr(txt, "unchanged")) != NULL) || 
 390           ((keyStr = strstr(txt, "not changed")) != NULL)) {
 391         iKO->rc = iKO_UNCHANGED;
 392       }
 393 
 394       if ((keyStr = strstr(txt, "key")) != NULL) {
 395          keyStr += 4;
 396          sscanf(keyStr, "%8X\n", &iKO->keyID); 
 397       } 
 398     }
 399 
 400   if (sd1[0] != 0)  close ( sd1[0] ); 
 401 
 402   /* Get the finger print */
 403 
 404   GetFingerPrint(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 Verify the PGP signature and extract the signed part in a file.
 787 
 788 EPNodePtr ptr   The pointer to the EP treenode containing the originating file
 789 
 790 ++++++++++++++++++++++++++++*/
 791 
 792 void VerifySignAndExplodeFile(EPNodePtr ptr) {
     /* [<][>][^][v][top][bottom][index][help] */
 793   char *strArgs[10];
 794   char Args0[100];
 795   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
 796     Args6[100];
 797   int gpg_pid;
 798   int gpg_in_fd, out_fd, err_fd;
 799   int status;
 800   char txt[LINE_LENGTH];
 801   /* char hostname[MAXHOSTNAMELEN]; */
 802   char oFile[FILENAME_LENGTH];
 803   char *keyStr;
 804   /* int childRC; */
 805 
 806   sprintf(oFile, "%s.%d.exp", ptr->file, ptr->nodeID);
 807 
 808   strcpy(Args0, "--no-secmem-warning");
 809   strcpy(Args1, "--keyring");
 810   strcpy(Args2, EP_keyRing);
 811   strcpy(Args3, "-o");
 812   strcpy(Args4, oFile);
 813   strcpy(Args5, "-d");
 814   strcpy(Args6, ptr->file);
 815   strArgs[6] = Args6;
 816   strArgs[7] = (char *)0;
 817   
 818   strArgs[0] = Args0;
 819   strArgs[1] = Args1;  
 820   strArgs[2] = Args2;  
 821   strArgs[3] = Args3;
 822   strArgs[4] = Args4;
 823   strArgs[5] = Args5;
 824   
 825   gpg_in_fd = INPUT_FD;
 826   out_fd = OUTPUT_FD;
 827   err_fd = ERROR_FD;
 828   if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
 829                               &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
 830     {
 831       ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
 832       exit(1);
 833     }
 834   
 835   if (waitpid (gpg_pid, &status, 0) < 0)
 836     {
 837       ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
 838       exit(1);
 839     }
 840   if (WIFEXITED(status) == 0)
 841     {
 842       ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
 843       exit(1);
 844     } else {
 845       /* Child exited, checking return code */
 846       /* childRC = (status & 0xF00) >> 8;
 847       if (childRC == 1) {
 848         fprintf (stderr, "Fatal: gpg child return code: %d\n", childRC);
 849         printf ("gpg failure\n");
 850         exit(1);
 851         } */
 852     }
 853 
 854 
 855   /* Parsing gpg output */
 856   ptr->isValidPGPSignature = vS_KO;
 857   while (fgets (txt, LINE_LENGTH - 1, stdin) != NULL)
 858     {
 859       /*        printf ( "GPG output : %s\n", txt );   */
 860       if (strstr(txt, "Good signature") != NULL)
 861         ptr->isValidPGPSignature = vS_IS_VALID;
 862 
 863       if (strstr(txt, "CRC error") != NULL)
 864         ptr->isValidPGPSignature = vS_CRC_ERROR;
 865 
 866       if (strstr(txt, "public key not found") != NULL)
 867         ptr->isValidPGPSignature = vS_NO_PUBLIC_KEY;
 868 
 869       if (strstr(txt, "no valid OpenPGP data found") != NULL)
 870         ptr->isValidPGPSignature = vS_NO_OPENPGP_DATA;
 871 
 872       if ((keyStr = strstr(txt, "key ID")) != NULL) {
 873         keyStr += 7;
 874         sscanf(keyStr, "%8X\n", &ptr->keyID);
 875       }
 876     }
 877     
 878   unlink(ptr->file);
 879   free(ptr->file);
 880   ptr->file = strdup(oFile);
 881   if (sd1[0] != 0)  close ( sd1[0] ); 
 882 }
 883 
 884 
 885 /*++++++++++++++++++++++++++++
 886 
 887 Get the KeyID of a PGP key.
 888 
 889 struct ImportKeyObject *iKO     The structure containing the key of which we want the KeyID
 890 
 891 ++++++++++++++++++++++++++++*/
 892 
 893 void GetKeyID(struct ImportKeyObject *iKO) {
     /* [<][>][^][v][top][bottom][index][help] */
 894   
 895   char *strArgs[9];
 896   char Args0[100];
 897   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
 898   int gpg_pid;
 899   int gpg_in_fd, out_fd, err_fd;
 900   int status;
 901   char txt[LINE_LENGTH];
 902   char *keyStr, *pos;
 903   const char lockFilename[] = ".PAlock";
 904   char keyRingLockFile[1000], keyRingPath[1000];
 905   time_t lockBirthDate;
 906   FILE *mystdin;
 907   int childRC;
 908 
 909   iKO->rc = iKO_GENERALFAILURE;
 910 
 911   strcpy(Args0, "--no-tty");
 912   strcpy(Args1, "--no-secmem-warning");
 913   strcpy(Args2, "--keyring");
 914   strcpy(Args3, iKO->keyRing);
 915   strcpy(Args4, "--import");
 916   strcpy(Args5, iKO->iFilename);
 917 
 918   strArgs[0] = Args0;  
 919   strArgs[1] = Args1;  
 920   strArgs[2] = Args2;  
 921   strArgs[3] = Args3;  
 922   strArgs[4] = Args4;  
 923   strArgs[5] = Args5;
 924   strArgs[6] = (char *)0;
 925 
 926   gpg_in_fd = INPUT_FD;
 927   out_fd = OUTPUT_FD;
 928   err_fd = ERROR_FD;
 929 
 930   /* create lock file filenames for NFS */
 931 
 932   strcpy(keyRingLockFile, iKO->keyRing);
 933   if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
 934     strcpy(pos + 1, lockFilename);
 935     strcpy(keyRingPath, keyRingLockFile);
 936     keyRingPath[pos - keyRingLockFile] = 0;
 937   } else {
 938     strcpy(keyRingLockFile, lockFilename);
 939     strcpy(keyRingPath, "");
 940   }
 941   
 942   lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
 943 
 944   if ( ( gpg_pid = spawn_job (EP_gpgcmd, strArgs,
 945                               &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
 946     ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
 947     exit(1);
 948   }
 949   
 950   if (waitpid (gpg_pid, &status, 0) < 0)
 951     {
 952       ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
 953       nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
 954       exit(1);
 955     }
 956 
 957   nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
 958 
 959   if (WIFEXITED(status) == 0)
 960     {
 961       ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
 962       exit(1);
 963     } else {
 964       /* Child exited, checking return code */
 965       childRC = (status & 0xF00) >> 8;
 966       if (childRC == 1) {
 967         ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
 968         exit(1);
 969       }
 970     }
 971 
 972 
 973   /* Parsing gpg output */
 974   /*   while (read(0, txt, 1000) != 0)
 975        fprintf(stderr, "child read %s\n", txt); */
 976 
 977   mystdin = fdopen(0, "r");
 978   iKO->rc = iKO_GENERALFAILURE;
 979   while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
 980     {
 981       /*          printf ( "GPG output : %s\n", txt );      */
 982 
 983       if ((keyStr = strstr(txt, "imported")) != NULL) {
 984         iKO->rc = iKO_OK;
 985       }
 986 
 987       if ((keyStr = strstr(txt, "CRC error")) != NULL) {
 988         iKO->rc = iKO_CRC_ERROR;
 989       }
 990 
 991       if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL) {
 992         iKO->rc = iKO_NO_OPENPGP_DATA;
 993       }
 994 
 995       if (((keyStr = strstr(txt, "unchanged")) != NULL) || 
 996           ((keyStr = strstr(txt, "not changed")) != NULL)) {
 997         iKO->rc = iKO_UNCHANGED;
 998       }
 999 
1000       if ((keyStr = strstr(txt, "gpg: key ")) != NULL) {
1001          keyStr += 9;
1002          sscanf(keyStr, "%8X\n", &iKO->keyID); 
1003       } 
1004     }
1005 
1006   if (sd1[0] != 0)  close ( sd1[0] ); 
1007 
1008 }
1009 

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