• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

rpmdb/pkgio.c

Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #if defined(HAVE_MACHINE_TYPES_H)
00009 # include <machine/types.h>
00010 #endif
00011 
00012 #include <netinet/in.h>
00013 
00014 #define _RPMIOB_INTERNAL
00015 #include <rpmiotypes.h>
00016 #include <rpmio_internal.h>
00017 #include <rpmcb.h>
00018 #include <rpmbc.h>              /* XXX beecrypt base64 */
00019 #include <rpmmacro.h>
00020 #include <rpmku.h>
00021 
00022 #define _RPMTAG_INTERNAL
00023 #include "header_internal.h"
00024 
00025 #include <rpmdb.h>
00026 #include <pkgio.h>
00027 
00028 #define _RPMTS_INTERNAL
00029 #include "rpmts.h"
00030 
00031 #include <rpmxar.h>
00032 
00033 #include "signature.h"
00034 #include "debug.h"
00035 
00036 /*@access rpmts @*/
00037 /*@access rpmxar @*/
00038 /*@access pgpDig @*/
00039 /*@access pgpDigParams @*/
00040 /*@access Header @*/            /* XXX compared with NULL */
00041 /*@access entryInfo @*/
00042 /*@access indexEntry @*/
00043 /*@access FD_t @*/              /* XXX stealing digests */
00044 /*@access FDSTAT_t @*/          /* XXX stealing digests */
00045 
00046 /*@unchecked@*/
00047 int _pkgio_debug = 0;
00048 
00049 /*@unchecked@*/
00050 static int _print_pkts = 0;
00051 
00054 /*@-exportheader@*/
00055 /*@unused@*/ ssize_t timedRead(FD_t fd, /*@out@*/ void * bufptr, size_t length)
00056         /*@globals fileSystem @*/
00057         /*@modifies fd, *bufptr, fileSystem @*/;
00058 #define timedRead       (ufdio->read)
00059 /*@=exportheader@*/
00060 
00061 /*===============================================*/
00069 static
00070 rpmRC rpmWriteHeader(FD_t fd, /*@null@*/ Header h, /*@null@*/ const char ** msg)
00071         /*@globals fileSystem, internalState @*/
00072         /*@modifies fd, h, *msg, fileSystem, internalState @*/
00073 {
00074     const void * uh = NULL;
00075     size_t nb;
00076     size_t length;
00077     rpmRC rc = RPMRC_FAIL;      /* assume failure */
00078 
00079 if (_pkgio_debug)
00080 fprintf(stderr, "--> rpmWriteHeader(%p, %p, %p)\n", fd, h, msg);
00081 
00082     if (h == NULL) {
00083         if (msg)
00084             *msg = xstrdup(_("write of NULL header"));
00085         goto exit;
00086     }
00087 
00088     uh = headerUnload(h, &length);
00089     if (uh == NULL) {
00090         if (msg)
00091             *msg = xstrdup(_("headerUnload failed"));
00092         goto exit;
00093     }
00094 
00095     {   unsigned char * hmagic = NULL;
00096         size_t nmagic = 0;
00097 
00098         (void) headerGetMagic(NULL, &hmagic, &nmagic);
00099         nb = Fwrite(hmagic, sizeof(hmagic[0]), nmagic, fd);
00100         if (nb != nmagic || Ferror(fd)) {
00101             if (msg)
00102                 *msg = (nb > 0
00103                         ? xstrdup(_("short write of header magic"))
00104                         : xstrdup(Fstrerror(fd)) );
00105             goto exit;
00106         }
00107     }
00108 
00109     /*@-sizeoftype@*/
00110     nb = Fwrite(uh, sizeof(char), length, fd);
00111     /*@=sizeoftype@*/
00112     if (nb != length || Ferror(fd)) {
00113         if (msg)
00114             *msg = (nb > 0
00115                     ? xstrdup(_("short write of header"))
00116                     : xstrdup(Fstrerror(fd)) );
00117             goto exit;
00118     }
00119     rc = RPMRC_OK;
00120 
00121 exit:
00122     uh = _free(uh);
00123     return rc;
00124 }
00125 
00126 /*===============================================*/
00127 
00128 rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
00129 {
00130     rpmop op = NULL;
00131 
00132     if (ts != NULL && (int)opx >= 0 && (int)opx < RPMTS_OP_MAX)
00133         op = ts->ops + opx;
00134 /*@-usereleased -compdef @*/
00135     return op;
00136 /*@=usereleased =compdef @*/
00137 }
00138 
00139 pgpDigParams rpmtsPubkey(const rpmts ts)
00140 {
00141 /*@-onlytrans@*/
00142     return pgpGetPubkey(rpmtsDig(ts));
00143 /*@=onlytrans@*/
00144 }
00145 
00146 rpmdb rpmtsGetRdb(rpmts ts)
00147 {
00148     rpmdb rdb = NULL;
00149     if (ts != NULL) {
00150         rdb = ts->rdb;
00151     }
00152 /*@-compdef -refcounttrans -usereleased @*/
00153     return rdb;
00154 /*@=compdef =refcounttrans =usereleased @*/
00155 }
00156 
00157 rpmRC rpmtsFindPubkey(rpmts ts, void * _dig)
00158 {
00159     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00160     pgpDig dig = (_dig ? _dig : rpmtsDig(ts));
00161     pgpDigParams sigp = pgpGetSignature(dig);
00162     pgpDigParams pubp = pgpGetPubkey(dig);
00163     rpmRC res = RPMRC_NOKEY;
00164     const char * pubkeysource = NULL;
00165     rpmiob iob = NULL;
00166     int krcache = 1;    /* XXX assume pubkeys are cached in keyutils keyring. */
00167     int xx;
00168 
00169 assert(dig != NULL);
00170 assert(sigp != NULL);
00171 assert(pubp != NULL);
00172 /*@-sefparams@*/
00173 assert(rpmtsDig(ts) == dig);
00174 /*@=sefparams@*/
00175 
00176 #if 0
00177 fprintf(stderr, "==> find sig id %08x %08x ts pubkey id %08x %08x\n",
00178 pgpGrab(sigp->signid, 4), pgpGrab(sigp->signid+4, 4),
00179 pgpGrab(ts->pksignid, 4), pgpGrab(ts->pksignid+4, 4));
00180 #endif
00181 
00182     /* Lazy free of previous pubkey if pubkey does not match this signature. */
00183     if (memcmp(sigp->signid, ts->pksignid, sizeof(ts->pksignid))) {
00184 #if 0
00185 fprintf(stderr, "*** free pkt %p[%d] id %08x %08x\n", ts->pkpkt, ts->pkpktlen, pgpGrab(ts->pksignid, 4), pgpGrab(ts->pksignid+4, 4));
00186 #endif
00187         ts->pkpkt = _free(ts->pkpkt);
00188         ts->pkpktlen = 0;
00189         memset(ts->pksignid, 0, sizeof(ts->pksignid));
00190     }
00191 
00192     /* Try keyutils keyring lookup. */
00193     if (ts->pkpkt == NULL) {
00194         iob = NULL;
00195         switch (rpmkuFindPubkey(sigp, &iob)) {
00196         case RPMRC_NOTFOUND:
00197         case RPMRC_FAIL:
00198         case RPMRC_NOTTRUSTED:
00199         case RPMRC_NOKEY:
00200             break;
00201         case RPMRC_OK:
00202             pubkeysource = xstrdup("keyutils");
00203             krcache = 0;        /* XXX don't bother caching. */
00204             ts->pkpkt = memcpy(xmalloc(iob->blen), iob->b, iob->blen);
00205             ts->pkpktlen = iob->blen;
00206             break;
00207         }
00208     }
00209 
00210     /* Try rpmdb keyring lookup. */
00211     if (ts->pkpkt == NULL) {
00212         unsigned hx = 0xffffffff;
00213         unsigned ix = 0xffffffff;
00214         rpmmi mi;
00215         Header h;
00216 
00217         /* XXX Do a lazy open if not done already. */
00218         if (ts->rdb == NULL) {
00219             xx = rpmdbOpen(ts->rootDir, &ts->rdb, ts->dbmode, 0644);
00220             if (xx) {
00221                 const char * dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
00222                 rpmlog(RPMLOG_ERR,
00223                         _("cannot open Packages database in %s\n"), dn);
00224                 dn = _free(dn);
00225             }
00226         }
00227 
00228         /* Retrieve the pubkey that matches the signature. */
00229         he->tag = RPMTAG_PUBKEYS;
00230 /*@-nullstate@*/
00231         mi = rpmmiInit(rpmtsGetRdb(ts), RPMTAG_PUBKEYS, sigp->signid, sizeof(sigp->signid));
00232 /*@=nullstate@*/
00233         while ((h = rpmmiNext(mi)) != NULL) {
00234             if (!headerGet(h, he, 0))
00235                 continue;
00236             hx = rpmmiInstance(mi);
00237             ix = rpmmiFilenum(mi);
00238 /*@-moduncon -nullstate @*/
00239             if (ix >= (unsigned) he->c
00240              || b64decode(he->p.argv[ix], (void **) &ts->pkpkt, &ts->pkpktlen))
00241                 ix = 0xffffffff;
00242 /*@=moduncon =nullstate @*/
00243             he->p.ptr = _free(he->p.ptr);
00244             break;
00245         }
00246         mi = rpmmiFree(mi);
00247 
00248         if (ix < 0xffffffff) {
00249             char hnum[32];
00250             sprintf(hnum, "h#%u", hx);
00251             pubkeysource = xstrdup(hnum);
00252         } else {
00253             ts->pkpkt = _free(ts->pkpkt);
00254             ts->pkpktlen = 0;
00255         }
00256     }
00257 
00258     /* Try keyserver lookup. */
00259     if (ts->pkpkt == NULL) {
00260         const char * fn = rpmExpand("%{_hkp_keyserver_query}",
00261                         pgpHexStr(sigp->signid, sizeof(sigp->signid)), NULL);
00262 
00263         xx = 0;
00264         if (fn && *fn != '%') {
00265             xx = (pgpReadPkts(fn, &ts->pkpkt, &ts->pkpktlen) != PGPARMOR_PUBKEY);
00266         }
00267         fn = _free(fn);
00268         if (xx) {
00269             ts->pkpkt = _free(ts->pkpkt);
00270             ts->pkpktlen = 0;
00271         } else {
00272             /* Save new pubkey in local ts keyring for delayed import. */
00273             pubkeysource = xstrdup("keyserver");
00274         }
00275     }
00276 
00277 #ifdef  NOTNOW
00278     /* Try filename from macro lookup. */
00279     if (ts->pkpkt == NULL) {
00280         const char * fn = rpmExpand("%{_gpg_pubkey}", NULL);
00281 
00282         xx = 0;
00283         if (fn && *fn != '%')
00284             xx = (pgpReadPkts(fn,&ts->pkpkt,&ts->pkpktlen) != PGPARMOR_PUBKEY);
00285         fn = _free(fn);
00286         if (xx) {
00287             ts->pkpkt = _free(ts->pkpkt);
00288             ts->pkpktlen = 0;
00289         } else {
00290             pubkeysource = xstrdup("macro");
00291         }
00292     }
00293 #endif
00294 
00295     /* Was a matching pubkey found? */
00296     if (ts->pkpkt == NULL || ts->pkpktlen == 0)
00297         goto exit;
00298 
00299     /* Retrieve parameters from pubkey packet(s). */
00300     xx = pgpPrtPkts((rpmuint8_t *)ts->pkpkt, ts->pkpktlen, dig, 0);
00301 
00302     /* Do the parameters match the signature? */
00303     if (sigp->pubkey_algo == pubp->pubkey_algo
00304 #ifdef  NOTYET
00305      && sigp->hash_algo == pubp->hash_algo
00306 #endif
00307      && !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid)) )
00308     {
00309 
00310         /* XXX Verify any pubkey signatures. */
00311 
00312         /* Save the pubkey in the keyutils keyring. */
00313         if (krcache) {
00314             if (iob == NULL) {
00315                 iob = rpmiobNew(ts->pkpktlen);
00316                 iob->b = memcpy(iob->b, ts->pkpkt, iob->blen);
00317             }
00318             (void) rpmkuStorePubkey(sigp, iob);
00319         }
00320 
00321         /* Pubkey packet looks good, save the signer id. */
00322         memcpy(ts->pksignid, pubp->signid, sizeof(ts->pksignid));
00323 
00324         if (pubkeysource)
00325             rpmlog(RPMLOG_DEBUG, "========== %s pubkey id %08x %08x (%s)\n",
00326                 (sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_DSA ? "DSA" :
00327                 (sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA ? "RSA" :
00328                         "???")),
00329                 pgpGrab(sigp->signid, 4), pgpGrab(sigp->signid+4, 4),
00330                 pubkeysource);
00331 
00332         res = RPMRC_OK;
00333     }
00334 
00335 exit:
00336     pubkeysource = _free(pubkeysource);
00337     if (res != RPMRC_OK) {
00338         ts->pkpkt = _free(ts->pkpkt);
00339         ts->pkpktlen = 0;
00340     }
00341 /*@-nullstate@*/
00342     return res;
00343 /*@=nullstate@*/
00344 }
00345 
00346 pgpDig rpmtsDig(rpmts ts)
00347 {
00348 /*@-mods@*/ /* FIX: hide lazy malloc for now */
00349     if (ts->dig == NULL) {
00350         ts->dig = pgpDigNew(0);
00351 /*@-refcounttrans@*/
00352         (void) pgpSetFindPubkey(ts->dig, (int (*)(void *, void *))rpmtsFindPubkey, ts);
00353 /*@=refcounttrans@*/
00354     }
00355 /*@=mods@*/
00356 /*@-compdef -retexpose -usereleased@*/
00357     return ts->dig;
00358 /*@=compdef =retexpose =usereleased@*/
00359 }
00360 
00361 void rpmtsCleanDig(rpmts ts)
00362 {
00363     if (ts && ts->dig) {
00364         int opx;
00365         opx = RPMTS_OP_DIGEST;
00366         (void) rpmswAdd(rpmtsOp(ts, opx), pgpStatsAccumulator(ts->dig, opx));
00367         opx = RPMTS_OP_SIGNATURE;
00368         (void) rpmswAdd(rpmtsOp(ts, opx), pgpStatsAccumulator(ts->dig, opx));
00369 /*@-onlytrans@*/
00370         (void) pgpDigFree(ts->dig, "rpmtsCleanDig");
00371         ts->dig = NULL;         /* XXX make sure the ptr is __REALLY__ gone */
00372 /*@=onlytrans@*/
00373     }
00374 }
00375 
00376 /*===============================================*/
00377 
00384 struct rpmlead {
00385     unsigned char magic[4];
00386     unsigned char major;
00387     unsigned char minor;
00388     unsigned short type;
00389     unsigned short archnum;
00390     char name[66];
00391     unsigned short osnum;
00392     unsigned short signature_type; 
00393 /*@unused@*/
00394     char reserved[16];          
00395 } ;
00396 
00397 /*@-type@*/
00398 /*@unchecked@*/ /*@observer@*/
00399 static unsigned char lead_magic[] = {
00400     0xed, 0xab, 0xee, 0xdb, 0x00, 0x00, 0x00, 0x00
00401 };
00402 /*@=type@*/
00403 
00404 /* The lead needs to be 8 byte aligned */
00405 
00413 static rpmRC wrLead(FD_t fd, const void * ptr, /*@null@*/ const char ** msg)
00414         /*@globals fileSystem @*/
00415         /*@modifies fd, fileSystem @*/
00416 {
00417     struct rpmlead l;
00418 
00419 if (_pkgio_debug)
00420 fprintf(stderr, "--> wrLead(%p, %p, %p)\n", fd, ptr, msg);
00421 
00422     memcpy(&l, ptr, sizeof(l));
00423 
00424     /* Set some sane defaults */
00425     if ((int)l.major == 0)
00426         l.major = (unsigned char) 3;
00427     if (l.signature_type == 0)
00428         l.signature_type = 5;           /* RPMSIGTYPE_HEADERSIG */
00429     if (msg && *msg)
00430         (void) strncpy(l.name, *msg, sizeof(l.name));
00431     
00432     memcpy(&l.magic, lead_magic, sizeof(l.magic));
00433     l.type = (unsigned short) htons(l.type);
00434     l.archnum = (unsigned short) htons(l.archnum);
00435     l.osnum = (unsigned short) htons(l.osnum);
00436     l.signature_type = (unsigned short) htons(l.signature_type);
00437         
00438     if (Fwrite(&l, 1, sizeof(l), fd) != sizeof(l))
00439         return RPMRC_FAIL;
00440 
00441     return RPMRC_OK;
00442 }
00443 
00451 static rpmRC rdLead(FD_t fd, /*@out@*/ /*@null@*/ void * ptr,
00452                 /*@null@*/ const char ** msg)
00453         /*@globals fileSystem @*/
00454         /*@modifies fd, *ptr, *msg, fileSystem @*/
00455 {
00456     rpmxar xar = fdGetXAR(fd);
00457     struct rpmlead ** leadp = ptr;
00458     struct rpmlead * l = xcalloc(1, sizeof(*l));
00459     char buf[BUFSIZ];
00460     rpmRC rc = RPMRC_FAIL;              /* assume failure */
00461     int xx;
00462 
00463 if (_pkgio_debug)
00464 fprintf(stderr, "--> rdLead(%p, %p, %p)\n", fd, ptr, msg);
00465 
00466     buf[0] = '\0';
00467     if (leadp != NULL) *leadp = NULL;
00468 
00469     /* Read the first 96 bytes of the file. */
00470     if ((xx = (int) timedRead(fd, (char *)l, sizeof(*l))) != (int) sizeof(*l)) {
00471         if (Ferror(fd)) {
00472             (void) snprintf(buf, sizeof(buf),
00473                 _("lead size(%u): BAD, read(%d), %s(%d)"),
00474                 (unsigned)sizeof(*l), xx, Fstrerror(fd), errno);
00475             rc = RPMRC_FAIL;
00476         } else {
00477             (void) snprintf(buf, sizeof(buf),
00478                 _("lead size(%u): BAD, read(%d), %s(%d)"),
00479                 (unsigned)sizeof(*l), xx, strerror(errno), errno);
00480             rc = RPMRC_NOTFOUND;
00481         }
00482         goto exit;
00483     }
00484 
00485     /* Attach rpmxar handler to fd if this is a xar archive. */
00486     if (xar == NULL) {
00487         unsigned char * bh = (unsigned char *)l;
00488         if (bh[0] == 'x' && bh[1] == 'a' && bh[2] == 'r' && bh[3] == '!') {
00489             const char * fn = fdGetOPath(fd);
00490 assert(fn != NULL);
00491             xar = rpmxarNew(fn, "r");
00492             fdSetXAR(fd, xar);
00493             (void) rpmxarFree(xar, "rdLead");
00494         }
00495     }
00496 
00497     /* With XAR, read lead from a xar archive file called "Lead". */
00498     xar = fdGetXAR(fd);
00499     if (xar != NULL) {
00500         unsigned char *b = NULL;
00501         size_t nb = 0;
00502         const char item[] = "Lead";
00503         if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) {
00504             (void) snprintf(buf, sizeof(buf),
00505                 _("XAR file not found (or no XAR support)"));
00506             rc = RPMRC_NOTFOUND;
00507             goto exit;
00508         }
00509         (void) rpmxarSwapBuf(xar, NULL, 0, &b, &nb);
00510         if (nb != sizeof(*l)) {
00511             (void) snprintf(buf, sizeof(buf),
00512                 _("lead size(%u): BAD, xar read(%u)"),
00513                 (unsigned)sizeof(*l), (unsigned)nb);
00514             b = _free(b);
00515             rc = RPMRC_FAIL;
00516             goto exit;
00517         }
00518         memcpy(l, b, nb);
00519         b = _free(b);
00520     }
00521 
00522     l->type = (unsigned short) ntohs(l->type);
00523     l->archnum = (unsigned short) ntohs(l->archnum);
00524     l->osnum = (unsigned short) ntohs(l->osnum);
00525     l->signature_type = (unsigned short) ntohs(l->signature_type);
00526 
00527     if (memcmp(l->magic, lead_magic, sizeof(l->magic))) {
00528 /*@+charint@*/
00529         (void) snprintf(buf, sizeof(buf), _("lead magic: BAD, read %02x%02x%02x%02x"), l->magic[0], l->magic[1], l->magic[2], l->magic[3]);
00530 /*@=charint@*/
00531         rc = RPMRC_NOTFOUND;
00532         goto exit;
00533     }
00534 
00535     switch (l->major) {
00536     default:
00537         (void) snprintf(buf, sizeof(buf),
00538                 _("lead version(%u): UNSUPPORTED"), (unsigned) l->major);
00539         rc = RPMRC_NOTFOUND;
00540         goto exit;
00541         /*@notreached@*/ break;
00542     case 3:
00543     case 4:
00544         break;
00545     }
00546 
00547     if (l->signature_type != 5) {       /* RPMSIGTYPE_HEADERSIG */
00548         (void) snprintf(buf, sizeof(buf),
00549                 _("sigh type(%u): UNSUPPORTED"), (unsigned) l->signature_type);
00550         rc = RPMRC_NOTFOUND;
00551         goto exit;
00552     }
00553 
00554     rc = RPMRC_OK;
00555 
00556 exit:
00557     if (rc == RPMRC_OK && leadp != NULL)
00558         *leadp = l;
00559     else
00560         /*@-dependenttrans@*/ l = _free(l); /*@=dependenttrans@*/
00561         
00562     if (msg != NULL && buf[0] != '\0') {
00563         buf[sizeof(buf)-1] = '\0';
00564         *msg = xstrdup(buf);
00565     }
00566     return rc;
00567 }
00568 
00569 /*===============================================*/
00570 
00578 static rpmRC wrSignature(FD_t fd, void * ptr,
00579                 /*@unused@*/ /*@null@*/ const char ** msg)
00580         /*@globals fileSystem, internalState @*/
00581         /*@modifies fd, ptr, *msg, fileSystem, internalState @*/
00582 {
00583     Header sigh = ptr;
00584     static unsigned char zero[8]
00585         = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' };
00586     size_t sigSize;
00587     size_t pad;
00588     rpmRC rc = RPMRC_OK;
00589 
00590 if (_pkgio_debug)
00591 fprintf(stderr, "--> wrSignature(%p, %p, %p)\n", fd, ptr, msg);
00592 
00593     rc = rpmWriteHeader(fd, sigh, msg);
00594     if (rc != RPMRC_OK)
00595         return rc;
00596 
00597     sigSize = headerSizeof(sigh);
00598     pad = (8 - (sigSize % 8)) % 8;
00599     if (pad) {
00600         if (Fwrite(zero, sizeof(zero[0]), pad, fd) != pad)
00601             rc = RPMRC_FAIL;
00602     }
00603     rpmlog(RPMLOG_DEBUG, D_("Signature: size(%u)+pad(%u)\n"), (unsigned)sigSize, (unsigned)pad);
00604     return rc;
00605 }
00606 
00615 static inline rpmRC printSize(FD_t fd, size_t siglen, size_t pad, size_t datalen)
00616         /*@globals fileSystem, internalState @*/
00617         /*@modifies fileSystem, internalState @*/
00618 {
00619     struct stat sb, * st = &sb;
00620     size_t expected;
00621     size_t nl = rpmpkgSizeof("Lead", NULL);
00622 
00623 #ifndef DYING   /* XXX Fstat(2) contentLength not gud enuf yet. */
00624     int fdno = Fileno(fd);
00625     /* HACK: workaround for davRead wiring. */
00626     if (fdno == 123456789) {
00627 /*@-type@*/
00628         st->st_size = 0;
00629         st->st_size -= nl + siglen + pad + datalen;
00630 /*@=type@*/
00631     } else
00632 #endif
00633     if (Fstat(fd, st) < 0)
00634         return RPMRC_FAIL;
00635 
00636     expected = nl + siglen + pad + datalen;
00637     rpmlog(RPMLOG_DEBUG,
00638         D_("Expected size: %12lu = lead(%u)+sigs(%u)+pad(%u)+data(%lu)\n"),
00639                 (unsigned long)expected,
00640                 (unsigned)nl, (unsigned) siglen, (unsigned) pad,
00641                 (unsigned long)datalen);
00642     rpmlog(RPMLOG_DEBUG,
00643         D_("  Actual size: %12lu\n"), (unsigned long)st->st_size);
00644 
00645     return RPMRC_OK;
00646 }
00647 
00655 static rpmRC rdSignature(FD_t fd, /*@out@*/ /*@null@*/ void * ptr,
00656                 /*@null@*/ const char ** msg)
00657         /*@globals fileSystem, internalState @*/
00658         /*@modifies *ptr, *msg, fileSystem, internalState @*/
00659 {
00660 rpmxar xar = fdGetXAR(fd);
00661     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00662     Header * sighp = ptr;
00663     char buf[BUFSIZ];
00664     rpmuint32_t block[4];
00665     rpmuint32_t il;
00666     rpmuint32_t dl;
00667     rpmuint32_t * ei = NULL;
00668     entryInfo pe;
00669     size_t startoff;
00670     size_t nb;
00671     rpmuint32_t ril = 0;
00672     indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
00673     entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
00674     unsigned char * dataStart;
00675     unsigned char * dataEnd = NULL;
00676     Header sigh = NULL;
00677     rpmRC rc = RPMRC_FAIL;              /* assume failure */
00678     int xx;
00679     rpmuint32_t i;
00680     static int map = 1;
00681 
00682 if (_pkgio_debug)
00683 fprintf(stderr, "--> rdSignature(%p, %p, %p)\n", fd, ptr, msg);
00684 
00685     buf[0] = '\0';
00686     if (sighp)
00687         *sighp = NULL;
00688 
00689     memset(block, 0, sizeof(block));
00690     if (xar != NULL) {
00691         const char item[] = "Signature";
00692         if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) {
00693             (void) snprintf(buf, sizeof(buf),
00694                 _("XAR file not found (or no XAR support)"));
00695             rc = RPMRC_NOTFOUND;
00696             goto exit;
00697         }
00698     }
00699     startoff = fd->stats->ops[FDSTAT_READ].bytes;
00700     if ((xx = (int) timedRead(fd, (void *)block, sizeof(block))) != (int) sizeof(block)) {
00701         (void) snprintf(buf, sizeof(buf),
00702                 _("sigh size(%d): BAD, read returned %d"), (int)sizeof(block), xx);
00703         goto exit;
00704     }
00705 
00706     {   unsigned char * hmagic = NULL;
00707         size_t nmagic = 0;
00708 
00709         (void) headerGetMagic(NULL, &hmagic, &nmagic);
00710 
00711         if (memcmp(block, hmagic, nmagic)) {
00712             unsigned char * x = (unsigned char *)block;
00713 /*@+charint@*/
00714             (void) snprintf(buf, sizeof(buf), _("sigh magic: BAD, read %02x%02x%02x%02x%02x%02x%02x%02x"), x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]);
00715 /*@=charint@*/
00716             goto exit;
00717         }
00718     }
00719     il = (rpmuint32_t) ntohl(block[2]);
00720     if (il > 32) {
00721         (void) snprintf(buf, sizeof(buf),
00722                 _("sigh tags: BAD, no. of tags(%u) out of range"), (unsigned) il);
00723         goto exit;
00724     }
00725     dl = (rpmuint32_t) ntohl(block[3]);
00726     if (dl > 8192) {
00727         (void) snprintf(buf, sizeof(buf),
00728                 _("sigh data: BAD, no. of bytes(%u) out of range"), (unsigned) dl);
00729         goto exit;
00730     }
00731 
00732 /*@-sizeoftype@*/
00733     nb = (il * sizeof(struct entryInfo_s)) + dl;
00734 /*@=sizeoftype@*/
00735     if (map) {
00736         size_t pvlen = (sizeof(il) + sizeof(dl) + nb);
00737         static const int prot = PROT_READ | PROT_WRITE;
00738         static const int flags = MAP_PRIVATE| MAP_ANONYMOUS;
00739         static const int fdno = -1;
00740         static const off_t off = 0;
00741 
00742         ei = mmap(NULL, pvlen, prot, flags, fdno, off);
00743         if (ei == NULL || ei == (void *)-1)
00744             fprintf(stderr,
00745                 "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n",
00746                 NULL, pvlen, prot, flags, fdno, (unsigned)off,
00747                 errno, strerror(errno));
00748     } else {
00749         size_t pvlen = (sizeof(il) + sizeof(dl) + nb);
00750         ei = xmalloc(pvlen);
00751     }
00752 
00753     if ((xx = (int) timedRead(fd, (void *)&ei[2], nb)) != (int) nb) {
00754         (void) snprintf(buf, sizeof(buf),
00755                 _("sigh blob(%u): BAD, read returned %d"), (unsigned) nb, xx);
00756         goto exit;
00757     }
00758     ei[0] = block[2];
00759     ei[1] = block[3];
00760 
00761     if (map) {
00762         size_t pvlen = (sizeof(il) + sizeof(dl) + nb);
00763         if (mprotect(ei, pvlen, PROT_READ) != 0)
00764             fprintf(stderr, "==> mprotect(%p[%u],0x%x) error(%d): %s\n",
00765                         ei, pvlen, PROT_READ,
00766                         errno, strerror(errno));
00767     }
00768 
00769     pe = (entryInfo) &ei[2];
00770     dataStart = (unsigned char *) (pe + il);
00771     
00772     /* Check (and convert) the 1st tag element. */
00773     xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
00774     if (xx != -1) {
00775         (void) snprintf(buf, sizeof(buf),
00776                 _("tag[%d]: BAD, tag %u type %u offset %d count %u"),
00777                 0, (unsigned) entry->info.tag, (unsigned) entry->info.type,
00778                 (int)entry->info.offset, (unsigned) entry->info.count);
00779         goto exit;
00780     }
00781 
00782     /* Is there an immutable header region tag? */
00783 /*@-sizeoftype@*/
00784     if (entry->info.tag == RPMTAG_HEADERSIGNATURES
00785        && entry->info.type == RPM_BIN_TYPE
00786        && entry->info.count == (rpmTagCount)REGION_TAG_COUNT)
00787     {
00788 /*@=sizeoftype@*/
00789 
00790 /*
00791  * XXX http://mysql.mirrors.pair.com/Downloads/MySQL-5.0/MySQL-client-community-5.0.51a-0.rhel4.i386.rpm
00792  * built by rpm-4.3.3 (from REL4) has entry->info.offset == 0.
00793  */
00794 assert(entry->info.offset >= 0);        /* XXX insurance */
00795         if (entry->info.offset >= (rpmint32_t)dl) {
00796             (void) snprintf(buf, sizeof(buf),
00797                 _("region offset: BAD, tag %u type %u offset %d count %u"),
00798                 (unsigned) entry->info.tag, (unsigned) entry->info.type,
00799                 (int)entry->info.offset, (unsigned) entry->info.count);
00800             goto exit;
00801         }
00802 
00803         /* Is there an immutable header region tag trailer? */
00804         dataEnd = dataStart + entry->info.offset;
00805 /*@-sizeoftype@*/
00806         (void) memcpy(info, dataEnd, REGION_TAG_COUNT);
00807         /* XXX Really old packages have HEADER_IMAGE, not HEADER_SIGNATURES. */
00808         if (info->tag == (rpmuint32_t) htonl(RPMTAG_HEADERIMAGE)) {
00809             rpmuint32_t stag = (rpmuint32_t) htonl(RPMTAG_HEADERSIGNATURES);
00810             info->tag = stag;
00811             memcpy(dataEnd, &stag, sizeof(stag));
00812         }
00813         dataEnd += REGION_TAG_COUNT;
00814 
00815         xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
00816         if (xx != -1 ||
00817             !(entry->info.tag == RPMTAG_HEADERSIGNATURES
00818            && entry->info.type == RPM_BIN_TYPE
00819            && entry->info.count == (rpmTagCount)REGION_TAG_COUNT))
00820         {
00821             (void) snprintf(buf, sizeof(buf),
00822                 _("region trailer: BAD, tag %u type %u offset %d count %u"),
00823                 (unsigned) entry->info.tag, (unsigned) entry->info.type,
00824                 (int)entry->info.offset, (unsigned) entry->info.count);
00825             goto exit;
00826         }
00827 /*@=sizeoftype@*/
00828         memset(info, 0, sizeof(*info));
00829 
00830         /* Is the no. of tags in the region less than the total no. of tags? */
00831         ril = (rpmuint32_t) (entry->info.offset/sizeof(*pe));
00832         if ((entry->info.offset % sizeof(*pe)) || ril > il) {
00833             (void) snprintf(buf, sizeof(buf),
00834                 _("region size: BAD, ril(%u) > il(%u)"), (unsigned) ril, (unsigned) il);
00835             goto exit;
00836         }
00837     }
00838 
00839     /* Sanity check signature tags */
00840     memset(info, 0, sizeof(*info));
00841     for (i = 1; i < (unsigned) il; i++) {
00842         xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
00843         if (xx != -1) {
00844             (void) snprintf(buf, sizeof(buf),
00845                 _("sigh tag[%u]: BAD, tag %u type %u offset %d count %u"),
00846                 (unsigned) i, (unsigned) entry->info.tag, (unsigned) entry->info.type,
00847                 (int)entry->info.offset, (unsigned) entry->info.count);
00848             goto exit;
00849         }
00850     }
00851 
00852     /* OK, blob looks sane, load the header. */
00853     sigh = headerLoad(ei);
00854     if (sigh == NULL) {
00855         (void) snprintf(buf, sizeof(buf), _("sigh load: BAD"));
00856         goto exit;
00857     }
00858     if (map) {
00859         sigh->flags |= HEADERFLAG_MAPPED;
00860         sigh->flags |= HEADERFLAG_RDONLY;
00861     } else
00862         sigh->flags |= HEADERFLAG_ALLOCATED;
00863     sigh->flags |= HEADERFLAG_SIGNATURE;
00864 
00865     {   size_t sigSize = headerSizeof(sigh);
00866         size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */
00867 
00868         /* Position at beginning of header. */
00869         if (pad && (xx = (int) timedRead(fd, (void *)block, pad)) != (int) pad)
00870         {
00871             (void) snprintf(buf, sizeof(buf),
00872                 _("sigh pad(%u): BAD, read %d bytes"), (unsigned) pad, xx);
00873             goto exit;
00874         }
00875 
00876         /* Print package component sizes. */
00877 
00878         he->tag = (rpmTag) RPMSIGTAG_SIZE;
00879         xx = headerGet(sigh, he, 0);
00880         if (xx) {
00881             size_t datasize = he->p.ui32p[0];
00882             rc = printSize(fd, sigSize, pad, datasize);
00883             if (rc != RPMRC_OK)
00884                 (void) snprintf(buf, sizeof(buf),
00885                         _("sigh sigSize(%u): BAD, Fstat(2) failed"), (unsigned) sigSize);
00886         }
00887         he->p.ptr = _free(he->p.ptr);
00888     }
00889     (void) headerSetStartOff(sigh, (rpmuint32_t)startoff);
00890     (void) headerSetEndOff(sigh, fd->stats->ops[FDSTAT_READ].bytes);
00891 
00892 exit:
00893     if (sighp && sigh && rc == RPMRC_OK)
00894         *sighp = headerLink(sigh);
00895     (void)headerFree(sigh);
00896     sigh = NULL;
00897 
00898     if (msg != NULL) {
00899         buf[sizeof(buf)-1] = '\0';
00900         *msg = xstrdup(buf);
00901     }
00902 
00903     return rc;
00904 }
00905 
00906 /*===============================================*/
00907 
00921 rpmRC headerCheck(pgpDig dig, const void * uh, size_t uc, const char ** msg)
00922 {
00923     char buf[8*BUFSIZ];
00924     rpmuint32_t * ei = (rpmuint32_t *) uh;
00925     rpmuint32_t il = (rpmuint32_t) ntohl(ei[0]);
00926     rpmuint32_t dl = (rpmuint32_t) ntohl(ei[1]);
00927 /*@-castexpose@*/
00928     entryInfo pe = (entryInfo) &ei[2];
00929 /*@=castexpose@*/
00930     rpmuint32_t ildl[2];
00931     size_t pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
00932     unsigned char * dataStart = (unsigned char *) (pe + il);
00933     indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
00934     entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
00935     const void * sig = NULL;
00936     unsigned char * b;
00937     rpmVSFlags vsflags = pgpDigVSFlags;
00938     rpmop op;
00939     size_t siglen = 0;
00940     int blen;
00941     size_t nb;
00942     rpmuint32_t ril = 0;
00943     unsigned char * regionEnd = NULL;
00944     rpmRC rc = RPMRC_FAIL;      /* assume failure */
00945     int xx;
00946     rpmuint32_t i;
00947 
00948 if (_pkgio_debug)
00949 fprintf(stderr, "--> headerCheck(%p, %p[%u], %p)\n", dig, uh, (unsigned) uc, msg);
00950 
00951     buf[0] = '\0';
00952 
00953     /* Is the blob the right size? */
00954     if (uc > 0 && pvlen != uc) {
00955         (void) snprintf(buf, sizeof(buf),
00956                 _("blob size(%d): BAD, 8 + 16 * il(%u) + dl(%u)"),
00957                 (int)uc, (unsigned)il, (unsigned)dl);
00958         goto exit;
00959     }
00960 
00961     /* Check (and convert) the 1st tag element. */
00962     xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
00963     if (xx != -1) {
00964         (void) snprintf(buf, sizeof(buf),
00965                 _("tag[%d]: BAD, tag %u type %u offset %d count %u"),
00966                 0, (unsigned) entry->info.tag, (unsigned) entry->info.type,
00967                 (int)entry->info.offset, (unsigned) entry->info.count);
00968         goto exit;
00969     }
00970 
00971     /* Is there an immutable header region tag? */
00972 /*@-sizeoftype@*/
00973     if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00974        && entry->info.type == RPM_BIN_TYPE
00975        && entry->info.count == (rpmTagCount)REGION_TAG_COUNT))
00976     {
00977         rc = RPMRC_NOTFOUND;
00978         goto exit;
00979     }
00980 /*@=sizeoftype@*/
00981 
00982     /* Is the offset within the data area? */
00983     if (entry->info.offset >= (int) dl) {
00984         (void) snprintf(buf, sizeof(buf),
00985                 _("region offset: BAD, tag %u type %u offset %d count %u"),
00986                 (unsigned) entry->info.tag, (unsigned) entry->info.type,
00987                 (int)entry->info.offset, (unsigned) entry->info.count);
00988         goto exit;
00989     }
00990 
00991     /* Is there an immutable header region tag trailer? */
00992     regionEnd = dataStart + entry->info.offset;
00993 /*@-sizeoftype@*/
00994     (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
00995     regionEnd += REGION_TAG_COUNT;
00996 
00997     xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
00998     if (xx != -1 ||
00999         !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
01000        && entry->info.type == RPM_BIN_TYPE
01001        && entry->info.count == (rpmTagCount)REGION_TAG_COUNT))
01002     {
01003         (void) snprintf(buf, sizeof(buf),
01004                 _("region trailer: BAD, tag %u type %u offset %d count %u"),
01005                 (unsigned) entry->info.tag, (unsigned) entry->info.type,
01006                 (int)entry->info.offset, (unsigned) entry->info.count);
01007         goto exit;
01008     }
01009 /*@=sizeoftype@*/
01010     memset(info, 0, sizeof(*info));
01011 
01012     /* Is the no. of tags in the region less than the total no. of tags? */
01013     ril = (rpmuint32_t) (entry->info.offset/sizeof(*pe));
01014     if ((entry->info.offset % sizeof(*pe)) || ril > il) {
01015         (void) snprintf(buf, sizeof(buf),
01016                 _("region size: BAD, ril(%u) > il(%u)"), (unsigned) ril, (unsigned)il);
01017         goto exit;
01018     }
01019 
01020     /* Find a header-only digest/signature tag. */
01021     for (i = ril; i < (unsigned) il; i++) {
01022         xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
01023         if (xx != -1) {
01024             (void) snprintf(buf, sizeof(buf),
01025                 _("tag[%u]: BAD, tag %u type %u offset %d count %u"),
01026                 (unsigned) i, (unsigned) entry->info.tag, (unsigned) entry->info.type,
01027                 (int)entry->info.offset, (unsigned) entry->info.count);
01028             goto exit;
01029         }
01030 
01031         switch (entry->info.tag) {
01032         case RPMTAG_SHA1HEADER:
01033             if (vsflags & RPMVSF_NOSHA1HEADER)
01034                 /*@switchbreak@*/ break;
01035             blen = 0;
01036             for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
01037                 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
01038                     /*@innerbreak@*/ break;
01039                 blen++;
01040             }
01041             if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
01042             {
01043                 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex"));
01044                 goto exit;
01045             }
01046             if (info->tag == 0) {
01047                 *info = entry->info;    /* structure assignment */
01048                 siglen = blen + 1;
01049             }
01050             /*@switchbreak@*/ break;
01051         case RPMTAG_RSAHEADER:
01052             if (vsflags & RPMVSF_NORSAHEADER)
01053                 /*@switchbreak@*/ break;
01054             if (entry->info.type != RPM_BIN_TYPE) {
01055                 (void) snprintf(buf, sizeof(buf), _("hdr RSA: BAD, not binary"));
01056                 goto exit;
01057             }
01058             *info = entry->info;        /* structure assignment */
01059             siglen = info->count;
01060             /*@switchbreak@*/ break;
01061         case RPMTAG_DSAHEADER:
01062             if (vsflags & RPMVSF_NODSAHEADER)
01063                 /*@switchbreak@*/ break;
01064             if (entry->info.type != RPM_BIN_TYPE) {
01065                 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary"));
01066                 goto exit;
01067             }
01068             *info = entry->info;        /* structure assignment */
01069             siglen = info->count;
01070             /*@switchbreak@*/ break;
01071         default:
01072             /*@switchbreak@*/ break;
01073         }
01074     }
01075     rc = RPMRC_NOTFOUND;
01076 
01077 exit:
01078     /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
01079     if (rc != RPMRC_NOTFOUND) {
01080         buf[sizeof(buf)-1] = '\0';
01081         if (msg) *msg = xstrdup(buf);
01082 if (_pkgio_debug)
01083 fprintf(stderr, "--> headerCheck #1: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
01084         return rc;
01085     }
01086 
01087     /* If no header-only digest/signature, then do simple sanity check. */
01088     if (info->tag == 0) {
01089         xx = (ril > 0 ? headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0) : -1);
01090         if (xx != -1) {
01091             (void) snprintf(buf, sizeof(buf),
01092                 _("tag[%d]: BAD, tag %u type %u offset %d count %u"),
01093                 xx+1, (unsigned) entry->info.tag, (unsigned) entry->info.type,
01094                 (int)entry->info.offset, (unsigned) entry->info.count);
01095             rc = RPMRC_FAIL;
01096         } else {
01097             (void) snprintf(buf, sizeof(buf), "Header sanity check: OK");
01098             rc = RPMRC_OK;
01099         }
01100         buf[sizeof(buf)-1] = '\0';
01101         if (msg) *msg = xstrdup(buf);
01102 if (_pkgio_debug)
01103 fprintf(stderr, "--> headerCheck #2: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
01104         return rc;
01105     }
01106 
01107     /* Verify header-only digest/signature. */
01108 assert(dig != NULL);
01109     dig->nbytes = 0;
01110 
01111     sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
01112     {
01113         const void * osig = pgpGetSig(dig);
01114 /*@-modobserver -observertrans -dependenttrans @*/      /* FIX: pgpSetSig() lazy free. */
01115         osig = _free(osig);
01116 /*@=modobserver =observertrans =dependenttrans @*/
01117         (void) pgpSetSig(dig, info->tag, info->type, sig, info->count);
01118     }
01119 
01120     switch (info->tag) {
01121     case RPMTAG_RSAHEADER:
01122         /* Parse the parameters from the OpenPGP packets that will be needed. */
01123         xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
01124         if (dig->signature.version != (rpmuint8_t)3
01125          && dig->signature.version != (rpmuint8_t)4)
01126         {
01127             rpmlog(RPMLOG_ERR,
01128                 _("skipping header with unverifiable V%u signature\n"),
01129                 (unsigned) dig->signature.version);
01130             rc = RPMRC_FAIL;
01131             goto exit;
01132         }
01133 
01134         ildl[0] = (rpmuint32_t) htonl(ril);
01135         ildl[1] = (rpmuint32_t) (regionEnd - dataStart);
01136         ildl[1] = (rpmuint32_t) htonl(ildl[1]);
01137 
01138         op = pgpStatsAccumulator(dig, 10);      /* RPMTS_OP_DIGEST */
01139         (void) rpmswEnter(op, 0);
01140         dig->hdrctx = rpmDigestInit((pgpHashAlgo)dig->signature.hash_algo, RPMDIGEST_NONE);
01141 
01142         b = NULL; nb = 0;
01143         (void) headerGetMagic(NULL, &b, &nb);
01144         if (b && nb > 0) {
01145             (void) rpmDigestUpdate(dig->hdrctx, b, nb);
01146             dig->nbytes += nb;
01147         }
01148 
01149         b = (unsigned char *) ildl;
01150         nb = sizeof(ildl);
01151         (void) rpmDigestUpdate(dig->hdrctx, b, nb);
01152         dig->nbytes += nb;
01153 
01154         b = (unsigned char *) pe;
01155         nb = (size_t) (htonl(ildl[0]) * sizeof(*pe));
01156         (void) rpmDigestUpdate(dig->hdrctx, b, nb);
01157         dig->nbytes += nb;
01158 
01159         b = (unsigned char *) dataStart;
01160         nb = (size_t) htonl(ildl[1]);
01161         (void) rpmDigestUpdate(dig->hdrctx, b, nb);
01162         dig->nbytes += nb;
01163         (void) rpmswExit(op, dig->nbytes);
01164 
01165         break;
01166     case RPMTAG_DSAHEADER:
01167         /* Parse the parameters from the OpenPGP packets that will be needed. */
01168         xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
01169         if (dig->signature.version != (rpmuint8_t)3
01170          && dig->signature.version != (rpmuint8_t)4)
01171         {
01172             rpmlog(RPMLOG_ERR,
01173                 _("skipping header with unverifiable V%u signature\n"),
01174                 (unsigned) dig->signature.version);
01175             rc = RPMRC_FAIL;
01176             goto exit;
01177         }
01178         /*@fallthrough@*/
01179     case RPMTAG_SHA1HEADER:
01180         ildl[0] = (rpmuint32_t) htonl(ril);
01181         ildl[1] = (rpmuint32_t) (regionEnd - dataStart);
01182         ildl[1] = (rpmuint32_t) htonl(ildl[1]);
01183 
01184         op = pgpStatsAccumulator(dig, 10);      /* RPMTS_OP_DIGEST */
01185         (void) rpmswEnter(op, 0);
01186         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
01187 
01188         b = NULL; nb = 0;
01189         (void) headerGetMagic(NULL, &b, &nb);
01190         if (b && nb > 0) {
01191             (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
01192             dig->nbytes += nb;
01193         }
01194 
01195         b = (unsigned char *) ildl;
01196         nb = sizeof(ildl);
01197         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
01198         dig->nbytes += nb;
01199 
01200         b = (unsigned char *) pe;
01201         nb = (size_t) (htonl(ildl[0]) * sizeof(*pe));
01202         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
01203         dig->nbytes += nb;
01204 
01205         b = (unsigned char *) dataStart;
01206         nb = (size_t) htonl(ildl[1]);
01207         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
01208         dig->nbytes += nb;
01209         (void) rpmswExit(op, dig->nbytes);
01210 
01211         break;
01212     default:
01213         sig = _free(sig);
01214         break;
01215     }
01216 
01217     buf[0] = '\0';
01218     rc = rpmVerifySignature(dig, buf);
01219 
01220     buf[sizeof(buf)-1] = '\0';
01221     if (msg) *msg = xstrdup(buf);
01222 
01223 if (_pkgio_debug)
01224 fprintf(stderr, "--> headerCheck #3: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
01225     return rc;
01226 }
01227 
01233 static size_t szHeader(/*@null@*/ const void * ptr)
01234         /*@*/
01235 {
01236     rpmuint32_t p[4];
01237 assert(ptr != NULL);
01238     memcpy(p, ptr, sizeof(p));
01239     return (8 + 8 + 16 * ntohl(p[2]) + ntohl(p[3]));
01240 }
01241 
01242 /*@-globuse@*/
01250 static rpmRC ckHeader(/*@unused@*/ FD_t fd, const void * ptr,
01251                 /*@unused@*/ /*@null@*/ const char ** msg)
01252         /*@globals fileSystem, internalState @*/
01253         /*@modifies ptr, fileSystem, internalState @*/
01254 {
01255     rpmRC rc = RPMRC_OK;
01256     Header h;
01257 
01258     h = headerLoad((void *)ptr);
01259     if (h == NULL)
01260         rc = RPMRC_FAIL;
01261     (void)headerFree(h);
01262     h = NULL;
01263 
01264     return rc;
01265 }
01266 
01274 static rpmRC rpmReadHeader(FD_t fd, /*@null@*/ Header * hdrp,
01275                 /*@null@*/ const char ** msg)
01276         /*@globals fileSystem, internalState @*/
01277         /*@modifies fd, *hdrp, *msg, fileSystem, internalState @*/
01278 {
01279 rpmxar xar = fdGetXAR(fd);
01280     pgpDig dig = pgpDigLink(fdGetDig(fd), "rpmReadHeader");
01281     char buf[BUFSIZ];
01282     rpmuint32_t block[4];
01283     rpmuint32_t il;
01284     rpmuint32_t dl;
01285     rpmuint32_t * ei = NULL;
01286     size_t uc = 0;
01287     unsigned char * b;
01288     size_t startoff;
01289     size_t nb;
01290     Header h = NULL;
01291     const char * origin = NULL;
01292     rpmRC rc = RPMRC_FAIL;              /* assume failure */
01293     int xx;
01294     static int map = 1;
01295 
01296 if (_pkgio_debug)
01297 fprintf(stderr, "--> rpmReadHeader(%p, %p, %p)\n", fd, hdrp, msg);
01298 
01299     /* Create (if not already) a signature parameters container. */
01300     if (dig == NULL) {
01301         dig = pgpDigNew(0);
01302         (void) fdSetDig(fd, dig);
01303     }
01304 
01305     buf[0] = '\0';
01306 
01307     if (hdrp)
01308         *hdrp = NULL;
01309 
01310     memset(block, 0, sizeof(block));
01311     if (xar != NULL) {
01312         const char item[] = "Header";
01313         if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) {
01314             (void) snprintf(buf, sizeof(buf),
01315                 _("XAR file not found (or no XAR support)"));
01316             rc = RPMRC_NOTFOUND;
01317             goto exit;
01318         }
01319     }
01320 
01321     startoff = fd->stats->ops[FDSTAT_READ].bytes;
01322     if ((xx = (int) timedRead(fd, (char *)block, sizeof(block))) != (int)sizeof(block)) {
01323         /* XXX Handle EOF's as RPMRC_NOTFOUND, not RPMRC_FAIL, returns. */
01324         if (xx == 0)
01325             rc = RPMRC_NOTFOUND;
01326         else
01327             (void) snprintf(buf, sizeof(buf),
01328                 _("hdr size(%u): BAD, read returned %d"), (unsigned)sizeof(block), xx);
01329         goto exit;
01330     }
01331 
01332     b = NULL;
01333     nb = 0;
01334     (void) headerGetMagic(NULL, &b, &nb);
01335     if (memcmp(block, b, nb)) {
01336         unsigned char * x = (unsigned char *) block;
01337 /*@+charint@*/
01338         (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD, read %02x%02x%02x%02x%02x%02x%02x%02x"), x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]);
01339 /*@=charint@*/
01340         goto exit;
01341     }
01342 
01343     il = (rpmuint32_t)ntohl(block[2]);
01344     if (hdrchkTags(il)) {
01345         (void) snprintf(buf, sizeof(buf),
01346                 _("hdr tags: BAD, no. of tags(%u) out of range"), (unsigned) il);
01347 
01348         goto exit;
01349     }
01350     dl = (rpmuint32_t)ntohl(block[3]);
01351     if (hdrchkData(dl)) {
01352         (void) snprintf(buf, sizeof(buf),
01353                 _("hdr data: BAD, no. of bytes(%u) out of range\n"), (unsigned) dl);
01354         goto exit;
01355     }
01356 
01357 /*@-sizeoftype@*/
01358     nb = (il * sizeof(struct entryInfo_s)) + dl;
01359 /*@=sizeoftype@*/
01360     uc = sizeof(il) + sizeof(dl) + nb;
01361     if (map) {
01362         static const int prot = PROT_READ | PROT_WRITE;
01363         static const int flags = MAP_PRIVATE| MAP_ANONYMOUS;
01364         static const int fdno = -1;
01365         static const off_t off = 0;
01366 
01367         ei = mmap(NULL, uc, prot, flags, fdno, off);
01368         if (ei == NULL || ei == (void *)-1)
01369             fprintf(stderr,
01370                 "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n",
01371                 NULL, uc, prot, flags, fdno, (unsigned)off,
01372                 errno, strerror(errno));
01373     } else {
01374         ei = (rpmuint32_t *) xmalloc(uc);
01375     }
01376 
01377     if ((xx = (int) timedRead(fd, (char *)&ei[2], nb)) != (int) nb) {
01378         (void) snprintf(buf, sizeof(buf),
01379                 _("hdr blob(%u): BAD, read returned %d"), (unsigned)nb, xx);
01380         goto exit;
01381     }
01382     ei[0] = block[2];
01383     ei[1] = block[3];
01384 
01385     if (map) {
01386         if (mprotect(ei, uc, PROT_READ) != 0)
01387             fprintf(stderr, "==> mprotect(%p[%u],0x%x) error(%d): %s\n",
01388                         ei, uc, PROT_READ,
01389                         errno, strerror(errno));
01390     }
01391 
01392     /* Sanity check header tags */
01393     rc = headerCheck(dig, ei, uc, msg);
01394     if (rc != RPMRC_OK)
01395         goto exit;
01396 
01397     /* OK, blob looks sane, load the header. */
01398     h = headerLoad(ei);
01399     if (h == NULL) {
01400         (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
01401         goto exit;
01402     }
01403     if (map) {
01404         h->flags |= HEADERFLAG_MAPPED;
01405         h->flags |= HEADERFLAG_RDONLY;
01406     } else
01407         h->flags |= HEADERFLAG_ALLOCATED;
01408     ei = NULL;  /* XXX will be freed with header */
01409 
01410     /* Save the opened path as the header origin. */
01411     /* XXX TODO: push the Realpath() underneath fdGetOPath(). */
01412     origin = fdGetOPath(fd);
01413     if (origin != NULL) {
01414         const char * lpath = NULL;
01415         int ut = urlPath(origin, &lpath);
01416         ut = ut;        /* XXX keep gcc quiet. */
01417         if (lpath && *lpath != '/') {
01418             char * rpath = Realpath(origin, NULL);
01419             (void) headerSetOrigin(h, rpath);
01420             rpath = _free(rpath);
01421         } else
01422             (void) headerSetOrigin(h, origin);
01423     }
01424 /*@-mods@*/
01425     {   struct stat * st = headerGetStatbuf(h);
01426         int saveno = errno;
01427         (void) Fstat(fd, st);
01428         errno = saveno;
01429     }
01430 /*@=mods@*/
01431     (void) headerSetStartOff(h, (rpmuint32_t)startoff);
01432     (void) headerSetEndOff(h, fd->stats->ops[FDSTAT_READ].bytes);
01433     
01434 exit:
01435     if (hdrp && h && rc == RPMRC_OK)
01436         *hdrp = headerLink(h);
01437     if (ei != NULL && uc > 0) {
01438         if (map) {
01439             if (munmap(ei, uc) != 0)
01440                 fprintf(stderr, "==> munmap(%p[%u]) error(%d): %s\n",
01441                 ei, uc, errno, strerror(errno));
01442             ei = NULL;
01443         } else
01444             ei = _free(ei);
01445     }
01446     dig = pgpDigFree(dig, "rpmReadHeader");
01447     (void)headerFree(h);
01448     h = NULL;
01449 
01450     if (msg != NULL && *msg == NULL && buf[0] != '\0') {
01451         buf[sizeof(buf)-1] = '\0';
01452         *msg = xstrdup(buf);
01453     }
01454 
01455 if (_pkgio_debug)
01456 fprintf(stderr, "--> rpmReadHeader: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
01457     return rc;
01458 }
01459 
01467 static rpmRC rdHeader(FD_t fd, /*@out@*/ /*@null@*/ void * ptr,
01468                 /*@null@*/ const char ** msg)
01469         /*@globals fileSystem, internalState @*/
01470         /*@modifies fd, *ptr, *msg, fileSystem, internalState @*/
01471 {
01472     Header * hdrp = ptr;
01473 /*@-compdef@*/
01474     return rpmReadHeader(fd, hdrp, msg);
01475 /*@=compdef@*/
01476 }
01477 
01485 static rpmRC wrHeader(FD_t fd, void * ptr,
01486                 /*@unused@*/ /*@null@*/ const char ** msg)
01487         /*@globals fileSystem, internalState @*/
01488         /*@modifies fd, ptr, *msg, fileSystem, internalState @*/
01489 {
01490     Header h = ptr;
01491     return rpmWriteHeader(fd, h, msg);
01492 }
01493 /*@=globuse@*/
01494 
01495 /*===============================================*/
01496 
01497 size_t rpmpkgSizeof(const char * fn, const void * ptr)
01498 {
01499     size_t len = 0;
01500 
01501     if (!strcmp(fn, "Lead"))
01502         len = 96;       /* RPMLEAD_SIZE */
01503     else
01504     if (!strcmp(fn, "Signature")) {
01505         len = szHeader(ptr);
01506         len += ((8 - (len % 8)) % 8);   /* padding */
01507     } else
01508     if (!strcmp(fn, "Header"))
01509         len = szHeader(ptr);
01510     return len;
01511 }
01512 
01513 rpmRC rpmpkgCheck(const char * fn, FD_t fd, const void * ptr, const char ** msg)
01514 {
01515     rpmRC rc = RPMRC_FAIL;
01516 
01517     if (msg)
01518         *msg = NULL;
01519 
01520     if (!strcmp(fn, "Header"))
01521         rc = ckHeader(fd, ptr, msg);
01522     return rc;
01523 }
01524 
01525 rpmRC rpmpkgRead(const char * fn, FD_t fd, void * ptr, const char ** msg)
01526 {
01527     rpmRC rc = RPMRC_FAIL;
01528 
01529     if (msg)
01530         *msg = NULL;
01531 
01532     if (!strcmp(fn, "Lead"))
01533         rc = rdLead(fd, ptr, msg);
01534     else
01535     if (!strcmp(fn, "Signature"))
01536         rc = rdSignature(fd, ptr, msg);
01537     else
01538     if (!strcmp(fn, "Header"))
01539         rc = rdHeader(fd, ptr, msg);
01540     return rc;
01541 }
01542 
01543 rpmRC rpmpkgWrite(const char * fn, FD_t fd, void * ptr, const char ** msg)
01544 {
01545     rpmRC rc = RPMRC_FAIL;
01546 
01547     if (msg)
01548         *msg = NULL;
01549 
01550     if (!strcmp(fn, "Lead"))
01551         rc = wrLead(fd, ptr, msg);
01552     else
01553     if (!strcmp(fn, "Signature"))
01554         rc = wrSignature(fd, ptr, msg);
01555     else
01556     if (!strcmp(fn, "Header"))
01557         rc = wrHeader(fd, ptr, msg);
01558     return rc;
01559 }

Generated on Fri Dec 3 2010 20:54:07 for rpm by  doxygen 1.7.2