From 56b3772145de71568a14366f55ffa83a5b507dac Mon Sep 17 00:00:00 2001 From: jbj Date: Tue, 3 Sep 2002 20:15:20 +0000 Subject: - fix: parse pgp packets more carefully. CVS patchset: 5699 CVS date: 2002/09/03 20:15:20 --- rpmio/rpmpgp.c | 57 +++++++++++++++++++++++++++++++++++++++++---------------- rpmio/rpmpgp.h | 11 ++++++----- 2 files changed, 47 insertions(+), 21 deletions(-) (limited to 'rpmio') diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c index c5b4681bd..3f301c326 100644 --- a/rpmio/rpmpgp.c +++ b/rpmio/rpmpgp.c @@ -321,17 +321,26 @@ const char * pgpMpiHex(const byte *p) /*@-boundswrite@*/ /** + * @return 0 on success */ -static void pgpHexSet(const char * pre, int lbits, - /*@out@*/ mp32number * mpn, const byte * p) +static int pgpHexSet(const char * pre, int lbits, + /*@out@*/ mp32number * mpn, const byte * p, const byte * pend) /*@globals fileSystem @*/ /*@modifies *mpn, fileSystem @*/ { unsigned int mbits = pgpMpiBits(p); - unsigned int nbits = (lbits > mbits ? lbits : mbits); - unsigned int nbytes = ((nbits + 7) >> 3); - char * t = xmalloc(2*nbytes+1); - unsigned int ix = 2 * ((nbits - mbits) >> 3); + unsigned int nbits; + unsigned int nbytes; + char * t; + unsigned int ix; + + if ((p + ((mbits+7) >> 3)) > pend) + return 1; + + nbits = (lbits > mbits ? lbits : mbits); + nbytes = ((nbits + 7) >> 3); + t = xmalloc(2*nbytes+1); + ix = 2 * ((nbits - mbits) >> 3); if (_debug) fprintf(stderr, "*** mbits %u nbits %u nbytes %u t %p[%d] ix %u\n", mbits, nbits, nbytes, t, (2*nbytes+1), ix); @@ -343,6 +352,7 @@ fprintf(stderr, "*** %s %s\n", pre, t); t = _free(t); if (_debug && _print) fprintf(stderr, "\t %s ", pre), mp32println(stderr, mpn->size, mpn->data); + return 0; } /*@=boundswrite@*/ @@ -460,9 +470,10 @@ static int pgpPrtSigParams(/*@unused@*/ pgpTag tag, byte pubkey_algo, byte sigty /*@globals fileSystem @*/ /*@modifies fileSystem @*/ { + const byte * pend = h + hlen; int i; - for (i = 0; p < &h[hlen]; i++, p += pgpMpiLen(p)) { + for (i = 0; p < pend; i++, p += pgpMpiLen(p)) { if (pubkey_algo == PGPPUBKEYALGO_RSA) { if (i >= 1) break; /*@-mods@*/ @@ -487,16 +498,20 @@ fprintf(stderr, "\t m**d = "), mp32println(stderr, _dig->c.size, _dig->c.data) if (_dig && (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT)) { + int xx; + xx = 0; switch (i) { case 0: /* r */ - pgpHexSet(pgpSigDSA[i], 160, &_dig->r, p); + xx = pgpHexSet(pgpSigDSA[i], 160, &_dig->r, p, pend); /*@switchbreak@*/ break; case 1: /* s */ - pgpHexSet(pgpSigDSA[i], 160, &_dig->s, p); + xx = pgpHexSet(pgpSigDSA[i], 160, &_dig->s, p, pend); /*@switchbreak@*/ break; default: + xx = 1; /*@switchbreak@*/ break; } + if (xx) return xx; } /*@=mods@*/ pgpPrtStr("", pgpSigDSA[i]); @@ -523,10 +538,8 @@ int pgpPrtSig(pgpTag tag, const byte *h, unsigned int hlen) { pgpPktSigV3 v = (pgpPktSigV3)h; time_t t; - if (v->hashlen != 5) { - fprintf(stderr, " hashlen(%u) != 5\n", (unsigned)v->hashlen); + if (v->hashlen != 5) return 1; - } pgpPrtVal("V3 ", pgpTagTbl, tag); pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo); @@ -572,6 +585,9 @@ int pgpPrtSig(pgpTag tag, const byte *h, unsigned int hlen) plen = pgpGrab(v->hashlen, sizeof(v->hashlen)); p += sizeof(v->hashlen); + if ((p + plen) > (h + hlen)) + return 1; + if (_debug && _print) fprintf(stderr, " hash[%u] -- %s\n", plen, pgpHexStr(p, plen)); /*@-mods@*/ @@ -586,6 +602,9 @@ fprintf(stderr, " hash[%u] -- %s\n", plen, pgpHexStr(p, plen)); plen = pgpGrab(p,2); p += 2; + if ((p + plen) > (h + hlen)) + return 1; + if (_debug && _print) fprintf(stderr, " unhash[%u] -- %s\n", plen, pgpHexStr(p, plen)); (void) pgpPrtSubType(p, plen, v->sigtype); @@ -933,7 +952,7 @@ int pgpPrtComment(pgpTag tag, const byte *h, unsigned int hlen) return 0; } -int pgpPrtPkt(const byte *pkt) +int pgpPrtPkt(const byte *pkt, unsigned int pleft) { unsigned int val = *pkt; unsigned int pktlen; @@ -957,6 +976,9 @@ int pgpPrtPkt(const byte *pkt) } pktlen = 1 + plen + hlen; + if (pktlen > pleft) + return -1; + h = pkt + 1 + plen; switch (tag) { case PGPTAG_SIGNATURE: @@ -1097,10 +1119,11 @@ pgpDig pgpFreeDig(/*@only@*/ /*@null@*/ pgpDig dig) return dig; } -int pgpPrtPkts(const byte * pkts, unsigned int plen, pgpDig dig, int printing) +int pgpPrtPkts(const byte * pkts, unsigned int pktlen, pgpDig dig, int printing) { unsigned int val = *pkts; const byte *p; + unsigned int pleft; int len; /*@-mods@*/ @@ -1114,10 +1137,12 @@ int pgpPrtPkts(const byte * pkts, unsigned int plen, pgpDig dig, int printing) _digp = NULL; /*@=mods@*/ - for (p = pkts; p < (pkts + plen); p += len) { - len = pgpPrtPkt(p); + for (p = pkts, pleft = pktlen; p < (pkts + pktlen); p += len, pleft -= len) { + len = pgpPrtPkt(p, pleft); if (len <= 0) return len; + if (len > pleft) /* XXX shouldn't happen */ + break; } return 0; } diff --git a/rpmio/rpmpgp.h b/rpmio/rpmpgp.h index 05d238c54..04e37688c 100644 --- a/rpmio/rpmpgp.h +++ b/rpmio/rpmpgp.h @@ -1196,11 +1196,12 @@ int pgpPrtComment(pgpTag tag, const byte *h, unsigned int hlen) /*@modifies fileSystem @*/; /** - * Print/parse a single OpenPGP packet. + * Print/parse next OpenPGP packet. * @param pkt OpenPGP packet - * @return -1 on error, otherwise packet length + * @param pleft no. bytes remaining + * @return -1 on error, otherwise this packet length */ -int pgpPrtPkt(const byte *pkt) +int pgpPrtPkt(const byte *pkt, unsigned int pleft) /*@globals fileSystem @*/ /*@modifies fileSystem @*/; /*@=exportlocal@*/ @@ -1208,12 +1209,12 @@ int pgpPrtPkt(const byte *pkt) /** * Print/parse a OpenPGP packet(s). * @param pkts OpenPGP packet(s) - * @param plen packet(s) length (no. of bytes) + * @param pktlen OpenPGP packet(s) length (no. of bytes) * @retval dig parsed output of signature/pubkey packet parameters * @param printing should packets be printed? * @return -1 on error, 0 on success */ -int pgpPrtPkts(const byte *pkts, unsigned int plen, pgpDig dig, int printing) +int pgpPrtPkts(const byte *pkts, unsigned int pktlen, pgpDig dig, int printing) /*@globals fileSystem @*/ /*@modifies fileSystem @*/; -- cgit v1.2.3