check pack file hash in the main process
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
diff --git a/lib/fetch.c b/lib/fetch.c
index 4936c36..e70d912 100644
--- a/lib/fetch.c
+++ b/lib/fetch.c
@@ -297,6 +297,48 @@ done:
return err;
}
+static const struct got_error *
+check_pack_hash(int fd, size_t sz, uint8_t *hcomp)
+{
+ SHA1_CTX ctx;
+ uint8_t hexpect[SHA1_DIGEST_LENGTH];
+ uint8_t buf[32 * 1024];
+ ssize_t n, r, nr;
+
+ if (sz < sizeof(struct got_packfile_hdr) + SHA1_DIGEST_LENGTH)
+ return got_error_msg(GOT_ERR_BAD_PACKFILE, "short packfile");
+
+ n = 0;
+ SHA1Init(&ctx);
+ while (n < sz - 20) {
+ nr = sizeof(buf);
+ if (sz - n - 20 < sizeof(buf))
+ nr = sz - n - 20;
+ r = read(fd, buf, nr);
+ if (r == -1)
+ return got_error_from_errno("read");
+ if (r != nr)
+ return got_error_msg(GOT_ERR_BAD_PACKFILE,
+ "short pack file");
+ SHA1Update(&ctx, buf, nr);
+ n += r;
+ }
+ SHA1Final(hcomp, &ctx);
+
+ r = read(fd, hexpect, sizeof(hexpect));
+ if (r == -1)
+ return got_error_from_errno("read");
+ if (r != sizeof(hexpect))
+ return got_error_msg(GOT_ERR_BAD_PACKFILE,
+ "short pack file");
+
+ if (memcmp(hcomp, hexpect, SHA1_DIGEST_LENGTH) != 0)
+ return got_error_msg(GOT_ERR_BAD_PACKFILE,
+ "packfile checksum mismatch");
+
+ return NULL;
+}
+
const struct got_error*
got_fetch_pack(struct got_object_id **pack_hash, struct got_pathlist_head *refs,
struct got_pathlist_head *symrefs, int fetchfd, struct got_repository *repo,
@@ -428,6 +470,14 @@ got_fetch_pack(struct got_object_id **pack_hash, struct got_pathlist_head *refs,
err = got_error_from_errno("waitpid");
goto done;
}
+
+ if (lseek(packfd, 0, SEEK_SET) == -1) {
+ err = got_error_from_errno("lseek");
+ goto done;
+ }
+ err = check_pack_hash(packfd, packfile_size, (*pack_hash)->sha1);
+ if (err)
+ goto done;
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_idxfds) == -1) {
err = got_error_from_errno("socketpair");
diff --git a/libexec/got-fetch-pack/got-fetch-pack.c b/libexec/got-fetch-pack/got-fetch-pack.c
index 14fb915..bbc450c 100644
--- a/libexec/got-fetch-pack/got-fetch-pack.c
+++ b/libexec/got-fetch-pack/got-fetch-pack.c
@@ -214,44 +214,6 @@ match_remote_ref(struct got_pathlist_head *have_refs, struct got_object_id *id,
return NULL;
}
-static const struct got_error *
-check_pack_hash(int fd, size_t sz, uint8_t *hcomp)
-{
- const struct got_error *err = NULL;
- SHA1_CTX ctx;
- uint8_t hexpect[SHA1_DIGEST_LENGTH];
- uint8_t buf[32 * 1024];
- ssize_t n, r, nr;
-
- if (sz < sizeof(struct got_packfile_hdr) + SHA1_DIGEST_LENGTH)
- return got_error_msg(GOT_ERR_BAD_PACKFILE, "short packfile");
-
- n = 0;
- SHA1Init(&ctx);
- while (n < sz - 20) {
- nr = sizeof(buf);
- if (sz - n - 20 < sizeof(buf))
- nr = sz - n - 20;
- err = readn(&r, fd, buf, nr);
- if (err)
- return err;
- if (r != nr)
- return got_error(GOT_ERR_BAD_PACKFILE);
- SHA1Update(&ctx, buf, nr);
- n += r;
- }
- SHA1Final(hcomp, &ctx);
-
- err = readn(&r, fd, hexpect, sizeof(hexpect));
- if (err)
- return err;
- if (r != sizeof(hexpect))
- return got_error(GOT_ERR_BAD_PACKFILE);
- if (memcmp(hcomp, hexpect, SHA1_DIGEST_LENGTH) != 0)
- return got_error(GOT_ERR_BAD_PACKFILE);
- return NULL;
-}
-
static int
match_branch(char *br, char *pat)
{
@@ -778,11 +740,6 @@ fetch_pack(int fd, int packfd, struct got_object_id *packid,
if (err)
goto done;
}
- if (lseek(packfd, 0, SEEK_SET) == -1) {
- err = got_error_from_errno("lseek");
- goto done;
- }
- err = check_pack_hash(packfd, packsz, packid->sha1);
done:
TAILQ_FOREACH(pe, &symrefs, entry) {
free((void *)pe->path);