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