Source File pa/gpg.c

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