00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "system.h"
00015
00016 #if HAVE_ASM_BYTEORDER_H
00017 #include <asm/byteorder.h>
00018 #endif
00019
00020 #include <rpmlib.h>
00021 #include <rpmmacro.h>
00022
00023 #include "md5.h"
00024 #include "misc.h"
00025 #include "rpmlead.h"
00026 #include "signature.h"
00027 #include "debug.h"
00028
00029
00030
00031 typedef unsigned char byte;
00032
00033 typedef int (*md5func)(const char * fn, byte * digest);
00034
00035 int rpmLookupSignatureType(int action)
00036 {
00037 static int disabled = 0;
00038 int rc = 0;
00039
00040 switch (action) {
00041 case RPMLOOKUPSIG_DISABLE:
00042 disabled = -2;
00043 break;
00044 case RPMLOOKUPSIG_ENABLE:
00045 disabled = 0;
00046
00047 case RPMLOOKUPSIG_QUERY:
00048 if (disabled)
00049 break;
00050 { const char *name = rpmExpand("%{_signature}", NULL);
00051 if (!(name && *name != '%'))
00052 rc = 0;
00053 else if (!xstrcasecmp(name, "none"))
00054 rc = 0;
00055 else if (!xstrcasecmp(name, "pgp"))
00056 rc = RPMSIGTAG_PGP;
00057 else if (!xstrcasecmp(name, "pgp5"))
00058 rc = RPMSIGTAG_PGP;
00059 else if (!xstrcasecmp(name, "gpg"))
00060 rc = RPMSIGTAG_GPG;
00061 else
00062 rc = -1;
00063 free((void *)name);
00064 } break;
00065 }
00066 return rc;
00067 }
00068
00069
00070
00071
00072 const char * rpmDetectPGPVersion(pgpVersion * pgpVer)
00073 {
00074
00075
00076
00077
00078 static pgpVersion saved_pgp_version = PGP_UNKNOWN;
00079 const char *pgpbin = rpmGetPath("%{_pgpbin}", NULL);
00080
00081 if (saved_pgp_version == PGP_UNKNOWN) {
00082 char *pgpvbin;
00083 struct stat st;
00084
00085 if (!(pgpbin && pgpbin[0] != '%')) {
00086 if (pgpbin) free((void *)pgpbin);
00087 saved_pgp_version = -1;
00088 return NULL;
00089 }
00090 pgpvbin = (char *)alloca(strlen(pgpbin) + sizeof("v"));
00091 (void)stpcpy(stpcpy(pgpvbin, pgpbin), "v");
00092
00093 if (stat(pgpvbin, &st) == 0)
00094 saved_pgp_version = PGP_5;
00095 else if (stat(pgpbin, &st) == 0)
00096 saved_pgp_version = PGP_2;
00097 else
00098 saved_pgp_version = PGP_NOTDETECTED;
00099 }
00100
00101 if (pgpbin && pgpVer)
00102 *pgpVer = saved_pgp_version;
00103 return pgpbin;
00104 }
00105
00115 static inline rpmRC checkSize(FD_t fd, int siglen, int pad, int datalen)
00116 {
00117 struct stat st;
00118 rpmRC rc;
00119
00120 if (fstat(Fileno(fd), &st))
00121 return RPMRC_FAIL;
00122
00123 if (!S_ISREG(st.st_mode)) {
00124 rpmMessage(RPMMESS_DEBUG,
00125 _("file is not regular -- skipping size check\n"));
00126 return RPMRC_OK;
00127 }
00128
00129 rc = (((sizeof(struct rpmlead) + siglen + pad + datalen) - st.st_size)
00130 ? RPMRC_BADSIZE : RPMRC_OK);
00131
00132 rpmMessage((rc == RPMRC_OK ? RPMMESS_DEBUG : RPMMESS_WARNING),
00133 _("Expected size: %12d = lead(%d)+sigs(%d)+pad(%d)+data(%d)\n"),
00134 sizeof(struct rpmlead)+siglen+pad+datalen,
00135 sizeof(struct rpmlead), siglen, pad, datalen);
00136 rpmMessage((rc == RPMRC_OK ? RPMMESS_DEBUG : RPMMESS_WARNING),
00137 _(" Actual size: %12d\n"), st.st_size);
00138
00139 return rc;
00140 }
00141
00142 rpmRC rpmReadSignature(FD_t fd, Header * headerp, sigType sig_type)
00143 {
00144 byte buf[2048];
00145 int sigSize, pad;
00146 int_32 type, count;
00147 int_32 *archSize;
00148 Header h = NULL;
00149 rpmRC rc = RPMRC_FAIL;
00150
00151 if (headerp)
00152 *headerp = NULL;
00153
00154 switch (sig_type) {
00155 case RPMSIGTYPE_NONE:
00156 rpmMessage(RPMMESS_DEBUG, _("No signature\n"));
00157 rc = RPMRC_OK;
00158 break;
00159 case RPMSIGTYPE_PGP262_1024:
00160 rpmMessage(RPMMESS_DEBUG, _("Old PGP signature\n"));
00161
00162 if (timedRead(fd, buf, 256) != 256)
00163 break;
00164 h = headerNew();
00165 headerAddEntry(h, RPMSIGTAG_PGP, RPM_BIN_TYPE, buf, 152);
00166 rc = RPMRC_OK;
00167 break;
00168 case RPMSIGTYPE_MD5:
00169 case RPMSIGTYPE_MD5_PGP:
00170 rpmError(RPMERR_BADSIGTYPE,
00171 _("Old (internal-only) signature! How did you get that!?\n"));
00172 break;
00173 case RPMSIGTYPE_HEADERSIG:
00174 case RPMSIGTYPE_DISABLE:
00175
00176 h = headerRead(fd, HEADER_MAGIC_YES);
00177 if (h == NULL)
00178 break;
00179
00180 rc = RPMRC_OK;
00181 sigSize = headerSizeof(h, HEADER_MAGIC_YES);
00182
00183
00184 if (headerIsEntry(h, RPMTAG_HEADERIMAGE))
00185 sigSize -= (16 + 16);
00186
00187 pad = (8 - (sigSize % 8)) % 8;
00188 if (sig_type == RPMSIGTYPE_HEADERSIG) {
00189 if (! headerGetEntry(h, RPMSIGTAG_SIZE, &type,
00190 (void **)&archSize, &count))
00191 break;
00192 rc = checkSize(fd, sigSize, pad, *archSize);
00193 }
00194 if (pad && timedRead(fd, buf, pad) != pad)
00195 rc = RPMRC_SHORTREAD;
00196 break;
00197 default:
00198 break;
00199 }
00200
00201 if (rc == 0 && headerp)
00202 *headerp = h;
00203 else if (h)
00204 headerFree(h);
00205
00206 return rc;
00207 }
00208
00209 int rpmWriteSignature(FD_t fd, Header h)
00210 {
00211 static byte buf[8] = "\000\000\000\000\000\000\000\000";
00212 int sigSize, pad;
00213 int rc;
00214
00215 rc = headerWrite(fd, h, HEADER_MAGIC_YES);
00216 if (rc)
00217 return rc;
00218
00219 sigSize = headerSizeof(h, HEADER_MAGIC_YES);
00220 pad = (8 - (sigSize % 8)) % 8;
00221 if (pad) {
00222 if (Fwrite(buf, sizeof(buf[0]), pad, fd) != pad)
00223 rc = 1;
00224 }
00225 rpmMessage(RPMMESS_DEBUG, _("Signature: size(%d)+pad(%d)\n"), sigSize, pad);
00226 return rc;
00227 }
00228
00229 Header rpmNewSignature(void)
00230 {
00231 Header h = headerNew();
00232 return h;
00233 }
00234
00235 void rpmFreeSignature(Header h)
00236 {
00237 headerFree(h);
00238 }
00239
00240 static int makePGPSignature(const char * file, void ** sig,
00241 int_32 * size, const char * passPhrase)
00242 {
00243 char * sigfile = alloca(1024);
00244 int pid, status;
00245 int inpipe[2];
00246 struct stat st;
00247
00248 (void) stpcpy( stpcpy(sigfile, file), ".sig");
00249
00250 inpipe[0] = inpipe[1] = 0;
00251 pipe(inpipe);
00252
00253 if (!(pid = fork())) {
00254 const char *pgp_path = rpmExpand("%{_pgp_path}", NULL);
00255 const char *name = rpmExpand("+myname=\"%{_pgp_name}\"", NULL);
00256 const char *path;
00257 pgpVersion pgpVer;
00258
00259 close(STDIN_FILENO);
00260 dup2(inpipe[0], 3);
00261 close(inpipe[1]);
00262
00263 dosetenv("PGPPASSFD", "3", 1);
00264 if (pgp_path && *pgp_path != '%')
00265 dosetenv("PGPPATH", pgp_path, 1);
00266
00267
00268
00269 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
00270 switch(pgpVer) {
00271 case PGP_2:
00272 execlp(path, "pgp", "+batchmode=on", "+verbose=0", "+armor=off",
00273 name, "-sb", file, sigfile, NULL);
00274 break;
00275 case PGP_5:
00276 execlp(path,"pgps", "+batchmode=on", "+verbose=0", "+armor=off",
00277 name, "-b", file, "-o", sigfile, NULL);
00278 break;
00279 case PGP_UNKNOWN:
00280 case PGP_NOTDETECTED:
00281 break;
00282 }
00283 }
00284 rpmError(RPMERR_EXEC, _("Couldn't exec pgp (%s)\n"), path);
00285 _exit(RPMERR_EXEC);
00286 }
00287
00288 close(inpipe[0]);
00289 (void)write(inpipe[1], passPhrase, strlen(passPhrase));
00290 (void)write(inpipe[1], "\n", 1);
00291 close(inpipe[1]);
00292
00293 (void)waitpid(pid, &status, 0);
00294 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
00295 rpmError(RPMERR_SIGGEN, _("pgp failed\n"));
00296 return 1;
00297 }
00298
00299 if (stat(sigfile, &st)) {
00300
00301 unlink(sigfile);
00302 rpmError(RPMERR_SIGGEN, _("pgp failed to write signature\n"));
00303 return 1;
00304 }
00305
00306 *size = st.st_size;
00307 rpmMessage(RPMMESS_DEBUG, _("PGP sig size: %d\n"), *size);
00308 *sig = xmalloc(*size);
00309
00310 { FD_t fd;
00311 int rc;
00312 fd = Fopen(sigfile, "r.fdio");
00313 rc = timedRead(fd, *sig, *size);
00314 unlink(sigfile);
00315 Fclose(fd);
00316 if (rc != *size) {
00317 free(*sig);
00318 rpmError(RPMERR_SIGGEN, _("unable to read the signature\n"));
00319 return 1;
00320 }
00321 }
00322
00323 rpmMessage(RPMMESS_DEBUG, _("Got %d bytes of PGP sig\n"), *size);
00324
00325 return 0;
00326 }
00327
00328
00329
00330
00331
00332
00333 static int makeGPGSignature(const char * file, void ** sig,
00334 int_32 * size, const char * passPhrase)
00335 {
00336 char * sigfile = alloca(1024);
00337 int pid, status;
00338 int inpipe[2];
00339 FILE * fpipe;
00340 struct stat st;
00341
00342 (void) stpcpy( stpcpy(sigfile, file), ".sig");
00343
00344 inpipe[0] = inpipe[1] = 0;
00345 pipe(inpipe);
00346
00347 if (!(pid = fork())) {
00348 const char *gpg_path = rpmExpand("%{_gpg_path}", NULL);
00349 const char *name = rpmExpand("%{_gpg_name}", NULL);
00350
00351 close(STDIN_FILENO);
00352 dup2(inpipe[0], 3);
00353 close(inpipe[1]);
00354
00355 if (gpg_path && *gpg_path != '%')
00356 dosetenv("GNUPGHOME", gpg_path, 1);
00357 execlp("gpg", "gpg",
00358 "--batch", "--no-verbose", "--no-armor", "--passphrase-fd", "3",
00359 "-u", name, "-sbo", sigfile, file,
00360 NULL);
00361 rpmError(RPMERR_EXEC, _("Couldn't exec gpg\n"));
00362 _exit(RPMERR_EXEC);
00363 }
00364
00365 fpipe = fdopen(inpipe[1], "w");
00366 close(inpipe[0]);
00367 fprintf(fpipe, "%s\n", passPhrase);
00368 fclose(fpipe);
00369
00370 (void)waitpid(pid, &status, 0);
00371 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
00372 rpmError(RPMERR_SIGGEN, _("gpg failed\n"));
00373 return 1;
00374 }
00375
00376 if (stat(sigfile, &st)) {
00377
00378 unlink(sigfile);
00379 rpmError(RPMERR_SIGGEN, _("gpg failed to write signature\n"));
00380 return 1;
00381 }
00382
00383 *size = st.st_size;
00384 rpmMessage(RPMMESS_DEBUG, _("GPG sig size: %d\n"), *size);
00385 *sig = xmalloc(*size);
00386
00387 { FD_t fd;
00388 int rc;
00389 fd = Fopen(sigfile, "r.fdio");
00390 rc = timedRead(fd, *sig, *size);
00391 unlink(sigfile);
00392 Fclose(fd);
00393 if (rc != *size) {
00394 free(*sig);
00395 rpmError(RPMERR_SIGGEN, _("unable to read the signature\n"));
00396 return 1;
00397 }
00398 }
00399
00400 rpmMessage(RPMMESS_DEBUG, _("Got %d bytes of GPG sig\n"), *size);
00401
00402 return 0;
00403 }
00404
00405 int rpmAddSignature(Header header, const char * file, int_32 sigTag,
00406 const char *passPhrase)
00407 {
00408 struct stat st;
00409 int_32 size;
00410 byte buf[16];
00411 void *sig;
00412 int ret = -1;
00413
00414 switch (sigTag) {
00415 case RPMSIGTAG_SIZE:
00416 stat(file, &st);
00417 size = st.st_size;
00418 ret = 0;
00419 headerAddEntry(header, RPMSIGTAG_SIZE, RPM_INT32_TYPE, &size, 1);
00420 break;
00421 case RPMSIGTAG_MD5:
00422 ret = mdbinfile(file, buf);
00423 if (ret == 0)
00424 headerAddEntry(header, sigTag, RPM_BIN_TYPE, buf, 16);
00425 break;
00426 case RPMSIGTAG_PGP5:
00427 case RPMSIGTAG_PGP:
00428 rpmMessage(RPMMESS_VERBOSE, _("Generating signature using PGP.\n"));
00429 ret = makePGPSignature(file, &sig, &size, passPhrase);
00430 if (ret == 0)
00431 headerAddEntry(header, sigTag, RPM_BIN_TYPE, sig, size);
00432 break;
00433 case RPMSIGTAG_GPG:
00434 rpmMessage(RPMMESS_VERBOSE, _("Generating signature using GPG.\n"));
00435 ret = makeGPGSignature(file, &sig, &size, passPhrase);
00436 if (ret == 0)
00437 headerAddEntry(header, sigTag, RPM_BIN_TYPE, sig, size);
00438 break;
00439 }
00440
00441 return ret;
00442 }
00443
00444 static rpmVerifySignatureReturn
00445 verifySizeSignature(const char * datafile, int_32 size, char * result)
00446 {
00447 struct stat st;
00448
00449 stat(datafile, &st);
00450 if (size != st.st_size) {
00451 sprintf(result, "Header+Archive size mismatch.\n"
00452 "Expected %d, saw %d.\n",
00453 size, (int)st.st_size);
00454 return RPMSIG_BAD;
00455 }
00456
00457 sprintf(result, "Header+Archive size OK: %d bytes\n", size);
00458 return RPMSIG_OK;
00459 }
00460
00461 #define X(_x) (unsigned)((_x) & 0xff)
00462
00463 static rpmVerifySignatureReturn
00464 verifyMD5Signature(const char * datafile, const byte * sig,
00465 char * result, md5func fn)
00466 {
00467 byte md5sum[16];
00468
00469 fn(datafile, md5sum);
00470 if (memcmp(md5sum, sig, 16)) {
00471 sprintf(result, "MD5 sum mismatch\n"
00472 "Expected: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
00473 "%02x%02x%02x%02x%02x\n"
00474 "Saw : %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
00475 "%02x%02x%02x%02x%02x\n",
00476 X(sig[0]), X(sig[1]), X(sig[2]), X(sig[3]),
00477 X(sig[4]), X(sig[5]), X(sig[6]), X(sig[7]),
00478 X(sig[8]), X(sig[9]), X(sig[10]), X(sig[11]),
00479 X(sig[12]), X(sig[13]), X(sig[14]), X(sig[15]),
00480 X(md5sum[0]), X(md5sum[1]), X(md5sum[2]), X(md5sum[3]),
00481 X(md5sum[4]), X(md5sum[5]), X(md5sum[6]), X(md5sum[7]),
00482 X(md5sum[8]), X(md5sum[9]), X(md5sum[10]), X(md5sum[11]),
00483 X(md5sum[12]), X(md5sum[13]), X(md5sum[14]), X(md5sum[15]) );
00484 return RPMSIG_BAD;
00485 }
00486
00487 sprintf(result, "MD5 sum OK: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
00488 "%02x%02x%02x%02x%02x\n",
00489 X(md5sum[0]), X(md5sum[1]), X(md5sum[2]), X(md5sum[3]),
00490 X(md5sum[4]), X(md5sum[5]), X(md5sum[6]), X(md5sum[7]),
00491 X(md5sum[8]), X(md5sum[9]), X(md5sum[10]), X(md5sum[11]),
00492 X(md5sum[12]), X(md5sum[13]), X(md5sum[14]), X(md5sum[15]) );
00493
00494 return RPMSIG_OK;
00495 }
00496
00497 static rpmVerifySignatureReturn
00498 verifyPGPSignature(const char * datafile, const void * sig, int count,
00499 char * result)
00500 {
00501 int pid, status, outpipe[2];
00502 FD_t sfd;
00503 char *sigfile;
00504 byte buf[BUFSIZ];
00505 FILE *file;
00506 int res = RPMSIG_OK;
00507 const char *path;
00508 pgpVersion pgpVer;
00509
00510
00511 if ((path = rpmDetectPGPVersion(&pgpVer)) == NULL) {
00512 errno = ENOENT;
00513 rpmError(RPMERR_EXEC,
00514 _("Could not run pgp. Use --nopgp to skip PGP checks.\n"));
00515 _exit(RPMERR_EXEC);
00516 }
00517
00518
00519
00520
00521
00522 if (pgpVer == PGP_5)
00523 res = RPMSIG_BAD;
00524
00525
00526 { const char *tmppath = rpmGetPath("%{_tmppath}", NULL);
00527 sigfile = tempnam(tmppath, "rpmsig");
00528 free((void *)tmppath);
00529 }
00530 sfd = Fopen(sigfile, "w.fdio");
00531 (void)Fwrite(sig, sizeof(char), count, sfd);
00532 Fclose(sfd);
00533
00534
00535 outpipe[0] = outpipe[1] = 0;
00536 pipe(outpipe);
00537
00538 if (!(pid = fork())) {
00539 const char *pgp_path = rpmExpand("%{_pgp_path}", NULL);
00540
00541 close(outpipe[0]);
00542 close(STDOUT_FILENO);
00543 dup2(outpipe[1], STDOUT_FILENO);
00544
00545 if (pgp_path && *pgp_path != '%')
00546 dosetenv("PGPPATH", pgp_path, 1);
00547
00548 switch (pgpVer) {
00549 case PGP_5:
00550
00551
00552
00553 { int save_stderr = dup(2);
00554 dup2(1, 2);
00555 execlp(path, "pgpv", "+batchmode=on", "+verbose=0",
00556
00557 "+OutputInformationFD=1",
00558
00559 "+OutputWarningFD=1",
00560 sigfile, "-o", datafile, NULL);
00561
00562 dup2(save_stderr, 2);
00563 close(save_stderr);
00564 } break;
00565 case PGP_2:
00566 execlp(path, "pgp", "+batchmode=on", "+verbose=0",
00567 sigfile, datafile, NULL);
00568 break;
00569 case PGP_UNKNOWN:
00570 case PGP_NOTDETECTED:
00571 break;
00572 }
00573
00574 rpmError(RPMERR_EXEC,
00575 _("Could not run pgp. Use --nopgp to skip PGP checks.\n"));
00576 _exit(RPMERR_EXEC);
00577 }
00578
00579 close(outpipe[1]);
00580 file = fdopen(outpipe[0], "r");
00581 result[0] = '\0';
00582 while (fgets(buf, 1024, file)) {
00583 if (strncmp("File '", buf, 6) &&
00584 strncmp("Text is assu", buf, 12) &&
00585 strncmp("This signature applies to another message", buf, 41) &&
00586 buf[0] != '\n') {
00587 strcat(result, buf);
00588 }
00589 if (!strncmp("WARNING: Can't find the right public key", buf, 40))
00590 res = RPMSIG_NOKEY;
00591 else if (!strncmp("Signature by unknown keyid:", buf, 27))
00592 res = RPMSIG_NOKEY;
00593 else if (!strncmp("WARNING: The signing key is not trusted", buf, 39))
00594 res = RPMSIG_NOTTRUSTED;
00595 else if (!strncmp("Good signature", buf, 14))
00596 res = RPMSIG_OK;
00597 }
00598 fclose(file);
00599
00600 (void)waitpid(pid, &status, 0);
00601 unlink(sigfile);
00602 if (!res && (!WIFEXITED(status) || WEXITSTATUS(status))) {
00603 res = RPMSIG_BAD;
00604 }
00605
00606 return res;
00607 }
00608
00609 static rpmVerifySignatureReturn
00610 verifyGPGSignature(const char * datafile, const void * sig, int count,
00611 char * result)
00612 {
00613 int pid, status, outpipe[2];
00614 FD_t sfd;
00615 char *sigfile;
00616 byte buf[BUFSIZ];
00617 FILE *file;
00618 int res = RPMSIG_OK;
00619
00620
00621 { const char *tmppath = rpmGetPath("%{_tmppath}", NULL);
00622 sigfile = tempnam(tmppath, "rpmsig");
00623 free((void *)tmppath);
00624 }
00625 sfd = Fopen(sigfile, "w.fdio");
00626 (void)Fwrite(sig, sizeof(char), count, sfd);
00627 Fclose(sfd);
00628
00629
00630 outpipe[0] = outpipe[1] = 0;
00631 pipe(outpipe);
00632
00633 if (!(pid = fork())) {
00634 const char *gpg_path = rpmExpand("%{_gpg_path}", NULL);
00635
00636 close(outpipe[0]);
00637
00638 dup2(outpipe[1], STDERR_FILENO);
00639
00640 if (gpg_path && *gpg_path != '%')
00641 dosetenv("GNUPGHOME", gpg_path, 1);
00642
00643 execlp("gpg", "gpg",
00644 "--batch", "--no-verbose",
00645 "--verify", sigfile, datafile,
00646 NULL);
00647 rpmError(RPMERR_EXEC,
00648 _("Could not run gpg. Use --nogpg to skip GPG checks.\n"));
00649 _exit(RPMERR_EXEC);
00650 }
00651
00652 close(outpipe[1]);
00653 file = fdopen(outpipe[0], "r");
00654 result[0] = '\0';
00655 while (fgets(buf, 1024, file)) {
00656 strcat(result, buf);
00657 if (!xstrncasecmp("gpg: Can't check signature: Public key not found", buf, 48)) {
00658 res = RPMSIG_NOKEY;
00659 }
00660 }
00661 fclose(file);
00662
00663 (void)waitpid(pid, &status, 0);
00664 unlink(sigfile);
00665 if (!res && (!WIFEXITED(status) || WEXITSTATUS(status))) {
00666 res = RPMSIG_BAD;
00667 }
00668
00669 return res;
00670 }
00671
00672 static int checkPassPhrase(const char * passPhrase, const int sigTag)
00673 {
00674 int passPhrasePipe[2];
00675 int pid, status;
00676 int fd;
00677
00678 passPhrasePipe[0] = passPhrasePipe[1] = 0;
00679 pipe(passPhrasePipe);
00680 if (!(pid = fork())) {
00681 close(STDIN_FILENO);
00682 close(STDOUT_FILENO);
00683 close(passPhrasePipe[1]);
00684 if (! rpmIsVerbose()) {
00685 close(STDERR_FILENO);
00686 }
00687 if ((fd = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
00688 dup2(fd, STDIN_FILENO);
00689 close(fd);
00690 }
00691 if ((fd = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
00692 dup2(fd, STDOUT_FILENO);
00693 close(fd);
00694 }
00695 dup2(passPhrasePipe[0], 3);
00696
00697 switch (sigTag) {
00698 case RPMSIGTAG_GPG:
00699 { const char *gpg_path = rpmExpand("%{_gpg_path}", NULL);
00700 const char *name = rpmExpand("%{_gpg_name}", NULL);
00701 if (gpg_path && *gpg_path != '%')
00702 dosetenv("GNUPGHOME", gpg_path, 1);
00703 execlp("gpg", "gpg",
00704 "--batch", "--no-verbose", "--passphrase-fd", "3",
00705 "-u", name, "-so", "-",
00706 NULL);
00707 rpmError(RPMERR_EXEC, _("Couldn't exec gpg\n"));
00708 _exit(RPMERR_EXEC);
00709 } break;
00710 case RPMSIGTAG_PGP5:
00711 case RPMSIGTAG_PGP:
00712 { const char *pgp_path = rpmExpand("%{_pgp_path}", NULL);
00713 const char *name = rpmExpand("+myname=\"%{_pgp_name}\"", NULL);
00714 const char *path;
00715 pgpVersion pgpVer;
00716
00717 dosetenv("PGPPASSFD", "3", 1);
00718 if (pgp_path && *pgp_path != '%')
00719 dosetenv("PGPPATH", pgp_path, 1);
00720
00721 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
00722 switch(pgpVer) {
00723 case PGP_2:
00724 execlp(path, "pgp", "+batchmode=on", "+verbose=0",
00725 name, "-sf", NULL);
00726 break;
00727 case PGP_5:
00728 execlp(path,"pgps", "+batchmode=on", "+verbose=0",
00729 name, "-f", NULL);
00730 break;
00731 case PGP_UNKNOWN:
00732 case PGP_NOTDETECTED:
00733 break;
00734 }
00735 }
00736 rpmError(RPMERR_EXEC, _("Couldn't exec pgp\n"));
00737 _exit(RPMERR_EXEC);
00738 } break;
00739 default:
00740 rpmError(RPMERR_SIGGEN, _("Invalid %%_signature spec in macro file\n"));
00741 _exit(RPMERR_SIGGEN);
00742 break;
00743 }
00744 }
00745
00746 close(passPhrasePipe[0]);
00747 (void)write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
00748 (void)write(passPhrasePipe[1], "\n", 1);
00749 close(passPhrasePipe[1]);
00750
00751 (void)waitpid(pid, &status, 0);
00752 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
00753 return 1;
00754 }
00755
00756
00757 return 0;
00758 }
00759
00760 char *rpmGetPassPhrase(const char * prompt, const int sigTag)
00761 {
00762 char *pass;
00763 int aok;
00764
00765 switch (sigTag) {
00766 case RPMSIGTAG_GPG:
00767 { const char *name = rpmExpand("%{_gpg_name}", NULL);
00768 aok = (name && *name != '%');
00769 free((void *)name);
00770 }
00771 if (!aok) {
00772 rpmError(RPMERR_SIGGEN,
00773 _("You must set \"%%_gpg_name\" in your macro file\n"));
00774 return NULL;
00775 }
00776 break;
00777 case RPMSIGTAG_PGP5:
00778 case RPMSIGTAG_PGP:
00779 { const char *name = rpmExpand("%{_pgp_name}", NULL);
00780 aok = (name && *name != '%');
00781 free((void *)name);
00782 }
00783 if (!aok) {
00784 rpmError(RPMERR_SIGGEN,
00785 _("You must set \"%%_pgp_name\" in your macro file\n"));
00786 return NULL;
00787 }
00788 break;
00789 default:
00790
00791
00792
00793 rpmError(RPMERR_SIGGEN, _("Invalid %%_signature spec in macro file\n"));
00794 return NULL;
00795 break;
00796 }
00797
00798 pass = getpass( (prompt ? prompt : "") ) ;
00799
00800 if (checkPassPhrase(pass, sigTag))
00801 return NULL;
00802
00803 return pass;
00804 }
00805
00806 rpmVerifySignatureReturn
00807 rpmVerifySignature(const char * file, int_32 sigTag, const void * sig,
00808 int count, char * result)
00809 {
00810 switch (sigTag) {
00811 case RPMSIGTAG_SIZE:
00812 return verifySizeSignature(file, *(int_32 *)sig, result);
00813 break;
00814 case RPMSIGTAG_MD5:
00815 return verifyMD5Signature(file, sig, result, mdbinfile);
00816 break;
00817 case RPMSIGTAG_LEMD5_1:
00818 case RPMSIGTAG_LEMD5_2:
00819 return verifyMD5Signature(file, sig, result, mdbinfileBroken);
00820 break;
00821 case RPMSIGTAG_PGP5:
00822 case RPMSIGTAG_PGP:
00823 return verifyPGPSignature(file, sig, count, result);
00824 break;
00825 case RPMSIGTAG_GPG:
00826 return verifyGPGSignature(file, sig, count, result);
00827 break;
00828 default:
00829 sprintf(result, "Do not know how to verify sig type %d\n", sigTag);
00830 return RPMSIG_UNKNOWN;
00831 }
00832
00833 return RPMSIG_OK;
00834 }