commit - 1d72a2a0ee2d5c4546c0471e054c0d81e407bc72
commit + 6ad68bce3639912fcf7725dbb589febec015788a
blob - 48821e99ab74a4c96cf039cf1b592301c97eda74
blob + 0ccf42c214a51c167c3c22051afc9fa855ec2c19
--- lib/got_lib_inflate.h
+++ lib/got_lib_inflate.h
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+struct got_inflate_checksum {
+ /* If not NULL, mix input bytes into this CRC checksum. */
+ uint32_t *input_crc;
+
+ /* If not NULL, mix input bytes into this SHA1 context. */
+ SHA1_CTX *input_sha1;
+};
+
struct got_inflate_buf {
z_stream z;
char *inbuf;
int flags;
#define GOT_INFLATE_F_HAVE_MORE 0x01
#define GOT_INFLATE_F_OWN_OUTBUF 0x02
- uint32_t *input_crc;
+ struct got_inflate_checksum *csum;
};
#define GOT_INFLATE_BUFSIZE 32768
const struct got_error *got_inflate_init(struct got_inflate_buf *, uint8_t *,
- size_t, uint32_t *);
+ size_t, struct got_inflate_checksum *);
const struct got_error *got_inflate_read(struct got_inflate_buf *, FILE *,
size_t *, size_t *);
const struct got_error *got_inflate_read_fd(struct got_inflate_buf *, int,
const struct got_error *got_inflate_to_mem(uint8_t **, size_t *, size_t *,
FILE *);
const struct got_error *got_inflate_to_mem_fd(uint8_t **, size_t *, size_t *,
- uint32_t *, size_t, int);
+ struct got_inflate_checksum *, size_t, int);
const struct got_error *got_inflate_to_mem_mmap(uint8_t **, size_t *, size_t *,
- uint32_t *, uint8_t *, size_t, size_t);
+ struct got_inflate_checksum *, uint8_t *, size_t, size_t);
const struct got_error *got_inflate_to_file(size_t *, FILE *, FILE *);
-const struct got_error *got_inflate_to_file_fd(size_t *, size_t *, uint32_t *,
- int, FILE *);
+const struct got_error *got_inflate_to_file_fd(size_t *, size_t *,
+ struct got_inflate_checksum *, int, FILE *);
const struct got_error *got_inflate_to_fd(size_t *, FILE *, int);
const struct got_error *got_inflate_to_file_mmap(size_t *, size_t *,
- uint32_t *, uint8_t *, size_t, size_t, FILE *);
+ struct got_inflate_checksum *, uint8_t *, size_t, size_t, FILE *);
blob - 50d5e7725fec453a7a1d9c9401bf8576478b267e
blob + fbef58ae984ad17c5cf64c92059811d717395226
--- lib/inflate.c
+++ lib/inflate.c
const struct got_error *
got_inflate_init(struct got_inflate_buf *zb, uint8_t *outbuf, size_t bufsize,
- uint32_t *input_crc)
+ struct got_inflate_checksum *csum)
{
const struct got_error *err = NULL;
int zerr;
} else
zb->outbuf = outbuf;
- zb->input_crc = input_crc;
+ zb->csum = csum;
done:
if (err)
got_inflate_end(zb);
return err;
}
+static void
+csum_input(struct got_inflate_checksum *csum, const char *buf, size_t len)
+{
+ if (csum->input_crc)
+ *csum->input_crc = crc32(*csum->input_crc, buf, len);
+
+ if (csum->input_sha1)
+ SHA1Update(csum->input_sha1, buf, len);
+}
+
const struct got_error *
got_inflate_read(struct got_inflate_buf *zb, FILE *f, size_t *outlenp,
size_t *consumed)
if (consumed)
*consumed = 0;
do {
- char *crc_in = NULL;
- size_t crc_avail = 0;
+ char *csum_in = NULL;
+ size_t csum_avail = 0;
if (z->avail_in == 0) {
size_t n = fread(zb->inbuf, 1, zb->inlen, f);
z->next_in = zb->inbuf;
z->avail_in = n;
}
- if (zb->input_crc) {
- crc_in = z->next_in;
- crc_avail = z->avail_in;
+ if (zb->csum) {
+ csum_in = z->next_in;
+ csum_avail = z->avail_in;
}
ret = inflate(z, Z_SYNC_FLUSH);
- if (zb->input_crc) {
- *zb->input_crc = crc32(*zb->input_crc,
- crc_in, crc_avail - z->avail_in);
- }
+ if (zb->csum)
+ csum_input(zb->csum, csum_in, csum_avail - z->avail_in);
} while (ret == Z_OK && z->avail_out > 0);
if (ret == Z_OK || ret == Z_BUF_ERROR) {
if (consumed)
*consumed = 0;
do {
- char *crc_in = NULL;
- size_t crc_avail = 0;
+ char *csum_in = NULL;
+ size_t csum_avail = 0;
if (z->avail_in == 0) {
ssize_t n = read(fd, zb->inbuf, zb->inlen);
z->next_in = zb->inbuf;
z->avail_in = n;
}
- if (zb->input_crc) {
- crc_in = z->next_in;
- crc_avail = z->avail_in;
+ if (zb->csum) {
+ csum_in = z->next_in;
+ csum_avail = z->avail_in;
}
ret = inflate(z, Z_SYNC_FLUSH);
- if (zb->input_crc) {
- *zb->input_crc = crc32(*zb->input_crc,
- crc_in, crc_avail - z->avail_in);
- }
+ if (zb->csum)
+ csum_input(zb->csum, csum_in, csum_avail - z->avail_in);
} while (ret == Z_OK && z->avail_out > 0);
if (ret == Z_OK || ret == Z_BUF_ERROR) {
*consumed = 0;
do {
- char *crc_in = NULL;
- size_t crc_avail = 0;
+ char *csum_in = NULL;
+ size_t csum_avail = 0;
size_t last_total_in = zb->z.total_in;
if (z->avail_in == 0) {
z->next_in = map + offset + *consumed;
z->avail_in = len - *consumed;
}
- if (zb->input_crc) {
- crc_in = z->next_in;
- crc_avail = z->avail_in;
+ if (zb->csum) {
+ csum_in = z->next_in;
+ csum_avail = z->avail_in;
}
ret = inflate(z, Z_SYNC_FLUSH);
- if (zb->input_crc) {
- *zb->input_crc = crc32(*zb->input_crc,
- crc_in, crc_avail - z->avail_in);
- }
+ if (zb->csum)
+ csum_input(zb->csum, csum_in, csum_avail - z->avail_in);
*consumed += z->total_in - last_total_in;
} while (ret == Z_OK && z->avail_out > 0);
const struct got_error *
got_inflate_to_mem_fd(uint8_t **outbuf, size_t *outlen,
- size_t *consumed_total, uint32_t *input_crc, size_t expected_size, int infd)
+ size_t *consumed_total, struct got_inflate_checksum *csum,
+ size_t expected_size, int infd)
{
const struct got_error *err;
size_t avail, consumed;
*outbuf = malloc(bufsize);
if (*outbuf == NULL)
return got_error_from_errno("malloc");
- err = got_inflate_init(&zb, *outbuf, GOT_INFLATE_BUFSIZE,
- input_crc);
+ err = got_inflate_init(&zb, *outbuf, GOT_INFLATE_BUFSIZE, csum);
} else
- err = got_inflate_init(&zb, NULL, bufsize, input_crc);
+ err = got_inflate_init(&zb, NULL, bufsize, csum);
if (err)
goto done;
const struct got_error *
got_inflate_to_mem_mmap(uint8_t **outbuf, size_t *outlen,
- size_t *consumed_total, uint32_t *input_crc, uint8_t *map, size_t offset,
- size_t len)
+ size_t *consumed_total, struct got_inflate_checksum *csum, uint8_t *map,
+ size_t offset, size_t len)
{
const struct got_error *err;
size_t avail, consumed;
*outbuf = malloc(GOT_INFLATE_BUFSIZE);
if (*outbuf == NULL)
return got_error_from_errno("malloc");
- err = got_inflate_init(&zb, *outbuf, GOT_INFLATE_BUFSIZE,
- input_crc);
+ err = got_inflate_init(&zb, *outbuf, GOT_INFLATE_BUFSIZE, csum);
if (err) {
free(*outbuf);
*outbuf = NULL;
return err;
}
} else {
- err = got_inflate_init(&zb, NULL, GOT_INFLATE_BUFSIZE,
- input_crc);
+ err = got_inflate_init(&zb, NULL, GOT_INFLATE_BUFSIZE, csum);
}
*outlen = 0;
const struct got_error *
got_inflate_to_file_fd(size_t *outlen, size_t *consumed_total,
- uint32_t *input_crc, int infd, FILE *outfile)
+ struct got_inflate_checksum *csum, int infd, FILE *outfile)
{
const struct got_error *err;
size_t avail, consumed;
struct got_inflate_buf zb;
- err = got_inflate_init(&zb, NULL, GOT_INFLATE_BUFSIZE, input_crc);
+ err = got_inflate_init(&zb, NULL, GOT_INFLATE_BUFSIZE, csum);
if (err)
goto done;
const struct got_error *
got_inflate_to_file_mmap(size_t *outlen, size_t *consumed_total,
- uint32_t *input_crc, uint8_t *map, size_t offset, size_t len,
- FILE *outfile)
+ struct got_inflate_checksum *csum, uint8_t *map, size_t offset,
+ size_t len, FILE *outfile)
{
const struct got_error *err;
size_t avail, consumed;
struct got_inflate_buf zb;
- err = got_inflate_init(&zb, NULL, GOT_INFLATE_BUFSIZE, input_crc);
+ err = got_inflate_init(&zb, NULL, GOT_INFLATE_BUFSIZE, csum);
if (err)
goto done;
blob - bfc9107d2db18c2536c48ab9fad45c73b2153910
blob + 90e1671dd36a9e6ac6007310645d997084c9c5db
--- libexec/got-index-pack/got-index-pack.c
+++ libexec/got-index-pack/got-index-pack.c
}
static const struct got_error *
-read_crc(uint32_t *crc, int fd, size_t len)
+read_checksum(uint32_t *crc, SHA1_CTX *sha1_ctx, int fd, size_t len)
{
uint8_t buf[8192];
size_t n;
return got_error_from_errno("read");
if (r == 0)
break;
- *crc = crc32(*crc, buf, r);
+ if (crc)
+ *crc = crc32(*crc, buf, r);
+ if (sha1_ctx)
+ SHA1Update(sha1_ctx, buf, r);
}
return NULL;
static const struct got_error *
read_packed_object(struct got_pack *pack, struct got_indexed_object *obj,
- FILE *tmpfile)
+ FILE *tmpfile, SHA1_CTX *pack_sha1_ctx)
{
const struct got_error *err = NULL;
SHA1_CTX ctx;
size_t headerlen;
const char *obj_label;
size_t mapoff = obj->off;
+ struct got_inflate_checksum csum;
+ csum.input_sha1 = pack_sha1_ctx;
+ csum.input_crc = &obj->crc;
+
err = got_pack_parse_object_type_and_size(&obj->type, &obj->size,
&obj->tslen, pack, obj->off);
if (err)
if (pack->map) {
obj->crc = crc32(obj->crc, pack->map + mapoff, obj->tslen);
+ SHA1Update(pack_sha1_ctx, pack->map + mapoff, obj->tslen);
mapoff += obj->tslen;
} else {
/* XXX Seek back and get the CRC of on-disk type+size bytes. */
if (lseek(pack->fd, obj->off, SEEK_SET) == -1)
return got_error_from_errno("lseek");
- err = read_crc(&obj->crc, pack->fd, obj->tslen);
+ err = read_checksum(&obj->crc, pack_sha1_ctx,
+ pack->fd, obj->tslen);
if (err)
return err;
}
}
if (pack->map) {
err = got_inflate_to_file_mmap(&datalen,
- &obj->len, &obj->crc, pack->map, mapoff,
+ &obj->len, &csum, pack->map, mapoff,
pack->filesize - mapoff, tmpfile);
} else {
err = got_inflate_to_file_fd(&datalen,
- &obj->len, &obj->crc, pack->fd, tmpfile);
+ &obj->len, &csum, pack->fd, tmpfile);
}
} else {
if (pack->map) {
err = got_inflate_to_mem_mmap(&data, &datalen,
- &obj->len, &obj->crc, pack->map, mapoff,
+ &obj->len, &csum, pack->map, mapoff,
pack->filesize - mapoff);
} else {
err = got_inflate_to_mem_fd(&data, &datalen,
- &obj->len, &obj->crc, obj->size, pack->fd);
+ &obj->len, &csum, obj->size, pack->fd);
}
}
if (err)
SHA1_DIGEST_LENGTH);
obj->crc = crc32(obj->crc, pack->map + mapoff,
SHA1_DIGEST_LENGTH);
+ SHA1Update(pack_sha1_ctx, pack->map + mapoff,
+ SHA1_DIGEST_LENGTH);
mapoff += SHA1_DIGEST_LENGTH;
err = got_inflate_to_mem_mmap(NULL, &datalen,
- &obj->len, &obj->crc, pack->map, mapoff,
+ &obj->len, &csum, pack->map, mapoff,
pack->filesize - mapoff);
if (err)
break;
}
obj->crc = crc32(obj->crc, obj->delta.ref.ref_id.sha1,
SHA1_DIGEST_LENGTH);
+ SHA1Update(pack_sha1_ctx, obj->delta.ref.ref_id.sha1,
+ SHA1_DIGEST_LENGTH);
err = got_inflate_to_mem_fd(NULL, &datalen, &obj->len,
- &obj->crc, obj->size, pack->fd);
+ &csum, obj->size, pack->fd);
if (err)
break;
}
if (pack->map) {
obj->crc = crc32(obj->crc, pack->map + mapoff,
obj->delta.ofs.base_offsetlen);
+ SHA1Update(pack_sha1_ctx, pack->map + mapoff,
+ obj->delta.ofs.base_offsetlen);
mapoff += obj->delta.ofs.base_offsetlen;
err = got_inflate_to_mem_mmap(NULL, &datalen,
- &obj->len, &obj->crc, pack->map, mapoff,
+ &obj->len, &csum, pack->map, mapoff,
pack->filesize - mapoff);
if (err)
break;
} else {
/*
- * XXX Seek back and get the CRC of on-disk
+ * XXX Seek back and get CRC and SHA1 of on-disk
* offset bytes.
*/
if (lseek(pack->fd, obj->off + obj->tslen, SEEK_SET)
err = got_error_from_errno("lseek");
break;
}
- err = read_crc(&obj->crc, pack->fd,
- obj->delta.ofs.base_offsetlen);
+ err = read_checksum(&obj->crc, pack_sha1_ctx,
+ pack->fd, obj->delta.ofs.base_offsetlen);
if (err)
break;
err = got_inflate_to_mem_fd(NULL, &datalen, &obj->len,
- &obj->crc, obj->size, pack->fd);
+ &csum, obj->size, pack->fd);
if (err)
break;
}
struct got_packfile_hdr hdr;
struct got_packidx packidx;
char buf[8];
+ char pack_sha1[SHA1_DIGEST_LENGTH];
+ char pack_sha1_expected[SHA1_DIGEST_LENGTH];
int nobj, nvalid, nloose, nresolved = 0, i;
struct got_indexed_object *objects = NULL, *obj;
SHA1_CTX ctx;
int p_indexed = 0, last_p_indexed = -1;
int p_resolved = 0, last_p_resolved = -1;
- /* Check pack file header. */
+ /* Require that pack file header and SHA1 trailer are present. */
+ if (pack->filesize < sizeof(hdr) + SHA1_DIGEST_LENGTH)
+ return got_error_msg(GOT_ERR_BAD_PACKFILE,
+ "short pack file");
+
if (pack->map) {
- if (pack->filesize < sizeof(hdr))
- return got_error_msg(GOT_ERR_BAD_PACKFILE,
- "short packfile header");
memcpy(&hdr, pack->map, sizeof(hdr));
mapoff += sizeof(hdr);
} else {
return got_error_from_errno("read");
if (r < sizeof(hdr))
return got_error_msg(GOT_ERR_BAD_PACKFILE,
- "short packfile header");
+ "short pack file");
}
if (hdr.signature != htobe32(GOT_PACKFILE_SIGNATURE))
return got_error_msg(GOT_ERR_BAD_PACKFILE,
"bad packfile with zero objects");
+ /* We compute the SHA1 of pack file contents and verify later on. */
+ SHA1Init(&ctx);
+ SHA1Update(&ctx, (void *)&hdr, sizeof(hdr));
+
/*
* Create an in-memory pack index which will grow as objects
* IDs in the pack file are discovered. Only fields used to
}
}
- err = read_packed_object(pack, obj, tmpfile);
+ err = read_packed_object(pack, obj, tmpfile, &ctx);
if (err)
goto done;
}
nvalid = nloose;
+ /*
+ * Having done a full pass over the pack file and can now
+ * verify its checksum.
+ */
+ SHA1Final(pack_sha1, &ctx);
+ if (pack->map) {
+ memcpy(pack_sha1_expected, pack->map +
+ pack->filesize - SHA1_DIGEST_LENGTH,
+ SHA1_DIGEST_LENGTH);
+ } else {
+ ssize_t n;
+ if (lseek(pack->fd, -SHA1_DIGEST_LENGTH, SEEK_END) == -1) {
+ err = got_error_from_errno("lseek");
+ goto done;
+ }
+ n = read(pack->fd, pack_sha1_expected, SHA1_DIGEST_LENGTH);
+ if (n == -1) {
+ err = got_error_from_errno("read");
+ goto done;
+ }
+ if (n != SHA1_DIGEST_LENGTH) {
+ err = got_error(GOT_ERR_IO);
+ goto done;
+ }
+ }
+ if (memcmp(pack_sha1, pack_sha1_expected, SHA1_DIGEST_LENGTH) != 0) {
+ err = got_error_msg(GOT_ERR_BAD_PACKFILE,
+ "pack file checksum mismatch");
+ goto done;
+ }
+
if (first_delta_idx == -1)
first_delta_idx = 0;