Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for multiple, named OpenPGP signatures per package #1050

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/package.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ void headerMergeLegacySigs(Header h, Header sigh)
case RPMSIGTAG_SHA256:
case RPMSIGTAG_DSA:
case RPMSIGTAG_RSA:
case RPMSIGTAG_OPENPGP:
default:
if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
continue;
Expand Down
2 changes: 2 additions & 0 deletions lib/rpmtag.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ typedef enum rpmTag_e {
RPMTAG_SHA256HEADER = RPMTAG_SIG_BASE+17, /* s */
/* RPMTAG_SIG_BASE+18 reserved for RPMSIGTAG_FILESIGNATURES */
/* RPMTAG_SIG_BASE+19 reserved for RPMSIGTAG_FILESIGNATURELENGTH */
RPMTAG_OPENPGPHEADER = RPMTAG_SIG_BASE+20, /* s[] */

RPMTAG_NAME = 1000, /* s */
#define RPMTAG_N RPMTAG_NAME /* s */
Expand Down Expand Up @@ -430,6 +431,7 @@ typedef enum rpmSigTag_e {
RPMSIGTAG_SHA256 = RPMTAG_SHA256HEADER,
RPMSIGTAG_FILESIGNATURES = RPMTAG_SIG_BASE + 18,
RPMSIGTAG_FILESIGNATURELENGTH = RPMTAG_SIG_BASE + 19,
RPMSIGTAG_OPENPGP = RPMTAG_OPENPGPHEADER,
} rpmSigTag;


Expand Down
53 changes: 49 additions & 4 deletions lib/rpmvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <rpm/rpmkeyring.h>
#include <rpm/rpmmacro.h>
#include <rpm/rpmlog.h>
#include <rpm/rpmbase64.h>
#include "lib/rpmvs.h"
#include "rpmio/digest.h"

Expand Down Expand Up @@ -41,6 +42,7 @@ static const struct vfytag_s rpmvfytags[] = {
{ RPMTAG_SHA256HEADER, RPM_STRING_TYPE, 1, 65, },
{ RPMTAG_PAYLOADDIGEST, RPM_STRING_ARRAY_TYPE, 0, 0, },
{ RPMTAG_PAYLOADDIGESTALT, RPM_STRING_ARRAY_TYPE, 0, 0, },
{ RPMTAG_OPENPGPHEADER, RPM_STRING_ARRAY_TYPE, 0, 0, },
{ 0 } /* sentinel */
};

Expand Down Expand Up @@ -93,6 +95,9 @@ static const struct vfyinfo_s rpmvfyitems[] = {
{ RPMTAG_PAYLOADDIGESTALT, 0,
{ RPMSIG_DIGEST_TYPE, RPMVSF_NOPAYLOAD,
(RPMSIG_PAYLOAD), PGPHASHALGO_SHA256, 0, 1, }, },
{ RPMTAG_OPENPGPHEADER, 1,
{ RPMSIG_SIGNATURE_TYPE, 0 /* XXX FIXME disabler */,
(RPMSIG_HEADER), 0, 0, }, },
{ 0 } /* sentinel */
};

Expand Down Expand Up @@ -140,6 +145,8 @@ static void rpmsinfoInit(const struct vfyinfo_s *vinfo,
rpmRC rc = RPMRC_FAIL;
const void *data = NULL;
rpm_count_t dlen = 0;
uint8_t *pkt = NULL;
size_t pktlen = 0;

*sinfo = vinfo->vi; /* struct assignment */
sinfo->wrapped = (vinfo->sigh == 0);
Expand Down Expand Up @@ -175,6 +182,22 @@ static void rpmsinfoInit(const struct vfyinfo_s *vinfo,
break;
}

if (td->tag == RPMTAG_OPENPGPHEADER) {
const char *split = strchr(data, ':');
if (split) {
/* Grab a copy of name */
size_t nlen = split - (const char *)data;
sinfo->name = memcpy(xmalloc(nlen + 1), data, nlen);
sinfo->name[nlen] = '\0';
/* Adjust data to beginning of hex part */
data = split + 1;
dlen -= nlen + 1;
} else {
/* XXX: Should we permit missing nole? */
data = NULL;
}
}

/* MD5 has data length of 16, everything else is (much) larger */
if (sinfo->hashalgo && (data == NULL || dlen < 16)) {
rasprintf(&sinfo->msg, _("%s tag %u: invalid data %p (%u)"),
Expand All @@ -193,6 +216,16 @@ static void rpmsinfoInit(const struct vfyinfo_s *vinfo,
}

if (sinfo->type == RPMSIG_SIGNATURE_TYPE) {
if (td->type == RPM_STRING_ARRAY_TYPE) {
if (rpmBase64Decode(data, (void **)&pkt, &pktlen)) {
rasprintf(&sinfo->msg, _("%s tag %u: invalid base64"),
origin, td->tag);
goto exit;
}
data = pkt;
dlen = pktlen;
}

if (pgpPrtParams(data, dlen, PGPTAG_SIGNATURE, &sinfo->sig)) {
rasprintf(&sinfo->msg, _("%s tag %u: invalid OpenPGP signature"),
origin, td->tag);
Expand All @@ -219,6 +252,8 @@ static void rpmsinfoInit(const struct vfyinfo_s *vinfo,
rc = RPMRC_OK;

exit:
if (pkt && pkt != td->data)
free(pkt);
sinfo->rc = rc;
return;
}
Expand All @@ -233,6 +268,7 @@ static void rpmsinfoFini(struct rpmsinfo_s *sinfo)
rpmDigestFinal(sinfo->ctx, NULL, NULL, 0);
free(sinfo->msg);
free(sinfo->descr);
free(sinfo->name);
memset(sinfo, 0, sizeof(*sinfo));
}
}
Expand Down Expand Up @@ -270,13 +306,20 @@ const char *rpmsinfoDescr(struct rpmsinfo_s *sinfo)
case RPMSIG_SIGNATURE_TYPE:
if (sinfo->sig) {
char *t = pgpIdentItem(sinfo->sig);
rasprintf(&sinfo->descr, _("%s%s"),
rangeName(sinfo->range), t);
if (sinfo->name) {
rasprintf(&sinfo->descr, _("%s%s [%s]"),
rangeName(sinfo->range), t, sinfo->name);
} else {
rasprintf(&sinfo->descr, _("%s%s"),
rangeName(sinfo->range), t);
}
free(t);
} else {
const char *alg = sinfo->sigalgo ?
pgpValString(PGPVAL_PUBKEYALGO, sinfo->sigalgo) :
"OpenPGP";
rasprintf(&sinfo->descr, _("%s%s%s %s"),
rangeName(sinfo->range),
pgpValString(PGPVAL_PUBKEYALGO, sinfo->sigalgo),
rangeName(sinfo->range), alg,
sinfo->alt ? " ALT" : "",
_("signature"));
}
Expand Down Expand Up @@ -394,6 +437,8 @@ void rpmvsFiniRange(struct rpmvs_s *sis, int range)

if (sinfo->range == range && sinfo->rc == RPMRC_OK) {
sinfo->ctx = rpmDigestBundleDupCtx(sis->bundle, sinfo->id);
if (sinfo->name)
rpmDigestUpdate(sinfo->ctx, sinfo->name, strlen(sinfo->name)+1);
/* Handle unsupported digests the same as disabled ones */
if (sinfo->ctx == NULL)
sinfo->rc = RPMRC_NOTFOUND;
Expand Down
1 change: 1 addition & 0 deletions lib/rpmvs.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct rpmsinfo_s {
char *dig;
};
char *descr;
char *name;
DIGEST_CTX ctx;
/* verify results */
rpmRC rc;
Expand Down
6 changes: 6 additions & 0 deletions rpmsign.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ static int mode = MODE_NONE;
static int signfiles = 0, fskpass = 0;
static char * fileSigningKey = NULL;
#endif
static char * name = NULL;

static struct rpmSignArgs sargs = {NULL, 0, 0};

Expand All @@ -32,6 +33,8 @@ static struct poptOption signOptsTable[] = {
N_("sign package(s) (identical to --addsign)"), NULL },
{ "delsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_DELSIGN,
N_("delete package signatures"), NULL },
{ "name", '\0', POPT_ARG_STRING, &name, 0,
N_("signature name"), NULL },
#ifdef WITH_IMAEVM
{ "signfiles", '\0', POPT_ARG_NONE, &signfiles, 0,
N_("sign package(s) files"), NULL},
Expand Down Expand Up @@ -168,6 +171,9 @@ int main(int argc, char *argv[])
}
#endif

if (name)
sargs.name = name;

switch (mode) {
case MODE_ADDSIGN:
case MODE_RESIGN:
Expand Down
79 changes: 57 additions & 22 deletions sign/rpmgensig.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <rpm/rpmfileutil.h> /* rpmMkTemp() */
#include <rpm/rpmlog.h>
#include <rpm/rpmstring.h>
#include <rpm/rpmbase64.h>
#include <rpmio/rpmio_internal.h>

#include "lib/rpmlead.h"
Expand Down Expand Up @@ -191,7 +192,8 @@ static int copyFile(FD_t *sfdp, const char *sfnp,
* generated signature is something we can use.
* Return generated signature tag data on success, NULL on failure.
*/
static rpmtd makeSigTag(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen)
static rpmtd makeSigTag(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen,
const char *name)
{
pgpDigParams sigp = NULL;
rpmTagVal sigtag;
Expand Down Expand Up @@ -225,20 +227,35 @@ static rpmtd makeSigTag(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen)
break;
}

if (name)
sigtag = RPMSIGTAG_OPENPGP;

/* Looks sane, create the tag data */
sigtd = rpmtdNew();
sigtd->count = pktlen;
sigtd->data = memcpy(xmalloc(pktlen), pkt, pktlen);;
sigtd->type = RPM_BIN_TYPE;
sigtd->tag = sigtag;
sigtd->flags |= RPMTD_ALLOCED;

if (name) {
char *b64 = rpmBase64Encode(pkt, pktlen, 0);
char *sigstr = rstrscat(NULL, name, ":", b64, NULL);
char **arr = xmalloc(1 * sizeof(*arr));
arr[0] = sigstr;
sigtd->data = arr;
sigtd->count = 1;
sigtd->type = RPM_STRING_ARRAY_TYPE;
free(b64);
} else {
sigtd->count = pktlen;
sigtd->data = memcpy(xmalloc(pktlen), pkt, pktlen);;
sigtd->type = RPM_BIN_TYPE;
}

exit:
pgpDigParamsFree(sigp);
return sigtd;
}

static int runGPG(sigTarget sigt, const char *sigfile)
static int runGPG(sigTarget sigt, const char *sigfile, const char *name)
{
int pid = 0, status;
FD_t fnamedPipe = NULL;
Expand Down Expand Up @@ -304,6 +321,15 @@ static int runGPG(sigTarget sigt, const char *sigfile)
sigt->fileName, Fstrerror(sigt->fd));
goto exit;
}

if (name) {
size_t nlen = strlen(name) + 1; /* include trailing \0 */
if (Fwrite(name, 1, nlen, fnamedPipe) != nlen) {
rpmlog(RPMLOG_ERR, _("Could not write to pipe\n"));
goto exit;
}
}

Fclose(fnamedPipe);
fnamedPipe = NULL;

Expand Down Expand Up @@ -337,17 +363,19 @@ static int runGPG(sigTarget sigt, const char *sigfile)
* @param ishdr header-only signature?
* @param sigt signature target
* @param passPhrase private key pass phrase
* @param name signer name (or NULL)
* @return generated sigtag on success, 0 on failure
*/
static rpmtd makeGPGSignature(Header sigh, int ishdr, sigTarget sigt)
static rpmtd makeGPGSignature(Header sigh, int ishdr, sigTarget sigt,
const char *name)
{
char * sigfile = rstrscat(NULL, sigt->fileName, ".sig", NULL);
struct stat st;
uint8_t * pkt = NULL;
size_t pktlen = 0;
rpmtd sigtd = NULL;

if (runGPG(sigt, sigfile))
if (runGPG(sigt, sigfile, name))
goto exit;

if (stat(sigfile, &st)) {
Expand Down Expand Up @@ -377,7 +405,7 @@ static rpmtd makeGPGSignature(Header sigh, int ishdr, sigTarget sigt)
rpmlog(RPMLOG_DEBUG, "Got %zd bytes of GPG sig\n", pktlen);

/* Parse the signature, change signature tag as appropriate. */
sigtd = makeSigTag(sigh, ishdr, pkt, pktlen);
sigtd = makeSigTag(sigh, ishdr, pkt, pktlen, name);
exit:
(void) unlink(sigfile);
free(sigfile);
Expand All @@ -393,6 +421,7 @@ static void deleteSigs(Header sigh)
headerDel(sigh, RPMSIGTAG_DSA);
headerDel(sigh, RPMSIGTAG_RSA);
headerDel(sigh, RPMSIGTAG_PGP5);
headerDel(sigh, RPMSIGTAG_OPENPGP);
}

static int haveSignature(rpmtd sigtd, Header h)
Expand All @@ -418,13 +447,15 @@ static int haveSignature(rpmtd sigtd, Header h)
return rc;
}

static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4)
static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4,
const char *name)
{
int rc = -1;
rpmtd sigtd = NULL;
int mode = name ? HEADERPUT_APPEND : HEADERPUT_DEFAULT;

/* Make the cheaper v4 signature first */
if ((sigtd = makeGPGSignature(sigh, 1, sigt_v4)) == NULL)
if ((sigtd = makeGPGSignature(sigh, 1, sigt_v4, name)) == NULL)
goto exit;

/* See if we already have a signature by the same key and parameters */
Expand All @@ -433,18 +464,22 @@ static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4)
goto exit;
}
/* Nuke all signature tags */
deleteSigs(sigh);
if (!name)
deleteSigs(sigh);

if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
if (headerPut(sigh, sigtd, mode) == 0)
goto exit;
rpmtdFree(sigtd);

/* Assume the same signature test holds for v3 signature too */
if ((sigtd = makeGPGSignature(sigh, 0, sigt_v3)) == NULL)
goto exit;
if (!name) {
rpmtdFree(sigtd);

if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
goto exit;
/* Assume the same signature test holds for v3 signature too */
if ((sigtd = makeGPGSignature(sigh, 0, sigt_v3, NULL)) == NULL)
goto exit;

if (headerPut(sigh, sigtd, mode) == 0)
goto exit;
}

rc = 0;
exit:
Expand Down Expand Up @@ -522,7 +557,7 @@ static int checkPkg(FD_t fd, char **msg)
* @param signfiles sign files if non-zero
* @return 0 on success, -1 on error
*/
static int rpmSign(const char *rpm, int deleting, int signfiles)
static int rpmSign(const char *rpm, int deleting, int signfiles, const char *name)
{
FD_t fd = NULL;
FD_t ofd = NULL;
Expand Down Expand Up @@ -596,7 +631,7 @@ static int rpmSign(const char *rpm, int deleting, int signfiles)
sigt_v4 = sigt_v3;
sigt_v4.size = headerSizeof(h, HEADER_MAGIC_YES);

res = replaceSignature(sigh, &sigt_v3, &sigt_v4);
res = replaceSignature(sigh, &sigt_v3, &sigt_v4, name);
if (res != 0) {
if (res == 1) {
rpmlog(RPMLOG_WARNING,
Expand Down Expand Up @@ -716,7 +751,7 @@ int rpmPkgSign(const char *path, const struct rpmSignArgs * args)
}
}

rc = rpmSign(path, 0, args ? args->signfiles : 0);
rc = rpmSign(path, 0, args ? args->signfiles : 0, args ? args->name : NULL);

if (args) {
if (args->hashalgo) {
Expand All @@ -732,5 +767,5 @@ int rpmPkgSign(const char *path, const struct rpmSignArgs * args)

int rpmPkgDelSign(const char *path, const struct rpmSignArgs * args)
{
return rpmSign(path, 1, 0);
return rpmSign(path, 1, 0, NULL);
}
1 change: 1 addition & 0 deletions sign/rpmsign.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct rpmSignArgs {
char *keyid;
pgpHashAlgo hashalgo;
int signfiles;
char *name;
/* ... what else? */
};

Expand Down
1 change: 1 addition & 0 deletions tests/rpmgeneral.at
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ OLDSUGGESTS
OLDSUGGESTSFLAGS
OLDSUGGESTSNAME
OLDSUGGESTSVERSION
OPENPGPHEADER
OPTFLAGS
ORDERFLAGS
ORDERNAME
Expand Down
Loading