Main Page Modules Data Structures File List Data Fields Globals Related Pages

# lib/package.c

Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include <netinet/in.h>
    00008
    00009 #include <rpmio_internal.h>
    00010 #include <rpmlib.h>
    00011
    00012 #include "rpmts.h"
    00013
    00014 #include "misc.h"       /* XXX stripTrailingChar() */
    00015 #include "legacy.h"     /* XXX providePackageNVR() and compressFileList() */
    00016 #include "rpmlead.h"
    00017
    00018 #include "header_internal.h"    /* XXX headerCheck */
    00019 #include "signature.h"
    00020 #include "debug.h"
    00021
    00022 #define alloca_strdup(_s)       strcpy(alloca(strlen(_s)+1), (_s))
    00023
    00024 /*@access pgpDig @*/
    00025 /*@access pgpDigParams @*/
    00026 /*@access rpmts @*/
    00027 /*@access Header @*/            /* XXX compared with NULL */
    00028 /*@access entryInfo @*/         /* XXX headerCheck */
    00029 /*@access indexEntry @*/        /* XXX headerCheck */
    00030 /*@access FD_t @*/              /* XXX stealing digests */
    00031
    00032 /*@unchecked@*/
    00033 static int _print_pkts = 0;
    00034
    00035 /*@unchecked@*/
    00036 static unsigned int nkeyids_max = 256;
    00037 /*@unchecked@*/
    00038 static unsigned int nkeyids = 0;
    00039 /*@unchecked@*/
    00040 static unsigned int nextkeyid  = 0;
    00041 /*@unchecked@*/ /*@only@*/ /*@null@*/
    00042 static unsigned int * keyids;
    00043
    00044 /*@unchecked@*/
    00045 static unsigned char header_magic[8] = {
    00046         0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
    00047 };
    00048
    00052 /*@observer@*/ /*@unchecked@*/
    00053 static int typeAlign[16] =  {
    00054     1,
    00055     1,
    00056     1,
    00057     2,
    00058     4,
    00059     8,
    00060     1,
    00061     1,
    00062     1,
    00063     1,
    00064     0,
    00065     0,
    00066     0,
    00067     0,
    00068     0,
    00069     0
    00070 };
    00071
    00076 #define hdrchkTags(_ntags)      ((_ntags) & 0xffff0000)
    00077
    00081 #define hdrchkType(_type) ((_type) < RPM_MIN_TYPE || (_type) > RPM_MAX_TYPE)
    00082
    00087 #define hdrchkData(_nbytes) ((_nbytes) & 0xff000000)
    00088
    00092 #define hdrchkAlign(_type, _off)        ((_off) & (typeAlign[_type]-1))
    00093
    00097 #define hdrchkRange(_dl, _off)          ((_off) < 0 || (_off) > (_dl))
    00098
    00099 void headerMergeLegacySigs(Header h, const Header sigh)
    00100 {
    00101     HFD_t hfd = (HFD_t) headerFreeData;
    00102     HAE_t hae = (HAE_t) headerAddEntry;
    00103     HeaderIterator hi;
    00104     int_32 tag, type, count;
    00105     const void * ptr;
    00106     int xx;
    00107
    00108     for (hi = headerInitIterator(sigh);
    00109         headerNextIterator(hi, &tag, &type, &ptr, &count);
    00110         ptr = hfd(ptr, type))
    00111     {
    00112         switch (tag) {
    00113         /* XXX Translate legacy signature tag values. */
    00114         case RPMSIGTAG_SIZE:
    00115             tag = RPMTAG_SIGSIZE;
    00116             /*@switchbreak@*/ break;
    00117         case RPMSIGTAG_LEMD5_1:
    00118             tag = RPMTAG_SIGLEMD5_1;
    00119             /*@switchbreak@*/ break;
    00120         case RPMSIGTAG_PGP:
    00121             tag = RPMTAG_SIGPGP;
    00122             /*@switchbreak@*/ break;
    00123         case RPMSIGTAG_LEMD5_2:
    00124             tag = RPMTAG_SIGLEMD5_2;
    00125             /*@switchbreak@*/ break;
    00126         case RPMSIGTAG_MD5:
    00127             tag = RPMTAG_SIGMD5;
    00128             /*@switchbreak@*/ break;
    00129         case RPMSIGTAG_GPG:
    00130             tag = RPMTAG_SIGGPG;
    00131             /*@switchbreak@*/ break;
    00132         case RPMSIGTAG_PGP5:
    00133             tag = RPMTAG_SIGPGP5;
    00134             /*@switchbreak@*/ break;
    00135         case RPMSIGTAG_PAYLOADSIZE:
    00136             tag = RPMTAG_ARCHIVESIZE;
    00137             /*@switchbreak@*/ break;
    00138         case RPMSIGTAG_SHA1:
    00139         case RPMSIGTAG_DSA:
    00140         case RPMSIGTAG_RSA:
    00141         default:
    00142             if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
    00143                 continue;
    00144             /*@switchbreak@*/ break;
    00145         }
    00146         if (ptr == NULL) continue;      /* XXX can't happen */
    00147         if (!headerIsEntry(h, tag)) {
    00148             if (hdrchkType(type))
    00149                 continue;
    00150             if (count < 0 || hdrchkData(count))
    00151                 continue;
    00152             switch(type) {
    00153             case RPM_NULL_TYPE:
    00154                 continue;
    00155                 /*@notreached@*/ /*@switchbreak@*/ break;
    00156             case RPM_CHAR_TYPE:
    00157             case RPM_INT8_TYPE:
    00158             case RPM_INT16_TYPE:
    00159             case RPM_INT32_TYPE:
    00160                 if (count != 1)
    00161                     continue;
    00162                 /*@switchbreak@*/ break;
    00163             case RPM_STRING_TYPE:
    00164             case RPM_BIN_TYPE:
    00165                 if (count >= 16*1024)
    00166                     continue;
    00167                 /*@switchbreak@*/ break;
    00168             case RPM_STRING_ARRAY_TYPE:
    00169             case RPM_I18NSTRING_TYPE:
    00170                 continue;
    00171                 /*@notreached@*/ /*@switchbreak@*/ break;
    00172             }
    00173             xx = hae(h, tag, type, ptr, count);
    00174         }
    00175     }
    00176     hi = headerFreeIterator(hi);
    00177 }
    00178
    00179 Header headerRegenSigHeader(const Header h, int noArchiveSize)
    00180 {
    00181     HFD_t hfd = (HFD_t) headerFreeData;
    00182     Header sigh = rpmNewSignature();
    00183     HeaderIterator hi;
    00184     int_32 tag, stag, type, count;
    00185     const void * ptr;
    00186     int xx;
    00187
    00188     for (hi = headerInitIterator(h);
    00189         headerNextIterator(hi, &tag, &type, &ptr, &count);
    00190         ptr = hfd(ptr, type))
    00191     {
    00192         switch (tag) {
    00193         /* XXX Translate legacy signature tag values. */
    00194         case RPMTAG_SIGSIZE:
    00195             stag = RPMSIGTAG_SIZE;
    00196             /*@switchbreak@*/ break;
    00197         case RPMTAG_SIGLEMD5_1:
    00198             stag = RPMSIGTAG_LEMD5_1;
    00199             /*@switchbreak@*/ break;
    00200         case RPMTAG_SIGPGP:
    00201             stag = RPMSIGTAG_PGP;
    00202             /*@switchbreak@*/ break;
    00203         case RPMTAG_SIGLEMD5_2:
    00204             stag = RPMSIGTAG_LEMD5_2;
    00205             /*@switchbreak@*/ break;
    00206         case RPMTAG_SIGMD5:
    00207             stag = RPMSIGTAG_MD5;
    00208             /*@switchbreak@*/ break;
    00209         case RPMTAG_SIGGPG:
    00210             stag = RPMSIGTAG_GPG;
    00211             /*@switchbreak@*/ break;
    00212         case RPMTAG_SIGPGP5:
    00213             stag = RPMSIGTAG_PGP5;
    00214             /*@switchbreak@*/ break;
    00215         case RPMTAG_ARCHIVESIZE:
    00216             /* XXX rpm-4.1 and later has archive size in signature header. */
    00217             if (noArchiveSize)
    00218                 continue;
    00219             stag = RPMSIGTAG_PAYLOADSIZE;
    00220             /*@switchbreak@*/ break;
    00221         case RPMTAG_SHA1HEADER:
    00222         case RPMTAG_DSAHEADER:
    00223         case RPMTAG_RSAHEADER:
    00224         default:
    00225             if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
    00226                 continue;
    00227             stag = tag;
    00228             /*@switchbreak@*/ break;
    00229         }
    00230         if (ptr == NULL) continue;      /* XXX can't happen */
    00231         if (!headerIsEntry(sigh, stag))
    00232             xx = headerAddEntry(sigh, stag, type, ptr, count);
    00233     }
    00234     hi = headerFreeIterator(hi);
    00235     return sigh;
    00236 }
    00237
    00243 static int rpmtsStashKeyid(rpmts ts)
    00244         /*@globals nkeyids, keyids @*/
    00245         /*@modifies nkeyids, keyids @*/
    00246 {
    00247     const void * sig = rpmtsSig(ts);
    00248     pgpDig dig = rpmtsDig(ts);
    00249     pgpDigParams sigp = rpmtsSignature(ts);
    00250     unsigned int keyid;
    00251     int i;
    00252
    00253     if (sig == NULL || dig == NULL || sigp == NULL)
    00254         return 0;
    00255
    00256     keyid = pgpGrab(sigp->signid+4, 4);
    00257     if (keyid == 0)
    00258         return 0;
    00259
    00260     if (keyids != NULL)
    00261     for (i = 0; i < nkeyids; i++) {
    00262 /*@-boundsread@*/
    00263         if (keyid == keyids[i])
    00264             return 1;
    00265 /*@=boundsread@*/
    00266     }
    00267
    00268     if (nkeyids < nkeyids_max) {
    00269         nkeyids++;
    00270         keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
    00271     }
    00272 /*@-boundswrite@*/
    00273     keyids[nextkeyid] = keyid;
    00274 /*@=boundswrite@*/
    00275     nextkeyid++;
    00276     nextkeyid %= nkeyids_max;
    00277
    00278     return 0;
    00279 }
    00280
    00281 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
    00282 {
    00283     entryInfo pe = (entryInfo) pev;
    00284     entryInfo info = iv;
    00285     int i;
    00286
    00287 /*@-boundsread@*/
    00288     for (i = 0; i < il; i++) {
    00289         info->tag = ntohl(pe[i].tag);
    00290         info->type = ntohl(pe[i].type);
    00291         info->offset = ntohl(pe[i].offset);
    00292         if (negate)
    00293             info->offset = -info->offset;
    00294         info->count = ntohl(pe[i].count);
    00295
    00296         if (hdrchkType(info->type))
    00297             return i;
    00298         if (hdrchkAlign(info->type, info->offset))
    00299             return i;
    00300         if (!negate && hdrchkRange(dl, info->offset))
    00301             return i;
    00302         if (hdrchkData(info->count))
    00303             return i;
    00304
    00305     }
    00306 /*@=boundsread@*/
    00307     return -1;
    00308 }
    00309
    00323 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg)
    00324 {
    00325     pgpDig dig;
    00326     unsigned char buf[8*BUFSIZ];
    00327     int_32 * ei = (int_32 *) uh;
    00328 /*@-boundsread@*/
    00329     int_32 il = ntohl(ei[0]);
    00330     int_32 dl = ntohl(ei[1]);
    00331 /*@-castexpose@*/
    00332     entryInfo pe = (entryInfo) &ei[2];
    00333 /*@=castexpose@*/
    00334 /*@=boundsread@*/
    00335     int_32 ildl[2];
    00336     int_32 pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
    00337     unsigned char * dataStart = (unsigned char *) (pe + il);
    00338     indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
    00339     entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
    00340     const void * sig = NULL;
    00341     const char * b;
    00342     rpmVSFlags vsflags = rpmtsVSFlags(ts);
    00343     int siglen = 0;
    00344     int blen;
    00345     size_t nb;
    00346     int_32 ril = 0;
    00347     unsigned char * end = NULL;
    00348     rpmRC rc = RPMRC_FAIL;      /* assume failure */
    00349     int xx;
    00350     int i;
    00351
    00352     buf[0] = '\0';
    00353
    00354     /* Is the blob the right size? */
    00355     if (uc > 0 && pvlen != uc) {
    00356         sprintf(buf, _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
    00357                         uc, il, dl);
    00358         goto exit;
    00359     }
    00360
    00361     /* Check (and convert) the 1st tag element. */
    00362     xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
    00363     if (xx != -1) {
    00364         sprintf(buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
    00365                 0, entry->info.tag, entry->info.type,
    00366                 entry->info.offset, entry->info.count);
    00367         goto exit;
    00368     }
    00369
    00370     /* Is there an immutable header region tag? */
    00371 /*@-sizeoftype@*/
    00372     if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
    00373        && entry->info.type == RPM_BIN_TYPE
    00374        && entry->info.count == REGION_TAG_COUNT))
    00375     {
    00376         rc = RPMRC_NOTFOUND;
    00377         goto exit;
    00378     }
    00379 /*@=sizeoftype@*/
    00380
    00381     /* Is there an immutable header region tag trailer? */
    00382     end = dataStart + entry->info.offset;
    00383 /*@-bounds@*/
    00384     (void) memcpy(info, end, entry->info.count);
    00385 /*@=bounds@*/
    00386     end += entry->info.count;
    00387
    00388 /*@-sizeoftype@*/
    00389     xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
    00390     if (xx != -1 ||
    00391         !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
    00392        && entry->info.type == RPM_BIN_TYPE
    00393        && entry->info.count == REGION_TAG_COUNT))
    00394     {
    00395         sprintf(buf,
    00396                 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
    00397                 entry->info.tag, entry->info.type,
    00398                 entry->info.offset, entry->info.count);
    00399         goto exit;
    00400     }
    00401 /*@=sizeoftype@*/
    00402 /*@-boundswrite@*/
    00403     memset(info, 0, sizeof(*info));
    00404 /*@=boundswrite@*/
    00405
    00406     /* Is the no. of tags in the region less than the total no. of tags? */
    00407     ril = entry->info.offset/sizeof(*pe);
    00408     if (ril > il) {
    00409         sprintf(buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
    00410         goto exit;
    00411     }
    00412
    00413     /* Find a header-only digest/signature tag. */
    00414     for (i = ril; i < il; i++) {
    00415         xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
    00416         if (xx != -1) {
    00417             sprintf(buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
    00418                 i, entry->info.tag, entry->info.type,
    00419                 entry->info.offset, entry->info.count);
    00420             goto exit;
    00421         }
    00422
    00423         switch (entry->info.tag) {
    00424         case RPMTAG_SHA1HEADER:
    00425             if (vsflags & RPMVSF_NOSHA1HEADER)
    00426                 /*@switchbreak@*/ break;
    00427             blen = 0;
    00428 /*@-boundsread@*/
    00429             for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
    00430                 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
    00431                     /*@innerbreak@*/ break;
    00432                 blen++;
    00433             }
    00434             if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
    00435                 goto exit;
    00436 /*@=boundsread@*/
    00437             if (info->tag == 0) {
    00438 /*@-boundswrite@*/
    00439                 *info = entry->info;    /* structure assignment */
    00440 /*@=boundswrite@*/
    00441                 siglen = blen + 1;
    00442             }
    00443             /*@switchbreak@*/ break;
    00444 #ifdef  NOTYET
    00445         case RPMTAG_RSAHEADER:
    00446 #endif
    00447         case RPMTAG_DSAHEADER:
    00448             if (vsflags & RPMVSF_NODSAHEADER)
    00449                 /*@switchbreak@*/ break;
    00450             if (entry->info.type != RPM_BIN_TYPE)
    00451                 goto exit;
    00452 /*@-boundswrite@*/
    00453             *info = entry->info;        /* structure assignment */
    00454 /*@=boundswrite@*/
    00455             siglen = info->count;
    00456             /*@switchbreak@*/ break;
    00457         default:
    00458             /*@switchbreak@*/ break;
    00459         }
    00460     }
    00461     rc = RPMRC_NOTFOUND;
    00462
    00463 exit:
    00464     /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
    00465     if (rc != RPMRC_NOTFOUND) {
    00466         if (msg) *msg = xstrdup(buf);
    00467         return rc;
    00468     }
    00469
    00470     /* If no header-only digest/signature, then do simple sanity check. */
    00471     if (info->tag == 0) {
    00472 verifyinfo_exit:
    00473         xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
    00474         if (xx != -1) {
    00475             sprintf(buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
    00476                 xx+1, entry->info.tag, entry->info.type,
    00477                 entry->info.offset, entry->info.count);
    00478             rc = RPMRC_FAIL;
    00479         } else {
    00480             sprintf(buf, "Header sanity check: OK\n");
    00481             rc = RPMRC_OK;
    00482         }
    00483         if (msg) *msg = xstrdup(buf);
    00484         return rc;
    00485     }
    00486
    00487     /* Verify header-only digest/signature. */
    00488     dig = rpmtsDig(ts);
    00489     if (dig == NULL)
    00490         goto verifyinfo_exit;
    00491     dig->nbytes = 0;
    00492
    00493 /*@-boundsread@*/
    00494     sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
    00495 /*@=boundsread@*/
    00496     (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
    00497
    00498     switch (info->tag) {
    00499 #ifdef  NOTYET
    00500     case RPMTAG_RSAHEADER:
    00501         /* Parse the parameters from the OpenPGP packets that will be needed. */
    00502         xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
    00503         /* XXX only V3 signatures for now. */
    00504         if (dig->signature.version != 3) {
    00505             rpmMessage(RPMMESS_WARNING,
    00506                 _("only V3 signatures can be verified, skipping V%u signature\n"),
    00507                 dig->signature.version);
    00508             rpmtsCleanDig(ts);
    00509             goto verifyinfo_exit;
    00510         }
    00511
    00512         ildl[0] = htonl(ril);
    00513         ildl[1] = (end - dataStart);
    00514         ildl[1] = htonl(ildl[1]);
    00515
    00516         dig->hdrmd5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
    00517
    00518         b = (unsigned char *) header_magic;
    00519         nb = sizeof(header_magic);
    00520         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
    00521         dig->nbytes += nb;
    00522
    00523         b = (unsigned char *) ildl;
    00524         nb = sizeof(ildl);
    00525         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
    00526         dig->nbytes += nb;
    00527
    00528         b = (unsigned char *) pe;
    00529         nb = (htonl(ildl[0]) * sizeof(*pe));
    00530         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
    00531         dig->nbytes += nb;
    00532
    00533         b = (unsigned char *) dataStart;
    00534         nb = htonl(ildl[1]);
    00535         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
    00536         dig->nbytes += nb;
    00537
    00538         break;
    00539 #endif
    00540     case RPMTAG_DSAHEADER:
    00541         /* Parse the parameters from the OpenPGP packets that will be needed. */
    00542         xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
    00543         /* XXX only V3 signatures for now. */
    00544         if (dig->signature.version != 3) {
    00545             rpmMessage(RPMMESS_WARNING,
    00546                 _("only V3 signatures can be verified, skipping V%u signature\n"),
    00547                 dig->signature.version);
    00548             rpmtsCleanDig(ts);
    00549             goto verifyinfo_exit;
    00550         }
    00551         /*@fallthrough@*/
    00552     case RPMTAG_SHA1HEADER:
    00553 /*@-boundswrite@*/
    00554         ildl[0] = htonl(ril);
    00555         ildl[1] = (end - dataStart);
    00556         ildl[1] = htonl(ildl[1]);
    00557 /*@=boundswrite@*/
    00558
    00559         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
    00560
    00561         b = (unsigned char *) header_magic;
    00562         nb = sizeof(header_magic);
    00563         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
    00564         dig->nbytes += nb;
    00565
    00566         b = (unsigned char *) ildl;
    00567         nb = sizeof(ildl);
    00568         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
    00569         dig->nbytes += nb;
    00570
    00571         b = (unsigned char *) pe;
    00572         nb = (htonl(ildl[0]) * sizeof(*pe));
    00573         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
    00574         dig->nbytes += nb;
    00575
    00576         b = (unsigned char *) dataStart;
    00577         nb = htonl(ildl[1]);
    00578         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
    00579         dig->nbytes += nb;
    00580
    00581         break;
    00582     default:
    00583         break;
    00584     }
    00585
    00586 /*@-boundswrite@*/
    00587     buf[0] = '\0';
    00588 /*@=boundswrite@*/
    00589     rc = rpmVerifySignature(ts, buf);
    00590
    00591 /*@-boundswrite@*/
    00592     if (msg != NULL)
    00593         *msg = xstrdup(buf);
    00594 /*@=boundswrite@*/
    00595
    00596     rpmtsCleanDig(ts);
    00597     return rc;
    00598 }
    00599
    00600 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
    00601 {
    00602     int_32 block[4];
    00603     int_32 il;
    00604     int_32 dl;
    00605     int_32 * ei = NULL;
    00606     size_t uc;
    00607     int_32 nb;
    00608     Header h = NULL;
    00609     rpmRC rc = RPMRC_FAIL;              /* assume failure */
    00610
    00611     if (hdrp)
    00612         *hdrp = NULL;
    00613
    00614     if (timedRead(fd, (char *)block, sizeof(block)) != sizeof(block))
    00615         goto exit;
    00616     if (memcmp(block, header_magic, sizeof(header_magic)))
    00617         goto exit;
    00618     il = ntohl(block[2]);
    00619     if (hdrchkTags(il))
    00620         goto exit;
    00621     dl = ntohl(block[3]);
    00622     if (hdrchkData(dl))
    00623         goto exit;
    00624
    00625     nb = (il * sizeof(struct entryInfo_s)) + dl;
    00626     uc = sizeof(il) + sizeof(dl) + nb;
    00627     ei = xmalloc(uc);
    00628     ei[0] = block[2];
    00629     ei[1] = block[3];
    00630     if (timedRead(fd, (char *)&ei[2], nb) != nb)
    00631         goto exit;
    00632
    00633     /* Sanity check header tags */
    00634     rc = headerCheck(ts, ei, uc, msg);
    00635     if (rc != RPMRC_OK)
    00636         goto exit;
    00637
    00638     /* OK, blob looks sane, load the header. */
    00639     h = headerLoad(ei);
    00640     if (h == NULL)
    00641         goto exit;
    00642     h->flags |= HEADERFLAG_ALLOCATED;
    00643     ei = NULL;  /* XXX will be freed with header */
    00644
    00645 exit:
    00646     if (rc == RPMRC_OK && hdrp && h)
    00647         *hdrp = headerLink(h);
    00648     ei = _free(ei);
    00649     h = headerFree(h);
    00650     return rc;
    00651 }
    00652
    00653 int rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
    00654 {
    00655     pgpDig dig;
    00656     byte buf[8*BUFSIZ];
    00657     ssize_t count;
    00658     struct rpmlead * l = alloca(sizeof(*l));
    00659     Header sigh = NULL;
    00660     int_32 sigtag;
    00661     int_32 sigtype;
    00662     const void * sig;
    00663     int_32 siglen;
    00664     Header h = NULL;
    00665     const char * msg;
    00666     int hmagic;
    00667     rpmVSFlags vsflags;
    00668     rpmRC rc = RPMRC_FAIL;      /* assume failure */
    00669     int xx;
    00670     int i;
    00671
    00672     if (hdrp) *hdrp = NULL;
    00673     {   struct stat st;
    00674 /*@-boundswrite@*/
    00675         memset(&st, 0, sizeof(st));
    00676 /*@=boundswrite@*/
    00677         (void) fstat(Fileno(fd), &st);
    00678         /* if fd points to a socket, pipe, etc, st.st_size is *always* zero */
    00679         if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l))
    00680             goto exit;
    00681     }
    00682
    00683     memset(l, 0, sizeof(*l));
    00684     rc = readLead(fd, l);
    00685     if (rc != RPMRC_OK) {
    00686         rc = RPMRC_NOTFOUND;
    00687         goto exit;
    00688     }
    00689
    00690     switch (l->major) {
    00691     case 1:
    00692         rpmError(RPMERR_NEWPACKAGE,
    00693             _("packaging version 1 is not supported by this version of RPM\n"));
    00694         goto exit;
    00695         /*@notreached@*/ break;
    00696     case 2:
    00697     case 3:
    00698     case 4:
    00699         break;
    00700     default:
    00701         rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
    00702                 "is supported by this version of RPM\n"));
    00703         goto exit;
    00704         /*@notreached@*/ break;
    00705     }
    00706
    00707     /* Read the signature header. */
    00708     rc = rpmReadSignature(fd, &sigh, l->signature_type);
    00709     switch (rc) {
    00710     default:
    00711         rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed\n"), fn);
    00712         goto exit;
    00713         /*@notreached@*/ break;
    00714     case RPMRC_OK:
    00715         if (sigh == NULL) {
    00716             rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
    00717             rc = RPMRC_FAIL;
    00718             goto exit;
    00719         }
    00720         break;
    00721     }
    00722
    00723 #define _chk(_mask)     (sigtag == 0 && !(vsflags & (_mask)))
    00724
    00725     /* Figger the most effective available signature. */
    00726     sigtag = 0;
    00727     vsflags = rpmtsVSFlags(ts);
    00728 #ifdef  DYING
    00729     if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA))
    00730         sigtag = RPMSIGTAG_DSA;
    00731     if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA))
    00732         sigtag = RPMSIGTAG_RSA;
    00733 #endif
    00734     if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
    00735         headerIsEntry(sigh, RPMSIGTAG_GPG))
    00736     {
    00737         sigtag = RPMSIGTAG_GPG;
    00738         fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
    00739     }
    00740     if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
    00741         headerIsEntry(sigh, RPMSIGTAG_PGP))
    00742     {
    00743         sigtag = RPMSIGTAG_PGP;
    00744         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
    00745     }
    00746 #ifdef  DYING
    00747     if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1))
    00748         sigtag = RPMSIGTAG_SHA1;
    00749 #endif
    00750     if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
    00751         headerIsEntry(sigh, RPMSIGTAG_MD5))
    00752     {
    00753         sigtag = RPMSIGTAG_MD5;
    00754         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
    00755     }
    00756
    00757     /* Read the metadata, computing digest(s) on the fly. */
    00758     h = NULL;
    00759     msg = NULL;
    00760     rc = rpmReadHeader(ts, fd, &h, &msg);
    00761     if (rc != RPMRC_OK || h == NULL) {
    00762         rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
    00763                 (msg && *msg ? msg : "\n"));
    00764         msg = _free(msg);
    00765         goto exit;
    00766     }
    00767     msg = _free(msg);
    00768
    00769     /* Any signatures to check? */
    00770     if (sigtag == 0) {
    00771         rc = RPMRC_OK;
    00772         goto exit;
    00773     }
    00774
    00775     dig = rpmtsDig(ts);
    00776     if (dig == NULL) {
    00777         rc = RPMRC_FAIL;
    00778         goto exit;
    00779     }
    00780     dig->nbytes = 0;
    00781
    00782     /* Retrieve the tag parameters from the signature header. */
    00783     sig = NULL;
    00784     xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
    00785     if (sig == NULL) {
    00786         rc = RPMRC_FAIL;
    00787         goto exit;
    00788     }
    00789     (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
    00790
    00791     switch (sigtag) {
    00792     case RPMSIGTAG_RSA:
    00793         /* Parse the parameters from the OpenPGP packets that will be needed. */
    00794         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
    00795         /* XXX only V3 signatures for now. */
    00796         if (dig->signature.version != 3) {
    00797             rpmMessage(RPMMESS_WARNING,
    00798                 _("only V3 signatures can be verified, skipping V%u signature\n"),
    00799                 dig->signature.version);
    00800             rc = RPMRC_OK;
    00801             goto exit;
    00802         }
    00803     {   void * uh = NULL;
    00804         int_32 uht;
    00805         int_32 uhc;
    00806
    00807         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
    00808             break;
    00809         dig->md5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
    00810         (void) rpmDigestUpdate(dig->md5ctx, header_magic, sizeof(header_magic));
    00811         dig->nbytes += sizeof(header_magic);
    00812         (void) rpmDigestUpdate(dig->md5ctx, uh, uhc);
    00813         dig->nbytes += uhc;
    00814         uh = headerFreeData(uh, uht);
    00815     }   break;
    00816     case RPMSIGTAG_DSA:
    00817         /* Parse the parameters from the OpenPGP packets that will be needed. */
    00818         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
    00819         /* XXX only V3 signatures for now. */
    00820         if (dig->signature.version != 3) {
    00821             rpmMessage(RPMMESS_WARNING,
    00822                 _("only V3 signatures can be verified, skipping V%u signature\n"),
    00823                 dig->signature.version);
    00824             rc = RPMRC_OK;
    00825             goto exit;
    00826         }
    00827         /*@fallthrough@*/
    00828     case RPMSIGTAG_SHA1:
    00829     {   void * uh = NULL;
    00830         int_32 uht;
    00831         int_32 uhc;
    00832
    00833         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
    00834             break;
    00835         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
    00836         (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
    00837         dig->nbytes += sizeof(header_magic);
    00838         (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
    00839         dig->nbytes += uhc;
    00840         uh = headerFreeData(uh, uht);
    00841     }   break;
    00842     case RPMSIGTAG_GPG:
    00843     case RPMSIGTAG_PGP5:        /* XXX legacy */
    00844     case RPMSIGTAG_PGP:
    00845         /* Parse the parameters from the OpenPGP packets that will be needed. */
    00846         xx = pgpPrtPkts(sig, siglen, dig,
    00847                         (_print_pkts & rpmIsDebug()));
    00848
    00849         /* XXX only V3 signatures for now. */
    00850         if (dig->signature.version != 3) {
    00851             rpmMessage(RPMMESS_WARNING,
    00852                 _("only V3 signatures can be verified, skipping V%u signature\n"),
    00853                 dig->signature.version);
    00854             rc = RPMRC_OK;
    00855             goto exit;
    00856         }
    00857         /*@fallthrough@*/
    00858     case RPMSIGTAG_MD5:
    00859         /* Legacy signatures need the compressed payload in the digest too. */
    00860         hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
    00861         dig->nbytes += headerSizeof(h, hmagic);
    00862         while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
    00863             dig->nbytes += count;
    00864         if (count < 0) {
    00865             rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
    00866                                         fn, Fstrerror(fd));
    00867             rc = RPMRC_FAIL;
    00868             goto exit;
    00869         }
    00870         dig->nbytes += count;
    00871
    00872         /* XXX Steal the digest-in-progress from the file handle. */
    00873         for (i = fd->ndigests - 1; i >= 0; i--) {
    00874             FDDIGEST_t fddig = fd->digests + i;
    00875             if (fddig->hashctx == NULL)
    00876                 continue;
    00877             if (fddig->hashalgo == PGPHASHALGO_MD5) {
    00878                 dig->md5ctx = fddig->hashctx;
    00879                 fddig->hashctx = NULL;
    00880                 continue;
    00881             }
    00882             if (fddig->hashalgo == PGPHASHALGO_SHA1) {
    00883                 dig->sha1ctx = fddig->hashctx;
    00884                 fddig->hashctx = NULL;
    00885                 continue;
    00886             }
    00887         }
    00888         break;
    00889     }
    00890
    00893 /*@-boundswrite@*/
    00894     buf[0] = '\0';
    00895 /*@=boundswrite@*/
    00896     rc = rpmVerifySignature(ts, buf);
    00897     switch (rc) {
    00898     case RPMRC_OK:              /* Signature is OK. */
    00899         rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
    00900         break;
    00901     case RPMRC_NOTTRUSTED:      /* Signature is OK, but key is not trusted. */
    00902     case RPMRC_NOKEY:           /* Public key is unavailable. */
    00903         /* XXX Print NOKEY/NOTTRUSTED warning only once. */
    00904     {   int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
    00905         rpmMessage(lvl, "%s: %s", fn, buf);
    00906     }   break;
    00907     case RPMRC_NOTFOUND:        /* Signature is unknown type. */
    00908         rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
    00909         break;
    00910     default:
    00911     case RPMRC_FAIL:            /* Signature does not verify. */
    00912         rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
    00913         break;
    00914     }
    00915
    00916 exit:
    00917     if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
    00918         /* Convert legacy headers on the fly ... */
    00919         legacyRetrofit(h, l);
    00920
    00921         /* Append (and remap) signature tags to the metadata. */
    00922         headerMergeLegacySigs(h, sigh);
    00923
    00924         /* Bump reference count for return. */
    00925 /*@-boundswrite@*/
    00926         *hdrp = headerLink(h);
    00927 /*@=boundswrite@*/
    00928     }
    00929     h = headerFree(h);
    00930     rpmtsCleanDig(ts);
    00931     sigh = rpmFreeSignature(sigh);
    00932     return rc;
    00933 }