replace-object.h: move read_replace_refs declaration from cache.h to here
[git.git] / gpg-interface.c
blobbd13fc92fef21df9606e01248957826fccf81423
1 #include "cache.h"
2 #include "commit.h"
3 #include "config.h"
4 #include "run-command.h"
5 #include "strbuf.h"
6 #include "dir.h"
7 #include "ident.h"
8 #include "gpg-interface.h"
9 #include "sigchain.h"
10 #include "tempfile.h"
11 #include "alias.h"
13 static char *configured_signing_key;
14 static const char *ssh_default_key_command, *ssh_allowed_signers, *ssh_revocation_file;
15 static enum signature_trust_level configured_min_trust_level = TRUST_UNDEFINED;
17 struct gpg_format {
18 const char *name;
19 const char *program;
20 const char **verify_args;
21 const char **sigs;
22 int (*verify_signed_buffer)(struct signature_check *sigc,
23 struct gpg_format *fmt,
24 const char *signature,
25 size_t signature_size);
26 int (*sign_buffer)(struct strbuf *buffer, struct strbuf *signature,
27 const char *signing_key);
28 const char *(*get_default_key)(void);
29 const char *(*get_key_id)(void);
32 static const char *openpgp_verify_args[] = {
33 "--keyid-format=long",
34 NULL
36 static const char *openpgp_sigs[] = {
37 "-----BEGIN PGP SIGNATURE-----",
38 "-----BEGIN PGP MESSAGE-----",
39 NULL
42 static const char *x509_verify_args[] = {
43 NULL
45 static const char *x509_sigs[] = {
46 "-----BEGIN SIGNED MESSAGE-----",
47 NULL
50 static const char *ssh_verify_args[] = { NULL };
51 static const char *ssh_sigs[] = {
52 "-----BEGIN SSH SIGNATURE-----",
53 NULL
56 static int verify_gpg_signed_buffer(struct signature_check *sigc,
57 struct gpg_format *fmt,
58 const char *signature,
59 size_t signature_size);
60 static int verify_ssh_signed_buffer(struct signature_check *sigc,
61 struct gpg_format *fmt,
62 const char *signature,
63 size_t signature_size);
64 static int sign_buffer_gpg(struct strbuf *buffer, struct strbuf *signature,
65 const char *signing_key);
66 static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
67 const char *signing_key);
69 static const char *get_default_ssh_signing_key(void);
71 static const char *get_ssh_key_id(void);
73 static struct gpg_format gpg_format[] = {
75 .name = "openpgp",
76 .program = "gpg",
77 .verify_args = openpgp_verify_args,
78 .sigs = openpgp_sigs,
79 .verify_signed_buffer = verify_gpg_signed_buffer,
80 .sign_buffer = sign_buffer_gpg,
81 .get_default_key = NULL,
82 .get_key_id = NULL,
85 .name = "x509",
86 .program = "gpgsm",
87 .verify_args = x509_verify_args,
88 .sigs = x509_sigs,
89 .verify_signed_buffer = verify_gpg_signed_buffer,
90 .sign_buffer = sign_buffer_gpg,
91 .get_default_key = NULL,
92 .get_key_id = NULL,
95 .name = "ssh",
96 .program = "ssh-keygen",
97 .verify_args = ssh_verify_args,
98 .sigs = ssh_sigs,
99 .verify_signed_buffer = verify_ssh_signed_buffer,
100 .sign_buffer = sign_buffer_ssh,
101 .get_default_key = get_default_ssh_signing_key,
102 .get_key_id = get_ssh_key_id,
106 static struct gpg_format *use_format = &gpg_format[0];
108 static struct gpg_format *get_format_by_name(const char *str)
110 int i;
112 for (i = 0; i < ARRAY_SIZE(gpg_format); i++)
113 if (!strcmp(gpg_format[i].name, str))
114 return gpg_format + i;
115 return NULL;
118 static struct gpg_format *get_format_by_sig(const char *sig)
120 int i, j;
122 for (i = 0; i < ARRAY_SIZE(gpg_format); i++)
123 for (j = 0; gpg_format[i].sigs[j]; j++)
124 if (starts_with(sig, gpg_format[i].sigs[j]))
125 return gpg_format + i;
126 return NULL;
129 void signature_check_clear(struct signature_check *sigc)
131 FREE_AND_NULL(sigc->payload);
132 FREE_AND_NULL(sigc->output);
133 FREE_AND_NULL(sigc->gpg_status);
134 FREE_AND_NULL(sigc->signer);
135 FREE_AND_NULL(sigc->key);
136 FREE_AND_NULL(sigc->fingerprint);
137 FREE_AND_NULL(sigc->primary_key_fingerprint);
140 /* An exclusive status -- only one of them can appear in output */
141 #define GPG_STATUS_EXCLUSIVE (1<<0)
142 /* The status includes key identifier */
143 #define GPG_STATUS_KEYID (1<<1)
144 /* The status includes user identifier */
145 #define GPG_STATUS_UID (1<<2)
146 /* The status includes key fingerprints */
147 #define GPG_STATUS_FINGERPRINT (1<<3)
148 /* The status includes trust level */
149 #define GPG_STATUS_TRUST_LEVEL (1<<4)
151 /* Short-hand for standard exclusive *SIG status with keyid & UID */
152 #define GPG_STATUS_STDSIG (GPG_STATUS_EXCLUSIVE|GPG_STATUS_KEYID|GPG_STATUS_UID)
154 static struct {
155 char result;
156 const char *check;
157 unsigned int flags;
158 } sigcheck_gpg_status[] = {
159 { 'G', "GOODSIG ", GPG_STATUS_STDSIG },
160 { 'B', "BADSIG ", GPG_STATUS_STDSIG },
161 { 'E', "ERRSIG ", GPG_STATUS_EXCLUSIVE|GPG_STATUS_KEYID },
162 { 'X', "EXPSIG ", GPG_STATUS_STDSIG },
163 { 'Y', "EXPKEYSIG ", GPG_STATUS_STDSIG },
164 { 'R', "REVKEYSIG ", GPG_STATUS_STDSIG },
165 { 0, "VALIDSIG ", GPG_STATUS_FINGERPRINT },
166 { 0, "TRUST_", GPG_STATUS_TRUST_LEVEL },
169 /* Keep the order same as enum signature_trust_level */
170 static struct sigcheck_gpg_trust_level {
171 const char *key;
172 const char *display_key;
173 enum signature_trust_level value;
174 } sigcheck_gpg_trust_level[] = {
175 { "UNDEFINED", "undefined", TRUST_UNDEFINED },
176 { "NEVER", "never", TRUST_NEVER },
177 { "MARGINAL", "marginal", TRUST_MARGINAL },
178 { "FULLY", "fully", TRUST_FULLY },
179 { "ULTIMATE", "ultimate", TRUST_ULTIMATE },
182 static void replace_cstring(char **field, const char *line, const char *next)
184 free(*field);
186 if (line && next)
187 *field = xmemdupz(line, next - line);
188 else
189 *field = NULL;
192 static int parse_gpg_trust_level(const char *level,
193 enum signature_trust_level *res)
195 size_t i;
197 for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_trust_level); i++) {
198 if (!strcmp(sigcheck_gpg_trust_level[i].key, level)) {
199 *res = sigcheck_gpg_trust_level[i].value;
200 return 0;
203 return 1;
206 static void parse_gpg_output(struct signature_check *sigc)
208 const char *buf = sigc->gpg_status;
209 const char *line, *next;
210 int i, j;
211 int seen_exclusive_status = 0;
213 /* Iterate over all lines */
214 for (line = buf; *line; line = strchrnul(line+1, '\n')) {
215 while (*line == '\n')
216 line++;
217 if (!*line)
218 break;
220 /* Skip lines that don't start with GNUPG status */
221 if (!skip_prefix(line, "[GNUPG:] ", &line))
222 continue;
224 /* Iterate over all search strings */
225 for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) {
226 if (skip_prefix(line, sigcheck_gpg_status[i].check, &line)) {
228 * GOODSIG, BADSIG etc. can occur only once for
229 * each signature. Therefore, if we had more
230 * than one then we're dealing with multiple
231 * signatures. We don't support them
232 * currently, and they're rather hard to
233 * create, so something is likely fishy and we
234 * should reject them altogether.
236 if (sigcheck_gpg_status[i].flags & GPG_STATUS_EXCLUSIVE) {
237 if (seen_exclusive_status++)
238 goto error;
241 if (sigcheck_gpg_status[i].result)
242 sigc->result = sigcheck_gpg_status[i].result;
243 /* Do we have key information? */
244 if (sigcheck_gpg_status[i].flags & GPG_STATUS_KEYID) {
245 next = strchrnul(line, ' ');
246 replace_cstring(&sigc->key, line, next);
247 /* Do we have signer information? */
248 if (*next && (sigcheck_gpg_status[i].flags & GPG_STATUS_UID)) {
249 line = next + 1;
250 next = strchrnul(line, '\n');
251 replace_cstring(&sigc->signer, line, next);
255 /* Do we have trust level? */
256 if (sigcheck_gpg_status[i].flags & GPG_STATUS_TRUST_LEVEL) {
258 * GPG v1 and v2 differs in how the
259 * TRUST_ lines are written. Some
260 * trust lines contain no additional
261 * space-separated information for v1.
263 size_t trust_size = strcspn(line, " \n");
264 char *trust = xmemdupz(line, trust_size);
266 if (parse_gpg_trust_level(trust, &sigc->trust_level)) {
267 free(trust);
268 goto error;
270 free(trust);
273 /* Do we have fingerprint? */
274 if (sigcheck_gpg_status[i].flags & GPG_STATUS_FINGERPRINT) {
275 const char *limit;
276 char **field;
278 next = strchrnul(line, ' ');
279 replace_cstring(&sigc->fingerprint, line, next);
282 * Skip interim fields. The search is
283 * limited to the same line since only
284 * OpenPGP signatures has a field with
285 * the primary fingerprint.
287 limit = strchrnul(line, '\n');
288 for (j = 9; j > 0; j--) {
289 if (!*next || limit <= next)
290 break;
291 line = next + 1;
292 next = strchrnul(line, ' ');
295 field = &sigc->primary_key_fingerprint;
296 if (!j) {
297 next = strchrnul(line, '\n');
298 replace_cstring(field, line, next);
299 } else {
300 replace_cstring(field, NULL, NULL);
304 break;
308 return;
310 error:
311 sigc->result = 'E';
312 /* Clear partial data to avoid confusion */
313 FREE_AND_NULL(sigc->primary_key_fingerprint);
314 FREE_AND_NULL(sigc->fingerprint);
315 FREE_AND_NULL(sigc->signer);
316 FREE_AND_NULL(sigc->key);
319 static int verify_gpg_signed_buffer(struct signature_check *sigc,
320 struct gpg_format *fmt,
321 const char *signature,
322 size_t signature_size)
324 struct child_process gpg = CHILD_PROCESS_INIT;
325 struct tempfile *temp;
326 int ret;
327 struct strbuf gpg_stdout = STRBUF_INIT;
328 struct strbuf gpg_stderr = STRBUF_INIT;
330 temp = mks_tempfile_t(".git_vtag_tmpXXXXXX");
331 if (!temp)
332 return error_errno(_("could not create temporary file"));
333 if (write_in_full(temp->fd, signature, signature_size) < 0 ||
334 close_tempfile_gently(temp) < 0) {
335 error_errno(_("failed writing detached signature to '%s'"),
336 temp->filename.buf);
337 delete_tempfile(&temp);
338 return -1;
341 strvec_push(&gpg.args, fmt->program);
342 strvec_pushv(&gpg.args, fmt->verify_args);
343 strvec_pushl(&gpg.args,
344 "--status-fd=1",
345 "--verify", temp->filename.buf, "-",
346 NULL);
348 sigchain_push(SIGPIPE, SIG_IGN);
349 ret = pipe_command(&gpg, sigc->payload, sigc->payload_len, &gpg_stdout, 0,
350 &gpg_stderr, 0);
351 sigchain_pop(SIGPIPE);
353 delete_tempfile(&temp);
355 ret |= !strstr(gpg_stdout.buf, "\n[GNUPG:] GOODSIG ");
356 sigc->output = strbuf_detach(&gpg_stderr, NULL);
357 sigc->gpg_status = strbuf_detach(&gpg_stdout, NULL);
359 parse_gpg_output(sigc);
361 strbuf_release(&gpg_stdout);
362 strbuf_release(&gpg_stderr);
364 return ret;
367 static void parse_ssh_output(struct signature_check *sigc)
369 const char *line, *principal, *search;
370 char *to_free;
371 char *key = NULL;
374 * ssh-keygen output should be:
375 * Good "git" signature for PRINCIPAL with RSA key SHA256:FINGERPRINT
377 * or for valid but unknown keys:
378 * Good "git" signature with RSA key SHA256:FINGERPRINT
380 * Note that "PRINCIPAL" can contain whitespace, "RSA" and
381 * "SHA256" part could be a different token that names of
382 * the algorithms used, and "FINGERPRINT" is a hexadecimal
383 * string. By finding the last occurence of " with ", we can
384 * reliably parse out the PRINCIPAL.
386 sigc->result = 'B';
387 sigc->trust_level = TRUST_NEVER;
389 line = to_free = xmemdupz(sigc->output, strcspn(sigc->output, "\n"));
391 if (skip_prefix(line, "Good \"git\" signature for ", &line)) {
392 /* Search for the last "with" to get the full principal */
393 principal = line;
394 do {
395 search = strstr(line, " with ");
396 if (search)
397 line = search + 1;
398 } while (search != NULL);
399 if (line == principal)
400 goto cleanup;
402 /* Valid signature and known principal */
403 sigc->result = 'G';
404 sigc->trust_level = TRUST_FULLY;
405 sigc->signer = xmemdupz(principal, line - principal - 1);
406 } else if (skip_prefix(line, "Good \"git\" signature with ", &line)) {
407 /* Valid signature, but key unknown */
408 sigc->result = 'G';
409 sigc->trust_level = TRUST_UNDEFINED;
410 } else {
411 goto cleanup;
414 key = strstr(line, "key ");
415 if (key) {
416 sigc->fingerprint = xstrdup(strstr(line, "key ") + 4);
417 sigc->key = xstrdup(sigc->fingerprint);
418 } else {
420 * Output did not match what we expected
421 * Treat the signature as bad
423 sigc->result = 'B';
426 cleanup:
427 free(to_free);
430 static int verify_ssh_signed_buffer(struct signature_check *sigc,
431 struct gpg_format *fmt,
432 const char *signature,
433 size_t signature_size)
435 struct child_process ssh_keygen = CHILD_PROCESS_INIT;
436 struct tempfile *buffer_file;
437 int ret = -1;
438 const char *line;
439 char *principal;
440 struct strbuf ssh_principals_out = STRBUF_INIT;
441 struct strbuf ssh_principals_err = STRBUF_INIT;
442 struct strbuf ssh_keygen_out = STRBUF_INIT;
443 struct strbuf ssh_keygen_err = STRBUF_INIT;
444 struct strbuf verify_time = STRBUF_INIT;
445 const struct date_mode verify_date_mode = {
446 .type = DATE_STRFTIME,
447 .strftime_fmt = "%Y%m%d%H%M%S",
448 /* SSH signing key validity has no timezone information - Use the local timezone */
449 .local = 1,
452 if (!ssh_allowed_signers) {
453 error(_("gpg.ssh.allowedSignersFile needs to be configured and exist for ssh signature verification"));
454 return -1;
457 buffer_file = mks_tempfile_t(".git_vtag_tmpXXXXXX");
458 if (!buffer_file)
459 return error_errno(_("could not create temporary file"));
460 if (write_in_full(buffer_file->fd, signature, signature_size) < 0 ||
461 close_tempfile_gently(buffer_file) < 0) {
462 error_errno(_("failed writing detached signature to '%s'"),
463 buffer_file->filename.buf);
464 delete_tempfile(&buffer_file);
465 return -1;
468 if (sigc->payload_timestamp)
469 strbuf_addf(&verify_time, "-Overify-time=%s",
470 show_date(sigc->payload_timestamp, 0, &verify_date_mode));
472 /* Find the principal from the signers */
473 strvec_pushl(&ssh_keygen.args, fmt->program,
474 "-Y", "find-principals",
475 "-f", ssh_allowed_signers,
476 "-s", buffer_file->filename.buf,
477 verify_time.buf,
478 NULL);
479 ret = pipe_command(&ssh_keygen, NULL, 0, &ssh_principals_out, 0,
480 &ssh_principals_err, 0);
481 if (ret && strstr(ssh_principals_err.buf, "usage:")) {
482 error(_("ssh-keygen -Y find-principals/verify is needed for ssh signature verification (available in openssh version 8.2p1+)"));
483 goto out;
485 if (ret || !ssh_principals_out.len) {
487 * We did not find a matching principal in the allowedSigners
488 * Check without validation
490 child_process_init(&ssh_keygen);
491 strvec_pushl(&ssh_keygen.args, fmt->program,
492 "-Y", "check-novalidate",
493 "-n", "git",
494 "-s", buffer_file->filename.buf,
495 verify_time.buf,
496 NULL);
497 pipe_command(&ssh_keygen, sigc->payload, sigc->payload_len,
498 &ssh_keygen_out, 0, &ssh_keygen_err, 0);
501 * Fail on unknown keys
502 * we still call check-novalidate to display the signature info
504 ret = -1;
505 } else {
506 /* Check every principal we found (one per line) */
507 const char *next;
508 for (line = ssh_principals_out.buf;
509 *line;
510 line = next) {
511 const char *end_of_text;
513 next = end_of_text = strchrnul(line, '\n');
515 /* Did we find a LF, and did we have CR before it? */
516 if (*end_of_text &&
517 line < end_of_text &&
518 end_of_text[-1] == '\r')
519 end_of_text--;
521 /* Unless we hit NUL, skip over the LF we found */
522 if (*next)
523 next++;
525 /* Not all lines are data. Skip empty ones */
526 if (line == end_of_text)
527 continue;
529 /* We now know we have an non-empty line. Process it */
530 principal = xmemdupz(line, end_of_text - line);
532 child_process_init(&ssh_keygen);
533 strbuf_release(&ssh_keygen_out);
534 strbuf_release(&ssh_keygen_err);
535 strvec_push(&ssh_keygen.args, fmt->program);
537 * We found principals
538 * Try with each until we find a match
540 strvec_pushl(&ssh_keygen.args, "-Y", "verify",
541 "-n", "git",
542 "-f", ssh_allowed_signers,
543 "-I", principal,
544 "-s", buffer_file->filename.buf,
545 verify_time.buf,
546 NULL);
548 if (ssh_revocation_file) {
549 if (file_exists(ssh_revocation_file)) {
550 strvec_pushl(&ssh_keygen.args, "-r",
551 ssh_revocation_file, NULL);
552 } else {
553 warning(_("ssh signing revocation file configured but not found: %s"),
554 ssh_revocation_file);
558 sigchain_push(SIGPIPE, SIG_IGN);
559 ret = pipe_command(&ssh_keygen, sigc->payload, sigc->payload_len,
560 &ssh_keygen_out, 0, &ssh_keygen_err, 0);
561 sigchain_pop(SIGPIPE);
563 FREE_AND_NULL(principal);
565 if (!ret)
566 ret = !starts_with(ssh_keygen_out.buf, "Good");
568 if (!ret)
569 break;
573 strbuf_stripspace(&ssh_keygen_out, 0);
574 strbuf_stripspace(&ssh_keygen_err, 0);
575 /* Add stderr outputs to show the user actual ssh-keygen errors */
576 strbuf_add(&ssh_keygen_out, ssh_principals_err.buf, ssh_principals_err.len);
577 strbuf_add(&ssh_keygen_out, ssh_keygen_err.buf, ssh_keygen_err.len);
578 sigc->output = strbuf_detach(&ssh_keygen_out, NULL);
579 sigc->gpg_status = xstrdup(sigc->output);
581 parse_ssh_output(sigc);
583 out:
584 if (buffer_file)
585 delete_tempfile(&buffer_file);
586 strbuf_release(&ssh_principals_out);
587 strbuf_release(&ssh_principals_err);
588 strbuf_release(&ssh_keygen_out);
589 strbuf_release(&ssh_keygen_err);
590 strbuf_release(&verify_time);
592 return ret;
595 static int parse_payload_metadata(struct signature_check *sigc)
597 const char *ident_line = NULL;
598 size_t ident_len;
599 struct ident_split ident;
600 const char *signer_header;
602 switch (sigc->payload_type) {
603 case SIGNATURE_PAYLOAD_COMMIT:
604 signer_header = "committer";
605 break;
606 case SIGNATURE_PAYLOAD_TAG:
607 signer_header = "tagger";
608 break;
609 case SIGNATURE_PAYLOAD_UNDEFINED:
610 case SIGNATURE_PAYLOAD_PUSH_CERT:
611 /* Ignore payloads we don't want to parse */
612 return 0;
613 default:
614 BUG("invalid value for sigc->payload_type");
617 ident_line = find_commit_header(sigc->payload, signer_header, &ident_len);
618 if (!ident_line || !ident_len)
619 return 1;
621 if (split_ident_line(&ident, ident_line, ident_len))
622 return 1;
624 if (!sigc->payload_timestamp && ident.date_begin && ident.date_end)
625 sigc->payload_timestamp = parse_timestamp(ident.date_begin, NULL, 10);
627 return 0;
630 int check_signature(struct signature_check *sigc,
631 const char *signature, size_t slen)
633 struct gpg_format *fmt;
634 int status;
636 sigc->result = 'N';
637 sigc->trust_level = -1;
639 fmt = get_format_by_sig(signature);
640 if (!fmt)
641 die(_("bad/incompatible signature '%s'"), signature);
643 if (parse_payload_metadata(sigc))
644 return 1;
646 status = fmt->verify_signed_buffer(sigc, fmt, signature, slen);
648 if (status && !sigc->output)
649 return !!status;
651 status |= sigc->result != 'G';
652 status |= sigc->trust_level < configured_min_trust_level;
654 return !!status;
657 void print_signature_buffer(const struct signature_check *sigc, unsigned flags)
659 const char *output = flags & GPG_VERIFY_RAW ? sigc->gpg_status :
660 sigc->output;
662 if (flags & GPG_VERIFY_VERBOSE && sigc->payload)
663 fwrite(sigc->payload, 1, sigc->payload_len, stdout);
665 if (output)
666 fputs(output, stderr);
669 size_t parse_signed_buffer(const char *buf, size_t size)
671 size_t len = 0;
672 size_t match = size;
673 while (len < size) {
674 const char *eol;
676 if (get_format_by_sig(buf + len))
677 match = len;
679 eol = memchr(buf + len, '\n', size - len);
680 len += eol ? eol - (buf + len) + 1 : size - len;
682 return match;
685 int parse_signature(const char *buf, size_t size, struct strbuf *payload, struct strbuf *signature)
687 size_t match = parse_signed_buffer(buf, size);
688 if (match != size) {
689 strbuf_add(payload, buf, match);
690 remove_signature(payload);
691 strbuf_add(signature, buf + match, size - match);
692 return 1;
694 return 0;
697 void set_signing_key(const char *key)
699 free(configured_signing_key);
700 configured_signing_key = xstrdup(key);
703 int git_gpg_config(const char *var, const char *value, void *cb UNUSED)
705 struct gpg_format *fmt = NULL;
706 char *fmtname = NULL;
707 char *trust;
708 int ret;
710 if (!strcmp(var, "user.signingkey")) {
711 if (!value)
712 return config_error_nonbool(var);
713 set_signing_key(value);
714 return 0;
717 if (!strcmp(var, "gpg.format")) {
718 if (!value)
719 return config_error_nonbool(var);
720 fmt = get_format_by_name(value);
721 if (!fmt)
722 return error(_("invalid value for '%s': '%s'"),
723 var, value);
724 use_format = fmt;
725 return 0;
728 if (!strcmp(var, "gpg.mintrustlevel")) {
729 if (!value)
730 return config_error_nonbool(var);
732 trust = xstrdup_toupper(value);
733 ret = parse_gpg_trust_level(trust, &configured_min_trust_level);
734 free(trust);
736 if (ret)
737 return error(_("invalid value for '%s': '%s'"),
738 var, value);
739 return 0;
742 if (!strcmp(var, "gpg.ssh.defaultkeycommand")) {
743 if (!value)
744 return config_error_nonbool(var);
745 return git_config_string(&ssh_default_key_command, var, value);
748 if (!strcmp(var, "gpg.ssh.allowedsignersfile")) {
749 if (!value)
750 return config_error_nonbool(var);
751 return git_config_pathname(&ssh_allowed_signers, var, value);
754 if (!strcmp(var, "gpg.ssh.revocationfile")) {
755 if (!value)
756 return config_error_nonbool(var);
757 return git_config_pathname(&ssh_revocation_file, var, value);
760 if (!strcmp(var, "gpg.program") || !strcmp(var, "gpg.openpgp.program"))
761 fmtname = "openpgp";
763 if (!strcmp(var, "gpg.x509.program"))
764 fmtname = "x509";
766 if (!strcmp(var, "gpg.ssh.program"))
767 fmtname = "ssh";
769 if (fmtname) {
770 fmt = get_format_by_name(fmtname);
771 return git_config_string(&fmt->program, var, value);
774 return 0;
778 * Returns 1 if `string` contains a literal ssh key, 0 otherwise
779 * `key` will be set to the start of the actual key if a prefix is present.
781 static int is_literal_ssh_key(const char *string, const char **key)
783 if (skip_prefix(string, "key::", key))
784 return 1;
785 if (starts_with(string, "ssh-")) {
786 *key = string;
787 return 1;
789 return 0;
792 static char *get_ssh_key_fingerprint(const char *signing_key)
794 struct child_process ssh_keygen = CHILD_PROCESS_INIT;
795 int ret = -1;
796 struct strbuf fingerprint_stdout = STRBUF_INIT;
797 struct strbuf **fingerprint;
798 char *fingerprint_ret;
799 const char *literal_key = NULL;
802 * With SSH Signing this can contain a filename or a public key
803 * For textual representation we usually want a fingerprint
805 if (is_literal_ssh_key(signing_key, &literal_key)) {
806 strvec_pushl(&ssh_keygen.args, "ssh-keygen", "-lf", "-", NULL);
807 ret = pipe_command(&ssh_keygen, literal_key,
808 strlen(literal_key), &fingerprint_stdout, 0,
809 NULL, 0);
810 } else {
811 strvec_pushl(&ssh_keygen.args, "ssh-keygen", "-lf",
812 configured_signing_key, NULL);
813 ret = pipe_command(&ssh_keygen, NULL, 0, &fingerprint_stdout, 0,
814 NULL, 0);
817 if (!!ret)
818 die_errno(_("failed to get the ssh fingerprint for key '%s'"),
819 signing_key);
821 fingerprint = strbuf_split_max(&fingerprint_stdout, ' ', 3);
822 if (!fingerprint[1])
823 die_errno(_("failed to get the ssh fingerprint for key '%s'"),
824 signing_key);
826 fingerprint_ret = strbuf_detach(fingerprint[1], NULL);
827 strbuf_list_free(fingerprint);
828 strbuf_release(&fingerprint_stdout);
829 return fingerprint_ret;
832 /* Returns the first public key from an ssh-agent to use for signing */
833 static const char *get_default_ssh_signing_key(void)
835 struct child_process ssh_default_key = CHILD_PROCESS_INIT;
836 int ret = -1;
837 struct strbuf key_stdout = STRBUF_INIT, key_stderr = STRBUF_INIT;
838 struct strbuf **keys;
839 char *key_command = NULL;
840 const char **argv;
841 int n;
842 char *default_key = NULL;
843 const char *literal_key = NULL;
845 if (!ssh_default_key_command)
846 die(_("either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"));
848 key_command = xstrdup(ssh_default_key_command);
849 n = split_cmdline(key_command, &argv);
851 if (n < 0)
852 die("malformed build-time gpg.ssh.defaultKeyCommand: %s",
853 split_cmdline_strerror(n));
855 strvec_pushv(&ssh_default_key.args, argv);
856 ret = pipe_command(&ssh_default_key, NULL, 0, &key_stdout, 0,
857 &key_stderr, 0);
859 if (!ret) {
860 keys = strbuf_split_max(&key_stdout, '\n', 2);
861 if (keys[0] && is_literal_ssh_key(keys[0]->buf, &literal_key)) {
863 * We only use `is_literal_ssh_key` here to check validity
864 * The prefix will be stripped when the key is used.
866 default_key = strbuf_detach(keys[0], NULL);
867 } else {
868 warning(_("gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"),
869 key_stderr.buf, key_stdout.buf);
872 strbuf_list_free(keys);
873 } else {
874 warning(_("gpg.ssh.defaultKeyCommand failed: %s %s"),
875 key_stderr.buf, key_stdout.buf);
878 free(key_command);
879 free(argv);
880 strbuf_release(&key_stdout);
882 return default_key;
885 static const char *get_ssh_key_id(void) {
886 return get_ssh_key_fingerprint(get_signing_key());
889 /* Returns a textual but unique representation of the signing key */
890 const char *get_signing_key_id(void)
892 if (use_format->get_key_id) {
893 return use_format->get_key_id();
896 /* GPG/GPGSM only store a key id on this variable */
897 return get_signing_key();
900 const char *get_signing_key(void)
902 if (configured_signing_key)
903 return configured_signing_key;
904 if (use_format->get_default_key) {
905 return use_format->get_default_key();
908 return git_committer_info(IDENT_STRICT | IDENT_NO_DATE);
911 const char *gpg_trust_level_to_str(enum signature_trust_level level)
913 struct sigcheck_gpg_trust_level *trust;
915 if (level < 0 || level >= ARRAY_SIZE(sigcheck_gpg_trust_level))
916 BUG("invalid trust level requested %d", level);
918 trust = &sigcheck_gpg_trust_level[level];
919 if (trust->value != level)
920 BUG("sigcheck_gpg_trust_level[] unsorted");
922 return sigcheck_gpg_trust_level[level].display_key;
925 int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key)
927 return use_format->sign_buffer(buffer, signature, signing_key);
931 * Strip CR from the line endings, in case we are on Windows.
932 * NEEDSWORK: make it trim only CRs before LFs and rename
934 static void remove_cr_after(struct strbuf *buffer, size_t offset)
936 size_t i, j;
938 for (i = j = offset; i < buffer->len; i++) {
939 if (buffer->buf[i] != '\r') {
940 if (i != j)
941 buffer->buf[j] = buffer->buf[i];
942 j++;
945 strbuf_setlen(buffer, j);
948 static int sign_buffer_gpg(struct strbuf *buffer, struct strbuf *signature,
949 const char *signing_key)
951 struct child_process gpg = CHILD_PROCESS_INIT;
952 int ret;
953 size_t bottom;
954 const char *cp;
955 struct strbuf gpg_status = STRBUF_INIT;
957 strvec_pushl(&gpg.args,
958 use_format->program,
959 "--status-fd=2",
960 "-bsau", signing_key,
961 NULL);
963 bottom = signature->len;
966 * When the username signingkey is bad, program could be terminated
967 * because gpg exits without reading and then write gets SIGPIPE.
969 sigchain_push(SIGPIPE, SIG_IGN);
970 ret = pipe_command(&gpg, buffer->buf, buffer->len,
971 signature, 1024, &gpg_status, 0);
972 sigchain_pop(SIGPIPE);
974 for (cp = gpg_status.buf;
975 cp && (cp = strstr(cp, "[GNUPG:] SIG_CREATED "));
976 cp++) {
977 if (cp == gpg_status.buf || cp[-1] == '\n')
978 break; /* found */
980 ret |= !cp;
981 strbuf_release(&gpg_status);
982 if (ret)
983 return error(_("gpg failed to sign the data"));
985 /* Strip CR from the line endings, in case we are on Windows. */
986 remove_cr_after(signature, bottom);
988 return 0;
991 static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
992 const char *signing_key)
994 struct child_process signer = CHILD_PROCESS_INIT;
995 int ret = -1;
996 size_t bottom, keylen;
997 struct strbuf signer_stderr = STRBUF_INIT;
998 struct tempfile *key_file = NULL, *buffer_file = NULL;
999 char *ssh_signing_key_file = NULL;
1000 struct strbuf ssh_signature_filename = STRBUF_INIT;
1001 const char *literal_key = NULL;
1002 int literal_ssh_key = 0;
1004 if (!signing_key || signing_key[0] == '\0')
1005 return error(
1006 _("user.signingKey needs to be set for ssh signing"));
1008 if (is_literal_ssh_key(signing_key, &literal_key)) {
1009 /* A literal ssh key */
1010 literal_ssh_key = 1;
1011 key_file = mks_tempfile_t(".git_signing_key_tmpXXXXXX");
1012 if (!key_file)
1013 return error_errno(
1014 _("could not create temporary file"));
1015 keylen = strlen(literal_key);
1016 if (write_in_full(key_file->fd, literal_key, keylen) < 0 ||
1017 close_tempfile_gently(key_file) < 0) {
1018 error_errno(_("failed writing ssh signing key to '%s'"),
1019 key_file->filename.buf);
1020 goto out;
1022 ssh_signing_key_file = strbuf_detach(&key_file->filename, NULL);
1023 } else {
1024 /* We assume a file */
1025 ssh_signing_key_file = expand_user_path(signing_key, 1);
1028 buffer_file = mks_tempfile_t(".git_signing_buffer_tmpXXXXXX");
1029 if (!buffer_file) {
1030 error_errno(_("could not create temporary file"));
1031 goto out;
1034 if (write_in_full(buffer_file->fd, buffer->buf, buffer->len) < 0 ||
1035 close_tempfile_gently(buffer_file) < 0) {
1036 error_errno(_("failed writing ssh signing key buffer to '%s'"),
1037 buffer_file->filename.buf);
1038 goto out;
1041 strvec_pushl(&signer.args, use_format->program,
1042 "-Y", "sign",
1043 "-n", "git",
1044 "-f", ssh_signing_key_file,
1045 NULL);
1046 if (literal_ssh_key)
1047 strvec_push(&signer.args, "-U");
1048 strvec_push(&signer.args, buffer_file->filename.buf);
1050 sigchain_push(SIGPIPE, SIG_IGN);
1051 ret = pipe_command(&signer, NULL, 0, NULL, 0, &signer_stderr, 0);
1052 sigchain_pop(SIGPIPE);
1054 if (ret) {
1055 if (strstr(signer_stderr.buf, "usage:"))
1056 error(_("ssh-keygen -Y sign is needed for ssh signing (available in openssh version 8.2p1+)"));
1058 error("%s", signer_stderr.buf);
1059 goto out;
1062 bottom = signature->len;
1064 strbuf_addbuf(&ssh_signature_filename, &buffer_file->filename);
1065 strbuf_addstr(&ssh_signature_filename, ".sig");
1066 if (strbuf_read_file(signature, ssh_signature_filename.buf, 0) < 0) {
1067 ret = error_errno(
1068 _("failed reading ssh signing data buffer from '%s'"),
1069 ssh_signature_filename.buf);
1070 goto out;
1072 /* Strip CR from the line endings, in case we are on Windows. */
1073 remove_cr_after(signature, bottom);
1075 out:
1076 if (key_file)
1077 delete_tempfile(&key_file);
1078 if (buffer_file)
1079 delete_tempfile(&buffer_file);
1080 if (ssh_signature_filename.len)
1081 unlink_or_warn(ssh_signature_filename.buf);
1082 strbuf_release(&signer_stderr);
1083 strbuf_release(&ssh_signature_filename);
1084 FREE_AND_NULL(ssh_signing_key_file);
1085 return ret;