fast-import: add 'strip-if-invalid' mode to '--signed-tags=<mode>'
With c20f112e51 (fast-import: add 'strip-if-invalid' mode to
--signed-commits=<mode>, 2025-11-17), git-fast-import(1) learned to
verify commit signatures during import and strip signatures that fail
verification. Extend the same behavior to signed tag objects by
introducing a 'strip-if-invalid' mode for the '--signed-tags' option.
Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
parent
4c36345e04
commit
817b042879
|
|
@ -66,11 +66,10 @@ fast-import stream! This option is enabled automatically for
|
|||
remote-helpers that use the `import` capability, as they are
|
||||
already trusted to run their own code.
|
||||
|
||||
`--signed-tags=(verbatim|warn-verbatim|warn-strip|strip|abort)`::
|
||||
`--signed-tags=<mode>`::
|
||||
Specify how to handle signed tags. Behaves in the same way as
|
||||
the `--signed-commits=<mode>` below, except that the
|
||||
`strip-if-invalid` mode is not yet supported. Like for signed
|
||||
commits, the default mode is `verbatim`.
|
||||
the `--signed-commits=<mode>` below. Like for signed commits,
|
||||
the default mode is `verbatim`.
|
||||
|
||||
`--signed-commits=<mode>`::
|
||||
Specify how to handle signed commits. The following <mode>s
|
||||
|
|
|
|||
|
|
@ -3089,7 +3089,34 @@ static void parse_new_commit(const char *arg)
|
|||
b->last_commit = object_count_by_type[OBJ_COMMIT];
|
||||
}
|
||||
|
||||
static void handle_tag_signature(struct strbuf *msg, const char *name)
|
||||
static void handle_tag_signature_if_invalid(struct strbuf *buf,
|
||||
struct strbuf *msg,
|
||||
size_t sig_offset)
|
||||
{
|
||||
struct strbuf signature = STRBUF_INIT;
|
||||
struct strbuf payload = STRBUF_INIT;
|
||||
struct signature_check sigc = { 0 };
|
||||
|
||||
strbuf_addbuf(&payload, buf);
|
||||
strbuf_addch(&payload, '\n');
|
||||
strbuf_add(&payload, msg->buf, sig_offset);
|
||||
strbuf_add(&signature, msg->buf + sig_offset, msg->len - sig_offset);
|
||||
|
||||
sigc.payload_type = SIGNATURE_PAYLOAD_TAG;
|
||||
sigc.payload = strbuf_detach(&payload, &sigc.payload_len);
|
||||
|
||||
if (!check_signature(&sigc, signature.buf, signature.len))
|
||||
goto out;
|
||||
|
||||
strbuf_setlen(msg, sig_offset);
|
||||
|
||||
out:
|
||||
signature_check_clear(&sigc);
|
||||
strbuf_release(&signature);
|
||||
strbuf_release(&payload);
|
||||
}
|
||||
|
||||
static void handle_tag_signature(struct strbuf *buf, struct strbuf *msg, const char *name)
|
||||
{
|
||||
size_t sig_offset = parse_signed_buffer(msg->buf, msg->len);
|
||||
|
||||
|
|
@ -3115,6 +3142,9 @@ static void handle_tag_signature(struct strbuf *msg, const char *name)
|
|||
/* Truncate the buffer to remove the signature */
|
||||
strbuf_setlen(msg, sig_offset);
|
||||
break;
|
||||
case SIGN_STRIP_IF_INVALID:
|
||||
handle_tag_signature_if_invalid(buf, msg, sig_offset);
|
||||
break;
|
||||
|
||||
/* Third, aborting modes */
|
||||
case SIGN_ABORT:
|
||||
|
|
@ -3123,9 +3153,6 @@ static void handle_tag_signature(struct strbuf *msg, const char *name)
|
|||
case SIGN_ABORT_IF_INVALID:
|
||||
die(_("'abort-if-invalid' is not a valid mode for "
|
||||
"git fast-import with --signed-tags=<mode>"));
|
||||
case SIGN_STRIP_IF_INVALID:
|
||||
die(_("'strip-if-invalid' is not a valid mode for "
|
||||
"git fast-import with --signed-tags=<mode>"));
|
||||
case SIGN_SIGN_IF_INVALID:
|
||||
die(_("'sign-if-invalid' is not a valid mode for "
|
||||
"git fast-import with --signed-tags=<mode>"));
|
||||
|
|
@ -3198,8 +3225,6 @@ static void parse_new_tag(const char *arg)
|
|||
/* tag payload/message */
|
||||
parse_data(&msg, 0, NULL);
|
||||
|
||||
handle_tag_signature(&msg, t->name);
|
||||
|
||||
/* build the tag object */
|
||||
strbuf_reset(&new_data);
|
||||
|
||||
|
|
@ -3211,6 +3236,9 @@ static void parse_new_tag(const char *arg)
|
|||
if (tagger)
|
||||
strbuf_addf(&new_data,
|
||||
"tagger %s\n", tagger);
|
||||
|
||||
handle_tag_signature(&new_data, &msg, t->name);
|
||||
|
||||
strbuf_addch(&new_data, '\n');
|
||||
strbuf_addbuf(&new_data, &msg);
|
||||
free(tagger);
|
||||
|
|
|
|||
|
|
@ -77,4 +77,77 @@ test_expect_success GPGSSH 'import SSH signed tag with --signed-tags=strip' '
|
|||
test_grep ! "SSH SIGNATURE" out
|
||||
'
|
||||
|
||||
for mode in strip-if-invalid
|
||||
do
|
||||
test_expect_success GPG "import tag with no signature with --signed-tags=$mode" '
|
||||
test_when_finished rm -rf import &&
|
||||
git init import &&
|
||||
|
||||
git fast-export --signed-tags=verbatim >output &&
|
||||
git -C import fast-import --quiet --signed-tags=$mode <output >log 2>&1 &&
|
||||
test_must_be_empty log
|
||||
'
|
||||
|
||||
test_expect_success GPG "keep valid OpenPGP signature with --signed-tags=$mode" '
|
||||
test_when_finished rm -rf import &&
|
||||
git init import &&
|
||||
|
||||
git fast-export --signed-tags=verbatim openpgp-signed >output &&
|
||||
git -C import fast-import --quiet --signed-tags=$mode <output >log 2>&1 &&
|
||||
IMPORTED=$(git -C import rev-parse --verify refs/tags/openpgp-signed) &&
|
||||
test $OPENPGP_SIGNED = $IMPORTED &&
|
||||
git -C import cat-file tag "$IMPORTED" >actual &&
|
||||
test_grep -E "^-----BEGIN PGP SIGNATURE-----" actual &&
|
||||
test_must_be_empty log
|
||||
'
|
||||
|
||||
test_expect_success GPG "handle signature invalidated by message change with --signed-tags=$mode" '
|
||||
test_when_finished rm -rf import &&
|
||||
git init import &&
|
||||
|
||||
git fast-export --signed-tags=verbatim openpgp-signed >output &&
|
||||
|
||||
# Change the tag message, which invalidates the signature. The tag
|
||||
# message length should not change though, otherwise the corresponding
|
||||
# `data <length>` command would have to be changed too.
|
||||
sed "s/OpenPGP signed tag/OpenPGP forged tag/" output >modified &&
|
||||
|
||||
git -C import fast-import --quiet --signed-tags=$mode <modified >log 2>&1 &&
|
||||
|
||||
IMPORTED=$(git -C import rev-parse --verify refs/tags/openpgp-signed) &&
|
||||
test $OPENPGP_SIGNED != $IMPORTED &&
|
||||
git -C import cat-file tag "$IMPORTED" >actual &&
|
||||
test_grep ! -E "^-----BEGIN PGP SIGNATURE-----" actual &&
|
||||
test_must_be_empty log
|
||||
'
|
||||
|
||||
test_expect_success GPGSM "keep valid X.509 signature with --signed-tags=$mode" '
|
||||
test_when_finished rm -rf import &&
|
||||
git init import &&
|
||||
|
||||
git fast-export --signed-tags=verbatim x509-signed >output &&
|
||||
git -C import fast-import --quiet --signed-tags=$mode <output >log 2>&1 &&
|
||||
IMPORTED=$(git -C import rev-parse --verify refs/tags/x509-signed) &&
|
||||
test $X509_SIGNED = $IMPORTED &&
|
||||
git -C import cat-file tag x509-signed >actual &&
|
||||
test_grep -E "^-----BEGIN SIGNED MESSAGE-----" actual &&
|
||||
test_must_be_empty log
|
||||
'
|
||||
|
||||
test_expect_success GPGSSH "keep valid SSH signature with --signed-tags=$mode" '
|
||||
test_when_finished rm -rf import &&
|
||||
git init import &&
|
||||
|
||||
test_config -C import gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
|
||||
|
||||
git fast-export --signed-tags=verbatim ssh-signed >output &&
|
||||
git -C import fast-import --quiet --signed-tags=$mode <output >log 2>&1 &&
|
||||
IMPORTED=$(git -C import rev-parse --verify refs/tags/ssh-signed) &&
|
||||
test $SSH_SIGNED = $IMPORTED &&
|
||||
git -C import cat-file tag ssh-signed >actual &&
|
||||
test_grep -E "^-----BEGIN SSH SIGNATURE-----" actual &&
|
||||
test_must_be_empty log
|
||||
'
|
||||
done
|
||||
|
||||
test_done
|
||||
|
|
|
|||
Loading…
Reference in New Issue