Commit 0ebaf0082bfd162e1116889d2b13917efd07d317

Stefan Sperling 2018-01-10T21:56:48

verify pack file index checksum

diff --git a/include/got_error.h b/include/got_error.h
index fbfadea..79deadb 100644
--- a/include/got_error.h
+++ b/include/got_error.h
@@ -30,6 +30,7 @@
 #define GOT_ERR_BAD_OBJ_DATA	0x0012
 #define GOT_ERR_FILE_OPEN	0x0013
 #define GOT_ERR_BAD_PACKIDX	0x0014
+#define GOT_ERR_PACKIDX_CSUM	0x0015
 
 static const struct got_error {
 	int code;
@@ -50,6 +51,7 @@ static const struct got_error {
 	{ GOT_ERR_BAD_OBJ_DATA,	"bad object data" },
 	{ GOT_ERR_FILE_OPEN,	"could not open file" },
 	{ GOT_ERR_BAD_PACKIDX,	"bad pack index file" },
+	{ GOT_ERR_PACKIDX_CSUM, "pack index file checksum error" },
 };
 
 const struct got_error * got_error(int code);
diff --git a/lib/pack.c b/lib/pack.c
index f8e642d..78231e4 100644
--- a/lib/pack.c
+++ b/lib/pack.c
@@ -75,6 +75,10 @@ got_packidx_open(struct got_packidx_v2_hdr **packidx, const char *path)
 	FILE *f;
 	const struct got_error *err = NULL;
 	size_t n, nobj, packfile_size;
+	SHA1_CTX ctx;
+	uint8_t sha1[SHA1_DIGEST_LENGTH];
+
+	SHA1Init(&ctx);
 
 	f = fopen(path, "rb");
 	if (f == NULL)
@@ -101,6 +105,8 @@ got_packidx_open(struct got_packidx_v2_hdr **packidx, const char *path)
 		goto done;
 	}
 
+	SHA1Update(&ctx, (uint8_t *)&p->magic, sizeof(p->magic));
+
 	n = fread(&p->version, sizeof(p->version), 1, f);
 	if (n != 1) {
 		err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
@@ -112,6 +118,8 @@ got_packidx_open(struct got_packidx_v2_hdr **packidx, const char *path)
 		goto done;
 	}
 
+	SHA1Update(&ctx, (uint8_t *)&p->version, sizeof(p->version));
+
 	n = fread(&p->fanout_table, sizeof(p->fanout_table), 1, f);
 	if (n != 1) {
 		err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
@@ -122,6 +130,8 @@ got_packidx_open(struct got_packidx_v2_hdr **packidx, const char *path)
 	if (err)
 		goto done;
 
+	SHA1Update(&ctx, (uint8_t *)p->fanout_table, sizeof(p->fanout_table));
+
 	nobj = betoh32(p->fanout_table[0xff]);
 
 	p->sorted_ids = calloc(nobj, sizeof(*p->sorted_ids));
@@ -136,6 +146,9 @@ got_packidx_open(struct got_packidx_v2_hdr **packidx, const char *path)
 		goto done;
 	}
 
+	SHA1Update(&ctx, (uint8_t *)p->sorted_ids,
+	    nobj * sizeof(*p->sorted_ids));
+
 	p->offsets = calloc(nobj, sizeof(*p->offsets));
 	if (p->offsets == NULL) {
 		err = got_error(GOT_ERR_NO_MEM);
@@ -148,6 +161,8 @@ got_packidx_open(struct got_packidx_v2_hdr **packidx, const char *path)
 		goto done;
 	}
 
+	SHA1Update(&ctx, (uint8_t *)p->offsets, nobj * sizeof(*p->offsets));
+
 	p->crc32 = calloc(nobj, sizeof(*p->crc32));
 	if (p->crc32 == NULL) {
 		err = got_error(GOT_ERR_NO_MEM);
@@ -160,6 +175,8 @@ got_packidx_open(struct got_packidx_v2_hdr **packidx, const char *path)
 		goto done;
 	}
 
+	SHA1Update(&ctx, (uint8_t *)p->crc32, nobj * sizeof(*p->crc32));
+
 	/* Large file offsets are contained only in files > 2GB. */
 	if (packfile_size <= 0x80000000)
 		goto checksum;
@@ -176,6 +193,9 @@ got_packidx_open(struct got_packidx_v2_hdr **packidx, const char *path)
 		goto done;
 	}
 
+	SHA1Update(&ctx, (uint8_t*)p->large_offsets,
+	    nobj * sizeof(*p->large_offsets));
+
 checksum:
 
 	n = fread(&p->trailer, sizeof(p->trailer), 1, f);
@@ -184,8 +204,10 @@ checksum:
 		goto done;
 	}
 
-	/* TODO verify checksum */
-
+	SHA1Update(&ctx, p->trailer.pack_file_sha1, SHA1_DIGEST_LENGTH);
+	SHA1Final(sha1, &ctx);
+	if (memcmp(p->trailer.pack_idx_sha1, sha1, SHA1_DIGEST_LENGTH) != 0)
+		err = got_error(GOT_ERR_PACKIDX_CSUM);
 done:
 	fclose(f);
 	if (err)