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

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

Generated on Sun Aug 20 07:15:05 2006 for rpm by  doxygen 1.3.9.1