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
|
|
|
|
2001-10-26 12:16:19 +08:00
|
|
|
#include <rpmio_internal.h>
|
1999-07-14 05:37:57 +08:00
|
|
|
#include <rpmlib.h>
|
1998-07-31 06:09:42 +08:00
|
|
|
|
2001-10-26 12:16:19 +08:00
|
|
|
#include "depends.h"
|
|
|
|
|
2001-10-22 05:43:32 +08:00
|
|
|
#include "misc.h" /* XXX stripTrailingChar() */
|
|
|
|
#include "legacy.h" /* XXX providePackageNVR() and compressFileList() */
|
1996-01-06 02:12:55 +08:00
|
|
|
#include "rpmlead.h"
|
2001-10-26 12:16:19 +08:00
|
|
|
|
1996-02-22 06:20:51 +08:00
|
|
|
#include "signature.h"
|
2000-12-13 04:03:45 +08:00
|
|
|
#include "debug.h"
|
1996-01-06 08:07:50 +08:00
|
|
|
|
2001-01-09 12:07:49 +08:00
|
|
|
#define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
|
|
|
|
|
2001-10-26 12:16:19 +08:00
|
|
|
/*@access rpmTransactionSet@*/
|
2002-03-11 03:00:31 +08:00
|
|
|
/*@access Header @*/ /* XXX compared with NULL */
|
|
|
|
/*@access FD_t @*/ /* XXX stealing digests */
|
2000-10-29 01:16:25 +08:00
|
|
|
|
2002-03-09 06:24:58 +08:00
|
|
|
/*@unchecked@*/
|
|
|
|
static int _print_pkts = 0;
|
|
|
|
|
2000-12-03 05:53:44 +08:00
|
|
|
void headerMergeLegacySigs(Header h, const Header sig)
|
|
|
|
{
|
2001-06-12 12:10:21 +08:00
|
|
|
HFD_t hfd = (HFD_t) headerFreeData;
|
|
|
|
HAE_t hae = (HAE_t) headerAddEntry;
|
2000-12-03 05:53:44 +08:00
|
|
|
HeaderIterator hi;
|
|
|
|
int_32 tag, type, count;
|
|
|
|
const void * ptr;
|
2001-10-16 22:58:57 +08:00
|
|
|
int xx;
|
2000-12-03 05:53:44 +08:00
|
|
|
|
|
|
|
for (hi = headerInitIterator(sig);
|
|
|
|
headerNextIterator(hi, &tag, &type, &ptr, &count);
|
2001-06-12 12:10:21 +08:00
|
|
|
ptr = hfd(ptr, type))
|
2000-12-03 05:53:44 +08:00
|
|
|
{
|
|
|
|
switch (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:
|
|
|
|
tag = RPMTAG_SIGSIZE;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMSIGTAG_LEMD5_1:
|
|
|
|
tag = RPMTAG_SIGLEMD5_1;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMSIGTAG_PGP:
|
|
|
|
tag = RPMTAG_SIGPGP;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMSIGTAG_LEMD5_2:
|
|
|
|
tag = RPMTAG_SIGLEMD5_2;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMSIGTAG_MD5:
|
|
|
|
tag = RPMTAG_SIGMD5;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMSIGTAG_GPG:
|
|
|
|
tag = RPMTAG_SIGGPG;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMSIGTAG_PGP5:
|
|
|
|
tag = RPMTAG_SIGPGP5;
|
|
|
|
/*@switchbreak@*/ break;
|
2002-03-04 07:09:49 +08:00
|
|
|
case RPMSIGTAG_PAYLOADSIZE:
|
|
|
|
tag = RPMTAG_ARCHIVESIZE;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
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:
|
2001-06-12 12:10:21 +08:00
|
|
|
if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
|
|
|
|
continue;
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@switchbreak@*/ break;
|
2000-12-03 05:53:44 +08:00
|
|
|
}
|
2001-05-04 05:00:18 +08:00
|
|
|
if (ptr == NULL) continue; /* XXX can't happen */
|
2000-12-03 05:53:44 +08:00
|
|
|
if (!headerIsEntry(h, tag))
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = hae(h, tag, type, ptr, count);
|
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
|
|
|
}
|
|
|
|
|
2001-02-12 06:02:29 +08:00
|
|
|
Header headerRegenSigHeader(const Header h)
|
|
|
|
{
|
2001-06-12 12:10:21 +08:00
|
|
|
HFD_t hfd = (HFD_t) headerFreeData;
|
2001-02-12 06:02:29 +08:00
|
|
|
Header sig = rpmNewSignature();
|
|
|
|
HeaderIterator hi;
|
|
|
|
int_32 tag, stag, type, count;
|
|
|
|
const void * ptr;
|
2001-10-16 22:58:57 +08:00
|
|
|
int xx;
|
2001-02-12 06:02:29 +08:00
|
|
|
|
|
|
|
for (hi = headerInitIterator(h);
|
|
|
|
headerNextIterator(hi, &tag, &type, &ptr, &count);
|
2001-06-12 12:10:21 +08:00
|
|
|
ptr = hfd(ptr, type))
|
2001-02-12 06:02:29 +08:00
|
|
|
{
|
|
|
|
switch (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:
|
|
|
|
stag = RPMSIGTAG_SIZE;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMTAG_SIGLEMD5_1:
|
|
|
|
stag = RPMSIGTAG_LEMD5_1;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMTAG_SIGPGP:
|
|
|
|
stag = RPMSIGTAG_PGP;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMTAG_SIGLEMD5_2:
|
|
|
|
stag = RPMSIGTAG_LEMD5_2;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMTAG_SIGMD5:
|
|
|
|
stag = RPMSIGTAG_MD5;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMTAG_SIGGPG:
|
|
|
|
stag = RPMSIGTAG_GPG;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
case RPMTAG_SIGPGP5:
|
|
|
|
stag = RPMSIGTAG_PGP5;
|
|
|
|
/*@switchbreak@*/ break;
|
2002-03-04 07:09:49 +08:00
|
|
|
case RPMTAG_ARCHIVESIZE:
|
|
|
|
stag = RPMSIGTAG_PAYLOADSIZE;
|
|
|
|
/*@switchbreak@*/ break;
|
|
|
|
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:
|
2001-06-12 12:10:21 +08:00
|
|
|
if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
|
|
|
|
continue;
|
|
|
|
stag = tag;
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@switchbreak@*/ break;
|
2001-02-12 06:02:29 +08:00
|
|
|
}
|
2001-05-04 05:00:18 +08:00
|
|
|
if (ptr == NULL) continue; /* XXX can't happen */
|
2001-02-12 06:02:29 +08:00
|
|
|
if (!headerIsEntry(sig, stag))
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = headerAddEntry(sig, stag, type, ptr, count);
|
2001-02-12 06:02:29 +08:00
|
|
|
}
|
2001-06-20 00:59:23 +08:00
|
|
|
hi = headerFreeIterator(hi);
|
2001-02-12 06:02:29 +08:00
|
|
|
return sig;
|
|
|
|
}
|
|
|
|
|
2001-10-26 12:16:19 +08:00
|
|
|
#ifdef DYING
|
2000-08-23 21:02:13 +08:00
|
|
|
/**
|
|
|
|
* Retrieve package components from file handle.
|
|
|
|
* @param fd file handle
|
|
|
|
* @param leadPtr address of lead (or NULL)
|
|
|
|
* @param sigs address of signatures (or NULL)
|
|
|
|
* @param hdrPtr address of header (or NULL)
|
2001-02-13 03:02:15 +08:00
|
|
|
* @return rpmRC return code
|
2000-08-23 21:02:13 +08:00
|
|
|
*/
|
2001-06-01 06:31:14 +08:00
|
|
|
static rpmRC readPackageHeaders(FD_t fd,
|
|
|
|
/*@null@*/ /*@out@*/ struct rpmlead * leadPtr,
|
|
|
|
/*@null@*/ /*@out@*/ Header * sigs,
|
|
|
|
/*@null@*/ /*@out@*/ Header * hdrPtr)
|
2001-10-15 11:22:10 +08:00
|
|
|
/*@globals fileSystem@*/
|
|
|
|
/*@modifies fd, *leadPtr, *sigs, *hdrPtr, fileSystem @*/
|
1999-07-14 07:33:02 +08:00
|
|
|
{
|
1999-07-09 06:10:33 +08:00
|
|
|
Header hdrBlock;
|
|
|
|
struct rpmlead leadBlock;
|
1999-09-18 04:52:46 +08:00
|
|
|
Header * hdr = NULL;
|
1999-07-09 06:10:33 +08:00
|
|
|
struct rpmlead * lead;
|
|
|
|
struct stat sb;
|
2001-02-13 03:02:15 +08:00
|
|
|
rpmRC rc;
|
1999-07-09 06:10:33 +08:00
|
|
|
|
|
|
|
hdr = hdrPtr ? hdrPtr : &hdrBlock;
|
|
|
|
lead = leadPtr ? leadPtr : &leadBlock;
|
|
|
|
|
2001-05-01 06:32:22 +08:00
|
|
|
memset(&sb, 0, sizeof(sb));
|
|
|
|
(void) fstat(Fileno(fd), &sb);
|
1999-07-09 06:10:33 +08:00
|
|
|
/* if fd points to a socket, pipe, etc, sb.st_size is *always* zero */
|
|
|
|
if (S_ISREG(sb.st_mode) && sb.st_size < sizeof(*lead)) return 1;
|
|
|
|
|
2000-11-07 21:16:43 +08:00
|
|
|
if (readLead(fd, lead))
|
2001-02-13 03:02:15 +08:00
|
|
|
return RPMRC_FAIL;
|
1999-07-09 06:10:33 +08:00
|
|
|
|
|
|
|
if (lead->magic[0] != RPMLEAD_MAGIC0 || lead->magic[1] != RPMLEAD_MAGIC1 ||
|
2001-10-25 09:36:32 +08:00
|
|
|
lead->magic[2] != RPMLEAD_MAGIC2 || lead->magic[3] != RPMLEAD_MAGIC3)
|
2001-02-13 03:02:15 +08:00
|
|
|
return RPMRC_BADMAGIC;
|
1999-07-09 06:10:33 +08:00
|
|
|
|
2000-05-31 03:30:28 +08:00
|
|
|
switch (lead->major) {
|
1999-07-09 06:10:33 +08:00
|
|
|
case 1:
|
2001-01-09 12:07:49 +08:00
|
|
|
rpmError(RPMERR_NEWPACKAGE,
|
2001-01-16 07:09:42 +08:00
|
|
|
_("packaging version 1 is not supported by this version of RPM\n"));
|
2001-02-13 03:02:15 +08:00
|
|
|
return RPMRC_FAIL;
|
2000-07-15 22:53:54 +08:00
|
|
|
/*@notreached@*/ break;
|
1999-07-09 06:10:33 +08:00
|
|
|
case 2:
|
|
|
|
case 3:
|
2000-05-31 03:30:28 +08:00
|
|
|
case 4:
|
2001-02-13 03:02:15 +08:00
|
|
|
rc = rpmReadSignature(fd, sigs, lead->signature_type);
|
|
|
|
if (rc == RPMRC_FAIL)
|
|
|
|
return rc;
|
2001-01-09 12:07:49 +08:00
|
|
|
*hdr = headerRead(fd, (lead->major >= 3)
|
|
|
|
? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
|
1999-07-09 06:10:33 +08:00
|
|
|
if (*hdr == NULL) {
|
2000-11-07 21:16:43 +08:00
|
|
|
if (sigs != NULL)
|
2001-05-23 22:25:19 +08:00
|
|
|
*sigs = rpmFreeSignature(*sigs);
|
2001-02-13 03:02:15 +08:00
|
|
|
return RPMRC_FAIL;
|
1999-07-09 06:10:33 +08:00
|
|
|
}
|
|
|
|
|
2001-10-26 12:16:19 +08:00
|
|
|
/* Convert legacy headers on the fly ... */
|
2001-10-25 09:36:32 +08:00
|
|
|
legacyRetrofit(*hdr, lead);
|
1999-07-09 06:10:33 +08:00
|
|
|
break;
|
|
|
|
default:
|
2000-07-15 22:53:54 +08:00
|
|
|
rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
|
2001-01-16 07:09:42 +08:00
|
|
|
"is supported by this version of RPM\n"));
|
2001-02-13 03:02:15 +08:00
|
|
|
return RPMRC_FAIL;
|
1999-09-18 04:52:46 +08:00
|
|
|
/*@notreached@*/ break;
|
1999-07-09 06:10:33 +08:00
|
|
|
}
|
|
|
|
|
2000-12-03 05:53:44 +08:00
|
|
|
if (hdrPtr == NULL)
|
2001-11-02 04:15:10 +08:00
|
|
|
*hdr = headerFree(*hdr, "ReadPackageHeaders exit");
|
1999-07-09 06:10:33 +08:00
|
|
|
|
2001-02-13 03:02:15 +08:00
|
|
|
return RPMRC_OK;
|
1999-07-09 06:10:33 +08:00
|
|
|
}
|
2001-10-26 12:16:19 +08:00
|
|
|
#endif
|
1999-07-09 06:10:33 +08:00
|
|
|
|
2002-03-07 07:17:31 +08:00
|
|
|
/*@unchecked@*/
|
|
|
|
static unsigned char header_magic[8] = {
|
|
|
|
0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
|
|
|
|
};
|
|
|
|
|
2001-10-26 12:16:19 +08:00
|
|
|
int rpmReadPackageFile(rpmTransactionSet ts, FD_t fd,
|
|
|
|
const char * fn, Header * hdrp)
|
1999-07-14 07:33:02 +08:00
|
|
|
{
|
2001-10-26 12:16:19 +08:00
|
|
|
byte buf[8*BUFSIZ];
|
|
|
|
ssize_t count;
|
|
|
|
struct rpmlead * l = alloca(sizeof(*l));
|
|
|
|
Header sig;
|
|
|
|
Header h = NULL;
|
|
|
|
int hmagic;
|
|
|
|
rpmRC rc = RPMRC_FAIL; /* assume failure */
|
|
|
|
int xx;
|
|
|
|
int i;
|
1999-07-09 06:10:33 +08:00
|
|
|
|
2001-10-26 12:16:19 +08:00
|
|
|
{ struct stat st;
|
|
|
|
memset(&st, 0, sizeof(st));
|
|
|
|
(void) fstat(Fileno(fd), &st);
|
|
|
|
/* if fd points to a socket, pipe, etc, st.st_size is *always* zero */
|
|
|
|
if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l))
|
|
|
|
goto exit;
|
|
|
|
}
|
2000-12-03 05:53:44 +08:00
|
|
|
|
2001-10-26 12:16:19 +08:00
|
|
|
memset(l, 0, sizeof(*l));
|
|
|
|
if (readLead(fd, l)) {
|
|
|
|
rpmError(RPMERR_READLEAD, _("%s: readLead failed\n"), fn);
|
2000-12-03 05:53:44 +08:00
|
|
|
goto exit;
|
2001-10-26 12:16:19 +08:00
|
|
|
}
|
1999-07-09 06:10:33 +08:00
|
|
|
|
2001-10-26 12:16:19 +08:00
|
|
|
if (l->magic[0] != RPMLEAD_MAGIC0 || l->magic[1] != RPMLEAD_MAGIC1
|
|
|
|
|| l->magic[2] != RPMLEAD_MAGIC2 || l->magic[3] != RPMLEAD_MAGIC3) {
|
|
|
|
rpmError(RPMERR_READLEAD, _("%s: bad magic\n"), fn);
|
|
|
|
rc = RPMRC_BADMAGIC;
|
|
|
|
goto exit;
|
2000-12-03 05:53:44 +08:00
|
|
|
}
|
2001-10-26 12:16:19 +08:00
|
|
|
|
|
|
|
switch (l->major) {
|
|
|
|
case 1:
|
|
|
|
rpmError(RPMERR_NEWPACKAGE,
|
|
|
|
_("packaging version 1 is not supported by this version of RPM\n"));
|
|
|
|
goto exit;
|
|
|
|
/*@notreached@*/ break;
|
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
case 4:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
|
|
|
|
"is supported by this version of RPM\n"));
|
|
|
|
goto exit;
|
|
|
|
/*@notreached@*/ break;
|
|
|
|
}
|
|
|
|
|
2002-03-04 07:09:49 +08:00
|
|
|
/* Read the signature header. */
|
2001-10-26 12:16:19 +08:00
|
|
|
rc = rpmReadSignature(fd, &sig, l->signature_type);
|
|
|
|
if (!(rc == RPMRC_OK || rc == RPMRC_BADSIZE)) {
|
|
|
|
rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed\n"), fn);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
if (sig == NULL) {
|
|
|
|
rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
|
|
|
|
rc = RPMRC_FAIL;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2002-03-04 07:09:49 +08:00
|
|
|
/* Figger the most effective available signature. */
|
2002-03-09 06:24:58 +08:00
|
|
|
ts->sigtag = 0;
|
|
|
|
if (ts->verify_legacy) {
|
|
|
|
if (ts->sigtag == 0 && !ts->nosignatures) {
|
|
|
|
if (headerIsEntry(sig, RPMSIGTAG_DSA))
|
|
|
|
ts->sigtag = RPMSIGTAG_DSA;
|
|
|
|
else if (headerIsEntry(sig, RPMSIGTAG_RSA))
|
|
|
|
ts->sigtag = RPMSIGTAG_RSA;
|
|
|
|
else if (headerIsEntry(sig, RPMSIGTAG_GPG)) {
|
|
|
|
ts->sigtag = RPMSIGTAG_GPG;
|
|
|
|
fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
|
|
|
|
} else if (headerIsEntry(sig, RPMSIGTAG_PGP)) {
|
|
|
|
ts->sigtag = RPMSIGTAG_PGP;
|
|
|
|
fdInitDigest(fd, PGPHASHALGO_MD5, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ts->sigtag == 0 && !ts->nodigests) {
|
|
|
|
if (headerIsEntry(sig, RPMSIGTAG_SHA1))
|
|
|
|
ts->sigtag = RPMSIGTAG_SHA1;
|
|
|
|
else if (headerIsEntry(sig, RPMSIGTAG_MD5)) {
|
|
|
|
ts->sigtag = RPMSIGTAG_MD5;
|
|
|
|
fdInitDigest(fd, PGPHASHALGO_MD5, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (ts->sigtag == 0 && !ts->nosignatures) {
|
|
|
|
if (headerIsEntry(sig, RPMSIGTAG_DSA))
|
|
|
|
ts->sigtag = RPMSIGTAG_DSA;
|
|
|
|
else if (headerIsEntry(sig, RPMSIGTAG_RSA))
|
|
|
|
ts->sigtag = RPMSIGTAG_RSA;
|
|
|
|
}
|
|
|
|
if (ts->sigtag == 0 && !ts->nodigests) {
|
|
|
|
if (headerIsEntry(sig, RPMSIGTAG_SHA1))
|
|
|
|
ts->sigtag = RPMSIGTAG_SHA1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
fprintf(stderr, "*** RPF: legacy %d nodigests %d nosignatures %d sigtag %d\n", ts->verify_legacy, ts->nodigests, ts->nosignatures, ts->sigtag);
|
|
|
|
#endif
|
2001-10-26 12:16:19 +08:00
|
|
|
|
2002-03-04 07:09:49 +08:00
|
|
|
/* Read the metadata, computing digest(s) on the fly. */
|
2001-10-26 12:16:19 +08:00
|
|
|
hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
|
|
|
|
h = headerRead(fd, hmagic);
|
|
|
|
if (h == NULL) {
|
|
|
|
rpmError(RPMERR_FREAD, _("%s: headerRead failed\n"), fn);
|
|
|
|
rc = RPMRC_FAIL;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Any signatures to check? */
|
|
|
|
if (ts->sigtag == 0) {
|
|
|
|
rc = RPMRC_OK;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
ts->dig = pgpNewDig();
|
2002-03-04 07:09:49 +08:00
|
|
|
if (ts->dig == NULL) {
|
|
|
|
rc = RPMRC_OK; /* XXX WRONG */
|
2001-10-26 12:16:19 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
2002-03-04 07:09:49 +08:00
|
|
|
ts->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. */
|
|
|
|
ts->sig = NULL;
|
2001-10-26 12:16:19 +08:00
|
|
|
xx = headerGetEntry(sig, ts->sigtag, &ts->sigtype,
|
|
|
|
(void **) &ts->sig, &ts->siglen);
|
2002-03-04 07:09:49 +08:00
|
|
|
if (ts->sig == NULL) {
|
|
|
|
rc = RPMRC_OK; /* XXX WRONG */
|
|
|
|
goto exit;
|
|
|
|
}
|
2001-10-26 12:16:19 +08:00
|
|
|
|
2002-03-04 07:09:49 +08:00
|
|
|
switch (ts->sigtag) {
|
2002-03-07 10:17:59 +08:00
|
|
|
case RPMSIGTAG_RSA:
|
|
|
|
/* Parse the parameters from the OpenPGP packets that will be needed. */
|
2002-03-09 06:24:58 +08:00
|
|
|
xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig,
|
|
|
|
(_print_pkts & rpmIsDebug()));
|
2002-03-08 06:54:43 +08:00
|
|
|
/* XXX only V3 signatures for now. */
|
|
|
|
if (ts->dig->signature.version != 3) {
|
|
|
|
rpmMessage(RPMMESS_WARNING,
|
|
|
|
_("only V3 signatures can be verified, skipping V%u signature"),
|
|
|
|
ts->dig->signature.version);
|
|
|
|
rc = RPMRC_OK;
|
|
|
|
goto exit;
|
|
|
|
}
|
2002-03-07 10:17:59 +08:00
|
|
|
{ void * uh = NULL;
|
|
|
|
int_32 uht;
|
|
|
|
int_32 uhc;
|
|
|
|
|
|
|
|
/*@-branchstate@*/
|
|
|
|
if (headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) {
|
|
|
|
ts->dig->md5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
|
|
|
|
(void) rpmDigestUpdate(ts->dig->md5ctx, header_magic, sizeof(header_magic));
|
|
|
|
ts->dig->nbytes += sizeof(header_magic);
|
|
|
|
(void) rpmDigestUpdate(ts->dig->md5ctx, uh, uhc);
|
|
|
|
ts->dig->nbytes += uhc;
|
|
|
|
uh = headerFreeData(uh, uht);
|
|
|
|
}
|
|
|
|
/*@=branchstate@*/
|
|
|
|
} break;
|
2002-03-04 07:09:49 +08:00
|
|
|
case RPMSIGTAG_DSA:
|
|
|
|
/* Parse the parameters from the OpenPGP packets that will be needed. */
|
2002-03-09 06:24:58 +08:00
|
|
|
xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig,
|
|
|
|
(_print_pkts & rpmIsDebug()));
|
2002-03-08 06:54:43 +08:00
|
|
|
/* XXX only V3 signatures for now. */
|
|
|
|
if (ts->dig->signature.version != 3) {
|
|
|
|
rpmMessage(RPMMESS_WARNING,
|
|
|
|
_("only V3 signatures can be verified, skipping V%u signature"),
|
|
|
|
ts->dig->signature.version);
|
|
|
|
rc = RPMRC_OK;
|
|
|
|
goto exit;
|
|
|
|
}
|
2002-03-04 07:09:49 +08:00
|
|
|
/*@fallthrough@*/
|
|
|
|
case RPMSIGTAG_SHA1:
|
|
|
|
{ void * uh = NULL;
|
|
|
|
int_32 uht;
|
|
|
|
int_32 uhc;
|
|
|
|
|
|
|
|
/*@-branchstate@*/
|
|
|
|
if (headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) {
|
2002-03-07 07:17:31 +08:00
|
|
|
ts->dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
|
|
|
|
(void) rpmDigestUpdate(ts->dig->hdrsha1ctx, header_magic, sizeof(header_magic));
|
|
|
|
ts->dig->nbytes += sizeof(header_magic);
|
|
|
|
(void) rpmDigestUpdate(ts->dig->hdrsha1ctx, uh, uhc);
|
2002-03-04 07:09:49 +08:00
|
|
|
ts->dig->nbytes += uhc;
|
|
|
|
uh = headerFreeData(uh, uht);
|
2001-10-26 12:16:19 +08:00
|
|
|
}
|
2002-03-04 07:09:49 +08:00
|
|
|
/*@=branchstate@*/
|
|
|
|
} break;
|
|
|
|
case RPMSIGTAG_GPG:
|
|
|
|
case RPMSIGTAG_PGP5: /* XXX legacy */
|
|
|
|
case RPMSIGTAG_PGP:
|
|
|
|
/* Parse the parameters from the OpenPGP packets that will be needed. */
|
2002-03-09 06:24:58 +08:00
|
|
|
xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig,
|
|
|
|
(_print_pkts & rpmIsDebug()));
|
2002-03-08 06:54:43 +08:00
|
|
|
|
|
|
|
/* XXX only V3 signatures for now. */
|
|
|
|
if (ts->dig->signature.version != 3) {
|
|
|
|
rpmMessage(RPMMESS_WARNING,
|
|
|
|
_("only V3 signatures can be verified, skipping V%u signature"),
|
|
|
|
ts->dig->signature.version);
|
|
|
|
rc = RPMRC_OK;
|
|
|
|
goto exit;
|
|
|
|
}
|
2002-03-04 07:09:49 +08:00
|
|
|
/*@fallthrough@*/
|
|
|
|
case RPMSIGTAG_MD5:
|
|
|
|
/* Legacy signatures need the compressed payload in the digest too. */
|
|
|
|
ts->dig->nbytes += headerSizeof(h, hmagic);
|
|
|
|
while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
|
|
|
|
ts->dig->nbytes += count;
|
|
|
|
if (count < 0) {
|
|
|
|
rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
|
|
|
|
fn, Fstrerror(fd));
|
|
|
|
rc = RPMRC_FAIL;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
ts->dig->nbytes += count;
|
|
|
|
|
|
|
|
/* XXX Steal the digest-in-progress from the file handle. */
|
|
|
|
for (i = fd->ndigests - 1; i >= 0; i--) {
|
|
|
|
FDDIGEST_t fddig = fd->digests + i;
|
|
|
|
if (fddig->hashctx == NULL)
|
|
|
|
continue;
|
|
|
|
if (fddig->hashalgo == PGPHASHALGO_MD5) {
|
2002-03-11 03:00:31 +08:00
|
|
|
#ifdef DYING
|
2002-03-04 07:09:49 +08:00
|
|
|
/*@-branchstate@*/
|
|
|
|
if (ts->dig->md5ctx != NULL)
|
|
|
|
(void) rpmDigestFinal(ts->dig->md5ctx, NULL, NULL, 0);
|
|
|
|
/*@=branchstate@*/
|
2002-03-11 03:00:31 +08:00
|
|
|
#else
|
2002-03-13 00:56:17 +08:00
|
|
|
assert(ts->dig->md5ctx == NULL);
|
2002-03-11 03:00:31 +08:00
|
|
|
#endif
|
2002-03-04 07:09:49 +08:00
|
|
|
ts->dig->md5ctx = fddig->hashctx;
|
|
|
|
fddig->hashctx = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (fddig->hashalgo == PGPHASHALGO_SHA1) {
|
2002-03-11 03:00:31 +08:00
|
|
|
#ifdef DYING
|
2002-03-04 07:09:49 +08:00
|
|
|
/*@-branchstate@*/
|
|
|
|
if (ts->dig->sha1ctx != NULL)
|
|
|
|
(void) rpmDigestFinal(ts->dig->sha1ctx, NULL, NULL, 0);
|
|
|
|
/*@=branchstate@*/
|
2002-03-11 03:00:31 +08:00
|
|
|
#else
|
2002-03-13 00:56:17 +08:00
|
|
|
assert(ts->dig->sha1ctx == NULL);
|
2002-03-11 03:00:31 +08:00
|
|
|
#endif
|
2002-03-04 07:09:49 +08:00
|
|
|
ts->dig->sha1ctx = fddig->hashctx;
|
|
|
|
fddig->hashctx = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
2001-10-26 12:16:19 +08:00
|
|
|
}
|
2002-03-04 07:09:49 +08:00
|
|
|
break;
|
2001-10-26 12:16:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** @todo Implement disable/enable/warn/error/anal policy. */
|
|
|
|
|
|
|
|
buf[0] = '\0';
|
|
|
|
switch (rpmVerifySignature(ts, buf)) {
|
2001-11-20 06:45:35 +08:00
|
|
|
case RPMSIG_OK: /* Signature is OK. */
|
2002-03-04 07:09:49 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
|
2001-10-26 12:16:19 +08:00
|
|
|
rc = RPMRC_OK;
|
|
|
|
break;
|
2001-11-20 06:45:35 +08:00
|
|
|
case RPMSIG_UNKNOWN: /* Signature is unknown. */
|
|
|
|
case RPMSIG_NOKEY: /* Key is unavailable. */
|
|
|
|
case RPMSIG_NOTTRUSTED: /* Signature is OK, but key is not trusted. */
|
2001-10-26 12:16:19 +08:00
|
|
|
rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
|
|
|
|
rc = RPMRC_OK;
|
|
|
|
break;
|
|
|
|
default:
|
2001-11-20 06:45:35 +08:00
|
|
|
case RPMSIG_BAD: /* Signature does not verify. */
|
2001-10-26 12:16:19 +08:00
|
|
|
rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
|
|
|
|
rc = RPMRC_OK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2000-12-03 05:53:44 +08:00
|
|
|
exit:
|
2002-03-08 06:54:43 +08:00
|
|
|
if (rc == RPMRC_OK && hdrp != NULL) {
|
2001-10-26 12:16:19 +08:00
|
|
|
/* Convert legacy headers on the fly ... */
|
|
|
|
legacyRetrofit(h, l);
|
|
|
|
|
2002-03-04 07:09:49 +08:00
|
|
|
/* Append (and remap) signature tags to the metadata. */
|
2001-10-26 12:16:19 +08:00
|
|
|
headerMergeLegacySigs(h, sig);
|
|
|
|
|
|
|
|
/* Bump reference count for return. */
|
2001-11-02 04:15:10 +08:00
|
|
|
*hdrp = headerLink(h, "ReadPackageFile *hdrp");
|
2001-10-26 12:16:19 +08:00
|
|
|
}
|
2001-11-02 04:15:10 +08:00
|
|
|
h = headerFree(h, "ReadPackageFile");
|
2001-10-26 12:16:19 +08:00
|
|
|
if (ts->sig != NULL)
|
|
|
|
ts->sig = headerFreeData(ts->sig, ts->sigtype);
|
|
|
|
if (ts->dig != NULL)
|
|
|
|
ts->dig = pgpFreeDig(ts->dig);
|
|
|
|
sig = rpmFreeSignature(sig);
|
2000-12-03 05:53:44 +08:00
|
|
|
return rc;
|
1999-07-09 06:10:33 +08:00
|
|
|
}
|