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

Generated on Sun Apr 8 21:29:36 2012 for rpm by  doxygen 1.3.9.1