예제 #1
0
/**
 * Remember current key id.
 * @param dig		container
 * @return		0 if new keyid, otherwise 1
 */
static int pgpStashKeyid(pgpDig dig)
	/*@globals nextkeyid, nkeyids, keyids @*/
	/*@modifies nextkeyid, nkeyids, keyids @*/
{
    pgpDigParams sigp = pgpGetSignature(dig);
    const void * sig = pgpGetSig(dig);
    unsigned int keyid;
    unsigned int i;

    if (sig == NULL || dig == NULL || sigp == NULL)
	return 0;

    keyid = pgpGrab(sigp->signid+4, 4);
    if (keyid == 0)
	return 0;

    if (keyids != NULL)
    for (i = 0; i < nkeyids; i++) {
	if (keyid == keyids[i])
	    return 1;
    }

    if (nkeyids < nkeyids_max) {
	nkeyids++;
	keyids = (unsigned int *) xrealloc(keyids, nkeyids * sizeof(*keyids));
    }
    if (keyids)		/* XXX can't happen */
	keyids[nextkeyid] = keyid;
    nextkeyid++;
    nextkeyid %= nkeyids_max;

    return 0;
}
예제 #2
0
/**
 * Remember current key id.
 * @param dig		OpenPGP packet containter
 * @return		0 if new keyid, otherwise 1
 */
static int stashKeyid(pgpDig dig)
{
    pgpDigParams sigp = dig ? &dig->signature : NULL;
    unsigned int keyid;
    int i;

    if (dig == NULL || sigp == NULL)
	return 0;

    keyid = pgpGrab(sigp->signid+4, 4);
    if (keyid == 0)
	return 0;

    if (keyids != NULL)
    for (i = 0; i < nkeyids; i++) {
	if (keyid == keyids[i])
	    return 1;
    }

    if (nkeyids < nkeyids_max) {
	nkeyids++;
	keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
    }
    if (keyids)		/* XXX can't happen */
	keyids[nextkeyid] = keyid;
    nextkeyid++;
    nextkeyid %= nkeyids_max;

    return 0;
}
예제 #3
0
파일: rpmpgp.c 프로젝트: crossbuild/rpm
/** \ingroup rpmpgp
 * Decode length from 1, 2, or 5 octet body length encoding, used in
 * new format packet headers and V4 signature subpackets.
 * @param s		pointer to length encoding buffer
 * @param slen		buffer size
 * @retval *lenp	decoded length
 * @return		no. of bytes used to encode the length, 0 on error
 */
static inline
size_t pgpLen(const uint8_t *s, size_t slen, size_t * lenp)
{
    size_t dlen = 0;
    size_t lenlen = 0;

    /*
     * Callers can only ensure we'll always have the first byte, beyond
     * that the required size is not known until we decode it so we need
     * to check if we have enough bytes to read the size as we go.
     */
    if (*s < 192) {
	lenlen = 1;
	dlen = *s;
    } else if (*s < 255 && slen > 2) {
	lenlen = 2;
	dlen = (((s[0]) - 192) << 8) + s[1] + 192;
    } else if (slen > 5) {
	lenlen = 5;
	dlen = pgpGrab(s+1, 4);
    }

    if (lenlen)
	*lenp = dlen;

    return lenlen;
}
예제 #4
0
파일: rpmpgp.c 프로젝트: crossbuild/rpm
/** \ingroup rpmpgp
 * Return hex formatted representation of a multiprecision integer.
 * @param p		bytes
 * @return		hex formatted string (malloc'ed)
 */
