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>
00020 #include <rpmcb.h>
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
00038
00039
00040
00041
00042
00043
00044
00045
00046 int _pkgio_debug = 0;
00047
00048
00049 static int _print_pkts = 0;
00050
00053
00054 ssize_t timedRead(FD_t fd, void * bufptr, size_t length)
00055
00056 ;
00057 #define timedRead (ufdio->read)
00058
00059
00060
00067 static
00068 rpmRC rpmWriteHeader(FD_t fd, Header h, const char ** msg)
00069
00070
00071 {
00072 const void * uh = NULL;
00073 ssize_t nb;
00074 size_t length;
00075 rpmRC rc = RPMRC_FAIL;
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
00108 nb = Fwrite(uh, sizeof(char), length, fd);
00109
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
00133 return op;
00134
00135 }
00136
00137 pgpDigParams rpmtsPubkey(const rpmts ts)
00138 {
00139
00140 return pgpGetPubkey(rpmtsDig(ts));
00141
00142 }
00143
00144 rpmdb rpmtsGetRdb(rpmts ts)
00145 {
00146 rpmdb rdb = NULL;
00147 if (ts != NULL) {
00148 rdb = ts->rdb;
00149 }
00150
00151 return rdb;
00152
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;
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
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
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
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;
00213 } else {
00214 ts->pkpkt = _free(ts->pkpkt);
00215 ts->pkpktlen = 0;
00216 }
00217 }
00218
00219 }
00220 #endif
00221
00222
00223 if (ts->pkpkt == NULL) {
00224 unsigned hx = 0xffffffff;
00225 unsigned ix = 0xffffffff;
00226 rpmdbMatchIterator mi;
00227 Header h;
00228
00229
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
00238 if (ix >= (unsigned) he->c
00239 || b64decode(he->p.argv[ix], (void **) &ts->pkpkt, &ts->pkpktlen))
00240 ix = 0xffffffff;
00241
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
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
00272 pubkeysource = xstrdup("keyserver");
00273 }
00274 }
00275
00276 #ifdef NOTNOW
00277
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
00295 if (ts->pkpkt == NULL || ts->pkpktlen == 0)
00296 goto exit;
00297
00298
00299 xx = pgpPrtPkts((uint8_t *)ts->pkpkt, ts->pkpktlen, dig, 0);
00300
00301
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
00310
00311 #if defined(HAVE_KEYUTILS_H)
00312
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
00324 (void) add_key("user", krn, ts->pkpkt, ts->pkpktlen, keyring);
00325
00326 }
00327 #endif
00328
00329
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
00354 if (ts->dig == NULL) {
00355 ts->dig = pgpDigNew(0);
00356
00357 (void) pgpSetFindPubkey(ts->dig, (int (*)(void *, void *))rpmtsFindPubkey, ts);
00358
00359 }
00360
00361
00362 return ts->dig;
00363
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
00375 ts->dig = pgpDigFree(ts->dig);
00376
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
00398 char reserved[16];
00399 } ;
00400
00401
00402
00403 static unsigned char lead_magic[] = {
00404 0xed, 0xab, 0xee, 0xdb, 0x00, 0x00, 0x00, 0x00
00405 };
00406
00407
00408
00409
00417 static rpmRC wrLead(FD_t fd, const void * ptr, const char ** msg)
00418
00419
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
00429 if ((int)l.major == 0)
00430 l.major = (unsigned char) 3;
00431 if (l.signature_type == 0)
00432 l.signature_type = 5;
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, void * ptr,
00456 const char ** msg)
00457
00458
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;
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
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
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
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
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
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 break;
00545 case 3:
00546 case 4:
00547 break;
00548 }
00549
00550 if (l->signature_type != 5) {
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, const char ** msg)
00582
00583
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
00620
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
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, void * ptr,
00655 const char ** msg)
00656
00657
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;
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
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
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
00729 nb = (il * sizeof(struct entryInfo_s)) + dl;
00730
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
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
00753
00754 if (entry->info.tag == RPMTAG_HEADERSIGNATURES
00755 && entry->info.type == RPM_BIN_TYPE
00756 && entry->info.count == REGION_TAG_COUNT)
00757 {
00758
00759
00760 assert(entry->info.offset > 0);
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
00770 dataEnd = dataStart + entry->info.offset;
00771
00772 (void) memcpy(info, dataEnd, REGION_TAG_COUNT);
00773
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
00794 memset(info, 0, sizeof(*info));
00795
00796
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
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
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;
00829
00830
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
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
00887 entryInfo pe = (entryInfo) &ei[2];
00888
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;
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
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
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
00931
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
00940
00941
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
00951 regionEnd = dataStart + entry->info.offset;
00952
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
00969 memset(info, 0, sizeof(*info));
00970
00971
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
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 break;
00994 blen = 0;
00995 for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
00996 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
00997 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;
01007 siglen = blen + 1;
01008 }
01009 break;
01010 case RPMTAG_RSAHEADER:
01011 if (vsflags & RPMVSF_NORSAHEADER)
01012 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;
01018 siglen = info->count;
01019 break;
01020 case RPMTAG_DSAHEADER:
01021 if (vsflags & RPMVSF_NODSAHEADER)
01022 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;
01028 siglen = info->count;
01029 break;
01030 default:
01031 break;
01032 }
01033 }
01034 rc = RPMRC_NOTFOUND;
01035
01036 exit:
01037
01038 if (rc != RPMRC_NOTFOUND) {
01039 buf[sizeof(buf)-1] = '\0';
01040 if (msg) *msg = xstrdup(buf);
01041 return rc;
01042 }
01043
01044
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
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
01070 osig = _free(osig);
01071
01072 (void) pgpSetSig(dig, info->tag, info->type, sig, info->count);
01073 }
01074
01075 switch (info->tag) {
01076 case RPMTAG_RSAHEADER:
01077
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);
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
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
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);
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( 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
01199 static rpmRC ckHeader( FD_t fd, const void * ptr,
01200 const char ** msg)
01201
01202
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, Header * hdrp,
01224 const char ** msg)
01225
01226
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;
01241 int xx;
01242
01243 if (_pkgio_debug)
01244 fprintf(stderr, "--> rpmReadHeader(%p, %p, %p)\n", fd, hdrp, msg);
01245
01246
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
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
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
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
01304 nb = (il * sizeof(struct entryInfo_s)) + dl;
01305
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
01317 rc = headerCheck(dig, ei, uc, msg);
01318 if (rc != RPMRC_OK)
01319 goto exit;
01320
01321
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;
01329
01330
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, void * ptr,
01358 const char ** msg)
01359
01360
01361 {
01362 Header * hdrp = ptr;
01363
01364 return rpmReadHeader(fd, hdrp, msg);
01365
01366 }
01367
01375 static rpmRC wrHeader(FD_t fd, void * ptr, const char ** msg)
01376
01377
01378 {
01379 Header h = ptr;
01380 return rpmWriteHeader(fd, h, msg);
01381 }
01382
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;
01392 else
01393 if (!strcmp(fn, "Signature")) {
01394 len = szHeader(ptr);
01395 len += ((8 - (len % 8)) % 8);
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 }