190
191
static enum sign_mode signed_tag_mode = SIGN_VERBATIM;
192
static enum sign_mode signed_commit_mode = SIGN_VERBATIM;
193
+static const char *signed_commit_keyid;
194
195
/* Memory pools */
196
static struct mem_pool fi_mem_pool = {
2837
strbuf_addbuf(new_data, msg);
2838
}
2839
2839
-static void handle_strip_if_invalid(struct strbuf *new_data,
2840
- struct signature_data *sig_sha1,
2841
- struct signature_data *sig_sha256,
2842
- struct strbuf *msg)
2840
+static void warn_invalid_signature(struct signature_check *check,
2841
+ const char *msg, enum sign_mode mode)
2842
{
2844
- struct strbuf tmp_buf = STRBUF_INIT;
2845
- struct signature_check signature_check = { 0 };
2846
- int ret;
2847
-
2848
- /* Check signature in a temporary commit buffer */
2849
- strbuf_addbuf(&tmp_buf, new_data);
2850
- finalize_commit_buffer(&tmp_buf, sig_sha1, sig_sha256, msg);
2851
- ret = verify_commit_buffer(tmp_buf.buf, tmp_buf.len, &signature_check);
2852
-
2853
- if (ret) {
2854
- const char *signer = signature_check.signer ?
2855
- signature_check.signer : _("unknown");
2856
- const char *subject;
2857
- int subject_len = find_commit_subject(msg->buf, &subject);
2843
+ const char *signer = check->signer ? check->signer : _("unknown");
2844
+ const char *subject;
2845
+ int subject_len = find_commit_subject(msg, &subject);
2846
2847
+ switch (mode) {
2848
+ case SIGN_STRIP_IF_INVALID:
2849
if (subject_len > 100)
2850
warning(_("stripping invalid signature for commit '%.100s...'\n"
2851
" allegedly by %s"), subject, signer);
2855
else
2856
warning(_("stripping invalid signature for commit\n"
2857
" allegedly by %s"), signer);
2858
+ break;
2859
+ case SIGN_SIGN_IF_INVALID:
2860
+ if (subject_len > 100)
2861
+ warning(_("replacing invalid signature for commit '%.100s...'\n"
2862
+ " allegedly by %s"), subject, signer);
2863
+ else if (subject_len > 0)
2864
+ warning(_("replacing invalid signature for commit '%.*s'\n"
2865
+ " allegedly by %s"), subject_len, subject, signer);
2866
+ else
2867
+ warning(_("replacing invalid signature for commit\n"
2868
+ " allegedly by %s"), signer);
2869
+ break;
2870
+ default:
2871
+ BUG("unsupported signing mode");
2872
+ }
2873
+}
2874
+
2875
+static void handle_signature_if_invalid(struct strbuf *new_data,
2876
+ struct signature_data *sig_sha1,
2877
+ struct signature_data *sig_sha256,
2878
+ struct strbuf *msg,
2879
+ enum sign_mode mode)
2880
+{
2881
+ struct strbuf tmp_buf = STRBUF_INIT;
2882
+ struct signature_check signature_check = { 0 };
2883
+ int ret;
2884
+
2885
+ /* Check signature in a temporary commit buffer */
2886
+ strbuf_addbuf(&tmp_buf, new_data);
2887
+ finalize_commit_buffer(&tmp_buf, sig_sha1, sig_sha256, msg);
2888
+ ret = verify_commit_buffer(tmp_buf.buf, tmp_buf.len, &signature_check);
2889
+
2890
+ if (ret) {
2891
+ warn_invalid_signature(&signature_check, msg->buf, mode);
2892
+
2893
+ if (mode == SIGN_SIGN_IF_INVALID) {
2894
+ struct strbuf signature = STRBUF_INIT;
2895
+ struct strbuf payload = STRBUF_INIT;
2896
+
2897
+ /*
2898
+ * NEEDSWORK: To properly support interoperability mode
2899
+ * when signing commit signatures, the commit buffer
2900
+ * must be provided in both the repository and
2901
+ * compatibility object formats. As currently
2902
+ * implemented, only the repository object format is
2903
+ * considered meaning compatibility signatures cannot be
2904
+ * generated. Thus, attempting to sign commit signatures
2905
+ * in interoperability mode is currently unsupported.
2906
+ */
2907
+ if (the_repository->compat_hash_algo)
2908
+ die(_("signing commits in interoperability mode is unsupported"));
2909
+
2910
+ strbuf_addstr(&payload, signature_check.payload);
2911
+ if (sign_buffer(&payload, &signature, signed_commit_keyid,
2912
+ SIGN_BUFFER_USE_DEFAULT_KEY))
2913
+ die(_("failed to sign commit object"));
2914
+ add_header_signature(new_data, &signature, the_hash_algo);
2915
+
2916
+ strbuf_release(&signature);
2917
+ strbuf_release(&payload);
2918
+ }
2919
2920
finalize_commit_buffer(new_data, NULL, NULL, msg);
2921
} else {
2978
/* fallthru */
2979
case SIGN_VERBATIM:
2980
case SIGN_STRIP_IF_INVALID:
2981
+ case SIGN_SIGN_IF_INVALID:
2982
import_one_signature(&sig_sha1, &sig_sha256, v);
2983
break;
2984
3063
"encoding %s\n",
3064
encoding);
3065
3014
- if (signed_commit_mode == SIGN_STRIP_IF_INVALID &&
3066
+ if ((signed_commit_mode == SIGN_STRIP_IF_INVALID ||
3067
+ signed_commit_mode == SIGN_SIGN_IF_INVALID) &&
3068
(sig_sha1.hash_algo || sig_sha256.hash_algo))
3016
- handle_strip_if_invalid(&new_data, &sig_sha1, &sig_sha256, &msg);
3069
+ handle_signature_if_invalid(&new_data, &sig_sha1, &sig_sha256,
3070
+ &msg, signed_commit_mode);
3071
else
3072
finalize_commit_buffer(&new_data, &sig_sha1, &sig_sha256, &msg);
3073
3114
case SIGN_STRIP_IF_INVALID:
3115
die(_("'strip-if-invalid' is not a valid mode for "
3116
"git fast-import with --signed-tags=<mode>"));
3117
+ case SIGN_SIGN_IF_INVALID:
3118
+ die(_("'sign-if-invalid' is not a valid mode for "
3119
+ "git fast-import with --signed-tags=<mode>"));
3120
default:
3121
BUG("invalid signed_tag_mode value %d from tag '%s'",
3122
signed_tag_mode, name);
3706
} else if (skip_prefix(option, "export-pack-edges=", &option)) {
3707
option_export_pack_edges(option);
3708
} else if (skip_prefix(option, "signed-commits=", &option)) {
3652
- if (parse_sign_mode(option, &signed_commit_mode))
3709
+ if (parse_sign_mode(option, &signed_commit_mode, &signed_commit_keyid))
3710
usagef(_("unknown --signed-commits mode '%s'"), option);
3711
} else if (skip_prefix(option, "signed-tags=", &option)) {
3655
- if (parse_sign_mode(option, &signed_tag_mode))
3712
+ if (parse_sign_mode(option, &signed_tag_mode, NULL))
3713
usagef(_("unknown --signed-tags mode '%s'"), option);
3714
} else if (!strcmp(option, "quiet")) {
3715
show_stats = 0;