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 |