Source File modules/pa/gpg.c

    1    | #include <stdio.h>
    2    | #include <stdlib.h>
    3    | #include <string.h>
    4    | #include <sys/wait.h>
    5    | #include <unistd.h>
    6    | #include <errno.h>
    7    | #include <sys/types.h>
    8    | #include <sys/stat.h>
    9    | #include <fcntl.h>
    10   | #include <time.h>
    11   |
    12   | #include "gpg.h"
    13   |
    14   | extern int sd1[2];
    15   | extern int spawn_job (char *path, char *argv[],
    16   | 		      int *in_fd, int *out_fd, int *err_fd);
    17   | extern time_t nfslock(char *path, char *namelock, int max_age, int notify);
    18   | extern int nfsunlock(char *path, char *namelock, int max_age, time_t birth);
    19   |
    20   | void ParseInputFile(struct VerifySignObject *vSO) {
    21   |   FILE *fin, *fout;
    22   |   char txt[LINE_LENGTH];
    23   |   char keyRing[LINE_LENGTH];
    24   |   char outputPath[LINE_LENGTH];
    25   |   const char PGP_prefix[] = "-----BEGIN PGP ";
    26   |   const char PGP_suffix[] = "-----END PGP ";
    27   |   int found_prefix = 0, nMsgs = 0, outFileOpened = 0, clearTextBlock = 1;
    28   |   char foutName[100];
    29   |   struct VerifySignObject *vSOList = vSO;
    30   |
    31   |   strcpy(keyRing, vSO->keyRing);
    32   |   strcpy(outputPath, vSO->outputPath);
    33   |
    34   |   if (!strcmp(vSOList->iSigFilename, "")) {
    35   |     if ((fin = fopen(vSOList->iDocSigFilename, "r")) != NULL) {
    36   |
    37   |       while (fgets (txt, LINE_LENGTH - 1, fin) != NULL) {
    38   |
    39   |       /* Looking for PGP prefix */
    40   | 	if ((strstr(txt, PGP_prefix) != NULL) && !found_prefix) {
    41   | 	  clearTextBlock = 0;
    42   | 	  found_prefix = 1;
    43   | 	  /* remember to delete those files */
    44   | 	  sprintf(foutName, "/tmp/PAtmp.%d.%d", (int)getpid(), nMsgs);
    45   | 	  if ((fout = fopen(foutName, "w")) == NULL ) {
    46   | 	    vSOList->isValid = vSO_NO_OUT_FILES;
    47   | 	    return;
    48   | 	  }
    49   | 	  outFileOpened = 1;
    50   | 	  vSOList->next = malloc(sizeof(struct VerifySignObject));
    51   | 	  vSOList = vSOList->next;
    52   | 	  strcpy(vSOList->iDocSigFilename, foutName);
    53   | 	  strcpy(vSOList->keyRing, keyRing);
    54   | 	  strcpy(vSOList->outputPath, outputPath);
    55   | 	  vSOList->next = NULL;
    56   | 	} else
    57   | 	  if ((strstr(txt, PGP_suffix) != NULL ) && found_prefix) {
    58   | 	    found_prefix = 0;
    59   | 	    clearTextBlock = 1;
    60   | 	    fputs(txt, fout);
    61   | 	    fclose(fout);
    62   | 	    outFileOpened = 0;
    63   | 	    nMsgs++;
    64   | 	  } else
    65   | 	    if (clearTextBlock && !outFileOpened) {
    66   | 	      sprintf(foutName, "/tmp/PAtmp.%d.%d", (int)getpid(), nMsgs);
    67   | 	      if ((fout = fopen(foutName, "w")) == NULL ) {
    68   | 		vSOList->isValid = vSO_NO_OUT_FILES;
    69   | 		return;
    70   | 	      }
    71   | 	      outFileOpened = 1;
    72   | 	      vSOList->next = malloc(sizeof(struct VerifySignObject));
    73   | 	      vSOList = vSOList->next;
    74   | 	      strcpy(vSOList->iDocSigFilename, foutName);
    75   | 	      strcpy(vSOList->keyRing, keyRing);
    76   | 	      strcpy(vSOList->outputPath, outputPath);
    77   | 	      vSOList->next = NULL;
    78   | 	    }
    79   | 	if (outFileOpened) {
    80   | 	  fputs(txt, fout);
    81   | 	}
    82   |       }
    83   |       if (outFileOpened) {
    84   | 	fclose(fout);
    85   |       }
    86   |       fclose(fin);
    87   |     } else {
    88   |       vSOList->isValid = vSO_NO_IN_FILES;
    89   |     }
    90   |   }
    91   | }
    92   |
    93   | void VerifySignature(struct VerifySignObject *vSO) {
    94   |   char *strArgs[10];
    95   |   char Args0[100];
    96   |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100],
    97   |     Args6[100], Args7[100];
    98   |   int gpg_pid;
    99   |   int gpg_in_fd, out_fd, err_fd;
    100  |   int status;
    101  |   static int nMsgs = 0;
    102  |   char txt[LINE_LENGTH];
    103  |   char *keyStr;
    104  |   struct VerifySignObject *pvSO = vSO->next, *ptmp;
    105  |
    106  |   while (pvSO != NULL) {
    107  |     nMsgs++;
    108  |     /* Copy the incoming object on the internal global object */
    109  |     /* memmove( &verifySignObj, pvSO, sizeof(struct VerifySignObject) ); */
    110  |
    111  |     sprintf(pvSO->oStream, "%s/PAtmp.%ld.%ld.%d", pvSO->outputPath,
    112  | 	    labs(gethostid()), getpid(), nMsgs);
    113  |
    114  |     strcpy(Args0, "--no-secmem-warning");
    115  |     strcpy(Args1, "--keyring");
    116  |     strcpy(Args2, pvSO->keyRing);
    117  |     strcpy(Args3, "-o");
    118  |     strcpy(Args4, pvSO->oStream);
    119  |     strcpy(Args5, "-d");
    120  |     if (!strcmp(pvSO->iSigFilename, "")) {
    121  |       strcpy(Args6, pvSO->iDocSigFilename);
    122  |       strArgs[6] = Args6;
    123  |       strArgs[7] = (char *)0;
    124  |     } else {
    125  |       strcpy(Args6, pvSO->iSigFilename);
    126  |       strcpy(Args7, pvSO->iDocSigFilename);
    127  |       strArgs[6] = Args6;
    128  |       strArgs[7] = Args7;
    129  |       strArgs[8] = (char *)0;
    130  |     }
    131  |
    132  |     strArgs[0] = Args0;
    133  |     strArgs[1] = Args1;
    134  |     strArgs[2] = Args2;
    135  |     strArgs[3] = Args3;
    136  |     strArgs[4] = Args4;
    137  |     strArgs[5] = Args5;
    138  |
    139  |     gpg_in_fd = INPUT_FD;
    140  |     out_fd = OUTPUT_FD;
    141  |     err_fd = ERROR_FD;
    142  |     if ( ( gpg_pid = spawn_job ("gpg", strArgs,
    143  | 				&gpg_in_fd, &out_fd, &err_fd) ) < 0 )
    144  |       {
    145  | 	printf ("could not spawn gpg");
    146  |       }
    147  |
    148  |     if (waitpid (gpg_pid, &status, 0) < 0)
    149  |       {
    150  | 	fprintf (stderr, "Error reaping child\t%s\n", ERRSTRING);
    151  | 	printf ("could not reap gpg process");
    152  |       }
    153  |     if (WIFEXITED(status) == 0)
    154  |       {
    155  | 	fprintf (stderr, "Bad child status: %d\t%s\n", status, ERRSTRING);
    156  | 	printf ("gpg failure\n");
    157  |       }
    158  |
    159  |
    160  |     /* Parsing gpg output */
    161  |     pvSO->isValid = vSO_KO;
    162  |     while (fgets (txt, LINE_LENGTH - 1, stdin) != NULL)
    163  |       {
    164  | 	/* 	printf ( "GPG output : %s\n", txt );  */
    165  | 	if (strstr(txt, "Good signature") != NULL)
    166  | 	  pvSO->isValid = vSO_IS_VALID;
    167  |
    168  | 	if (strstr(txt, "CRC error") != NULL)
    169  | 	  pvSO->isValid = vSO_CRC_ERROR;
    170  |
    171  | 	if (strstr(txt, "public key not found") != NULL)
    172  | 	  pvSO->isValid = vSO_NO_PUBLIC_KEY;
    173  |
    174  | 	if (strstr(txt, "no valid OpenPGP data found") != NULL)
    175  | 	  pvSO->isValid = vSO_NO_OPENPGP_DATA;
    176  |
    177  | 	if ((keyStr = strstr(txt, "key ID")) != NULL) {
    178  | 	  keyStr += 7;
    179  | 	  sscanf(keyStr, "%8X\n", &pvSO->keyID);
    180  | 	}
    181  |       }
    182  |
    183  |     unlink(pvSO->iDocSigFilename);
    184  |     pvSO = pvSO->next;
    185  |   }
    186  |   if (sd1[0] != 0)  close ( sd1[0] );
    187  | }
    188  |
    189  |
    190  | /* ------------------------------------------------- */
    191  | void PA_VerifySignature(struct VerifySignObject *vSO) {
    192  |
    193  |   /* split input file if there are multiple signed messages */
    194  |   ParseInputFile( vSO );
    195  |
    196  |   /* Verify each single PGP mesg */
    197  |   VerifySignature( vSO );
    198  |
    199  | }
    200  |
    201  | /* ------------------------------------------------- */
    202  | void PA_Decrypt(struct ReadCryptedObject *rDO) {
    203  |
    204  |   char *strArgs[9];
    205  |   char clearTextExtension[4] = ".gpg";
    206  |   char Args0[100] = "abracadabra";
    207  |   char Args1[100];
    208  |   char Args2[100];
    209  |   char Args3[100];
    210  |   char Args4[100];
    211  |   char Args5[100];
    212  |   char Args6[100];
    213  |   int gpg_pid;
    214  |   int gpg_in_fd, out_fd, err_fd;
    215  |   int status;
    216  |   char txt[LINE_LENGTH];
    217  |
    218  |
    219  |   strcpy(Args0, "--no-tty");
    220  |   strcpy(Args1, "--no-secmem-warning");
    221  |   strcpy(Args2, "--keyring");
    222  |   strcpy(Args3, rDO->keyRing);
    223  |   strcpy(Args4, "--output");
    224  |   strcpy(Args5, strcat(rDO->iFilename, clearTextExtension));
    225  |   strcpy(Args6, rDO->iFilename);
    226  |
    227  |   strArgs[0] = Args0;
    228  |   strArgs[1] = Args1;
    229  |   strArgs[2] = Args2;
    230  |   strArgs[3] = Args3;
    231  |   strArgs[4] = Args4;
    232  |   strArgs[5] = Args5;
    233  |   strArgs[6] = Args6;
    234  |   strArgs[7] = (char *) 0;
    235  |
    236  |   gpg_in_fd = INPUT_FD;
    237  |   out_fd = OUTPUT_FD;
    238  |   err_fd = ERROR_FD;
    239  |   if ( ( gpg_pid = spawn_job ("gpg", strArgs,
    240  | 			      &gpg_in_fd, &out_fd, &err_fd) ) < 0 )
    241  |     {
    242  |       printf ("could not spawn gpg");
    243  |     }
    244  |
    245  |   if (waitpid (gpg_pid, &status, 0) < 0)
    246  |     {
    247  |       fprintf (stderr, "Error reaping child\t%s\n", ERRSTRING);
    248  |       printf ("could not reap gpg process");
    249  |     }
    250  |   if (WIFEXITED(status) == 0)
    251  |     {
    252  |       fprintf (stderr, "Bad child status: %d\t%s\n", status, ERRSTRING);
    253  |       printf ("gpg failure");
    254  |     }
    255  |
    256  |
    257  |   /* Parsing gpg output */
    258  |   while (fgets (txt, STRING_LENGTH - 1, stdin) != NULL)
    259  |     {
    260  |
    261  |     }
    262  |
    263  |   if (sd1[0] != 0)  close ( sd1[0] );
    264  | }
    265  |
    266  |
    267  | /* ------------------------------------------------- */
    268  | void PA_ImportKey(struct ImportKeyObject *iKO) {
    269  |
    270  |   char *strArgs[9];
    271  |   char Args0[100] = "abracadabra";
    272  |   char Args1[100], Args2[100], Args3[100], Args4[100], Args5[100];
    273  |   int gpg_pid;
    274  |   int gpg_in_fd, out_fd, err_fd;
    275  |   int status;
    276  |   char txt[LINE_LENGTH];
    277  |   char *keyStr, *pos;
    278  |   const char lockFilename[] = ".PAlock";
    279  |   char keyRingLockFile[1000], keyRingPath[1000];
    280  |   time_t lockBirthDate;
    281  |   FILE *mystdin;
    282  |
    283  |   iKO->rc = iKO_GENERALFAILURE;
    284  |
    285  |   strcpy(Args0, "--no-tty");
    286  |   strcpy(Args1, "--no-secmem-warning");
    287  |   strcpy(Args2, "--keyring");
    288  |   strcpy(Args3, iKO->keyRing);
    289  |   strcpy(Args4, "--import");
    290  |   strcpy(Args5, iKO->iFilename);
    291  |
    292  |   strArgs[0] = Args0;
    293  |   strArgs[1] = Args1;
    294  |   strArgs[2] = Args2;
    295  |   strArgs[3] = Args3;
    296  |   strArgs[4] = Args4;
    297  |   strArgs[5] = Args5;
    298  |   strArgs[6] = (char *)0;
    299  |
    300  |   gpg_in_fd = INPUT_FD;
    301  |   out_fd = OUTPUT_FD;
    302  |   err_fd = ERROR_FD;
    303  |
    304  |   /* create lock file filenames for NFS */
    305  |
    306  |   strcpy(keyRingLockFile, iKO->keyRing);
    307  |   if ((pos = strrchr(keyRingLockFile, '/')) != NULL) {
    308  |     strcpy(pos + 1, lockFilename);
    309  |     strcpy(keyRingPath, keyRingLockFile);
    310  |     keyRingPath[pos - keyRingLockFile] = 0;
    311  |   } else {
    312  |     strcpy(keyRingLockFile, lockFilename);
    313  |     strcpy(keyRingPath, "");
    314  |   }
    315  |
    316  |   lockBirthDate = nfslock(keyRingPath, (char*)lockFilename, 0, 0);
    317  |
    318  |   if ( ( gpg_pid = spawn_job ("gpg", strArgs,
    319  | 			      &gpg_in_fd, &out_fd, &err_fd) ) < 0 ) {
    320  |     printf ("could not spawn gpg");
    321  |   }
    322  |
    323  |   if (waitpid (gpg_pid, &status, 0) < 0)
    324  |     {
    325  |       fprintf (stderr, "Error reaping child\t%s\n", ERRSTRING);
    326  |       printf ("could not reap gpg process");
    327  |     }
    328  |
    329  |   nfsunlock(keyRingPath, (char*)lockFilename, 0, lockBirthDate);
    330  |
    331  |   if (WIFEXITED(status) == 0)
    332  |     {
    333  |       fprintf (stderr, "Bad child status: %d\t%s\n", status, ERRSTRING);
    334  |       printf ("gpg failure");
    335  |     }
    336  |
    337  |
    338  |   /* Parsing gpg output */
    339  |   /*   while (read(0, txt, 1000) != 0)
    340  |        fprintf(stderr, "child read %s\n", txt); */
    341  |
    342  |   mystdin = fdopen(0, "r");
    343  |   iKO->rc = iKO_GENERALFAILURE;
    344  |   while (fgets (txt, LINE_LENGTH - 1, mystdin) != NULL)
    345  |     {
    346  |           printf ( "GPG output : %s\n", txt );
    347  |
    348  |       if ((keyStr = strstr(txt, "imported")) != NULL) {
    349  | 	iKO->rc = iKO_OK;
    350  |       }
    351  |
    352  |       if ((keyStr = strstr(txt, "CRC error")) != NULL) {
    353  | 	iKO->rc = iKO_CRC_ERROR;
    354  |       }
    355  |
    356  |       if ((keyStr = strstr(txt, "no valid OpenPGP")) != NULL) {
    357  | 	iKO->rc = iKO_NO_OPENPGP_DATA;
    358  |       }
    359  |
    360  |       if ((keyStr = strstr(txt, "unchanged")) != NULL) {
    361  | 	iKO->rc = iKO_UNCHANGED;
    362  |       }
    363  |
    364  |       if ((keyStr = strstr(txt, "key")) != NULL) {
    365  | 	 keyStr += 4;
    366  | 	 sscanf(keyStr, "%8X\n", &iKO->keyID);
    367  |       }
    368  |     }
    369  |
    370  |   if (sd1[0] != 0)  close ( sd1[0] );
    371  | }
    372  |
    373  |