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 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 
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         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
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         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00568 
00569         break;
00570 #endif
00571     case RPMTAG_DSAHEADER:
00572         /* Parse the parameters from the OpenPGP packets that will be needed. */
00573         xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00574         /* XXX only V3 signatures for now. */
00575         if (dig->signature.version != 3) {
00576             rpmMessage(RPMMESS_WARNING,
00577                 _("only V3 signatures can be verified, skipping V%u signature\n"),
00578                 dig->signature.version);
00579             rpmtsCleanDig(ts);
00580             goto verifyinfo_exit;
00581         }
00582         /*@fallthrough@*/
00583     case RPMTAG_SHA1HEADER:
00584 /*@-boundswrite@*/
00585         ildl[0] = htonl(ril);
00586         ildl[1] = (regionEnd - dataStart);
00587         ildl[1] = htonl(ildl[1]);
00588 /*@=boundswrite@*/
00589 
00590         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00591         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00592 
00593         b = (unsigned char *) header_magic;
00594         nb = sizeof(header_magic);
00595         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00596         dig->nbytes += nb;
00597 
00598         b = (unsigned char *) ildl;
00599         nb = sizeof(ildl);
00600         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00601         dig->nbytes += nb;
00602 
00603         b = (unsigned char *) pe;
00604         nb = (htonl(ildl[0]) * sizeof(*pe));
00605         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00606         dig->nbytes += nb;
00607 
00608         b = (unsigned char *) dataStart;
00609         nb = htonl(ildl[1]);
00610         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00611         dig->nbytes += nb;
00612         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00613 
00614         break;
00615     default:
00616         sig = _free(sig);
00617         break;
00618     }
00619 
00620 /*@-boundswrite@*/
00621     buf[0] = '\0';
00622 /*@=boundswrite@*/
00623     rc = rpmVerifySignature(ts, buf);
00624 
00625 /*@-boundswrite@*/
00626     buf[sizeof(buf)-1] = '\0';
00627     if (msg) *msg = xstrdup(buf);
00628 /*@=boundswrite@*/
00629 
00630     rpmtsCleanDig(ts);
00631     if (info->tag == RPMTAG_SHA1HEADER)
00632         sig = _free(sig);
00633     return rc;
00634 }
00635 
00636 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
00637 {
00638     char buf[BUFSIZ];
00639     int_32 block[4];
00640     int_32 il;
00641     int_32 dl;
00642     int_32 * ei = NULL;
00643     size_t uc;
00644     int_32 nb;
00645     Header h = NULL;
00646     rpmRC rc = RPMRC_FAIL;              /* assume failure */
00647     int xx;
00648 
00649 /*@-boundswrite@*/
00650     buf[0] = '\0';
00651 
00652     if (hdrp)
00653         *hdrp = NULL;
00654     if (msg)
00655         *msg = NULL;
00656 /*@=boundswrite@*/
00657 
00658     memset(block, 0, sizeof(block));
00659     if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
00660         (void) snprintf(buf, sizeof(buf),
00661                 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
00662         goto exit;
00663     }
00664     if (memcmp(block, header_magic, sizeof(header_magic))) {
00665         (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
00666         goto exit;
00667     }
00668 /*@-boundsread@*/
00669     il = ntohl(block[2]);
00670 /*@=boundsread@*/
00671     if (hdrchkTags(il)) {
00672         (void) snprintf(buf, sizeof(buf),
00673                 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
00674 
00675         goto exit;
00676     }
00677 /*@-boundsread@*/
00678     dl = ntohl(block[3]);
00679 /*@=boundsread@*/
00680     if (hdrchkData(dl)) {
00681         (void) snprintf(buf, sizeof(buf),
00682                 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
00683         goto exit;
00684     }
00685 
00686 /*@-sizeoftype@*/
00687     nb = (il * sizeof(struct entryInfo_s)) + dl;
00688 /*@=sizeoftype@*/
00689     uc = sizeof(il) + sizeof(dl) + nb;
00690     ei = xmalloc(uc);
00691 /*@-bounds@*/
00692     ei[0] = block[2];
00693     ei[1] = block[3];
00694     if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
00695         (void) snprintf(buf, sizeof(buf),
00696                 _("hdr blob(%d): BAD, read returned %d\n"), nb, xx);
00697         goto exit;
00698     }
00699 /*@=bounds@*/
00700 
00701     /* Sanity check header tags */
00702     rc = headerCheck(ts, ei, uc, msg);
00703     if (rc != RPMRC_OK)
00704         goto exit;
00705 
00706     /* OK, blob looks sane, load the header. */
00707     h = headerLoad(ei);
00708     if (h == NULL) {
00709         (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
00710         goto exit;
00711     }
00712     h->flags |= HEADERFLAG_ALLOCATED;
00713     ei = NULL;  /* XXX will be freed with header */
00714     
00715 exit:
00716 /*@-boundswrite@*/
00717     if (hdrp && h && rc == RPMRC_OK)
00718         *hdrp = headerLink(h);
00719 /*@=boundswrite@*/
00720     ei = _free(ei);
00721     h = headerFree(h);
00722 
00723 /*@-boundswrite@*/
00724     if (msg != NULL && *msg == NULL && buf[0] != '\0') {
00725         buf[sizeof(buf)-1] = '\0';
00726         *msg = xstrdup(buf);
00727     }
00728 /*@=boundswrite@*/
00729 
00730     return rc;
00731 }
00732 
00733 /*@-bounds@*/   /* LCL: segfault */
00734 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
00735 {
00736     pgpDig dig;
00737     byte buf[8*BUFSIZ];
00738     ssize_t count;
00739     struct rpmlead * l = alloca(sizeof(*l));
00740     Header sigh = NULL;
00741     int_32 sigtag;
00742     int_32 sigtype;
00743     const void * sig;
00744     int_32 siglen;
00745     Header h = NULL;
00746     const char * msg;
00747     int hmagic;
00748     rpmVSFlags vsflags;
00749     rpmRC rc = RPMRC_FAIL;      /* assume failure */
00750     int xx;
00751     int i;
00752 
00753     if (hdrp) *hdrp = NULL;
00754 
00755 #ifdef  DYING
00756     {   struct stat st;
00757 /*@-boundswrite@*/
00758         memset(&st, 0, sizeof(st));
00759 /*@=boundswrite@*/
00760         (void) fstat(Fileno(fd), &st);
00761         /* if fd points to a socket, pipe, etc, st.st_size is *always* zero */
00762         if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l)) {
00763             rc = RPMRC_NOTFOUND;
00764             goto exit;
00765         }
00766     }
00767 #endif
00768 
00769     memset(l, 0, sizeof(*l));
00770     rc = readLead(fd, l);
00771     if (rc != RPMRC_OK)
00772         goto exit;
00773 
00774     switch (l->major) {
00775     case 1:
00776         rpmError(RPMERR_NEWPACKAGE,
00777             _("packaging version 1 is not supported by this version of RPM\n"));
00778         rc = RPMRC_NOTFOUND;
00779         goto exit;
00780         /*@notreached@*/ break;
00781     case 2:
00782     case 3:
00783     case 4:
00784         break;
00785     default:
00786         rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
00787                 "is supported by this version of RPM\n"));
00788         rc = RPMRC_NOTFOUND;
00789         goto exit;
00790         /*@notreached@*/ break;
00791     }
00792 
00793     /* Read the signature header. */
00794     msg = NULL;
00795     rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
00796     switch (rc) {
00797     default:
00798         rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
00799                 (msg && *msg ? msg : "\n"));
00800         msg = _free(msg);
00801         goto exit;
00802         /*@notreached@*/ break;
00803     case RPMRC_OK:
00804         if (sigh == NULL) {
00805             rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
00806             rc = RPMRC_FAIL;
00807             goto exit;
00808         }
00809         break;
00810     }
00811     msg = _free(msg);
00812 
00813 #define _chk(_mask)     (sigtag == 0 && !(vsflags & (_mask)))
00814 
00815     /* Figger the most effective available signature. */
00816     sigtag = 0;
00817     vsflags = rpmtsVSFlags(ts);
00818 #ifdef  DYING
00819     if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA))
00820         sigtag = RPMSIGTAG_DSA;
00821     if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA))
00822         sigtag = RPMSIGTAG_RSA;
00823 #endif
00824     if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
00825         headerIsEntry(sigh, RPMSIGTAG_GPG))
00826     {
00827         sigtag = RPMSIGTAG_GPG;
00828         fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00829     }
00830     if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
00831         headerIsEntry(sigh, RPMSIGTAG_PGP))
00832     {
00833         sigtag = RPMSIGTAG_PGP;
00834         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00835     }
00836 #ifdef  DYING
00837     if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1))
00838         sigtag = RPMSIGTAG_SHA1;
00839 #endif
00840     if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
00841         headerIsEntry(sigh, RPMSIGTAG_MD5))
00842     {
00843         sigtag = RPMSIGTAG_MD5;
00844         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00845     }
00846 
00847     /* Read the metadata, computing digest(s) on the fly. */
00848     h = NULL;
00849     msg = NULL;
00850     rc = rpmReadHeader(ts, fd, &h, &msg);
00851     if (rc != RPMRC_OK || h == NULL) {
00852         rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
00853                 (msg && *msg ? msg : "\n"));
00854         msg = _free(msg);
00855         goto exit;
00856     }
00857     msg = _free(msg);
00858 
00859     /* Any signatures to check? */
00860     if (sigtag == 0) {
00861         rc = RPMRC_OK;
00862         goto exit;
00863     }
00864 
00865     dig = rpmtsDig(ts);
00866     if (dig == NULL) {
00867         rc = RPMRC_FAIL;
00868         goto exit;
00869     }
00870     dig->nbytes = 0;
00871 
00872     /* Retrieve the tag parameters from the signature header. */
00873     sig = NULL;
00874     xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
00875     if (sig == NULL) {
00876         rc = RPMRC_FAIL;
00877         goto exit;
00878     }
00879     (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
00880 
00881     switch (sigtag) {
00882     case RPMSIGTAG_RSA:
00883         /* Parse the parameters from the OpenPGP packets that will be needed. */
00884         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00885         /* XXX only V3 signatures for now. */
00886         if (dig->signature.version != 3) {
00887             rpmMessage(RPMMESS_WARNING,
00888                 _("only V3 signatures can be verified, skipping V%u signature\n"),
00889                 dig->signature.version);
00890             rc = RPMRC_OK;
00891             goto exit;
00892         }
00893     {   void * uh = NULL;
00894         int_32 uht;
00895         int_32 uhc;
00896 
00897         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00898             break;
00899         dig->md5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
00900         (void) rpmDigestUpdate(dig->md5ctx, header_magic, sizeof(header_magic));
00901         dig->nbytes += sizeof(header_magic);
00902         (void) rpmDigestUpdate(dig->md5ctx, uh, uhc);
00903         dig->nbytes += uhc;
00904         uh = headerFreeData(uh, uht);
00905     }   break;
00906     case RPMSIGTAG_DSA:
00907         /* Parse the parameters from the OpenPGP packets that will be needed. */
00908         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00909         /* XXX only V3 signatures for now. */
00910         if (dig->signature.version != 3) {
00911             rpmMessage(RPMMESS_WARNING,
00912                 _("only V3 signatures can be verified, skipping V%u signature\n"),
00913                 dig->signature.version);
00914             rc = RPMRC_OK;
00915             goto exit;
00916         }
00917         /*@fallthrough@*/
00918     case RPMSIGTAG_SHA1:
00919     {   void * uh = NULL;
00920         int_32 uht;
00921         int_32 uhc;
00922 
00923         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00924             break;
00925         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00926         (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
00927         dig->nbytes += sizeof(header_magic);
00928         (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
00929         dig->nbytes += uhc;
00930         uh = headerFreeData(uh, uht);
00931     }   break;
00932     case RPMSIGTAG_GPG:
00933     case RPMSIGTAG_PGP5:        /* XXX legacy */
00934     case RPMSIGTAG_PGP:
00935         /* Parse the parameters from the OpenPGP packets that will be needed. */
00936         xx = pgpPrtPkts(sig, siglen, dig,
00937                         (_print_pkts & rpmIsDebug()));
00938 
00939         /* XXX only V3 signatures for now. */
00940         if (dig->signature.version != 3) {
00941             rpmMessage(RPMMESS_WARNING,
00942                 _("only V3 signatures can be verified, skipping V%u signature\n"),
00943                 dig->signature.version);
00944             rc = RPMRC_OK;
00945             goto exit;
00946         }
00947         /*@fallthrough@*/
00948     case RPMSIGTAG_MD5:
00949         /* Legacy signatures need the compressed payload in the digest too. */
00950         hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
00951         dig->nbytes += headerSizeof(h, hmagic);
00952         while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00953             dig->nbytes += count;
00954         if (count < 0) {
00955             rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
00956                                         fn, Fstrerror(fd));
00957             rc = RPMRC_FAIL;
00958             goto exit;
00959         }
00960         dig->nbytes += count;
00961 
00962         /* XXX Steal the digest-in-progress from the file handle. */
00963         for (i = fd->ndigests - 1; i >= 0; i--) {
00964             FDDIGEST_t fddig = fd->digests + i;
00965             if (fddig->hashctx == NULL)
00966                 continue;
00967             if (fddig->hashalgo == PGPHASHALGO_MD5) {
00968                 dig->md5ctx = fddig->hashctx;
00969                 fddig->hashctx = NULL;
00970                 continue;
00971             }
00972             if (fddig->hashalgo == PGPHASHALGO_SHA1) {
00973                 dig->sha1ctx = fddig->hashctx;
00974                 fddig->hashctx = NULL;
00975                 continue;
00976             }
00977         }
00978         break;
00979     }
00980 
00983 /*@-boundswrite@*/
00984     buf[0] = '\0';
00985 /*@=boundswrite@*/
00986     rc = rpmVerifySignature(ts, buf);
00987     switch (rc) {
00988     case RPMRC_OK:              /* Signature is OK. */
00989         rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
00990         break;
00991     case RPMRC_NOTTRUSTED:      /* Signature is OK, but key is not trusted. */
00992     case RPMRC_NOKEY:           /* Public key is unavailable. */
00993         /* XXX Print NOKEY/NOTTRUSTED warning only once. */
00994     {   int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
00995         rpmMessage(lvl, "%s: %s", fn, buf);
00996     }   break;
00997     case RPMRC_NOTFOUND:        /* Signature is unknown type. */
00998         rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
00999         break;
01000     default:
01001     case RPMRC_FAIL:            /* Signature does not verify. */
01002         rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
01003         break;
01004     }
01005 
01006 exit:
01007     if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
01008         /* Convert legacy headers on the fly ... */
01009         legacyRetrofit(h, l);
01010         
01011         /* Append (and remap) signature tags to the metadata. */
01012         headerMergeLegacySigs(h, sigh);
01013 
01014         /* Bump reference count for return. */
01015 /*@-boundswrite@*/
01016         *hdrp = headerLink(h);
01017 /*@=boundswrite@*/
01018     }
01019     h = headerFree(h);
01020     rpmtsCleanDig(ts);
01021     sigh = rpmFreeSignature(sigh);
01022     return rc;
01023 }
01024 /*@=bounds@*/

Generated on Thu May 19 18:31:17 2005 for rpm by doxygen 1.3.5