static inline
char * pgpMpiStr(const uint8_t *p)
{
    char *str = NULL;
    char *hex = pgpHexStr(p+2, pgpMpiLen(p)-2);
    rasprintf(&str, "[%4u]: %s", pgpGrab(p, (size_t) 2), hex);
    free(hex);
    return str;
}
예제 #5
0
rpmRC rpmkuFindPubkey(pgpDigParams sigp, /*@out@*/ rpmiob * iobp)
{
    if (iobp != NULL)
	*iobp = NULL;

#if defined(HAVE_KEYUTILS_H)
    if (_kuCache) {
/*@observer@*/
	static const char krprefix[] = "rpm:gpg:pubkey:";
	key_serial_t keyring = (key_serial_t) _kuKeyring;
	char krfp[32];
	char * krn = (char *) alloca(strlen(krprefix) + sizeof("12345678"));
	long key;
	int xx;

	(void) snprintf(krfp, sizeof(krfp), "%08X", pgpGrab(sigp->signid+4, 4));
	krfp[sizeof(krfp)-1] = '\0';
	*krn = '\0';
	(void) stpcpy( stpcpy(krn, krprefix), krfp);

	key = keyctl_search(keyring, "user", krn, 0);
	xx = keyctl_read(key, NULL, 0);
	if (xx > 0) {
	    rpmiob iob = rpmiobNew(xx);
	    xx = keyctl_read(key, (char *)iob->b, iob->blen);
	    if (xx > 0) {
#ifdef	NOTYET
		pubkeysource = xstrdup(krn);
		_kuCache = 0;	/* XXX don't bother caching. */
#endif
	    } else
		iob = rpmiobFree(iob);

	    if (iob != NULL && iobp != NULL) {
		*iobp = iob;
		return RPMRC_OK;
	    } else {
		iob = rpmiobFree(iob);
		return RPMRC_NOTFOUND;
	    }
	} else
	    return RPMRC_NOTFOUND;
    } else
#endif	/* HAVE_KEYUTILS_H */
    return RPMRC_NOTFOUND;
}
예제 #6
0
rpmRC rpmkuStorePubkey(pgpDigParams sigp, /*@only@*/ rpmiob iob)
{
#if defined(HAVE_KEYUTILS_H)
    if (_kuCache) {
/*@observer@*/
	static const char krprefix[] = "rpm:gpg:pubkey:";
	key_serial_t keyring = (key_serial_t) _kuKeyring;
	char krfp[32];
	char * krn = (char *) alloca(strlen(krprefix) + sizeof("12345678"));

	(void) snprintf(krfp, sizeof(krfp), "%08X", pgpGrab(sigp->signid+4, 4));
	krfp[sizeof(krfp)-1] = '\0';
	*krn = '\0';
	(void) stpcpy( stpcpy(krn, krprefix), krfp);
/*@-moduncon -noeffectuncon @*/
	(void) add_key("user", krn, iob->b, iob->blen, keyring);
/*@=moduncon =noeffectuncon @*/
    }
#endif	/* HAVE_KEYUTILS_H */
    iob = rpmiobFree(iob);
    return RPMRC_OK;
}
예제 #7
0
파일: formats.c 프로젝트: OlegGirko/rpm
/**
 * Display signature fingerprint and time.
 * @param td		tag data container
 * @return		formatted string
 */
static char * pgpsigFormat(rpmtd td)
{
    char * val = NULL;

    if (rpmtdType(td) != RPM_BIN_TYPE) {
	val = xstrdup(_("(not a blob)"));
    } else {
	pgpDigParams sigp = NULL;

	if (pgpPrtParams(td->data, td->count, PGPTAG_SIGNATURE, &sigp)) {
	    val = xstrdup(_("(not an OpenPGP signature)"));
	} else {
	    char dbuf[BUFSIZ];
	    char *keyid = pgpHexStr(sigp->signid, sizeof(sigp->signid));
	    unsigned int dateint = pgpGrab(sigp->time, sizeof(sigp->time));
	    time_t date = dateint;
	    struct tm * tms = localtime(&date);
	    unsigned int key_algo = pgpDigParamsAlgo(sigp, PGPVAL_PUBKEYALGO);
	    unsigned int hash_algo = pgpDigParamsAlgo(sigp, PGPVAL_HASHALGO);

	    if (!(tms && strftime(dbuf, sizeof(dbuf), "%c", tms) > 0)) {
		snprintf(dbuf, sizeof(dbuf),
			 _("Invalid date %u"), dateint);
		dbuf[sizeof(dbuf)-1] = '\0';
	    }

	    rasprintf(&val, "%s/%s, %s, Key ID %s",
			pgpValString(PGPVAL_PUBKEYALGO, key_algo),
			pgpValString(PGPVAL_HASHALGO, hash_algo),
			dbuf, keyid);

	    free(keyid);
	    pgpDigParamsFree(sigp);
	}
    }

    return val;
}
예제 #8
0
파일: package.c 프로젝트: Conan-Kudo/rpm
static unsigned int getKeyid(pgpDigParams sigp)
{
    return (sigp != NULL) ? pgpGrab(sigp->signid+4, 4) : 0;
}
예제 #9
0
rpmRC rpmnsProbeSignature(void * _ts, const char * fn, const char * sigfn,
		const char * pubfn, const char * pubid,
		/*@unused@*/ int flags)
{
    rpmts ts = (rpmts) _ts;
    pgpDig dig = rpmtsDig(ts);
    pgpDigParams sigp = pgpGetSignature(dig);
    pgpDigParams pubp = pgpGetPubkey(dig);
    rpmuint8_t * sigpkt = NULL;
    size_t sigpktlen = 0;
    DIGEST_CTX ctx = NULL;
    rpmRC rc = RPMRC_FAIL;	/* assume failure */
    int xx;
rpmhkp hkp = NULL;
pgpPkt pp = (pgpPkt) alloca(sizeof(*pp));
size_t pleft;
int validate = 1;

SPEW((stderr, "==> check(%s, %s, %s, %s)\n", fn,
	(sigfn ? sigfn : "(null)"),
	(pubfn ? pubfn : "(null)"),
	(pubid ? pubid : "(null)")));

    /* Choose signature location: clearsign from fn if sigfn is NULL */
assert(fn && *fn);
    if (!(sigfn && *sigfn))
	sigfn = fn;

    /* Load the signature from the file. */
    {	const char * _sigfn = rpmExpand(sigfn, NULL);
	xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen);
	if (xx != PGPARMOR_SIGNATURE) {
SPEW((stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, (unsigned)sigpktlen, xx));
	    _sigfn = _free(_sigfn);
	    goto exit;
	}
	_sigfn = _free(_sigfn);
    }

    pleft = sigpktlen;
    xx = pgpPktLen(sigpkt, pleft, pp);
    xx = rpmhkpLoadSignature(NULL, dig, pp);
    if (xx) goto exit;

    if (sigp->version != (rpmuint8_t)3 && sigp->version != (rpmuint8_t)4) {
SPEW((stderr, "==> unverifiable V%u\n", (unsigned)sigp->version));
	goto exit;
    }

    if (ts->hkp == NULL)
	ts->hkp = rpmhkpNew(NULL, 0);
    hkp = rpmhkpLink(ts->hkp);

    /* Load the pubkey. Use pubfn if specified, otherwise rpmdb keyring. */
    if (pubfn && *pubfn) {
	const char * _pubfn = rpmExpand(pubfn, NULL);
/*@-type@*/
hkp->pkt = _free(hkp->pkt);	/* XXX memleaks */
hkp->pktlen = 0;
	xx = pgpReadPkts(_pubfn, &hkp->pkt, &hkp->pktlen);
/*@=type@*/

	if (xx != PGPARMOR_PUBKEY) {
SPEW((stderr, "==> pgpReadPkts(%s) PUB %p[%u] rc %d\n", _pubfn, hkp->pkt, (unsigned)hkp->pktlen, xx));
	    _pubfn = _free(_pubfn);
	    goto exit;
	}
	_pubfn = _free(_pubfn);

	/* Split the result into packet array. */
hkp->pkts = _free(hkp->pkts);	/* XXX memleaks */
hkp->npkts = 0;
	xx = pgpGrabPkts(hkp->pkt, hkp->pktlen, &hkp->pkts, &hkp->npkts);

#ifdef	DYING
_rpmhkpDumpDig(__FUNCTION__, dig, NULL);
#endif

	if (!xx)
	    (void) pgpPubkeyFingerprint(hkp->pkt, hkp->pktlen, hkp->keyid);
	memcpy(pubp->signid, hkp->keyid, sizeof(pubp->signid));/* XXX useless */

	/* Validate pubkey self-signatures (if any). */
	/* XXX TODO: only validate once, then cache using rpmku */
	/* XXX need at least 3 packets to validate a pubkey */
	if (validate && hkp->npkts >= 3) {
#ifdef	DYING
pgpPrtPkts(hkp->pkt, hkp->pktlen, NULL, 1);
#endif
	    xx = rpmhkpValidate(hkp, NULL);
	    switch (xx) {
	    case RPMRC_OK:
		break;
	    case RPMRC_NOTFOUND:
	    case RPMRC_FAIL:	/* XXX remap to NOTFOUND? */
	    case RPMRC_NOTTRUSTED:
	    case RPMRC_NOKEY:
	    default:
SPEW((stderr, "\t<-- rpmhkpValidate() rc %d\n", xx));
		rc = (rpmRC)xx;
		goto exit;
	    }
	}

	/* Retrieve parameters from pubkey/subkey packet(s). */
	xx = rpmhkpFindKey(hkp, dig, sigp->signid, sigp->pubkey_algo);
	if (xx) {
SPEW((stderr, "\t<-- rpmhkpFindKey() rc %d\n", xx));
	    goto exit;
	}

    } else {
	rc = (rpmRC)pgpFindPubkey(dig);
	if (rc != RPMRC_OK) {
SPEW((stderr, "\t<-- pgpFindPubkey() rc %d\n", rc));
	    goto exit;
	}
    }

    /* Is this the requested pubkey? */
    if (pubid && *pubid) {
	size_t ns = strlen(pubid);
	const char * s;
	char * t;
	size_t i;

	/* At least 8 hex digits please. */
	for (i = 0, s = pubid; *s && isxdigit(*s); s++, i++)
	    {};
	if (!(*s == '\0' && i > 8 && (i%2) == 0)) {
SPEW((stderr, "==> invalid pubid:  %s\n", pubid));
	    goto exit;
	}

	/* Truncate to key id size. */
	s = pubid;
	if (ns > 16) {
	    s += (ns - 16);
	    ns = 16;
	}
	ns >>= 1;
	t = (char *) memset(alloca(ns), 0, ns);
	for (i = 0; i < ns; i++)
	    t[i] = (char)((nibble(s[2*i]) << 4) | nibble(s[2*i+1]));

	/* Compare the pubkey id. */
	s = (const char *)pubp->signid;
	xx = memcmp(t, s + (8 - ns), ns);

#ifdef	DYING
	/* XXX HACK: V4 RSA key id's are wonky atm. */
	if (pubp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA)
	    xx = 0;
#endif

	if (xx) {
SPEW((stderr, "==> mismatched: pubkey id (%08x %08x) != %s\n",
pgpGrab(pubp->signid, 4), pgpGrab(pubp->signid+4, 4), pubid));
	    goto exit;
	}
    }
예제 #10
0
파일: rpmvs.c 프로젝트: junaruga/rpm
static rpmRC rpmsinfoInit(rpmtd td, const char *origin,
		      struct rpmsinfo_s *sinfo, char **msg)
{
    rpmRC rc = RPMRC_FAIL;
    const void *data = NULL;
    const struct vfytag_s *tinfo;
    const struct vfyinfo_s *vinfo;
    rpm_count_t dlen = 0;
    int ix;

    if ((ix = sinfoLookup(td->tag)) == -1) {
	/* anything unknown just falls through for now */
	rc = RPMRC_OK;
	goto exit;
    }
    vinfo = &rpmvfyitems[ix];
    tinfo = &rpmvfytags[ix];
    assert(tinfo->tag == vinfo->tag);

    *sinfo = rpmvfyitems[ix].vi; /* struct assignment */

    if (tinfo->tagtype && tinfo->tagtype != td->type) {
	rasprintf(msg, _("%s tag %u: invalid type %u"),
			origin, td->tag, td->type);
	goto exit;
    }

    if (tinfo->tagcount && tinfo->tagcount != td->count) {
	rasprintf(msg, _("%s: tag %u: invalid count %u"),
			origin, td->tag, td->count);
	goto exit;
    }

    switch (td->type) {
    case RPM_STRING_TYPE:
    case RPM_STRING_ARRAY_TYPE:
	data = rpmtdGetString(td);
	if (data)
	    dlen = strlen(data);
	break;
    case RPM_BIN_TYPE:
	data = td->data;
	dlen = td->count;
	break;
    }

    /* MD5 has data length of 16, everything else is (much) larger */
    if (sinfo->hashalgo && (data == NULL || dlen < 16)) {
	rasprintf(msg, _("%s tag %u: invalid data %p (%u)"),
			origin, td->tag, data, dlen);
	goto exit;
    }

    if (td->type == RPM_STRING_TYPE && td->size == 0)
	td->size = dlen + 1;

    if (tinfo->tagsize && (td->flags & RPMTD_IMMUTABLE) &&
		tinfo->tagsize != td->size) {
	rasprintf(msg, _("%s tag %u: invalid size %u"),
			origin, td->tag, td->size);
	goto exit;
    }

    if (sinfo->type == RPMSIG_SIGNATURE_TYPE) {
	if (pgpPrtParams(data, dlen, PGPTAG_SIGNATURE, &sinfo->sig)) {
	    rasprintf(msg, _("%s tag %u: invalid OpenPGP signature"),
		    origin, td->tag);
	    goto exit;
	}
	sinfo->hashalgo = pgpDigParamsAlgo(sinfo->sig, PGPVAL_HASHALGO);
	sinfo->keyid = pgpGrab(sinfo->sig->signid+4, 4);
    } else if (sinfo->type == RPMSIG_DIGEST_TYPE) {
	if (td->type == RPM_BIN_TYPE) {
	    sinfo->dig = pgpHexStr(data, dlen);
	} else {
	    if (!validHex(data, dlen)) {
		rasprintf(msg, _("%s: tag %u: invalid hex"), origin, td->tag);
		goto exit;
	    }
	    sinfo->dig = xstrdup(data);
	}
    }

