rpm 5.2.1

- 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 }