Merge branch 'bt/gpg-interface'

What is queued here is only the obviously correct and
uncontroversial code clean-up part, which is an earlier 7 patches,
of a larger series.

The remainder that is not queued introduces a few configuration
variables to deal with e-signature backends with different
signature format.

* bt/gpg-interface:
  gpg-interface: find the last gpg signature line
  gpg-interface: extract gpg line matching helper
  gpg-interface: fix const-correctness of "eol" pointer
  gpg-interface: use size_t for signature buffer size
  gpg-interface: modernize function declarations
  gpg-interface: handle bool user.signingkey
  t7004: fix mistaken tag name
This commit is contained in:
Junio C Hamano 2018-05-08 15:59:29 +09:00
commit 6d2a655a4f
3 changed files with 71 additions and 34 deletions

View File

@ -101,22 +101,26 @@ void print_signature_buffer(const struct signature_check *sigc, unsigned flags)
fputs(output, stderr); fputs(output, stderr);
} }
/* static int is_gpg_start(const char *line)
* Look at GPG signed content (e.g. a signed tag object), whose {
* payload is followed by a detached signature on it. Return the return starts_with(line, PGP_SIGNATURE) ||
* offset where the embedded detached signature begins, or the end of starts_with(line, PGP_MESSAGE);
* the data when there is no such signature. }
*/
size_t parse_signature(const char *buf, unsigned long size) size_t parse_signature(const char *buf, size_t size)
{ {
char *eol;
size_t len = 0; size_t len = 0;
while (len < size && !starts_with(buf + len, PGP_SIGNATURE) && size_t match = size;
!starts_with(buf + len, PGP_MESSAGE)) { while (len < size) {
const char *eol;
if (is_gpg_start(buf + len))
match = len;
eol = memchr(buf + len, '\n', size - len); eol = memchr(buf + len, '\n', size - len);
len += eol ? eol - (buf + len) + 1 : size - len; len += eol ? eol - (buf + len) + 1 : size - len;
} }
return len; return match;
} }
void set_signing_key(const char *key) 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) int git_gpg_config(const char *var, const char *value, void *cb)
{ {
if (!strcmp(var, "user.signingkey")) { if (!strcmp(var, "user.signingkey")) {
if (!value)
return config_error_nonbool(var);
set_signing_key(value); set_signing_key(value);
return 0;
} }
if (!strcmp(var, "gpg.program")) { if (!strcmp(var, "gpg.program")) {
if (!value) if (!value)
return config_error_nonbool(var); return config_error_nonbool(var);
gpg_program = xstrdup(value); gpg_program = xstrdup(value);
return 0;
} }
return 0; return 0;
} }
@ -145,12 +155,6 @@ const char *get_signing_key(void)
return git_committer_info(IDENT_STRICT|IDENT_NO_DATE); 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) int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key)
{ {
struct child_process gpg = CHILD_PROCESS_INIT; 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; 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, int verify_signed_buffer(const char *payload, size_t payload_size,
const char *signature, size_t signature_size, const char *signature, size_t signature_size,
struct strbuf *gpg_output, struct strbuf *gpg_status) struct strbuf *gpg_output, struct strbuf *gpg_status)

View File

@ -23,16 +23,43 @@ struct signature_check {
char *key; char *key;
}; };
extern void signature_check_clear(struct signature_check *sigc); 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); * Look at GPG signed content (e.g. a signed tag object), whose
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); * payload is followed by a detached signature on it. Return the
extern int git_gpg_config(const char *, const char *, void *); * offset where the embedded detached signature begins, or the end of
extern void set_signing_key(const char *); * the data when there is no such signature.
extern const char *get_signing_key(void); */
extern int check_signature(const char *payload, size_t plen, size_t parse_signature(const char *buf, size_t size);
const char *signature, size_t slen, struct signature_check *sigc);
void print_signature_buffer(const struct signature_check *sigc, unsigned flags); 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 #endif

View File

@ -1056,7 +1056,18 @@ test_expect_success GPG \
git tag -s -F sigblanknonlfile blanknonlfile-signed-tag && git tag -s -F sigblanknonlfile blanknonlfile-signed-tag &&
get_tag_msg blanknonlfile-signed-tag >actual && get_tag_msg blanknonlfile-signed-tag >actual &&
test_cmp expect 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: # messages with commented lines for signed tags: