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

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