2000-08-28 03:27:03 +08:00
|
|
|
/** \ingroup header
|
|
|
|
* \file lib/package.c
|
|
|
|
*/
|
|
|
|
|
1998-07-26 05:00:26 +08:00
|
|
|
#include "system.h"
|
1997-11-18 11:13:56 +08:00
|
|
|
|
1996-02-15 01:54:37 +08:00
|
|
|
#include <netinet/in.h>
|
1996-01-06 02:12:55 +08:00
|
|
|
|
2008-01-30 19:53:51 +08:00
|
|
|
#include <rpm/rpmlib.h> /* XXX RPMSIGTAG, other sig stuff */
|
2007-12-08 20:02:32 +08:00
|
|
|
#include <rpm/rpmts.h>
|
2008-01-30 23:05:29 +08:00
|
|
|
#include <rpm/rpmlog.h>
|
2008-03-31 18:31:03 +08:00
|
|
|
#include <rpm/rpmstring.h>
|
2001-10-26 12:16:19 +08:00
|
|
|
|
2007-11-27 17:34:23 +08:00
|
|
|
#include "lib/legacy.h" /* XXX legacyRetrofit() */
|
2007-11-23 18:39:29 +08:00
|
|
|
#include "lib/rpmlead.h"
|
|
|
|
#include "lib/signature.h"
|
2008-01-30 23:05:29 +08:00
|
|
|
#include "rpmio/digest.h"
|
|
|
|
#include "rpmio/rpmio_internal.h" /* fd*Digest(), fd stats */
|
2008-05-12 17:28:12 +08:00
|
|
|
#include "lib/header_internal.h" /* XXX headerCheck */
|
2008-01-30 23:05:29 +08:00
|
|
|
|
2000-12-13 04:03:45 +08:00
|
|
|
#include "debug.h"
|
1996-01-06 08:07:50 +08:00
|
|
|
|
2002-03-09 06:24:58 +08:00
|
|
|
static int _print_pkts = 0;
|
|
|
|
|
2008-03-07 14:20:03 +08:00
|
|
|
static const unsigned int nkeyids_max = 256;
|
2002-09-01 06:39:34 +08:00
|
|
|
static unsigned int nkeyids = 0;
|
|
|
|
static unsigned int nextkeyid = 0;
|
|
|
|
static unsigned int * keyids;
|
2002-07-25 00:21:23 +08:00
|
|
|
|
2008-03-07 14:15:03 +08:00
|
|
|
/* XXX FIXME: these are doubled here and header.c and .. */
|
|
|
|
static unsigned char const header_magic[8] = {
|
2002-07-25 00:21:23 +08:00
|
|
|
0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
|
|
|
|
};
|
|
|
|
|
2002-09-04 09:52:26 +08:00
|
|
|
void headerMergeLegacySigs(Header h, const Header sigh)
|
2000-12-03 05:53:44 +08:00
|
|
|
{
|
|
|
|
HeaderIterator hi;
|
2008-05-14 15:20:56 +08:00
|
|
|
struct rpmtd_s td;
|
2000-12-03 05:53:44 +08:00
|
|
|
|
2008-05-14 15:20:56 +08:00
|
|
|
hi = headerInitIterator(sigh);
|
|
|
|
for (; headerNext(hi, &td); rpmtdFreeData(&td))
|
2000-12-03 05:53:44 +08:00
|
|
|
{
|
2008-05-14 15:20:56 +08:00
|
|
|
switch (td.tag) {
|
2002-03-04 07:09:49 +08:00
|
|
|
/* XXX Translate legacy signature tag values. */
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMSIGTAG_SIZE:
|
2008-05-14 15:20:56 +08:00
|
|
|
td.tag = RPMTAG_SIGSIZE;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMSIGTAG_LEMD5_1:
|
2008-05-14 15:20:56 +08:00
|
|
|
td.tag = RPMTAG_SIGLEMD5_1;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMSIGTAG_PGP:
|
2008-05-14 15:20:56 +08:00
|
|
|
td.tag = RPMTAG_SIGPGP;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMSIGTAG_LEMD5_2:
|
2008-05-14 15:20:56 +08:00
|
|
|
td.tag = RPMTAG_SIGLEMD5_2;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMSIGTAG_MD5:
|
2008-05-14 15:20:56 +08:00
|
|
|
td.tag = RPMTAG_SIGMD5;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMSIGTAG_GPG:
|
2008-05-14 15:20:56 +08:00
|
|
|
td.tag = RPMTAG_SIGGPG;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMSIGTAG_PGP5:
|
2008-05-14 15:20:56 +08:00
|
|
|
td.tag = RPMTAG_SIGPGP5;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-03-04 07:09:49 +08:00
|
|
|
case RPMSIGTAG_PAYLOADSIZE:
|
2008-05-14 15:20:56 +08:00
|
|
|
td.tag = RPMTAG_ARCHIVESIZE;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-03-04 07:09:49 +08:00
|
|
|
case RPMSIGTAG_SHA1:
|
|
|
|
case RPMSIGTAG_DSA:
|
2002-03-07 10:17:59 +08:00
|
|
|
case RPMSIGTAG_RSA:
|
2001-03-15 07:09:09 +08:00
|
|
|
default:
|
2008-05-14 15:20:56 +08:00
|
|
|
if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
|
2001-06-12 12:10:21 +08:00
|
|
|
continue;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2000-12-03 05:53:44 +08:00
|
|
|
}
|
2008-05-14 15:20:56 +08:00
|
|
|
if (td.data == NULL) continue; /* XXX can't happen */
|
|
|
|
if (!headerIsEntry(h, td.tag)) {
|
|
|
|
if (hdrchkType(td.type))
|
2002-09-04 09:52:26 +08:00
|
|
|
continue;
|
2008-05-14 15:20:56 +08:00
|
|
|
if (td.count < 0 || hdrchkData(td.count))
|
2002-09-04 09:52:26 +08:00
|
|
|
continue;
|
2008-05-14 15:20:56 +08:00
|
|
|
switch(td.type) {
|
2002-09-04 09:52:26 +08:00
|
|
|
case RPM_NULL_TYPE:
|
|
|
|
continue;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-09-04 09:52:26 +08:00
|
|
|
case RPM_CHAR_TYPE:
|
|
|
|
case RPM_INT8_TYPE:
|
|
|
|
case RPM_INT16_TYPE:
|
|
|
|
case RPM_INT32_TYPE:
|
2008-05-14 15:20:56 +08:00
|
|
|
if (td.count != 1)
|
2002-09-04 09:52:26 +08:00
|
|
|
continue;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-09-04 09:52:26 +08:00
|
|
|
case RPM_STRING_TYPE:
|
|
|
|
case RPM_BIN_TYPE:
|
2008-05-14 15:20:56 +08:00
|
|
|
if (td.count >= 16*1024)
|
2002-09-04 09:52:26 +08:00
|
|
|
continue;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-09-04 09:52:26 +08:00
|
|
|
case RPM_STRING_ARRAY_TYPE:
|
|
|
|
case RPM_I18NSTRING_TYPE:
|
|
|
|
continue;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-09-04 09:52:26 +08:00
|
|
|
}
|
2008-05-14 15:20:56 +08:00
|
|
|
(void) headerPut(h, &td, HEADERPUT_DEFAULT);
|
2002-09-04 09:52:26 +08:00
|
|
|
}
|
2000-12-03 05:53:44 +08:00
|
|
|
}
|
2001-06-20 00:59:23 +08:00
|
|
|
hi = headerFreeIterator(hi);
|
2000-12-03 05:53:44 +08:00
|
|
|
}
|
|
|
|
|
2002-07-26 07:36:32 +08:00
|
|
|
Header headerRegenSigHeader(const Header h, int noArchiveSize)
|
2001-02-12 06:02:29 +08:00
|
|
|
{
|
2002-09-04 09:52:26 +08:00
|
|
|
Header sigh = rpmNewSignature();
|
2001-02-12 06:02:29 +08:00
|
|
|
HeaderIterator hi;
|
2008-05-14 15:29:07 +08:00
|
|
|
struct rpmtd_s td;
|
2001-02-12 06:02:29 +08:00
|
|
|
|
2008-05-14 15:29:07 +08:00
|
|
|
for (hi = headerInitIterator(h); headerNext(hi, &td); rpmtdFreeData(&td)) {
|
|
|
|
switch (td.tag) {
|
2002-03-04 07:09:49 +08:00
|
|
|
/* XXX Translate legacy signature tag values. */
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMTAG_SIGSIZE:
|
2008-05-14 15:29:07 +08:00
|
|
|
td.tag = RPMSIGTAG_SIZE;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMTAG_SIGLEMD5_1:
|
2008-05-14 15:29:07 +08:00
|
|
|
td.tag = RPMSIGTAG_LEMD5_1;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMTAG_SIGPGP:
|
2008-05-14 15:29:07 +08:00
|
|
|
td.tag = RPMSIGTAG_PGP;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMTAG_SIGLEMD5_2:
|
2008-05-14 15:29:07 +08:00
|
|
|
td.tag = RPMSIGTAG_LEMD5_2;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMTAG_SIGMD5:
|
2008-05-14 15:29:07 +08:00
|
|
|
td.tag = RPMSIGTAG_MD5;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMTAG_SIGGPG:
|
2008-05-14 15:29:07 +08:00
|
|
|
td.tag = RPMSIGTAG_GPG;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-14 06:01:38 +08:00
|
|
|
case RPMTAG_SIGPGP5:
|
2008-05-14 15:29:07 +08:00
|
|
|
td.tag = RPMSIGTAG_PGP5;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-03-04 07:09:49 +08:00
|
|
|
case RPMTAG_ARCHIVESIZE:
|
2002-07-26 07:36:32 +08:00
|
|
|
/* XXX rpm-4.1 and later has archive size in signature header. */
|
|
|
|
if (noArchiveSize)
|
|
|
|
continue;
|
2008-05-14 15:29:07 +08:00
|
|
|
td.tag = RPMSIGTAG_PAYLOADSIZE;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-03-04 07:09:49 +08:00
|
|
|
case RPMTAG_SHA1HEADER:
|
|
|
|
case RPMTAG_DSAHEADER:
|
2002-03-07 10:17:59 +08:00
|
|
|
case RPMTAG_RSAHEADER:
|
2001-02-12 06:02:29 +08:00
|
|
|
default:
|
2008-05-14 15:29:07 +08:00
|
|
|
if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
|
2001-06-12 12:10:21 +08:00
|
|
|
continue;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-02-12 06:02:29 +08:00
|
|
|
}
|
2008-05-14 15:29:07 +08:00
|
|
|
if (td.data == NULL) continue; /* XXX can't happen */
|
|
|
|
if (!headerIsEntry(sigh, td.tag))
|
|
|
|
(void) headerPut(sigh, &td, HEADERPUT_DEFAULT);
|
2001-02-12 06:02:29 +08:00
|
|
|
}
|
2001-06-20 00:59:23 +08:00
|
|
|
hi = headerFreeIterator(hi);
|
2002-09-04 09:52:26 +08:00
|
|
|
return sigh;
|
2001-02-12 06:02:29 +08:00
|
|
|
}
|
|
|
|
|
2002-07-01 06:47:32 +08:00
|
|
|
/**
|
|
|
|
* Remember current key id.
|
|
|
|
* @param ts transaction set
|
|
|
|
* @return 0 if new keyid, otherwise 1
|
|
|
|
*/
|
|
|
|
static int rpmtsStashKeyid(rpmts ts)
|
|
|
|
{
|
2002-07-22 06:06:19 +08:00
|
|
|
const void * sig = rpmtsSig(ts);
|
|
|
|
pgpDig dig = rpmtsDig(ts);
|
|
|
|
pgpDigParams sigp = rpmtsSignature(ts);
|
2002-07-01 06:47:32 +08:00
|
|
|
unsigned int keyid;
|
|
|
|
int i;
|
|
|
|
|
2002-07-22 06:06:19 +08:00
|
|
|
if (sig == NULL || dig == NULL || sigp == NULL)
|
2002-07-01 06:47:32 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
keyid = pgpGrab(sigp->signid+4, 4);
|
2002-07-02 21:16:50 +08:00
|
|
|
if (keyid == 0)
|
|
|
|
return 0;
|
2002-07-01 06:47:32 +08:00
|
|
|
|
2002-07-02 21:16:50 +08:00
|
|
|
if (keyids != NULL)
|
2002-07-01 06:47:32 +08:00
|
|
|
for (i = 0; i < nkeyids; i++) {
|
|
|
|
if (keyid == keyids[i])
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-09-01 06:39:34 +08:00
|
|
|
if (nkeyids < nkeyids_max) {
|
|
|
|
nkeyids++;
|
|
|
|
keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
|
|
|
|
}
|
2002-09-17 23:21:03 +08:00
|
|
|
if (keyids) /* XXX can't happen */
|
|
|
|
keyids[nextkeyid] = keyid;
|
2002-09-01 06:39:34 +08:00
|
|
|
nextkeyid++;
|
|
|
|
nextkeyid %= nkeyids_max;
|
2002-07-01 06:47:32 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-07-25 00:21:23 +08:00
|
|
|
/**
|
|
|
|
* Check header consistency, performing headerGetEntry() the hard way.
|
|
|
|
*
|
|
|
|
* Sanity checks on the header are performed while looking for a
|
|
|
|
* header-only digest or signature to verify the blob. If found,
|
|
|
|
* the digest or signature is verified.
|
|
|
|
*
|
|
|
|
* @param ts transaction set
|
|
|
|
* @param uh unloaded header blob
|
|
|
|
* @param uc no. of bytes in blob (or 0 to disable)
|
|
|
|
* @retval *msg signature verification msg
|
|
|
|
* @return RPMRC_OK/RPMRC_NOTFOUND/RPMRC_FAIL
|
|
|
|
*/
|
2007-12-16 19:02:27 +08:00
|
|
|
rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, char ** msg)
|
2002-07-25 00:21:23 +08:00
|
|
|
{
|
|
|
|
pgpDig dig;
|
2008-04-03 13:07:00 +08:00
|
|
|
char *buf = NULL;
|
2007-10-26 19:24:14 +08:00
|
|
|
int32_t * ei = (int32_t *) uh;
|
|
|
|
int32_t il = ntohl(ei[0]);
|
|
|
|
int32_t dl = ntohl(ei[1]);
|
2002-07-25 00:21:23 +08:00
|
|
|
entryInfo pe = (entryInfo) &ei[2];
|
2007-10-26 19:24:14 +08:00
|
|
|
int32_t ildl[2];
|
|
|
|
int32_t pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
|
2002-09-04 09:52:26 +08:00
|
|
|
unsigned char * dataStart = (unsigned char *) (pe + il);
|
2008-04-26 19:41:58 +08:00
|
|
|
struct indexEntry_s entry;
|
|
|
|
struct entryInfo_s info;
|
2007-12-16 03:17:59 +08:00
|
|
|
void * sig = NULL;
|
2007-07-11 18:10:47 +08:00
|
|
|
unsigned const char * b;
|
2002-08-06 09:41:44 +08:00
|
|
|
rpmVSFlags vsflags = rpmtsVSFlags(ts);
|
2007-12-14 03:18:37 +08:00
|
|
|
size_t siglen = 0;
|
|
|
|
size_t blen;
|
2002-07-25 00:21:23 +08:00
|
|
|
size_t nb;
|
2007-10-26 19:24:14 +08:00
|
|
|
int32_t ril = 0;
|
2002-09-17 04:10:20 +08:00
|
|
|
unsigned char * regionEnd = NULL;
|
2002-07-25 00:21:23 +08:00
|
|
|
rpmRC rc = RPMRC_FAIL; /* assume failure */
|
|
|
|
int xx;
|
|
|
|
int i;
|
2004-08-20 01:00:15 +08:00
|
|
|
static int hclvl;
|
2002-07-25 00:21:23 +08:00
|
|
|
|
2004-08-20 01:00:15 +08:00
|
|
|
hclvl++;
|
2002-08-22 08:37:21 +08:00
|
|
|
|
2002-07-25 00:21:23 +08:00
|
|
|
/* Is the blob the right size? */
|
2002-08-22 08:37:21 +08:00
|
|
|
if (uc > 0 && pvlen != uc) {
|
2008-04-03 13:07:00 +08:00
|
|
|
rasprintf(&buf, _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
|
2002-10-10 03:07:43 +08:00
|
|
|
(int)uc, (int)il, (int)dl);
|
2002-07-25 00:21:23 +08:00
|
|
|
goto exit;
|
2002-08-22 08:37:21 +08:00
|
|
|
}
|
2002-07-25 00:21:23 +08:00
|
|
|
|
2008-04-26 19:41:58 +08:00
|
|
|
memset(&entry, 0, sizeof(entry));
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
|
2002-07-25 00:21:23 +08:00
|
|
|
/* Check (and convert) the 1st tag element. */
|
2008-04-26 19:41:58 +08:00
|
|
|
xx = headerVerifyInfo(1, dl, pe, &entry.info, 0);
|
2002-08-22 08:37:21 +08:00
|
|
|
if (xx != -1) {
|
2008-04-03 13:07:00 +08:00
|
|
|
rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
|
2008-04-26 19:41:58 +08:00
|
|
|
0, entry.info.tag, entry.info.type,
|
|
|
|
entry.info.offset, entry.info.count);
|
2002-07-25 00:21:23 +08:00
|
|
|
goto exit;
|
2002-08-22 08:37:21 +08:00
|
|
|
}
|
2002-07-25 00:21:23 +08:00
|
|
|
|
|
|
|
/* Is there an immutable header region tag? */
|
2008-04-26 19:41:58 +08:00
|
|
|
if (!(entry.info.tag == RPMTAG_HEADERIMMUTABLE
|
|
|
|
&& entry.info.type == RPM_BIN_TYPE
|
|
|
|
&& entry.info.count == REGION_TAG_COUNT))
|
2002-07-25 00:21:23 +08:00
|
|
|
{
|
|
|
|
rc = RPMRC_NOTFOUND;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2002-09-17 04:10:20 +08:00
|
|
|
/* Is the offset within the data area? */
|
2008-04-26 19:41:58 +08:00
|
|
|
if (entry.info.offset >= dl) {
|
2008-04-03 13:07:00 +08:00
|
|
|
rasprintf(&buf,
|
2002-09-17 04:10:20 +08:00
|
|
|
_("region offset: BAD, tag %d type %d offset %d count %d\n"),
|
2008-04-26 19:41:58 +08:00
|
|
|
entry.info.tag, entry.info.type,
|
|
|
|
entry.info.offset, entry.info.count);
|
2002-09-17 04:10:20 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2002-07-25 00:21:23 +08:00
|
|
|
/* Is there an immutable header region tag trailer? */
|
2008-04-26 19:41:58 +08:00
|
|
|
regionEnd = dataStart + entry.info.offset;
|
|
|
|
(void) memcpy(&info, regionEnd, REGION_TAG_COUNT);
|
2002-09-17 04:10:20 +08:00
|
|
|
regionEnd += REGION_TAG_COUNT;
|
2002-07-25 00:21:23 +08:00
|
|
|
|
2008-04-26 19:41:58 +08:00
|
|
|
xx = headerVerifyInfo(1, dl, &info, &entry.info, 1);
|
2002-08-22 08:37:21 +08:00
|
|
|
if (xx != -1 ||
|
2008-04-26 19:41:58 +08:00
|
|
|
!(entry.info.tag == RPMTAG_HEADERIMMUTABLE
|
|
|
|
&& entry.info.type == RPM_BIN_TYPE
|
|
|
|
&& entry.info.count == REGION_TAG_COUNT))
|
2002-08-22 08:37:21 +08:00
|
|
|
{
|
2008-04-03 13:07:00 +08:00
|
|
|
rasprintf(&buf,
|
2002-08-22 08:37:21 +08:00
|
|
|
_("region trailer: BAD, tag %d type %d offset %d count %d\n"),
|
2008-04-26 19:41:58 +08:00
|
|
|
entry.info.tag, entry.info.type,
|
|
|
|
entry.info.offset, entry.info.count);
|
2002-07-25 00:21:23 +08:00
|
|
|
goto exit;
|
2002-08-22 08:37:21 +08:00
|
|
|
}
|
2008-04-26 19:41:58 +08:00
|
|
|
memset(&info, 0, sizeof(info));
|
2002-07-25 00:21:23 +08:00
|
|
|
|
|
|
|
/* Is the no. of tags in the region less than the total no. of tags? */
|
2008-04-26 19:41:58 +08:00
|
|
|
ril = entry.info.offset/sizeof(*pe);
|
|
|
|
if ((entry.info.offset % sizeof(*pe)) || ril > il) {
|
2008-04-03 13:07:00 +08:00
|
|
|
rasprintf(&buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
|
2002-07-25 00:21:23 +08:00
|
|
|
goto exit;
|
2002-08-22 08:37:21 +08:00
|
|
|
}
|
2002-07-25 00:21:23 +08:00
|
|
|
|
|
|
|
/* Find a header-only digest/signature tag. */
|
|
|
|
for (i = ril; i < il; i++) {
|
2008-04-26 19:41:58 +08:00
|
|
|
xx = headerVerifyInfo(1, dl, pe+i, &entry.info, 0);
|
2002-08-22 08:37:21 +08:00
|
|
|
if (xx != -1) {
|
2008-04-03 13:07:00 +08:00
|
|
|
rasprintf(&buf,
|
2002-09-17 04:10:20 +08:00
|
|
|
_("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
|
2008-04-26 19:41:58 +08:00
|
|
|
i, entry.info.tag, entry.info.type,
|
|
|
|
entry.info.offset, entry.info.count);
|
2002-07-25 00:21:23 +08:00
|
|
|
goto exit;
|
2002-08-22 08:37:21 +08:00
|
|
|
}
|
2002-07-25 00:21:23 +08:00
|
|
|
|
2008-04-26 19:41:58 +08:00
|
|
|
switch (entry.info.tag) {
|
2002-07-25 00:21:23 +08:00
|
|
|
case RPMTAG_SHA1HEADER:
|
2002-08-06 09:41:44 +08:00
|
|
|
if (vsflags & RPMVSF_NOSHA1HEADER)
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-07-25 00:21:23 +08:00
|
|
|
blen = 0;
|
2008-04-26 19:41:58 +08:00
|
|
|
for (b = dataStart + entry.info.offset; *b != '\0'; b++) {
|
2002-07-25 00:21:23 +08:00
|
|
|
if (strchr("0123456789abcdefABCDEF", *b) == NULL)
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-07-25 00:21:23 +08:00
|
|
|
blen++;
|
|
|
|
}
|
2008-04-26 19:41:58 +08:00
|
|
|
if (entry.info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
|
2002-09-17 04:10:20 +08:00
|
|
|
{
|
2008-04-03 13:07:00 +08:00
|
|
|
rasprintf(&buf, _("hdr SHA1: BAD, not hex\n"));
|
2002-07-25 00:21:23 +08:00
|
|
|
goto exit;
|
2002-09-17 04:10:20 +08:00
|
|
|
}
|
2008-04-26 19:41:58 +08:00
|
|
|
if (info.tag == 0) {
|
|
|
|
info = entry.info; /* structure assignment */
|
2002-07-25 00:21:23 +08:00
|
|
|
siglen = blen + 1;
|
|
|
|
}
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-07-25 00:21:23 +08:00
|
|
|
case RPMTAG_RSAHEADER:
|
2005-03-12 23:16:42 +08:00
|
|
|
if (vsflags & RPMVSF_NORSAHEADER)
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2008-04-26 19:41:58 +08:00
|
|
|
if (entry.info.type != RPM_BIN_TYPE) {
|
2008-04-03 13:07:00 +08:00
|
|
|
rasprintf(&buf, _("hdr RSA: BAD, not binary\n"));
|
2005-03-12 23:16:42 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
2008-04-26 19:41:58 +08:00
|
|
|
info = entry.info; /* structure assignment */
|
|
|
|
siglen = info.count;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-07-25 00:21:23 +08:00
|
|
|
case RPMTAG_DSAHEADER:
|
2002-08-06 09:41:44 +08:00
|
|
|
if (vsflags & RPMVSF_NODSAHEADER)
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2008-04-26 19:41:58 +08:00
|
|
|
if (entry.info.type != RPM_BIN_TYPE) {
|
2008-04-03 13:07:00 +08:00
|
|
|
rasprintf(&buf, _("hdr DSA: BAD, not binary\n"));
|
2002-07-25 00:21:23 +08:00
|
|
|
goto exit;
|
2002-09-17 04:10:20 +08:00
|
|
|
}
|
2008-04-26 19:41:58 +08:00
|
|
|
info = entry.info; /* structure assignment */
|
|
|
|
siglen = info.count;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-07-25 00:21:23 +08:00
|
|
|
default:
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-07-25 00:21:23 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
rc = RPMRC_NOTFOUND;
|
|
|
|
|
|
|
|
exit:
|
|
|
|
/* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
|
2002-08-22 08:37:21 +08:00
|
|
|
if (rc != RPMRC_NOTFOUND) {
|
2008-04-03 13:07:00 +08:00
|
|
|
if (msg)
|
|
|
|
*msg = buf;
|
|
|
|
else
|
|
|
|
free(buf);
|
2004-08-20 01:00:15 +08:00
|
|
|
hclvl--;
|
2002-07-25 00:21:23 +08:00
|
|
|
return rc;
|
2002-08-22 08:37:21 +08:00
|
|
|
}
|
2002-07-25 00:21:23 +08:00
|
|
|
|
|
|
|
/* If no header-only digest/signature, then do simple sanity check. */
|
2008-04-26 19:41:58 +08:00
|
|
|
if (info.tag == 0) {
|
2002-07-25 00:21:23 +08:00
|
|
|
verifyinfo_exit:
|
2008-04-26 19:41:58 +08:00
|
|
|
xx = headerVerifyInfo(ril-1, dl, pe+1, &entry.info, 0);
|
2002-08-22 08:37:21 +08:00
|
|
|
if (xx != -1) {
|
2008-04-03 13:07:00 +08:00
|
|
|
rasprintf(&buf,
|
2002-09-17 04:10:20 +08:00
|
|
|
_("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
|
2008-04-26 19:41:58 +08:00
|
|
|
xx+1, entry.info.tag, entry.info.type,
|
|
|
|
entry.info.offset, entry.info.count);
|
2002-07-25 00:21:23 +08:00
|
|
|
rc = RPMRC_FAIL;
|
2002-08-22 08:37:21 +08:00
|
|
|
} else {
|
2008-04-03 13:07:00 +08:00
|
|
|
rasprintf(&buf, "Header sanity check: OK\n");
|
2002-07-25 00:21:23 +08:00
|
|
|
rc = RPMRC_OK;
|
2002-08-22 08:37:21 +08:00
|
|
|
}
|
2008-04-03 13:07:00 +08:00
|
|
|
if (msg)
|
|
|
|
*msg = buf;
|
|
|
|
else
|
|
|
|
free(buf);
|
2004-08-20 01:00:15 +08:00
|
|
|
hclvl--;
|
2002-07-25 00:21:23 +08:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Verify header-only digest/signature. */
|
|
|
|
dig = rpmtsDig(ts);
|
|
|
|
if (dig == NULL)
|
|
|
|
goto verifyinfo_exit;
|
|
|
|
dig->nbytes = 0;
|
|
|
|
|
2008-04-26 19:41:58 +08:00
|
|
|
sig = memcpy(xmalloc(siglen), dataStart + info.offset, siglen);
|
|
|
|
(void) rpmtsSetSig(ts, info.tag, info.type, sig, (size_t) info.count);
|
2002-07-25 00:21:23 +08:00
|
|
|
|
2008-04-26 19:41:58 +08:00
|
|
|
switch (info.tag) {
|
2002-07-25 00:21:23 +08:00
|
|
|
case RPMTAG_RSAHEADER:
|
|
|
|
/* Parse the parameters from the OpenPGP packets that will be needed. */
|
2008-04-26 19:41:58 +08:00
|
|
|
xx = pgpPrtPkts(sig, info.count, dig, (_print_pkts & rpmIsDebug()));
|
2005-02-03 02:47:42 +08:00
|
|
|
if (dig->signature.version != 3 && dig->signature.version != 4) {
|
2007-10-09 19:49:02 +08:00
|
|
|
rpmlog(RPMLOG_ERR,
|
2007-06-12 16:22:49 +08:00
|
|
|
_("skipping header with unverifiable V%u signature\n"),
|
2002-07-25 00:21:23 +08:00
|
|
|
dig->signature.version);
|
|
|
|
rpmtsCleanDig(ts);
|
2007-06-12 16:22:49 +08:00
|
|
|
rc = RPMRC_FAIL;
|
|
|
|
goto exit;
|
2002-07-25 00:21:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ildl[0] = htonl(ril);
|
2002-09-17 04:10:20 +08:00
|
|
|
ildl[1] = (regionEnd - dataStart);
|
2002-07-25 00:21:23 +08:00
|
|
|
ildl[1] = htonl(ildl[1]);
|
|
|
|
|
2003-04-09 05:42:55 +08:00
|
|
|
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
|
2005-03-13 09:39:19 +08:00
|
|
|
dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
|
2002-07-25 00:21:23 +08:00
|
|
|
|
|
|
|
b = (unsigned char *) header_magic;
|
|
|
|
nb = sizeof(header_magic);
|
|
|
|
(void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
|
|
|
|
dig->nbytes += nb;
|
|
|
|
|
|
|
|
b = (unsigned char *) ildl;
|
|
|
|
nb = sizeof(ildl);
|
|
|
|
(void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
|
|
|
|
dig->nbytes += nb;
|
|
|
|
|
|
|
|
b = (unsigned char *) pe;
|
|
|
|
nb = (htonl(ildl[0]) * sizeof(*pe));
|
|
|
|
(void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
|
|
|
|
dig->nbytes += nb;
|
|
|
|
|
|
|
|
b = (unsigned char *) dataStart;
|
|
|
|
nb = htonl(ildl[1]);
|
|
|
|
(void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
|
|
|
|
dig->nbytes += nb;
|
2003-04-09 05:42:55 +08:00
|
|
|
(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
|
2002-07-25 00:21:23 +08:00
|
|
|
|
|
|
|
break;
|
|
|
|
case RPMTAG_DSAHEADER:
|
|
|
|
/* Parse the parameters from the OpenPGP packets that will be needed. */
|
2008-04-26 19:41:58 +08:00
|
|
|
xx = pgpPrtPkts(sig, info.count, dig, (_print_pkts & rpmIsDebug()));
|
2005-02-03 02:47:42 +08:00
|
|
|
if (dig->signature.version != 3 && dig->signature.version != 4) {
|
2007-10-09 19:49:02 +08:00
|
|
|
rpmlog(RPMLOG_ERR,
|
2007-06-12 16:22:49 +08:00
|
|
|
_("skipping header with unverifiable V%u signature\n"),
|
2002-07-25 00:21:23 +08:00
|
|
|
dig->signature.version);
|
|
|
|
rpmtsCleanDig(ts);
|
2007-06-12 16:22:49 +08:00
|
|
|
rc = RPMRC_FAIL;
|
|
|
|
goto exit;
|
2002-07-25 00:21:23 +08:00
|
|
|
}
|
|
|
|
case RPMTAG_SHA1HEADER:
|
|
|
|
ildl[0] = htonl(ril);
|
2002-09-17 04:10:20 +08:00
|
|
|
ildl[1] = (regionEnd - dataStart);
|
2002-07-25 00:21:23 +08:00
|
|
|
ildl[1] = htonl(ildl[1]);
|
|
|
|
|
2003-04-09 05:42:55 +08:00
|
|
|
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
|
2002-07-25 00:21:23 +08:00
|
|
|
dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
|
|
|
|
|
|
|
|
b = (unsigned char *) header_magic;
|
|
|
|
nb = sizeof(header_magic);
|
|
|
|
(void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
|
|
|
|
dig->nbytes += nb;
|
|
|
|
|
|
|
|
b = (unsigned char *) ildl;
|
|
|
|
nb = sizeof(ildl);
|
|
|
|
(void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
|
|
|
|
dig->nbytes += nb;
|
|
|
|
|
|
|
|
b = (unsigned char *) pe;
|
|
|
|
nb = (htonl(ildl[0]) * sizeof(*pe));
|
|
|
|
(void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
|
|
|
|
dig->nbytes += nb;
|
|
|
|
|
|
|
|
b = (unsigned char *) dataStart;
|
|
|
|
nb = htonl(ildl[1]);
|
|
|
|
(void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
|
|
|
|
dig->nbytes += nb;
|
2003-04-09 05:42:55 +08:00
|
|
|
(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
|
2002-07-25 00:21:23 +08:00
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
2003-03-07 06:50:04 +08:00
|
|
|
sig = _free(sig);
|
2002-07-25 00:21:23 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-04-03 13:07:00 +08:00
|
|
|
rc = rpmVerifySignature(ts, &buf);
|
2002-07-25 00:21:23 +08:00
|
|
|
|
2008-04-03 13:07:00 +08:00
|
|
|
if (msg)
|
|
|
|
*msg = buf;
|
|
|
|
else
|
|
|
|
free(buf);
|
2002-07-25 00:21:23 +08:00
|
|
|
|
2004-08-20 01:00:15 +08:00
|
|
|
/* XXX headerCheck can recurse, free info only at top level. */
|
|
|
|
if (hclvl == 1)
|
2004-10-10 03:40:09 +08:00
|
|
|
rpmtsCleanDig(ts);
|
2008-04-26 19:41:58 +08:00
|
|
|
if (info.tag == RPMTAG_SHA1HEADER)
|
2003-03-07 06:50:04 +08:00
|
|
|
sig = _free(sig);
|
2004-08-20 01:00:15 +08:00
|
|
|
hclvl--;
|
2002-07-25 00:21:23 +08:00
|
|
|
return rc;
|
|
|
|
}
|
2002-03-07 07:17:31 +08:00
|
|
|
|
2007-12-16 19:02:27 +08:00
|
|
|
rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, char ** msg)
|
2002-09-01 06:39:34 +08:00
|
|
|
{
|
2008-03-31 18:31:03 +08:00
|
|
|
char *buf = NULL;
|
2007-10-26 19:24:14 +08:00
|
|
|
int32_t block[4];
|
|
|
|
int32_t il;
|
|
|
|
int32_t dl;
|
|
|
|
int32_t * ei = NULL;
|
2002-09-01 06:39:34 +08:00
|
|
|
size_t uc;
|
2008-01-02 19:55:16 +08:00
|
|
|
size_t nb;
|
2002-09-01 06:39:34 +08:00
|
|
|
Header h = NULL;
|
|
|
|
rpmRC rc = RPMRC_FAIL; /* assume failure */
|
2002-09-17 04:10:20 +08:00
|
|
|
int xx;
|
|
|
|
|
2002-09-01 06:39:34 +08:00
|
|
|
if (hdrp)
|
|
|
|
*hdrp = NULL;
|
2002-09-17 04:10:20 +08:00
|
|
|
if (msg)
|
|
|
|
*msg = NULL;
|
2002-09-01 06:39:34 +08:00
|
|
|
|
2002-09-17 23:21:03 +08:00
|
|
|
memset(block, 0, sizeof(block));
|
2002-09-17 04:10:20 +08:00
|
|
|
if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
|
2008-03-31 18:31:03 +08:00
|
|
|
rasprintf(&buf,
|
2002-10-10 03:07:43 +08:00
|
|
|
_("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
|
2002-09-01 06:39:34 +08:00
|
|
|
goto exit;
|
2002-09-17 04:10:20 +08:00
|
|
|
}
|
|
|
|
if (memcmp(block, header_magic, sizeof(header_magic))) {
|
2008-03-31 18:31:03 +08:00
|
|
|
rasprintf(&buf, _("hdr magic: BAD\n"));
|
2002-09-01 06:39:34 +08:00
|
|
|
goto exit;
|
2002-09-17 04:10:20 +08:00
|
|
|
}
|
2002-09-01 06:39:34 +08:00
|
|
|
il = ntohl(block[2]);
|
2002-09-17 04:10:20 +08:00
|
|
|
if (hdrchkTags(il)) {
|
2008-03-31 18:31:03 +08:00
|
|
|
rasprintf(&buf, _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
|
2002-09-01 06:39:34 +08:00
|
|
|
goto exit;
|
2002-09-17 04:10:20 +08:00
|
|
|
}
|
2002-09-01 06:39:34 +08:00
|
|
|
dl = ntohl(block[3]);
|
2002-09-17 04:10:20 +08:00
|
|
|
if (hdrchkData(dl)) {
|
2008-03-31 18:31:03 +08:00
|
|
|
rasprintf(&buf,
|
|
|
|
_("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
|
2002-09-01 06:39:34 +08:00
|
|
|
goto exit;
|
2002-09-17 04:10:20 +08:00
|
|
|
}
|
2002-09-01 06:39:34 +08:00
|
|
|
|
|
|
|
nb = (il * sizeof(struct entryInfo_s)) + dl;
|
|
|
|
uc = sizeof(il) + sizeof(dl) + nb;
|
|
|
|
ei = xmalloc(uc);
|
|
|
|
ei[0] = block[2];
|
|
|
|
ei[1] = block[3];
|
2002-09-17 04:10:20 +08:00
|
|
|
if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
|
2008-03-31 18:31:03 +08:00
|
|
|
rasprintf(&buf, _("hdr blob(%zd): BAD, read returned %d\n"), nb, xx);
|
2002-09-01 06:39:34 +08:00
|
|
|
goto exit;
|
2002-09-17 04:10:20 +08:00
|
|
|
}
|
2002-09-01 06:39:34 +08:00
|
|
|
|
|
|
|
/* Sanity check header tags */
|
|
|
|
rc = headerCheck(ts, ei, uc, msg);
|
|
|
|
if (rc != RPMRC_OK)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
/* OK, blob looks sane, load the header. */
|
|
|
|
h = headerLoad(ei);
|
2002-09-17 04:10:20 +08:00
|
|
|
if (h == NULL) {
|
2008-03-31 18:31:03 +08:00
|
|
|
rasprintf(&buf, _("hdr load: BAD\n"));
|
2002-09-01 06:39:34 +08:00
|
|
|
goto exit;
|
2002-09-17 04:10:20 +08:00
|
|
|
}
|
2002-09-01 06:39:34 +08:00
|
|
|
h->flags |= HEADERFLAG_ALLOCATED;
|
|
|
|
ei = NULL; /* XXX will be freed with header */
|
|
|
|
|
|
|
|
exit:
|
2002-09-17 23:21:03 +08:00
|
|
|
if (hdrp && h && rc == RPMRC_OK)
|
2002-09-01 06:39:34 +08:00
|
|
|
*hdrp = headerLink(h);
|
|
|
|
ei = _free(ei);
|
|
|
|
h = headerFree(h);
|
2002-09-17 04:10:20 +08:00
|
|
|
|
2008-03-31 18:31:03 +08:00
|
|
|
if (msg != NULL && *msg == NULL && buf != NULL) {
|
|
|
|
*msg = buf;
|
|
|
|
} else {
|
|
|
|
free(buf);
|
2002-09-17 04:10:20 +08:00
|
|
|
}
|
|
|
|
|
2002-09-01 06:39:34 +08:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2003-04-17 01:48:04 +08:00
|
|
|
rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
|
1999-07-14 07:33:02 +08:00
|
|
|
{
|
2002-07-22 06:06:19 +08:00
|
|
|
pgpDig dig;
|
2007-07-11 18:10:47 +08:00
|
|
|
char buf[8*BUFSIZ];
|
2001-10-26 12:16:19 +08:00
|
|
|
ssize_t count;
|
2007-12-02 00:31:09 +08:00
|
|
|
rpmlead l = NULL;
|
2002-07-25 02:52:22 +08:00
|
|
|
Header sigh = NULL;
|
2008-02-05 23:42:19 +08:00
|
|
|
rpmSigTag sigtag;
|
2008-02-05 22:14:34 +08:00
|
|
|
rpmTagType sigtype;
|
2007-12-19 18:05:56 +08:00
|
|
|
rpm_data_t sig;
|
2007-12-13 15:25:10 +08:00
|
|
|
rpm_count_t siglen;
|
2004-10-15 08:14:29 +08:00
|
|
|
rpmtsOpX opx;
|
|
|
|
size_t nb;
|
2001-10-26 12:16:19 +08:00
|
|
|
Header h = NULL;
|
2007-12-16 19:02:27 +08:00
|
|
|
char * msg;
|
2002-08-06 09:41:44 +08:00
|
|
|
rpmVSFlags vsflags;
|
2001-10-26 12:16:19 +08:00
|
|
|
rpmRC rc = RPMRC_FAIL; /* assume failure */
|
|
|
|
int xx;
|
1999-07-09 06:10:33 +08:00
|
|
|
|
2002-08-28 04:50:21 +08:00
|
|
|
if (hdrp) *hdrp = NULL;
|
2003-04-17 01:48:04 +08:00
|
|
|
|
2007-12-02 00:31:09 +08:00
|
|
|
l = rpmLeadNew();
|
2001-10-26 12:16:19 +08:00
|
|
|
|
2007-12-02 00:31:09 +08:00
|
|
|
if ((rc = rpmLeadRead(fd, l)) == RPMRC_OK) {
|
2008-03-31 17:07:37 +08:00
|
|
|
const char * err = NULL;
|
|
|
|
if ((rc = rpmLeadCheck(l, &err)) == RPMRC_FAIL) {
|
|
|
|
rpmlog(RPMLOG_ERR, "%s: %s\n", fn, err);
|
|
|
|
}
|
2001-10-26 12:16:19 +08:00
|
|
|
}
|
2007-12-02 00:31:09 +08:00
|
|
|
l = rpmLeadFree(l);
|
|
|
|
|
|
|
|
if (rc != RPMRC_OK)
|
|
|
|
goto exit;
|
2001-10-26 12:16:19 +08:00
|
|
|
|
2002-03-04 07:09:49 +08:00
|
|
|
/* Read the signature header. */
|
2002-09-17 04:10:20 +08:00
|
|
|
msg = NULL;
|
2007-12-02 00:31:09 +08:00
|
|
|
rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg);
|
2002-08-24 05:01:59 +08:00
|
|
|
switch (rc) {
|
|
|
|
default:
|
2007-11-19 22:25:24 +08:00
|
|
|
rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), fn,
|
2002-09-17 04:10:20 +08:00
|
|
|
(msg && *msg ? msg : "\n"));
|
|
|
|
msg = _free(msg);
|
2001-10-26 12:16:19 +08:00
|
|
|
goto exit;
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-08-24 05:01:59 +08:00
|
|
|
case RPMRC_OK:
|
|
|
|
if (sigh == NULL) {
|
2007-11-19 22:25:24 +08:00
|
|
|
rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
|
2002-08-24 05:01:59 +08:00
|
|
|
rc = RPMRC_FAIL;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
break;
|
2001-10-26 12:16:19 +08:00
|
|
|
}
|
2002-09-17 04:10:20 +08:00
|
|
|
msg = _free(msg);
|
2001-10-26 12:16:19 +08:00
|
|
|
|
2002-08-06 09:41:44 +08:00
|
|
|
#define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask)))
|
|
|
|
|
2004-10-15 08:14:29 +08:00
|
|
|
/*
|
|
|
|
* Figger the most effective available signature.
|
|
|
|
* Prefer signatures over digests, then header-only over header+payload.
|
|
|
|
* DSA will be preferred over RSA if both exist because tested first.
|
|
|
|
* Note that NEEDPAYLOAD prevents header+payload signatures and digests.
|
|
|
|
*/
|
2002-07-22 06:06:19 +08:00
|
|
|
sigtag = 0;
|
2004-10-15 08:14:29 +08:00
|
|
|
opx = 0;
|
2002-08-06 09:41:44 +08:00
|
|
|
vsflags = rpmtsVSFlags(ts);
|
2004-10-15 08:14:29 +08:00
|
|
|
if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA)) {
|
2002-08-06 09:41:44 +08:00
|
|
|
sigtag = RPMSIGTAG_DSA;
|
2004-10-15 08:14:29 +08:00
|
|
|
} else
|
|
|
|
if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA)) {
|
2002-08-06 09:41:44 +08:00
|
|
|
sigtag = RPMSIGTAG_RSA;
|
2004-10-15 08:14:29 +08:00
|
|
|
} else
|
2002-08-06 09:41:44 +08:00
|
|
|
if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
|
|
|
|
headerIsEntry(sigh, RPMSIGTAG_GPG))
|
|
|
|
{
|
|
|
|
sigtag = RPMSIGTAG_GPG;
|
|
|
|
fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
|
2004-10-15 08:14:29 +08:00
|
|
|
opx = RPMTS_OP_SIGNATURE;
|
|
|
|
} else
|
2002-08-06 09:41:44 +08:00
|
|
|
if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
|
|
|
|
headerIsEntry(sigh, RPMSIGTAG_PGP))
|
|
|
|
{
|
|
|
|
sigtag = RPMSIGTAG_PGP;
|
|
|
|
fdInitDigest(fd, PGPHASHALGO_MD5, 0);
|
2004-10-15 08:14:29 +08:00
|
|
|
opx = RPMTS_OP_SIGNATURE;
|
|
|
|
} else
|
|
|
|
if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1)) {
|
2002-08-06 09:41:44 +08:00
|
|
|
sigtag = RPMSIGTAG_SHA1;
|
2004-10-15 08:14:29 +08:00
|
|
|
} else
|
2002-08-06 09:41:44 +08:00
|
|
|
if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
|
|
|
|
headerIsEntry(sigh, RPMSIGTAG_MD5))
|
|
|
|
{
|
|
|
|
sigtag = RPMSIGTAG_MD5;
|
|
|
|
fdInitDigest(fd, PGPHASHALGO_MD5, 0);
|
2004-10-15 08:14:29 +08:00
|
|
|
opx = RPMTS_OP_DIGEST;
|
2002-03-09 06:24:58 +08:00
|
|
|
}
|
|
|
|
|
2002-03-04 07:09:49 +08:00
|
|
|
/* Read the metadata, computing digest(s) on the fly. */
|
2002-09-01 06:39:34 +08:00
|
|
|
h = NULL;
|
|
|
|
msg = NULL;
|
2004-10-15 08:14:29 +08:00
|
|
|
|
|
|
|
/* XXX stats will include header i/o and setup overhead. */
|
|
|
|
/* XXX repackaged packages have appended tags, legacy dig/sig check fails */
|
|
|
|
if (opx > 0)
|
|
|
|
(void) rpmswEnter(rpmtsOp(ts, opx), 0);
|
|
|
|
nb = -fd->stats->ops[FDSTAT_READ].bytes;
|
2002-09-01 06:39:34 +08:00
|
|
|
rc = rpmReadHeader(ts, fd, &h, &msg);
|
2004-10-15 08:14:29 +08:00
|
|
|
nb += fd->stats->ops[FDSTAT_READ].bytes;
|
|
|
|
if (opx > 0)
|
|
|
|
(void) rpmswExit(rpmtsOp(ts, opx), nb);
|
|
|
|
|
2002-09-01 06:39:34 +08:00
|
|
|
if (rc != RPMRC_OK || h == NULL) {
|
2007-11-19 22:25:24 +08:00
|
|
|
rpmlog(RPMLOG_ERR, _("%s: headerRead failed: %s"), fn,
|
2002-09-04 09:52:26 +08:00
|
|
|
(msg && *msg ? msg : "\n"));
|
2002-09-01 06:39:34 +08:00
|
|
|
msg = _free(msg);
|
2001-10-26 12:16:19 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
2002-09-01 06:39:34 +08:00
|
|
|
msg = _free(msg);
|
2001-10-26 12:16:19 +08:00
|
|
|
|
2004-10-15 08:14:29 +08:00
|
|
|
/* Any digests or signatures to check? */
|
2002-07-22 06:06:19 +08:00
|
|
|
if (sigtag == 0) {
|
2001-10-26 12:16:19 +08:00
|
|
|
rc = RPMRC_OK;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2002-07-22 06:06:19 +08:00
|
|
|
dig = rpmtsDig(ts);
|
|
|
|
if (dig == NULL) {
|
2002-05-14 06:34:25 +08:00
|
|
|
rc = RPMRC_FAIL;
|
2001-10-26 12:16:19 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
2002-07-22 06:06:19 +08:00
|
|
|
dig->nbytes = 0;
|
2001-10-26 12:16:19 +08:00
|
|
|
|
2002-03-04 07:09:49 +08:00
|
|
|
/* Retrieve the tag parameters from the signature header. */
|
2002-07-22 06:06:19 +08:00
|
|
|
sig = NULL;
|
2007-12-19 18:05:56 +08:00
|
|
|
xx = headerGetEntry(sigh, sigtag, &sigtype, &sig, &siglen);
|
2002-07-22 06:06:19 +08:00
|
|
|
if (sig == NULL) {
|
2002-05-14 06:34:25 +08:00
|
|
|
rc = RPMRC_FAIL;
|
2002-03-04 07:09:49 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
2002-07-22 06:06:19 +08:00
|
|
|
(void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
|
2001-10-26 12:16:19 +08:00
|
|
|
|
2002-07-22 06:06:19 +08:00
|
|
|
switch (sigtag) {
|
2002-03-07 10:17:59 +08:00
|
|
|
case RPMSIGTAG_RSA:
|
|
|
|
/* Parse the parameters from the OpenPGP packets that will be needed. */
|
2002-07-25 00:21:23 +08:00
|
|
|
xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
|
2005-02-03 02:47:42 +08:00
|
|
|
if (dig->signature.version != 3 && dig->signature.version != 4) {
|
2007-10-09 19:49:02 +08:00
|
|
|
rpmlog(RPMLOG_ERR,
|
2007-06-12 16:22:49 +08:00
|
|
|
_("skipping package %s with unverifiable V%u signature\n"),
|
|
|
|
fn, dig->signature.version);
|
|
|
|
rc = RPMRC_FAIL;
|
2002-03-08 06:54:43 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
2002-03-07 10:17:59 +08:00
|
|
|
{ void * uh = NULL;
|
2008-02-05 22:14:34 +08:00
|
|
|
rpmTagType uht;
|
2007-12-13 15:25:10 +08:00
|
|
|
rpm_count_t uhc;
|
2002-03-07 10:17:59 +08:00
|
|
|
|
2002-04-13 09:28:20 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
|
|
|
|
break;
|
2004-10-15 08:14:29 +08:00
|
|
|
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
|
2005-03-13 09:39:19 +08:00
|
|
|
dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
|
2005-03-12 23:16:42 +08:00
|
|
|
(void) rpmDigestUpdate(dig->hdrmd5ctx, header_magic, sizeof(header_magic));
|
2002-07-22 06:06:19 +08:00
|
|
|
dig->nbytes += sizeof(header_magic);
|
2005-03-12 23:16:42 +08:00
|
|
|
(void) rpmDigestUpdate(dig->hdrmd5ctx, uh, uhc);
|
2002-07-22 06:06:19 +08:00
|
|
|
dig->nbytes += uhc;
|
2004-10-15 08:14:29 +08:00
|
|
|
(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
|
|
|
|
rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
|
2002-04-13 09:28:20 +08:00
|
|
|
uh = headerFreeData(uh, uht);
|
2002-03-07 10:17:59 +08:00
|
|
|
} break;
|
2002-03-04 07:09:49 +08:00
|
|
|
case RPMSIGTAG_DSA:
|
|
|
|
/* Parse the parameters from the OpenPGP packets that will be needed. */
|
2002-07-25 00:21:23 +08:00
|
|
|
xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
|
2005-02-03 02:47:42 +08:00
|
|
|
if (dig->signature.version != 3 && dig->signature.version != 4) {
|
2007-10-09 19:49:02 +08:00
|
|
|
rpmlog(RPMLOG_ERR,
|
2007-06-12 16:22:49 +08:00
|
|
|
_("skipping package %s with unverifiable V%u signature\n"),
|
|
|
|
fn, dig->signature.version);
|
|
|
|
rc = RPMRC_FAIL;
|
2002-03-08 06:54:43 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
2002-03-04 07:09:49 +08:00
|
|
|
case RPMSIGTAG_SHA1:
|
|
|
|
{ void * uh = NULL;
|
2008-02-05 22:14:34 +08:00
|
|
|
rpmTagType uht;
|
2007-12-13 15:25:10 +08:00
|
|
|
rpm_count_t uhc;
|
2002-03-04 07:09:49 +08:00
|
|
|
|
2002-04-13 09:28:20 +08:00
|
|
|
if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
|
|
|
|
break;
|
2004-10-15 08:14:29 +08:00
|
|
|
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
|
2002-07-22 06:06:19 +08:00
|
|
|
dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
|
|
|
|
(void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
|
|
|
|
dig->nbytes += sizeof(header_magic);
|
|
|
|
(void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
|
|
|
|
dig->nbytes += uhc;
|
2004-10-15 08:14:29 +08:00
|
|
|
(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
|
|
|
|
if (sigtag == RPMSIGTAG_SHA1)
|
|
|
|
rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
|
2002-04-13 09:28:20 +08:00
|
|
|
uh = headerFreeData(uh, uht);
|
2002-03-04 07:09:49 +08:00
|
|
|
} break;
|
|
|
|
case RPMSIGTAG_GPG:
|
|
|
|
case RPMSIGTAG_PGP5: /* XXX legacy */
|
|
|
|
case RPMSIGTAG_PGP:
|
|
|
|
/* Parse the parameters from the OpenPGP packets that will be needed. */
|
2004-10-15 08:14:29 +08:00
|
|
|
xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
|
2002-03-08 06:54:43 +08:00
|
|
|
|
2005-02-03 02:47:42 +08:00
|
|
|
if (dig->signature.version != 3 && dig->signature.version != 4) {
|
2007-10-09 19:49:02 +08:00
|
|
|
rpmlog(RPMLOG_ERR,
|
2007-06-12 16:22:49 +08:00
|
|
|
_("skipping package %s with unverifiable V%u signature\n"),
|
|
|
|
fn, dig->signature.version);
|
|
|
|
rc = RPMRC_FAIL;
|
2002-03-08 06:54:43 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
2002-03-04 07:09:49 +08:00
|
|
|
case RPMSIGTAG_MD5:
|
|
|
|
/* Legacy signatures need the compressed payload in the digest too. */
|
2004-10-15 08:14:29 +08:00
|
|
|
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
|
2002-03-04 07:09:49 +08:00
|
|
|
while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
|
2002-07-22 06:06:19 +08:00
|
|
|
dig->nbytes += count;
|
2004-10-15 08:14:29 +08:00
|
|
|
(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
|
|
|
|
rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
|
|
|
|
dig->nbytes += nb; /* XXX include size of header blob. */
|
2002-03-04 07:09:49 +08:00
|
|
|
if (count < 0) {
|
2007-11-19 22:25:24 +08:00
|
|
|
rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"),
|
2002-03-04 07:09:49 +08:00
|
|
|
fn, Fstrerror(fd));
|
|
|
|
rc = RPMRC_FAIL;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2007-11-16 23:18:55 +08:00
|
|
|
fdStealDigest(fd, dig);
|
2002-03-04 07:09:49 +08:00
|
|
|
break;
|
2008-02-05 23:42:19 +08:00
|
|
|
/* shut up gcc */
|
|
|
|
case RPMSIGTAG_LEMD5_1:
|
|
|
|
case RPMSIGTAG_LEMD5_2:
|
|
|
|
case RPMSIGTAG_BADSHA1_1:
|
|
|
|
case RPMSIGTAG_BADSHA1_2:
|
|
|
|
case RPMSIGTAG_SIZE:
|
|
|
|
case RPMSIGTAG_PAYLOADSIZE:
|
|
|
|
break;
|
2001-10-26 12:16:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @todo Implement disable/enable/warn/error/anal policy. */
|
|
|
|
|
2008-04-03 13:07:00 +08:00
|
|
|
rc = rpmVerifySignature(ts, &msg);
|
2002-08-24 05:01:59 +08:00
|
|
|
switch (rc) {
|
|
|
|
case RPMRC_OK: /* Signature is OK. */
|
2008-04-03 13:07:00 +08:00
|
|
|
rpmlog(RPMLOG_DEBUG, "%s: %s", fn, msg);
|
2001-10-26 12:16:19 +08:00
|
|
|
break;
|
2002-08-24 05:01:59 +08:00
|
|
|
case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */
|
|
|
|
case RPMRC_NOKEY: /* Public key is unavailable. */
|
2002-07-01 06:47:32 +08:00
|
|
|
/* XXX Print NOKEY/NOTTRUSTED warning only once. */
|
2007-10-09 19:52:01 +08:00
|
|
|
{ int lvl = (rpmtsStashKeyid(ts) ? RPMLOG_DEBUG : RPMLOG_WARNING);
|
2008-04-03 13:07:00 +08:00
|
|
|
rpmlog(lvl, "%s: %s", fn, msg);
|
2002-07-21 03:02:40 +08:00
|
|
|
} break;
|
2002-08-24 05:01:59 +08:00
|
|
|
case RPMRC_NOTFOUND: /* Signature is unknown type. */
|
2008-04-03 13:07:00 +08:00
|
|
|
rpmlog(RPMLOG_WARNING, "%s: %s", fn, msg);
|
2001-10-26 12:16:19 +08:00
|
|
|
break;
|
|
|
|
default:
|
2002-08-24 05:01:59 +08:00
|
|
|
case RPMRC_FAIL: /* Signature does not verify. */
|
2008-04-03 13:07:00 +08:00
|
|
|
rpmlog(RPMLOG_ERR, "%s: %s", fn, msg);
|
2001-10-26 12:16:19 +08:00
|
|
|
break;
|
|
|
|
}
|
2008-04-09 17:47:03 +08:00
|
|
|
free(msg);
|
2001-10-26 12:16:19 +08:00
|
|
|
|
2000-12-03 05:53:44 +08:00
|
|
|
exit:
|
2002-08-28 04:50:21 +08:00
|
|
|
if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
|
2007-11-07 19:12:20 +08:00
|
|
|
/*
|
|
|
|
* Convert legacy headers on the fly. Not having "new" style compressed
|
|
|
|
* filenames is close enough estimate for legacy indication...
|
2008-04-21 15:59:31 +08:00
|
|
|
* Source rpms are retrofitted for the silly RPMTAG_SOURCEPACKAGE tag.
|
2007-11-07 19:12:20 +08:00
|
|
|
*/
|
2008-04-21 15:59:31 +08:00
|
|
|
if (!headerIsEntry(h, RPMTAG_DIRNAMES) || headerIsSource(h)) {
|
2007-11-07 19:21:06 +08:00
|
|
|
legacyRetrofit(h);
|
2007-11-07 19:12:20 +08:00
|
|
|
}
|
2001-10-26 12:16:19 +08:00
|
|
|
|
2002-03-04 07:09:49 +08:00
|
|
|
/* Append (and remap) signature tags to the metadata. */
|
2002-07-22 06:06:19 +08:00
|
|
|
headerMergeLegacySigs(h, sigh);
|
2001-10-26 12:16:19 +08:00
|
|
|
|
|
|
|
/* Bump reference count for return. */
|
2002-07-14 03:08:51 +08:00
|
|
|
*hdrp = headerLink(h);
|
2001-10-26 12:16:19 +08:00
|
|
|
}
|
2002-07-14 03:08:51 +08:00
|
|
|
h = headerFree(h);
|
2002-07-22 06:06:19 +08:00
|
|
|
rpmtsCleanDig(ts);
|
|
|
|
sigh = rpmFreeSignature(sigh);
|
2000-12-03 05:53:44 +08:00
|
|
|
return rc;
|
1999-07-09 06:10:33 +08:00
|
|
|
}
|
2007-05-24 15:56:53 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check for supported payload format in header.
|
|
|
|
* @param h header to check
|
|
|
|
* @return RPMRC_OK if supported, RPMRC_FAIL otherwise
|
|
|
|
*/
|
2007-06-19 21:12:04 +08:00
|
|
|
rpmRC headerCheckPayloadFormat(Header h) {
|
2007-05-24 15:56:53 +08:00
|
|
|
rpmRC rc = RPMRC_FAIL;
|
|
|
|
int xx;
|
|
|
|
const char *payloadfmt = NULL;
|
|
|
|
|
|
|
|
xx = headerGetEntry(h, RPMTAG_PAYLOADFORMAT, NULL,
|
2007-12-19 18:05:56 +08:00
|
|
|
(rpm_data_t *)&payloadfmt, NULL);
|
2007-07-09 16:23:58 +08:00
|
|
|
/*
|
|
|
|
* XXX Ugh, rpm 3.x packages don't have payload format tag. Instead
|
|
|
|
* of blinly allowing, should check somehow (HDRID existence or... ?)
|
|
|
|
*/
|
|
|
|
if (!payloadfmt)
|
|
|
|
return RPMRC_OK;
|
|
|
|
|
2007-05-24 15:56:53 +08:00
|
|
|
if (payloadfmt && strncmp(payloadfmt, "cpio", strlen("cpio")) == 0) {
|
|
|
|
rc = RPMRC_OK;
|
|
|
|
} else {
|
2007-12-14 23:55:31 +08:00
|
|
|
char *nevra = headerGetNEVRA(h, NULL);
|
2007-06-05 17:43:53 +08:00
|
|
|
if (payloadfmt && strncmp(payloadfmt, "drpm", strlen("drpm")) == 0) {
|
2007-10-09 19:49:02 +08:00
|
|
|
rpmlog(RPMLOG_ERR,
|
2007-05-24 15:56:53 +08:00
|
|
|
_("%s is a Delta RPM and cannot be directly installed\n"),
|
|
|
|
nevra);
|
|
|
|
} else {
|
2007-10-09 19:49:02 +08:00
|
|
|
rpmlog(RPMLOG_ERR,
|
2007-05-24 15:56:53 +08:00
|
|
|
_("Unsupported payload (%s) in package %s\n"),
|
2007-06-05 17:43:53 +08:00
|
|
|
payloadfmt ? payloadfmt : "none", nevra);
|
2007-05-24 15:56:53 +08:00
|
|
|
}
|
|
|
|
nevra = _free(nevra);
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|