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