diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2016-02-08 18:51:13 +0100 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2016-02-09 15:58:16 +0100 |
commit | a65afb757e2675eb8889a9ce1f8809434cdb3af7 (patch) | |
tree | 560d6cf3ffb0eec439ad03afab83e6575e2e9326 /src/commit.c | |
parent | 0f9d15493d5d8ad4353dd7beed52c9567334f6e5 (diff) | |
download | libgit2-gpgsign.tar.gz |
Introduce git_commit_extract_signaturegpgsign
This returns the GPG signature for a commit and its contents without the
signature block, allowing for the verification of the commit's
signature.
Diffstat (limited to 'src/commit.c')
-rw-r--r-- | src/commit.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/commit.c b/src/commit.c index 81aae489f..c5e580139 100644 --- a/src/commit.c +++ b/src/commit.c @@ -616,3 +616,89 @@ oom: giterr_set_oom(); return -1; } + +int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_repository *repo, git_oid *commit_id, const char *field) +{ + git_odb_object *obj; + git_odb *odb; + const char *buf; + const char *h, *eol; + int error; + + git_buf_sanitize(signature); + git_buf_sanitize(signed_data); + + if (!field) + field = "gpgsig"; + + if ((error = git_repository_odb__weakptr(&odb, repo)) < 0) + return error; + + if ((error = git_odb_read(&obj, odb, commit_id)) < 0) + return error; + + buf = git_odb_object_data(obj); + + while ((h = strchr(buf, '\n')) && h[1] != '\0' && h[1] != '\n') { + h++; + if (git__prefixcmp(buf, field)) { + if (git_buf_put(signed_data, buf, h - buf) < 0) + return -1; + + buf = h; + continue; + } + + h = buf; + h += strlen(field); + eol = strchr(h, '\n'); + if (h[0] != ' ') { + buf = h; + continue; + } + if (!eol) + goto malformed; + + h++; /* skip the SP */ + + git_buf_put(signature, h, eol - h); + if (git_buf_oom(signature)) + goto oom; + + /* If the next line starts with SP, it's multi-line, we must continue */ + while (eol[1] == ' ') { + git_buf_putc(signature, '\n'); + h = eol + 2; + eol = strchr(h, '\n'); + if (!eol) + goto malformed; + + git_buf_put(signature, h, eol - h); + } + + if (git_buf_oom(signature)) + goto oom; + + git_odb_object_free(obj); + return git_buf_puts(signed_data, eol+1); + } + + giterr_set(GITERR_INVALID, "this commit is not signed"); + error = GIT_ENOTFOUND; + goto cleanup; + +malformed: + giterr_set(GITERR_OBJECT, "malformed header"); + error = -1; + goto cleanup; +oom: + giterr_set_oom(); + error = -1; + goto cleanup; + +cleanup: + git_odb_object_free(obj); + git_buf_clear(signature); + git_buf_clear(signed_data); + return error; +} |