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 nextkeyid, nkeyids, keyids @*/
00245         /*@modifies nextkeyid, 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     if (keyids)         /* XXX can't happen */
00274         keyids[nextkeyid] = keyid;
00275 /*@=boundswrite@*/
00276     nextkeyid++;
00277     nextkeyid %= nkeyids_max;
00278 
00279     return 0;
00280 }
00281 
00282 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
00283 {
00284 /*@-castexpose@*/
00285     entryInfo pe = (entryInfo) pev;
00286 /*@=castexpose@*/
00287     entryInfo info = iv;
00288     int i;
00289 
00290 /*@-boundsread@*/
00291     for (i = 0; i < il; i++) {
00292         info->tag = ntohl(pe[i].tag);
00293         info->type = ntohl(pe[i].type);
00294         info->offset = ntohl(pe[i].offset);
00295         if (negate)
00296             info->offset = -info->offset;
00297         info->count = ntohl(pe[i].count);
00298 
00299         if (hdrchkType(info->type))
00300             return i;
00301         if (hdrchkAlign(info->type, info->offset))
00302             return i;
00303         if (!negate && hdrchkRange(dl, info->offset))
00304             return i;
00305         if (hdrchkData(info->count))
00306             return i;
00307 
00308     }
00309 /*@=boundsread@*/
00310     return -1;
00311 }
00312 
00326 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg)
00327 {
00328     pgpDig dig;
00329     unsigned char buf[8*BUFSIZ];
00330     int_32 * ei = (int_32 *) uh;
00331 /*@-boundsread@*/
00332     int_32 il = ntohl(ei[0]);
00333     int_32 dl = ntohl(ei[1]);
00334 /*@-castexpose@*/
00335     entryInfo pe = (entryInfo) &ei[2];
00336 /*@=castexpose@*/
00337 /*@=boundsread@*/
00338     int_32 ildl[2];
00339     int_32 pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
00340     unsigned char * dataStart = (unsigned char *) (pe + il);
00341     indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
00342     entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
00343     const void * sig = NULL;
00344     const char * b;
00345     rpmVSFlags vsflags = rpmtsVSFlags(ts);
00346     int siglen = 0;
00347     int blen;
00348     size_t nb;
00349     int_32 ril = 0;
00350     unsigned char * regionEnd = NULL;
00351     rpmRC rc = RPMRC_FAIL;      /* assume failure */
00352     int xx;
00353     int i;
00354 
00355 /*@-boundswrite@*/
00356     buf[0] = '\0';
00357 /*@=boundswrite@*/
00358 
00359     /* Is the blob the right size? */
00360     if (uc > 0 && pvlen != uc) {
00361         (void) snprintf(buf, sizeof(buf),
00362                 _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
00363                 uc, il, dl);
00364         goto exit;
00365     }
00366 
00367     /* Check (and convert) the 1st tag element. */
00368     xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
00369     if (xx != -1) {
00370         (void) snprintf(buf, sizeof(buf),
00371                 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00372                 0, entry->info.tag, entry->info.type,
00373                 entry->info.offset, entry->info.count);
00374         goto exit;
00375     }
00376 
00377     /* Is there an immutable header region tag? */
00378 /*@-sizeoftype@*/
00379     if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00380        && entry->info.type == RPM_BIN_TYPE
00381        && entry->info.count == REGION_TAG_COUNT))
00382     {
00383         rc = RPMRC_NOTFOUND;
00384         goto exit;
00385     }
00386 /*@=sizeoftype@*/
00387 
00388     /* Is the offset within the data area? */
00389     if (entry->info.offset >= dl) {
00390         (void) snprintf(buf, sizeof(buf),
00391                 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
00392                 entry->info.tag, entry->info.type,
00393                 entry->info.offset, entry->info.count);
00394         goto exit;
00395     }
00396 
00397     /* Is there an immutable header region tag trailer? */
00398     regionEnd = dataStart + entry->info.offset;
00399 /*@-sizeoftype@*/
00400 /*@-bounds@*/
00401     (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
00402 /*@=bounds@*/
00403     regionEnd += REGION_TAG_COUNT;
00404 
00405     xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
00406     if (xx != -1 ||
00407         !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00408        && entry->info.type == RPM_BIN_TYPE
00409        && entry->info.count == REGION_TAG_COUNT))
00410     {
00411         (void) snprintf(buf, sizeof(buf),
00412                 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
00413                 entry->info.tag, entry->info.type,
00414                 entry->info.offset, entry->info.count);
00415         goto exit;
00416     }
00417 /*@=sizeoftype@*/
00418 /*@-boundswrite@*/
00419     memset(info, 0, sizeof(*info));
00420 /*@=boundswrite@*/
00421 
00422     /* Is the no. of tags in the region less than the total no. of tags? */
00423     ril = entry->info.offset/sizeof(*pe);
00424     if ((entry->info.offset % sizeof(*pe)) || ril > il) {
00425         (void) snprintf(buf, sizeof(buf),
00426                 _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
00427         goto exit;
00428     }
00429 
00430     /* Find a header-only digest/signature tag. */
00431     for (i = ril; i < il; i++) {
00432         xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
00433         if (xx != -1) {
00434             (void) snprintf(buf, sizeof(buf),
00435                 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00436                 i, entry->info.tag, entry->info.type,
00437                 entry->info.offset, entry->info.count);
00438             goto exit;
00439         }
00440 
00441         switch (entry->info.tag) {
00442         case RPMTAG_SHA1HEADER:
00443             if (vsflags & RPMVSF_NOSHA1HEADER)
00444                 /*@switchbreak@*/ break;
00445             blen = 0;
00446 /*@-boundsread@*/
00447             for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
00448                 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
00449                     /*@innerbreak@*/ break;
00450                 blen++;
00451             }
00452             if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
00453             {
00454                 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex\n"));
00455                 goto exit;
00456             }
00457 /*@=boundsread@*/
00458             if (info->tag == 0) {
00459 /*@-boundswrite@*/
00460                 *info = entry->info;    /* structure assignment */
00461 /*@=boundswrite@*/
00462                 siglen = blen + 1;
00463             }
00464             /*@switchbreak@*/ break;
00465 #ifdef  NOTYET
00466         case RPMTAG_RSAHEADER:
00467 #endif
00468         case RPMTAG_DSAHEADER:
00469             if (vsflags & RPMVSF_NODSAHEADER)
00470                 /*@switchbreak@*/ break;
00471             if (entry->info.type != RPM_BIN_TYPE) {
00472                 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n"));
00473                 goto exit;
00474             }
00475 /*@-boundswrite@*/
00476             *info = entry->info;        /* structure assignment */
00477 /*@=boundswrite@*/
00478             siglen = info->count;
00479             /*@switchbreak@*/ break;
00480         default:
00481             /*@switchbreak@*/ break;
00482         }
00483     }
00484     rc = RPMRC_NOTFOUND;
00485 
00486 exit:
00487     /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
00488     if (rc != RPMRC_NOTFOUND) {
00489 /*@-boundswrite@*/
00490         buf[sizeof(buf)-1] = '\0';
00491         if (msg) *msg = xstrdup(buf);
00492 /*@=boundswrite@*/
00493         return rc;
00494     }
00495 
00496     /* If no header-only digest/signature, then do simple sanity check. */
00497     if (info->tag == 0) {
00498 verifyinfo_exit:
00499         xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
00500         if (xx != -1) {
00501             (void) snprintf(buf, sizeof(buf),
00502                 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00503                 xx+1, entry->info.tag, entry->info.type,
00504                 entry->info.offset, entry->info.count);
00505             rc = RPMRC_FAIL;
00506         } else {
00507             (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
00508             rc = RPMRC_OK;
00509         }
00510 /*@-boundswrite@*/
00511         buf[sizeof(buf)-1] = '\0';
00512         if (msg) *msg = xstrdup(buf);
00513 /*@=boundswrite@*/
00514         return rc;
00515     }
00516 
00517     /* Verify header-only digest/signature. */
00518     dig = rpmtsDig(ts);
00519     if (dig == NULL)
00520         goto verifyinfo_exit;
00521     dig->nbytes = 0;
00522 
00523 /*@-boundsread@*/
00524     sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
00525 /*@=boundsread@*/
00526     (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
00527 
00528     switch (info->tag) {
00529 #ifdef  NOTYET
00530     case RPMTAG_RSAHEADER:
00531         /* Parse the parameters from the OpenPGP packets that will be needed. */
00532         xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00533         /* XXX only V3 signatures for now. */
00534         if (dig->signature.version != 3) {
00535             rpmMessage(RPMMESS_WARNING,
00536                 _("only V3 signatures can be verified, skipping V%u signature\n"),
00537                 dig->signature.version);
00538             rpmtsCleanDig(ts);
00539             goto verifyinfo_exit;
00540         }
00541 
00542         ildl[0] = htonl(ril);
00543         ildl[1] = (regionEnd - dataStart);
00544         ildl[1] = htonl(ildl[1]);
00545 
00546         dig->hdrmd5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
00547 
00548         b = (unsigned char *) header_magic;
00549         nb = sizeof(header_magic);
00550         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00551         dig->nbytes += nb;
00552 
00553         b = (unsigned char *) ildl;
00554         nb = sizeof(ildl);
00555         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00556         dig->nbytes += nb;
00557 
00558         b = (unsigned char *) pe;
00559         nb = (htonl(ildl[0]) * sizeof(*pe));
00560         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00561         dig->nbytes += nb;
00562 
00563         b = (unsigned char *) dataStart;
00564         nb = htonl(ildl[1]);
00565         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00566         dig->nbytes += nb;
00567 
00568         break;
00569 #endif
00570     case RPMTAG_DSAHEADER:
00571         /* Parse the parameters from the OpenPGP packets that will be needed. */
00572         xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00573         /* XXX only V3 signatures for now. */
00574         if (dig->signature.version != 3) {
00575             rpmMessage(RPMMESS_WARNING,
00576                 _("only V3 signatures can be verified, skipping V%u signature\n"),
00577                 dig->signature.version);
00578             rpmtsCleanDig(ts);
00579             goto verifyinfo_exit;
00580         }
00581         /*@fallthrough@*/
00582     case RPMTAG_SHA1HEADER:
00583 /*@-boundswrite@*/
00584         ildl[0] = htonl(ril);
00585         ildl[1] = (regionEnd - dataStart);
00586         ildl[1] = htonl(ildl[1]);
00587 /*@=boundswrite@*/
00588 
00589         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00590 
00591         b = (unsigned char *) header_magic;
00592         nb = sizeof(header_magic);
00593         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00594         dig->nbytes += nb;
00595 
00596         b = (unsigned char *) ildl;
00597         nb = sizeof(ildl);
00598         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00599         dig->nbytes += nb;
00600 
00601         b = (unsigned char *) pe;
00602         nb = (htonl(ildl[0]) * sizeof(*pe));
00603         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00604         dig->nbytes += nb;
00605 
00606         b = (unsigned char *) dataStart;
00607         nb = htonl(ildl[1]);
00608         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00609         dig->nbytes += nb;
00610 
00611         break;
00612     default:
00613         break;
00614     }
00615 
00616 /*@-boundswrite@*/
00617     buf[0] = '\0';
00618 /*@=boundswrite@*/
00619     rc = rpmVerifySignature(ts, buf);
00620 
00621 /*@-boundswrite@*/
00622     buf[sizeof(buf)-1] = '\0';
00623     if (msg) *msg = xstrdup(buf);
00624 /*@=boundswrite@*/
00625 
00626     rpmtsCleanDig(ts);
00627     return rc;
00628 }
00629 
00630 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
00631 {
00632     char buf[BUFSIZ];
00633     int_32 block[4];
00634     int_32 il;
00635     int_32 dl;
00636     int_32 * ei = NULL;
00637     size_t uc;
00638     int_32 nb;
00639     Header h = NULL;
00640     rpmRC rc = RPMRC_FAIL;              /* assume failure */
00641     int xx;
00642 
00643 /*@-boundswrite@*/
00644     buf[0] = '\0';
00645 
00646     if (hdrp)
00647         *hdrp = NULL;
00648     if (msg)
00649         *msg = NULL;
00650 /*@=boundswrite@*/
00651 
00652     memset(block, 0, sizeof(block));
00653     if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
00654         (void) snprintf(buf, sizeof(buf),
00655                 _("hdr size(%d): BAD, read returned %d\n"), sizeof(block), xx);
00656         goto exit;
00657     }
00658     if (memcmp(block, header_magic, sizeof(header_magic))) {
00659         (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
00660         goto exit;
00661     }
00662 /*@-boundsread@*/
00663     il = ntohl(block[2]);
00664 /*@=boundsread@*/
00665     if (hdrchkTags(il)) {
00666         (void) snprintf(buf, sizeof(buf),
00667                 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
00668 
00669         goto exit;
00670     }
00671 /*@-boundsread@*/
00672     dl = ntohl(block[3]);
00673 /*@=boundsread@*/
00674     if (hdrchkData(dl)) {
00675         (void) snprintf(buf, sizeof(buf),
00676                 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
00677         goto exit;
00678     }
00679 
00680 /*@-sizeoftype@*/
00681     nb = (il * sizeof(struct entryInfo_s)) + dl;
00682 /*@=sizeoftype@*/
00683     uc = sizeof(il) + sizeof(dl) + nb;
00684     ei = xmalloc(uc);
00685 /*@-bounds@*/
00686     ei[0] = block[2];
00687     ei[1] = block[3];
00688     if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
00689         (void) snprintf(buf, sizeof(buf),
00690                 _("hdr blob(%d): BAD, read returned %d\n"), nb, xx);
00691         goto exit;
00692     }
00693 /*@=bounds@*/
00694 
00695     /* Sanity check header tags */
00696     rc = headerCheck(ts, ei, uc, msg);
00697     if (rc != RPMRC_OK)
00698         goto exit;
00699 
00700     /* OK, blob looks sane, load the header. */
00701     h = headerLoad(ei);
00702     if (h == NULL) {
00703         (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
00704         goto exit;
00705     }
00706     h->flags |= HEADERFLAG_ALLOCATED;
00707     ei = NULL;  /* XXX will be freed with header */
00708     
00709 exit:
00710 /*@-boundswrite@*/
00711     if (hdrp && h && rc == RPMRC_OK)
00712         *hdrp = headerLink(h);
00713 /*@=boundswrite@*/
00714     ei = _free(ei);
00715     h = headerFree(h);
00716 
00717 /*@-boundswrite@*/
00718     if (msg != NULL && *msg == NULL && buf[0] != '\0') {
00719         buf[sizeof(buf)-1] = '\0';
00720         *msg = xstrdup(buf);
00721     }
00722 /*@=boundswrite@*/
00723 
00724     return rc;
00725 }
00726 
00727 /*@-bounds@*/   /* LCL: segfault */
00728 int rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
00729 {
00730     pgpDig dig;
00731     byte buf[8*BUFSIZ];
00732     ssize_t count;
00733     struct rpmlead * l = alloca(sizeof(*l));
00734     Header sigh = NULL;
00735     int_32 sigtag;
00736     int_32 sigtype;
00737     const void * sig;
00738     int_32 siglen;
00739     Header h = NULL;
00740     const char * msg;
00741     int hmagic;
00742     rpmVSFlags vsflags;
00743     rpmRC rc = RPMRC_FAIL;      /* assume failure */
00744     int xx;
00745     int i;
00746 
00747     if (hdrp) *hdrp = NULL;
00748     {   struct stat st;
00749 /*@-boundswrite@*/
00750         memset(&st, 0, sizeof(st));
00751 /*@=boundswrite@*/
00752         (void) fstat(Fileno(fd), &st);
00753         /* if fd points to a socket, pipe, etc, st.st_size is *always* zero */
00754         if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l))
00755             goto exit;
00756     }
00757 
00758     memset(l, 0, sizeof(*l));
00759     rc = readLead(fd, l);
00760     if (rc != RPMRC_OK) {
00761         rc = RPMRC_NOTFOUND;
00762         goto exit;
00763     }
00764 
00765     switch (l->major) {
00766     case 1:
00767         rpmError(RPMERR_NEWPACKAGE,
00768             _("packaging version 1 is not supported by this version of RPM\n"));
00769         goto exit;
00770         /*@notreached@*/ break;
00771     case 2:
00772     case 3:
00773     case 4:
00774         break;
00775     default:
00776         rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
00777                 "is supported by this version of RPM\n"));
00778         goto exit;
00779         /*@notreached@*/ break;
00780     }
00781 
00782     /* Read the signature header. */
00783     msg = NULL;
00784     rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
00785     switch (rc) {
00786     default:
00787         rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
00788                 (msg && *msg ? msg : "\n"));
00789         msg = _free(msg);
00790         goto exit;
00791         /*@notreached@*/ break;
00792     case RPMRC_OK:
00793         if (sigh == NULL) {
00794             rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
00795             rc = RPMRC_FAIL;
00796             goto exit;
00797         }
00798         break;
00799     }
00800     msg = _free(msg);
00801 
00802 #define _chk(_mask)     (sigtag == 0 && !(vsflags & (_mask)))
00803 
00804     /* Figger the most effective available signature. */
00805     sigtag = 0;
00806     vsflags = rpmtsVSFlags(ts);
00807 #ifdef  DYING
00808     if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA))
00809         sigtag = RPMSIGTAG_DSA;
00810     if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA))
00811         sigtag = RPMSIGTAG_RSA;
00812 #endif
00813     if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
00814         headerIsEntry(sigh, RPMSIGTAG_GPG))
00815     {
00816         sigtag = RPMSIGTAG_GPG;
00817         fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00818     }
00819     if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
00820         headerIsEntry(sigh, RPMSIGTAG_PGP))
00821     {
00822         sigtag = RPMSIGTAG_PGP;
00823         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00824     }
00825 #ifdef  DYING
00826     if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1))
00827         sigtag = RPMSIGTAG_SHA1;
00828 #endif
00829     if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
00830         headerIsEntry(sigh, RPMSIGTAG_MD5))
00831     {
00832         sigtag = RPMSIGTAG_MD5;
00833         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00834     }
00835 
00836     /* Read the metadata, computing digest(s) on the fly. */
00837     h = NULL;
00838     msg = NULL;
00839     rc = rpmReadHeader(ts, fd, &h, &msg);
00840     if (rc != RPMRC_OK || h == NULL) {
00841         rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
00842                 (msg && *msg ? msg : "\n"));
00843         msg = _free(msg);
00844         goto exit;
00845     }
00846     msg = _free(msg);
00847 
00848     /* Any signatures to check? */
00849     if (sigtag == 0) {
00850         rc = RPMRC_OK;
00851         goto exit;
00852     }
00853 
00854     dig = rpmtsDig(ts);
00855     if (dig == NULL) {
00856         rc = RPMRC_FAIL;
00857         goto exit;
00858     }
00859     dig->nbytes = 0;
00860 
00861     /* Retrieve the tag parameters from the signature header. */
00862     sig = NULL;
00863     xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
00864     if (sig == NULL) {
00865         rc = RPMRC_FAIL;
00866         goto exit;
00867     }
00868     (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
00869 
00870     switch (sigtag) {
00871     case RPMSIGTAG_RSA:
00872         /* Parse the parameters from the OpenPGP packets that will be needed. */
00873         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00874         /* XXX only V3 signatures for now. */
00875         if (dig->signature.version != 3) {
00876             rpmMessage(RPMMESS_WARNING,
00877                 _("only V3 signatures can be verified, skipping V%u signature\n"),
00878                 dig->signature.version);
00879             rc = RPMRC_OK;
00880             goto exit;
00881         }
00882     {   void * uh = NULL;
00883         int_32 uht;
00884         int_32 uhc;
00885 
00886         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00887             break;
00888         dig->md5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
00889         (void) rpmDigestUpdate(dig->md5ctx, header_magic, sizeof(header_magic));
00890         dig->nbytes += sizeof(header_magic);
00891         (void) rpmDigestUpdate(dig->md5ctx, uh, uhc);
00892         dig->nbytes += uhc;
00893         uh = headerFreeData(uh, uht);
00894     }   break;
00895     case RPMSIGTAG_DSA:
00896         /* Parse the parameters from the OpenPGP packets that will be needed. */
00897         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00898         /* XXX only V3 signatures for now. */
00899         if (dig->signature.version != 3) {
00900             rpmMessage(RPMMESS_WARNING,
00901                 _("only V3 signatures can be verified, skipping V%u signature\n"),
00902                 dig->signature.version);
00903             rc = RPMRC_OK;
00904             goto exit;
00905         }
00906         /*@fallthrough@*/
00907     case RPMSIGTAG_SHA1:
00908     {   void * uh = NULL;
00909         int_32 uht;
00910         int_32 uhc;
00911 
00912         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00913             break;
00914         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00915         (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
00916         dig->nbytes += sizeof(header_magic);
00917         (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
00918         dig->nbytes += uhc;
00919         uh = headerFreeData(uh, uht);
00920     }   break;
00921     case RPMSIGTAG_GPG:
00922     case RPMSIGTAG_PGP5:        /* XXX legacy */
00923     case RPMSIGTAG_PGP:
00924         /* Parse the parameters from the OpenPGP packets that will be needed. */
00925         xx = pgpPrtPkts(sig, siglen, dig,
00926                         (_print_pkts & rpmIsDebug()));
00927 
00928         /* XXX only V3 signatures for now. */
00929         if (dig->signature.version != 3) {
00930             rpmMessage(RPMMESS_WARNING,
00931                 _("only V3 signatures can be verified, skipping V%u signature\n"),
00932                 dig->signature.version);
00933             rc = RPMRC_OK;
00934             goto exit;
00935         }
00936         /*@fallthrough@*/
00937     case RPMSIGTAG_MD5:
00938         /* Legacy signatures need the compressed payload in the digest too. */
00939         hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
00940         dig->nbytes += headerSizeof(h, hmagic);
00941         while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00942             dig->nbytes += count;
00943         if (count < 0) {
00944             rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
00945                                         fn, Fstrerror(fd));
00946             rc = RPMRC_FAIL;
00947             goto exit;
00948         }
00949         dig->nbytes += count;
00950 
00951         /* XXX Steal the digest-in-progress from the file handle. */
00952         for (i = fd->ndigests - 1; i >= 0; i--) {
00953             FDDIGEST_t fddig = fd->digests + i;
00954             if (fddig->hashctx == NULL)
00955                 continue;
00956             if (fddig->hashalgo == PGPHASHALGO_MD5) {
00957                 dig->md5ctx = fddig->hashctx;
00958                 fddig->hashctx = NULL;
00959                 continue;
00960             }
00961             if (fddig->hashalgo == PGPHASHALGO_SHA1) {
00962                 dig->sha1ctx = fddig->hashctx;
00963                 fddig->hashctx = NULL;
00964                 continue;
00965             }
00966         }
00967         break;
00968     }
00969 
00972 /*@-boundswrite@*/
00973     buf[0] = '\0';
00974 /*@=boundswrite@*/
00975     rc = rpmVerifySignature(ts, buf);
00976     switch (rc) {
00977     case RPMRC_OK:              /* Signature is OK. */
00978         rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
00979         break;
00980     case RPMRC_NOTTRUSTED:      /* Signature is OK, but key is not trusted. */
00981     case RPMRC_NOKEY:           /* Public key is unavailable. */
00982         /* XXX Print NOKEY/NOTTRUSTED warning only once. */
00983     {   int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
00984         rpmMessage(lvl, "%s: %s", fn, buf);
00985     }   break;
00986     case RPMRC_NOTFOUND:        /* Signature is unknown type. */
00987         rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
00988         break;
00989     default:
00990     case RPMRC_FAIL:            /* Signature does not verify. */
00991         rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
00992         break;
00993     }
00994 
00995 exit:
00996     if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
00997         /* Convert legacy headers on the fly ... */
00998         legacyRetrofit(h, l);
00999         
01000         /* Append (and remap) signature tags to the metadata. */
01001         headerMergeLegacySigs(h, sigh);
01002 
01003         /* Bump reference count for return. */
01004 /*@-boundswrite@*/
01005         *hdrp = headerLink(h);
01006 /*@=boundswrite@*/
01007     }
01008     h = headerFree(h);
01009     rpmtsCleanDig(ts);
01010     sigh = rpmFreeSignature(sigh);
01011     return rc;
01012 }
01013 /*@=bounds@*/

Generated on Tue Sep 17 15:59:49 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002