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