static JSBool rpmdc_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { /* XXX obj is the global object so lookup "this" object. */ JSObject * o = JSVAL_TO_OBJECT(argv[-2]); void * ptr = JS_GetInstancePrivate(cx, o, &rpmdcClass, NULL); rpmdc dc = ptr; JSBool ok = JS_FALSE; const char * s = NULL; unsigned int _dalgo = PGPHASHALGO_NONE; unsigned int _flags = RPMDIGEST_NONE; if (!(ok = JS_ConvertArguments(cx, argc, argv, "/s", &s))) goto exit; if (dc) { /* XXX retrieve current settings for persistence. */ _dalgo = rpmDigestAlgo(dc); _flags = rpmDigestF(dc); (void) rpmDigestFinal(dc, NULL, NULL, 0); /* XXX error msg */ dc = ptr = NULL; (void) JS_SetPrivate(cx, o, (void *)dc); } if (_dalgo == PGPHASHALGO_NONE) _dalgo = _dalgo_default; dc = ptr = rpmdc_init(cx, o, _dalgo, _flags); if (dc && s != NULL) { size_t ns = strlen(s); (void) rpmDigestUpdate(dc, s, ns); s = NULL; ns = 0; if (!rpmDigestFinal(dc, &s, &ns, 1)) { *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, s)); } else *rval = JSVAL_VOID; s = _free(s); /* XXX reinitialize so that _dalgo is persistent */ dc = ptr = NULL; (void) JS_SetPrivate(cx, o, (void *)dc); dc = ptr = rpmdc_init(cx, o, _dalgo, _flags); } else *rval = JSVAL_VOID; ok = JS_TRUE; exit: if (_debug) fprintf(stderr, "<== %s(%p,%p,%p[%u],%p) o %p ptr %p\n", __FUNCTION__, cx, obj, argv, (unsigned)argc, rval, o, ptr); return ok; }
static JSBool rpmdc_Fini(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { void * ptr = JS_GetInstancePrivate(cx, obj, &rpmdcClass, NULL); rpmdc dc = ptr; JSBool ok = JS_FALSE; const char * s = NULL; size_t ns = 0; _METHOD_DEBUG_ENTRY(_debug); *rval = JSVAL_FALSE; if (dc == NULL) goto exit; (void) rpmDigestFinal(dc, &s, &ns, 1); *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, s)); (void) JS_SetPrivate(cx, obj, (void *)NULL); ok = JS_TRUE; exit: s = _free(s); return ok; }
/* --- Object methods */ static JSBool rpmdc_Init(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { void * ptr = JS_GetInstancePrivate(cx, obj, &rpmdcClass, NULL); rpmdc dc = ptr; JSBool ok = JS_FALSE; unsigned int _dalgo = PGPHASHALGO_NONE; unsigned int _flags = RPMDIGEST_NONE; _METHOD_DEBUG_ENTRY(_debug); if (!(ok = JS_ConvertArguments(cx, argc, argv, "/uu", &_dalgo, &_flags))) goto exit; if (dc) { if (_dalgo == PGPHASHALGO_NONE) _dalgo = rpmDigestAlgo(dc); (void) rpmDigestFinal(dc, NULL, NULL, 0); (void) JS_SetPrivate(cx, obj, (void *)NULL); } if (_dalgo == PGPHASHALGO_NONE) _dalgo = _dalgo_default; dc = rpmDigestInit(_dalgo, _flags); (void) JS_SetPrivate(cx, obj, (void *)dc); *rval = JSVAL_TRUE; ok = JS_TRUE; exit: return ok; }
static rpmRC verifyMD5Digest(rpmtd sigtd, DIGEST_CTX md5ctx, char **msg) { rpmRC res = RPMRC_FAIL; /* assume failure */ uint8_t * md5sum = NULL; size_t md5len = 0; char *md5; const char *title = _("MD5 digest:"); *msg = NULL; DIGEST_CTX ctx = rpmDigestDup(md5ctx); if (ctx == NULL) { rasprintf(msg, "%s %s\n", title, rpmSigString(res)); goto exit; } (void) rpmDigestFinal(ctx, (void **)&md5sum, &md5len, 0); md5 = pgpHexStr(md5sum, md5len); if (md5len != sigtd->count || memcmp(md5sum, sigtd->data, md5len)) { char *hex = rpmtdFormat(sigtd, RPMTD_FORMAT_STRING, NULL); rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title, rpmSigString(res), hex, md5); free(hex); } else { res = RPMRC_OK; rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), md5); } free(md5); exit: md5sum = _free(md5sum); return res; }
static rpmRC verifyDigest(rpmtd sigtd, DIGEST_CTX digctx, const char *title, char **msg) { rpmRC res = RPMRC_FAIL; /* assume failure */ char * dig = NULL; size_t diglen = 0; char *pkgdig = rpmtdFormat(sigtd, RPMTD_FORMAT_STRING, NULL); DIGEST_CTX ctx = rpmDigestDup(digctx); if (rpmDigestFinal(ctx, (void **)&dig, &diglen, 1) || diglen == 0) { rasprintf(msg, "%s %s", title, rpmSigString(res)); goto exit; } if (strcasecmp(pkgdig, dig) == 0) { res = RPMRC_OK; rasprintf(msg, "%s %s (%s)", title, rpmSigString(res), pkgdig); } else { rasprintf(msg, "%s: %s Expected(%s) != (%s)", title, rpmSigString(res), pkgdig, dig); } exit: free(dig); free(pkgdig); return res; }
int rpmvsVerifyItems(struct rpmvs_s *sis, int range, rpmDigestBundle bundle, rpmKeyring keyring, rpmsinfoCb cb, void *cbdata) { int failed = 0; for (int i = 0; i < sis->nsigs; i++) { struct rpmsinfo_s *sinfo = &sis->sigs[i]; if (sinfo->range == range) { if (sis->rcs[i] == RPMRC_OK) { DIGEST_CTX ctx = rpmDigestBundleDupCtx(bundle, sinfo->id); sis->results[i] = _free(sis->results[i]); sis->rcs[i] = rpmVerifySignature(keyring, sinfo, ctx, &sis->results[i]); rpmDigestFinal(ctx, NULL, NULL, 0); rpmDigestBundleFinal(bundle, sinfo->id, NULL, NULL, 0); } if (cb) sis->rcs[i] = cb(sinfo, sis->rcs[i], sis->results[i], cbdata); if (sis->rcs[i] != RPMRC_OK) failed++; } } return failed; }
/** * Verify header immutable region SHA1 digest. * @retval msg verbose success/failure text * @param sha1ctx * @return RPMRC_OK on success */ static rpmRC verifySHA1Digest(rpmtd sigtd, DIGEST_CTX sha1ctx, char **msg) { rpmRC res = RPMRC_FAIL; /* assume failure */ char * SHA1 = NULL; const char *title = _("Header SHA1 digest:"); const char *sig = sigtd->data; *msg = NULL; DIGEST_CTX ctx = rpmDigestDup(sha1ctx); if (ctx == NULL) { rasprintf(msg, "%s %s\n", title, rpmSigString(res)); goto exit; } (void) rpmDigestFinal(ctx, (void **)&SHA1, NULL, 1); if (SHA1 == NULL || !rstreq(SHA1, sig)) { rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title, rpmSigString(res), sig, SHA1 ? SHA1 : "(nil)"); } else { res = RPMRC_OK; rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), SHA1); } exit: SHA1 = _free(SHA1); return res; }
static void *nullDigest(int algo, int ascii) { void *d = NULL; DIGEST_CTX ctx = rpmDigestInit(algo, 0); rpmDigestFinal(ctx, &d, NULL, ascii); return d; }
static int rpmltcSetDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp) /*@modifies dig @*/ { rpmltc ltc = dig->impl; int rc; int xx; pgpDigParams pubp = pgpGetPubkey(dig); dig->pubkey_algoN = rpmltcPubkeyAlgo2Name(pubp->pubkey_algo); dig->hash_algoN = rpmltcHashAlgo2Name(sigp->hash_algo); assert(sigp->hash_algo == rpmDigestAlgo(ctx)); /* Set DSA hash. */ /* XXX FIXME: should this lazy free be done elsewhere? */ ltc->digest = _free(ltc->digest); ltc->digestlen = 0; xx = rpmDigestFinal(ctx, (void **)<c->digest, <c->digestlen, 0); /* Compare leading 16 bits of digest for quick check. */ rc = memcmp(ltc->digest, sigp->signhash16, sizeof(sigp->signhash16)); SPEW(0, !rc, dig); return rc; }
int rpmDigestBundleFinal(rpmDigestBundle bundle, int algo, void ** datap, size_t * lenp, int asAscii) { int rc = 0; if (bundle && algo >= bundle->index_min && algo <= bundle->index_max) { rc = rpmDigestFinal(bundle->digests[algo], datap, lenp, asAscii); bundle->digests[algo] = NULL; } return rc; }
static void rpmdc_dtor(JSContext *cx, JSObject *obj) { void * ptr = JS_GetInstancePrivate(cx, obj, &rpmdcClass, NULL); rpmdc dc = ptr; _DTOR_DEBUG_ENTRY(_debug); if (dc) (void) rpmDigestFinal(dc, NULL, NULL, 0); }
static int makeHDRDigest(Header sigh, const char * file, rpmTagVal sigTag) { Header h = NULL; FD_t fd = NULL; char * SHA1 = NULL; int ret = -1; /* assume failure. */ switch (sigTag) { case RPMSIGTAG_SHA1: fd = Fopen(file, "r.fdio"); if (fd == NULL || Ferror(fd)) goto exit; h = headerRead(fd, HEADER_MAGIC_YES); if (h == NULL) goto exit; if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) { DIGEST_CTX ctx; struct rpmtd_s utd; if (!headerGet(h, RPMTAG_HEADERIMMUTABLE, &utd, HEADERGET_DEFAULT) || utd.data == NULL) { rpmlog(RPMLOG_ERR, _("Immutable header region could not be read. " "Corrupted package?\n")); goto exit; } ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); (void) rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic)); (void) rpmDigestUpdate(ctx, utd.data, utd.count); (void) rpmDigestFinal(ctx, (void **)&SHA1, NULL, 1); rpmtdFreeData(&utd); } else { rpmlog(RPMLOG_ERR, _("Cannot sign RPM v3 packages\n")); goto exit; } if (SHA1 == NULL) goto exit; if (!sighdrPut(sigh, RPMSIGTAG_SHA1, RPM_STRING_TYPE, SHA1, 1)) goto exit; ret = 0; break; default: break; } exit: free(SHA1); headerFree(h); if (fd != NULL) (void) Fclose(fd); return ret; }
rpmDigestBundle rpmDigestBundleFree(rpmDigestBundle bundle) { if (bundle) { for (int i = bundle->index_min; i <= bundle->index_max ; i++) { if (bundle->digests[i] == NULL) continue; rpmDigestFinal(bundle->digests[i], NULL, NULL, 0); bundle->digests[i] = NULL; } memset(bundle, 0, sizeof(*bundle)); free(bundle); } return NULL; }
static rpmRC verifyDigest(struct rpmsinfo_s *sinfo, DIGEST_CTX digctx, char **msg) { rpmRC res = RPMRC_FAIL; /* assume failure */ char * dig = NULL; size_t diglen = 0; DIGEST_CTX ctx = rpmDigestDup(digctx); if (rpmDigestFinal(ctx, (void **)&dig, &diglen, 1) || diglen == 0) goto exit; if (strcasecmp(sinfo->dig, dig) == 0) { res = RPMRC_OK; } else { rasprintf(msg, "Expected %s != %s", sinfo->dig, dig); } exit: free(dig); return res; }
static int rpmltcSetELG(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp) /*@*/ { rpmltc ltc = dig->impl; int rc = 1; /* XXX always fail. */ int xx; assert(sigp->hash_algo == rpmDigestAlgo(ctx)); /* XXX FIXME: should this lazy free be done elsewhere? */ ltc->digest = _free(ltc->digest); ltc->digestlen = 0; xx = rpmDigestFinal(ctx, (void **)<c->digest, <c->digestlen, 0); /* Compare leading 16 bits of digest for quick check. */ rc = memcmp(ltc->digest, sigp->signhash16, sizeof(sigp->signhash16)); SPEW(rc, !rc, dig); return rc; }
static int rpmcdsaSetECDSA(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp) /*@*/ { rpmcdsa cdsa = dig->impl; int rc = 1; /* assume failure. */ int xx; assert(sigp->hash_algo == rpmDigestAlgo(ctx)); /* XXX FIXME: should this lazy free be done elsewhere? */ cdsa->digest = _free(cdsa->digest); cdsa->digestlen = 0; xx = rpmDigestFinal(ctx, &cdsa->digest, &cdsa->digestlen, 0); /* Compare leading 16 bits of digest for quick check. */ rc = memcmp(cdsa->digest, sigp->signhash16, sizeof(sigp->signhash16)); SPEW(rc, !rc, dig); return rc; }
static int rpmcdsaSetRSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp) /*@modifies dig @*/ { rpmcdsa cdsa = dig->impl; int rc; int xx; pgpDigParams pubp = pgpGetPubkey(dig); dig->pubkey_algoN = rpmcdsaPubkeyAlgo2Name(pubp->pubkey_algo); dig->hash_algoN = rpmcdsaHashAlgo2Name(sigp->hash_algo); assert(sigp->hash_algo == rpmDigestAlgo(ctx)); /* XXX FIXME: should this lazy free be done elsewhere? */ cdsa->digest = _free(cdsa->digest); cdsa->digestlen = 0; xx = rpmDigestFinal(ctx, (void **)&cdsa->digest, &cdsa->digestlen, 1); /* Compare leading 16 bits of digest for quick check. */ rc = 0; SPEW(0, !rc, dig); return rc; }
static int rpmpkgVerifySigs(rpmKeyring keyring, rpmQueryFlags flags, FD_t fd, const char *fn) { char *buf = NULL; char *missingKeys = NULL; char *untrustedKeys = NULL; struct rpmtd_s sigtd; pgpDigParams sig = NULL; Header sigh = NULL; HeaderIterator hi = NULL; char * msg = NULL; int res = 1; /* assume failure */ rpmRC rc; int failed = 0; int nodigests = !(flags & VERIFY_DIGEST); int nosignatures = !(flags & VERIFY_SIGNATURE); struct sigtInfo_s sinfo; rpmDigestBundle plbundle = rpmDigestBundleNew(); rpmDigestBundle hdrbundle = rpmDigestBundleNew(); if ((rc = rpmLeadRead(fd, NULL, NULL, &msg)) != RPMRC_OK) { goto exit; } rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg); if (rc != RPMRC_OK) { goto exit; } /* Initialize all digests we'll be needing */ hi = headerInitIterator(sigh); for (; headerNext(hi, &sigtd) != 0; rpmtdFreeData(&sigtd)) { rc = rpmSigInfoParse(&sigtd, "package", &sinfo, NULL, NULL); if (nosignatures && sinfo.type == RPMSIG_SIGNATURE_TYPE) continue; if (nodigests && sinfo.type == RPMSIG_DIGEST_TYPE) continue; if (rc == RPMRC_OK && sinfo.hashalgo) { rpmDigestBundleAdd(sinfo.payload ? plbundle : hdrbundle, sinfo.hashalgo, RPMDIGEST_NONE); } } hi = headerFreeIterator(hi); /* Read the file, generating digest(s) on the fly. */ fdSetBundle(fd, plbundle); if (readFile(fd, fn, plbundle, hdrbundle)) { goto exit; } rasprintf(&buf, "%s:%c", fn, (rpmIsVerbose() ? '\n' : ' ') ); hi = headerInitIterator(sigh); for (; headerNext(hi, &sigtd) != 0; rpmtdFreeData(&sigtd)) { char *result = NULL; DIGEST_CTX ctx = NULL; if (sigtd.data == NULL) /* XXX can't happen */ continue; /* Clean up parameters from previous sigtag. */ sig = pgpDigParamsFree(sig); /* Note: we permit failures to be ignored via disablers */ rc = rpmSigInfoParse(&sigtd, "package", &sinfo, &sig, &result); if (nosignatures && sinfo.type == RPMSIG_SIGNATURE_TYPE) continue; if (nodigests && sinfo.type == RPMSIG_DIGEST_TYPE) continue; if (sinfo.type == RPMSIG_OTHER_TYPE) continue; if (rc == RPMRC_OK) { ctx = rpmDigestBundleDupCtx(sinfo.payload ? plbundle : hdrbundle, sinfo.hashalgo); rc = rpmVerifySignature(keyring, &sigtd, sig, ctx, &result); rpmDigestFinal(ctx, NULL, NULL, 0); } if (result) { formatResult(sigtd.tag, rc, result, (rc == RPMRC_NOKEY ? &missingKeys : &untrustedKeys), &buf); free(result); } if (rc != RPMRC_OK) { failed = 1; } } res = failed; if (rpmIsVerbose()) { rpmlog(RPMLOG_NOTICE, "%s", buf); } else { const char *ok = (failed ? _("NOT OK") : _("OK")); rpmlog(RPMLOG_NOTICE, "%s%s%s%s%s%s%s%s\n", buf, ok, missingKeys ? _(" (MISSING KEYS:") : "", missingKeys ? missingKeys : "", missingKeys ? _(") ") : "", untrustedKeys ? _(" (UNTRUSTED KEYS:") : "", untrustedKeys ? untrustedKeys : "", untrustedKeys ? _(")") : ""); } free(missingKeys); free(untrustedKeys); exit: if (res && msg != NULL) rpmlog(RPMLOG_ERR, "%s: %s\n", fn, msg); free(msg); free(buf); rpmDigestBundleFree(hdrbundle); rpmDigestBundleFree(plbundle); fdSetBundle(fd, NULL); /* XXX avoid double-free from fd close */ sigh = rpmFreeSignature(sigh); hi = headerFreeIterator(hi); pgpDigParamsFree(sig); return res; }
/* Build pubkey header. */ static int makePubkeyHeader(rpmts ts, rpmPubkey key, Header * hdrp) { Header h = headerNew(); const char * afmt = "%{pubkeys:armor}"; const char * group = "Public Keys"; const char * license = "pubkey"; const char * buildhost = "localhost"; const char * userid; rpmsenseFlags pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL); uint32_t zero = 0; uint32_t keytime = 0; pgpDig dig = NULL; pgpDigParams pubp = NULL; char * d = NULL; char * enc = NULL; char * n = NULL; char * u = NULL; char * v = NULL; char * r = NULL; char * evr = NULL; int rc = -1; if ((enc = rpmPubkeyBase64(key)) == NULL) goto exit; if ((dig = rpmPubkeyDig(key)) == NULL) goto exit; if ((pubp = pgpDigGetParams(dig, PGPTAG_PUBLIC_KEY)) == NULL) goto exit; /* Build header elements. */ v = pgpHexStr(pubp->signid, sizeof(pubp->signid)); r = pgpHexStr(pubp->time, sizeof(pubp->time)); userid = pubp->userid ? pubp->userid : "none"; keytime = pgpGrab(pubp->time, sizeof(pubp->time)); rasprintf(&n, "gpg(%s)", v+8); rasprintf(&u, "gpg(%s)", userid); rasprintf(&evr, "%d:%s-%s", pubp->version, v, r); headerPutString(h, RPMTAG_PUBKEYS, enc); if ((d = headerFormat(h, afmt, NULL)) == NULL) goto exit; headerPutString(h, RPMTAG_NAME, "gpg-pubkey"); headerPutString(h, RPMTAG_VERSION, v+8); headerPutString(h, RPMTAG_RELEASE, r); headerPutString(h, RPMTAG_DESCRIPTION, d); headerPutString(h, RPMTAG_GROUP, group); headerPutString(h, RPMTAG_LICENSE, license); headerPutString(h, RPMTAG_SUMMARY, u); headerPutString(h, RPMTAG_PACKAGER, userid); headerPutUint32(h, RPMTAG_SIZE, &zero, 1); headerPutString(h, RPMTAG_PROVIDENAME, u); headerPutString(h, RPMTAG_PROVIDEVERSION, evr); headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1); headerPutString(h, RPMTAG_PROVIDENAME, n); headerPutString(h, RPMTAG_PROVIDEVERSION, evr); headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1); headerPutString(h, RPMTAG_RPMVERSION, RPMVERSION); headerPutString(h, RPMTAG_BUILDHOST, buildhost); headerPutUint32(h, RPMTAG_BUILDTIME, &keytime, 1); headerPutString(h, RPMTAG_SOURCERPM, "(none)"); /* Reload the lot to immutable region and stomp sha1 digest on it */ h = headerReload(h, RPMTAG_HEADERIMMUTABLE); if (h != NULL) { char *sha1 = NULL; unsigned int blen = 0; const void *blob = headerExport(h, &blen); /* XXX FIXME: bah, this code is repeated in way too many places */ DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic)); rpmDigestUpdate(ctx, blob, blen); rpmDigestFinal(ctx, (void **)&sha1, NULL, 1); if (sha1) { headerPutString(h, RPMTAG_SHA1HEADER, sha1); *hdrp = headerLink(h); rc = 0; } free(sha1); } exit: headerFree(h); pgpFreeDig(dig); free(n); free(u); free(v); free(r); free(evr); free(enc); free(d); return rc; }
/* * Argument monster to verify header-only signature/digest if there is * one, otherwisereturn RPMRC_NOTFOUND to signal for plain sanity check. */ static rpmRC headerSigVerify(rpmKeyring keyring, rpmVSFlags vsflags, int il, int dl, int ril, int rdl, entryInfo pe, unsigned char * dataStart, char **buf) { size_t siglen = 0; rpmRC rc = RPMRC_FAIL; pgpDigParams sig = NULL; struct rpmtd_s sigtd; struct entryInfo_s info, einfo; unsigned int hashalgo = 0; rpmtdReset(&sigtd); memset(&info, 0, sizeof(info)); memset(&einfo, 0, sizeof(einfo)); /* Find a header-only digest/signature tag. */ for (int i = ril; i < il; i++) { if (headerVerifyInfo(1, dl, pe+i, &einfo, 0) != -1) { rasprintf(buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"), i, einfo.tag, einfo.type, einfo.offset, einfo.count); goto exit; } switch (einfo.tag) { case RPMTAG_SHA1HEADER: { size_t blen = 0; unsigned const char * b; if (vsflags & RPMVSF_NOSHA1HEADER) break; for (b = dataStart + einfo.offset; *b != '\0'; b++) { if (strchr("0123456789abcdefABCDEF", *b) == NULL) break; blen++; } if (einfo.type != RPM_STRING_TYPE || *b != '\0' || blen != 40) { rasprintf(buf, _("hdr SHA1: BAD, not hex\n")); goto exit; } if (info.tag == 0) { info = einfo; /* structure assignment */ siglen = blen + 1; } } break; case RPMTAG_RSAHEADER: if (vsflags & RPMVSF_NORSAHEADER) break; if (einfo.type != RPM_BIN_TYPE) { rasprintf(buf, _("hdr RSA: BAD, not binary\n")); goto exit; } info = einfo; /* structure assignment */ siglen = info.count; break; case RPMTAG_DSAHEADER: if (vsflags & RPMVSF_NODSAHEADER) break; if (einfo.type != RPM_BIN_TYPE) { rasprintf(buf, _("hdr DSA: BAD, not binary\n")); goto exit; } info = einfo; /* structure assignment */ siglen = info.count; break; default: break; } } /* No header-only digest/signature found, get outta here */ if (info.tag == 0) { rc = RPMRC_NOTFOUND; goto exit; } sigtd.tag = info.tag; sigtd.type = info.type; sigtd.count = info.count; sigtd.data = memcpy(xmalloc(siglen), dataStart + info.offset, siglen); sigtd.flags = RPMTD_ALLOCED; switch (info.tag) { case RPMTAG_RSAHEADER: case RPMTAG_DSAHEADER: if (parsePGPSig(&sigtd, "header", NULL, &sig)) goto exit; hashalgo = pgpDigParamsAlgo(sig, PGPVAL_HASHALGO); break; case RPMTAG_SHA1HEADER: hashalgo = PGPHASHALGO_SHA1; break; default: break; } if (hashalgo) { DIGEST_CTX ctx = rpmDigestInit(hashalgo, RPMDIGEST_NONE); int32_t ildl[2] = { htonl(ril), htonl(rdl) }; rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic)); rpmDigestUpdate(ctx, ildl, sizeof(ildl)); rpmDigestUpdate(ctx, pe, (ril * sizeof(*pe))); rpmDigestUpdate(ctx, dataStart, rdl); rc = rpmVerifySignature(keyring, &sigtd, sig, ctx, buf); rpmDigestFinal(ctx, NULL, NULL, 0); } exit: rpmtdFreeData(&sigtd); pgpDigParamsFree(sig); return rc; }
static rpmRC headerVerify(rpmKeyring keyring, rpmVSFlags vsflags, const void * uh, size_t uc, char ** msg) { pgpDig dig = NULL; char *buf = NULL; int32_t * ei = (int32_t *) uh; int32_t il = ntohl(ei[0]); int32_t dl = ntohl(ei[1]); entryInfo pe = (entryInfo) &ei[2]; int32_t ildl[2]; int32_t pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl; unsigned char * dataStart = (unsigned char *) (pe + il); struct indexEntry_s entry; struct entryInfo_s info; unsigned const char * b; size_t siglen = 0; size_t blen; size_t nb; int32_t ril = 0; unsigned char * regionEnd = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ int xx; int i; struct rpmtd_s sigtd; DIGEST_CTX ctx = NULL; /* Is the blob the right size? */ if (uc > 0 && pvlen != uc) { rasprintf(&buf, _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"), (int)uc, (int)il, (int)dl); goto exit; } memset(&entry, 0, sizeof(entry)); memset(&info, 0, sizeof(info)); /* Check (and convert) the 1st tag element. */ xx = headerVerifyInfo(1, dl, pe, &entry.info, 0); if (xx != -1) { rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"), 0, entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } /* Is there an immutable header region tag? */ if (!(entry.info.tag == RPMTAG_HEADERIMMUTABLE && entry.info.type == RPM_BIN_TYPE && entry.info.count == REGION_TAG_COUNT)) { rc = RPMRC_NOTFOUND; goto exit; } /* Is the offset within the data area? */ if (entry.info.offset >= dl) { rasprintf(&buf, _("region offset: BAD, tag %d type %d offset %d count %d\n"), entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } /* Is there an immutable header region tag trailer? */ regionEnd = dataStart + entry.info.offset; (void) memcpy(&info, regionEnd, REGION_TAG_COUNT); regionEnd += REGION_TAG_COUNT; xx = headerVerifyInfo(1, dl, &info, &entry.info, 1); if (xx != -1 || !(entry.info.tag == RPMTAG_HEADERIMMUTABLE && entry.info.type == RPM_BIN_TYPE && entry.info.count == REGION_TAG_COUNT)) { rasprintf(&buf, _("region trailer: BAD, tag %d type %d offset %d count %d\n"), entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } memset(&info, 0, sizeof(info)); /* Is the no. of tags in the region less than the total no. of tags? */ ril = entry.info.offset/sizeof(*pe); if ((entry.info.offset % sizeof(*pe)) || ril > il) { rasprintf(&buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il); goto exit; } /* Find a header-only digest/signature tag. */ for (i = ril; i < il; i++) { xx = headerVerifyInfo(1, dl, pe+i, &entry.info, 0); if (xx != -1) { rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"), i, entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } switch (entry.info.tag) { case RPMTAG_SHA1HEADER: if (vsflags & RPMVSF_NOSHA1HEADER) break; blen = 0; for (b = dataStart + entry.info.offset; *b != '\0'; b++) { if (strchr("0123456789abcdefABCDEF", *b) == NULL) break; blen++; } if (entry.info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40) { rasprintf(&buf, _("hdr SHA1: BAD, not hex\n")); goto exit; } if (info.tag == 0) { info = entry.info; /* structure assignment */ siglen = blen + 1; } break; case RPMTAG_RSAHEADER: if (vsflags & RPMVSF_NORSAHEADER) break; if (entry.info.type != RPM_BIN_TYPE) { rasprintf(&buf, _("hdr RSA: BAD, not binary\n")); goto exit; } info = entry.info; /* structure assignment */ siglen = info.count; break; case RPMTAG_DSAHEADER: if (vsflags & RPMVSF_NODSAHEADER) break; if (entry.info.type != RPM_BIN_TYPE) { rasprintf(&buf, _("hdr DSA: BAD, not binary\n")); goto exit; } info = entry.info; /* structure assignment */ siglen = info.count; break; default: break; } } rc = RPMRC_NOTFOUND; exit: /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */ if (rc != RPMRC_NOTFOUND) { if (msg) *msg = buf; else free(buf); return rc; } /* If no header-only digest/signature, then do simple sanity check. */ if (info.tag == 0) { verifyinfo_exit: xx = headerVerifyInfo(ril-1, dl, pe+1, &entry.info, 0); if (xx != -1) { rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"), xx+1, entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); rc = RPMRC_FAIL; } else { rasprintf(&buf, "Header sanity check: OK\n"); rc = RPMRC_OK; } if (msg) *msg = buf; else free(buf); return rc; } /* Verify header-only digest/signature. */ dig = pgpNewDig(); if (dig == NULL) goto verifyinfo_exit; sigtd.tag = info.tag; sigtd.type = info.type; sigtd.count = info.count; sigtd.data = memcpy(xmalloc(siglen), dataStart + info.offset, siglen); sigtd.flags = RPMTD_ALLOCED; switch (info.tag) { case RPMTAG_RSAHEADER: case RPMTAG_DSAHEADER: if ((rc = parsePGP(&sigtd, "header", dig)) != RPMRC_OK) { pgpFreeDig(dig); goto exit; } /* fallthrough */ case RPMTAG_SHA1HEADER: { pgpHashAlgo hashalgo = (info.tag == RPMTAG_SHA1HEADER) ? PGPHASHALGO_SHA1 : dig->signature.hash_algo; ildl[0] = htonl(ril); ildl[1] = (regionEnd - dataStart); ildl[1] = htonl(ildl[1]); ctx = rpmDigestInit(hashalgo, RPMDIGEST_NONE); b = (unsigned char *) rpm_header_magic; nb = sizeof(rpm_header_magic); (void) rpmDigestUpdate(ctx, b, nb); b = (unsigned char *) ildl; nb = sizeof(ildl); (void) rpmDigestUpdate(ctx, b, nb); b = (unsigned char *) pe; nb = (htonl(ildl[0]) * sizeof(*pe)); (void) rpmDigestUpdate(ctx, b, nb); b = (unsigned char *) dataStart; nb = htonl(ildl[1]); (void) rpmDigestUpdate(ctx, b, nb); } break; default: sigtd.data = _free(sigtd.data); /* Hmm...? */ break; } rc = rpmVerifySignature(keyring, &sigtd, dig, ctx, &buf); if (msg) *msg = buf; else free(buf); rpmtdFreeData(&sigtd); pgpFreeDig(dig); rpmDigestFinal(ctx, NULL, NULL, 0); return rc; }
static rpmRC rpmpkgRead(rpmKeyring keyring, rpmVSFlags vsflags, FD_t fd, const char * fn, Header * hdrp) { pgpDig dig = NULL; char buf[8*BUFSIZ]; ssize_t count; rpmlead l = NULL; Header sigh = NULL; rpmSigTag sigtag; struct rpmtd_s sigtd; Header h = NULL; char * msg; rpmRC rc = RPMRC_FAIL; /* assume failure */ int leadtype = -1; headerGetFlags hgeflags = HEADERGET_DEFAULT; DIGEST_CTX ctx = NULL; if (hdrp) *hdrp = NULL; rpmtdReset(&sigtd); l = rpmLeadNew(); if ((rc = rpmLeadRead(fd, l)) == RPMRC_OK) { const char * err = NULL; if ((rc = rpmLeadCheck(l, &err)) == RPMRC_FAIL) { rpmlog(RPMLOG_ERR, "%s: %s\n", fn, err); } leadtype = rpmLeadType(l); } l = rpmLeadFree(l); if (rc != RPMRC_OK) goto exit; /* Read the signature header. */ msg = NULL; rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg); switch (rc) { default: rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), fn, (msg && *msg ? msg : "\n")); msg = _free(msg); goto exit; break; case RPMRC_OK: if (sigh == NULL) { rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn); rc = RPMRC_FAIL; goto exit; } break; } msg = _free(msg); #define _chk(_mask, _tag) \ (sigtag == 0 && !(vsflags & (_mask)) && headerIsEntry(sigh, (_tag))) /* * Figger the most effective available signature. * Prefer signatures over digests, then header-only over header+payload. * DSA will be preferred over RSA if both exist because tested first. * Note that NEEDPAYLOAD prevents header+payload signatures and digests. */ sigtag = 0; if (_chk(RPMVSF_NODSAHEADER, RPMSIGTAG_DSA)) { sigtag = RPMSIGTAG_DSA; } else if (_chk(RPMVSF_NORSAHEADER, RPMSIGTAG_RSA)) { sigtag = RPMSIGTAG_RSA; } else if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_GPG)) { sigtag = RPMSIGTAG_GPG; fdInitDigest(fd, PGPHASHALGO_SHA1, 0); } else if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_PGP)) { sigtag = RPMSIGTAG_PGP; fdInitDigest(fd, PGPHASHALGO_MD5, 0); } else if (_chk(RPMVSF_NOSHA1HEADER, RPMSIGTAG_SHA1)) { sigtag = RPMSIGTAG_SHA1; } else if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_MD5)) { sigtag = RPMSIGTAG_MD5; fdInitDigest(fd, PGPHASHALGO_MD5, 0); } /* Read the metadata, computing digest(s) on the fly. */ h = NULL; msg = NULL; rc = rpmpkgReadHeader(keyring, vsflags, fd, &h, &msg); if (rc != RPMRC_OK || h == NULL) { rpmlog(RPMLOG_ERR, _("%s: headerRead failed: %s"), fn, (msg && *msg ? msg : "\n")); msg = _free(msg); goto exit; } msg = _free(msg); /* Any digests or signatures to check? */ if (sigtag == 0) { rc = RPMRC_OK; goto exit; } dig = pgpNewDig(); if (dig == NULL) { rc = RPMRC_FAIL; goto exit; } /* Retrieve the tag parameters from the signature header. */ if (!headerGet(sigh, sigtag, &sigtd, hgeflags)) { rc = RPMRC_FAIL; goto exit; } switch (sigtag) { case RPMSIGTAG_RSA: case RPMSIGTAG_DSA: if ((rc = parsePGP(&sigtd, "package", dig)) != RPMRC_OK) { goto exit; } /* fallthrough */ case RPMSIGTAG_SHA1: { struct rpmtd_s utd; pgpHashAlgo hashalgo = (sigtag == RPMSIGTAG_SHA1) ? PGPHASHALGO_SHA1 : dig->signature.hash_algo; if (!headerGet(h, RPMTAG_HEADERIMMUTABLE, &utd, hgeflags)) break; ctx = rpmDigestInit(hashalgo, RPMDIGEST_NONE); (void) rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic)); (void) rpmDigestUpdate(ctx, utd.data, utd.count); rpmtdFreeData(&utd); } break; case RPMSIGTAG_GPG: case RPMSIGTAG_PGP5: /* XXX legacy */ case RPMSIGTAG_PGP: if ((rc = parsePGP(&sigtd, "package", dig)) != RPMRC_OK) { goto exit; } /* fallthrough */ case RPMSIGTAG_MD5: /* Legacy signatures need the compressed payload in the digest too. */ while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) {} if (count < 0) { rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"), fn, Fstrerror(fd)); rc = RPMRC_FAIL; goto exit; } ctx = rpmDigestBundleDupCtx(fdGetBundle(fd), (sigtag == RPMSIGTAG_MD5) ? PGPHASHALGO_MD5 : dig->signature.hash_algo); break; default: break; } /** @todo Implement disable/enable/warn/error/anal policy. */ rc = rpmVerifySignature(keyring, &sigtd, dig, ctx, &msg); switch (rc) { case RPMRC_OK: /* Signature is OK. */ rpmlog(RPMLOG_DEBUG, "%s: %s", fn, msg); break; case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */ case RPMRC_NOKEY: /* Public key is unavailable. */ /* XXX Print NOKEY/NOTTRUSTED warning only once. */ { int lvl = (stashKeyid(dig) ? RPMLOG_DEBUG : RPMLOG_WARNING); rpmlog(lvl, "%s: %s", fn, msg); } break; case RPMRC_NOTFOUND: /* Signature is unknown type. */ rpmlog(RPMLOG_WARNING, "%s: %s", fn, msg); break; default: case RPMRC_FAIL: /* Signature does not verify. */ rpmlog(RPMLOG_ERR, "%s: %s", fn, msg); break; } free(msg); exit: if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) { /* Retrofit RPMTAG_SOURCEPACKAGE to srpms for compatibility */ if (leadtype == RPMLEAD_SOURCE && headerIsSource(h)) { if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE)) { uint32_t one = 1; headerPutUint32(h, RPMTAG_SOURCEPACKAGE, &one, 1); } } /* * Try to make sure binary rpms have RPMTAG_SOURCERPM set as that's * what we use for differentiating binary vs source elsewhere. */ if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE) && headerIsSource(h)) { headerPutString(h, RPMTAG_SOURCERPM, "(none)"); } /* * Convert legacy headers on the fly. Not having "new" style compressed * filenames is close enough estimate for legacy indication... */ if (!headerIsEntry(h, RPMTAG_DIRNAMES)) { headerConvert(h, HEADERCONV_RETROFIT_V3); } /* Append (and remap) signature tags to the metadata. */ headerMergeLegacySigs(h, sigh); /* Bump reference count for return. */ *hdrp = headerLink(h); } rpmtdFreeData(&sigtd); rpmDigestFinal(ctx, NULL, NULL, 0); h = headerFree(h); pgpFreeDig(dig); sigh = rpmFreeSignature(sigh); return rc; }
/* * Argument monster to verify header-only signature/digest if there is * one, otherwisereturn RPMRC_NOTFOUND to signal for plain sanity check. */ static rpmRC headerSigVerify(rpmKeyring keyring, rpmVSFlags vsflags, hdrblob blob, char **buf) { rpmRC rc = RPMRC_FAIL; pgpDigParams sig = NULL; struct rpmtd_s sigtd; struct entryInfo_s einfo; struct sigtInfo_s sinfo; rpmtdReset(&sigtd); memset(&einfo, 0, sizeof(einfo)); /* Find a header-only digest/signature tag. */ for (int i = blob->ril; i < blob->il; i++) { ei2h(blob->pe+i, &einfo); switch (einfo.tag) { case RPMTAG_SHA1HEADER: if (vsflags & RPMVSF_NOSHA1HEADER) break; if (sigtd.tag == 0) ei2td(&einfo, blob->dataStart, 0, &sigtd); break; case RPMTAG_RSAHEADER: if (vsflags & RPMVSF_NORSAHEADER) break; ei2td(&einfo, blob->dataStart, einfo.count, &sigtd); break; case RPMTAG_DSAHEADER: if (vsflags & RPMVSF_NODSAHEADER) break; ei2td(&einfo, blob->dataStart, einfo.count, &sigtd); break; default: break; } } /* No header-only digest/signature found, get outta here */ if (sigtd.tag == 0) { rc = RPMRC_NOTFOUND; goto exit; } if (rpmSigInfoParse(&sigtd, "header", &sinfo, &sig, buf)) goto exit; if (sinfo.hashalgo) { DIGEST_CTX ctx = rpmDigestInit(sinfo.hashalgo, RPMDIGEST_NONE); int32_t ildl[2] = { htonl(blob->ril), htonl(blob->rdl) }; rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic)); rpmDigestUpdate(ctx, ildl, sizeof(ildl)); rpmDigestUpdate(ctx, blob->pe, (blob->ril * sizeof(*blob->pe))); rpmDigestUpdate(ctx, blob->dataStart, blob->rdl); rc = rpmVerifySignature(keyring, &sigtd, sig, ctx, buf); rpmDigestFinal(ctx, NULL, NULL, 0); } exit: rpmtdFreeData(&sigtd); pgpDigParamsFree(sig); return rc; }
static rpmRC rpmpkgRead(rpmKeyring keyring, rpmVSFlags vsflags, FD_t fd, Header * hdrp, unsigned int *keyidp, char **msg) { pgpDigParams sig = NULL; Header sigh = NULL; rpmTagVal sigtag; struct rpmtd_s sigtd; struct sigtInfo_s sinfo; Header h = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ int leadtype = -1; headerGetFlags hgeflags = HEADERGET_DEFAULT; if (hdrp) *hdrp = NULL; rpmtdReset(&sigtd); if ((rc = rpmLeadRead(fd, &leadtype, msg)) != RPMRC_OK) { /* Avoid message spew on manifests */ if (rc == RPMRC_NOTFOUND) { *msg = _free(*msg); } goto exit; } /* Read the signature header. */ rc = rpmReadSignature(fd, &sigh, msg); if (rc != RPMRC_OK) { goto exit; } #define _chk(_mask, _tag) \ (sigtag == 0 && !(vsflags & (_mask)) && headerIsEntry(sigh, (_tag))) /* * Figger the most effective means of verification available, prefer * signatures over digests. Legacy header+payload entries are not used. * DSA will be preferred over RSA if both exist because tested first. */ sigtag = 0; if (_chk(RPMVSF_NODSAHEADER, RPMSIGTAG_DSA)) { sigtag = RPMSIGTAG_DSA; } else if (_chk(RPMVSF_NORSAHEADER, RPMSIGTAG_RSA)) { sigtag = RPMSIGTAG_RSA; } else if (_chk(RPMVSF_NOSHA1HEADER, RPMSIGTAG_SHA1)) { sigtag = RPMSIGTAG_SHA1; } /* Read the metadata, computing digest(s) on the fly. */ h = NULL; rc = rpmpkgReadHeader(fd, &h, msg); if (rc != RPMRC_OK || h == NULL) { goto exit; } /* Any digests or signatures to check? */ if (sigtag == 0) { rc = RPMRC_OK; goto exit; } /* Free up any previous "ok" message before signature/digest check */ *msg = _free(*msg); /* Retrieve the tag parameters from the signature header. */ if (!headerGet(sigh, sigtag, &sigtd, hgeflags)) { rc = RPMRC_FAIL; goto exit; } if (rpmSigInfoParse(&sigtd, "package", &sinfo, &sig, msg) == RPMRC_OK) { struct rpmtd_s utd; DIGEST_CTX ctx = rpmDigestInit(sinfo.hashalgo, RPMDIGEST_NONE); if (headerGet(h, RPMTAG_HEADERIMMUTABLE, &utd, hgeflags)) { rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic)); rpmDigestUpdate(ctx, utd.data, utd.count); rpmtdFreeData(&utd); } /** @todo Implement disable/enable/warn/error/anal policy. */ rc = rpmVerifySignature(keyring, &sigtd, sig, ctx, msg); rpmDigestFinal(ctx, NULL, NULL, 0); } else { rc = RPMRC_FAIL; } exit: if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) { /* Retrofit RPMTAG_SOURCEPACKAGE to srpms for compatibility */ if (leadtype == RPMLEAD_SOURCE && headerIsSource(h)) { if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE)) { uint32_t one = 1; headerPutUint32(h, RPMTAG_SOURCEPACKAGE, &one, 1); } } /* * Try to make sure binary rpms have RPMTAG_SOURCERPM set as that's * what we use for differentiating binary vs source elsewhere. */ if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE) && headerIsSource(h)) { headerPutString(h, RPMTAG_SOURCERPM, "(none)"); } /* * Convert legacy headers on the fly. Not having immutable region * equals a truly ancient package, do full retrofit. OTOH newer * packages might have been built with --nodirtokens, test and handle * the non-compressed filelist case separately. */ if (!headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) headerConvert(h, HEADERCONV_RETROFIT_V3); else if (headerIsEntry(h, RPMTAG_OLDFILENAMES)) headerConvert(h, HEADERCONV_COMPRESSFILELIST); /* Append (and remap) signature tags to the metadata. */ headerMergeLegacySigs(h, sigh); /* Bump reference count for return. */ *hdrp = headerLink(h); if (keyidp) *keyidp = getKeyid(sig); } rpmtdFreeData(&sigtd); h = headerFree(h); pgpDigParamsFree(sig); sigh = headerFree(sigh); return rc; }
static void test_gridfile( gridfs *gfs, char *data_before, int64_t length, char *filename, char *content_type ) { gridfile gfile[1]; FILE *stream; #ifdef DYING mongo_md5_state_t pms[1]; mongo_md5_byte_t digest[16]; #endif char hex_digest[33]; int64_t i = length; int n; char *data_after = (char*)bson_malloc( LARGE ); int truncBytes; char* lowerName; ASSERT(gridfs_find_filename( gfs, filename, gfile ) == MONGO_OK); ASSERT( gridfile_exists( gfile ) ); stream = fopen( "output", "w+" ); gridfile_write_file( gfile, stream ); fseek( stream, 0, SEEK_SET ); ASSERT( fread( data_after, (size_t)length, sizeof( char ), stream ) ); fclose( stream ); ASSERT( memcmp( data_before, data_after, (size_t)length ) == 0 ); gridfile_read_buffer( gfile, data_after, length ); ASSERT( memcmp( data_before, data_after, (size_t)length ) == 0 ); lowerName = (char*) bson_malloc( (int)strlen( filename ) + 1); strcpy( lowerName, filename ); _strlwr( lowerName ); ASSERT( strcmp( gridfile_get_filename( gfile ), lowerName ) == 0 ); bson_free( lowerName ); ASSERT( gridfile_get_contentlength( gfile ) == (size_t)length ); ASSERT( gridfile_get_chunksize( gfile ) == DEFAULT_CHUNK_SIZE ); ASSERT( strcmp( gridfile_get_contenttype( gfile ), content_type ) == 0 ) ; ASSERT( memcmp( data_before, data_after, (size_t)length ) == 0 ); if( !( gfile->flags & GRIDFILE_COMPRESS ) ) { #ifdef DYING mongo_md5_init( pms ); n = 0; while( i > INT_MAX ) { mongo_md5_append( pms, ( const mongo_md5_byte_t * )data_before + ( n * INT_MAX ), INT_MAX ); i -= INT_MAX; n += 1; } if( i > 0 ) mongo_md5_append( pms, ( const mongo_md5_byte_t * )data_before + ( n * INT_MAX ), (int)i ); mongo_md5_finish( pms, digest ); digest2hex( digest, hex_digest ); #else { DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE); const char * _digest = NULL; int xx; while( i > INT_MAX ) { xx = rpmDigestUpdate(ctx, (char *)data_before + (n*INT_MAX), INT_MAX); i -= INT_MAX; n += 1; } xx = rpmDigestFinal(ctx, &_digest, NULL, 1); strncpy(hex_digest, _digest, 32+1); hex_digest[32] = '\0'; _digest = _free(_digest); } #endif ASSERT( strcmp( gridfile_get_md5( gfile ), hex_digest ) == 0 ); } truncBytes = (int) (length > DEFAULT_CHUNK_SIZE * 4 ? length - DEFAULT_CHUNK_SIZE * 2 - 13 : 23); gridfile_writer_init( gfile, gfs, filename, content_type, GRIDFILE_DEFAULT); ASSERT( gridfile_truncate(gfile, (size_t)(length - truncBytes)) == (size_t)(length - truncBytes)); gridfile_writer_done( gfile ); gridfile_seek(gfile, 0); ASSERT( gridfile_get_contentlength( gfile ) == (size_t)(length - truncBytes) ); ASSERT( gridfile_read_buffer( gfile, data_after, length ) == (size_t)(length - truncBytes)); ASSERT( memcmp( data_before, data_after, (size_t)(length - truncBytes) ) == 0 ); gridfile_writer_init( gfile, gfs, filename, content_type, GRIDFILE_DEFAULT); gridfile_truncate(gfile, 0); gridfile_writer_done( gfile ); ASSERT( gridfile_get_contentlength( gfile ) == 0 ); ASSERT( gridfile_read_buffer( gfile, data_after, length ) == 0 ); gridfile_destroy( gfile ); ASSERT( gridfs_remove_filename( gfs, filename ) == MONGO_OK ); free( data_after ); gridfs_test_unlink( "output" ); }