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
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);
/* 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:
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>"));
/* tag payload/message */
parse_data(&msg, 0, NULL);
- handle_tag_signature(&msg, t->name);
-
/* build the tag object */
strbuf_reset(&new_data);
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);
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