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