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