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

Generated on Sun Oct 26 13:01:59 2003 for rpm by doxygen1.2.18