rpm
5.2.1
|
00001 00006 #include "system.h" 00007 00008 #include <rpmio_internal.h> 00009 #include <poptIO.h> 00010 #include <rpmbc.h> /* XXX beecrypt base64 */ 00011 #include <rpmtag.h> 00012 #include <rpmtypes.h> 00013 #define _RPMEVR_INTERNAL /* XXX RPMSENSE_KEYRING */ 00014 #include <rpmevr.h> 00015 #include <rpmdb.h> 00016 #include <rpmxar.h> 00017 #include <pkgio.h> 00018 #include "signature.h" 00019 00020 #include <rpmts.h> 00021 00022 #include "rpmgi.h" 00023 00024 #include <rpmversion.h> 00025 #include <rpmcli.h> 00026 00027 #include "debug.h" 00028 00029 /*@access FD_t @*/ /* XXX stealing digests */ 00030 /*@access Header @*/ /* XXX void * arg */ 00031 /*@access pgpDig @*/ 00032 /*@access pgpDigParams @*/ 00033 00034 /*@unchecked@*/ 00035 int _print_pkts = 0; 00036 00039 static int manageFile(/*@out@*/ FD_t *fdp, 00040 /*@null@*/ /*@out@*/ const char **fnp, 00041 int flags, /*@unused@*/ int rc) 00042 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00043 /*@modifies *fdp, *fnp, rpmGlobalMacroContext, 00044 fileSystem, internalState @*/ 00045 { 00046 const char *fn; 00047 FD_t fd; 00048 00049 if (fdp == NULL) /* programmer error */ 00050 return 1; 00051 00052 /* close and reset *fdp to NULL */ 00053 if (*fdp && (fnp == NULL || *fnp == NULL)) { 00054 (void) Fclose(*fdp); 00055 *fdp = NULL; 00056 return 0; 00057 } 00058 00059 /* open a file and set *fdp */ 00060 if (*fdp == NULL && fnp != NULL && *fnp != NULL) { 00061 fd = Fopen(*fnp, ((flags & O_WRONLY) ? "w.fdio" : "r.fdio")); 00062 if (fd == NULL || Ferror(fd)) { 00063 rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"), *fnp, 00064 Fstrerror(fd)); 00065 return 1; 00066 } 00067 *fdp = fd; 00068 return 0; 00069 } 00070 00071 /* open a temp file */ 00072 if (*fdp == NULL && (fnp == NULL || *fnp == NULL)) { 00073 fn = NULL; 00074 if (rpmTempFile(NULL, (fnp ? &fn : NULL), &fd)) { 00075 rpmlog(RPMLOG_ERR, _("rpmTempFile failed\n")); 00076 return 1; 00077 } 00078 if (fnp != NULL) 00079 *fnp = fn; 00080 /*@-refcounttrans@*/ /* FIX: XfdLink/XfdFree annotation */ 00081 *fdp = fdLink(fd, "manageFile return"); 00082 fd = fdFree(fd, "manageFile return"); 00083 /*@=refcounttrans@*/ 00084 return 0; 00085 } 00086 00087 /* no operation */ 00088 if (*fdp != NULL && fnp != NULL && *fnp != NULL) 00089 return 0; 00090 00091 /* XXX never reached */ 00092 return 1; 00093 } 00094 00098 static int copyFile(FD_t *sfdp, const char **sfnp, 00099 FD_t *tfdp, const char **tfnp) 00100 /*@globals rpmGlobalMacroContext, h_errno, 00101 fileSystem, internalState @*/ 00102 /*@modifies *sfdp, *sfnp, *tfdp, *tfnp, rpmGlobalMacroContext, 00103 fileSystem, internalState @*/ 00104 { 00105 unsigned char buf[BUFSIZ]; 00106 ssize_t count; 00107 int rc = 1; 00108 00109 if (manageFile(sfdp, sfnp, O_RDONLY, 0)) 00110 goto exit; 00111 if (manageFile(tfdp, tfnp, O_WRONLY|O_CREAT|O_TRUNC, 0)) 00112 goto exit; 00113 00114 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), *sfdp)) > 0) 00115 { 00116 if (Fwrite(buf, sizeof(buf[0]), count, *tfdp) != (size_t)count) { 00117 rpmlog(RPMLOG_ERR, _("%s: Fwrite failed: %s\n"), *tfnp, 00118 Fstrerror(*tfdp)); 00119 goto exit; 00120 } 00121 } 00122 if (count < 0) { 00123 rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"), *sfnp, Fstrerror(*sfdp)); 00124 goto exit; 00125 } 00126 if (Fflush(*tfdp) != 0) { 00127 rpmlog(RPMLOG_ERR, _("%s: Fflush failed: %s\n"), *tfnp, 00128 Fstrerror(*tfdp)); 00129 goto exit; 00130 } 00131 00132 rc = 0; 00133 00134 exit: 00135 if (*sfdp) (void) manageFile(sfdp, NULL, 0, rc); 00136 if (*tfdp) (void) manageFile(tfdp, NULL, 0, rc); 00137 return rc; 00138 } 00139 00147 static int getSignid(Header sigh, rpmSigTag sigtag, unsigned char * signid) 00148 /*@globals fileSystem, internalState @*/ 00149 /*@modifies *signid, fileSystem, internalState @*/ 00150 { 00151 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00152 int rc = 1; 00153 int xx; 00154 00155 he->tag = (rpmTag) sigtag; 00156 xx = headerGet(sigh, he, 0); 00157 if (xx && he->p.ptr != NULL) { 00158 pgpDig dig = pgpDigNew(0); 00159 00160 if (!pgpPrtPkts(he->p.ptr, he->c, dig, 0)) { 00161 memcpy(signid, dig->signature.signid, sizeof(dig->signature.signid)); 00162 rc = 0; 00163 } 00164 00165 he->p.ptr = _free(he->p.ptr); 00166 dig = pgpDigFree(dig, "getSignid"); 00167 } 00168 return rc; 00169 } 00170 00178 static int rpmReSign(/*@unused@*/ rpmts ts, 00179 QVA_t qva, const char ** argv) 00180 /*@globals rpmGlobalMacroContext, h_errno, 00181 fileSystem, internalState @*/ 00182 /*@modifies ts, rpmGlobalMacroContext, 00183 fileSystem, internalState @*/ 00184 { 00185 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00186 rpmgi gi = NULL; 00187 FD_t fd = NULL; 00188 FD_t ofd = NULL; 00189 struct rpmlead *lead = NULL; 00190 rpmSigTag sigtag; 00191 const char *sigtarget = NULL; 00192 char tmprpm[1024+1]; 00193 Header sigh = NULL; 00194 const char * msg = NULL; 00195 int res = EXIT_FAILURE; 00196 int deleting = (qva->qva_mode == RPMSIGN_DEL_SIGNATURE); 00197 rpmRC rc; 00198 int xx; 00199 int i; 00200 00201 tmprpm[0] = '\0'; 00202 00203 if (argv) 00204 { /* start-of-arg-iteration */ 00205 rpmuint32_t tag = (qva->qva_source == RPMQV_FTSWALK) 00206 ? RPMDBI_FTSWALK : RPMDBI_ARGLIST; 00207 rpmgiFlags _giFlags = RPMGI_NONE; 00208 00209 gi = rpmgiNew(ts, tag, NULL, 0); 00210 /*@-mods@*/ 00211 if (rpmioFtsOpts == 0) 00212 rpmioFtsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT); 00213 /*@=mods@*/ 00214 rc = rpmgiSetArgs(gi, argv, rpmioFtsOpts, (_giFlags|RPMGI_NOHEADER)); 00215 00216 while (rpmgiNext(gi) == RPMRC_OK) { 00217 const char * fn = rpmgiHdrPath(gi); 00218 const char * tfn; 00219 00220 fprintf(stdout, "%s:\n", fn); 00221 00222 /*@-modobserver@*/ /* XXX rpmgiHdrPath should not be observer */ 00223 if (manageFile(&fd, &fn, O_RDONLY, 0)) 00224 goto exit; 00225 /*@=modobserver@*/ 00226 00227 { const char item[] = "Lead"; 00228 msg = NULL; 00229 rc = rpmpkgRead(item, fd, &lead, &msg); 00230 if (rc != RPMRC_OK) { 00231 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg); 00232 msg = _free(msg); 00233 goto exit; 00234 } 00235 msg = _free(msg); 00236 } 00237 00238 { const char item[] = "Signature"; 00239 msg = NULL; 00240 rc = rpmpkgRead(item, fd, &sigh, &msg); 00241 switch (rc) { 00242 default: 00243 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, 00244 (msg && *msg ? msg : "")); 00245 msg = _free(msg); 00246 goto exit; 00247 /*@notreached@*/ /*@switchbreak@*/ break; 00248 case RPMRC_OK: 00249 if (sigh == NULL) { 00250 rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn); 00251 goto exit; 00252 } 00253 /*@switchbreak@*/ break; 00254 } 00255 msg = _free(msg); 00256 } 00257 00258 /* Write the header and archive to a temp file */ 00259 /* ASSERT: ofd == NULL && sigtarget == NULL */ 00260 /*@-modobserver@*/ /* XXX rpmgiHdrPath should not be observer */ 00261 if (copyFile(&fd, &fn, &ofd, &sigtarget)) 00262 goto exit; 00263 /*@=modobserver@*/ 00264 /* Both fd and ofd are now closed. sigtarget contains tempfile name. */ 00265 /* ASSERT: fd == NULL && ofd == NULL */ 00266 00267 /* Lose the immutable region (if present). */ 00268 he->tag = RPMTAG_HEADERSIGNATURES; 00269 xx = headerGet(sigh, he, 0); 00270 if (xx) { 00271 HE_t ohe = memset(alloca(sizeof(*ohe)), 0, sizeof(*ohe)); 00272 HeaderIterator hi; 00273 Header oh; 00274 Header nh; 00275 00276 nh = headerNew(); 00277 if (nh == NULL) { 00278 he->p.ptr = _free(he->p.ptr); 00279 goto exit; 00280 } 00281 00282 oh = headerCopyLoad(he->p.ptr); 00283 for (hi = headerInit(oh); 00284 headerNext(hi, ohe, 0); 00285 ohe->p.ptr = _free(ohe->p.ptr)) 00286 { 00287 if (ohe->p.ptr) { 00288 xx = headerPut(nh, ohe, 0); 00289 } 00290 } 00291 hi = headerFini(hi); 00292 (void)headerFree(oh); 00293 oh = NULL; 00294 00295 (void)headerFree(sigh); 00296 sigh = NULL; 00297 sigh = headerLink(nh); 00298 (void)headerFree(nh); 00299 nh = NULL; 00300 } 00301 00302 if (sigh != NULL) { 00303 /* Eliminate broken digest values. */ 00304 he->tag = (rpmTag)RPMSIGTAG_LEMD5_1; 00305 xx = headerDel(sigh, he, 0); 00306 he->tag = (rpmTag)RPMSIGTAG_LEMD5_2; 00307 xx = headerDel(sigh, he, 0); 00308 he->tag = (rpmTag)RPMSIGTAG_BADSHA1_1; 00309 xx = headerDel(sigh, he, 0); 00310 he->tag = (rpmTag)RPMSIGTAG_BADSHA1_2; 00311 xx = headerDel(sigh, he, 0); 00312 00313 /* Toss and recalculate header+payload size and digests. */ 00314 { static const rpmuint32_t sigs[] = 00315 { RPMSIGTAG_SIZE, RPMSIGTAG_MD5, RPMSIGTAG_SHA1 }; 00316 size_t nsigs = sizeof(sigs) / sizeof(sigs[0]); 00317 for (i = 0; i < (int)nsigs; i++) { 00318 he->tag = (rpmTag)sigs[i]; 00319 xx = headerDel(sigh, he, 0); 00320 xx = rpmAddSignature(sigh, sigtarget, (rpmSigTag) he->tag, qva->passPhrase); 00321 if (xx) 00322 goto exit; 00323 } 00324 } 00325 00326 if (deleting) { 00327 /* Nuke all the signature tags. */ 00328 static const rpmuint32_t sigs[] = 00329 { RPMSIGTAG_GPG, RPMSIGTAG_PGP5, RPMSIGTAG_PGP, 00330 RPMSIGTAG_DSA, RPMSIGTAG_RSA }; 00331 size_t nsigs = sizeof(sigs) / sizeof(sigs[0]); 00332 for (i = 0; i < (int)nsigs; i++) { 00333 he->tag = (rpmTag)sigs[i]; 00334 xx = headerDel(sigh, he, 0); 00335 } 00336 } else { /* If gpg/pgp is configured, replace the signature. */ 00337 int addsig = 0; 00338 sigtag = RPMSIGTAG_GPG; 00339 addsig = 1; 00340 00341 if (addsig) { 00342 unsigned char oldsignid[8], newsignid[8]; 00343 00344 /* Grab the old signature fingerprint (if any) */ 00345 memset(oldsignid, 0, sizeof(oldsignid)); 00346 xx = getSignid(sigh, sigtag, oldsignid); 00347 00348 switch (sigtag) { 00349 default: 00350 /*@switchbreak@*/ break; 00351 case RPMSIGTAG_DSA: 00352 he->tag = (rpmTag)RPMSIGTAG_GPG; 00353 xx = headerDel(sigh, he, 0); 00354 /*@switchbreak@*/ break; 00355 case RPMSIGTAG_RSA: 00356 he->tag = (rpmTag)RPMSIGTAG_PGP; 00357 xx = headerDel(sigh, he, 0); 00358 /*@switchbreak@*/ break; 00359 case RPMSIGTAG_GPG: 00360 he->tag = (rpmTag)RPMSIGTAG_PGP; 00361 xx = headerDel(sigh, he, 0); 00362 he->tag = (rpmTag)RPMSIGTAG_DSA; 00363 xx = headerDel(sigh, he, 0); 00364 /*@fallthrough@*/ 00365 case RPMSIGTAG_PGP5: 00366 case RPMSIGTAG_PGP: 00367 he->tag = (rpmTag)RPMSIGTAG_RSA; 00368 xx = headerDel(sigh, he, 0); 00369 /*@switchbreak@*/ break; 00370 } 00371 00372 he->tag = (rpmTag)sigtag; 00373 xx = headerDel(sigh, he, 0); 00374 xx = rpmAddSignature(sigh, sigtarget, sigtag, qva->passPhrase); 00375 if (xx) 00376 goto exit; 00377 00378 /* If package was previously signed, check for same signer. */ 00379 memset(newsignid, 0, sizeof(newsignid)); 00380 if (memcmp(oldsignid, newsignid, sizeof(oldsignid))) { 00381 00382 /* Grab the new signature fingerprint */ 00383 xx = getSignid(sigh, sigtag, newsignid); 00384 00385 /* If same signer, skip resigning the package. */ 00386 if (!memcmp(oldsignid, newsignid, sizeof(oldsignid))) { 00387 00388 rpmlog(RPMLOG_WARNING, 00389 _("%s: was already signed by key ID %s, skipping\n"), 00390 fn, pgpHexStr(newsignid+4, sizeof(newsignid)-4)); 00391 00392 /* Clean up intermediate target */ 00393 xx = Unlink(sigtarget); 00394 sigtarget = _free(sigtarget); 00395 continue; 00396 } 00397 } 00398 } 00399 } 00400 00401 /* Reallocate the signature into one contiguous region. */ 00402 sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES); 00403 if (sigh == NULL) /* XXX can't happen */ 00404 goto exit; 00405 } 00406 00407 /* Write the lead/signature of the output rpm */ 00408 (void) stpcpy( stpcpy(tmprpm, fn), ".XXXXXX"); 00409 00410 #if defined(HAVE_MKSTEMP) 00411 (void) close(mkstemp(tmprpm)); 00412 #else 00413 (void) mktemp(tmprpm); 00414 #endif 00415 tfn = tmprpm; 00416 00417 if (manageFile(&ofd, &tfn, O_WRONLY|O_CREAT|O_TRUNC, 0)) 00418 goto exit; 00419 00420 { const char item[] = "Lead"; 00421 rc = rpmpkgWrite(item, ofd, lead, NULL); 00422 if (rc != RPMRC_OK) { 00423 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", tfn, item, Fstrerror(ofd)); 00424 goto exit; 00425 } 00426 } 00427 00428 { const char item[] = "Signature"; 00429 rc = rpmpkgWrite(item, ofd, sigh, NULL); 00430 if (rc != RPMRC_OK) { 00431 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", tfn, item, Fstrerror(ofd)); 00432 goto exit; 00433 } 00434 } 00435 00436 /* Append the header and archive from the temp file */ 00437 /* ASSERT: fd == NULL && ofd != NULL */ 00438 if (copyFile(&fd, &sigtarget, &ofd, &tfn)) 00439 goto exit; 00440 /* Both fd and ofd are now closed. */ 00441 /* ASSERT: fd == NULL && ofd == NULL */ 00442 00443 /* Move final target into place. */ 00444 xx = Unlink(fn); 00445 xx = Rename(tfn, fn); 00446 tmprpm[0] = '\0'; 00447 00448 /* Clean up intermediate target */ 00449 xx = Unlink(sigtarget); 00450 sigtarget = _free(sigtarget); 00451 } 00452 00453 } /* end-of-arg-iteration */ 00454 00455 res = 0; 00456 00457 exit: 00458 if (fd) (void) manageFile(&fd, NULL, 0, res); 00459 if (ofd) (void) manageFile(&ofd, NULL, 0, res); 00460 00461 lead = _free(lead); 00462 (void)headerFree(sigh); 00463 sigh = NULL; 00464 00465 gi = rpmgiFree(gi); 00466 00467 if (sigtarget) { 00468 xx = Unlink(sigtarget); 00469 sigtarget = _free(sigtarget); 00470 } 00471 if (tmprpm[0] != '\0') { 00472 xx = Unlink(tmprpm); 00473 tmprpm[0] = '\0'; 00474 } 00475 00476 return res; 00477 } 00478 00479 rpmRC rpmcliImportPubkey(const rpmts ts, const unsigned char * pkt, ssize_t pktlen) 00480 { 00481 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00482 static unsigned char zeros[] = 00483 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 00484 const char * afmt = "%{pubkeys:armor}"; 00485 const char * group = "Public Keys"; 00486 const char * license = "pubkey"; 00487 const char * buildhost = "localhost"; 00488 rpmuint32_t pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL); 00489 rpmuint32_t zero = 0; 00490 pgpDig dig = NULL; 00491 pgpDigParams pubp = NULL; 00492 const char * d = NULL; 00493 const char * enc = NULL; 00494 const char * n = NULL; 00495 const char * u = NULL; 00496 const char * v = NULL; 00497 const char * r = NULL; 00498 const char * evr = NULL; 00499 Header h = NULL; 00500 rpmRC rc = RPMRC_FAIL; /* assume failure */ 00501 char * t; 00502 int xx; 00503 00504 if (pkt == NULL || pktlen <= 0) 00505 return RPMRC_FAIL; 00506 if (rpmtsOpenDB(ts, (O_RDWR|O_CREAT))) 00507 return RPMRC_FAIL; 00508 00509 /*@-moduncon@*/ 00510 if ((enc = b64encode(pkt, pktlen)) == NULL) 00511 goto exit; 00512 /*@=moduncon@*/ 00513 00514 dig = pgpDigNew(0); 00515 00516 /* Build header elements. */ 00517 (void) pgpPrtPkts(pkt, pktlen, dig, 0); 00518 pubp = pgpGetPubkey(dig); 00519 00520 if (!memcmp(pubp->signid, zeros, sizeof(pubp->signid)) 00521 || !memcmp(pubp->time, zeros, sizeof(pubp->time)) 00522 || pubp->userid == NULL) 00523 goto exit; 00524 00525 v = t = xmalloc(16+1); 00526 t = stpcpy(t, pgpHexStr(pubp->signid, sizeof(pubp->signid))); 00527 00528 r = t = xmalloc(8+1); 00529 t = stpcpy(t, pgpHexStr(pubp->time, sizeof(pubp->time))); 00530 00531 n = t = xmalloc(sizeof("gpg()")+8); 00532 t = stpcpy( stpcpy( stpcpy(t, "gpg("), v+8), ")"); 00533 00534 /*@-nullpass@*/ /* FIX: pubp->userid may be NULL */ 00535 u = t = xmalloc(sizeof("gpg()")+strlen(pubp->userid)); 00536 t = stpcpy( stpcpy( stpcpy(t, "gpg("), pubp->userid), ")"); 00537 /*@=nullpass@*/ 00538 00539 evr = t = xmalloc(sizeof("4X:-")+strlen(v)+strlen(r)); 00540 t = stpcpy(t, (pubp->version == 4 ? "4:" : "3:")); 00541 t = stpcpy( stpcpy( stpcpy(t, v), "-"), r); 00542 00543 /* Check for pre-existing header. */ 00544 00545 /* Build pubkey header. */ 00546 h = headerNew(); 00547 00548 he->append = 1; 00549 00550 he->tag = RPMTAG_PUBKEYS; 00551 he->t = RPM_STRING_ARRAY_TYPE; 00552 he->p.argv = &enc; 00553 he->c = 1; 00554 xx = headerPut(h, he, 0); 00555 00556 he->append = 0; 00557 00558 d = headerSprintf(h, afmt, NULL, rpmHeaderFormats, NULL); 00559 if (d == NULL) 00560 goto exit; 00561 00562 he->t = RPM_STRING_TYPE; 00563 he->c = 1; 00564 he->tag = RPMTAG_NAME; 00565 he->p.str = xstrdup("gpg-pubkey"); 00566 xx = headerPut(h, he, 0); 00567 he->p.ptr = _free(he->p.ptr); 00568 he->tag = RPMTAG_VERSION; 00569 he->p.str = v+8; 00570 xx = headerPut(h, he, 0); 00571 he->tag = RPMTAG_RELEASE; 00572 he->p.str = xstrdup(r); 00573 xx = headerPut(h, he, 0); 00574 he->p.ptr = _free(he->p.ptr); 00575 00576 /* Add Summary/Description/Group. */ 00577 he->tag = RPMTAG_DESCRIPTION; 00578 he->p.str = xstrdup(d); 00579 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES) 00580 xx = headerAddI18NString(h, he->tag, he->p.ptr, "C"); 00581 #else 00582 xx = headerPut(h, he, 0); 00583 #endif 00584 he->p.ptr = _free(he->p.ptr); 00585 00586 he->tag = RPMTAG_GROUP; 00587 he->p.str = xstrdup(group); 00588 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES) 00589 xx = headerAddI18NString(h, he->tag, he->p.ptr, "C"); 00590 #else 00591 xx = headerPut(h, he, 0); 00592 #endif 00593 he->p.ptr = _free(he->p.ptr); 00594 00595 he->tag = RPMTAG_SUMMARY; 00596 he->p.str = xstrdup(u); 00597 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES) 00598 xx = headerAddI18NString(h, he->tag, he->p.ptr, "C"); 00599 #else 00600 xx = headerPut(h, he, 0); 00601 #endif 00602 he->p.ptr = _free(he->p.ptr); 00603 00604 #ifdef NOTYET /* XXX can't erase pubkeys with "pubkey" arch. */ 00605 /* Add a "pubkey" arch/os to avoid missing value NULL ptrs. */ 00606 he->tag = RPMTAG_ARCH; 00607 he->p.str = "pubkey"; 00608 xx = headerPut(h, he, 0); 00609 he->tag = RPMTAG_OS; 00610 he->p.str = "pubkey"; 00611 xx = headerPut(h, he, 0); 00612 #endif 00613 00614 he->tag = RPMTAG_LICENSE; 00615 he->p.str = xstrdup(license); 00616 xx = headerPut(h, he, 0); 00617 he->p.ptr = _free(he->p.ptr); 00618 00619 he->tag = RPMTAG_SIZE; 00620 he->t = RPM_UINT32_TYPE; 00621 he->p.ui32p = &zero; 00622 he->c = 1; 00623 xx = headerPut(h, he, 0); 00624 00625 he->append = 1; 00626 00627 /* Provides: gpg(IDENTITY) = PUBKEYVERSIONTYPE:PUBKEYID-CREATION */ 00628 he->tag = RPMTAG_PROVIDENAME; 00629 he->t = RPM_STRING_ARRAY_TYPE; 00630 he->p.argv = &u; 00631 he->c = 1; 00632 xx = headerPut(h, he, 0); 00633 he->tag = RPMTAG_PROVIDEVERSION; 00634 he->t = RPM_STRING_ARRAY_TYPE; 00635 he->p.argv = &evr; 00636 he->c = 1; 00637 xx = headerPut(h, he, 0); 00638 he->tag = RPMTAG_PROVIDEFLAGS; 00639 he->t = RPM_UINT32_TYPE; 00640 he->p.ui32p = &pflags; 00641 he->c = 1; 00642 xx = headerPut(h, he, 0); 00643 00644 /* Provides: gpg(PUBKEYID) = PUBKEYVERSION:PUBKEYID-CREATION */ 00645 he->tag = RPMTAG_PROVIDENAME; 00646 he->t = RPM_STRING_ARRAY_TYPE; 00647 he->p.argv = &n; 00648 he->c = 1; 00649 xx = headerPut(h, he, 0); 00650 he->tag = RPMTAG_PROVIDEVERSION; 00651 he->t = RPM_STRING_ARRAY_TYPE; 00652 he->p.argv = &evr; 00653 he->c = 1; 00654 xx = headerPut(h, he, 0); 00655 he->tag = RPMTAG_PROVIDEFLAGS; 00656 he->t = RPM_UINT32_TYPE; 00657 he->p.ui32p = &pflags; 00658 he->c = 1; 00659 xx = headerPut(h, he, 0); 00660 00661 he->append = 0; 00662 00663 he->tag = RPMTAG_RPMVERSION; 00664 he->t = RPM_STRING_TYPE; 00665 he->p.str = xstrdup(RPMVERSION); 00666 he->c = 1; 00667 xx = headerPut(h, he, 0); 00668 he->p.ptr = _free(he->p.ptr); 00669 00670 /* XXX W2DO: tag value inherited from parent? */ 00671 he->tag = RPMTAG_BUILDHOST; 00672 he->t = RPM_STRING_TYPE; 00673 he->p.str = xstrdup(buildhost); 00674 he->c = 1; 00675 xx = headerPut(h, he, 0); 00676 he->p.ptr = _free(he->p.ptr); 00677 00678 { rpmuint32_t tid = rpmtsGetTid(ts); 00679 he->tag = RPMTAG_INSTALLTIME; 00680 he->t = RPM_UINT32_TYPE; 00681 he->p.ui32p = &tid; 00682 he->c = 1; 00683 xx = headerPut(h, he, 0); 00684 /* XXX W2DO: tag value inherited from parent? */ 00685 he->tag = RPMTAG_BUILDTIME; 00686 he->t = RPM_UINT32_TYPE; 00687 he->p.ui32p = &tid; 00688 he->c = 1; 00689 xx = headerPut(h, he, 0); 00690 } 00691 00692 #ifdef NOTYET 00693 /* XXX W2DO: tag value inherited from parent? */ 00694 he->tag = RPMTAG_SOURCERPM; 00695 he->t = RPM_STRING_TYPE; 00696 he->p.str = fn; 00697 he->c = 1; 00698 xx = headerPut(h, he, 0); 00699 #endif 00700 00701 /* Add header to database. */ 00702 xx = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), h, NULL); 00703 if (xx != 0) 00704 goto exit; 00705 rc = RPMRC_OK; 00706 00707 exit: 00708 /* Clean up. */ 00709 (void)headerFree(h); 00710 h = NULL; 00711 dig = pgpDigFree(dig, "rpmcliImportPubkey"); 00712 n = _free(n); 00713 u = _free(u); 00714 v = _free(v); 00715 r = _free(r); 00716 evr = _free(evr); 00717 enc = _free(enc); 00718 d = _free(d); 00719 00720 return rc; 00721 } 00722 00731 static int rpmcliImportPubkeys(const rpmts ts, 00732 /*@unused@*/ QVA_t qva, 00733 /*@null@*/ const char ** argv) 00734 /*@globals rpmGlobalMacroContext, h_errno, 00735 fileSystem, internalState @*/ 00736 /*@modifies ts, rpmGlobalMacroContext, 00737 fileSystem, internalState @*/ 00738 { 00739 const char * fn; 00740 rpmuint8_t * pkt = NULL; 00741 size_t pktlen = 0; 00742 char * t = NULL; 00743 int res = 0; 00744 rpmRC rpmrc; 00745 int rc; 00746 00747 if (argv == NULL) return res; 00748 00749 while ((fn = *argv++) != NULL) { 00750 00751 rpmtsClean(ts); 00752 pkt = _free(pkt); 00753 t = _free(t); 00754 00755 /* If arg looks like a keyid, then attempt keyserver retrieve. */ 00756 if (fn[0] == '0' && fn[1] == 'x') { 00757 const char * s; 00758 int i; 00759 for (i = 0, s = fn+2; *s && isxdigit(*s); s++, i++) 00760 {}; 00761 if (i == 8 || i == 16) { 00762 t = rpmExpand("%{_hkp_keyserver_query}", fn+2, NULL); 00763 if (t && *t != '%') 00764 fn = t; 00765 } 00766 } 00767 00768 /* Read pgp packet. */ 00769 if ((rc = pgpReadPkts(fn, &pkt, &pktlen)) <= 0) { 00770 rpmlog(RPMLOG_ERR, _("%s: import read failed(%d).\n"), fn, rc); 00771 res++; 00772 continue; 00773 } 00774 if (rc != PGPARMOR_PUBKEY) { 00775 rpmlog(RPMLOG_ERR, _("%s: not an armored public key.\n"), fn); 00776 res++; 00777 continue; 00778 } 00779 00780 /* Import pubkey packet(s). */ 00781 if ((rpmrc = rpmcliImportPubkey(ts, pkt, pktlen)) != RPMRC_OK) { 00782 rpmlog(RPMLOG_ERR, _("%s: import failed.\n"), fn); 00783 res++; 00784 continue; 00785 } 00786 00787 } 00788 00789 rpmtsClean(ts); 00790 pkt = _free(pkt); 00791 t = _free(t); 00792 return res; 00793 } 00794 00798 static rpmRC readFile(FD_t fd, const char * fn) 00799 /*@globals fileSystem, internalState @*/ 00800 /*@modifies fd, fileSystem, internalState @*/ 00801 { 00802 rpmxar xar = fdGetXAR(fd); 00803 pgpDig dig = fdGetDig(fd); 00804 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00805 unsigned char buf[4*BUFSIZ]; 00806 ssize_t count; 00807 rpmRC rc; 00808 int xx; 00809 00810 dig->nbytes = 0; 00811 00812 /* Read the header from the package. */ 00813 { Header h = NULL; 00814 const char item[] = "Header"; 00815 const char * msg = NULL; 00816 rc = rpmpkgRead(item, fd, &h, &msg); 00817 if (rc != RPMRC_OK) { 00818 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg); 00819 msg = _free(msg); 00820 goto exit; 00821 } 00822 msg = _free(msg); 00823 00824 dig->nbytes += headerSizeof(h); 00825 00826 if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) { 00827 unsigned char * hmagic = NULL; 00828 size_t nmagic = 0; 00829 00830 he->tag = RPMTAG_HEADERIMMUTABLE; 00831 xx = headerGet(h, he, 0); 00832 if (!xx || he->p.ptr == NULL) { 00833 (void)headerFree(h); 00834 h = NULL; 00835 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, _("headerGet failed"), 00836 _("failed to retrieve original header\n")); 00837 rc = RPMRC_FAIL; 00838 goto exit; 00839 } 00840 (void) headerGetMagic(NULL, &hmagic, &nmagic); 00841 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); 00842 if (hmagic && nmagic > 0) 00843 (void) rpmDigestUpdate(dig->hdrsha1ctx, hmagic, nmagic); 00844 (void) rpmDigestUpdate(dig->hdrsha1ctx, he->p.ptr, he->c); 00845 dig->hdrctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE); 00846 if (hmagic && nmagic > 0) 00847 (void) rpmDigestUpdate(dig->hdrctx, hmagic, nmagic); 00848 (void) rpmDigestUpdate(dig->hdrctx, he->p.ptr, he->c); 00849 he->p.ptr = _free(he->p.ptr); 00850 } 00851 (void)headerFree(h); 00852 h = NULL; 00853 } 00854 00855 if (xar != NULL) { 00856 const char item[] = "Payload"; 00857 if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) { 00858 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, 00859 _("XAR file not found (or no XAR support)")); 00860 rc = RPMRC_NOTFOUND; 00861 goto exit; 00862 } 00863 } 00864 00865 /* Read the payload from the package. */ 00866 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) 00867 dig->nbytes += count; 00868 if (count < 0 || Ferror(fd)) { 00869 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, _("Fread failed"), Fstrerror(fd)); 00870 rc = RPMRC_FAIL; 00871 goto exit; 00872 } 00873 00874 /* XXX Steal the digest-in-progress from the file handle. */ 00875 fdStealDigest(fd, dig); 00876 00877 rc = RPMRC_OK; /* XXX unnecessary */ 00878 00879 exit: 00880 return rc; 00881 } 00882 00883 int rpmVerifySignatures(QVA_t qva, rpmts ts, void * _fd, const char * fn) 00884 { 00885 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00886 HE_t she = memset(alloca(sizeof(*she)), 0, sizeof(*she)); 00887 /*@-castexpose@*/ 00888 FD_t fd = (FD_t)_fd; 00889 /*@=castexpose@*/ 00890 char result[1024]; 00891 char buf[8192], * b; 00892 char missingKeys[7164], * m; 00893 char untrustedKeys[7164], * u; 00894 pgpDig dig; 00895 pgpDigParams sigp; 00896 Header sigh = NULL; 00897 HeaderIterator hi = NULL; 00898 const char * msg = NULL; 00899 int res = 0; 00900 int xx; 00901 rpmRC rc, sigres; 00902 int failed; 00903 int nodigests = !(qva->qva_flags & VERIFY_DIGEST); 00904 int nosignatures = !(qva->qva_flags & VERIFY_SIGNATURE); 00905 00906 { 00907 { const char item[] = "Lead"; 00908 msg = NULL; 00909 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */ 00910 rc = rpmpkgRead(item, fd, NULL, &msg); 00911 /*@=mods@*/ 00912 if (rc != RPMRC_OK) { 00913 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg); 00914 msg = _free(msg); 00915 res++; 00916 goto exit; 00917 } 00918 msg = _free(msg); 00919 } 00920 00921 { const char item[] = "Signature"; 00922 msg = NULL; 00923 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */ 00924 rc = rpmpkgRead(item, fd, &sigh, &msg); 00925 /*@=mods@*/ 00926 switch (rc) { 00927 default: 00928 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, 00929 (msg && *msg ? msg : "")); 00930 msg = _free(msg); 00931 res++; 00932 goto exit; 00933 /*@notreached@*/ /*@switchbreak@*/ break; 00934 case RPMRC_OK: 00935 if (sigh == NULL) { 00936 rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn); 00937 res++; 00938 goto exit; 00939 } 00940 /*@switchbreak@*/ break; 00941 } 00942 msg = _free(msg); 00943 } 00944 00945 /* Grab a hint of what needs doing to avoid duplication. */ 00946 she->tag = 0; 00947 if (she->tag == 0 && !nosignatures) { 00948 if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_DSA)) 00949 she->tag = (rpmTag) RPMSIGTAG_DSA; 00950 else if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_RSA)) 00951 she->tag = (rpmTag) RPMSIGTAG_RSA; 00952 } 00953 if (she->tag == 0 && !nodigests) { 00954 if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_MD5)) 00955 she->tag = (rpmTag) RPMSIGTAG_MD5; 00956 else if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_SHA1)) 00957 she->tag = (rpmTag) RPMSIGTAG_SHA1; /* XXX never happens */ 00958 } 00959 00960 dig = rpmtsDig(ts); 00961 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */ 00962 (void) fdSetDig(fd, dig); 00963 /*@=mods@*/ 00964 sigp = pgpGetSignature(dig); 00965 00966 /* XXX RSA needs the hash_algo, so decode early. */ 00967 if ((rpmSigTag) she->tag == RPMSIGTAG_RSA) { 00968 he->tag = she->tag; 00969 xx = headerGet(sigh, he, 0); 00970 xx = pgpPrtPkts(he->p.ptr, he->c, dig, 0); 00971 he->p.ptr = _free(he->p.ptr); 00972 } 00973 00974 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */ 00975 if (headerIsEntry(sigh, (rpmTag)RPMSIGTAG_MD5)) 00976 fdInitDigest(fd, PGPHASHALGO_MD5, 0); 00977 /*@=mods@*/ 00978 00979 /* Read the file, generating digest(s) on the fly. */ 00980 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */ 00981 if (dig == NULL || sigp == NULL 00982 || readFile(fd, fn) != RPMRC_OK) 00983 { 00984 res++; 00985 goto exit; 00986 } 00987 /*@=mods@*/ 00988 00989 failed = 0; 00990 b = buf; *b = '\0'; 00991 m = missingKeys; *m = '\0'; 00992 u = untrustedKeys; *u = '\0'; 00993 sprintf(b, "%s:%c", fn, (rpmIsVerbose() ? '\n' : ' ') ); 00994 b += strlen(b); 00995 00996 if (sigh != NULL) 00997 for (hi = headerInit(sigh); 00998 headerNext(hi, she, 0) != 0; 00999 she->p.ptr = _free(she->p.ptr)) 01000 { 01001 01002 assert(she->p.ptr != NULL); 01003 01004 /* Clean up parameters from previous she->tag. */ 01005 pgpDigClean(dig); 01006 01007 /*@-ownedtrans -noeffect@*/ 01008 xx = pgpSetSig(dig, she->tag, she->t, she->p.ptr, she->c); 01009 /*@=ownedtrans =noeffect@*/ 01010 01011 switch ((rpmSigTag)she->tag) { 01012 case RPMSIGTAG_RSA: 01013 case RPMSIGTAG_DSA: 01014 if (nosignatures) 01015 continue; 01016 xx = pgpPrtPkts(she->p.ptr, she->c, dig, 01017 (_print_pkts & rpmIsDebug())); 01018 01019 if (sigp->version != 3 && sigp->version != 4) { 01020 rpmlog(RPMLOG_ERR, 01021 _("skipping package %s with unverifiable V%u signature\n"), 01022 fn, sigp->version); 01023 res++; 01024 goto exit; 01025 } 01026 /*@switchbreak@*/ break; 01027 case RPMSIGTAG_SHA1: 01028 if (nodigests) 01029 continue; 01030 /* XXX Don't bother with header sha1 if header dsa. */ 01031 if (!nosignatures && (rpmSigTag)she->tag == RPMSIGTAG_DSA) 01032 continue; 01033 /*@switchbreak@*/ break; 01034 case RPMSIGTAG_MD5: 01035 if (nodigests) 01036 continue; 01037 /*@switchbreak@*/ break; 01038 default: 01039 continue; 01040 /*@notreached@*/ /*@switchbreak@*/ break; 01041 } 01042 01043 sigres = rpmVerifySignature(dig, result); 01044 01045 if (sigres) { 01046 failed = 1; 01047 if (rpmIsVerbose()) 01048 b = stpcpy( stpcpy( stpcpy(b, " "), result), "\n"); 01049 else 01050 switch ((rpmSigTag)she->tag) { 01051 case RPMSIGTAG_SIZE: 01052 b = stpcpy(b, "SIZE "); 01053 /*@switchbreak@*/ break; 01054 case RPMSIGTAG_SHA1: 01055 b = stpcpy(b, "SHA1 "); 01056 /*@switchbreak@*/ break; 01057 case RPMSIGTAG_MD5: 01058 b = stpcpy(b, "MD5 "); 01059 /*@switchbreak@*/ break; 01060 case RPMSIGTAG_RSA: 01061 b = stpcpy(b, "RSA "); 01062 /*@switchbreak@*/ break; 01063 case RPMSIGTAG_DSA: 01064 b = stpcpy(b, "(SHA1) DSA "); 01065 /*@switchbreak@*/ break; 01066 default: 01067 b = stpcpy(b, "?UnknownSignatureType? "); 01068 /*@switchbreak@*/ break; 01069 } 01070 } else { 01071 if (rpmIsVerbose()) 01072 b = stpcpy( stpcpy( stpcpy(b, " "), result), "\n"); 01073 else 01074 switch ((rpmSigTag)she->tag) { 01075 case RPMSIGTAG_SIZE: 01076 b = stpcpy(b, "size "); 01077 /*@switchbreak@*/ break; 01078 case RPMSIGTAG_SHA1: 01079 b = stpcpy(b, "sha1 "); 01080 /*@switchbreak@*/ break; 01081 case RPMSIGTAG_MD5: 01082 b = stpcpy(b, "md5 "); 01083 /*@switchbreak@*/ break; 01084 case RPMSIGTAG_RSA: 01085 b = stpcpy(b, "rsa "); 01086 /*@switchbreak@*/ break; 01087 case RPMSIGTAG_DSA: 01088 b = stpcpy(b, "(sha1) dsa "); 01089 /*@switchbreak@*/ break; 01090 default: 01091 b = stpcpy(b, "??? "); 01092 /*@switchbreak@*/ break; 01093 } 01094 } 01095 } 01096 hi = headerFini(hi); 01097 /* XXX clear the already free'd signature data. */ 01098 /*@-noeffect@*/ 01099 xx = pgpSetSig(dig, 0, 0, NULL, 0); 01100 /*@=noeffect@*/ 01101 01102 res += failed; 01103 01104 if (failed) { 01105 if (rpmIsVerbose()) { 01106 rpmlog(RPMLOG_NOTICE, "%s", buf); 01107 } else { 01108 rpmlog(RPMLOG_NOTICE, "%s%s%s%s%s%s%s%s\n", buf, 01109 _("NOT_OK"), 01110 (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "", 01111 missingKeys, 01112 (missingKeys[0] != '\0') ? _(") ") : "", 01113 (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "", 01114 untrustedKeys, 01115 (untrustedKeys[0] != '\0') ? _(")") : ""); 01116 01117 } 01118 } else { 01119 if (rpmIsVerbose()) { 01120 rpmlog(RPMLOG_NOTICE, "%s", buf); 01121 } else { 01122 rpmlog(RPMLOG_NOTICE, "%s%s%s%s%s%s%s%s\n", buf, 01123 _("OK"), 01124 (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "", 01125 missingKeys, 01126 (missingKeys[0] != '\0') ? _(") ") : "", 01127 (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "", 01128 untrustedKeys, 01129 (untrustedKeys[0] != '\0') ? _(")") : ""); 01130 } 01131 } 01132 01133 } 01134 01135 exit: 01136 rpmtsCleanDig(ts); 01137 (void)headerFree(sigh); 01138 sigh = NULL; 01139 return res; 01140 } 01141 01142 int rpmcliSign(rpmts ts, QVA_t qva, const char ** argv) 01143 /*@globals rpmioFtsOpts @*/ 01144 /*@modifies rpmioFtsOpts @*/ 01145 { 01146 int res = 0; 01147 01148 if (argv == NULL) return res; 01149 01150 switch (qva->qva_mode) { 01151 case RPMSIGN_CHK_SIGNATURE: 01152 break; 01153 case RPMSIGN_IMPORT_PUBKEY: 01154 return rpmcliImportPubkeys(ts, qva, argv); 01155 /*@notreached@*/ break; 01156 case RPMSIGN_NEW_SIGNATURE: 01157 case RPMSIGN_ADD_SIGNATURE: 01158 case RPMSIGN_DEL_SIGNATURE: 01159 return rpmReSign(ts, qva, argv); 01160 /*@notreached@*/ break; 01161 case RPMSIGN_NONE: 01162 default: 01163 return -1; 01164 /*@notreached@*/ break; 01165 } 01166 01167 { /* start-of-arg-iteration */ 01168 01169 int tag = (qva->qva_source == RPMQV_FTSWALK) 01170 ? RPMDBI_FTSWALK : RPMDBI_ARGLIST; 01171 rpmgi gi = rpmgiNew(ts, tag, NULL, 0); 01172 rpmgiFlags _giFlags = RPMGI_NONE; 01173 rpmRC rc; 01174 01175 if (rpmioFtsOpts == 0) 01176 rpmioFtsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT); 01177 rc = rpmgiSetArgs(gi, argv, rpmioFtsOpts, (_giFlags|RPMGI_NOHEADER)); 01178 while (rpmgiNext(gi) == RPMRC_OK) { 01179 const char * fn = rpmgiHdrPath(gi); 01180 FD_t fd; 01181 int xx; 01182 01183 fd = Fopen(fn, "r.fdio"); 01184 if (fd == NULL || Ferror(fd)) { 01185 rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"), 01186 fn, Fstrerror(fd)); 01187 res++; 01188 } else if (rpmVerifySignatures(qva, ts, fd, fn)) { 01189 res++; 01190 } 01191 01192 if (fd != NULL) { 01193 xx = Fclose(fd); 01194 } 01195 } 01196 01197 gi = rpmgiFree(gi); 01198 01199 } /* end-of-arg-iteration */ 01200 01201 return res; 01202 }