00001
00005 #include "system.h"
00006
00007 #include <rpmio.h>
00008 #include <rpmurl.h>
00009 #include <rpmcb.h>
00010 #define _RPMPGP_INTERNAL
00011 #include <rpmpgp.h>
00012 #include <rpmmacro.h>
00013 #include <rpmku.h>
00014
00015 #include <rpmtag.h>
00016 #include "rpmdb.h"
00017 #include <pkgio.h>
00018 #include "legacy.h"
00019 #include "signature.h"
00020
00021 #include "debug.h"
00022
00023
00024
00025
00026
00027
00028
00029 int rpmTempFile(const char * prefix, const char ** fnptr, void * fdptr)
00030 {
00031 const char * tpmacro = "%{?_tmppath}%{!?_tmppath:/var/tmp/}";
00032 const char * tempfn = NULL;
00033 const char * tfn = NULL;
00034 static int _initialized = 0;
00035 int temput;
00036 FD_t fd = NULL;
00037 unsigned int ran;
00038
00039 if (!prefix) prefix = "";
00040
00041
00042 if (!_initialized) {
00043 _initialized = 1;
00044 tempfn = rpmGenPath(prefix, tpmacro, NULL);
00045 if (rpmioMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1))
00046 goto errxit;
00047 }
00048
00049
00050 ran = (unsigned) time(NULL);
00051 srand(ran);
00052 ran = rand() % 100000;
00053
00054
00055
00056 do {
00057 char tfnbuf[64];
00058 #ifndef NOTYET
00059 sprintf(tfnbuf, "rpm-tmp.%u", ran++);
00060 tempfn = _free(tempfn);
00061 tempfn = rpmGenPath(prefix, tpmacro, tfnbuf);
00062 #else
00063 strcpy(tfnbuf, "rpm-tmp.XXXXXX");
00064 tempfn = _free(tempfn);
00065 tempfn = rpmGenPath(prefix, tpmacro, mktemp(tfnbuf));
00066 #endif
00067
00068 temput = urlPath(tempfn, &tfn);
00069 if (*tfn == '\0') goto errxit;
00070
00071 switch (temput) {
00072 case URL_IS_DASH:
00073 case URL_IS_HKP:
00074 goto errxit;
00075 break;
00076 case URL_IS_HTTPS:
00077 case URL_IS_HTTP:
00078 case URL_IS_FTP:
00079 default:
00080 break;
00081 }
00082
00083 fd = Fopen(tempfn, "w+x.fdio");
00084
00085 } while ((fd == NULL || Ferror(fd)) && errno == EEXIST);
00086
00087 if (fd == NULL || Ferror(fd)) {
00088 rpmlog(RPMLOG_ERR, _("error creating temporary file %s\n"), tempfn);
00089 goto errxit;
00090 }
00091
00092 switch(temput) {
00093 case URL_IS_PATH:
00094 case URL_IS_UNKNOWN:
00095 { struct stat sb, sb2;
00096 if (!stat(tfn, &sb) && S_ISLNK(sb.st_mode)) {
00097 rpmlog(RPMLOG_ERR, _("error creating temporary file %s\n"), tfn);
00098 goto errxit;
00099 }
00100
00101 if (sb.st_nlink != 1) {
00102 rpmlog(RPMLOG_ERR, _("error creating temporary file %s\n"), tfn);
00103 goto errxit;
00104 }
00105
00106 if (fstat(Fileno(fd), &sb2) == 0) {
00107 if (sb2.st_ino != sb.st_ino || sb2.st_dev != sb.st_dev) {
00108 rpmlog(RPMLOG_ERR, _("error creating temporary file %s\n"), tfn);
00109 goto errxit;
00110 }
00111 }
00112 } break;
00113 default:
00114 break;
00115 }
00116
00117 if (fnptr)
00118 *fnptr = tempfn;
00119 else
00120 tempfn = _free(tempfn);
00121 if (fdptr)
00122 *(FD_t *)fdptr = fd;
00123
00124 return 0;
00125
00126 errxit:
00127 tempfn = _free(tempfn);
00128 if (fnptr)
00129 *fnptr = NULL;
00130
00131 if (fd != NULL) (void) Fclose(fd);
00132
00133 return 1;
00134 }
00135
00136
00146 static int makeGPGSignature(const char * file, rpmSigTag * sigTagp,
00147 rpmuint8_t ** pktp, rpmuint32_t * pktlenp,
00148 const char * passPhrase)
00149
00150
00151
00152
00153 {
00154 char * sigfile = alloca(strlen(file)+sizeof(".sig"));
00155 pid_t pid;
00156 int status;
00157 int inpipe[2];
00158 FILE * fpipe;
00159 struct stat st;
00160 const char * cmd;
00161 char *const *av;
00162 pgpDig dig = NULL;
00163 pgpDigParams sigp = NULL;
00164 const char * pw = NULL;
00165 int rc;
00166
00167 (void) stpcpy( stpcpy(sigfile, file), ".sig");
00168
00169 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
00170 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
00171
00172 inpipe[0] = inpipe[1] = 0;
00173 if (pipe(inpipe) < 0) {
00174 rpmlog(RPMLOG_ERR, _("Couldn't create pipe for signing: %m"));
00175 return 1;
00176 }
00177
00178 if (!(pid = fork())) {
00179 const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
00180
00181 (void) dup2(inpipe[0], 3);
00182 (void) close(inpipe[1]);
00183
00184 if (gpg_path && *gpg_path != '\0')
00185 (void) setenv("GNUPGHOME", gpg_path, 1);
00186
00187 unsetenv("MALLOC_CHECK_");
00188 cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
00189 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00190 if (!rc)
00191 rc = execve(av[0], av+1, environ);
00192
00193 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
00194 strerror(errno));
00195 _exit(EXIT_FAILURE);
00196 }
00197
00198 delMacro(NULL, "__plaintext_filename");
00199 delMacro(NULL, "__signature_filename");
00200
00201 pw = rpmkuPassPhrase(passPhrase);
00202 if (pw == NULL) {
00203 rpmlog(RPMLOG_ERR, _("Failed rpmkuPassPhrase(passPhrase): %s\n"),
00204 strerror(errno));
00205 return 1;
00206 }
00207
00208 fpipe = fdopen(inpipe[1], "w");
00209 (void) close(inpipe[0]);
00210 if (fpipe) {
00211 fprintf(fpipe, "%s\n", (pw ? pw : ""));
00212 (void) fclose(fpipe);
00213 }
00214
00215 if (pw != NULL) {
00216 (void) memset((void *)pw, 0, strlen(pw));
00217 pw = _free(pw);
00218 }
00219
00220
00221 (void) waitpid(pid, &status, 0);
00222
00223 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
00224 rpmlog(RPMLOG_ERR, _("gpg exec failed (%d)\n"), WEXITSTATUS(status));
00225 return 1;
00226 }
00227
00228 if (Stat(sigfile, &st)) {
00229
00230 if (sigfile) (void) Unlink(sigfile);
00231 rpmlog(RPMLOG_ERR, _("gpg failed to write signature\n"));
00232 return 1;
00233 }
00234
00235 *pktlenp = (rpmuint32_t)st.st_size;
00236 rpmlog(RPMLOG_DEBUG, D_("GPG sig size: %u\n"), (unsigned)*pktlenp);
00237 *pktp = xmalloc(*pktlenp);
00238
00239 { FD_t fd;
00240
00241 rc = 0;
00242 fd = Fopen(sigfile, "r.ufdio");
00243 if (fd != NULL && !Ferror(fd)) {
00244 rc = (int) Fread(*pktp, sizeof((*pktp)[0]), *pktlenp, fd);
00245 if (sigfile) (void) Unlink(sigfile);
00246 (void) Fclose(fd);
00247 }
00248 if ((rpmuint32_t)rc != *pktlenp) {
00249 *pktp = _free(*pktp);
00250 rpmlog(RPMLOG_ERR, _("unable to read the signature\n"));
00251 return 1;
00252 }
00253 }
00254
00255 rpmlog(RPMLOG_DEBUG, D_("Got %u bytes of GPG sig\n"), (unsigned)*pktlenp);
00256
00257
00258 dig = pgpDigNew(0);
00259
00260 (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
00261 sigp = pgpGetSignature(dig);
00262
00263
00264 switch (*sigTagp) {
00265 default:
00266 assert(0);
00267 break;
00268 case RPMSIGTAG_SIZE:
00269 case RPMSIGTAG_MD5:
00270 case RPMSIGTAG_SHA1:
00271 break;
00272 case RPMSIGTAG_DSA:
00273
00274 if (sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA)
00275 *sigTagp = RPMSIGTAG_RSA;
00276 break;
00277 case RPMSIGTAG_RSA:
00278 if (sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_DSA)
00279 *sigTagp = RPMSIGTAG_DSA;
00280 break;
00281 }
00282
00283 dig = pgpDigFree(dig, "makeGPGSignature");
00284
00285 return 0;
00286 }
00287
00296
00297 static int makeHDRSignature(Header sigh, const char * file, rpmSigTag sigTag,
00298 const char * passPhrase)
00299
00300
00301 {
00302 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00303 Header h = NULL;
00304 FD_t fd = NULL;
00305 rpmuint8_t * pkt;
00306 rpmuint32_t pktlen;
00307 const char * fn = NULL;
00308 const char * msg;
00309 rpmRC rc;
00310 int ret = -1;
00311 int xx;
00312
00313 switch (sigTag) {
00314 default:
00315 assert(0);
00316 break;
00317 case RPMSIGTAG_SIZE:
00318 case RPMSIGTAG_MD5:
00319 case RPMSIGTAG_PGP5:
00320 case RPMSIGTAG_PGP:
00321 case RPMSIGTAG_GPG:
00322 goto exit;
00323 break;
00324 case RPMSIGTAG_SHA1:
00325 { const char * SHA1 = NULL;
00326 fd = Fopen(file, "r.fdio");
00327 if (fd == NULL || Ferror(fd))
00328 goto exit;
00329 { const char item[] = "Header";
00330 msg = NULL;
00331 rc = rpmpkgRead(item, fd, &h, &msg);
00332 if (rc != RPMRC_OK) {
00333 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
00334 msg = _free(msg);
00335 goto exit;
00336 }
00337 msg = _free(msg);
00338 }
00339 (void) Fclose(fd); fd = NULL;
00340
00341 if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
00342 unsigned char * hmagic = NULL;
00343 size_t nmagic = 0;
00344 DIGEST_CTX ctx;
00345
00346 he->tag = RPMTAG_HEADERIMMUTABLE;
00347 if (!headerGet(h, he, 0) || he->p.ptr == NULL)
00348 {
00349 (void)headerFree(h);
00350 h = NULL;
00351 goto exit;
00352 }
00353 (void) headerGetMagic(NULL, &hmagic, &nmagic);
00354 ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00355 if (hmagic && nmagic > 0)
00356 (void) rpmDigestUpdate(ctx, hmagic, nmagic);
00357 (void) rpmDigestUpdate(ctx, he->p.ptr, he->c);
00358 (void) rpmDigestFinal(ctx, &SHA1, NULL, 1);
00359 he->p.ptr = _free(he->p.ptr);
00360 }
00361 (void)headerFree(h);
00362 h = NULL;
00363
00364 if (SHA1 == NULL)
00365 goto exit;
00366 he->tag = (rpmTag) RPMSIGTAG_SHA1;
00367 he->t = RPM_STRING_TYPE;
00368 he->p.str = SHA1;
00369 he->c = 1;
00370 xx = headerPut(sigh, he, 0);
00371 SHA1 = _free(SHA1);
00372 if (!xx)
00373 goto exit;
00374 ret = 0;
00375 } break;
00376 case RPMSIGTAG_DSA:
00377 fd = Fopen(file, "r.fdio");
00378 if (fd == NULL || Ferror(fd))
00379 goto exit;
00380 { const char item[] = "Header";
00381 msg = NULL;
00382 rc = rpmpkgRead(item, fd, &h, &msg);
00383 if (rc != RPMRC_OK) {
00384 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
00385 msg = _free(msg);
00386 goto exit;
00387 }
00388 msg = _free(msg);
00389 }
00390 (void) Fclose(fd); fd = NULL;
00391
00392 if (rpmTempFile(NULL, &fn, &fd))
00393 goto exit;
00394 { const char item[] = "Header";
00395 msg = NULL;
00396 rc = rpmpkgWrite(item, fd, h, &msg);
00397 if (rc != RPMRC_OK) {
00398 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
00399 msg = _free(msg);
00400 goto exit;
00401 }
00402 msg = _free(msg);
00403 }
00404 (void) Fclose(fd); fd = NULL;
00405
00406 if (makeGPGSignature(fn, &sigTag, &pkt, &pktlen, passPhrase))
00407 goto exit;
00408 he->tag = (rpmTag) sigTag;
00409 he->t = RPM_BIN_TYPE;
00410 he->p.ptr = pkt;
00411 he->c = pktlen;
00412 xx = headerPut(sigh, he, 0);
00413 if (!xx)
00414 goto exit;
00415 ret = 0;
00416 break;
00417 }
00418
00419 exit:
00420 if (fn) {
00421 (void) Unlink(fn);
00422 fn = _free(fn);
00423 }
00424 (void)headerFree(h);
00425 h = NULL;
00426 if (fd != NULL) (void) Fclose(fd);
00427 return ret;
00428 }
00429
00430
00431 int rpmAddSignature(Header sigh, const char * file, rpmSigTag sigTag,
00432 const char * passPhrase)
00433 {
00434 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00435 struct stat st;
00436 rpmuint8_t * pkt;
00437 rpmuint32_t pktlen;
00438 int ret = -1;
00439 int xx;
00440
00441 switch (sigTag) {
00442 default:
00443 assert(0);
00444 break;
00445 case RPMSIGTAG_SIZE:
00446 if (Stat(file, &st) != 0)
00447 break;
00448 pktlen = (rpmuint32_t)st.st_size;
00449 he->tag = (rpmTag) sigTag;
00450 he->t = RPM_UINT32_TYPE;
00451 he->p.ui32p = &pktlen;
00452 he->c = 1;
00453
00454 xx = headerPut(sigh, he, 0);
00455
00456 if (!xx)
00457 break;
00458 ret = 0;
00459 break;
00460 case RPMSIGTAG_MD5:
00461 pktlen = 128/8;
00462 pkt = memset(alloca(pktlen), 0, pktlen);
00463 if (dodigest(PGPHASHALGO_MD5, file, (unsigned char *)pkt, 0, NULL))
00464 break;
00465 he->tag = (rpmTag) sigTag;
00466 he->t = RPM_BIN_TYPE;
00467 he->p.ptr = pkt;
00468 he->c = pktlen;
00469 xx = headerPut(sigh, he, 0);
00470 if (!xx)
00471 break;
00472 ret = 0;
00473 break;
00474 case RPMSIGTAG_GPG:
00475 ret = makeHDRSignature(sigh, file, RPMSIGTAG_DSA, passPhrase);
00476 break;
00477 case RPMSIGTAG_RSA:
00478 case RPMSIGTAG_DSA:
00479 case RPMSIGTAG_SHA1:
00480 ret = makeHDRSignature(sigh, file, sigTag, passPhrase);
00481 break;
00482 }
00483
00484 return ret;
00485 }
00486
00487 int rpmCheckPassPhrase(const char * passPhrase)
00488 {
00489 const char *pw;
00490 int p[2];
00491 pid_t pid;
00492 int status;
00493 int rc;
00494 int xx;
00495
00496 p[0] = p[1] = 0;
00497 xx = pipe(p);
00498
00499 if (!(pid = fork())) {
00500 const char * cmd;
00501 char *const *av;
00502 int fdno;
00503
00504 xx = close(STDIN_FILENO);
00505 xx = close(STDOUT_FILENO);
00506 xx = close(p[1]);
00507 if (!rpmIsVerbose())
00508 xx = close(STDERR_FILENO);
00509 if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
00510 xx = dup2(fdno, STDIN_FILENO);
00511 xx = close(fdno);
00512 }
00513 if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
00514 xx = dup2(fdno, STDOUT_FILENO);
00515 xx = close(fdno);
00516 }
00517 xx = dup2(p[0], 3);
00518
00519 unsetenv("MALLOC_CHECK_");
00520 { const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
00521
00522 if (gpg_path && *gpg_path != '\0')
00523 (void) setenv("GNUPGHOME", gpg_path, 1);
00524
00525 cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
00526 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00527 if (!rc)
00528 rc = execve(av[0], av+1, environ);
00529
00530 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
00531 strerror(errno));
00532 }
00533 }
00534
00535 pw = rpmkuPassPhrase(passPhrase);
00536 if (pw == NULL) {
00537 rpmlog(RPMLOG_ERR, _("Failed rpmkuPassPhrase(passPhrase): %s\n"),
00538 strerror(errno));
00539 return 1;
00540 }
00541
00542 xx = close(p[0]);
00543 xx = (int) write(p[1], pw, strlen(pw));
00544 xx = (int) write(p[1], "\n", 1);
00545 xx = close(p[1]);
00546
00547 if (pw != NULL) {
00548 (void) memset((void *)pw, 0, strlen(pw));
00549 pw = _free(pw);
00550 }
00551
00552
00553 (void) waitpid(pid, &status, 0);
00554
00555
00556 return ((!WIFEXITED(status) || WEXITSTATUS(status)) ? 1 : 0);
00557 }
00558
00559 static const char * rpmSigString(rpmRC res)
00560
00561 {
00562 const char * str;
00563 switch (res) {
00564 case RPMRC_OK: str = "OK"; break;
00565 case RPMRC_FAIL: str = "BAD"; break;
00566 case RPMRC_NOKEY: str = "NOKEY"; break;
00567 case RPMRC_NOTTRUSTED: str = "NOTRUSTED"; break;
00568 default:
00569 case RPMRC_NOTFOUND: str = "UNKNOWN"; break;
00570 }
00571 return str;
00572 }
00573
00574 static rpmRC
00575 verifySize(const pgpDig dig, char * t)
00576
00577 {
00578 const void * sig = pgpGetSig(dig);
00579 rpmRC res;
00580 rpmuint32_t size = 0xffffffff;
00581
00582 *t = '\0';
00583 t = stpcpy(t, _("Header+Payload size: "));
00584
00585 if (sig == NULL || dig == NULL || dig->nbytes == 0) {
00586 res = RPMRC_NOKEY;
00587 t = stpcpy(t, rpmSigString(res));
00588 goto exit;
00589 }
00590
00591 memcpy(&size, sig, sizeof(size));
00592
00593 if (size !=(rpmuint32_t) dig->nbytes) {
00594 res = RPMRC_FAIL;
00595 t = stpcpy(t, rpmSigString(res));
00596 sprintf(t, " Expected(%u) != (%u)\n", (unsigned)size, (unsigned)dig->nbytes);
00597 } else {
00598 res = RPMRC_OK;
00599 t = stpcpy(t, rpmSigString(res));
00600 sprintf(t, " (%u)", (unsigned)dig->nbytes);
00601 }
00602
00603 exit:
00604 return res;
00605 }
00606
00607 static rpmRC
00608 verifyMD5(pgpDig dig, char * t, DIGEST_CTX md5ctx)
00609
00610
00611 {
00612 const void * sig = pgpGetSig(dig);
00613 rpmuint32_t siglen = pgpGetSiglen(dig);
00614 rpmRC res;
00615 rpmuint8_t * md5sum = NULL;
00616 size_t md5len = 0;
00617
00618 assert(dig != NULL);
00619 assert(md5ctx != NULL);
00620 assert(sig != NULL);
00621
00622 *t = '\0';
00623
00624
00625 t = stpcpy(t, rpmDigestName(md5ctx));
00626 t = stpcpy(t, _(" digest: "));
00627
00628 if (sig == NULL) {
00629 res = RPMRC_NOKEY;
00630 t = stpcpy(t, rpmSigString(res));
00631 goto exit;
00632 }
00633
00634 { rpmop op = pgpStatsAccumulator(dig, 10);
00635 (void) rpmswEnter(op, 0);
00636 (void) rpmDigestFinal(rpmDigestDup(md5ctx), &md5sum, &md5len, 0);
00637 (void) rpmswExit(op, 0);
00638 if (op != NULL) op->count--;
00639 }
00640
00641 if (md5len != siglen || memcmp(md5sum, sig, md5len)) {
00642 res = RPMRC_FAIL;
00643 t = stpcpy(t, rpmSigString(res));
00644 t = stpcpy(t, " Expected(");
00645 (void) pgpHexCvt(t, sig, siglen);
00646 t += strlen(t);
00647 t = stpcpy(t, ") != (");
00648 } else {
00649 res = RPMRC_OK;
00650 t = stpcpy(t, rpmSigString(res));
00651 t = stpcpy(t, " (");
00652 }
00653 (void) pgpHexCvt(t, md5sum, md5len);
00654 t += strlen(t);
00655 t = stpcpy(t, ")");
00656
00657 exit:
00658 md5sum = _free(md5sum);
00659 return res;
00660 }
00661
00669 static rpmRC
00670 verifySHA1(pgpDig dig, char * t, DIGEST_CTX shactx)
00671
00672
00673 {
00674 const void * sig = pgpGetSig(dig);
00675 #ifdef NOTYET
00676 rpmuint32_t siglen = pgpGetSiglen(dig);
00677 #endif
00678 rpmRC res;
00679 const char * SHA1 = NULL;
00680
00681 assert(dig != NULL);
00682 assert(shactx != NULL);
00683 assert(sig != NULL);
00684
00685 *t = '\0';
00686 t = stpcpy(t, _("Header "));
00687
00688
00689 t = stpcpy(t, rpmDigestName(shactx));
00690 t = stpcpy(t, _(" digest: "));
00691
00692 if (sig == NULL) {
00693 res = RPMRC_NOKEY;
00694 t = stpcpy(t, rpmSigString(res));
00695 goto exit;
00696 }
00697
00698 { rpmop op = pgpStatsAccumulator(dig, 10);
00699 (void) rpmswEnter(op, 0);
00700 (void) rpmDigestFinal(rpmDigestDup(shactx), &SHA1, NULL, 1);
00701 (void) rpmswExit(op, 0);
00702 }
00703
00704 if (SHA1 == NULL || strlen(SHA1) != strlen(sig) || strcmp(SHA1, sig)) {
00705 res = RPMRC_FAIL;
00706 t = stpcpy(t, rpmSigString(res));
00707 t = stpcpy(t, " Expected(");
00708 t = stpcpy(t, sig);
00709 t = stpcpy(t, ") != (");
00710 } else {
00711 res = RPMRC_OK;
00712 t = stpcpy(t, rpmSigString(res));
00713 t = stpcpy(t, " (");
00714 }
00715 if (SHA1)
00716 t = stpcpy(t, SHA1);
00717 t = stpcpy(t, ")");
00718
00719 exit:
00720 SHA1 = _free(SHA1);
00721 return res;
00722 }
00723
00731 static rpmRC
00732 verifyRSA(pgpDig dig, char * t, DIGEST_CTX rsactx)
00733
00734
00735 {
00736 const void * sig = pgpGetSig(dig);
00737 #ifdef NOTYET
00738 rpmuint32_t siglen = pgpGetSiglen(dig);
00739 #endif
00740 pgpDigParams sigp = pgpGetSignature(dig);
00741 rpmRC res = RPMRC_OK;
00742 int xx;
00743
00744 assert(dig != NULL);
00745 assert(rsactx != NULL);
00746 assert(sigp != NULL);
00747 assert(sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA);
00748 assert(sigp->hash_algo == (rpmuint8_t)rpmDigestAlgo(rsactx));
00749 assert(pgpGetSigtag(dig) == RPMSIGTAG_RSA);
00750 assert(sig != NULL);
00751
00752 *t = '\0';
00753 if (dig->hdrctx == rsactx)
00754 t = stpcpy(t, _("Header "));
00755
00756
00757 *t++ = 'V';
00758 switch (sigp->version) {
00759 case 3: *t++ = '3'; break;
00760 case 4: *t++ = '4'; break;
00761 }
00762
00763
00764 { const char * hashname = rpmDigestName(rsactx);
00765 t = stpcpy(t, " RSA");
00766 if (strcmp(hashname, "UNKNOWN")) {
00767 *t++ = '/';
00768 t = stpcpy(t, hashname);
00769 }
00770 }
00771 t = stpcpy(t, _(" signature: "));
00772
00773 { rpmop op = pgpStatsAccumulator(dig, 10);
00774 DIGEST_CTX ctx = rpmDigestDup(rsactx);
00775
00776 (void) rpmswEnter(op, 0);
00777 if (sigp->hash != NULL)
00778 xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
00779
00780 if (sigp->version == (rpmuint8_t) 4) {
00781 rpmuint32_t nb = (rpmuint32_t) sigp->hashlen;
00782 rpmuint8_t trailer[6];
00783 nb = (rpmuint32_t) htonl(nb);
00784 trailer[0] = sigp->version;
00785 trailer[1] = (rpmuint8_t)0xff;
00786 memcpy(trailer+2, &nb, sizeof(nb));
00787 xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
00788 }
00789 (void) rpmswExit(op, sigp->hashlen);
00790 if (op != NULL) op->count--;
00791
00792 if ((xx = pgpImplSetRSA(ctx, dig, sigp)) != 0) {
00793 res = RPMRC_FAIL;
00794 goto exit;
00795 }
00796 }
00797
00798
00799 res = pgpFindPubkey(dig);
00800 if (res != RPMRC_OK)
00801 goto exit;
00802
00803
00804 { rpmop op = pgpStatsAccumulator(dig, 11);
00805 (void) rpmswEnter(op, 0);
00806 xx = pgpImplVerifyRSA(dig);
00807 (void) rpmswExit(op, 0);
00808 res = (xx ? RPMRC_OK : RPMRC_FAIL);
00809 }
00810
00811 exit:
00812
00813 t = stpcpy(t, rpmSigString(res));
00814 if (sigp != NULL) {
00815 t = stpcpy(t, ", key ID ");
00816 (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4);
00817 t += strlen(t);
00818 }
00819 return res;
00820 }
00821
00829 static rpmRC
00830 verifyDSA(pgpDig dig, char * t, DIGEST_CTX dsactx)
00831
00832
00833 {
00834 const void * sig = pgpGetSig(dig);
00835 #ifdef NOTYET
00836 rpmuint32_t siglen = pgpGetSiglen(dig);
00837 #endif
00838 pgpDigParams sigp = pgpGetSignature(dig);
00839 rpmRC res;
00840 int xx;
00841
00842 assert(dig != NULL);
00843 assert(dsactx != NULL);
00844 assert(sigp != NULL);
00845 assert(sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_DSA);
00846 assert(sigp->hash_algo == (rpmuint8_t)rpmDigestAlgo(dsactx));
00847 assert(pgpGetSigtag(dig) == RPMSIGTAG_DSA);
00848 assert(sig != NULL);
00849
00850 *t = '\0';
00851 if (dig != NULL && dig->hdrsha1ctx == dsactx)
00852 t = stpcpy(t, _("Header "));
00853
00854
00855 *t++ = 'V';
00856 switch (sigp->version) {
00857 case 3: *t++ = '3'; break;
00858 case 4: *t++ = '4'; break;
00859 }
00860
00861
00862 { const char * hashname = rpmDigestName(dsactx);
00863 t = stpcpy(t, " DSA");
00864 if (strcmp(hashname, "UNKNOWN") && strcmp(hashname, "SHA1")) {
00865 *t++ = '/';
00866 t = stpcpy(t, hashname);
00867 }
00868 }
00869 t = stpcpy(t, _(" signature: "));
00870
00871 { rpmop op = pgpStatsAccumulator(dig, 10);
00872 DIGEST_CTX ctx = rpmDigestDup(dsactx);
00873
00874 (void) rpmswEnter(op, 0);
00875 if (sigp->hash != NULL)
00876 xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
00877
00878 if (sigp->version == (rpmuint8_t) 4) {
00879 rpmuint32_t nb = (rpmuint32_t) sigp->hashlen;
00880 rpmuint8_t trailer[6];
00881 nb = (rpmuint32_t) htonl(nb);
00882 trailer[0] = sigp->version;
00883 trailer[1] = (rpmuint8_t)0xff;
00884 memcpy(trailer+2, &nb, sizeof(nb));
00885 xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
00886 }
00887 (void) rpmswExit(op, sigp->hashlen);
00888 if (op != NULL) op->count--;
00889
00890 if (pgpImplSetDSA(ctx, dig, sigp)) {
00891 res = RPMRC_FAIL;
00892 goto exit;
00893 }
00894 }
00895
00896
00897 res = pgpFindPubkey(dig);
00898 if (res != RPMRC_OK)
00899 goto exit;
00900
00901
00902 { rpmop op = pgpStatsAccumulator(dig, 11);
00903 (void) rpmswEnter(op, 0);
00904 xx = pgpImplVerifyDSA(dig);
00905 res = (xx ? RPMRC_OK : RPMRC_FAIL);
00906 (void) rpmswExit(op, 0);
00907 }
00908
00909 exit:
00910
00911 t = stpcpy(t, rpmSigString(res));
00912 if (sigp != NULL) {
00913 t = stpcpy(t, ", key ID ");
00914 (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4);
00915 t += strlen(t);
00916 }
00917 return res;
00918 }
00919
00920 rpmRC
00921 rpmVerifySignature(void * _dig, char * result)
00922 {
00923 pgpDig dig = _dig;
00924 const void * sig = pgpGetSig(dig);
00925 rpmuint32_t siglen = pgpGetSiglen(dig);
00926 rpmSigTag sigtag = pgpGetSigtag(dig);
00927 rpmRC res;
00928
00929 if (dig == NULL || sig == NULL || siglen == 0) {
00930 sprintf(result, _("Verify signature: BAD PARAMETERS\n"));
00931 return RPMRC_NOTFOUND;
00932 }
00933
00934 switch (sigtag) {
00935 case RPMSIGTAG_SIZE:
00936 res = verifySize(dig, result);
00937 break;
00938 case RPMSIGTAG_MD5:
00939 res = verifyMD5(dig, result, dig->md5ctx);
00940 break;
00941 case RPMSIGTAG_SHA1:
00942 res = verifySHA1(dig, result, dig->hdrsha1ctx);
00943 break;
00944 case RPMSIGTAG_RSA:
00945 res = verifyRSA(dig, result, dig->hdrctx);
00946 break;
00947 case RPMSIGTAG_DSA:
00948 res = verifyDSA(dig, result, dig->hdrsha1ctx);
00949 break;
00950 default:
00951 sprintf(result, _("Signature: UNKNOWN (%u)\n"), (unsigned)sigtag);
00952 res = RPMRC_NOTFOUND;
00953 break;
00954 }
00955 return res;
00956 }