rpm 5.3.7

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