rpm  5.4.10
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_DSA:
367  he->tag = (rpmTag)RPMSIGTAG_GPG;
368  xx = headerDel(sigh, he, 0);
369  /*@switchbreak@*/ break;
370  case RPMSIGTAG_RSA:
371  he->tag = (rpmTag)RPMSIGTAG_PGP;
372  xx = headerDel(sigh, he, 0);
373  /*@switchbreak@*/ break;
374  case RPMSIGTAG_GPG:
375  he->tag = (rpmTag)RPMSIGTAG_PGP;
376  xx = headerDel(sigh, he, 0);
377  he->tag = (rpmTag)RPMSIGTAG_DSA;
378  xx = headerDel(sigh, he, 0);
379  /*@fallthrough@*/
380  case RPMSIGTAG_PGP5:
381  case RPMSIGTAG_PGP:
382  he->tag = (rpmTag)RPMSIGTAG_RSA;
383  xx = headerDel(sigh, he, 0);
384  /*@switchbreak@*/ break;
385  }
386 
387  he->tag = (rpmTag)sigtag;
388  xx = headerDel(sigh, he, 0);
389  xx = rpmAddSignature(sigh, sigtarget, sigtag, qva->passPhrase);
390  if (xx)
391  goto exit;
392 
393  /* If package was previously signed, check for same signer. */
394  memset(newsignid, 0, sizeof(newsignid));
395  if (memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
396 
397  /* Grab the new signature fingerprint */
398  xx = getSignid(sigh, sigtag, newsignid);
399 
400  /* If same signer, skip resigning the package. */
401  if (!memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
402 
404  _("%s: was already signed by key ID %s, skipping\n"),
405  fn, pgpHexStr(newsignid+4, sizeof(newsignid)-4));
406 
407  /* Clean up intermediate target */
408  xx = Unlink(sigtarget);
409  sigtarget = _free(sigtarget);
410  continue;
411  }
412  }
413  }
414  }
415 
416  /* Reallocate the signature into one contiguous region. */
418  if (sigh == NULL) /* XXX can't happen */
419  goto exit;
420 }
421 
422  /* Write the lead/signature of the output rpm */
423  (void) stpcpy( stpcpy(tmprpm, fn), ".XXXXXX");
424 
425 #if defined(HAVE_MKSTEMP)
426  mode = umask(0077);
427  (void) close(mkstemp(tmprpm));
428  (void) umask(mode);
429 #else
430  (void) mktemp(tmprpm);
431 #endif
432  tfn = tmprpm;
433 
434  if (manageFile(&ofd, &tfn, O_WRONLY|O_CREAT|O_TRUNC, 0))
435  goto exit;
436 
437  { const char item[] = "Lead";
438  const char * msg = NULL;
439  rpmRC rc = rpmpkgWrite(item, ofd, lead, &msg);
440  if (rc != RPMRC_OK) {
441  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", tfn, item, Fstrerror(ofd));
442  msg = _free(msg);
443  goto exit;
444  }
445  msg = _free(msg);
446  }
447 
448  { const char item[] = "Signature";
449  const char * msg = NULL;
450  rpmRC rc = rpmpkgWrite(item, ofd, sigh, &msg);
451  if (rc != RPMRC_OK) {
452  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", tfn, item, Fstrerror(ofd));
453  msg = _free(msg);
454  goto exit;
455  }
456  msg = _free(msg);
457  }
458  (void)headerFree(sigh);
459  sigh = NULL;
460 
461  /* Append the header and archive from the temp file */
462  /* ASSERT: fd == NULL && ofd != NULL */
463  if (copyFile(&fd, &sigtarget, &ofd, &tfn))
464  goto exit;
465  /* Both fd and ofd are now closed. */
466  /* ASSERT: fd == NULL && ofd == NULL */
467 
468  /* Move final target into place. */
469  xx = Unlink(fn);
470  xx = Rename(tfn, fn);
471  tmprpm[0] = '\0';
472 
473  /* Clean up intermediate target */
474  xx = Unlink(sigtarget);
475  sigtarget = _free(sigtarget);
476  }
477 
478  /* XXX disambiguate end-of-iteration from item failures. */
479  if (rpmrc == RPMRC_NOTFOUND)
480  rpmrc = (rpmRC) rpmgiRc(gi);
481 
482  gi = rpmgiFree(gi);
483 
484  } /* end-of-arg-iteration */
485 
486  if (rpmrc == RPMRC_OK)
487  res = 0;
488 
489 exit:
490  if (fd) (void) manageFile(&fd, NULL, 0, res);
491  if (ofd) (void) manageFile(&ofd, NULL, 0, res);
492 
493  lead = _free(lead);
494  (void)headerFree(sigh);
495  sigh = NULL;
496 
497  if (sigtarget) {
498  xx = Unlink(sigtarget);
499  sigtarget = _free(sigtarget);
500  }
501  if (tmprpm[0] != '\0') {
502  xx = Unlink(tmprpm);
503  tmprpm[0] = '\0';
504  }
505 
506  return res;
507 }
508 
509 rpmRC rpmcliImportPubkey(const rpmts ts, const unsigned char * pkt, ssize_t pktlen)
510 {
511  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
512  static unsigned char zeros[] =
513  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
514  const char * afmt = "%{pubkeys:armor}";
515  const char * group = "Public Keys";
516  const char * license = "pubkey";
517  const char * buildhost = "localhost";
518  rpmuint32_t pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL);
519  rpmuint32_t zero = 0;
520  pgpDig dig = NULL;
521  pgpDigParams pubp = NULL;
522  const char * d = NULL;
523  const char * enc = NULL;
524  const char * n = NULL;
525  const char * u = NULL;
526  const char * v = NULL;
527  const char * r = NULL;
528  const char * evr = NULL;
529  Header h = NULL;
530  rpmRC rc = RPMRC_FAIL; /* assume failure */
531  char * t;
532  int xx;
533 rpmhkp hkp = NULL;
534 pgpPkt pp = (pgpPkt) alloca(sizeof(*pp));
535 int validate = 1;
536 
537  if (pkt == NULL || pktlen <= 0)
538  goto exit;
539  if (rpmtsOpenDB(ts, (O_RDWR|O_CREAT)))
540  goto exit;
541 
542 /*@-moduncon@*/
543  if ((enc = b64encode(pkt, pktlen)) == NULL)
544  goto exit;
545 /*@=moduncon@*/
546 
548  pubp = pgpGetPubkey(dig);
549 
550  //* Validate the pubkey. */
551  if (ts->hkp == NULL)
552  ts->hkp = rpmhkpNew(NULL, 0);
553  hkp = rpmhkpLink(ts->hkp);
554 hkp->pkt = (rpmuint8_t *)pkt;
555 hkp->pktlen = pktlen;
556 
557  xx = pgpGrabPkts(hkp->pkt, hkp->pktlen, &hkp->pkts, &hkp->npkts);
558  if (!xx)
559  (void) pgpPubkeyFingerprint(hkp->pkt, hkp->pktlen, hkp->keyid);
560  memcpy(pubp->signid, hkp->keyid, sizeof(pubp->signid)); /* XXX useless */
561 
562  xx = pgpPktLen(hkp->pkt, hkp->pktlen, pp);
563 
564  xx = rpmhkpLoadKey(hkp, dig, 0, 0);
565 
566  /* Validate pubkey self-signatures. */
567  if (validate) {
568  rpmRC yy = rpmhkpValidate(hkp, NULL);
569  switch (yy) {
570  case RPMRC_OK:
571  break;
572  case RPMRC_NOTFOUND:
573  case RPMRC_FAIL: /* XXX remap to NOTFOUND? */
574  case RPMRC_NOTTRUSTED:
575  case RPMRC_NOKEY:
576  default:
577 #ifdef NOTYET /* XXX make check-pubkey fails?!? . */
578  rc = yy;
579  goto exit;
580 #endif
581  /*@notreached@*/ break;
582  }
583  }
584 
585  /* XXX hack up a user id (if not already present) */
586  if (pubp->userid == NULL) {
587  if (hkp->uidx >= 0 && hkp->uidx < hkp->npkts) {
588  size_t nb = pgpPktLen(hkp->pkts[hkp->uidx], hkp->pktlen, pp);
589  char * t;
590  nb = pp->hlen;
591  t = (char *) memcpy(xmalloc(nb + 1), pp->u.u->userid, nb);
592  t[nb] = '\0';
593  pubp->userid = t;
594  } else
595  pubp->userid = xstrdup(pgpHexStr(pubp->signid+4, 4));
596  }
597 
598 #ifdef DYING
599 _rpmhkpDumpDig(__FUNCTION__, dig);
600 #endif
601 
602  /* Build header elements. */
603  if (!memcmp(pubp->signid, zeros, sizeof(pubp->signid))
604  || !memcmp(pubp->time, zeros, sizeof(pubp->time))
605  || pubp->userid == NULL)
606  goto exit;
607 
608  v = t = (char *) xmalloc(16+1);
609  t = stpcpy(t, pgpHexStr(pubp->signid, sizeof(pubp->signid)));
610 
611  r = t = (char *) xmalloc(8+1);
612  t = stpcpy(t, pgpHexStr(pubp->time, sizeof(pubp->time)));
613 
614  n = t = (char *) xmalloc(sizeof("gpg()")+8);
615  t = stpcpy( stpcpy( stpcpy(t, "gpg("), v+8), ")");
616 
617  { const char * userid =
618  (pubp->userid ? pubp->userid : pgpHexStr(pubp->signid+4, 4));
619  u = t = (char *) xmalloc(sizeof("gpg()")+strlen(userid));
620  t = stpcpy( stpcpy( stpcpy(t, "gpg("), userid), ")");
621  }
622 
623  evr = t = (char *) xmalloc(sizeof("4X:-")+strlen(v)+strlen(r));
624  t = stpcpy(t, (pubp->version == 4 ? "4:" : "3:"));
625  t = stpcpy( stpcpy( stpcpy(t, v), "-"), r);
626 
627  /* Check for pre-existing header. */
628 
629  /* Build pubkey header. */
630  h = headerNew();
631 
632  he->append = 1;
633 
634  he->tag = RPMTAG_PUBKEYS;
635  he->t = RPM_STRING_ARRAY_TYPE;
636  he->p.argv = &enc;
637  he->c = 1;
638  xx = headerPut(h, he, 0);
639 
640  he->append = 0;
641 
642  d = headerSprintf(h, afmt, NULL, rpmHeaderFormats, NULL);
643  if (d == NULL)
644  goto exit;
645 
646  he->t = RPM_STRING_TYPE;
647  he->c = 1;
648  he->tag = RPMTAG_NAME;
649  he->p.str = xstrdup("gpg-pubkey");
650  xx = headerPut(h, he, 0);
651  he->p.ptr = _free(he->p.ptr);
652  he->tag = RPMTAG_VERSION;
653  he->p.str = v+8;
654  xx = headerPut(h, he, 0);
655  he->tag = RPMTAG_RELEASE;
656  he->p.str = xstrdup(r);
657  xx = headerPut(h, he, 0);
658  he->p.ptr = _free(he->p.ptr);
659 
660  /* Add Summary/Description/Group. */
661  he->tag = RPMTAG_DESCRIPTION;
662  he->p.str = xstrdup(d);
663 #if defined(SUPPORT_I18NSTRING_TYPE)
664  xx = headerAddI18NString(h, he->tag, he->p.str, "C");
665 #else
666  xx = headerPut(h, he, 0);
667 #endif
668  he->p.ptr = _free(he->p.ptr);
669 
670  he->tag = RPMTAG_GROUP;
671  he->p.str = xstrdup(group);
672 #if defined(SUPPORT_I18NSTRING_TYPE)
673  xx = headerAddI18NString(h, he->tag, he->p.str, "C");
674 #else
675  xx = headerPut(h, he, 0);
676 #endif
677  he->p.ptr = _free(he->p.ptr);
678 
679  he->tag = RPMTAG_SUMMARY;
680  he->p.str = xstrdup(u);
681 #if defined(SUPPORT_I18NSTRING_TYPE)
682  xx = headerAddI18NString(h, he->tag, he->p.str, "C");
683 #else
684  xx = headerPut(h, he, 0);
685 #endif
686  he->p.ptr = _free(he->p.ptr);
687 
688 #ifdef NOTYET /* XXX can't erase pubkeys with "pubkey" arch. */
689  /* Add a "pubkey" arch/os to avoid missing value NULL ptrs. */
690  he->tag = RPMTAG_ARCH;
691  he->p.str = "pubkey";
692  xx = headerPut(h, he, 0);
693  he->tag = RPMTAG_OS;
694  he->p.str = "pubkey";
695  xx = headerPut(h, he, 0);
696 #endif
697 
698  he->tag = RPMTAG_LICENSE;
699  he->p.str = xstrdup(license);
700  xx = headerPut(h, he, 0);
701  he->p.ptr = _free(he->p.ptr);
702 
703  he->tag = RPMTAG_SIZE;
704  he->t = RPM_UINT32_TYPE;
705  he->p.ui32p = &zero;
706  he->c = 1;
707  xx = headerPut(h, he, 0);
708 
709  he->append = 1;
710 
711  /* Provides: gpg(IDENTITY) = PUBKEYVERSIONTYPE:PUBKEYID-CREATION */
712  he->tag = RPMTAG_PROVIDENAME;
713  he->t = RPM_STRING_ARRAY_TYPE;
714  he->p.argv = &u;
715  he->c = 1;
716  xx = headerPut(h, he, 0);
718  he->t = RPM_STRING_ARRAY_TYPE;
719  he->p.argv = &evr;
720  he->c = 1;
721  xx = headerPut(h, he, 0);
722  he->tag = RPMTAG_PROVIDEFLAGS;
723  he->t = RPM_UINT32_TYPE;
724  he->p.ui32p = &pflags;
725  he->c = 1;
726  xx = headerPut(h, he, 0);
727 
728  /* Provides: gpg(PUBKEYID) = PUBKEYVERSION:PUBKEYID-CREATION */
729  he->tag = RPMTAG_PROVIDENAME;
730  he->t = RPM_STRING_ARRAY_TYPE;
731  he->p.argv = &n;
732  he->c = 1;
733  xx = headerPut(h, he, 0);
735  he->t = RPM_STRING_ARRAY_TYPE;
736  he->p.argv = &evr;
737  he->c = 1;
738  xx = headerPut(h, he, 0);
739  he->tag = RPMTAG_PROVIDEFLAGS;
740  he->t = RPM_UINT32_TYPE;
741  he->p.ui32p = &pflags;
742  he->c = 1;
743  xx = headerPut(h, he, 0);
744 
745  he->append = 0;
746 
747  he->tag = RPMTAG_RPMVERSION;
748  he->t = RPM_STRING_TYPE;
749  he->p.str = xstrdup(RPMVERSION);
750  he->c = 1;
751  xx = headerPut(h, he, 0);
752  he->p.ptr = _free(he->p.ptr);
753 
754  /* XXX W2DO: tag value inherited from parent? */
755  he->tag = RPMTAG_BUILDHOST;
756  he->t = RPM_STRING_TYPE;
757  he->p.str = xstrdup(buildhost);
758  he->c = 1;
759  xx = headerPut(h, he, 0);
760  he->p.ptr = _free(he->p.ptr);
761 
762  { rpmuint32_t tid = rpmtsGetTid(ts);
763  he->tag = RPMTAG_INSTALLTIME;
764  he->t = RPM_UINT32_TYPE;
765  he->p.ui32p = &tid;
766  he->c = 1;
767  xx = headerPut(h, he, 0);
768  /* XXX W2DO: tag value inherited from parent? */
769  he->tag = RPMTAG_BUILDTIME;
770  he->t = RPM_UINT32_TYPE;
771  he->p.ui32p = &tid;
772  he->c = 1;
773  xx = headerPut(h, he, 0);
774  }
775 
776 #ifdef NOTYET
777  /* XXX W2DO: tag value inherited from parent? */
778  he->tag = RPMTAG_SOURCERPM;
779  he->t = RPM_STRING_TYPE;
780  he->p.str = fn;
781  he->c = 1;
782  xx = headerPut(h, he, 0);
783 #endif
784 
785  /* Reallocate the pubkey header into an immutable region. */
787  h = headerReload(h, he->tag);
788  { size_t length = 0;
789  he->t = RPM_BIN_TYPE;
790  he->p.ptr = headerUnload(h, &length);
791  he->c = length;
792  }
793 
794  /* Calculate the header-only SHA1 digest. */
796  unsigned char * hmagic = NULL;
797  size_t nmagic = 0;
798  const char * SHA1 = NULL;
799 
800  (void) headerGetMagic(NULL, &hmagic, &nmagic);
801  if (hmagic && nmagic > 0)
802  (void) rpmDigestUpdate(ctx, hmagic, nmagic);
803  (void) rpmDigestUpdate(ctx, he->p.ptr, he->c);
804  (void) rpmDigestFinal(ctx, &SHA1, NULL, 1);
805  he->p.ptr = _free(he->p.ptr);
806 
807  if (SHA1 == NULL)
808  goto exit;
809  he->tag = RPMTAG_SHA1HEADER;
810  he->t = RPM_STRING_TYPE;
811  he->p.str = SHA1;
812  he->c = 1;
813  xx = headerPut(h, he, 0);
814  SHA1 = _free(SHA1);
815  }
816 
817  he->tag = RPMTAG_PACKAGECOLOR;
818  he->t = RPM_UINT32_TYPE;
819  he->p.ui32p = &zero;
820  he->c = 1;
821  xx = headerPut(h, he, 0);
822 
823  /* Add header to database. */
824  xx = rpmtxnBegin(rpmtsGetRdb(ts), NULL, NULL);
825  xx = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), h, NULL);
826  if (xx != 0) {
827  xx = rpmtxnAbort(rpmtsGetRdb(ts)->db_txn);
828  rpmtsGetRdb(ts)->db_txn = NULL;
829  goto exit;
830  } else
831  xx = rpmtxnCommit(rpmtsGetRdb(ts)->db_txn);
832  rpmtsGetRdb(ts)->db_txn = NULL;
833  xx = rpmtxnCheckpoint(rpmtsGetRdb(ts));
834  rc = RPMRC_OK;
835 
836 exit:
837  /* Clean up. */
838 hkp->pkt = NULL;
839 hkp->pktlen = 0;
840 hkp->pkts = _free(hkp->pkts);
841 hkp->npkts = 0;
842  (void) rpmhkpFree(hkp);
843  hkp = NULL;
844  (void)headerFree(h);
845  h = NULL;
846  dig = pgpDigFree(dig);
847  n = _free(n);
848  u = _free(u);
849  v = _free(v);
850  r = _free(r);
851  evr = _free(evr);
852  enc = _free(enc);
853  d = _free(d);
854 
855  return rc;
856 }
857 
866 static int rpmcliImportPubkeys(const rpmts ts,
867  /*@unused@*/ QVA_t qva,
868  /*@null@*/ const char ** argv)
869  /*@globals rpmGlobalMacroContext, h_errno,
870  fileSystem, internalState @*/
871  /*@modifies ts, rpmGlobalMacroContext,
872  fileSystem, internalState @*/
873 {
874  const char * fn;
875  rpmuint8_t * pkt = NULL;
876  size_t pktlen = 0;
877  char * t = NULL;
878  int res = 0;
879  rpmRC rpmrc;
880  int rc;
881 
882  if (argv == NULL) return res;
883 
884  while ((fn = *argv++) != NULL) {
885 
886  rpmtsClean(ts);
887  pkt = _free(pkt);
888  t = _free(t);
889 
890  /* If arg looks like a keyid, then attempt keyserver retrieve. */
891  if (fn[0] == '0' && fn[1] == 'x') {
892  const char * s;
893  int i;
894  for (i = 0, s = fn+2; *s && isxdigit(*s); s++, i++)
895  {};
896  if (i == 8 || i == 16) {
897  t = rpmExpand("%{_hkp_keyserver_query}", fn, NULL);
898  if (t && *t != '%')
899  fn = t;
900  }
901  }
902 
903  /* Read pgp packet. */
904  if ((rc = pgpReadPkts(fn, &pkt, &pktlen)) <= 0) {
905  rpmlog(RPMLOG_ERR, _("%s: import read failed(%d).\n"), fn, rc);
906  res++;
907  continue;
908  }
909  if (rc != PGPARMOR_PUBKEY) {
910  rpmlog(RPMLOG_ERR, _("%s: not an armored public key.\n"), fn);
911  res++;
912  continue;
913  }
914 
915  /* Import pubkey packet(s). */
916  if ((rpmrc = rpmcliImportPubkey(ts, pkt, pktlen)) != RPMRC_OK) {
917  rpmlog(RPMLOG_ERR, _("%s: import failed.\n"), fn);
918  res++;
919  continue;
920  }
921 
922  }
923 
924 rpmtsClean(ts);
925  pkt = _free(pkt);
926  t = _free(t);
927  return res;
928 }
929 
933 static rpmRC readFile(FD_t fd, const char * fn)
934  /*@globals fileSystem, internalState @*/
935  /*@modifies fd, fileSystem, internalState @*/
936 {
937 rpmxar xar = fdGetXAR(fd);
938 pgpDig dig = fdGetDig(fd);
939  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
940  unsigned char buf[4*BUFSIZ];
941  ssize_t count;
942  unsigned ix;
943  rpmRC rc;
944  int xx;
945 
946  dig->nbytes = 0;
947 
948  /* Read the header from the package. */
949  { Header h = NULL;
950  const char item[] = "Header";
951  const char * msg = NULL;
952  rc = rpmpkgRead(item, fd, &h, &msg);
953  if (rc != RPMRC_OK) {
954  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
955  msg = _free(msg);
956  goto exit;
957  }
958  msg = _free(msg);
959 
960  dig->nbytes += headerSizeof(h);
961 
962  /* Fish out the autosign pubkey (if present). */
963  he->tag = RPMTAG_PUBKEYS;
964  xx = headerGet(h, he, 0);
965  if (xx && he->p.argv != NULL && he->c > 0)
966  switch (he->t) {
967  default:
968  break;
970  ix = he->c - 1; /* XXX FIXME: assumes last pubkey */
971  dig->pub = _free(dig->pub);
972  dig->publen = 0;
973  { rpmiob iob = rpmiobNew(0);
974  iob = rpmiobAppend(iob, he->p.argv[ix], 0);
975  xx = pgpArmorUnwrap(iob, (rpmuint8_t **)&dig->pub, &dig->publen);
976  iob = rpmiobFree(iob);
977  }
978  if (xx != PGPARMOR_PUBKEY) {
979  dig->pub = _free(dig->pub);
980  dig->publen = 0;
981  }
982  break;
983  }
984  he->p.ptr = _free(he->p.ptr);
985 
987  unsigned char * hmagic = NULL;
988  size_t nmagic = 0;
989 
991  xx = headerGet(h, he, 0);
992  if (!xx || he->p.ptr == NULL) {
993  (void)headerFree(h);
994  h = NULL;
995  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, _("headerGet failed"),
996  _("failed to retrieve original header\n"));
997  rc = RPMRC_FAIL;
998  goto exit;
999  }
1000  (void) headerGetMagic(NULL, &hmagic, &nmagic);
1001  dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
1002  if (hmagic && nmagic > 0)
1003  (void) rpmDigestUpdate(dig->hdrsha1ctx, hmagic, nmagic);
1004  (void) rpmDigestUpdate(dig->hdrsha1ctx, he->p.ptr, he->c);
1005  dig->hdrctx = rpmDigestInit((pgpHashAlgo)dig->signature.hash_algo, RPMDIGEST_NONE);
1006  if (hmagic && nmagic > 0)
1007  (void) rpmDigestUpdate(dig->hdrctx, hmagic, nmagic);
1008  (void) rpmDigestUpdate(dig->hdrctx, he->p.ptr, he->c);
1009  he->p.ptr = _free(he->p.ptr);
1010  }
1011  (void)headerFree(h);
1012  h = NULL;
1013  }
1014 
1015  if (xar != NULL) {
1016  const char item[] = "Payload";
1017  if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) {
1018  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item,
1019  _("XAR file not found (or no XAR support)"));
1020  rc = RPMRC_NOTFOUND;
1021  goto exit;
1022  }
1023  }
1024 
1025  /* Read the payload from the package. */
1026  while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
1027  dig->nbytes += count;
1028  if (count < 0 || Ferror(fd)) {
1029  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, _("Fread failed"), Fstrerror(fd));
1030  rc = RPMRC_FAIL;
1031  goto exit;
1032  }
1033 
1034  /* XXX Steal the digest-in-progress from the file handle. */
1035  fdStealDigest(fd, dig);
1036 
1037  rc = RPMRC_OK; /* XXX unnecessary */
1038 
1039 exit:
1040  return rc;
1041 }
1042 
1043 int rpmVerifySignatures(QVA_t qva, rpmts ts, void * _fd, const char * fn)
1044 {
1045  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1046  HE_t she = (HE_t) memset(alloca(sizeof(*she)), 0, sizeof(*she));
1047 /*@-castexpose@*/
1048  FD_t fd = (FD_t)_fd;
1049 /*@=castexpose@*/
1050  char result[1024];
1051  char buf[8192], * b;
1052  char missingKeys[7164], * m;
1053  char untrustedKeys[7164], * u;
1054  pgpDig dig;
1055  pgpDigParams sigp;
1056  Header sigh = NULL;
1057  HeaderIterator hi = NULL;
1058  int res = 0;
1059  int xx;
1060  rpmRC sigres;
1061  int failed;
1062  int nodigests = !(qva->qva_flags & VERIFY_DIGEST);
1063  int nosignatures = !(qva->qva_flags & VERIFY_SIGNATURE);
1064 pgpPkt pp = (pgpPkt) alloca(sizeof(*pp));
1065 
1066  {
1067  { const char item[] = "Lead";
1068  const char * msg = NULL;
1069  rpmRC rc = rpmpkgRead(item, fd, NULL, &msg);
1070  switch (rc) {
1071  default:
1072  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
1073  msg = _free(msg);
1074  res++;
1075  goto exit;
1076  /*@notreachea@*/ break;
1077  case RPMRC_OK:
1078  break;
1079  }
1080  msg = _free(msg);
1081  }
1082 
1083  { const char item[] = "Signature";
1084  const char * msg = NULL;
1085  rpmRC rc = rpmpkgRead(item, fd, &sigh, &msg);
1086  switch (rc) {
1087  default:
1088  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item,
1089  (msg && *msg ? msg : ""));
1090  msg = _free(msg);
1091  res++;
1092  goto exit;
1093  /*@notreached@*/ /*@switchbreak@*/ break;
1094  case RPMRC_OK:
1095  if (sigh == NULL) {
1096  rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
1097  res++;
1098  goto exit;
1099  }
1100  /*@switchbreak@*/ break;
1101  }
1102  msg = _free(msg);
1103  }
1104 
1105  /* Grab a hint of what needs doing to avoid duplication. */
1106  she->tag = (rpmTag)0;
1107  if (she->tag == 0 && !nosignatures) {
1108  if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_DSA))
1109  she->tag = (rpmTag) RPMSIGTAG_DSA;
1110  else if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_RSA))
1111  she->tag = (rpmTag) RPMSIGTAG_RSA;
1112  }
1113  if (she->tag == 0 && !nodigests) {
1114  if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_MD5))
1115  she->tag = (rpmTag) RPMSIGTAG_MD5;
1116  else if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_SHA1))
1117  she->tag = (rpmTag) RPMSIGTAG_SHA1; /* XXX never happens */
1118  }
1119 
1120  dig = rpmtsDig(ts);
1121 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */
1122  (void) fdSetDig(fd, dig);
1123 /*@=mods@*/
1124  sigp = pgpGetSignature(dig);
1125 
1126  /* XXX RSA needs the hash_algo, so decode early. */
1127  if ((rpmSigTag) she->tag == RPMSIGTAG_RSA) {
1128  he->tag = she->tag;
1129  xx = headerGet(sigh, he, 0);
1130  xx = pgpPktLen(he->p.ui8p, he->c, pp);
1131  xx = rpmhkpLoadSignature(NULL, dig, pp);
1132  he->p.ptr = _free(he->p.ptr);
1133  }
1134 
1135 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */
1136  if (headerIsEntry(sigh, (rpmTag)RPMSIGTAG_MD5))
1137  fdInitDigest(fd, PGPHASHALGO_MD5, 0);
1138 /*@=mods@*/
1139 
1140  /* Read the file, generating digest(s) on the fly. */
1141 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */
1142  if (dig == NULL || sigp == NULL
1143  || readFile(fd, fn) != RPMRC_OK)
1144  {
1145  res++;
1146  goto exit;
1147  }
1148 /*@=mods@*/
1149 
1150  failed = 0;
1151  b = buf; *b = '\0';
1152  m = missingKeys; *m = '\0';
1153  u = untrustedKeys; *u = '\0';
1154  sprintf(b, "%s:%c", fn, (rpmIsVerbose() ? '\n' : ' ') );
1155  b += strlen(b);
1156 
1157  if (sigh != NULL)
1158  for (hi = headerInit(sigh);
1159  headerNext(hi, she, 0) != 0;
1160  she->p.ptr = _free(she->p.ptr))
1161  {
1162 
1163 assert(she->p.ptr != NULL);
1164 
1165  /* Clean up parameters from previous she->tag. */
1166  pgpDigClean(dig);
1167 
1168 /*@-ownedtrans -noeffect@*/
1169  xx = pgpSetSig(dig, she->tag, she->t, she->p.ptr, she->c);
1170 /*@=ownedtrans =noeffect@*/
1171 
1172  switch ((rpmSigTag)she->tag) {
1173  case RPMSIGTAG_RSA:
1174  case RPMSIGTAG_DSA:
1175  if (nosignatures)
1176  continue;
1177 
1178  xx = pgpPktLen(she->p.ui8p, she->c, pp);
1179  xx = rpmhkpLoadSignature(NULL, dig, pp);
1180  if (sigp->version != 3 && sigp->version != 4) {
1182  _("skipping package %s with unverifiable V%u signature\n"),
1183  fn, sigp->version);
1184  res++;
1185  goto exit;
1186  }
1187  /*@switchbreak@*/ break;
1188  case RPMSIGTAG_SHA1:
1189  if (nodigests)
1190  continue;
1191  /* XXX Don't bother with header sha1 if header dsa. */
1192  if (!nosignatures && (rpmSigTag)she->tag == RPMSIGTAG_DSA)
1193  continue;
1194  /*@switchbreak@*/ break;
1195  case RPMSIGTAG_MD5:
1196  if (nodigests)
1197  continue;
1198  /*@switchbreak@*/ break;
1199  default:
1200  continue;
1201  /*@notreached@*/ /*@switchbreak@*/ break;
1202  }
1203 
1204  sigres = rpmVerifySignature(dig, result);
1205 
1206  if (sigres) {
1207  failed = 1;
1208  if (rpmIsVerbose())
1209  b = stpcpy( stpcpy( stpcpy(b, " "), result), "\n");
1210  else
1211  switch ((rpmSigTag)she->tag) {
1212  case RPMSIGTAG_SIZE:
1213  b = stpcpy(b, "SIZE ");
1214  /*@switchbreak@*/ break;
1215  case RPMSIGTAG_SHA1:
1216  b = stpcpy(b, "SHA1 ");
1217  /*@switchbreak@*/ break;
1218  case RPMSIGTAG_MD5:
1219  b = stpcpy(b, "MD5 ");
1220  /*@switchbreak@*/ break;
1221  case RPMSIGTAG_RSA:
1222  b = stpcpy(b, "RSA ");
1223  /*@switchbreak@*/ break;
1224  case RPMSIGTAG_DSA:
1225  b = stpcpy(b, "(SHA1) DSA ");
1226  /*@switchbreak@*/ break;
1227  default:
1228  b = stpcpy(b, "?UnknownSignatureType? ");
1229  /*@switchbreak@*/ break;
1230  }
1231  } else {
1232  if (rpmIsVerbose())
1233  b = stpcpy( stpcpy( stpcpy(b, " "), result), "\n");
1234  else
1235  switch ((rpmSigTag)she->tag) {
1236  case RPMSIGTAG_SIZE:
1237  b = stpcpy(b, "size ");
1238  /*@switchbreak@*/ break;
1239  case RPMSIGTAG_SHA1:
1240  b = stpcpy(b, "sha1 ");
1241  /*@switchbreak@*/ break;
1242  case RPMSIGTAG_MD5:
1243  b = stpcpy(b, "md5 ");
1244  /*@switchbreak@*/ break;
1245  case RPMSIGTAG_RSA:
1246  b = stpcpy(b, "rsa ");
1247  /*@switchbreak@*/ break;
1248  case RPMSIGTAG_DSA:
1249  b = stpcpy(b, "(sha1) dsa ");
1250  /*@switchbreak@*/ break;
1251  default:
1252  b = stpcpy(b, "??? ");
1253  /*@switchbreak@*/ break;
1254  }
1255  }
1256  }
1257  hi = headerFini(hi);
1258  /* XXX clear the already free'd signature data. */
1259 /*@-noeffect@*/
1260  xx = pgpSetSig(dig, 0, 0, NULL, 0);
1261 /*@=noeffect@*/
1262 
1263  res += failed;
1264 
1265  if (failed) {
1266  if (rpmIsVerbose()) {
1267  rpmlog(RPMLOG_NOTICE, "%s", buf);
1268  } else {
1269  rpmlog(RPMLOG_NOTICE, "%s%s%s%s%s%s%s%s\n", buf,
1270  _("NOT_OK"),
1271  (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
1272  missingKeys,
1273  (missingKeys[0] != '\0') ? _(") ") : "",
1274  (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
1275  untrustedKeys,
1276  (untrustedKeys[0] != '\0') ? _(")") : "");
1277 
1278  }
1279  } else {
1280  if (rpmIsVerbose()) {
1281  rpmlog(RPMLOG_NOTICE, "%s", buf);
1282  } else {
1283  rpmlog(RPMLOG_NOTICE, "%s%s%s%s%s%s%s%s\n", buf,
1284  _("OK"),
1285  (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
1286  missingKeys,
1287  (missingKeys[0] != '\0') ? _(") ") : "",
1288  (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
1289  untrustedKeys,
1290  (untrustedKeys[0] != '\0') ? _(")") : "");
1291  }
1292  }
1293 
1294  }
1295 
1296 exit:
1297  rpmtsCleanDig(ts);
1298  (void)headerFree(sigh);
1299  sigh = NULL;
1300  return res;
1301 }
1302 
1303 int rpmcliSign(rpmts ts, QVA_t qva, const char ** argv)
1304  /*@globals rpmioFtsOpts @*/
1305  /*@modifies rpmioFtsOpts @*/
1306 {
1307  rpmRC rpmrc;
1308  int res = 0;
1309 
1310  if (argv == NULL) return res;
1311 
1312  switch (qva->qva_mode) {
1313  case RPMSIGN_CHK_SIGNATURE:
1314  break;
1315  case RPMSIGN_IMPORT_PUBKEY:
1316  return rpmcliImportPubkeys(ts, qva, argv);
1317  /*@notreached@*/ break;
1318  case RPMSIGN_NEW_SIGNATURE:
1319  case RPMSIGN_ADD_SIGNATURE:
1320  case RPMSIGN_DEL_SIGNATURE:
1321  return rpmReSign(ts, qva, argv);
1322  /*@notreached@*/ break;
1323  case RPMSIGN_NONE:
1324  default:
1325  return -1;
1326  /*@notreached@*/ break;
1327  }
1328 
1329 { /* start-of-arg-iteration */
1330 
1331  int tag = (qva->qva_source == RPMQV_FTSWALK)
1333  rpmgi gi = rpmgiNew(ts, tag, NULL, 0);
1334  rpmgiFlags _giFlags = RPMGI_NONE;
1335  rpmRC rc;
1336 
1337  if (rpmioFtsOpts == 0)
1339  rc = (rpmRC)
1340  rpmgiSetArgs(gi, argv, rpmioFtsOpts,
1341  (rpmgiFlags)(_giFlags|RPMGI_NOHEADER));
1342  while ((rpmrc = rpmgiNext(gi)) == RPMRC_OK) {
1343  const char * fn = rpmgiHdrPath(gi);
1344  FD_t fd;
1345  int xx;
1346 
1347  fd = Fopen(fn, "r.fdio");
1348  if (fd == NULL || Ferror(fd)) {
1349  rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"),
1350  fn, Fstrerror(fd));
1351  res++;
1352  } else if (rpmVerifySignatures(qva, ts, fd, fn)) {
1353  res++;
1354  }
1355 
1356  if (fd != NULL) {
1357  xx = Fclose(fd);
1358  }
1359  }
1360 
1361  /* XXX disambiguate end-of-iteration from item failures. */
1362  if (res == 0 && rpmrc == RPMRC_NOTFOUND) {
1363  rpmrc = (rpmRC) rpmgiRc(gi);
1364  if (rpmrc != RPMRC_OK)
1365  res++;
1366  }
1367 
1368  gi = rpmgiFree(gi);
1369 
1370 } /* end-of-arg-iteration */
1371 
1372  return res;
1373 }
Structure(s)and methods for a XAR archive wrapper format.
rpmTagType t
Definition: rpmtag.h:505
pgpDigParams pgpGetPubkey(pgpDig dig)
Return OpenPGP pubkey parameters.
Definition: rpmpgp.c:1232
const char * str
Definition: rpmtag.h:72
rpmTag tag
Definition: rpmtag.h:504
int rpmgiRc(rpmgi gi)
Return current iteration item(s) exit code.
Definition: rpmgi.c:859
const char ** argv
Definition: rpmtag.h:74
struct rpmxar_s * rpmxar
Definition: rpmxar.h:14
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:433
int headerIsEntry(Header h, rpmTag tag)
Check if tag is in header.
Definition: header.c:1431
pgpDig pgpDigFree(pgpDig dig)
Destroy a container for parsed OpenPGP packates.
rpmRC rpmcliImportPubkey(const rpmts ts, const unsigned char *pkt, ssize_t pktlen)
Import public key packet(s).
Definition: rpmchecksig.c:509
int pgpPktLen(const rpmuint8_t *pkt, size_t pleft, pgpPkt pp)
Definition: rpmpgp.c:940
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:1665
enum rpmSigTag_e rpmSigTag
Definition: rpmtag.h:475
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:322
rpmuint32_t * ui32p
Definition: rpmtag.h:69
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2833
rpmgi rpmgiFree(rpmgi gi)
Destroy a generalized iterator.
struct pgpDigParams_s * pgpDigParams
Definition: rpmiotypes.h:87
DIGEST_CTX rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
Initialize digest.
Definition: digest.c:244
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2222
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2285
enum pgpHashAlgo_e pgpHashAlgo
9.4.
The Header data structure.
HeaderIterator headerFini(HeaderIterator hi)
Destroy header tag container iterator.
Definition: header.c:2125
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:637
headerSprintfExtension rpmHeaderFormats
Table of query format extensions.
Definition: formats.c:305
HeaderIterator headerInit(Header h)
Create header tag iterator.
Definition: header.c:2135
FD_t fdLink(void *cookie, const char *msg)
static rpmRC readFile(FD_t fd, const char *fn)
Definition: rpmchecksig.c:933
int Fflush(FD_t fd)
fflush(3) clone.
Definition: rpmio.c:2916
int headerDel(Header h, HE_t he, unsigned int flags)
Remove tag container from header.
Definition: header.c:2304
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:1257
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:1425
Header tag iterator data structure.
Definition: header.c:2120
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:78
int headerNext(HeaderIterator hi, HE_t he, unsigned int flags)
Return next tag from header.
Definition: header.c:2149
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:1397
Command line option information.
Definition: rpmcli.h:634
char * headerSprintf(Header h, const char *fmt, headerTagTableEntry tags, headerSprintfExtension exts, errmsg_t *errmsg)
Return formatted output string from header tags.
Definition: hdrfmt.c:6700
#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:1564
unsigned int rpmuint32_t
Definition: rpmiotypes.h:25
struct _HE_s * HE_t
Definition: rpmtag.h:58
void rpmtsCleanDig(rpmts ts)
Free signature verification data.
Definition: pkgio.c:457
const char * Fstrerror(FD_t fd)
strerror(3) clone.
Definition: rpmio.c:2401
void * ptr
Definition: rpmtag.h:66
int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len)
Update context with next plain text buffer.
Definition: digest.c:907
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
FD_t fdFree(FD_t fd, const char *msg)
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:23
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:480
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:507
struct pgpPkt_s * pgpPkt
Definition: rpmiotypes.h:79
pgpDigParams pgpGetSignature(pgpDig dig)
Return OpenPGP signature parameters.
Definition: rpmpgp.c:1227
#define RPMDBI_FTSWALK
Definition: rpmtag.h:488
Digest private data.
Definition: digest.c:127
rpmRC rpmgiSetArgs(rpmgi gi, ARGV_t argv, int ftsOpts, rpmgiFlags flags)
Load iterator args.
Definition: rpmgi.c:864
rpmQVSources qva_source
Definition: rpmcli.h:635
The FD_t File Handle data structure.
struct pgpDig_s * pgpDig
Definition: rpmiotypes.h:83
rpmTagCount c
Definition: rpmtag.h:508
Generate and verify rpm package signatures.
Header headerFree(Header h)
Dereference a header instance.
int rpmioFtsOpts
Definition: poptIO.c:526
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:941
char * rpmExpand(const char *arg,...)
Return (malloc&#39;ed) concatenated macro expansion(s).
Definition: macro.c:3117
void pgpDigClean(pgpDig dig)
Release (malloc&#39;d) data from container.
Definition: rpmpgp.c:1107
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:67
const char * passPhrase
Definition: rpmcli.h:659
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
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:1307
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:1206
#define RPMDBI_ARGLIST
Definition: rpmtag.h:487
size_t headerSizeof(Header h)
Return size of on-disk header representation in bytes.
Definition: header.c:266
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2944
Definition: rpmtag.h:503
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:970
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:647
struct rpmiob_s * rpmiob
Definition: rpmiotypes.h:57
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)
int rpmcliSign(rpmts ts, QVA_t qva, const char **argv)
Create/Modify/Check elements from signature header.
Definition: rpmchecksig.c:1303
#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
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:921
#define _(Text)
Definition: system.h:30
int rpmdbAdd(rpmdb db, int iid, Header h, rpmts ts)
Add package header to rpm database and indices.
Definition: rpmdb.c:2884
const char * rpmgiHdrPath(rpmgi gi)
Return current header path.
Definition: rpmgi.c:840
#define xmalloc
Definition: system.h:33
static int rpmReSign(rpmts ts, QVA_t qva, const char **argv)
Create/modify elements in signature header.
Definition: rpmchecksig.c:193
rpmRC rpmpkgRead(const char *fn, FD_t fd, void *ptr, const char **msg)
Read item from file descriptor.
Definition: pkgio.c:1647
rpmuint32_t rpmtsGetTid(rpmts ts)
Get transaction id, i.e.
Definition: rpmts.c:1022
Access RPM indices using Berkeley DB interface(s).
enum rpmTag_e rpmTag
Definition: rpmtag.h:471
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:866
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:1165
pgpDig rpmtsDig(rpmts ts)
Get OpenPGP packet parameters, i.e.
Definition: pkgio.c:442
Header headerNew(void)
Create new (empty) header instance.
Definition: header.c:180
#define FTS_NOSTAT
Definition: fts.h:90
int rpmVerifySignatures(QVA_t qva, rpmts ts, void *_fd, const char *fn)
Check package and header signatures.
Definition: rpmchecksig.c:1043
void rpmtsClean(rpmts ts)
Free memory needed only for dependency checks and ordering.
Definition: rpmts.c:596
unsigned int append
Definition: rpmtag.h:512
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397