rpm  5.4.15
rpmchecksig.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio_internal.h>
9 #include <poptIO.h>
10 #include <rpmbc.h> /* XXX beecrypt base64 */
11 
12 #define _RPMHKP_INTERNAL /* XXX internal prototypes. */
13 #include <rpmhkp.h>
14 
15 #include <rpmtag.h>
16 #include <rpmtypes.h>
17 #define _RPMEVR_INTERNAL /* XXX RPMSENSE_KEYRING */
18 #include <rpmevr.h>
19 #define _RPMDB_INTERNAL /* XXX db_txn */
20 #include <rpmdb.h>
21 #include <rpmtxn.h>
22 #include <rpmxar.h>
23 #include <pkgio.h>
24 #include "signature.h"
25 
26 #define _RPMTS_INTERNAL /* XXX ts->hkp */
27 #include <rpmts.h>
28 
29 #include "rpmgi.h"
30 
31 #include <rpmversion.h>
32 #include <rpmcli.h>
33 
34 #include "debug.h"
35 
36 /*@access FD_t @*/ /* XXX stealing digests */
37 /*@access Header @*/ /* XXX void * arg */
38 /*@access pgpDig @*/
39 /*@access pgpDigParams @*/
40 
41 #ifdef __cplusplus
42 GENfree(struct rpmlead *)
43 GENfree(rpmuint8_t **)
44 #endif /* __cplusplus */
45 
46 /*@unchecked@*/
47 int _print_pkts = 0;
48 
51 static int manageFile(/*@out@*/ FD_t *fdp,
52  /*@null@*/ /*@out@*/ const char **fnp,
53  int flags, /*@unused@*/ int rc)
54  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
55  /*@modifies *fdp, *fnp, rpmGlobalMacroContext,
56  fileSystem, internalState @*/
57 {
58  const char *fn;
59  FD_t fd;
60 
61  if (fdp == NULL) /* programmer error */
62  return 1;
63 
64  /* close and reset *fdp to NULL */
65  if (*fdp && (fnp == NULL || *fnp == NULL)) {
66  (void) Fclose(*fdp);
67  *fdp = NULL;
68  return 0;
69  }
70 
71  /* open a file and set *fdp */
72  if (*fdp == NULL && fnp != NULL && *fnp != NULL) {
73  fd = Fopen(*fnp, ((flags & O_WRONLY) ? "w.fdio" : "r.fdio"));
74  if (fd == NULL || Ferror(fd)) {
75  rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"), *fnp,
76  Fstrerror(fd));
77  return 1;
78  }
79  *fdp = fd;
80  return 0;
81  }
82 
83  /* open a temp file */
84  if (*fdp == NULL && (fnp == NULL || *fnp == NULL)) {
85  fn = NULL;
86  if (rpmTempFile(NULL, (fnp ? &fn : NULL), &fd)) {
87  rpmlog(RPMLOG_ERR, _("rpmTempFile failed\n"));
88  return 1;
89  }
90  if (fnp != NULL)
91  *fnp = fn;
92 /*@-refcounttrans@*/ /* FIX: XfdLink/XfdFree annotation */
93  *fdp = fdLink(fd, "manageFile return");
94  fd = fdFree(fd, "manageFile return");
95 /*@=refcounttrans@*/
96  return 0;
97  }
98 
99  /* no operation */
100  if (*fdp != NULL && fnp != NULL && *fnp != NULL)
101  return 0;
102 
103  /* XXX never reached */
104  return 1;
105 }
106 
110 static int copyFile(FD_t *sfdp, const char **sfnp,
111  FD_t *tfdp, const char **tfnp)
112  /*@globals rpmGlobalMacroContext, h_errno,
113  fileSystem, internalState @*/
114  /*@modifies *sfdp, *sfnp, *tfdp, *tfnp, rpmGlobalMacroContext,
115  fileSystem, internalState @*/
116 {
117  unsigned char buf[BUFSIZ];
118  ssize_t count;
119  int rc = 1;
120 
121  if (manageFile(sfdp, sfnp, O_RDONLY, 0))
122  goto exit;
123  if (manageFile(tfdp, tfnp, O_WRONLY|O_CREAT|O_TRUNC, 0))
124  goto exit;
125 
126  while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), *sfdp)) > 0)
127  {
128  if (Fwrite(buf, sizeof(buf[0]), count, *tfdp) != (size_t)count) {
129  rpmlog(RPMLOG_ERR, _("%s: Fwrite failed: %s\n"), *tfnp,
130  Fstrerror(*tfdp));
131  goto exit;
132  }
133  }
134  if (count < 0) {
135  rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"), *sfnp, Fstrerror(*sfdp));
136  goto exit;
137  }
138  if (Fflush(*tfdp) != 0) {
139  rpmlog(RPMLOG_ERR, _("%s: Fflush failed: %s\n"), *tfnp,
140  Fstrerror(*tfdp));
141  goto exit;
142  }
143 
144  rc = 0;
145 
146 exit:
147  if (*sfdp) (void) manageFile(sfdp, NULL, 0, rc);
148  if (*tfdp) (void) manageFile(tfdp, NULL, 0, rc);
149  return rc;
150 }
151 
159 static int getSignid(Header sigh, rpmSigTag sigtag, unsigned char * signid)
160  /*@globals fileSystem, internalState @*/
161  /*@modifies *signid, fileSystem, internalState @*/
162 {
163  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
164  int rc = 1;
165  int xx;
166 
167  he->tag = (rpmTag) sigtag;
168  xx = headerGet(sigh, he, 0);
169  if (xx && he->p.ptr != NULL) {
171 
172  /* XXX expose ppSignid() from rpmhkp.c? */
173  pgpPkt pp = (pgpPkt) alloca(sizeof(*pp));
174  (void) pgpPktLen(he->p.ui8p, he->c, pp);
175  if (!rpmhkpLoadSignature(NULL, dig, pp)) {
176  memcpy(signid, dig->signature.signid, sizeof(dig->signature.signid));
177  rc = 0;
178  }
179 
180  he->p.ptr = _free(he->p.ptr);
181  dig = pgpDigFree(dig);
182  }
183  return rc;
184 }
185 
193 static int rpmReSign(/*@unused@*/ rpmts ts,
194  QVA_t qva, const char ** argv)
195  /*@globals rpmGlobalMacroContext, h_errno,
196  fileSystem, internalState @*/
197  /*@modifies ts, rpmGlobalMacroContext,
198  fileSystem, internalState @*/
199 {
200  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
201  rpmgi gi = NULL;
202  FD_t fd = NULL;
203  FD_t ofd = NULL;
204  struct rpmlead *lead = NULL;
205  rpmSigTag sigtag;
206  const char *sigtarget = NULL;
207  char tmprpm[1024+1];
208  Header sigh = NULL;
209  int res = 1; /* XXX assume failure */
210  int deleting = (qva->qva_mode == RPMSIGN_DEL_SIGNATURE);
211  rpmRC rpmrc = RPMRC_OK;
212  int xx;
213  int i;
214  mode_t mode;
215 
216  tmprpm[0] = '\0';
217 
218  if (argv)
219  { /* start-of-arg-iteration */
220  rpmuint32_t tag = (qva->qva_source == RPMQV_FTSWALK)
222  rpmgiFlags _giFlags = RPMGI_NONE;
223 
224  gi = rpmgiNew(ts, tag, NULL, 0);
225 /*@-mods@*/
226  if (rpmioFtsOpts == 0)
228 /*@=mods@*/
229  rpmrc = rpmgiSetArgs(gi, argv, rpmioFtsOpts, (rpmgiFlags)(_giFlags|RPMGI_NOHEADER));
230 
231  while ((rpmrc = rpmgiNext(gi)) == RPMRC_OK) {
232  const char * fn = rpmgiHdrPath(gi);
233  const char * tfn;
234 
235  fprintf(stdout, "%s:\n", fn);
236 
237 /*@-modobserver@*/ /* XXX rpmgiHdrPath should not be observer */
238  if (manageFile(&fd, &fn, O_RDONLY, 0))
239  goto exit;
240 /*@=modobserver@*/
241 
242  { const char item[] = "Lead";
243  const char * msg = NULL;
244  rpmRC rc = rpmpkgRead(item, fd, &lead, &msg);
245  if (rc != RPMRC_OK) {
246  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
247  msg = _free(msg);
248  goto exit;
249  }
250  msg = _free(msg);
251  }
252 
253  { const char item[] = "Signature";
254  const char * msg = NULL;
255  rpmRC rc = rpmpkgRead(item, fd, &sigh, &msg);
256  switch (rc) {
257  default:
258  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item,
259  (msg && *msg ? msg : ""));
260  msg = _free(msg);
261  goto exit;
262  /*@notreached@*/ /*@switchbreak@*/ break;
263  case RPMRC_OK:
264  if (sigh == NULL) {
265  rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
266  goto exit;
267  }
268  /*@switchbreak@*/ break;
269  }
270  msg = _free(msg);
271  }
272 
273  /* Write the header and archive to a temp file */
274  /* ASSERT: ofd == NULL && sigtarget == NULL */
275 /*@-modobserver@*/ /* XXX rpmgiHdrPath should not be observer */
276  if (copyFile(&fd, &fn, &ofd, &sigtarget))
277  goto exit;
278 /*@=modobserver@*/
279  /* Both fd and ofd are now closed. sigtarget contains tempfile name. */
280  /* ASSERT: fd == NULL && ofd == NULL */
281 
282  /* Lose the immutable region (if present). */
284  xx = headerGet(sigh, he, 0);
285  if (xx) {
286  HE_t ohe = (HE_t) memset(alloca(sizeof(*ohe)), 0, sizeof(*ohe));
287  HeaderIterator hi;
288  Header oh;
289  Header nh;
290 
291  nh = headerNew();
292  if (nh == NULL) {
293  he->p.ptr = _free(he->p.ptr);
294  goto exit;
295  }
296 
297  oh = headerCopyLoad(he->p.ptr);
298  for (hi = headerInit(oh);
299  headerNext(hi, ohe, 0);
300  ohe->p.ptr = _free(ohe->p.ptr))
301  {
302  if (ohe->p.ptr) {
303  xx = headerPut(nh, ohe, 0);
304  }
305  }
306  hi = headerFini(hi);
307  (void)headerFree(oh);
308  oh = NULL;
309 
310  (void)headerFree(sigh);
311  sigh = NULL;
312  sigh = headerLink(nh);
313  (void)headerFree(nh);
314  nh = NULL;
315  }
316 
317 if (sigh != NULL) {
318  /* Eliminate broken digest values. */
320  xx = headerDel(sigh, he, 0);
322  xx = headerDel(sigh, he, 0);
324  xx = headerDel(sigh, he, 0);
326  xx = headerDel(sigh, he, 0);
327 
328  /* Toss and recalculate header+payload size and digests. */
329  { static const rpmuint32_t sigs[] =
331  size_t nsigs = sizeof(sigs) / sizeof(sigs[0]);
332  for (i = 0; i < (int)nsigs; i++) {
333  he->tag = (rpmTag)sigs[i];
334  xx = headerDel(sigh, he, 0);
335  xx = rpmAddSignature(sigh, sigtarget, (rpmSigTag) he->tag, qva->passPhrase);
336  if (xx)
337  goto exit;
338  }
339  }
340 
341  if (deleting) {
342  /* Nuke all the signature tags. */
343  static const rpmuint32_t sigs[] =
346  size_t nsigs = sizeof(sigs) / sizeof(sigs[0]);
347  for (i = 0; i < (int)nsigs; i++) {
348  he->tag = (rpmTag)sigs[i];
349  xx = headerDel(sigh, he, 0);
350  }
351  } else { /* If gpg/pgp is configured, replace the signature. */
352  int addsig = 0;
353  sigtag = RPMSIGTAG_GPG;
354  addsig = 1;
355 
356  if (addsig) {
357  unsigned char oldsignid[8], newsignid[8];
358 
359  /* Grab the old signature fingerprint (if any) */
360  memset(oldsignid, 0, sizeof(oldsignid));
361  xx = getSignid(sigh, sigtag, oldsignid);
362 
363  switch (sigtag) {
364  default:
365  /*@switchbreak@*/ break;
366  case RPMSIGTAG_ECDSA:
367 #ifdef NOTYET /* XXX FIXME: W2DO? */
368  he->tag = (rpmTag)RPMSIGTAG_GPG;
369  xx = headerDel(sigh, he, 0);
370 #endif
371  /*@switchbreak@*/ break;
372  case RPMSIGTAG_DSA:
373  he->tag = (rpmTag)RPMSIGTAG_GPG;
374  xx = headerDel(sigh, he, 0);
375  /*@switchbreak@*/ break;
376  case RPMSIGTAG_RSA:
377  he->tag = (rpmTag)RPMSIGTAG_PGP;
378  xx = headerDel(sigh, he, 0);
379  /*@switchbreak@*/ break;
380  case RPMSIGTAG_GPG:
381  he->tag = (rpmTag)RPMSIGTAG_PGP;
382  xx = headerDel(sigh, he, 0);
383  he->tag = (rpmTag)RPMSIGTAG_DSA;
384  xx = headerDel(sigh, he, 0);
385  /*@fallthrough@*/
386  case RPMSIGTAG_PGP5:
387  case RPMSIGTAG_PGP:
388  he->tag = (rpmTag)RPMSIGTAG_RSA;
389  xx = headerDel(sigh, he, 0);
390  /*@switchbreak@*/ break;
391  }
392 
393  he->tag = (rpmTag)sigtag;
394  xx = headerDel(sigh, he, 0);
395  xx = rpmAddSignature(sigh, sigtarget, sigtag, qva->passPhrase);
396  if (xx)
397  goto exit;
398 
399  /* If package was previously signed, check for same signer. */
400  memset(newsignid, 0, sizeof(newsignid));
401  if (memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
402 
403  /* Grab the new signature fingerprint */
404  xx = getSignid(sigh, sigtag, newsignid);
405 
406  /* If same signer, skip resigning the package. */
407  if (!memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
408 
410  _("%s: was already signed by key ID %s, skipping\n"),
411  fn, pgpHexStr(newsignid+4, sizeof(newsignid)-4));
412 
413  /* Clean up intermediate target */
414  xx = Unlink(sigtarget);
415  sigtarget = _free(sigtarget);
416  continue;
417  }
418  }
419  }
420  }
421 
422  /* Reallocate the signature into one contiguous region. */
424  if (sigh == NULL) /* XXX can't happen */
425  goto exit;
426 }
427 
428  /* Write the lead/signature of the output rpm */
429  (void) stpcpy( stpcpy(tmprpm, fn), ".XXXXXX");
430 
431 #if defined(HAVE_MKSTEMP)
432  mode = umask(0077);
433  (void) close(mkstemp(tmprpm));
434  (void) umask(mode);
435 #else
436  (void) mktemp(tmprpm);
437 #endif
438  tfn = tmprpm;
439 
440  if (manageFile(&ofd, &tfn, O_WRONLY|O_CREAT|O_TRUNC, 0))
441  goto exit;
442 
443  { const char item[] = "Lead";
444  const char * msg = NULL;
445  rpmRC rc = rpmpkgWrite(item, ofd, lead, &msg);
446  if (rc != RPMRC_OK) {
447  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", tfn, item, Fstrerror(ofd));
448  msg = _free(msg);
449  goto exit;
450  }
451  msg = _free(msg);
452  }
453 
454  { const char item[] = "Signature";
455  const char * msg = NULL;
456  rpmRC rc = rpmpkgWrite(item, ofd, sigh, &msg);
457  if (rc != RPMRC_OK) {
458  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", tfn, item, Fstrerror(ofd));
459  msg = _free(msg);
460  goto exit;
461  }
462  msg = _free(msg);
463  }
464  (void)headerFree(sigh);
465  sigh = NULL;
466 
467  /* Append the header and archive from the temp file */
468  /* ASSERT: fd == NULL && ofd != NULL */
469  if (copyFile(&fd, &sigtarget, &ofd, &tfn))
470  goto exit;
471  /* Both fd and ofd are now closed. */
472  /* ASSERT: fd == NULL && ofd == NULL */
473 
474  /* Move final target into place. */
475  xx = Unlink(fn);
476  xx = Rename(tfn, fn);
477  tmprpm[0] = '\0';
478 
479  /* Clean up intermediate target */
480  xx = Unlink(sigtarget);
481  sigtarget = _free(sigtarget);
482  }
483 
484  /* XXX disambiguate end-of-iteration from item failures. */
485  if (rpmrc == RPMRC_NOTFOUND)
486  rpmrc = (rpmRC) rpmgiRc(gi);
487 
488  } /* end-of-arg-iteration */
489 
490  if (rpmrc == RPMRC_OK)
491  res = 0;
492 
493 exit:
494  gi = rpmgiFree(gi);
495 
496  if (fd) (void) manageFile(&fd, NULL, 0, res);
497  if (ofd) (void) manageFile(&ofd, NULL, 0, res);
498 
499  lead = _free(lead);
500  (void)headerFree(sigh);
501  sigh = NULL;
502 
503  if (sigtarget) {
504  xx = Unlink(sigtarget);
505  sigtarget = _free(sigtarget);
506  }
507  if (tmprpm[0] != '\0') {
508  xx = Unlink(tmprpm);
509  tmprpm[0] = '\0';
510  }
511 
512  return res;
513 }
514 
515 rpmRC rpmcliImportPubkey(const rpmts ts, const unsigned char * pkt, ssize_t pktlen)
516 {
517  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
518  static unsigned char zeros[] =
519  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
520  const char * afmt = "%{pubkeys:armor}";
521  const char * group = "Public Keys";
522  const char * license = "pubkey";
523  const char * buildhost = "localhost";
524  rpmuint32_t pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL);
525  rpmuint32_t zero = 0;
526  pgpDig dig = NULL;
527  pgpDigParams pubp = NULL;
528  const char * d = NULL;
529  const char * enc = NULL;
530  const char * n = NULL;
531  const char * u = NULL;
532  const char * v = NULL;
533  const char * r = NULL;
534  const char * evr = NULL;
535  Header h = NULL;
536  rpmRC rc = RPMRC_FAIL; /* assume failure */
537  char * t;
538  int xx;
539 rpmhkp hkp = NULL;
540 pgpPkt pp = (pgpPkt) alloca(sizeof(*pp));
541 int validate = 1;
542 
543  /* XXX coverity #1035781 */
544  /* Validate the pubkey. */
545  if (ts->hkp == NULL)
546  ts->hkp = rpmhkpNew(NULL, 0);
547  hkp = rpmhkpLink(ts->hkp);
548 hkp->pkt = (rpmuint8_t *)pkt;
549 hkp->pktlen = pktlen;
550 
551  if (pkt == NULL || pktlen <= 0)
552  goto exit;
553  if (rpmtsOpenDB(ts, (O_RDWR|O_CREAT)))
554  goto exit;
555 
556 /*@-moduncon@*/
557  if ((enc = b64encode(pkt, pktlen)) == NULL)
558  goto exit;
559 /*@=moduncon@*/
560 
562  pubp = pgpGetPubkey(dig);
563 
564  xx = pgpGrabPkts(hkp->pkt, hkp->pktlen, &hkp->pkts, &hkp->npkts);
565  if (!xx)
566  (void) pgpPubkeyFingerprint(hkp->pkt, hkp->pktlen, hkp->keyid);
567  memcpy(pubp->signid, hkp->keyid, sizeof(pubp->signid)); /* XXX useless */
568 
569  xx = pgpPktLen(hkp->pkt, hkp->pktlen, pp);
570 
571  xx = rpmhkpLoadKey(hkp, dig, 0, 0);
572 
573  /* Validate pubkey self-signatures. */
574  if (validate) {
575  rpmRC yy = rpmhkpValidate(hkp, NULL);
576  switch (yy) {
577  case RPMRC_OK:
578  break;
579  case RPMRC_NOTFOUND:
580  case RPMRC_FAIL: /* XXX remap to NOTFOUND? */
581  case RPMRC_NOTTRUSTED:
582  case RPMRC_NOKEY:
583  default:
584 #ifdef NOTYET /* XXX make check-pubkey fails?!? . */
585  rc = yy;
586  goto exit;
587 #endif
588  /*@notreached@*/ break;
589  }
590  }
591 
592  /* XXX hack up a user id (if not already present) */
593  if (pubp->userid == NULL) {
594  if (hkp->uidx >= 0 && hkp->uidx < hkp->npkts) {
595  size_t nb = pgpPktLen(hkp->pkts[hkp->uidx], hkp->pktlen, pp);
596  char * t;
597  nb = pp->hlen;
598  t = (char *) memcpy(xmalloc(nb + 1), pp->u.u->userid, nb);
599  t[nb] = '\0';
600  pubp->userid = t;
601  } else
602  pubp->userid = xstrdup(pgpHexStr(pubp->signid+4, 4));
603  }
604 
605 #ifdef DYING
606 _rpmhkpDumpDig(__FUNCTION__, dig);
607 #endif
608 
609  /* Build header elements. */
610  if (!memcmp(pubp->signid, zeros, sizeof(pubp->signid))
611  || !memcmp(pubp->time, zeros, sizeof(pubp->time))
612  || pubp->userid == NULL)
613  goto exit;
614 
615  v = t = (char *) xmalloc(16+1);
616  t = stpcpy(t, pgpHexStr(pubp->signid, sizeof(pubp->signid)));
617 
618  r = t = (char *) xmalloc(8+1);
619  t = stpcpy(t, pgpHexStr(pubp->time, sizeof(pubp->time)));
620 
621  n = t = (char *) xmalloc(sizeof("gpg()")+8);
622  t = stpcpy( stpcpy( stpcpy(t, "gpg("), v+8), ")");
623 
624  { const char * userid =
625  (pubp->userid ? pubp->userid : pgpHexStr(pubp->signid+4, 4));
626  u = t = (char *) xmalloc(sizeof("gpg()")+strlen(userid));
627  t = stpcpy( stpcpy( stpcpy(t, "gpg("), userid), ")");
628  }
629 
630  evr = t = (char *) xmalloc(sizeof("4X:-")+strlen(v)+strlen(r));
631  t = stpcpy(t, (pubp->version == 4 ? "4:" : "3:"));
632  t = stpcpy( stpcpy( stpcpy(t, v), "-"), r);
633 
634  /* Check for pre-existing header. */
635 
636  /* Build pubkey header. */
637  h = headerNew();
638 
639  he->append = 1;
640 
641  he->tag = RPMTAG_PUBKEYS;
642  he->t = RPM_STRING_ARRAY_TYPE;
643  he->p.argv = &enc;
644  he->c = 1;
645  xx = headerPut(h, he, 0);
646 
647  he->append = 0;
648 
649  d = headerSprintf(h, afmt, NULL, rpmHeaderFormats, NULL);
650  if (d == NULL)
651  goto exit;
652 
653  he->t = RPM_STRING_TYPE;
654  he->c = 1;
655  he->tag = RPMTAG_NAME;
656  he->p.str = xstrdup("gpg-pubkey");
657  xx = headerPut(h, he, 0);
658  he->p.ptr = _free(he->p.ptr);
659  he->tag = RPMTAG_VERSION;
660  he->p.str = v+8;
661  xx = headerPut(h, he, 0);
662  he->tag = RPMTAG_RELEASE;
663  he->p.str = xstrdup(r);
664  xx = headerPut(h, he, 0);
665  he->p.ptr = _free(he->p.ptr);
666 
667  /* Add Summary/Description/Group. */
668  he->tag = RPMTAG_DESCRIPTION;
669  he->p.str = xstrdup(d);
670 #if defined(SUPPORT_I18NSTRING_TYPE)
671  xx = headerAddI18NString(h, he->tag, he->p.str, "C");
672 #else
673  xx = headerPut(h, he, 0);
674 #endif
675  he->p.ptr = _free(he->p.ptr);
676 
677  he->tag = RPMTAG_GROUP;
678  he->p.str = xstrdup(group);
679 #if defined(SUPPORT_I18NSTRING_TYPE)
680  xx = headerAddI18NString(h, he->tag, he->p.str, "C");
681 #else
682  xx = headerPut(h, he, 0);
683 #endif
684  he->p.ptr = _free(he->p.ptr);
685 
686  he->tag = RPMTAG_SUMMARY;
687  he->p.str = xstrdup(u);
688 #if defined(SUPPORT_I18NSTRING_TYPE)
689  xx = headerAddI18NString(h, he->tag, he->p.str, "C");
690 #else
691  xx = headerPut(h, he, 0);
692 #endif
693  he->p.ptr = _free(he->p.ptr);
694 
695 #ifdef NOTYET /* XXX can't erase pubkeys with "pubkey" arch. */
696  /* Add a "pubkey" arch/os to avoid missing value NULL ptrs. */
697  he->tag = RPMTAG_ARCH;
698  he->p.str = "pubkey";
699  xx = headerPut(h, he, 0);
700  he->tag = RPMTAG_OS;
701  he->p.str = "pubkey";
702  xx = headerPut(h, he, 0);
703 #endif
704 
705  he->tag = RPMTAG_LICENSE;
706  he->p.str = xstrdup(license);
707  xx = headerPut(h, he, 0);
708  he->p.ptr = _free(he->p.ptr);
709 
710  he->tag = RPMTAG_SIZE;
711  he->t = RPM_UINT32_TYPE;
712  he->p.ui32p = &zero;
713  he->c = 1;
714  xx = headerPut(h, he, 0);
715 
716  he->append = 1;
717 
718  /* Provides: gpg(IDENTITY) = PUBKEYVERSIONTYPE:PUBKEYID-CREATION */
719  he->tag = RPMTAG_PROVIDENAME;
720  he->t = RPM_STRING_ARRAY_TYPE;
721  he->p.argv = &u;
722  he->c = 1;
723  xx = headerPut(h, he, 0);
725  he->t = RPM_STRING_ARRAY_TYPE;
726  he->p.argv = &evr;
727  he->c = 1;
728  xx = headerPut(h, he, 0);
729  he->tag = RPMTAG_PROVIDEFLAGS;
730  he->t = RPM_UINT32_TYPE;
731  he->p.ui32p = &pflags;
732  he->c = 1;
733  xx = headerPut(h, he, 0);
734 
735  /* Provides: gpg(PUBKEYID) = PUBKEYVERSION:PUBKEYID-CREATION */
736  he->tag = RPMTAG_PROVIDENAME;
737  he->t = RPM_STRING_ARRAY_TYPE;
738  he->p.argv = &n;
739  he->c = 1;
740  xx = headerPut(h, he, 0);
742  he->t = RPM_STRING_ARRAY_TYPE;
743  he->p.argv = &evr;
744  he->c = 1;
745  xx = headerPut(h, he, 0);
746  he->tag = RPMTAG_PROVIDEFLAGS;
747  he->t = RPM_UINT32_TYPE;
748  he->p.ui32p = &pflags;
749  he->c = 1;
750  xx = headerPut(h, he, 0);
751 
752  he->append = 0;
753 
754  he->tag = RPMTAG_RPMVERSION;
755  he->t = RPM_STRING_TYPE;
756  he->p.str = xstrdup(RPMVERSION);
757  he->c = 1;
758  xx = headerPut(h, he, 0);
759  he->p.ptr = _free(he->p.ptr);
760 
761  /* XXX W2DO: tag value inherited from parent? */
762  he->tag = RPMTAG_BUILDHOST;
763  he->t = RPM_STRING_TYPE;
764  he->p.str = xstrdup(buildhost);
765  he->c = 1;
766  xx = headerPut(h, he, 0);
767  he->p.ptr = _free(he->p.ptr);
768 
769  { rpmuint32_t tid = rpmtsGetTid(ts);
770  he->tag = RPMTAG_INSTALLTIME;
771  he->t = RPM_UINT32_TYPE;
772  he->p.ui32p = &tid;
773  he->c = 1;
774  xx = headerPut(h, he, 0);
775  /* XXX W2DO: tag value inherited from parent? */
776  he->tag = RPMTAG_BUILDTIME;
777  he->t = RPM_UINT32_TYPE;
778  he->p.ui32p = &tid;
779  he->c = 1;
780  xx = headerPut(h, he, 0);
781  }
782 
783 #ifdef NOTYET
784  /* XXX W2DO: tag value inherited from parent? */
785  he->tag = RPMTAG_SOURCERPM;
786  he->t = RPM_STRING_TYPE;
787  he->p.str = fn;
788  he->c = 1;
789  xx = headerPut(h, he, 0);
790 #endif
791 
792  /* Reallocate the pubkey header into an immutable region. */
794  h = headerReload(h, he->tag);
795  { size_t length = 0;
796  he->t = RPM_BIN_TYPE;
797  he->p.ptr = headerUnload(h, &length);
798  he->c = length;
799  }
800 
801  /* Calculate the header-only SHA1 digest. */
803  unsigned char * hmagic = NULL;
804  size_t nmagic = 0;
805  const char * SHA1 = NULL;
806 
807  (void) headerGetMagic(NULL, &hmagic, &nmagic);
808  if (hmagic && nmagic > 0)
809  (void) rpmDigestUpdate(ctx, hmagic, nmagic);
810  (void) rpmDigestUpdate(ctx, he->p.ptr, he->c);
811  (void) rpmDigestFinal(ctx, &SHA1, NULL, 1);
812  he->p.ptr = _free(he->p.ptr);
813 
814  if (SHA1 == NULL)
815  goto exit;
816  he->tag = RPMTAG_SHA1HEADER;
817  he->t = RPM_STRING_TYPE;
818  he->p.str = SHA1;
819  he->c = 1;
820  xx = headerPut(h, he, 0);
821  SHA1 = _free(SHA1);
822  }
823 
824  he->tag = RPMTAG_PACKAGECOLOR;
825  he->t = RPM_UINT32_TYPE;
826  he->p.ui32p = &zero;
827  he->c = 1;
828  xx = headerPut(h, he, 0);
829 
830  /* Add header to database. */
831  xx = rpmtxnBegin(rpmtsGetRdb(ts), NULL, NULL);
832  xx = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), h, NULL);
833  if (xx != 0) {
834  xx = rpmtxnAbort(rpmtsGetRdb(ts)->db_txn);
835  rpmtsGetRdb(ts)->db_txn = NULL;
836  goto exit;
837  } else
838  xx = rpmtxnCommit(rpmtsGetRdb(ts)->db_txn);
839  rpmtsGetRdb(ts)->db_txn = NULL;
840  xx = rpmtxnCheckpoint(rpmtsGetRdb(ts));
841  rc = RPMRC_OK;
842 
843 exit:
844  /* Clean up. */
845 hkp->pkt = NULL;
846 hkp->pktlen = 0;
847 hkp->pkts = _free(hkp->pkts);
848 hkp->npkts = 0;
849  (void) rpmhkpFree(hkp);
850  hkp = NULL;
851  (void)headerFree(h);
852  h = NULL;
853  dig = pgpDigFree(dig);
854  n = _free(n);
855  u = _free(u);
856  v = _free(v);
857  r = _free(r);
858  evr = _free(evr);
859  enc = _free(enc);
860  d = _free(d);
861 
862  return rc;
863 }
864 
873 static int rpmcliImportPubkeys(const rpmts ts,
874  /*@unused@*/ QVA_t qva,
875  /*@null@*/ const char ** argv)
876  /*@globals rpmGlobalMacroContext, h_errno,
877  fileSystem, internalState @*/
878  /*@modifies ts, rpmGlobalMacroContext,
879  fileSystem, internalState @*/
880 {
881  const char * fn;
882  rpmuint8_t * pkt = NULL;
883  size_t pktlen = 0;
884  char * t = NULL;
885  int res = 0;
886  rpmRC rpmrc;
887  int rc;
888 
889  if (argv == NULL) return res;
890 
891  while ((fn = *argv++) != NULL) {
892 
893  rpmtsClean(ts);
894  pkt = _free(pkt);
895  t = _free(t);
896 
897  /* If arg looks like a keyid, then attempt keyserver retrieve. */
898  if (fn[0] == '0' && fn[1] == 'x') {
899  const char * s;
900  int i;
901  for (i = 0, s = fn+2; *s && isxdigit(*s); s++, i++)
902  {};
903  if (i == 8 || i == 16) {
904  t = rpmExpand("%{_hkp_keyserver_query}", fn, NULL);
905  if (t && *t != '%')
906  fn = t;
907  }
908  }
909 
910  /* Read pgp packet. */
911  if ((rc = pgpReadPkts(fn, &pkt, &pktlen)) <= 0) {
912  rpmlog(RPMLOG_ERR, _("%s: import read failed(%d).\n"), fn, rc);
913  res++;
914  continue;
915  }
916  if (rc != PGPARMOR_PUBKEY) {
917  rpmlog(RPMLOG_ERR, _("%s: not an armored public key.\n"), fn);
918  res++;
919  continue;
920  }
921 
922  /* Import pubkey packet(s). */
923  if ((rpmrc = rpmcliImportPubkey(ts, pkt, pktlen)) != RPMRC_OK) {
924  rpmlog(RPMLOG_ERR, _("%s: import failed.\n"), fn);
925  res++;
926  continue;
927  }
928 
929  }
930 
931 rpmtsClean(ts);
932  pkt = _free(pkt);
933  t = _free(t);
934  return res;
935 }
936 
940 static rpmRC readFile(FD_t fd, const char * fn)
941  /*@globals fileSystem, internalState @*/
942  /*@modifies fd, fileSystem, internalState @*/
943 {
944 rpmxar xar = fdGetXAR(fd);
945 pgpDig dig = fdGetDig(fd);
946  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
947  unsigned char buf[4*BUFSIZ];
948  ssize_t count;
949  unsigned ix;
950  rpmRC rc;
951  int xx;
952 
953  dig->nbytes = 0;
954 
955  /* Read the header from the package. */
956  { Header h = NULL;
957  const char item[] = "Header";
958  const char * msg = NULL;
959  rc = rpmpkgRead(item, fd, &h, &msg);
960  if (rc != RPMRC_OK) {
961  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
962  msg = _free(msg);
963  goto exit;
964  }
965  msg = _free(msg);
966 
967  dig->nbytes += headerSizeof(h);
968 
969  /* Fish out the autosign pubkey (if present). */
970  he->tag = RPMTAG_PUBKEYS;
971  xx = headerGet(h, he, 0);
972  if (xx && he->p.argv != NULL && he->c > 0)
973  switch (he->t) {
974  default:
975  break;
977  ix = he->c - 1; /* XXX FIXME: assumes last pubkey */
978  dig->pub = _free(dig->pub);
979  dig->publen = 0;
980  { rpmiob iob = rpmiobNew(0);
981  iob = rpmiobAppend(iob, he->p.argv[ix], 0);
982  xx = pgpArmorUnwrap(iob, (rpmuint8_t **)&dig->pub, &dig->publen);
983  iob = rpmiobFree(iob);
984  }
985  if (xx != PGPARMOR_PUBKEY) {
986  dig->pub = _free(dig->pub);
987  dig->publen = 0;
988  }
989  break;
990  }
991  he->p.ptr = _free(he->p.ptr);
992 
994  unsigned char * hmagic = NULL;
995  size_t nmagic = 0;
996 
998  xx = headerGet(h, he, 0);
999  if (!xx || he->p.ptr == NULL) {
1000  (void)headerFree(h);
1001  h = NULL;
1002  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, _("headerGet failed"),
1003  _("failed to retrieve original header\n"));
1004  rc = RPMRC_FAIL;
1005  goto exit;
1006  }
1007  (void) headerGetMagic(NULL, &hmagic, &nmagic);
1008  /* XXX dig->hsha? */
1010  if (hmagic && nmagic > 0)
1011  (void) rpmDigestUpdate(dig->hdsa, hmagic, nmagic);
1012  (void) rpmDigestUpdate(dig->hdsa, he->p.ptr, he->c);
1013  dig->hrsa = rpmDigestInit((pgpHashAlgo)dig->signature.hash_algo, RPMDIGEST_NONE);
1014  if (hmagic && nmagic > 0)
1015  (void) rpmDigestUpdate(dig->hrsa, hmagic, nmagic);
1016  (void) rpmDigestUpdate(dig->hrsa, he->p.ptr, he->c);
1017  he->p.ptr = _free(he->p.ptr);
1018  }
1019  (void)headerFree(h);
1020  h = NULL;
1021  }
1022 
1023  if (xar != NULL) {
1024  const char item[] = "Payload";
1025  if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) {
1026  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item,
1027  _("XAR file not found (or no XAR support)"));
1028  rc = RPMRC_NOTFOUND;
1029  goto exit;
1030  }
1031  }
1032 
1033  /* Read the payload from the package. */
1034  while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
1035  dig->nbytes += count;
1036  if (count < 0 || Ferror(fd)) {
1037  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, _("Fread failed"), Fstrerror(fd));
1038  rc = RPMRC_FAIL;
1039  goto exit;
1040  }
1041 
1042  /* XXX Steal the digest-in-progress from the file handle. */
1043  fdStealDigest(fd, dig);
1044 
1045  rc = RPMRC_OK; /* XXX unnecessary */
1046 
1047 exit:
1048  return rc;
1049 }
1050 
1051 int rpmVerifySignatures(QVA_t qva, rpmts ts, void * _fd, const char * fn)
1052 {
1053  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1054  HE_t she = (HE_t) memset(alloca(sizeof(*she)), 0, sizeof(*she));
1055 /*@-castexpose@*/
1056  FD_t fd = (FD_t)_fd;
1057 /*@=castexpose@*/
1058  char result[1024];
1059  char buf[8192], * b;
1060  char missingKeys[7164], * m;
1061  char untrustedKeys[7164], * u;
1062  pgpDig dig;
1063  pgpDigParams sigp;
1064  Header sigh = NULL;
1065  HeaderIterator hi = NULL;
1066  int res = 0;
1067  int xx;
1068  rpmRC sigres;
1069  int failed;
1070  int nodigests = !(qva->qva_flags & VERIFY_DIGEST);
1071  int nosignatures = !(qva->qva_flags & VERIFY_SIGNATURE);
1072 pgpPkt pp = (pgpPkt) alloca(sizeof(*pp));
1073 
1074  {
1075  { const char item[] = "Lead";
1076  const char * msg = NULL;
1077  rpmRC rc = rpmpkgRead(item, fd, NULL, &msg);
1078  switch (rc) {
1079  default:
1080  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
1081  msg = _free(msg);
1082  res++;
1083  goto exit;
1084  /*@notreachea@*/ break;
1085  case RPMRC_OK:
1086  break;
1087  }
1088  msg = _free(msg);
1089  }
1090 
1091  { const char item[] = "Signature";
1092  const char * msg = NULL;
1093  rpmRC rc = rpmpkgRead(item, fd, &sigh, &msg);
1094  switch (rc) {
1095  default:
1096  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item,
1097  (msg && *msg ? msg : ""));
1098  msg = _free(msg);
1099  res++;
1100  goto exit;
1101  /*@notreached@*/ /*@switchbreak@*/ break;
1102  case RPMRC_OK:
1103  if (sigh == NULL) {
1104  rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
1105  res++;
1106  goto exit;
1107  }
1108  /*@switchbreak@*/ break;
1109  }
1110  msg = _free(msg);
1111  }
1112 
1113  /* Grab a hint of what needs doing to avoid duplication. */
1114  she->tag = (rpmTag)0;
1115  if (she->tag == 0 && !nosignatures) {
1116  if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_DSA))
1117  she->tag = (rpmTag) RPMSIGTAG_DSA;
1118  else if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_RSA))
1119  she->tag = (rpmTag) RPMSIGTAG_RSA;
1120  else if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_ECDSA))
1121  she->tag = (rpmTag) RPMSIGTAG_ECDSA;
1122  }
1123  if (she->tag == 0 && !nodigests) {
1124  if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_MD5))
1125  she->tag = (rpmTag) RPMSIGTAG_MD5;
1126  else if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_SHA1))
1127  she->tag = (rpmTag) RPMSIGTAG_SHA1; /* XXX never happens */
1128  }
1129 
1130  dig = rpmtsDig(ts);
1131 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */
1132  (void) fdSetDig(fd, dig);
1133 /*@=mods@*/
1134  sigp = pgpGetSignature(dig);
1135 
1136  /* XXX RSA needs the hash_algo, so decode early. */
1137  if ((rpmSigTag) she->tag == RPMSIGTAG_RSA) {
1138  he->tag = she->tag;
1139  xx = headerGet(sigh, he, 0);
1140  xx = pgpPktLen(he->p.ui8p, he->c, pp);
1141  xx = rpmhkpLoadSignature(NULL, dig, pp);
1142  he->p.ptr = _free(he->p.ptr);
1143  }
1144 
1145 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */
1146  if (headerIsEntry(sigh, (rpmTag)RPMSIGTAG_MD5))
1147  fdInitDigest(fd, PGPHASHALGO_MD5, 0);
1148 /*@=mods@*/
1149 
1150  /* Read the file, generating digest(s) on the fly. */
1151 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */
1152  if (dig == NULL || sigp == NULL
1153  || readFile(fd, fn) != RPMRC_OK)
1154  {
1155  res++;
1156  goto exit;
1157  }
1158 /*@=mods@*/
1159 
1160  failed = 0;
1161  b = buf; *b = '\0';
1162  m = missingKeys; *m = '\0';
1163  u = untrustedKeys; *u = '\0';
1164  sprintf(b, "%s:%c", fn, (rpmIsVerbose() ? '\n' : ' ') );
1165  b += strlen(b);
1166 
1167  if (sigh != NULL)
1168  for (hi = headerInit(sigh);
1169  headerNext(hi, she, 0) != 0;
1170  she->p.ptr = _free(she->p.ptr))
1171  {
1172 
1173 assert(she->p.ptr != NULL);
1174 
1175  /* Clean up parameters from previous she->tag. */
1176  pgpDigClean(dig);
1177 
1178 /*@-ownedtrans -noeffect@*/
1179  xx = pgpSetSig(dig, she->tag, she->t, she->p.ptr, she->c);
1180 /*@=ownedtrans =noeffect@*/
1181 
1182  switch ((rpmSigTag)she->tag) {
1183  case RPMSIGTAG_RSA:
1184  case RPMSIGTAG_DSA:
1185  case RPMSIGTAG_ECDSA:
1186  if (nosignatures)
1187  continue;
1188 
1189  xx = pgpPktLen(she->p.ui8p, she->c, pp);
1190  xx = rpmhkpLoadSignature(NULL, dig, pp);
1191  if (sigp->version != 3 && sigp->version != 4) {
1193  _("skipping package %s with unverifiable V%u signature\n"),
1194  fn, sigp->version);
1195  res++;
1196  goto exit;
1197  }
1198  /*@switchbreak@*/ break;
1199  case RPMSIGTAG_SHA1:
1200  if (nodigests)
1201  continue;
1202  /* XXX Don't bother with header sha1 if header dsa. */
1203  if (!nosignatures && (rpmSigTag)she->tag == RPMSIGTAG_DSA)
1204  continue;
1205  /*@switchbreak@*/ break;
1206  case RPMSIGTAG_MD5:
1207  if (nodigests)
1208  continue;
1209  /*@switchbreak@*/ break;
1210  default:
1211  continue;
1212  /*@notreached@*/ /*@switchbreak@*/ break;
1213  }
1214 
1215  sigres = rpmVerifySignature(dig, result);
1216 
1217  if (sigres) {
1218  failed = 1;
1219  if (rpmIsVerbose())
1220  b = stpcpy( stpcpy( stpcpy(b, " "), result), "\n");
1221  else
1222  switch ((rpmSigTag)she->tag) {
1223  case RPMSIGTAG_SIZE:
1224  b = stpcpy(b, "SIZE ");
1225  /*@switchbreak@*/ break;
1226  case RPMSIGTAG_SHA1:
1227  b = stpcpy(b, "SHA1 ");
1228  /*@switchbreak@*/ break;
1229  case RPMSIGTAG_MD5:
1230  b = stpcpy(b, "MD5 ");
1231  /*@switchbreak@*/ break;
1232  case RPMSIGTAG_RSA:
1233  b = stpcpy(b, "RSA ");
1234  /*@switchbreak@*/ break;
1235  case RPMSIGTAG_DSA:
1236  b = stpcpy(b, "(SHA1) DSA ");
1237  /*@switchbreak@*/ break;
1238  case RPMSIGTAG_ECDSA:
1239  b = stpcpy(b, "ECDSA ");
1240  /*@switchbreak@*/ break; /* coverity #1214084 */
1241  default:
1242  b = stpcpy(b, "?UnknownSignatureType? ");
1243  /*@switchbreak@*/ break;
1244  }
1245  } else {
1246  if (rpmIsVerbose())
1247  b = stpcpy( stpcpy( stpcpy(b, " "), result), "\n");
1248  else
1249  switch ((rpmSigTag)she->tag) {
1250  case RPMSIGTAG_SIZE:
1251  b = stpcpy(b, "size ");
1252  /*@switchbreak@*/ break;
1253  case RPMSIGTAG_SHA1:
1254  b = stpcpy(b, "sha1 ");
1255  /*@switchbreak@*/ break;
1256  case RPMSIGTAG_MD5:
1257  b = stpcpy(b, "md5 ");
1258  /*@switchbreak@*/ break;
1259  case RPMSIGTAG_RSA:
1260  b = stpcpy(b, "rsa ");
1261  /*@switchbreak@*/ break;
1262  case RPMSIGTAG_DSA:
1263  b = stpcpy(b, "(sha1) dsa ");
1264  /*@switchbreak@*/ break;
1265  case RPMSIGTAG_ECDSA:
1266  b = stpcpy(b, "ecdsa ");
1267  /*@switchbreak@*/ break;
1268  default:
1269  b = stpcpy(b, "??? ");
1270  /*@switchbreak@*/ break;
1271  }
1272  }
1273  }
1274  hi = headerFini(hi);
1275  /* XXX clear the already free'd signature data. */
1276 /*@-noeffect@*/
1277  xx = pgpSetSig(dig, 0, 0, NULL, 0);
1278 /*@=noeffect@*/
1279 
1280  res += failed;
1281 
1282  if (failed) {
1283  if (rpmIsVerbose()) {
1284  rpmlog(RPMLOG_NOTICE, "%s", buf);
1285  } else {
1286  rpmlog(RPMLOG_NOTICE, "%s%s%s%s%s%s%s%s\n", buf,
1287  _("NOT_OK"),
1288  (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
1289  missingKeys,
1290  (missingKeys[0] != '\0') ? _(") ") : "",
1291  (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
1292  untrustedKeys,
1293  (untrustedKeys[0] != '\0') ? _(")") : "");
1294 
1295  }
1296  } else {
1297  if (rpmIsVerbose()) {
1298  rpmlog(RPMLOG_NOTICE, "%s", buf);
1299  } else {
1300  rpmlog(RPMLOG_NOTICE, "%s%s%s%s%s%s%s%s\n", buf,
1301  _("OK"),
1302  (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
1303  missingKeys,
1304  (missingKeys[0] != '\0') ? _(") ") : "",
1305  (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
1306  untrustedKeys,
1307  (untrustedKeys[0] != '\0') ? _(")") : "");
1308  }
1309  }
1310 
1311  }
1312 
1313 exit:
1314  rpmtsCleanDig(ts);
1315  (void)headerFree(sigh);
1316  sigh = NULL;
1317  return res;
1318 }
1319 
1320 int rpmcliSign(rpmts ts, QVA_t qva, const char ** argv)
1321  /*@globals rpmioFtsOpts @*/
1322  /*@modifies rpmioFtsOpts @*/
1323 {
1324  rpmRC rpmrc;
1325  int res = 0;
1326 
1327  if (argv == NULL) return res;
1328 
1329  switch (qva->qva_mode) {
1330  case RPMSIGN_CHK_SIGNATURE:
1331  break;
1332  case RPMSIGN_IMPORT_PUBKEY:
1333  return rpmcliImportPubkeys(ts, qva, argv);
1334  /*@notreached@*/ break;
1335  case RPMSIGN_NEW_SIGNATURE:
1336  case RPMSIGN_ADD_SIGNATURE:
1337  case RPMSIGN_DEL_SIGNATURE:
1338  return rpmReSign(ts, qva, argv);
1339  /*@notreached@*/ break;
1340  case RPMSIGN_NONE:
1341  default:
1342  return -1;
1343  /*@notreached@*/ break;
1344  }
1345 
1346 { /* start-of-arg-iteration */
1347 
1348  int tag = (qva->qva_source == RPMQV_FTSWALK)
1350  rpmgi gi = rpmgiNew(ts, tag, NULL, 0);
1351  rpmgiFlags _giFlags = RPMGI_NONE;
1352  rpmRC rc;
1353 
1354  if (rpmioFtsOpts == 0)
1356  rc = (rpmRC)
1357  rpmgiSetArgs(gi, argv, rpmioFtsOpts,
1358  (rpmgiFlags)(_giFlags|RPMGI_NOHEADER));
1359  while ((rpmrc = rpmgiNext(gi)) == RPMRC_OK) {
1360  const char * fn = rpmgiHdrPath(gi);
1361  FD_t fd;
1362  int xx;
1363 
1364  fd = Fopen(fn, "r.fdio");
1365  if (fd == NULL || Ferror(fd)) {
1366  rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"),
1367  fn, Fstrerror(fd));
1368  res++;
1369  } else if (rpmVerifySignatures(qva, ts, fd, fn)) {
1370  res++;
1371  }
1372 
1373  if (fd != NULL) {
1374  xx = Fclose(fd);
1375  }
1376  }
1377 
1378  /* XXX disambiguate end-of-iteration from item failures. */
1379  if (res == 0 && rpmrc == RPMRC_NOTFOUND) {
1380  rpmrc = (rpmRC) rpmgiRc(gi);
1381  if (rpmrc != RPMRC_OK)
1382  res++;
1383  }
1384 
1385  gi = rpmgiFree(gi);
1386 
1387 } /* end-of-arg-iteration */
1388 
1389  return res;
1390 }
Structure(s)and methods for a XAR archive wrapper format.
const bson * b
Definition: bson.h:280
rpmTagType t
Definition: rpmtag.h:504
const char const double d
Definition: bson.h:800
void _rpmhkpDumpDig(const char *msg, pgpDig dig, FILE *fp)
Definition: rpmhkp.c:1164
pgpDigParams pgpGetPubkey(pgpDig dig)
Return OpenPGP pubkey parameters.
Definition: rpmpgp.c:1397
const char * str
Definition: rpmtag.h:73
rpmTag tag
Definition: rpmtag.h:503
int rpmgiRc(rpmgi gi)
Return current iteration item(s) exit code.
Definition: rpmgi.c:861
const char ** argv
Definition: rpmtag.h:75
struct rpmxar_s * rpmxar
Definition: rpmxar.h:14
int rpmtxnBegin(rpmdb rpmdb, rpmtxn parent, rpmtxn *txnp)
Definition: rpmtxn.c:56
int rpmAddSignature(Header sigh, const char *file, rpmSigTag sigTag, const char *passPhrase)
Generate signature(s) from a header+payload file, save in signature header.
Definition: signature.c:477
rpmRC rpmhkpValidate(rpmhkp hkp, const char *keyname)
Retrieve/Validate binding and certification signatures on a pubkey.
Definition: rpmhkp.c:901
int rpmtxnCheckpoint(rpmdb rpmdb)
Definition: rpmtxn.c:85
int headerIsEntry(Header h, rpmTag tag)
Check if tag is in header.
Definition: header.c:1439
pgpDig pgpDigFree(pgpDig dig)
Destroy a container for parsed OpenPGP packates.
const char bson_timestamp_t * ts
Definition: bson.h:1004
rpmRC rpmcliImportPubkey(const rpmts ts, const unsigned char *pkt, ssize_t pktlen)
Import public key packet(s).
Definition: rpmchecksig.c:515
int pgpPktLen(const rpmuint8_t *pkt, size_t pleft, pgpPkt pp)
Definition: rpmpgp.c:999
static const int zero
Definition: bson.c:111
const char * RPMVERSION
Definition: misc.c:17
rpmRC rpmpkgWrite(const char *fn, FD_t fd, void *ptr, const char **msg)
Write item onto file descriptor.
Definition: pkgio.c:1692
int rpmtxnCommit(rpmtxn txn)
Definition: rpmtxn.c:75
enum rpmSigTag_e rpmSigTag
Definition: rpmtag.h:474
size_t Fwrite(const void *buf, size_t size, size_t nmemb, FD_t fd)
fwrite(3) clone.
Definition: rpmio.c:2434
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
rpmuint32_t * ui32p
Definition: rpmtag.h:70
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2840
rpmgi rpmgiFree(rpmgi gi)
Destroy a generalized iterator.
struct pgpDigParams_s * pgpDigParams
Definition: rpmiotypes.h:101
DIGEST_CTX rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
Initialize digest context.
Definition: digest.c:247
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2231
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2294
enum pgpHashAlgo_e pgpHashAlgo
9.4.
rpmhkp rpmhkpNew(const rpmuint8_t *keyid, uint32_t flags)
Create a new hkp handle.
Definition: rpmhkp.c:112
The Header data structure.
HeaderIterator headerFini(HeaderIterator hi)
Destroy header tag container iterator.
Definition: header.c:2134
static pgpDig fdGetDig(FD_t fd)
int rpmxarNext(rpmxar xar)
Iterate a xar archive instance.
Definition: rpmxar.c:128
rpmQueryFlags qva_flags
Definition: rpmcli.h:633
headerSprintfExtension rpmHeaderFormats
Table of query format extensions.
Definition: formats.c:305
HeaderIterator headerInit(Header h)
Create header tag iterator.
Definition: header.c:2144
FD_t fdLink(void *cookie, const char *msg)
static rpmRC readFile(FD_t fd, const char *fn)
Definition: rpmchecksig.c:940
int Fflush(FD_t fd)
fflush(3) clone.
Definition: rpmio.c:2923
int headerDel(Header h, HE_t he, unsigned int flags)
Remove tag container from header.
Definition: header.c:2313
int pgpSetSig(pgpDig dig, rpmuint32_t sigtag, rpmuint32_t sigtype, const void *sig, rpmuint32_t siglen)
Set signature tag info, i.e.
Definition: rpmpgp.c:1422
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
Header headerCopyLoad(const void *uh)
Make a copy and convert header to in-memory representation.
Definition: header.c:1433
Header tag iterator data structure.
Definition: header.c:2129
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
rpmiob rpmiobAppend(rpmiob iob, const char *s, size_t nl)
Append string to I/O buffer.
Definition: rpmiob.c:77
rpmhkp rpmhkpFree(rpmhkp hkp)
Destroy a hkp handle.
int headerNext(HeaderIterator hi, HE_t he, unsigned int flags)
Return next tag from header.
Definition: header.c:2158
static void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int _flags)
Attach digest to fd.
static int copyFile(FD_t *sfdp, const char **sfnp, FD_t *tfdp, const char **tfnp)
Copy header+payload, calculating digest(s) on the fly.
Definition: rpmchecksig.c:110
pgpArmor pgpArmorUnwrap(rpmiob iob, rpmuint8_t **pkt, size_t *pktlen)
Parse armored OpenPGP packets from an iob.
Definition: rpmpgp.c:1564
Command line option information.
Definition: rpmcli.h:630
char * headerSprintf(Header h, const char *fmt, headerTagTableEntry tags, headerSprintfExtension exts, errmsg_t *errmsg)
Return formatted output string from header tags.
Definition: hdrfmt.c:6730
#define _fd(_a)
Definition: psm.h:32
void * headerUnload(Header h, size_t *lenp)
headerUnload.
Definition: header.c:648
char * alloca()
static int getSignid(Header sigh, rpmSigTag sigtag, unsigned char *signid)
Retrieve signer fingerprint from an OpenPGP signature tag.
Definition: rpmchecksig.c:159
pgpArmor pgpReadPkts(const char *fn, rpmuint8_t **pkt, size_t *pktlen)
Parse armored OpenPGP packets from a file.
Definition: rpmpgp.c:1739
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
struct _HE_s * HE_t
Definition: rpmtag.h:59
void rpmtsCleanDig(rpmts ts)
Free signature verification data.
Definition: pkgio.c:456
const char * Fstrerror(FD_t fd)
strerror(3) clone.
Definition: rpmio.c:2401
void * ptr
Definition: rpmtag.h:67
const char const bson_bool_t v
Definition: bson.h:919
int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len)
Update context with next plain text buffer.
Definition: digest.c:986
rpmgi rpmgiNew(rpmts ts, int tag, const void *keyp, size_t keylen)
Return a generalized iterator.
Definition: rpmgi.c:543
struct _FD_s * FD_t
Definition: rpmio.h:43
static void fdSetDig(FD_t fd, pgpDig dig)
int rpmxarPull(rpmxar xar, const char *fn)
Definition: rpmxar.c:168
const char * mode
Definition: mongo.h:440
FD_t fdFree(FD_t fd, const char *msg)
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:26
int Rename(const char *oldpath, const char *newpath)
rename(2) clone.
Definition: rpmrpc.c:286
enum rpmgiFlags_e rpmgiFlags
The lead data structure.
Definition: pkgio.c:479
int rpmTempFile(const char *prefix, const char **fnptr, void *fdptr)
Return file handle for a temporaray file.
Definition: signature.c:30
#define FTS_COMFOLLOW
Definition: fts.h:87
rpmTagData p
Definition: rpmtag.h:506
struct pgpPkt_s * pgpPkt
Definition: rpmiotypes.h:93
pgpDigParams pgpGetSignature(pgpDig dig)
Return OpenPGP signature parameters.
Definition: rpmpgp.c:1392
#define RPMDBI_FTSWALK
Definition: rpmtag.h:487
Digest private data.
Definition: digest.c:130
rpmRC rpmgiSetArgs(rpmgi gi, ARGV_t argv, int ftsOpts, rpmgiFlags flags)
Load iterator args.
Definition: rpmgi.c:866
rpmQVSources qva_source
Definition: rpmcli.h:631
The FD_t File Handle data structure.
struct pgpDig_s * pgpDig
Definition: rpmiotypes.h:97
rpmTagCount c
Definition: rpmtag.h:507
Generate and verify rpm package signatures.
Header headerFree(Header h)
Dereference a header instance.
int rpmioFtsOpts
Definition: poptIO.c:539
int headerGetMagic(Header h, unsigned char **magicp, size_t *nmagicp)
Return header magic.
Definition: header.c:1162
rpmRC rpmVerifySignature(void *_dig, char *result)
Verify a signature from a package.
Definition: signature.c:1094
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
Definition: macro.c:3250
void pgpDigClean(pgpDig dig)
Release (malloc'd) data from container.
Definition: rpmpgp.c:1155
size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
fread(3) clone.
Definition: rpmio.c:2412
rpmuint8_t * ui8p
Definition: rpmtag.h:68
const char * passPhrase
Definition: rpmcli.h:655
int Fclose(FD_t fd)
fclose(3) clone.
Definition: rpmio.c:2534
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
Definition: rpmiob.c:44
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
Header headerLink(Header h)
Reference a header instance.
int pgpGrabPkts(const rpmuint8_t *pkts, size_t pktlen, rpmuint8_t ***pppkts, int *pnpkts)
Return array of packet pointers.
Definition: rpmpgp.c:1472
rpmdb rpmtsGetRdb(rpmts ts)
Get transaction set database handle.
Definition: pkgio.c:151
struct rpmgi_s * rpmgi
Generalized iterator.
Definition: rpmtypes.h:53
enum rpmRC_e rpmRC
RPM return codes.
pgpDig pgpDigNew(pgpVSFlags vsflags, pgpPubkeyAlgo pubkey_algo)
Create a container for parsed OpenPGP packates.
Definition: rpmpgp.c:1314
#define RPMDBI_ARGLIST
Definition: rpmtag.h:486
size_t headerSizeof(Header h)
Return size of on-disk header representation in bytes.
Definition: header.c:266
rpmhkp rpmhkpLink(rpmhkp hkp)
Reference a hkp handle instance.
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2951
Definition: rpmtag.h:502
const char const int i
Definition: bson.h:778
int _print_pkts
Definition: rpmchecksig.c:47
Methods to handle package elements.
int pgpPubkeyFingerprint(const rpmuint8_t *pkt, size_t pktlen, rpmuint8_t *keyid)
Print/parse an OpenPGP subtype packet.
Definition: rpmpgp.c:1029
char * stpcpy(char *dest, const char *src)
struct rpmts_s * rpmts
The RPM Transaction Set.
Definition: rpmtypes.h:14
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
struct rpmiob_s * rpmiob
Definition: rpmiotypes.h:60
Header headerReload(Header h, rpmTag tag)
Convert header to on-disk representation, and then reload.
Definition: header.c:1314
Structures and prototypes used for an "rpmts" transaction set.
static rpmxar fdGetXAR(FD_t fd)
Structure(s) and routine(s) used for EVR parsing and comparison.
int rpmcliSign(rpmts ts, QVA_t qva, const char **argv)
Create/Modify/Check elements from signature header.
Definition: rpmchecksig.c:1320
#define FTS_LOGICAL
Definition: fts.h:88
#define rpmIsVerbose()
Definition: rpmcb.h:21
int rpmtsOpenDB(rpmts ts, int dbmode)
Open the database used by the transaction.
Definition: rpmts.c:115
int rpmhkpLoadKey(rpmhkp hkp, pgpDig dig, int keyx, rpmuint8_t pubkey_algo)
Definition: rpmhkp.c:363
rpmRC rpmgiNext(rpmgi gi)
Perform next iteration step.
Definition: rpmgi.c:584
int rpmDigestFinal(DIGEST_CTX ctx, void *datap, size_t *lenp, int asAscii)
Return digest and destroy context.
Definition: digest.c:1000
#define _(Text)
Definition: system.h:29
int rpmdbAdd(rpmdb db, int iid, Header h, rpmts ts)
Add package header to rpm database and indices.
Definition: rpmdb.c:2887
const char * rpmgiHdrPath(rpmgi gi)
Return current header path.
Definition: rpmgi.c:842
#define xmalloc
Definition: system.h:32
static int rpmReSign(rpmts ts, QVA_t qva, const char **argv)
Create/modify elements in signature header.
Definition: rpmchecksig.c:193
struct rpmhkp_s * rpmhkp
Definition: rpmhkp.h:11
rpmRC rpmpkgRead(const char *fn, FD_t fd, void *ptr, const char **msg)
Read item from file descriptor.
Definition: pkgio.c:1674
Database transaction wrappers.
rpmuint32_t rpmtsGetTid(rpmts ts)
Get transaction id, i.e.
Definition: rpmts.c:1024
Access RPM indices using Berkeley DB interface(s).
enum rpmTag_e rpmTag
Definition: rpmtag.h:470
static void fdStealDigest(FD_t fd, pgpDig dig)
static int rpmcliImportPubkeys(const rpmts ts, QVA_t qva, const char **argv)
Import public key(s).
Definition: rpmchecksig.c:873
static int manageFile(FD_t *fdp, const char **fnp, int flags, int rc)
Definition: rpmchecksig.c:51
static char * pgpHexStr(const rpmuint8_t *p, size_t plen)
Return hex formatted representation of bytes.
Definition: rpmpgp.h:1124
pgpDig rpmtsDig(rpmts ts)
Get OpenPGP packet parameters, i.e.
Definition: pkgio.c:441
Header headerNew(void)
Create new (empty) header instance.
Definition: header.c:180
int rpmtxnAbort(rpmtxn txn)
Definition: rpmtxn.c:47
#define FTS_NOSTAT
Definition: fts.h:90
int rpmhkpLoadSignature(rpmhkp hkp, pgpDig dig, pgpPkt pp)
Definition: rpmhkp.c:461
int rpmVerifySignatures(QVA_t qva, rpmts ts, void *_fd, const char *fn)
Check package and header signatures.
Definition: rpmchecksig.c:1051
void rpmtsClean(rpmts ts)
Free memory needed only for dependency checks and ordering.
Definition: rpmts.c:598
unsigned int append
Definition: rpmtag.h:511
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397