+79
-22
index b8a7757cfd..935e688e33 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
static enum sign_mode signed_tag_mode = SIGN_VERBATIM;
static enum sign_mode signed_commit_mode = SIGN_VERBATIM;
+static const char *signed_commit_keyid;
/* Memory pools */
static struct mem_pool fi_mem_pool = {
strbuf_addbuf(new_data, msg);
}
-static void handle_strip_if_invalid(struct strbuf *new_data,
- struct signature_data *sig_sha1,
- struct signature_data *sig_sha256,
- struct strbuf *msg)
+static void warn_invalid_signature(struct signature_check *check,
+ const char *msg, enum sign_mode mode)
{
- struct strbuf tmp_buf = STRBUF_INIT;
- struct signature_check signature_check = { 0 };
- int ret;
-
- /* Check signature in a temporary commit buffer */
- strbuf_addbuf(&tmp_buf, new_data);
- finalize_commit_buffer(&tmp_buf, sig_sha1, sig_sha256, msg);
- ret = verify_commit_buffer(tmp_buf.buf, tmp_buf.len, &signature_check);
-
- if (ret) {
- const char *signer = signature_check.signer ?
- signature_check.signer : _("unknown");
- const char *subject;
- int subject_len = find_commit_subject(msg->buf, &subject);
+ const char *signer = check->signer ? check->signer : _("unknown");
+ const char *subject;
+ int subject_len = find_commit_subject(msg, &subject);
+ switch (mode) {
+ case SIGN_STRIP_IF_INVALID:
if (subject_len > 100)
warning(_("stripping invalid signature for commit '%.100s...'\n"
" allegedly by %s"), subject, signer);
else
warning(_("stripping invalid signature for commit\n"
" allegedly by %s"), signer);
+ break;
+ case SIGN_SIGN_IF_INVALID:
+ if (subject_len > 100)
+ warning(_("replacing invalid signature for commit '%.100s...'\n"
+ " allegedly by %s"), subject, signer);
+ else if (subject_len > 0)
+ warning(_("replacing invalid signature for commit '%.*s'\n"
+ " allegedly by %s"), subject_len, subject, signer);
+ else
+ warning(_("replacing invalid signature for commit\n"
+ " allegedly by %s"), signer);
+ break;
+ default:
+ BUG("unsupported signing mode");
+ }
+}
+
+static void handle_signature_if_invalid(struct strbuf *new_data,
+ struct signature_data *sig_sha1,
+ struct signature_data *sig_sha256,
+ struct strbuf *msg,
+ enum sign_mode mode)
+{
+ struct strbuf tmp_buf = STRBUF_INIT;
+ struct signature_check signature_check = { 0 };
+ int ret;
+
+ /* Check signature in a temporary commit buffer */
+ strbuf_addbuf(&tmp_buf, new_data);
+ finalize_commit_buffer(&tmp_buf, sig_sha1, sig_sha256, msg);
+ ret = verify_commit_buffer(tmp_buf.buf, tmp_buf.len, &signature_check);
+
+ if (ret) {
+ warn_invalid_signature(&signature_check, msg->buf, mode);
+
+ if (mode == SIGN_SIGN_IF_INVALID) {
+ struct strbuf signature = STRBUF_INIT;
+ struct strbuf payload = STRBUF_INIT;
+
+ /*
+ * NEEDSWORK: To properly support interoperability mode
+ * when signing commit signatures, the commit buffer
+ * must be provided in both the repository and
+ * compatibility object formats. As currently
+ * implemented, only the repository object format is
+ * considered meaning compatibility signatures cannot be
+ * generated. Thus, attempting to sign commit signatures
+ * in interoperability mode is currently unsupported.
+ */
+ if (the_repository->compat_hash_algo)
+ die(_("signing commits in interoperability mode is unsupported"));
+
+ strbuf_addstr(&payload, signature_check.payload);
+ if (sign_buffer(&payload, &signature, signed_commit_keyid,
+ SIGN_BUFFER_USE_DEFAULT_KEY))
+ die(_("failed to sign commit object"));
+ add_header_signature(new_data, &signature, the_hash_algo);
+
+ strbuf_release(&signature);
+ strbuf_release(&payload);
+ }
finalize_commit_buffer(new_data, NULL, NULL, msg);
} else {
/* fallthru */
case SIGN_VERBATIM:
case SIGN_STRIP_IF_INVALID:
+ case SIGN_SIGN_IF_INVALID:
import_one_signature(&sig_sha1, &sig_sha256, v);
break;
"encoding %s\n",
encoding);
- if (signed_commit_mode == SIGN_STRIP_IF_INVALID &&
+ if ((signed_commit_mode == SIGN_STRIP_IF_INVALID ||
+ signed_commit_mode == SIGN_SIGN_IF_INVALID) &&
(sig_sha1.hash_algo || sig_sha256.hash_algo))
- handle_strip_if_invalid(&new_data, &sig_sha1, &sig_sha256, &msg);
+ handle_signature_if_invalid(&new_data, &sig_sha1, &sig_sha256,
+ &msg, signed_commit_mode);
else
finalize_commit_buffer(&new_data, &sig_sha1, &sig_sha256, &msg);
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>"));
default:
BUG("invalid signed_tag_mode value %d from tag '%s'",
signed_tag_mode, name);
} else if (skip_prefix(option, "export-pack-edges=", &option)) {
option_export_pack_edges(option);
} else if (skip_prefix(option, "signed-commits=", &option)) {
- if (parse_sign_mode(option, &signed_commit_mode))
+ if (parse_sign_mode(option, &signed_commit_mode, &signed_commit_keyid))
usagef(_("unknown --signed-commits mode '%s'"), option);
} else if (skip_prefix(option, "signed-tags=", &option)) {
- if (parse_sign_mode(option, &signed_tag_mode))
+ if (parse_sign_mode(option, &signed_tag_mode, NULL))
usagef(_("unknown --signed-tags mode '%s'"), option);
} else if (!strcmp(option, "quiet")) {
show_stats = 0;
+15
-8
index 27eacbb632..d517425034 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
return ret;
}
-int parse_sign_mode(const char *arg, enum sign_mode *mode)
+int parse_sign_mode(const char *arg, enum sign_mode *mode, const char **keyid)
{
- if (!strcmp(arg, "abort"))
+ if (!strcmp(arg, "abort")) {
*mode = SIGN_ABORT;
- else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore"))
+ } else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore")) {
*mode = SIGN_VERBATIM;
- else if (!strcmp(arg, "warn-verbatim") || !strcmp(arg, "warn"))
+ } else if (!strcmp(arg, "warn-verbatim") || !strcmp(arg, "warn")) {
*mode = SIGN_WARN_VERBATIM;
- else if (!strcmp(arg, "warn-strip"))
+ } else if (!strcmp(arg, "warn-strip")) {
*mode = SIGN_WARN_STRIP;
- else if (!strcmp(arg, "strip"))
+ } else if (!strcmp(arg, "strip")) {
*mode = SIGN_STRIP;
- else if (!strcmp(arg, "strip-if-invalid"))
+ } else if (!strcmp(arg, "strip-if-invalid")) {
*mode = SIGN_STRIP_IF_INVALID;
- else
+ } else if (!strcmp(arg, "sign-if-invalid")) {
+ *mode = SIGN_SIGN_IF_INVALID;
+ } else if (skip_prefix(arg, "sign-if-invalid=", &arg)) {
+ *mode = SIGN_SIGN_IF_INVALID;
+ if (keyid)
+ *keyid = arg;
+ } else {
return -1;
+ }
return 0;
}