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