rpm  5.4.14
package.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <netinet/in.h>
8 
9 #include <rpmio_internal.h>
10 #include <rpmcb.h> /* XXX fnpyKey */
11 
12 #define _RPMHKP_INTERNAL /* XXX internal prototypes. */
13 #include <rpmhkp.h>
14 
15 #include <rpmtag.h>
16 #include <rpmtypes.h>
17 #include <pkgio.h>
18 #include "signature.h" /* XXX rpmVerifySignature */
19 
20 #include "rpmts.h"
21 
22 #include "debug.h"
23 
24 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
25 
26 /*@access pgpDig @*/
27 /*@access pgpDigParams @*/
28 /*@access Header @*/ /* XXX compared with NULL */
29 /*@access FD_t @*/ /* XXX void * */
30 
31 /*@unchecked@*/ /*@only@*/ /*@null@*/
32 unsigned int * keyids = NULL;
33 
34 #ifndef DYING
35 /*@unchecked@*/
36 static unsigned int nkeyids_max = 256;
37 /*@unchecked@*/
38 static unsigned int nkeyids = 0;
39 /*@unchecked@*/
40 static unsigned int nextkeyid = 0;
41 
48  /*@globals nextkeyid, nkeyids, keyids @*/
49  /*@modifies nextkeyid, nkeyids, keyids @*/
50 {
52  const void * sig = pgpGetSig(dig);
53  unsigned int keyid;
54  unsigned int i;
55 
56  if (sig == NULL || dig == NULL || sigp == NULL)
57  return 0;
58 
59  keyid = pgpGrab(sigp->signid+4, 4);
60  if (keyid == 0)
61  return 0;
62 
63  if (keyids != NULL)
64  for (i = 0; i < nkeyids; i++) {
65  if (keyid == keyids[i])
66  return 1;
67  }
68 
69  if (nkeyids < nkeyids_max) {
70  nkeyids++;
71  keyids = (unsigned int *) xrealloc(keyids, nkeyids * sizeof(*keyids));
72  }
73  if (keyids) /* XXX can't happen */
74  keyids[nextkeyid] = keyid;
75  nextkeyid++;
77 
78  return 0;
79 }
80 #endif
81 
82 /*@-mods@*/
83 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
84 {
85  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
86  HE_t she = (HE_t) memset(alloca(sizeof(*she)), 0, sizeof(*she));
87  pgpDig dig = rpmtsDig(ts);
88  char buf[8*BUFSIZ];
89  ssize_t count;
90  Header sigh = NULL;
91  rpmtsOpX opx;
92  rpmop op = NULL;
93  size_t nb;
94  unsigned ix;
95  Header h = NULL;
96  const char * msg = NULL;
98  rpmRC rc = RPMRC_FAIL; /* assume failure */
99  rpmop opsave = (rpmop) memset(alloca(sizeof(*opsave)), 0, sizeof(*opsave));
100  int xx;
101 pgpPkt pp = (pgpPkt) alloca(sizeof(*pp));
102 
103  if (hdrp) *hdrp = NULL;
104 
105 assert(dig != NULL);
106  (void) fdSetDig(fd, dig);
107 
108  /* Snapshot current I/O counters (cached persistent I/O reuses counters) */
109  (void) rpmswAdd(opsave, fdstat_op(fd, FDSTAT_READ));
110 
111  { const char item[] = "Lead";
112  msg = NULL;
113  rc = rpmpkgRead(item, fd, NULL, &msg);
114  switch (rc) {
115  default:
116  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
117  /*@fallthrough@*/
118  case RPMRC_NOTFOUND:
119  msg = _free(msg);
120  goto exit;
121  /*@notreached@*/ break;
122  case RPMRC_OK:
123  break;
124  }
125  msg = _free(msg);
126  }
127 
128  { const char item[] = "Signature";
129  msg = NULL;
130  rc = rpmpkgRead(item, fd, &sigh, &msg);
131  switch (rc) {
132  default:
133  rpmlog(RPMLOG_ERR, "%s: %s: %s", fn, item,
134  (msg && *msg ? msg : _("read failed\n")));
135  msg = _free(msg);
136  goto exit;
137  /*@notreached@*/ break;
138  case RPMRC_OK:
139  if (sigh == NULL) {
140  rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
141  rc = RPMRC_FAIL;
142  goto exit;
143  }
144  break;
145  }
146  msg = _free(msg);
147  }
148 
149 #define _chk(_mask) (she->tag == 0 && !(vsflags & (_mask)))
150 
151  /*
152  * Figger the most effective available signature.
153  * Prefer signatures over digests, then header-only over header+payload.
154  * DSA will be preferred over RSA if both exist because tested first.
155  * Note that NEEDPAYLOAD prevents header+payload signatures and digests.
156  */
157  she->tag = (rpmTag)0;
158  opx = (rpmtsOpX)0;
159  vsflags = pgpDigVSFlags;
161  she->tag = (rpmTag)RPMSIGTAG_DSA;
162  } else
164  she->tag = (rpmTag)RPMSIGTAG_RSA;
165  } else
167  she->tag = (rpmTag)RPMSIGTAG_SHA1;
168  } else
171  {
172  she->tag = (rpmTag)RPMSIGTAG_MD5;
174  opx = RPMTS_OP_DIGEST;
175  }
176 
177  /* Read the metadata, computing digest(s) on the fly. */
178  h = NULL;
179  msg = NULL;
180 
181  /* XXX stats will include header i/o and setup overhead. */
182  /* XXX repackaged packages have appended tags, legacy dig/sig check fails */
183  if (opx > 0) {
184  op = (rpmop) pgpStatsAccumulator(dig, opx);
185  (void) rpmswEnter(op, 0);
186  }
187 /*@-type@*/ /* XXX arrow access of non-pointer (FDSTAT_t) */
188  nb = fd->stats->ops[FDSTAT_READ].bytes;
189  { const char item[] = "Header";
190  msg = NULL;
191  rc = rpmpkgRead(item, fd, &h, &msg);
192  if (rc != RPMRC_OK) {
193  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
194  msg = _free(msg);
195  goto exit;
196  }
197  msg = _free(msg);
198  }
199  nb = fd->stats->ops[FDSTAT_READ].bytes - nb;
200 /*@=type@*/
201  if (opx > 0 && op != NULL) {
202  (void) rpmswExit(op, nb);
203  op = NULL;
204  }
205 
206  /* Any digests or signatures to check? */
207  if (she->tag == 0) {
208  rc = RPMRC_OK;
209  goto exit;
210  }
211 
212  dig->nbytes = 0;
213 
214  /* Fish out the autosign pubkey (if present). */
215  he->tag = RPMTAG_PUBKEYS;
216  xx = headerGet(h, he, 0);
217  if (xx && he->p.argv != NULL && he->c > 0)
218  switch (he->t) {
219  default:
220  break;
222  ix = he->c - 1; /* XXX FIXME: assumes last pubkey */
223  dig->pub = _free(dig->pub);
224  dig->publen = 0;
225  { rpmiob iob = rpmiobNew(0);
226  iob = rpmiobAppend(iob, he->p.argv[ix], 0);
227  xx = pgpArmorUnwrap(iob, (rpmuint8_t **)&dig->pub, &dig->publen);
228  iob = rpmiobFree(iob);
229  }
230  if (xx != PGPARMOR_PUBKEY) {
231  dig->pub = _free(dig->pub);
232  dig->publen = 0;
233  }
234  break;
235  }
236  he->p.ptr = _free(he->p.ptr);
237 
238  /* Retrieve the tag parameters from the signature header. */
239  xx = headerGet(sigh, she, 0);
240  if (she->p.ptr == NULL) {
241  rc = RPMRC_FAIL;
242  goto exit;
243  }
244 /*@-ownedtrans -noeffect@*/
245  xx = pgpSetSig(dig, she->tag, she->t, she->p.ptr, she->c);
246 /*@=ownedtrans =noeffect@*/
247 
248  switch ((rpmSigTag)she->tag) {
249  default: /* XXX keep gcc quiet. */
250 assert(0);
251  /*@notreached@*/ break;
252  case RPMSIGTAG_RSA:
253  /* Parse the parameters from the OpenPGP packets that will be needed. */
254  xx = pgpPktLen(she->p.ui8p, she->c, pp);
255  xx = rpmhkpLoadSignature(NULL, dig, pp);
256  if (dig->signature.version != 3 && dig->signature.version != 4) {
258  _("skipping package %s with unverifiable V%u signature\n"),
259  fn, dig->signature.version);
260  rc = RPMRC_FAIL;
261  goto exit;
262  }
263  { void * uh = NULL;
264  rpmTagType uht;
265  rpmTagCount uhc;
266  unsigned char * hmagic = NULL;
267  size_t nmagic = 0;
268 
270  xx = headerGet(h, he, 0);
271  uht = he->t;
272  uh = he->p.ptr;
273  uhc = he->c;
274  if (!xx)
275  break;
276  (void) headerGetMagic(NULL, &hmagic, &nmagic);
277  op = (rpmop) pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */
278  (void) rpmswEnter(op, 0);
279  dig->hdrctx = rpmDigestInit((pgpHashAlgo)dig->signature.hash_algo, RPMDIGEST_NONE);
280  if (hmagic && nmagic > 0) {
281  (void) rpmDigestUpdate(dig->hdrctx, hmagic, nmagic);
282  dig->nbytes += nmagic;
283  }
284  (void) rpmDigestUpdate(dig->hdrctx, uh, uhc);
285  dig->nbytes += uhc;
286  (void) rpmswExit(op, dig->nbytes);
287  op->count--; /* XXX one too many */
288  uh = _free(uh);
289  } break;
290  case RPMSIGTAG_DSA:
291  /* Parse the parameters from the OpenPGP packets that will be needed. */
292  xx = pgpPktLen(she->p.ui8p, she->c, pp);
293  xx = rpmhkpLoadSignature(NULL, dig, pp);
294  if (dig->signature.version != 3 && dig->signature.version != 4) {
296  _("skipping package %s with unverifiable V%u signature\n"),
297  fn, dig->signature.version);
298  rc = RPMRC_FAIL;
299  goto exit;
300  }
301  /*@fallthrough@*/
302  case RPMSIGTAG_SHA1:
303  { void * uh = NULL;
304  rpmTagType uht;
305  rpmTagCount uhc;
306  unsigned char * hmagic = NULL;
307  size_t nmagic = 0;
308 
310  xx = headerGet(h, he, 0);
311  uht = he->t;
312  uh = he->p.ptr;
313  uhc = he->c;
314  if (!xx)
315  break;
316  (void) headerGetMagic(NULL, &hmagic, &nmagic);
317  op = (rpmop) pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */
318  (void) rpmswEnter(op, 0);
319  dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
320  if (hmagic && nmagic > 0) {
321  (void) rpmDigestUpdate(dig->hdrsha1ctx, hmagic, nmagic);
322  dig->nbytes += nmagic;
323  }
324  (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
325  dig->nbytes += uhc;
326  (void) rpmswExit(op, dig->nbytes);
327  if ((rpmSigTag)she->tag == RPMSIGTAG_SHA1)
328  op->count--; /* XXX one too many */
329  uh = _free(uh);
330  } break;
331  case RPMSIGTAG_MD5:
332  /* Legacy signatures need the compressed payload in the digest too. */
333  op = (rpmop) pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */
334  (void) rpmswEnter(op, 0);
335  while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
336  dig->nbytes += count;
337  (void) rpmswExit(op, dig->nbytes);
338  op->count--; /* XXX one too many */
339  dig->nbytes += nb; /* XXX include size of header blob. */
340  if (count < 0) {
341  rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"),
342  fn, Fstrerror(fd));
343  rc = RPMRC_FAIL;
344  goto exit;
345  }
346 
347  /* XXX Steal the digest-in-progress from the file handle. */
348  fdStealDigest(fd, dig);
349  break;
350  }
351 
354  buf[0] = '\0';
355  rc = rpmVerifySignature(dig, buf);
356  switch (rc) {
357  case RPMRC_OK: /* Signature is OK. */
358  rpmlog(RPMLOG_DEBUG, "%s: %s\n", fn, buf);
359  break;
360  case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */
361  case RPMRC_NOKEY: /* Public key is unavailable. */
362 #ifndef DYING
363  /* XXX Print NOKEY/NOTTRUSTED warning only once. */
364  { int lvl = (pgpStashKeyid(dig) ? RPMLOG_DEBUG : RPMLOG_WARNING);
365  rpmlog(lvl, "%s: %s\n", fn, buf);
366  } break;
367  case RPMRC_NOTFOUND: /* Signature is unknown type. */
368  rpmlog(RPMLOG_WARNING, "%s: %s\n", fn, buf);
369  break;
370 #else
371  case RPMRC_NOTFOUND: /* Signature is unknown type. */
372  case RPMRC_NOSIG: /* Signature is unavailable. */
373 #endif
374  default:
375  case RPMRC_FAIL: /* Signature does not verify. */
376  rpmlog(RPMLOG_ERR, "%s: %s\n", fn, buf);
377  break;
378  }
379 
380 exit:
381  if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
382 
383  /* Append (and remap) signature tags to the metadata. */
384  headerMergeLegacySigs(h, sigh);
385 
386  /* Bump reference count for return. */
387  *hdrp = headerLink(h);
388  }
389  (void)headerFree(h);
390  h = NULL;
391 
392  /* Accumulate time reading package header. */
394  fdstat_op(fd, FDSTAT_READ));
396  opsave);
397 
398 #ifdef NOTYET
399  /* Return RPMRC_NOSIG for MANDATORY signature verification. */
400  { rpmSigTag sigtag = pgpGetSigtag(dig);
401  switch (sigtag) {
402  default:
403  rc = RPMRC_NOSIG;
404  /*@fallthrough@*/
405  case RPMSIGTAG_RSA:
406  case RPMSIGTAG_DSA:
407  break;
408  }
409  }
410 #endif
411 
412  rpmtsCleanDig(ts);
413  (void)headerFree(sigh);
414  sigh = NULL;
415  return rc;
416 }
417 /*@=mods@*/
FDSTAT_t stats
static void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int _flags)
Attach digest to fd.
rpmTagType t
Definition: rpmtag.h:502
int xx
Definition: spec.c:744
rpmTag tag
Definition: rpmtag.h:501
rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
Retrieve operation timestamp from a transaction set.
Definition: pkgio.c:133
const void * uh
Definition: rpmts-py.c:977
const char ** argv
Definition: rpmtag.h:75
#define headerFree(_h)
Definition: rpmtag.h:870
rpmlog(RPMLOG_ERR,"%s\n", buf)
rpmuint32_t rpmTagCount
Definition: rpmtag.h:55
rpmtime_t rpmswAdd(rpmop to, rpmop from)
Sum statistic counters.
Definition: rpmsw.c:280
int pgpPktLen(const rpmuint8_t *pkt, size_t pleft, pgpPkt pp)
Definition: rpmpgp.c:939
static char *size_t nb
fgets(3) analogue that reads \ continuations.
Definition: macro.c:409
struct rpmts_s * rpmts
The RPM Transaction Set.
Definition: rpmtypes.h:14
int rc
Definition: poptALL.c:670
The Header data structure.
void headerMergeLegacySigs(Header h, const Header sigh)
Translate and merge legacy signature tags into header.
Definition: hdrNVR.c:242
pgpDig rpmtsDig(rpmts ts)
Get OpenPGP packet parameters, i.e.
Definition: pkgio.c:442
enum rpmTag_e rpmTag
Definition: rpmtag.h:468
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
rpmtime_t rpmswSub(rpmop to, rpmop from)
Subtract statistic counters.
Definition: rpmsw.c:292
rpmiob rpmiobAppend(rpmiob iob, const char *s, size_t nl)
Append string to I/O buffer.
Definition: rpmiob.c:77
Header headerLink(Header h)
Reference a header instance.
Header h
Definition: spec.c:739
struct pgpDig_s * pgpDig
Definition: rpmiotypes.h:86
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:26
struct rpmiob_s * rpmiob
Definition: rpmiotypes.h:60
enum rpmSigTag_e rpmSigTag
Definition: rpmtag.h:472
char * alloca()
enum rpmRC_e rpmRC
RPM return codes.
Definition: signature.c:616
goto exit
Definition: db3.c:1903
memset(_r, 0, sizeof(*_r))
int count
Definition: rpmdb-py.c:157
pgpVSFlags pgpDigVSFlags
Disabler bits(s) for signature/digest checking.
Definition: rpmpgp.c:1104
const char * Fstrerror(FD_t fd)
strerror(3) clone.
Definition: rpmio.c:2399
assert(key->size==sizeof(hdrNum))
void * ptr
Definition: rpmtag.h:67
int count
Definition: rpmsw.h:41
int ix
Definition: rpmps-py.c:174
int headerGetMagic(Header h, unsigned char **magicp, size_t *nmagicp)
Return header magic.
Definition: header.c:1162
int headerIsEntry(Header h, rpmTag tag)
Check if tag is in header.
Definition: header.c:1438
enum rpmTagType_e rpmTagType
Definition: rpmtag.h:47
enum pgpHashAlgo_e pgpHashAlgo
9.4.
enum rpmtsOpX_e rpmtsOpX
Indices for timestamps.
void * pgpStatsAccumulator(pgpDig dig, int opx)
Return pgpDig container accumulator structure.
Definition: rpmpgp.c:1270
rpmTagData p
Definition: rpmtag.h:504
int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len)
Update context with next plain text buffer.
Definition: digest.c:907
void rpmswExit(op, 0)
pgpDigParams pgpGetSignature(pgpDig dig)
Return OpenPGP signature parameters.
Definition: rpmpgp.c:1226
rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char *fn, Header *hdrp)
Return package header from file handle, verifying digests/signatures.
Definition: package.c:83
struct _HE_s * HE_t
Destroy an extension cache.
Definition: rpmtag.h:59
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2230
The FD_t File Handle data structure.
struct pgpPkt_s * pgpPkt
Definition: rpmiotypes.h:82
rpmTagCount c
Definition: rpmtag.h:505
Generate and verify rpm package signatures.
DIGEST_CTX rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
Initialize digest.
Definition: digest.c:244
static void fdSetDig(FD_t fd, pgpDig dig)
size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
fread(3) clone.
Definition: rpmio.c:2410
static unsigned int nextkeyid
Definition: package.c:40
rpmuint8_t * ui8p
Definition: rpmtag.h:68
* op
Definition: rpmps-py.c:266
pgpVSFlags rpmVSFlags
Bit(s) to control digest and signature verification.
Definition: rpmts.h:35
node fd
Definition: rpmfd-py.c:124
Cumulative statistics for an operation.
Definition: rpmsw.h:39
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
Definition: rpmiob.c:44
rpmuint32_t pgpGetSigtag(pgpDig dig)
Get signature tag.
Definition: rpmpgp.c:1236
unsigned int * keyids
Definition: poptALL.c:598
Definition: rpmtag.h:500
Methods to handle package elements.
static void fdStealDigest(FD_t fd, pgpDig dig)
const void * pgpGetSig(pgpDig dig)
Get signature tag data, i.e.
Definition: rpmpgp.c:1246
#define _chk(_mask)
Structures and prototypes used for an &quot;rpmts&quot; transaction set.
const char * msg
Definition: rpmts-py.c:976
struct pgpDigParams_s * pgpDigParams
Definition: rpmiotypes.h:90
return NULL
Definition: poptALL.c:613
static void
Print copy of spec file, filling in Group/Description/Summary from specspo.
Definition: spec.c:737
static unsigned int nkeyids
Definition: package.c:38
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:1256
char * buf
Parse (and execute) macro undefinition.
Definition: macro.c:703
#define _(Text)
Definition: system.h:29
static rpmop fdstat_op(FD_t fd, fdOpX opx)
static unsigned int pgpGrab(const rpmuint8_t *s, size_t nbytes)
Return (native-endian) integer from big-endian representation.
Definition: rpmpgp.h:1076
static int pgpStashKeyid(pgpDig dig)
Remember current key id.
Definition: package.c:47
rpmRC rpmpkgRead(const char *fn, FD_t fd, void *ptr, const char **msg)
Read item from file descriptor.
Definition: pkgio.c:1647
void rpmswEnter(op, 0)
struct rpmop_s * rpmop
Definition: rpmsw.h:24
rpmVSFlags vsflags
Definition: rpmrepo.c:161
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
pgpDigParams sigp
Definition: signature.c:748
int i
Definition: spec.c:743
pgpDig dig
Definition: rpmts-py.c:979
pgpArmor pgpArmorUnwrap(rpmiob iob, rpmuint8_t **pkt, size_t *pktlen)
Parse armored OpenPGP packets from an iob.
Definition: rpmpgp.c:1398
rpmRC rpmVerifySignature(void *_dig, char *result)
Verify a signature from a package.
Definition: signature.c:941
static unsigned int nkeyids_max
Definition: package.c:36
#define xrealloc
Definition: system.h:35
size_t fn
Definition: macro.c:1698
void rpmtsCleanDig(rpmts ts)
Free signature verification data.
Definition: pkgio.c:457