    if (sinfo->hashalgo)
	sinfo->id = (td->tag << 16) | rpmtdGetIndex(td);

    rc = RPMRC_OK;

exit:
    return rc;
}
예제 #11
0
파일: rpmts.c 프로젝트: OlegGirko/rpm
/* Build pubkey header. */
static int makePubkeyHeader(rpmts ts, rpmPubkey key, Header * hdrp)
{
    Header h = headerNew();
    const char * afmt = "%{pubkeys:armor}";
    const char * group = "Public Keys";
    const char * license = "pubkey";
    const char * buildhost = "localhost";
    const char * userid;
    rpmsenseFlags pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL);
    uint32_t zero = 0;
    uint32_t keytime = 0;
    pgpDig dig = NULL;
    pgpDigParams pubp = NULL;
    char * d = NULL;
    char * enc = NULL;
    char * n = NULL;
    char * u = NULL;
    char * v = NULL;
    char * r = NULL;
    char * evr = NULL;
    int rc = -1;

    if ((enc = rpmPubkeyBase64(key)) == NULL)
	goto exit;
    if ((dig = rpmPubkeyDig(key)) == NULL)
	goto exit;
    if ((pubp = pgpDigGetParams(dig, PGPTAG_PUBLIC_KEY)) == NULL)
	goto exit;

    /* Build header elements. */
    v = pgpHexStr(pubp->signid, sizeof(pubp->signid)); 
    r = pgpHexStr(pubp->time, sizeof(pubp->time));
    userid = pubp->userid ? pubp->userid : "none";
    keytime = pgpGrab(pubp->time, sizeof(pubp->time));

    rasprintf(&n, "gpg(%s)", v+8);
    rasprintf(&u, "gpg(%s)", userid);
    rasprintf(&evr, "%d:%s-%s", pubp->version, v, r);

    headerPutString(h, RPMTAG_PUBKEYS, enc);

    if ((d = headerFormat(h, afmt, NULL)) == NULL)
	goto exit;

    headerPutString(h, RPMTAG_NAME, "gpg-pubkey");
    headerPutString(h, RPMTAG_VERSION, v+8);
    headerPutString(h, RPMTAG_RELEASE, r);
    headerPutString(h, RPMTAG_DESCRIPTION, d);
    headerPutString(h, RPMTAG_GROUP, group);
    headerPutString(h, RPMTAG_LICENSE, license);
    headerPutString(h, RPMTAG_SUMMARY, u);
    headerPutString(h, RPMTAG_PACKAGER, userid);

    headerPutUint32(h, RPMTAG_SIZE, &zero, 1);

    headerPutString(h, RPMTAG_PROVIDENAME, u);
    headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
    headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1);
	
    headerPutString(h, RPMTAG_PROVIDENAME, n);
    headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
    headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1);

    headerPutString(h, RPMTAG_RPMVERSION, RPMVERSION);
    headerPutString(h, RPMTAG_BUILDHOST, buildhost);
    headerPutUint32(h, RPMTAG_BUILDTIME, &keytime, 1);
    headerPutString(h, RPMTAG_SOURCERPM, "(none)");

    /* Reload the lot to immutable region and stomp sha1 digest on it */
    h = headerReload(h, RPMTAG_HEADERIMMUTABLE);
    if (h != NULL) {
	char *sha1 = NULL;
	unsigned int blen = 0;
	const void *blob = headerExport(h, &blen);

	/* XXX FIXME: bah, this code is repeated in way too many places */
	DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
	rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic));
	rpmDigestUpdate(ctx, blob, blen);
	rpmDigestFinal(ctx, (void **)&sha1, NULL, 1);

	if (sha1) {
	    headerPutString(h, RPMTAG_SHA1HEADER, sha1);
	    *hdrp = headerLink(h);
	    rc = 0;
	}
	free(sha1);
    }

exit:
    headerFree(h);
    pgpFreeDig(dig);
    free(n);
    free(u);
    free(v);
    free(r);
    free(evr);
    free(enc);
    free(d);

    return rc;
}