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

Generated on Mon Nov 29 2010 05:18:46 for rpm by  doxygen 1.7.2