Source File pa/gpg.c

    1    | /***************************************
    2    |   $Revision: 1.43 $
    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,2002                    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   |
    51   | extern int  EP_TreeHeight;
    52   | extern int  EP_Node_ID;
    53   | extern int  EP_Debug;
    54   |
    55   |
    56   | /* static int parseMailBlock_nMsg;
    57   |    static int parseRecursionLevel; */
    58   |
    59   | extern int sd1[2];
    60   | extern int spawn_job (char *path, char *argv[],
    61   | 		      int *in_fd, int *out_fd, int *err_fd);
    62   | extern time_t nfslock(char *path, char *namelock, int max_age, int notify);
    63   | extern int nfsunlock(char *path, char *namelock, int max_age, time_t birth);
    64   |
    65   |
    66   | static char* outputPrefix = NULL;
    67   | static char* keyRing = NULL;
    68   | static char* gpgCmd = NULL;
    69   | static char *tmpdir = NULL;
    70   |
    71   | static void VerifySignAndExplodeFile(EPNodePtr ptr);
    72   | static void GetKeyID(struct ImportKeyObject *iKO);
    73   |
    74   |
    75   | /**************************************
    76   |  *
    77   |  * API functions
    78   |  *
    79   |  **************************************/
    80   |
    81   | /*++++++++++++++++++++++++++++
    82   |
    83   | Copies a string with memory allocation care.
    84   |
    85   | char* dest The destination string
    86   | char* orig The origin string
    87   |
    88   |
    89   | ++++++++++++++++++++++++++++*/
    90   |
    91   | void pa_strcpy(char** dest, char* orig) {
    92   |   if (*dest) {
    93   |     free(*dest);
    94   |   }
    95   |
    96   |   *dest = malloc(strlen(orig) + 1);
    97   |   strcpy(*dest, orig);
    98   | }
    99   |
    100  | /*++++++++++++++++++++++++++++
    101  |
    102  | Set the GPG temporary directory.
    103  |
    104  | char* dir The directory
    105  |
    106  |
    107  | This memory allocated is never freed, maybe a PA_end function?
    108  |
    109  | ++++++++++++++++++++++++++++*/
    110  |
    111  | void PA_SetTmpDir(char* dir) {
    112  |   pa_strcpy(&tmpdir, dir);
    113  | }
    114  |
    115  | /*++++++++++++++++++++++++++++
    116  |
    117  | Set the GPG command line.
    118  |
    119  | char* path The path including command name
    120  |
    121  |
    122  | This memory allocated is never freed, maybe a PA_end function?
    123  |
    124  | ++++++++++++++++++++++++++++*/
    125  |
    126  | void PA_SetGPGCmd(char* path) {
    127  |   pa_strcpy(&gpgCmd, path);
    128  | }
    129  |
    130  | /*++++++++++++++++++++++++++++
    131  |
    132  | Set the path to the Keyring.
    133  |
    134  | char* path The path including file name
    135  |
    136  | ++++++++++++++++++++++++++++*/
    137  |
    138  | void PA_SetKeyRing(char* path) {
    139  |   pa_strcpy(&keyRing, path);
    140  | }
    141  |
    142  | /*++++++++++++++++++++++++++++
    143  |
    144  | Set the path to the output file.
    145  |
    146  | char* path The path including file name
    147  |
    148  | ++++++++++++++++++++++++++++*/
    149  |
    150  | void PA_SetOutputPrefix(char* path) {
    151  |   pa_strcpy(&outputPrefix, path);
    152  | }
    153  |
    154  | /*++++++++++++++++++++++++++++
    155  |
    156  | Verify a detached PGP signature.
    157  |
    158  | struct VerifySignObject *vSO	The signed object structure to be verified.
    159  |
    160  | ++++++++++++++++++++++++++++*/
    161  |
    162  | void PA_VerifySignature(struct VerifySignObject *vSO) {
    163  |   char *strArgs[10];
    164  |   char Args0[100];
    165  |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
    166  |     Args6[100], Args7[100];
    167  |   int gpg_pid;
    168  |   int gpg_in_fd, out_fd, err_fd;
    169  |   int status;
    170  |   /* static int nMsgs = 0; */
    171  |   char txt[LINE_LENGTH];
    172  |   char *keyStr;
    173  |   /* int childRC; */
    174  |
    175  |   int fIn,fOut;
    176  |   char tmpFileName[100],lfcrStr[10],strIn[10];
    177  |   char prevChar;
    178  |   FILE *mystdin;
    179  |
    180  |   vSO->type = vSO_Type_Signed;
    181  |
    182  |   strcpy(Args0, "--no-secmem-warning");
    183  |   strcpy(Args1, "--keyring");
    184  |   strcpy(Args2, keyRing);
    185  |   strcpy(Args3, "-o");
    186  |   if (!strcmp(vSO->iSigFilename, "")) {
    187  |     strcpy(Args4, vSO->oStream);
    188  |     strcpy(Args5, "-d");
    189  |     strcpy(Args6, vSO->iDocSigFilename);
    190  |     strArgs[6] = Args6;
    191  |     strArgs[7] = (char *)0;
    192  |   } else {
    193  |     /* change <cr> to <lf>+<cr> to be related-rfc compliant */
    194  |     fIn=open(vSO->iDocSigFilename,O_RDONLY);
    195  |     if (fIn==-1) {
    196  |       ER_perror(FAC_PA, PA_CANTREAD, "can't open %s for reading", vSO->iDocSigFilename);
    197  |       exit(1);
    198  |     }
    199  |     strcpy(tmpFileName,tmpdir);
    200  |     strcat(tmpFileName,"/patmpXXXXXXX");
    201  |     fOut=mkstemp(tmpFileName);
    202  |     if (fOut==-1) {
    203  |       ER_perror(FAC_PA, PA_NOTEMP, "%s", tmpFileName);
    204  |       exit(1);
    205  |     }
    206  |     prevChar=0;
    207  |     sprintf(lfcrStr,"%c%c%c",13,10,0);
    208  |     while(read(fIn,strIn,1)>0)
    209  |     {
    210  |       if ((strIn[0]==10)&&(prevChar!=13)) {
    211  | 	write(fOut,lfcrStr,2);
    212  |       } else {
    213  | 	write(fOut,strIn,1);
    214  |       }
    215  |       prevChar=strIn[0];
    216  |     }
    217  |     close(fOut);
    218  |     close(fIn);
    219  |     /* end change <cr> to <lf>+<cr> to be related-rfc compliant */
    220  |
    221  |     strcpy(Args5, "--verify");
    222  |     strcpy(Args6, vSO->iSigFilename);
    223  |     strcpy(Args7, tmpFileName);
    224  |
    225  |     strArgs[6] = Args6;
    226  |     strArgs[7] = Args7;
    227  |     strArgs[8] = (char *)0;
    228  |     strcpy(vSO->oStream, vSO->iDocSigFilename);
    229  |   }
    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  |
    238  |   gpg_in_fd = INPUT_FD;
    239  |   out_fd = OUTPUT_FD;
    240  |   err_fd = ERROR_FD;
    241  |   if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
    242  | 			      &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
    243  |     {
    244  |       ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
    245  |       exit(1);
    246  |     }
    247  |
    248  |   if (waitpid (gpg_pid, &status, 0) < 0)
    249  |     {
    250  |       ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
    251  |       exit(1);
    252  |     }
    253  |   unlink(tmpFileName);
    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  | 	fprintf (stderr, "Fatal: gpg child return code: %d\n", childRC);
    263  | 	printf ("gpg failure\n");
    264  | 	exit(1);
    265  | 	} */
    266  |     }
    267  |
    268  |
    269  |   /* Parsing gpg output */
    270  |   mystdin = fdopen(0, "r");
    271  |   vSO->isValid = vSO_KO;
    272  |   while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
    273  |     {
    274  |       /* 	printf ( "GPG output : %s\n", txt );   */
    275  |       if (strstr(txt, "Good signature") != NULL)
    276  | 	vSO->isValid = vSO_IS_VALID;
    277  |
    278  |       if (strstr(txt, "CRC error") != NULL)
    279  | 	vSO->isValid = vSO_CRC_ERROR;
    280  |
    281  |       if (strstr(txt, "public key not found") != NULL)
    282  | 	vSO->isValid = vSO_NO_PUBLIC_KEY;
    283  |
    284  |       if (strstr(txt, "no valid OpenPGP data found") != NULL)
    285  | 	vSO->isValid = vSO_NO_OPENPGP_DATA;
    286  |
    287  |       if ((keyStr = strstr(txt, "key ID")) != NULL) {
    288  | 	keyStr += 7;
    289  | 	sscanf(keyStr, "%8X\n", &vSO->keyID);
    290  |       }
    291  |     }
    292  |
    293  |   if (sd1[0] != 0)  close ( sd1[0] );
    294  | }
    295  |
    296  |
    297  |
    298  | /*++++++++++++++++++++++++++++
    299  |
    300  | Decrypt a PGP-encrypted file.
    301  |
    302  | struct ReadCryptedObject *rDO	The object to be decrypted
    303  |
    304  |
    305  | Note:
    306  |   This functions is not used by PA/EP/MM
    307  |   It can be useful in the future....  (FP)
    308  |
    309  | ++++++++++++++++++++++++++++*/
    310  |
    311  | void PA_Decrypt(struct ReadCryptedObject *rDO) {
    312  |
    313  |   char *strArgs[9];
    314  |   char clearTextExtension[4] = ".gpg";
    315  |   char Args0[100];
    316  |   char Args1[100];
    317  |   char Args2[100];
    318  |   char Args3[100];
    319  |   char Args4[100];
    320  |   char Args5[100];
    321  |   char Args6[100];
    322  |   int gpg_pid;
    323  |   int gpg_in_fd, out_fd, err_fd;
    324  |   int status;
    325  |   char txt[LINE_LENGTH];
    326  |   int childRC;
    327  |   FILE *mystdin;
    328  |
    329  |   strcpy(Args0, "--no-tty");
    330  |   strcpy(Args1, "--no-secmem-warning");
    331  |   strcpy(Args2, "--keyring");
    332  |   strcpy(Args3, rDO->keyRing);
    333  |   strcpy(Args4, "--output");
    334  |   strcpy(Args5, strcat(rDO->iFilename, clearTextExtension));
    335  |   strcpy(Args6, rDO->iFilename);
    336  |
    337  |   strArgs[0] = Args0;
    338  |   strArgs[1] = Args1;
    339  |   strArgs[2] = Args2;
    340  |   strArgs[3] = Args3;
    341  |   strArgs[4] = Args4;
    342  |   strArgs[5] = Args5;
    343  |   strArgs[6] = Args6;
    344  |   strArgs[7] = (char *) 0;
    345  |
    346  |   gpg_in_fd = INPUT_FD;
    347  |   out_fd = OUTPUT_FD;
    348  |   err_fd = ERROR_FD;
    349  |   if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
    350  | 			      &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
    351  |     {
    352  |       ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
    353  |       exit(1);
    354  |     }
    355  |
    356  |   if (waitpid (gpg_pid, &status, 0) < 0)
    357  |     {
    358  |       ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
    359  |       exit(1);
    360  |     }
    361  |   if (WIFEXITED(status) == 0)
    362  |     {
    363  |       ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
    364  |       exit(1);
    365  |     } else {
    366  |       /* Child exited, checking return code */
    367  |       childRC = (status & 0xF00) >> 8;
    368  |       if (childRC == 1) {
    369  | 	ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
    370  | 	exit(1);
    371  |       }
    372  |     }
    373  |
    374  |
    375  |   /* Parsing gpg output */
    376  |   mystdin = fdopen(0, "r");
    377  |   while (fgets (txt, STRING_LENGTH - 1, mystdin) != NULL)
    378  |     {
    379  |
    380  |     }
    381  |
    382  |   if (sd1[0] != 0)  close ( sd1[0] );
    383  | }
    384  |
    385  |
    386  |
    387  | /*++++++++++++++++++++++++++++
    388  |
    389  | Import a PGP key.
    390  |
    391  | struct ImportKeyObject *iKO	The structure where the imported key goes
    392  |
    393  | ++++++++++++++++++++++++++++*/
    394  |
    395  | void PA_ImportKey(struct ImportKeyObject *iKO) {
    396  |
    397  |   char *strArgs[9];
    398  |   char Args0[100];
    399  |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
    400  |   int gpg_pid;
    401  |   int gpg_in_fd, out_fd, err_fd;
    402  |   int status;
    403  |   char txt[LINE_LENGTH];
    404  |   char *keyStr, *pos;
    405  |   const char lockFilename[] = ".PAlock";
    406  |   char keyRingLockFile[1000], keyRingPath[1000];
    407  |   time_t lockBirthDate;
    408  |   FILE *mystdin;
    409  |   int childRC;
    410  |   int key_count;
    411  |   GList *key_list = NULL;
    412  |   GList *next = NULL;
    413  |   struct ImportKeyObject iKO_toBeRemoved;
    414  |
    415  |   iKO->rc = iKO_GENERALFAILURE;
    416  |
    417  |   strcpy(Args0, "--no-tty");
    418  |   strcpy(Args1, "--no-secmem-warning");
    419  |   strcpy(Args2, "--keyring");
    420  |   strcpy(Args3, iKO->keyRing);
    421  |   strcpy(Args4, "--import");
    422  |   strcpy(Args5, iKO->iFilename);
    423  |
    424  |   strArgs[0] = Args0;
    425  |   strArgs[1] = Args1;
    426  |   strArgs[2] = Args2;
    427  |   strArgs[3] = Args3;
    428  |   strArgs[4] = Args4;
    429  |   strArgs[5] = Args5;
    430  |   strArgs[6] = (char *)0;
    431  |
    432  |   gpg_in_fd = INPUT_FD;
    433  |   out_fd = OUTPUT_FD;
    434  |   err_fd = ERROR_FD;
    435  |
    436  |   /* create lock file filenames for NFS */
    437  |
    438  |   strcpy(keyRingLockFile, iKO->keyRing);
    439  |   if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
    440  |     strcpy(pos + 1, lockFilename);
    441  |     strcpy(keyRingPath, keyRingLockFile);
    442  |     keyRingPath[pos - keyRingLockFile] = 0;
    443  |   } else {
    444  |     strcpy(keyRingLockFile, lockFilename);
    445  |     strcpy(keyRingPath, "");
    446  |   }
    447  |
    448  |   lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
    449  |
    450  |   if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
    451  | 			      &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
    452  |     ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
    453  |     exit(1);
    454  |   }
    455  |
    456  |   if (waitpid (gpg_pid, &status, 0) < 0)
    457  |     {
    458  |       ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
    459  |       nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
    460  |       exit(1);
    461  |     }
    462  |
    463  |   nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
    464  |
    465  |   if (WIFEXITED(status) == 0)
    466  |     {
    467  |       ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
    468  |     }
    469  |     else
    470  |     {
    471  |       /* Child exited, checking return code */
    472  |       childRC = (status & 0xF00) >> 8;
    473  |       if (tracing)
    474  |         printf("TRACING: PA_ImportKey child return code [%d]\n", childRC);
    475  |       if (childRC == 1)
    476  |       {
    477  |         ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
    478  |         /*  exit(1);  */
    479  |       }
    480  |     }
    481  |
    482  |
    483  |   /* Parsing gpg output */
    484  |   /*   while (read(0, txt, 1000) != 0)
    485  |        fprintf(stderr, "child read %s\n", txt); */
    486  |
    487  |   mystdin = fdopen(0, "r");
    488  |   iKO->rc = iKO_GENERALFAILURE;
    489  |   key_count = 0;
    490  |   while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
    491  |   {
    492  |     /* printf ( "GPG output : %s\n", txt );      */
    493  |
    494  |     if ((keyStr = strstr(txt, "imported")) != NULL)
    495  |     {
    496  | 	  iKO->rc = iKO_OK;
    497  |     }
    498  |
    499  |     if ((keyStr = strstr(txt, "CRC error")) != NULL)
    500  |     {
    501  | 	  iKO->rc = iKO_CRC_ERROR;
    502  |     }
    503  |
    504  |     if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL)
    505  |     {
    506  | 	  iKO->rc = iKO_NO_OPENPGP_DATA;
    507  |     }
    508  |
    509  |     if ((keyStr = strstr(txt, "invalid armor header")) != NULL)
    510  |     {
    511  | 	  iKO->rc = iKO_INVALID_ARMOR_HEADER;
    512  |     }
    513  |
    514  |     if (((keyStr = strstr(txt, "unchanged")) != NULL) ||
    515  | 	  ((keyStr = strstr(txt, "not changed")) != NULL))
    516  |     {
    517  | 	  iKO->rc = iKO_UNCHANGED;
    518  |     }
    519  |
    520  |     if ((keyStr = strstr(txt, "key")) != NULL)
    521  |     {
    522  | 	  keyStr += 4;
    523  | 	  sscanf(keyStr, "%8X\n", &iKO->keyID);
    524  |       key_count++;
    525  |       /* and put the key ID into the keys list (if it was new to the keyring)*/
    526  |       if(strstr(txt, "imported") != NULL)
    527  |       {
    528  |         key_list = g_list_append(key_list, GINT_TO_POINTER(iKO->keyID));
    529  |       }
    530  |     }
    531  |   }
    532  |
    533  |   if (sd1[0] != 0)  close ( sd1[0] );
    534  |
    535  |   if(key_count > 1){/* if there were more than one keys imported */
    536  |     iKO->rc = iKO_MULTIPLE_KEYS; /* this is an error */
    537  |     /* now, roll-back, remove the added keys from key-ring */
    538  |     for( next = key_list; next != NULL; next = g_list_next(next) ){
    539  |       strcpy(iKO_toBeRemoved.keyRing,
    540  |           iKO->keyRing);
    541  |       iKO_toBeRemoved.keyID = (u32)(next->data);
    542  |       PA_RemoveKey_withKeyID(&iKO_toBeRemoved);
    543  |     }
    544  |
    545  |   }else{
    546  |     /* Get the finger print */
    547  |     GetFingerPrint(iKO);
    548  |     GetKeyOwner(iKO);
    549  |   }
    550  | }
    551  |
    552  |
    553  |
    554  | /*++++++++++++++++++++++++++++
    555  |
    556  | Remove a PGP key.
    557  |
    558  | struct ImportKeyObject *iKO	The structure containing the key to be removed
    559  |
    560  | ++++++++++++++++++++++++++++*/
    561  |
    562  | void PA_RemoveKey(struct ImportKeyObject *iKO) {
    563  |
    564  |   char *strArgs[9];
    565  |   char Args0[100]= "gpg";
    566  |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100], Args6[100], Args7[100];
    567  |   int gpg_pid;
    568  |   int gpg_in_fd, out_fd, err_fd;
    569  |   int status;
    570  |   char txt[LINE_LENGTH];
    571  |   char *keyStr, *pos;
    572  |   const char lockFilename[] = ".PAlock";
    573  |   char keyRingLockFile[1000], keyRingPath[1000];
    574  |   time_t lockBirthDate;
    575  |   FILE *mystdin;
    576  |   int childRC;
    577  |
    578  |   iKO->rc = iKO_GENERALFAILURE;
    579  |
    580  |   GetKeyID(iKO);   /* getting key-id */
    581  |
    582  |   /*   printf("Key id = %08lX\n", iKO->keyID); */
    583  |
    584  |   if ((iKO->rc == iKO_OK) || (iKO->rc == iKO_UNCHANGED)) {
    585  |     strcpy(Args1, "--batch");
    586  |     strcpy(Args2, "--yes");
    587  |     strcpy(Args3, "--no-secmem-warning");
    588  |     strcpy(Args4, "--keyring");
    589  |     strcpy(Args5, iKO->keyRing);
    590  |     strcpy(Args6, "--delete-key");
    591  |     sprintf(Args7, "%08X", iKO->keyID);
    592  |
    593  |     strArgs[0] = Args0;
    594  |     strArgs[1] = Args1;
    595  |     strArgs[2] = Args2;
    596  |     strArgs[3] = Args3;
    597  |     strArgs[4] = Args4;
    598  |     strArgs[5] = Args5;
    599  |     strArgs[6] = Args6;
    600  |     strArgs[7] = Args7;
    601  |     strArgs[8] = (char *)0;
    602  |
    603  |
    604  |     gpg_in_fd = INPUT_FD;
    605  |     out_fd = OUTPUT_FD;
    606  |     err_fd = ERROR_FD;
    607  |
    608  |   /* create lock file filenames for NFS */
    609  |
    610  |     strcpy(keyRingLockFile, iKO->keyRing);
    611  |     if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
    612  |       strcpy(pos + 1, lockFilename);
    613  |       strcpy(keyRingPath, keyRingLockFile);
    614  |       keyRingPath[pos - keyRingLockFile] = 0;
    615  |     } else {
    616  |       strcpy(keyRingLockFile, lockFilename);
    617  |       strcpy(keyRingPath, "");
    618  |     }
    619  |
    620  |     lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
    621  |
    622  |     if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
    623  | 				&gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
    624  |       ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
    625  |       exit(1);
    626  |     }
    627  |
    628  |     /*    printf("Child pid = %d\n", gpg_pid); */
    629  |
    630  |     if (waitpid (gpg_pid, &status, 0) < 0)
    631  |       {
    632  | 	ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
    633  | 	exit(1);
    634  |       }
    635  |
    636  |     nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
    637  |
    638  |     if (WIFEXITED(status) == 0)
    639  |     {
    640  | 	ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
    641  | 	exit(1);
    642  |     }
    643  |     else
    644  |     {
    645  | 	  /* Child exited, checking return code */
    646  | 	  childRC = (status & 0xF00) >> 8;
    647  | 	  if (childRC == 1)
    648  |       {
    649  | 	    ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
    650  | 	  }
    651  |     }
    652  |
    653  |
    654  |     mystdin = fdopen(0, "r");
    655  |     iKO->rc = iKO_OK;
    656  |     while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
    657  |     {
    658  | 	  /* printf ( "GPG output : %s\n", txt );        */
    659  |
    660  | 	  if ((keyStr = strstr(txt, "delete key failed")) != NULL)
    661  |       {
    662  | 	    iKO->rc = iKO_GENERALFAILURE;
    663  | 	  }
    664  | 	  if ((keyStr = strstr(txt, "there is a secret key for this public key")) != NULL)
    665  |       {
    666  | 	    iKO->rc = iKO_SECRET_KEY_PRESENT;
    667  | 	  }
    668  |     }
    669  |
    670  |     if (sd1[0] != 0)  close ( sd1[0] );
    671  |   }
    672  | }
    673  |
    674  | /*++++++++++++++++++++++++++++
    675  |
    676  | Remove a PGP key, using its KeyID (otherwise it's the same as PA_RemoveKey
    677  |
    678  | struct ImportKeyObject *iKO	The structure containing the key to be removed
    679  |
    680  | ++++++++++++++++++++++++++++*/
    681  |
    682  | void PA_RemoveKey_withKeyID(struct ImportKeyObject *iKO) {
    683  |
    684  |   char *strArgs[9];
    685  |   char Args0[100]= "gpg";
    686  |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100], Args6[100], Args7[100];
    687  |   int gpg_pid;
    688  |   int gpg_in_fd, out_fd, err_fd;
    689  |   int status;
    690  |   char txt[LINE_LENGTH];
    691  |   char *keyStr, *pos;
    692  |   const char lockFilename[] = ".PAlock";
    693  |   char keyRingLockFile[1000], keyRingPath[1000];
    694  |   time_t lockBirthDate;
    695  |   FILE *mystdin;
    696  |   int childRC;
    697  |
    698  |   iKO->rc = iKO_GENERALFAILURE;
    699  |
    700  |
    701  |     strcpy(Args1, "--batch");
    702  |     strcpy(Args2, "--yes");
    703  |     strcpy(Args3, "--no-secmem-warning");
    704  |     strcpy(Args4, "--keyring");
    705  |     strcpy(Args5, iKO->keyRing);
    706  |     strcpy(Args6, "--delete-key");
    707  |     sprintf(Args7, "%08X", iKO->keyID);
    708  |
    709  |     strArgs[0] = Args0;
    710  |     strArgs[1] = Args1;
    711  |     strArgs[2] = Args2;
    712  |     strArgs[3] = Args3;
    713  |     strArgs[4] = Args4;
    714  |     strArgs[5] = Args5;
    715  |     strArgs[6] = Args6;
    716  |     strArgs[7] = Args7;
    717  |     strArgs[8] = (char *)0;
    718  |
    719  |
    720  |     gpg_in_fd = INPUT_FD;
    721  |     out_fd = OUTPUT_FD;
    722  |     err_fd = ERROR_FD;
    723  |
    724  |   /* create lock file filenames for NFS */
    725  |
    726  |     strcpy(keyRingLockFile, iKO->keyRing);
    727  |     if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
    728  |       strcpy(pos + 1, lockFilename);
    729  |       strcpy(keyRingPath, keyRingLockFile);
    730  |       keyRingPath[pos - keyRingLockFile] = 0;
    731  |     } else {
    732  |       strcpy(keyRingLockFile, lockFilename);
    733  |       strcpy(keyRingPath, "");
    734  |     }
    735  |
    736  |     lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
    737  |
    738  |
    739  |     if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
    740  | 				&gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
    741  |       ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
    742  |       exit(1);
    743  |     }
    744  |
    745  |     /*    printf("Child pid = %d\n", gpg_pid); */
    746  |
    747  |     if (waitpid (gpg_pid, &status, 0) < 0)
    748  |       {
    749  | 	ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
    750  | 	exit(1);
    751  |       }
    752  |
    753  |     nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
    754  |
    755  |     if (WIFEXITED(status) == 0)
    756  |       {
    757  | 	ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
    758  | 	exit(1);
    759  |       }  else {
    760  | 	/* Child exited, checking return code */
    761  | 	childRC = (status & 0xF00) >> 8;
    762  | 	if (childRC == 1) {
    763  | 	  ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
    764  | 	}
    765  |       }
    766  |
    767  |
    768  |     mystdin = fdopen(0, "r");
    769  |     iKO->rc = iKO_OK;
    770  |     while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
    771  |       {
    772  | 	/* printf ( "GPG output : %s\n", txt );        */
    773  |
    774  | 	if ((keyStr = strstr(txt, "delete key failed")) != NULL) {
    775  | 	  iKO->rc = iKO_GENERALFAILURE;
    776  | 	}
    777  | 	if ((keyStr = strstr(txt, "there is a secret key for this public key")) != NULL) {
    778  | 	  iKO->rc = iKO_SECRET_KEY_PRESENT;
    779  | 	}
    780  |
    781  |       }
    782  |
    783  |     if (sd1[0] != 0)  close ( sd1[0] );
    784  |
    785  | }
    786  |
    787  |
    788  |
    789  |
    790  | /*++++++++++++++++++++++++++++
    791  |
    792  | Parse a file and look for PGP-signed elements inside.
    793  |
    794  | EPNodePtr ptr	The pointer to the EP treenode containing the file to be parsed.
    795  |
    796  | ++++++++++++++++++++++++++++*/
    797  |
    798  | EPNodePtr PA_ParseMessage(EPNodePtr ptr) {
    799  |
    800  |   /* Assumptions:
    801  |      - ptr is describing a text file, not MIME
    802  |      - input file is broken down to pieces, plain text or PGP blocks
    803  |      - if input file is doesn't have any PGP block, this is a leaf
    804  |      - otherwise send each block to the proper handler.
    805  |   */
    806  |
    807  |   FILE *fin, *fout;
    808  |   char txt[MAX_LINE_BUF], *strptr;
    809  |   /* char blockFilename[LINE_LENGTH]; */
    810  |   const char PGP_prefix_msg[] =       "-----BEGIN PGP MESSAGE";
    811  |   const char PGP_suffix_msg[] =       "-----END PGP MESSAGE";
    812  |   const char PGP_prefix_signed[] =    "-----BEGIN PGP SIGNED MESSAGE";
    813  |   const char PGP_suffix_signature[] = "-----END PGP SIGNATURE";
    814  |   int found_prefix = 0, found_suffix = 0;
    815  |   EPNodePtr p = ptr, prev = ptr;
    816  |   int end_of_fin = 0, text_block = 1;
    817  |
    818  |
    819  |   ER_dbg_va (FAC_PA, ASP_PA_GEN, "Entering PA_ParseMessage...");
    820  |
    821  |
    822  |   if ((fin = fopen(ptr->file, "r")) != NULL) {
    823  |
    824  |     do {
    825  |       /* this is needed because a text block parser ends when it finds
    826  | 	 a PGP prefix, so we already have a txt buffer.   */
    827  |
    828  |       if (!text_block || (prev == ptr)) {
    829  | 	strptr = fgets(txt, MAX_LINE_BUF, fin);
    830  | 	if (strptr == NULL ) end_of_fin = 1;
    831  |       }
    832  |
    833  |       if (!end_of_fin && (found_prefix || (strstr(txt, PGP_prefix_msg) != NULL) ||
    834  | 			  (strstr(txt, PGP_prefix_signed) != NULL))) {
    835  | 	/* PGP block */
    836  | 	found_prefix = 1;
    837  | 	text_block = 0;
    838  |
    839  | 	p = EP_DefineNewNode(++EP_Node_ID, vS_TO_BE_PGPVERIFIED,
    840  | 			     ptr->MIMEContentType, ptr->strMIMEContentType, 0);
    841  |
    842  | 	if (prev != ptr)
    843  | 	  prev->next = p;
    844  | 	else
    845  | 	  ptr->inner = p;
    846  |
    847  | 	if ((fout = fopen(p->file, "w")) != NULL ) {
    848  | 	  fputs(txt, fout);
    849  | 	  /* To be replaced by fwrite(), more efficient */
    850  | 	  while ((found_prefix != found_suffix) &&
    851  | 		 ((strptr = fgets(txt, MAX_LINE_BUF, fin)) != NULL)) {
    852  | 	    if (strstr(txt, PGP_prefix_msg) != NULL) found_prefix++;
    853  | 	    if (strstr(txt, PGP_prefix_signed) != NULL) found_prefix++;
    854  | 	    if (strstr(txt, PGP_suffix_msg) != NULL) found_suffix++;
    855  | 	    if (strstr(txt, PGP_suffix_signature) != NULL) found_suffix++;
    856  | 	    fputs(txt, fout);
    857  | 	  }
    858  | 	  if (strptr == NULL ) end_of_fin = 1;
    859  |
    860  | 	  fclose(fout);
    861  |
    862  | 	  if (found_prefix == found_suffix) {
    863  | 	    found_prefix = found_suffix = 0;
    864  |
    865  | 	    VerifySignAndExplodeFile(p);
    866  |
    867  | 	    /* Called form EP_ParseMail or EP_PArseText ? */
    868  |
    869  | 	    if (strstr(outputPrefix, "EPMtmp") != NULL)
    870  | 	      {
    871  | 		ER_dbg_va (FAC_PA, ASP_PA_GEN, "Found prefix and suffix; calling EP_MIMEParse...");
    872  | 		EP_MIMEParse(p);
    873  | 	      }
    874  | 	    else {
    875  |               PA_ParseMessage(p);
    876  |             }
    877  | 	    prev = p;
    878  | 	  } else {
    879  | 	    /* Wrong PGP delimiters order. */
    880  | 	    p->isValidPGPSignature = vS_UNMATCHED_PGP_DELIMITERS;
    881  | 	  }
    882  | 	} else {
    883  | 	  p->isValidPGPSignature = vS_UNABLE_TO_WRITE_FILE;
    884  | 	  return p;
    885  | 	}
    886  |
    887  |       } else {
    888  | 	/* Clear text block */
    889  |
    890  | 	text_block = 1;
    891  |
    892  | 	if (strptr == NULL) end_of_fin = 1;
    893  | 	else {
    894  | 	  p = EP_DefineNewNode(++EP_Node_ID, vS_IS_NOT_PGP,
    895  | 			       ptr->MIMEContentType,
    896  | 			       ptr->strMIMEContentType, 0);
    897  |
    898  | 	  if (prev != ptr)
    899  | 	    prev->next = p;
    900  | 	  else
    901  | 	    ptr->inner = p;
    902  |
    903  | 	  if ((fout = fopen(p->file, "w")) != NULL ) {
    904  | 	    fputs(txt, fout);
    905  | 	    /* To be replaced by fwrite(), more efficient */
    906  | 	    while ((!found_prefix &&
    907  | 		    (strptr = fgets(txt, MAX_LINE_BUF, fin)) != NULL)) {
    908  | 	      if ((strstr(txt, PGP_prefix_msg) != NULL) ||
    909  | 		  (strstr(txt, PGP_prefix_signed) != NULL)) found_prefix++;
    910  | 	      else
    911  | 		fputs(txt, fout);
    912  | 	    }
    913  | 	    if (strptr == NULL ) end_of_fin = 1;
    914  |
    915  | 	    fclose(fout);
    916  |
    917  | 	    /* Check if the blockfile is finished and this is the first
    918  | 	       segment. If so this is a text leaf */
    919  | 	    if (found_prefix || (prev != p)) {
    920  | 	      if (prev->MIMEContentType == -1)
    921  | 		{
    922  | 		  if (strstr(outputPrefix, "EPMtmp") != NULL)
    923  | 		    {
    924  | 		      ER_dbg_va (FAC_PA, ASP_PA_GEN, "PA_ParseMessage: sending to EP_MIMEParse");
    925  | 		      EP_MIMEParse(p);
    926  | 		    }
    927  | 		  else {
    928  | 		    PA_ParseMessage(p);
    929  |                   }
    930  | 		}
    931  |
    932  | 	      prev = p;
    933  | 	    }
    934  |
    935  | 	  } else {
    936  | 	    p->isValidPGPSignature = vS_UNABLE_TO_WRITE_FILE;
    937  | 	    return p;
    938  | 	  }
    939  | 	}
    940  |       }
    941  |     } while (!end_of_fin);
    942  |   } else {
    943  |     p->isValidPGPSignature = vS_NO_IN_FILES;
    944  |   }
    945  |
    946  |   return ptr;
    947  | }
    948  |
    949  |
    950  | /**************************************
    951  |  *
    952  |  * Internal functions
    953  |  *
    954  |  **************************************/
    955  |
    956  |
    957  |
    958  | /*++++++++++++++++++++++++++++
    959  |
    960  | Get the fingerprint of a PGP key.
    961  |
    962  | ImportKeyObject *iKO	The imported key object
    963  |
    964  | ++++++++++++++++++++++++++++*/
    965  |
    966  | void GetFingerPrint(struct ImportKeyObject *iKO) {
    967  |
    968  |   char *strArgs[9];
    969  |   char Args0[100] ;
    970  |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
    971  |   int gpg_pid;
    972  |   int gpg_in_fd, out_fd, err_fd;
    973  |   int status;
    974  |   char txt[LINE_LENGTH];
    975  |   char *keyStr;
    976  |   FILE *mystdin;
    977  |   int childRC;
    978  |
    979  |   strcpy(Args0, "--no-tty");
    980  |   strcpy(Args1, "--no-secmem-warning");
    981  |   strcpy(Args2, "--keyring");
    982  |   strcpy(Args3, iKO->keyRing);
    983  |   strcpy(Args4, "--fingerprint");
    984  |   sprintf(Args5, "%08X", iKO->keyID);
    985  |
    986  |   strArgs[0] = Args0;
    987  |   strArgs[1] = Args1;
    988  |   strArgs[2] = Args2;
    989  |   strArgs[3] = Args3;
    990  |   strArgs[4] = Args4;
    991  |   strArgs[5] = Args5;
    992  |   strArgs[6] = (char *)0;
    993  |
    994  |   gpg_in_fd = INPUT_FD;
    995  |   out_fd = OUTPUT_FD;
    996  |   err_fd = ERROR_FD;
    997  |
    998  |   /* create lock file filenames for NFS */
    999  |
    1000 |   if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
    1001 | 			      &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
    1002 |     ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
    1003 |     exit(1);
    1004 |   }
    1005 |
    1006 |   if (waitpid (gpg_pid, &status, 0) < 0)
    1007 |     {
    1008 |       ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
    1009 |       exit(1);
    1010 |     }
    1011 |
    1012 |   if (WIFEXITED(status) == 0)
    1013 |     {
    1014 |       ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
    1015 |       exit(1);
    1016 |     } else {
    1017 |       /* Child exited, checking return code */
    1018 |       childRC = (status & 0xF00) >> 8;
    1019 |       if (childRC == 1) {
    1020 | 	ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
    1021 | 	exit(1);
    1022 |       }
    1023 |     }
    1024 |
    1025 |
    1026 |   mystdin = fdopen(0, "r");
    1027 |   while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
    1028 |     {
    1029 |       /* printf ( "GPG output : %s\n", txt );      */
    1030 |
    1031 |       if ((keyStr = strstr(txt, "Key fingerprint =")) != NULL) {
    1032 | 	strcpy(iKO->fingerPrint, keyStr + 18);
    1033 | 	iKO->fingerPrint[strlen(iKO->fingerPrint)-1] = 0;
    1034 |       }
    1035 |
    1036 |       if ((keyStr = strstr(txt, "key")) != NULL) {
    1037 | 	 keyStr += 4;
    1038 | 	 sscanf(keyStr, "%8X\n", &iKO->keyID);
    1039 |       }
    1040 |     }
    1041 |
    1042 |   if (sd1[0] != 0)  close ( sd1[0] );
    1043 | }
    1044 |
    1045 |
    1046 |
    1047 | /*++++++++++++++++++++++++++++
    1048 |
    1049 | Get the owner of a PGP key.
    1050 |
    1051 | ImportKeyObject *iKO	The imported key object
    1052 |
    1053 | ++++++++++++++++++++++++++++*/
    1054 |
    1055 | void GetKeyOwner(struct ImportKeyObject *iKO) {
    1056 |
    1057 |   char *strArgs[9];
    1058 |   char Args0[100] ;
    1059 |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
    1060 |   int gpg_pid;
    1061 |   int gpg_in_fd, out_fd, err_fd;
    1062 |   int status;
    1063 |   char txt[LINE_LENGTH];
    1064 |   char *keyStr;
    1065 |   FILE *mystdin;
    1066 |   int childRC;
    1067 |
    1068 |   strcpy(Args0, "--no-tty");
    1069 |   strcpy(Args1, "--no-secmem-warning");
    1070 |   strcpy(Args2, "--keyring");
    1071 |   strcpy(Args3, iKO->keyRing);
    1072 |   strcpy(Args4, "--fingerprint");
    1073 |   sprintf(Args5, "%08X", iKO->keyID);
    1074 |
    1075 |   strArgs[0] = Args0;
    1076 |   strArgs[1] = Args1;
    1077 |   strArgs[2] = Args2;
    1078 |   strArgs[3] = Args3;
    1079 |   strArgs[4] = Args4;
    1080 |   strArgs[5] = Args5;
    1081 |   strArgs[6] = (char *)0;
    1082 |
    1083 |   gpg_in_fd = INPUT_FD;
    1084 |   out_fd = OUTPUT_FD;
    1085 |   err_fd = ERROR_FD;
    1086 |
    1087 |   /* create lock file filenames for NFS */
    1088 |
    1089 |   if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
    1090 | 			      &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
    1091 |     ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
    1092 |     exit(1);
    1093 |   }
    1094 |
    1095 |   if (waitpid (gpg_pid, &status, 0) < 0)
    1096 |     {
    1097 |       ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
    1098 |       exit(1);
    1099 |     }
    1100 |
    1101 |   if (WIFEXITED(status) == 0)
    1102 |     {
    1103 |       ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
    1104 |       exit(1);
    1105 |     } else {
    1106 |       /* Child exited, checking return code */
    1107 |       childRC = (status & 0xF00) >> 8;
    1108 |       if (childRC == 1) {
    1109 | 	ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
    1110 | 	exit(1);
    1111 |       }
    1112 |     }
    1113 |
    1114 |
    1115 |   mystdin = fdopen(0, "r");
    1116 |   while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
    1117 |     {
    1118 |       /* printf ( "GPG output : %s\n", txt );      */
    1119 |
    1120 |       if ((keyStr = strstr(txt, "pub "/*"Key fingerprint ="*/)) == txt /*!= NULL*/) {
    1121 | 	strcpy(iKO->keyOwner, keyStr + 30);
    1122 | 	iKO->keyOwner[strlen(iKO->keyOwner)-1] = 0;
    1123 |       }
    1124 |
    1125 |       if ((keyStr = strstr(txt, "key")) != NULL) {
    1126 | 	 keyStr += 4;
    1127 | 	 sscanf(keyStr, "%8X\n", &iKO->keyID);
    1128 |       }
    1129 |     }
    1130 |
    1131 |   if (sd1[0] != 0)  close ( sd1[0] );
    1132 | }
    1133 |
    1134 |
    1135 |
    1136 | /*++++++++++++++++++++++++++++
    1137 |
    1138 | Verify the PGP signature and extract the signed part in a file.
    1139 |
    1140 | EPNodePtr ptr	The pointer to the EP treenode containing the originating file
    1141 |
    1142 | ++++++++++++++++++++++++++++*/
    1143 |
    1144 | void VerifySignAndExplodeFile(EPNodePtr ptr) {
    1145 |   char *strArgs[10];
    1146 |   char Args0[100];
    1147 |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
    1148 |     Args6[100];
    1149 |   int gpg_pid;
    1150 |   int gpg_in_fd, out_fd, err_fd;
    1151 |   int status;
    1152 |   char txt[LINE_LENGTH];
    1153 |   /* char hostname[MAXHOSTNAMELEN]; */
    1154 |   char oFile[FILENAME_LENGTH];
    1155 |   char *keyStr;
    1156 |   /* int childRC; */
    1157 |   FILE *mystdin;
    1158 |
    1159 |   sprintf(oFile, "%s.%d.exp", ptr->file, ptr->nodeID);
    1160 |
    1161 |   strcpy(Args0, "--no-secmem-warning");
    1162 |   strcpy(Args1, "--keyring");
    1163 |   strcpy(Args2, keyRing);
    1164 |   strcpy(Args3, "-o");
    1165 |   strcpy(Args4, oFile);
    1166 |   strcpy(Args5, "-d");
    1167 |   strcpy(Args6, ptr->file);
    1168 |   strArgs[6] = Args6;
    1169 |   strArgs[7] = (char *)0;
    1170 |
    1171 |   strArgs[0] = Args0;
    1172 |   strArgs[1] = Args1;
    1173 |   strArgs[2] = Args2;
    1174 |   strArgs[3] = Args3;
    1175 |   strArgs[4] = Args4;
    1176 |   strArgs[5] = Args5;
    1177 |
    1178 |   gpg_in_fd = INPUT_FD;
    1179 |   out_fd = OUTPUT_FD;
    1180 |   err_fd = ERROR_FD;
    1181 |
    1182 |   if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
    1183 | 			      &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
    1184 |       ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
    1185 |       exit(1);
    1186 |   }
    1187 |
    1188 |   if (waitpid (gpg_pid, &status, 0) < 0) {
    1189 |     ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
    1190 |     exit(1);
    1191 |   }
    1192 |   if (WIFEXITED(status) == 0) {
    1193 |     ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
    1194 |     exit(1);
    1195 |   }
    1196 |   else {
    1197 |   }
    1198 |
    1199 |
    1200 |   /* Parsing gpg output */
    1201 |   mystdin = fdopen(0, "r");
    1202 |   ptr->isValidPGPSignature = vS_KO;
    1203 |   while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
    1204 |     {
    1205 |       /* 	printf ( "GPG output : %s\n", txt );   */
    1206 |       if (strstr(txt, "Good signature") != NULL)
    1207 | 	ptr->isValidPGPSignature = vS_IS_VALID;
    1208 |
    1209 |       if (strstr(txt, "CRC error") != NULL)
    1210 | 	ptr->isValidPGPSignature = vS_CRC_ERROR;
    1211 |
    1212 |       if (strstr(txt, "public key not found") != NULL)
    1213 | 	ptr->isValidPGPSignature = vS_NO_PUBLIC_KEY;
    1214 |
    1215 |       if (strstr(txt, "no valid OpenPGP data found") != NULL)
    1216 | 	ptr->isValidPGPSignature = vS_NO_OPENPGP_DATA;
    1217 |
    1218 |       if ((keyStr = strstr(txt, "key ID")) != NULL) {
    1219 | 	keyStr += 7;
    1220 | 	sscanf(keyStr, "%8X\n", &ptr->keyID);
    1221 |       }
    1222 |     }
    1223 |
    1224 |   if (ptr->isValidPGPSignature == vS_NO_OPENPGP_DATA) {
    1225 |     FILE* f;
    1226 |     f= fopen(oFile, "w");
    1227 |     fprintf(f, " \n");
    1228 |     fclose(f);
    1229 |   }
    1230 |
    1231 |   unlink(ptr->file);
    1232 |   UT_free(ptr->file);
    1233 |   ptr->file = UT_strdup(oFile);
    1234 |   if (sd1[0] != 0)  close ( sd1[0] );
    1235 | }
    1236 |
    1237 |
    1238 | /*++++++++++++++++++++++++++++
    1239 |
    1240 | Get the KeyID of a PGP key.
    1241 |
    1242 | struct ImportKeyObject *iKO	The structure containing the key of which we want the KeyID
    1243 |
    1244 | ++++++++++++++++++++++++++++*/
    1245 |
    1246 | void GetKeyID(struct ImportKeyObject *iKO) {
    1247 |
    1248 |   char *strArgs[9];
    1249 |   char Args0[100];
    1250 |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
    1251 |   int gpg_pid;
    1252 |   int gpg_in_fd, out_fd, err_fd;
    1253 |   int status;
    1254 |   char txt[LINE_LENGTH];
    1255 |   char *keyStr, *pos;
    1256 |   const char lockFilename[] = ".PAlock";
    1257 |   char keyRingLockFile[1000], keyRingPath[1000];
    1258 |   time_t lockBirthDate;
    1259 |   FILE *mystdin;
    1260 |   int childRC;
    1261 |
    1262 |   iKO->rc = iKO_GENERALFAILURE;
    1263 |
    1264 |   strcpy(Args0, "--no-tty");
    1265 |   strcpy(Args1, "--no-secmem-warning");
    1266 |   strcpy(Args2, "--keyring");
    1267 |   strcpy(Args3, iKO->keyRing);
    1268 |   strcpy(Args4, "--import");
    1269 |   strcpy(Args5, iKO->iFilename);
    1270 |
    1271 |   strArgs[0] = Args0;
    1272 |   strArgs[1] = Args1;
    1273 |   strArgs[2] = Args2;
    1274 |   strArgs[3] = Args3;
    1275 |   strArgs[4] = Args4;
    1276 |   strArgs[5] = Args5;
    1277 |   strArgs[6] = (char *)0;
    1278 |
    1279 |   gpg_in_fd = INPUT_FD;
    1280 |   out_fd = OUTPUT_FD;
    1281 |   err_fd = ERROR_FD;
    1282 |
    1283 |   /* create lock file filenames for NFS */
    1284 |
    1285 |   strcpy(keyRingLockFile, iKO->keyRing);
    1286 |   if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
    1287 |     strcpy(pos + 1, lockFilename);
    1288 |     strcpy(keyRingPath, keyRingLockFile);
    1289 |     keyRingPath[pos - keyRingLockFile] = 0;
    1290 |   } else {
    1291 |     strcpy(keyRingLockFile, lockFilename);
    1292 |     strcpy(keyRingPath, "");
    1293 |   }
    1294 |
    1295 |   lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
    1296 |
    1297 |   if ( ( gpg_pid = spawn_job (gpgCmd, strArgs,
    1298 | 			      &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
    1299 |     ER_perror(FAC_PA, PA_CANTSPWN, "gpg");
    1300 |     exit(1);
    1301 |   }
    1302 |
    1303 |   if (waitpid (gpg_pid, &status, 0) < 0)
    1304 |     {
    1305 |       ER_perror(FAC_PA, PA_REAP, "gpg process: %s", ERRSTRING);
    1306 |       nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
    1307 |       exit(1);
    1308 |     }
    1309 |
    1310 |   nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
    1311 |
    1312 |   if (WIFEXITED(status) == 0)
    1313 |     {
    1314 |       ER_perror(FAC_PA, PA_CHST, "%d - %s", status, ERRSTRING);
    1315 |       exit(1);
    1316 |     } else {
    1317 |       /* Child exited, checking return code */
    1318 |       childRC = (status & 0xF00) >> 8;
    1319 |       if (childRC == 1) {
    1320 | 	ER_perror(FAC_PA, PA_CHRC, "%d", childRC);
    1321 | 	exit(1);
    1322 |       }
    1323 |     }
    1324 |
    1325 |
    1326 |   /* Parsing gpg output */
    1327 |   /*   while (read(0, txt, 1000) != 0)
    1328 |        fprintf(stderr, "child read %s\n", txt); */
    1329 |
    1330 |   mystdin = fdopen(0, "r");
    1331 |   iKO->rc = iKO_GENERALFAILURE;
    1332 |   while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
    1333 |     {
    1334 |       /*          printf ( "GPG output : %s\n", txt );      */
    1335 |
    1336 |       if ((keyStr = strstr(txt, "imported")) != NULL) {
    1337 | 	iKO->rc = iKO_OK;
    1338 |       }
    1339 |
    1340 |       if ((keyStr = strstr(txt, "CRC error")) != NULL) {
    1341 | 	iKO->rc = iKO_CRC_ERROR;
    1342 |       }
    1343 |
    1344 |       if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL) {
    1345 | 	iKO->rc = iKO_NO_OPENPGP_DATA;
    1346 |       }
    1347 |
    1348 |       if (((keyStr = strstr(txt, "unchanged")) != NULL) ||
    1349 | 	  ((keyStr = strstr(txt, "not changed")) != NULL)) {
    1350 | 	iKO->rc = iKO_UNCHANGED;
    1351 |       }
    1352 |
    1353 |       if ((keyStr = strstr(txt, "gpg: key ")) != NULL) {
    1354 | 	 keyStr += 9;
    1355 | 	 sscanf(keyStr, "%8X\n", &iKO->keyID);
    1356 |       }
    1357 |     }
    1358 |
    1359 |   if (sd1[0] != 0)  close ( sd1[0] );
    1360 |
    1361 | }
    1362 |