diff --git a/gpg-interface.c b/gpg-interface.c index 4feacf16e5..0647bd6348 100644 --- a/gpg-interface.c +++ b/gpg-interface.c @@ -101,22 +101,26 @@ void print_signature_buffer(const struct signature_check *sigc, unsigned flags) fputs(output, stderr); } -/* - * Look at GPG signed content (e.g. a signed tag object), whose - * payload is followed by a detached signature on it. Return the - * offset where the embedded detached signature begins, or the end of - * the data when there is no such signature. - */ -size_t parse_signature(const char *buf, unsigned long size) +static int is_gpg_start(const char *line) +{ + return starts_with(line, PGP_SIGNATURE) || + starts_with(line, PGP_MESSAGE); +} + +size_t parse_signature(const char *buf, size_t size) { - char *eol; size_t len = 0; - while (len < size && !starts_with(buf + len, PGP_SIGNATURE) && - !starts_with(buf + len, PGP_MESSAGE)) { + size_t match = size; + while (len < size) { + const char *eol; + + if (is_gpg_start(buf + len)) + match = len; + eol = memchr(buf + len, '\n', size - len); len += eol ? eol - (buf + len) + 1 : size - len; } - return len; + return match; } void set_signing_key(const char *key) @@ -128,13 +132,19 @@ void set_signing_key(const char *key) int git_gpg_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "user.signingkey")) { + if (!value) + return config_error_nonbool(var); set_signing_key(value); + return 0; } + if (!strcmp(var, "gpg.program")) { if (!value) return config_error_nonbool(var); gpg_program = xstrdup(value); + return 0; } + return 0; } @@ -145,12 +155,6 @@ const char *get_signing_key(void) return git_committer_info(IDENT_STRICT|IDENT_NO_DATE); } -/* - * Create a detached signature for the contents of "buffer" and append - * it after "signature"; "buffer" and "signature" can be the same - * strbuf instance, which would cause the detached signature appended - * at the end. - */ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key) { struct child_process gpg = CHILD_PROCESS_INIT; @@ -192,11 +196,6 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *sig return 0; } -/* - * Run "gpg" to see if the payload matches the detached signature. - * gpg_output, when set, receives the diagnostic output from GPG. - * gpg_status, when set, receives the status output from GPG. - */ int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, struct strbuf *gpg_output, struct strbuf *gpg_status) diff --git a/gpg-interface.h b/gpg-interface.h index d2d4fd3a65..a5e6517ae6 100644 --- a/gpg-interface.h +++ b/gpg-interface.h @@ -23,16 +23,43 @@ struct signature_check { char *key; }; -extern void signature_check_clear(struct signature_check *sigc); -extern size_t parse_signature(const char *buf, unsigned long size); -extern void parse_gpg_output(struct signature_check *); -extern int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key); -extern int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, struct strbuf *gpg_output, struct strbuf *gpg_status); -extern int git_gpg_config(const char *, const char *, void *); -extern void set_signing_key(const char *); -extern const char *get_signing_key(void); -extern int check_signature(const char *payload, size_t plen, - const char *signature, size_t slen, struct signature_check *sigc); -void print_signature_buffer(const struct signature_check *sigc, unsigned flags); +void signature_check_clear(struct signature_check *sigc); + +/* + * Look at GPG signed content (e.g. a signed tag object), whose + * payload is followed by a detached signature on it. Return the + * offset where the embedded detached signature begins, or the end of + * the data when there is no such signature. + */ +size_t parse_signature(const char *buf, size_t size); + +void parse_gpg_output(struct signature_check *); + +/* + * Create a detached signature for the contents of "buffer" and append + * it after "signature"; "buffer" and "signature" can be the same + * strbuf instance, which would cause the detached signature appended + * at the end. + */ +int sign_buffer(struct strbuf *buffer, struct strbuf *signature, + const char *signing_key); + +/* + * Run "gpg" to see if the payload matches the detached signature. + * gpg_output, when set, receives the diagnostic output from GPG. + * gpg_status, when set, receives the status output from GPG. + */ +int verify_signed_buffer(const char *payload, size_t payload_size, + const char *signature, size_t signature_size, + struct strbuf *gpg_output, struct strbuf *gpg_status); + +int git_gpg_config(const char *, const char *, void *); +void set_signing_key(const char *); +const char *get_signing_key(void); +int check_signature(const char *payload, size_t plen, + const char *signature, size_t slen, + struct signature_check *sigc); +void print_signature_buffer(const struct signature_check *sigc, + unsigned flags); #endif diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 2aac77af70..e3f1e014aa 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -1056,7 +1056,18 @@ test_expect_success GPG \ git tag -s -F sigblanknonlfile blanknonlfile-signed-tag && get_tag_msg blanknonlfile-signed-tag >actual && test_cmp expect actual && - git tag -v signed-tag + git tag -v blanknonlfile-signed-tag +' + +test_expect_success GPG 'signed tag with embedded PGP message' ' + cat >msg <<-\EOF && + -----BEGIN PGP MESSAGE----- + + this is not a real PGP message + -----END PGP MESSAGE----- + EOF + git tag -s -F msg confusing-pgp-message && + git tag -v confusing-pgp-message ' # messages with commented lines for signed tags: