00001
00005 #include "system.h"
00006
00007 #include "rpmio_internal.h"
00008 #include <rpmlib.h>
00009 #include <rpmmacro.h>
00010 #include "rpmdb.h"
00011
00012 #include "rpmts.h"
00013
00014 #include "misc.h"
00015 #include "legacy.h"
00016 #include "rpmlead.h"
00017 #include "signature.h"
00018 #include "header_internal.h"
00019 #include "debug.h"
00020
00021
00022
00023
00024
00025
00026
00027 #if !defined(__GLIBC__)
00028 char ** environ = NULL;
00029 #endif
00030
00031 int rpmLookupSignatureType(int action)
00032 {
00033
00034 static int disabled = 0;
00035 int rc = 0;
00036
00037 switch (action) {
00038 case RPMLOOKUPSIG_DISABLE:
00039 disabled = -2;
00040 break;
00041 case RPMLOOKUPSIG_ENABLE:
00042 disabled = 0;
00043
00044 case RPMLOOKUPSIG_QUERY:
00045 if (disabled)
00046 break;
00047
00048 { const char *name = rpmExpand("%{?_signature}", NULL);
00049 if (!(name && *name != '\0'))
00050 rc = 0;
00051 else if (!xstrcasecmp(name, "none"))
00052 rc = 0;
00053 else if (!xstrcasecmp(name, "pgp"))
00054 rc = RPMSIGTAG_PGP;
00055 else if (!xstrcasecmp(name, "pgp5"))
00056 rc = RPMSIGTAG_PGP;
00057 else if (!xstrcasecmp(name, "gpg"))
00058 rc = RPMSIGTAG_GPG;
00059 else
00060 rc = -1;
00061 name = _free(name);
00062 } break;
00063
00064 }
00065 return rc;
00066 }
00067
00068
00069
00070
00071 const char * rpmDetectPGPVersion(pgpVersion * pgpVer)
00072 {
00073
00074
00075
00076
00077 static pgpVersion saved_pgp_version = PGP_UNKNOWN;
00078 const char *pgpbin = rpmGetPath("%{?_pgpbin}", NULL);
00079
00080 if (saved_pgp_version == PGP_UNKNOWN) {
00081 char *pgpvbin;
00082 struct stat st;
00083
00084
00085 if (!(pgpbin && pgpbin[0] != '\0')) {
00086 pgpbin = _free(pgpbin);
00087 saved_pgp_version = -1;
00088 return NULL;
00089 }
00090
00091
00092 pgpvbin = (char *)alloca(strlen(pgpbin) + sizeof("v"));
00093 (void)stpcpy(stpcpy(pgpvbin, pgpbin), "v");
00094
00095
00096 if (stat(pgpvbin, &st) == 0)
00097 saved_pgp_version = PGP_5;
00098 else if (stat(pgpbin, &st) == 0)
00099 saved_pgp_version = PGP_2;
00100 else
00101 saved_pgp_version = PGP_NOTDETECTED;
00102 }
00103
00104
00105 if (pgpVer && pgpbin)
00106 *pgpVer = saved_pgp_version;
00107
00108 return pgpbin;
00109 }
00110
00120 static inline rpmRC printSize(FD_t fd, int siglen, int pad, int datalen)
00121
00122
00123 {
00124 struct stat st;
00125
00126 if (fstat(Fileno(fd), &st) < 0)
00127 return RPMRC_FAIL;
00128
00129
00130 rpmMessage(RPMMESS_DEBUG,
00131 _("Expected size: %12d = lead(%d)+sigs(%d)+pad(%d)+data(%d)\n"),
00132 (int)sizeof(struct rpmlead)+siglen+pad+datalen,
00133 (int)sizeof(struct rpmlead), siglen, pad, datalen);
00134
00135 rpmMessage(RPMMESS_DEBUG,
00136 _(" Actual size: %12d\n"), (int)st.st_size);
00137
00138 return RPMRC_OK;
00139 }
00140
00141
00142 static unsigned char header_magic[8] = {
00143 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
00144 };
00145
00146 rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type)
00147 {
00148 int_32 block[4];
00149 int_32 il;
00150 int_32 dl;
00151 int_32 * ei = NULL;
00152 entryInfo pe;
00153 int_32 nb;
00154 indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
00155 entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
00156 Header sigh = NULL;
00157 rpmRC rc = RPMRC_FAIL;
00158 int xx;
00159 int i;
00160
00161 if (sighp)
00162 *sighp = NULL;
00163
00164 if (sig_type != RPMSIGTYPE_HEADERSIG)
00165 goto exit;
00166
00167 if (timedRead(fd, (char *)block, sizeof(block)) != sizeof(block))
00168 goto exit;
00169 if (memcmp(block, header_magic, sizeof(header_magic)))
00170 goto exit;
00171 il = ntohl(block[2]);
00172 if (il < 0 || il > 32)
00173 goto exit;
00174 dl = ntohl(block[3]);
00175 if (dl < 0 || dl > 8192)
00176 goto exit;
00177
00178 nb = (il * sizeof(struct entryInfo_s)) + dl;
00179 ei = xmalloc(sizeof(il) + sizeof(dl) + nb);
00180 ei[0] = htonl(il);
00181 ei[1] = htonl(dl);
00182 pe = (entryInfo) &ei[2];
00183 if (timedRead(fd, (char *)pe, nb) != nb)
00184 goto exit;
00185
00186
00187 memset(info, 0, sizeof(*info));
00188 for (i = 0; i < il; i++) {
00189 xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
00190 if (xx != -1)
00191 goto exit;
00192 }
00193
00194
00195 sigh = headerLoad(ei);
00196 if (sigh == NULL)
00197 goto exit;
00198 sigh->flags |= HEADERFLAG_ALLOCATED;
00199
00200 { int sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
00201 int pad = (8 - (sigSize % 8)) % 8;
00202 int_32 * archSize = NULL;
00203
00204
00205 if (pad && timedRead(fd, (char *)block, pad) != pad)
00206 goto exit;
00207
00208
00209 if (headerGetEntry(sigh, RPMSIGTAG_SIZE, NULL,(void **)&archSize, NULL))
00210 rc = printSize(fd, sigSize, pad, *archSize);
00211 }
00212
00213 exit:
00214 if (rc == RPMRC_OK && sighp && sigh)
00215 *sighp = headerLink(sigh);
00216 sigh = headerFree(sigh);
00217 return rc;
00218 }
00219
00220 int rpmWriteSignature(FD_t fd, Header h)
00221 {
00222 static byte buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
00223 int sigSize, pad;
00224 int rc;
00225
00226 rc = headerWrite(fd, h, HEADER_MAGIC_YES);
00227 if (rc)
00228 return rc;
00229
00230 sigSize = headerSizeof(h, HEADER_MAGIC_YES);
00231 pad = (8 - (sigSize % 8)) % 8;
00232 if (pad) {
00233
00234 if (Fwrite(buf, sizeof(buf[0]), pad, fd) != pad)
00235 rc = 1;
00236
00237 }
00238 rpmMessage(RPMMESS_DEBUG, _("Signature: size(%d)+pad(%d)\n"), sigSize, pad);
00239 return rc;
00240 }
00241
00242 Header rpmNewSignature(void)
00243 {
00244 Header h = headerNew();
00245 return h;
00246 }
00247
00248 Header rpmFreeSignature(Header h)
00249 {
00250 return headerFree(h);
00251 }
00252
00261 static int makePGPSignature(const char * file, byte ** pkt,
00262 int_32 * pktlen, const char * passPhrase)
00263
00264
00265
00266
00267 {
00268 char * sigfile = alloca(1024);
00269 int pid, status;
00270 int inpipe[2];
00271 struct stat st;
00272 const char * cmd;
00273 char *const *av;
00274 int rc;
00275
00276
00277 (void) stpcpy( stpcpy(sigfile, file), ".sig");
00278
00279
00280 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
00281 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
00282
00283 inpipe[0] = inpipe[1] = 0;
00284
00285 (void) pipe(inpipe);
00286
00287
00288 if (!(pid = fork())) {
00289 const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
00290 const char *path;
00291 pgpVersion pgpVer;
00292
00293 (void) close(STDIN_FILENO);
00294 (void) dup2(inpipe[0], 3);
00295 (void) close(inpipe[1]);
00296
00297 (void) dosetenv("PGPPASSFD", "3", 1);
00298
00299 if (pgp_path && *pgp_path != '\0')
00300 (void) dosetenv("PGPPATH", pgp_path, 1);
00301
00302
00303
00304
00305 unsetenv("MALLOC_CHECK_");
00306 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
00307 switch(pgpVer) {
00308 case PGP_2:
00309 cmd = rpmExpand("%{?__pgp_sign_cmd}", NULL);
00310 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00311
00312 if (!rc)
00313 rc = execve(av[0], av+1, environ);
00314
00315 break;
00316 case PGP_5:
00317 cmd = rpmExpand("%{?__pgp5_sign_cmd}", NULL);
00318 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00319
00320 if (!rc)
00321 rc = execve(av[0], av+1, environ);
00322
00323 break;
00324 case PGP_UNKNOWN:
00325 case PGP_NOTDETECTED:
00326 errno = ENOENT;
00327 break;
00328 }
00329 }
00330 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "pgp",
00331 strerror(errno));
00332 _exit(RPMERR_EXEC);
00333 }
00334
00335 delMacro(NULL, "__plaintext_filename");
00336 delMacro(NULL, "__signature_filename");
00337
00338 (void) close(inpipe[0]);
00339 if (passPhrase)
00340 (void) write(inpipe[1], passPhrase, strlen(passPhrase));
00341 (void) write(inpipe[1], "\n", 1);
00342 (void) close(inpipe[1]);
00343
00344 (void)waitpid(pid, &status, 0);
00345 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
00346 rpmError(RPMERR_SIGGEN, _("pgp failed\n"));
00347 return 1;
00348 }
00349
00350 if (stat(sigfile, &st)) {
00351
00352 if (sigfile) (void) unlink(sigfile);
00353 rpmError(RPMERR_SIGGEN, _("pgp failed to write signature\n"));
00354 return 1;
00355 }
00356
00357
00358 *pktlen = st.st_size;
00359 rpmMessage(RPMMESS_DEBUG, _("PGP sig size: %d\n"), *pktlen);
00360 *pkt = xmalloc(*pktlen);
00361
00362
00363
00364 { FD_t fd;
00365
00366 rc = 0;
00367 fd = Fopen(sigfile, "r.fdio");
00368 if (fd != NULL && !Ferror(fd)) {
00369 rc = timedRead(fd, *pkt, *pktlen);
00370 if (sigfile) (void) unlink(sigfile);
00371 (void) Fclose(fd);
00372 }
00373 if (rc != *pktlen) {
00374
00375 *pkt = _free(*pkt);
00376
00377 rpmError(RPMERR_SIGGEN, _("unable to read the signature\n"));
00378 return 1;
00379 }
00380 }
00381
00382 rpmMessage(RPMMESS_DEBUG, _("Got %d bytes of PGP sig\n"), *pktlen);
00383
00384
00385 return 0;
00386 }
00387
00396 static int makeGPGSignature(const char * file, byte ** pkt,
00397 int_32 * pktlen, const char * passPhrase)
00398
00399
00400
00401
00402 {
00403 char * sigfile = alloca(1024);
00404 int pid, status;
00405 int inpipe[2];
00406 FILE * fpipe;
00407 struct stat st;
00408 const char * cmd;
00409 char *const *av;
00410 int rc;
00411
00412
00413 (void) stpcpy( stpcpy(sigfile, file), ".sig");
00414
00415
00416 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
00417 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
00418
00419 inpipe[0] = inpipe[1] = 0;
00420
00421 (void) pipe(inpipe);
00422
00423
00424 if (!(pid = fork())) {
00425 const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
00426
00427 (void) close(STDIN_FILENO);
00428 (void) dup2(inpipe[0], 3);
00429 (void) close(inpipe[1]);
00430
00431
00432 if (gpg_path && *gpg_path != '\0')
00433 (void) dosetenv("GNUPGHOME", gpg_path, 1);
00434
00435
00436 unsetenv("MALLOC_CHECK_");
00437 cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
00438 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00439
00440 if (!rc)
00441 rc = execve(av[0], av+1, environ);
00442
00443
00444 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "gpg",
00445 strerror(errno));
00446 _exit(RPMERR_EXEC);
00447 }
00448
00449 delMacro(NULL, "__plaintext_filename");
00450 delMacro(NULL, "__signature_filename");
00451
00452 fpipe = fdopen(inpipe[1], "w");
00453 (void) close(inpipe[0]);
00454 if (fpipe) {
00455 fprintf(fpipe, "%s\n", (passPhrase ? passPhrase : ""));
00456 (void) fclose(fpipe);
00457 }
00458
00459 (void) waitpid(pid, &status, 0);
00460 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
00461 rpmError(RPMERR_SIGGEN, _("gpg failed\n"));
00462 return 1;
00463 }
00464
00465 if (stat(sigfile, &st)) {
00466
00467 if (sigfile) (void) unlink(sigfile);
00468 rpmError(RPMERR_SIGGEN, _("gpg failed to write signature\n"));
00469 return 1;
00470 }
00471
00472
00473 *pktlen = st.st_size;
00474 rpmMessage(RPMMESS_DEBUG, _("GPG sig size: %d\n"), *pktlen);
00475 *pkt = xmalloc(*pktlen);
00476
00477
00478
00479 { FD_t fd;
00480
00481 rc = 0;
00482 fd = Fopen(sigfile, "r.fdio");
00483 if (fd != NULL && !Ferror(fd)) {
00484 rc = timedRead(fd, *pkt, *pktlen);
00485 if (sigfile) (void) unlink(sigfile);
00486 (void) Fclose(fd);
00487 }
00488 if (rc != *pktlen) {
00489
00490 *pkt = _free(*pkt);
00491
00492 rpmError(RPMERR_SIGGEN, _("unable to read the signature\n"));
00493 return 1;
00494 }
00495 }
00496
00497 rpmMessage(RPMMESS_DEBUG, _("Got %d bytes of GPG sig\n"), *pktlen);
00498
00499
00500 return 0;
00501 }
00502
00511 static int makeHDRSignature(Header sig, const char * file, int_32 sigTag,
00512 const char * passPhrase)
00513
00514
00515 {
00516 Header h = NULL;
00517 FD_t fd = NULL;
00518 byte * pkt;
00519 int_32 pktlen;
00520 const char * fn = NULL;
00521 const char * SHA1 = NULL;
00522 int ret = -1;
00523
00524 switch (sigTag) {
00525 case RPMSIGTAG_SIZE:
00526 case RPMSIGTAG_MD5:
00527 case RPMSIGTAG_PGP5:
00528 case RPMSIGTAG_PGP:
00529 case RPMSIGTAG_GPG:
00530 goto exit;
00531 break;
00532 case RPMSIGTAG_SHA1:
00533 fd = Fopen(file, "r.fdio");
00534 if (fd == NULL || Ferror(fd))
00535 goto exit;
00536 h = headerRead(fd, HEADER_MAGIC_YES);
00537 if (h == NULL)
00538 goto exit;
00539 (void) Fclose(fd); fd = NULL;
00540
00541 if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
00542 DIGEST_CTX ctx;
00543 void * uh;
00544 int_32 uht, uhc;
00545
00546 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)
00547 || uh == NULL)
00548 {
00549 h = headerFree(h);
00550 goto exit;
00551 }
00552 ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00553 (void) rpmDigestUpdate(ctx, header_magic, sizeof(header_magic));
00554 (void) rpmDigestUpdate(ctx, uh, uhc);
00555 (void) rpmDigestFinal(ctx, (void **)&SHA1, NULL, 1);
00556 uh = headerFreeData(uh, uht);
00557 }
00558 h = headerFree(h);
00559
00560 if (SHA1 == NULL)
00561 goto exit;
00562 if (!headerAddEntry(sig, RPMSIGTAG_SHA1, RPM_STRING_TYPE, SHA1, 1))
00563 goto exit;
00564 ret = 0;
00565 break;
00566 case RPMSIGTAG_DSA:
00567 fd = Fopen(file, "r.fdio");
00568 if (fd == NULL || Ferror(fd))
00569 goto exit;
00570 h = headerRead(fd, HEADER_MAGIC_YES);
00571 if (h == NULL)
00572 goto exit;
00573 (void) Fclose(fd); fd = NULL;
00574 if (makeTempFile(NULL, &fn, &fd))
00575 goto exit;
00576 if (headerWrite(fd, h, HEADER_MAGIC_YES))
00577 goto exit;
00578 (void) Fclose(fd); fd = NULL;
00579 if (makeGPGSignature(fn, &pkt, &pktlen, passPhrase)
00580 || !headerAddEntry(sig, sigTag, RPM_BIN_TYPE, pkt, pktlen))
00581 goto exit;
00582 ret = 0;
00583 break;
00584 case RPMSIGTAG_RSA:
00585 fd = Fopen(file, "r.fdio");
00586 if (fd == NULL || Ferror(fd))
00587 goto exit;
00588 h = headerRead(fd, HEADER_MAGIC_YES);
00589 if (h == NULL)
00590 goto exit;
00591 (void) Fclose(fd); fd = NULL;
00592 if (makeTempFile(NULL, &fn, &fd))
00593 goto exit;
00594 if (headerWrite(fd, h, HEADER_MAGIC_YES))
00595 goto exit;
00596 (void) Fclose(fd); fd = NULL;
00597 if (makePGPSignature(fn, &pkt, &pktlen, passPhrase)
00598 || !headerAddEntry(sig, sigTag, RPM_BIN_TYPE, pkt, pktlen))
00599 goto exit;
00600 ret = 0;
00601 break;
00602 }
00603
00604 exit:
00605 if (fn) {
00606 (void) unlink(fn);
00607 fn = _free(fn);
00608 }
00609 SHA1 = _free(SHA1);
00610 h = headerFree(h);
00611 if (fd) (void) Fclose(fd);
00612 return ret;
00613 }
00614
00615 int rpmAddSignature(Header sig, const char * file, int_32 sigTag,
00616 const char * passPhrase)
00617 {
00618 struct stat st;
00619 byte * pkt;
00620 int_32 pktlen;
00621 int ret = -1;
00622
00623 switch (sigTag) {
00624 case RPMSIGTAG_SIZE:
00625 if (stat(file, &st) != 0)
00626 break;
00627 pktlen = st.st_size;
00628 if (!headerAddEntry(sig, sigTag, RPM_INT32_TYPE, &pktlen, 1))
00629 break;
00630 ret = 0;
00631 break;
00632 case RPMSIGTAG_MD5:
00633 pktlen = 16;
00634 pkt = xcalloc(1, pktlen);
00635 if (domd5(file, pkt, 0, NULL)
00636 || !headerAddEntry(sig, sigTag, RPM_BIN_TYPE, pkt, pktlen))
00637 break;
00638 ret = 0;
00639 break;
00640 case RPMSIGTAG_PGP5:
00641 case RPMSIGTAG_PGP:
00642 if (makePGPSignature(file, &pkt, &pktlen, passPhrase)
00643 || !headerAddEntry(sig, sigTag, RPM_BIN_TYPE, pkt, pktlen))
00644 break;
00645 #ifdef NOTYET
00646
00647 ret = makeHDRSignature(sig, file, RPMSIGTAG_RSA, passPhrase);
00648 #endif
00649 ret = 0;
00650 break;
00651 case RPMSIGTAG_GPG:
00652 if (makeGPGSignature(file, &pkt, &pktlen, passPhrase)
00653 || !headerAddEntry(sig, sigTag, RPM_BIN_TYPE, pkt, pktlen))
00654 break;
00655
00656 ret = makeHDRSignature(sig, file, RPMSIGTAG_DSA, passPhrase);
00657 break;
00658 case RPMSIGTAG_RSA:
00659 case RPMSIGTAG_DSA:
00660 case RPMSIGTAG_SHA1:
00661 ret = makeHDRSignature(sig, file, sigTag, passPhrase);
00662 break;
00663 }
00664
00665 return ret;
00666 }
00667
00668 static int checkPassPhrase(const char * passPhrase, const int sigTag)
00669
00670
00671 {
00672 int passPhrasePipe[2];
00673 int pid, status;
00674 int rc;
00675 int xx;
00676
00677 passPhrasePipe[0] = passPhrasePipe[1] = 0;
00678
00679 xx = pipe(passPhrasePipe);
00680
00681 if (!(pid = fork())) {
00682 const char * cmd;
00683 char *const *av;
00684 int fdno;
00685
00686 xx = close(STDIN_FILENO);
00687 xx = close(STDOUT_FILENO);
00688 xx = close(passPhrasePipe[1]);
00689 if (! rpmIsVerbose())
00690 xx = close(STDERR_FILENO);
00691 if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
00692 xx = dup2(fdno, STDIN_FILENO);
00693 xx = close(fdno);
00694 }
00695 if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
00696 xx = dup2(fdno, STDOUT_FILENO);
00697 xx = close(fdno);
00698 }
00699 xx = dup2(passPhrasePipe[0], 3);
00700
00701 unsetenv("MALLOC_CHECK_");
00702 switch (sigTag) {
00703 case RPMSIGTAG_DSA:
00704 case RPMSIGTAG_GPG:
00705 { const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
00706
00707
00708 if (gpg_path && *gpg_path != '\0')
00709 (void) dosetenv("GNUPGHOME", gpg_path, 1);
00710
00711
00712 cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
00713 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00714
00715 if (!rc)
00716 rc = execve(av[0], av+1, environ);
00717
00718
00719 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "gpg",
00720 strerror(errno));
00721 } break;
00722 case RPMSIGTAG_RSA:
00723 case RPMSIGTAG_PGP5:
00724 case RPMSIGTAG_PGP:
00725 { const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
00726 const char *path;
00727 pgpVersion pgpVer;
00728
00729 (void) dosetenv("PGPPASSFD", "3", 1);
00730
00731 if (pgp_path && *pgp_path != '\0')
00732 xx = dosetenv("PGPPATH", pgp_path, 1);
00733
00734
00735 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
00736 switch(pgpVer) {
00737 case PGP_2:
00738 cmd = rpmExpand("%{?__pgp_check_password_cmd}", NULL);
00739 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00740
00741 if (!rc)
00742 rc = execve(av[0], av+1, environ);
00743
00744 break;
00745 case PGP_5:
00746 cmd = rpmExpand("%{?__pgp5_check_password_cmd}", NULL);
00747 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00748
00749 if (!rc)
00750 rc = execve(av[0], av+1, environ);
00751
00752 break;
00753 case PGP_UNKNOWN:
00754 case PGP_NOTDETECTED:
00755 break;
00756 }
00757 }
00758 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "pgp",
00759 strerror(errno));
00760 _exit(RPMERR_EXEC);
00761 } break;
00762 default:
00763 rpmError(RPMERR_SIGGEN, _("Invalid %%_signature spec in macro file\n"));
00764 _exit(RPMERR_SIGGEN);
00765 break;
00766 }
00767 }
00768
00769 xx = close(passPhrasePipe[0]);
00770 xx = write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
00771 xx = write(passPhrasePipe[1], "\n", 1);
00772 xx = close(passPhrasePipe[1]);
00773
00774 (void) waitpid(pid, &status, 0);
00775
00776 return ((!WIFEXITED(status) || WEXITSTATUS(status)) ? 1 : 0);
00777 }
00778
00779 char * rpmGetPassPhrase(const char * prompt, const int sigTag)
00780 {
00781 char *pass;
00782 int aok;
00783
00784 switch (sigTag) {
00785 case RPMSIGTAG_DSA:
00786 case RPMSIGTAG_GPG:
00787
00788 { const char *name = rpmExpand("%{?_gpg_name}", NULL);
00789 aok = (name && *name != '\0');
00790 name = _free(name);
00791 }
00792
00793 if (!aok) {
00794 rpmError(RPMERR_SIGGEN,
00795 _("You must set \"%%_gpg_name\" in your macro file\n"));
00796 return NULL;
00797 }
00798 break;
00799 case RPMSIGTAG_RSA:
00800 case RPMSIGTAG_PGP5:
00801 case RPMSIGTAG_PGP:
00802
00803 { const char *name = rpmExpand("%{?_pgp_name}", NULL);
00804 aok = (name && *name != '\0');
00805 name = _free(name);
00806 }
00807
00808 if (!aok) {
00809 rpmError(RPMERR_SIGGEN,
00810 _("You must set \"%%_pgp_name\" in your macro file\n"));
00811 return NULL;
00812 }
00813 break;
00814 default:
00815
00816
00817
00818 rpmError(RPMERR_SIGGEN, _("Invalid %%_signature spec in macro file\n"));
00819 return NULL;
00820 break;
00821 }
00822
00823
00824 pass = getpass( (prompt ? prompt : "") ) ;
00825
00826
00827 if (checkPassPhrase(pass, sigTag))
00828 return NULL;
00829
00830 return pass;
00831 }
00832
00833 static const char * rpmSigString(rpmRC res)
00834
00835 {
00836 const char * str;
00837 switch (res) {
00838 case RPMRC_OK: str = "OK"; break;
00839 case RPMRC_FAIL: str = "BAD"; break;
00840 case RPMRC_NOKEY: str = "NOKEY"; break;
00841 case RPMRC_NOTTRUSTED: str = "NOTRUSTED"; break;
00842 default:
00843 case RPMRC_NOTFOUND: str = "UNKNOWN"; break;
00844 }
00845 return str;
00846 }
00847
00848
00849 static rpmRC
00850 verifySizeSignature(const rpmts ts, char * t)
00851
00852 {
00853 const void * sig = rpmtsSig(ts);
00854 pgpDig dig = rpmtsDig(ts);
00855 rpmRC res;
00856 int_32 size = 0x7fffffff;
00857
00858 *t = '\0';
00859 t = stpcpy(t, _("Header+Payload size: "));
00860
00861 if (sig == NULL || dig == NULL || dig->nbytes == 0) {
00862 res = RPMRC_NOKEY;
00863 t = stpcpy(t, rpmSigString(res));
00864 goto exit;
00865 }
00866
00867 memcpy(&size, sig, sizeof(size));
00868
00869 if (size != dig->nbytes) {
00870 res = RPMRC_FAIL;
00871 t = stpcpy(t, rpmSigString(res));
00872 sprintf(t, " Expected(%d) != (%d)\n", size, dig->nbytes);
00873 } else {
00874 res = RPMRC_OK;
00875 t = stpcpy(t, rpmSigString(res));
00876 sprintf(t, " (%d)", dig->nbytes);
00877 }
00878
00879 exit:
00880 t = stpcpy(t, "\n");
00881 return res;
00882 }
00883
00884
00885
00886 static rpmRC
00887 verifyMD5Signature(const rpmts ts, char * t,
00888 DIGEST_CTX md5ctx)
00889
00890 {
00891 const void * sig = rpmtsSig(ts);
00892 int_32 siglen = rpmtsSiglen(ts);
00893 pgpDig dig = rpmtsDig(ts);
00894 rpmRC res;
00895 byte * md5sum = NULL;
00896 size_t md5len = 0;
00897
00898 *t = '\0';
00899 t = stpcpy(t, _("MD5 digest: "));
00900
00901 if (md5ctx == NULL || sig == NULL || dig == NULL) {
00902 res = RPMRC_NOKEY;
00903 t = stpcpy(t, rpmSigString(res));
00904 goto exit;
00905 }
00906
00907 (void) rpmDigestFinal(rpmDigestDup(md5ctx),
00908 (void **)&md5sum, &md5len, 0);
00909
00910 if (md5len != siglen || memcmp(md5sum, sig, md5len)) {
00911 res = RPMRC_FAIL;
00912 t = stpcpy(t, rpmSigString(res));
00913 t = stpcpy(t, " Expected(");
00914 (void) pgpHexCvt(t, sig, siglen);
00915 t += strlen(t);
00916 t = stpcpy(t, ") != (");
00917 } else {
00918 res = RPMRC_OK;
00919 t = stpcpy(t, rpmSigString(res));
00920 t = stpcpy(t, " (");
00921 }
00922 (void) pgpHexCvt(t, md5sum, md5len);
00923 t += strlen(t);
00924 t = stpcpy(t, ")");
00925
00926 exit:
00927 md5sum = _free(md5sum);
00928 t = stpcpy(t, "\n");
00929 return res;
00930 }
00931
00932
00933
00941 static rpmRC
00942 verifySHA1Signature(const rpmts ts, char * t,
00943 DIGEST_CTX sha1ctx)
00944
00945 {
00946 const void * sig = rpmtsSig(ts);
00947 #ifdef NOTYET
00948 int_32 siglen = rpmtsSiglen(ts);
00949 #endif
00950 pgpDig dig = rpmtsDig(ts);
00951 rpmRC res;
00952 const char * SHA1 = NULL;
00953
00954 *t = '\0';
00955 t = stpcpy(t, _("Header SHA1 digest: "));
00956
00957 if (sha1ctx == NULL || sig == NULL || dig == NULL) {
00958 res = RPMRC_NOKEY;
00959 t = stpcpy(t, rpmSigString(res));
00960 goto exit;
00961 }
00962
00963 (void) rpmDigestFinal(rpmDigestDup(sha1ctx),
00964 (void **)&SHA1, NULL, 1);
00965
00966 if (SHA1 == NULL || strlen(SHA1) != strlen(sig) || strcmp(SHA1, sig)) {
00967 res = RPMRC_FAIL;
00968 t = stpcpy(t, rpmSigString(res));
00969 t = stpcpy(t, " Expected(");
00970 t = stpcpy(t, sig);
00971 t = stpcpy(t, ") != (");
00972 } else {
00973 res = RPMRC_OK;
00974 t = stpcpy(t, rpmSigString(res));
00975 t = stpcpy(t, " (");
00976 }
00977 if (SHA1)
00978 t = stpcpy(t, SHA1);
00979 t = stpcpy(t, ")");
00980
00981 exit:
00982 SHA1 = _free(SHA1);
00983 t = stpcpy(t, "\n");
00984 return res;
00985 }
00986
00987
00993 static inline unsigned char nibble(char c)
00994
00995 {
00996 if (c >= '0' && c <= '9')
00997 return (c - '0');
00998 if (c >= 'A' && c <= 'F')
00999 return (c - 'A') + 10;
01000 if (c >= 'a' && c <= 'f')
01001 return (c - 'a') + 10;
01002 return 0;
01003 }
01004
01005
01013 static rpmRC
01014 verifyPGPSignature(rpmts ts, char * t,
01015 DIGEST_CTX md5ctx)
01016
01017
01018 {
01019 const void * sig = rpmtsSig(ts);
01020 #ifdef NOTYET
01021 int_32 siglen = rpmtsSiglen(ts);
01022 #endif
01023 int_32 sigtag = rpmtsSigtag(ts);
01024 pgpDig dig = rpmtsDig(ts);
01025 pgpDigParams sigp = rpmtsSignature(ts);
01026 rpmRC res;
01027 int xx;
01028
01029 *t = '\0';
01030 t = stpcpy(t, _("V3 RSA/MD5 signature: "));
01031
01032 if (md5ctx == NULL || sig == NULL || dig == NULL || sigp == NULL) {
01033 res = RPMRC_NOKEY;
01034 goto exit;
01035 }
01036
01037
01038 if (!(sigtag == RPMSIGTAG_PGP
01039 && sigp->pubkey_algo == PGPPUBKEYALGO_RSA
01040 && sigp->hash_algo == PGPHASHALGO_MD5))
01041 {
01042 res = RPMRC_NOKEY;
01043 goto exit;
01044 }
01045
01046 { DIGEST_CTX ctx = rpmDigestDup(md5ctx);
01047 byte signhash16[2];
01048 const char * s;
01049
01050 if (sigp->hash != NULL)
01051 xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
01052
01053 #ifdef NOTYET
01054 if (sigp->sigtype == 4) {
01055 int nb = dig->nbytes + sigp->hashlen;
01056 byte trailer[6];
01057 nb = htonl(nb);
01058 trailer[0] = 0x4;
01059 trailer[1] = 0xff;
01060 memcpy(trailer+2, &nb, sizeof(nb));
01061 xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
01062 }
01063 #endif
01064
01065 xx = rpmDigestFinal(ctx, (void **)&dig->md5, &dig->md5len, 1);
01066
01067
01068 s = dig->md5;
01069 signhash16[0] = (nibble(s[0]) << 4) | nibble(s[1]);
01070 signhash16[1] = (nibble(s[2]) << 4) | nibble(s[3]);
01071 if (memcmp(signhash16, sigp->signhash16, sizeof(signhash16))) {
01072 res = RPMRC_FAIL;
01073 goto exit;
01074 }
01075
01076 }
01077
01078 { const char * prefix = "3020300c06082a864886f70d020505000410";
01079 unsigned int nbits = 1024;
01080 unsigned int nb = (nbits + 7) >> 3;
01081 const char * hexstr;
01082 char * tt;
01083
01084 hexstr = tt = xmalloc(2 * nb + 1);
01085 memset(tt, 'f', (2 * nb));
01086 tt[0] = '0'; tt[1] = '0';
01087 tt[2] = '0'; tt[3] = '1';
01088 tt += (2 * nb) - strlen(prefix) - strlen(dig->md5) - 2;
01089 *tt++ = '0'; *tt++ = '0';
01090 tt = stpcpy(tt, prefix);
01091 tt = stpcpy(tt, dig->md5);
01092
01093 mp32nzero(&dig->rsahm); mp32nsethex(&dig->rsahm, hexstr);
01094
01095 hexstr = _free(hexstr);
01096
01097 }
01098
01099
01100 res = rpmtsFindPubkey(ts);
01101 if (res != RPMRC_OK)
01102 goto exit;
01103
01104 if (rsavrfy(&dig->rsa_pk, &dig->rsahm, &dig->c))
01105 res = RPMRC_OK;
01106 else
01107 res = RPMRC_FAIL;
01108
01109 exit:
01110 t = stpcpy(t, rpmSigString(res));
01111 if (sigp != NULL) {
01112 t = stpcpy(t, ", key ID ");
01113 (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4);
01114 t += strlen(t);
01115 }
01116 t = stpcpy(t, "\n");
01117 return res;
01118 }
01119
01120
01128
01129 static rpmRC
01130 verifyGPGSignature(rpmts ts, char * t,
01131 DIGEST_CTX sha1ctx)
01132
01133
01134 {
01135 const void * sig = rpmtsSig(ts);
01136 #ifdef NOTYET
01137 int_32 siglen = rpmtsSiglen(ts);
01138 #endif
01139 int_32 sigtag = rpmtsSigtag(ts);
01140 pgpDig dig = rpmtsDig(ts);
01141 pgpDigParams sigp = rpmtsSignature(ts);
01142 rpmRC res;
01143 int xx;
01144
01145 *t = '\0';
01146 if (dig != NULL && dig->hdrsha1ctx == sha1ctx)
01147 t = stpcpy(t, _("Header "));
01148 t = stpcpy(t, _("V3 DSA signature: "));
01149
01150 if (sha1ctx == NULL || sig == NULL || dig == NULL || sigp == NULL) {
01151 res = RPMRC_NOKEY;
01152 goto exit;
01153 }
01154
01155
01156 if (!((sigtag == RPMSIGTAG_GPG || sigtag == RPMSIGTAG_DSA)
01157 && sigp->pubkey_algo == PGPPUBKEYALGO_DSA
01158 && sigp->hash_algo == PGPHASHALGO_SHA1))
01159 {
01160 res = RPMRC_NOKEY;
01161 goto exit;
01162 }
01163
01164 { DIGEST_CTX ctx = rpmDigestDup(sha1ctx);
01165 byte signhash16[2];
01166
01167 if (sigp->hash != NULL)
01168 xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
01169
01170 #ifdef NOTYET
01171 if (sigp->sigtype == 4) {
01172 int nb = dig->nbytes + sigp->hashlen;
01173 byte trailer[6];
01174 nb = htonl(nb);
01175 trailer[0] = 0x4;
01176 trailer[1] = 0xff;
01177 memcpy(trailer+2, &nb, sizeof(nb));
01178 xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
01179 }
01180 #endif
01181 xx = rpmDigestFinal(ctx, (void **)&dig->sha1, &dig->sha1len, 1);
01182
01183 mp32nzero(&dig->hm); mp32nsethex(&dig->hm, dig->sha1);
01184
01185
01186 signhash16[0] = (*dig->hm.data >> 24) & 0xff;
01187 signhash16[1] = (*dig->hm.data >> 16) & 0xff;
01188 if (memcmp(signhash16, sigp->signhash16, sizeof(signhash16))) {
01189 res = RPMRC_FAIL;
01190 goto exit;
01191 }
01192 }
01193
01194
01195 res = rpmtsFindPubkey(ts);
01196 if (res != RPMRC_OK)
01197 goto exit;
01198
01199 if (dsavrfy(&dig->p, &dig->q, &dig->g,
01200 &dig->hm, &dig->y, &dig->r, &dig->s))
01201 res = RPMRC_OK;
01202 else
01203 res = RPMRC_FAIL;
01204
01205 exit:
01206 t = stpcpy(t, rpmSigString(res));
01207 if (sigp != NULL) {
01208 t = stpcpy(t, ", key ID ");
01209 (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4);
01210 t += strlen(t);
01211 }
01212 t = stpcpy(t, "\n");
01213 return res;
01214 }
01215
01216
01217 rpmRC
01218 rpmVerifySignature(const rpmts ts, char * result)
01219 {
01220 const void * sig = rpmtsSig(ts);
01221 int_32 siglen = rpmtsSiglen(ts);
01222 int_32 sigtag = rpmtsSigtag(ts);
01223 pgpDig dig = rpmtsDig(ts);
01224 rpmRC res;
01225
01226 if (sig == NULL || siglen <= 0 || dig == NULL) {
01227 sprintf(result, _("Verify signature: BAD PARAMETERS\n"));
01228 return RPMRC_NOTFOUND;
01229 }
01230
01231 switch (sigtag) {
01232 case RPMSIGTAG_SIZE:
01233 res = verifySizeSignature(ts, result);
01234 break;
01235 case RPMSIGTAG_MD5:
01236 res = verifyMD5Signature(ts, result, dig->md5ctx);
01237 break;
01238 case RPMSIGTAG_SHA1:
01239 res = verifySHA1Signature(ts, result, dig->hdrsha1ctx);
01240 break;
01241 case RPMSIGTAG_RSA:
01242 case RPMSIGTAG_PGP5:
01243 case RPMSIGTAG_PGP:
01244 res = verifyPGPSignature(ts, result, dig->md5ctx);
01245 break;
01246 case RPMSIGTAG_DSA:
01247 res = verifyGPGSignature(ts, result, dig->hdrsha1ctx);
01248 break;
01249 case RPMSIGTAG_GPG:
01250 res = verifyGPGSignature(ts, result, dig->sha1ctx);
01251 break;
01252 case RPMSIGTAG_LEMD5_1:
01253 case RPMSIGTAG_LEMD5_2:
01254 sprintf(result, _("Broken MD5 digest: UNSUPPORTED\n"));
01255 res = RPMRC_NOTFOUND;
01256 break;
01257 default:
01258 sprintf(result, _("Signature: UNKNOWN (%d)\n"), sigtag);
01259 res = RPMRC_NOTFOUND;
01260 break;
01261 }
01262 return res;
01263 }