ssh signing: provide a textual signing_key_id
[git.git] / gpg-interface.c
blob0f1c6a02e53257b09042178effbd7bd7ce14909b
1 #include "cache.h"
2 #include "commit.h"
3 #include "config.h"
4 #include "run-command.h"
5 #include "strbuf.h"
6 #include "gpg-interface.h"
7 #include "sigchain.h"
8 #include "tempfile.h"
9 #include "alias.h"
11 static char *configured_signing_key;
12 static const char *ssh_default_key_command;
13 static enum signature_trust_level configured_min_trust_level = TRUST_UNDEFINED;
15 struct gpg_format {
16 const char *name;
17 const char *program;
18 const char **verify_args;
19 const char **sigs;
20 int (*verify_signed_buffer)(struct signature_check *sigc,
21 struct gpg_format *fmt, const char *payload,
22 size_t payload_size, const char *signature,
23 size_t signature_size);
24 int (*sign_buffer)(struct strbuf *buffer, struct strbuf *signature,
25 const char *signing_key);
26 const char *(*get_default_key)(void);
27 const char *(*get_key_id)(void);
30 static const char *openpgp_verify_args[] = {
31 "--keyid-format=long",
32 NULL
34 static const char *openpgp_sigs[] = {
35 "-----BEGIN PGP SIGNATURE-----",
36 "-----BEGIN PGP MESSAGE-----",
37 NULL
40 static const char *x509_verify_args[] = {
41 NULL
43 static const char *x509_sigs[] = {
44 "-----BEGIN SIGNED MESSAGE-----",
45 NULL
48 static const char *ssh_verify_args[] = { NULL };
49 static const char *ssh_sigs[] = {
50 "-----BEGIN SSH SIGNATURE-----",
51 NULL
54 static int verify_gpg_signed_buffer(struct signature_check *sigc,
55 struct gpg_format *fmt, const char *payload,
56 size_t payload_size, const char *signature,
57 size_t signature_size);
58 static int sign_buffer_gpg(struct strbuf *buffer, struct strbuf *signature,
59 const char *signing_key);
60 static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
61 const char *signing_key);
63 static const char *get_default_ssh_signing_key(void);
65 static const char *get_ssh_key_id(void);
67 static struct gpg_format gpg_format[] = {
69 .name = "openpgp",
70 .program = "gpg",
71 .verify_args = openpgp_verify_args,
72 .sigs = openpgp_sigs,
73 .verify_signed_buffer = verify_gpg_signed_buffer,
74 .sign_buffer = sign_buffer_gpg,
75 .get_default_key = NULL,
76 .get_key_id = NULL,
79 .name = "x509",
80 .program = "gpgsm",
81 .verify_args = x509_verify_args,
82 .sigs = x509_sigs,
83 .verify_signed_buffer = verify_gpg_signed_buffer,
84 .sign_buffer = sign_buffer_gpg,
85 .get_default_key = NULL,
86 .get_key_id = NULL,
89 .name = "ssh",
90 .program = "ssh-keygen",
91 .verify_args = ssh_verify_args,
92 .sigs = ssh_sigs,
93 .verify_signed_buffer = NULL, /* TODO */
94 .sign_buffer = sign_buffer_ssh,
95 .get_default_key = get_default_ssh_signing_key,
96 .get_key_id = get_ssh_key_id,
100 static struct gpg_format *use_format = &gpg_format[0];
102 static struct gpg_format *get_format_by_name(const char *str)
104 int i;
106 for (i = 0; i < ARRAY_SIZE(gpg_format); i++)
107 if (!strcmp(gpg_format[i].name, str))
108 return gpg_format + i;
109 return NULL;
112 static struct gpg_format *get_format_by_sig(const char *sig)
114 int i, j;
116 for (i = 0; i < ARRAY_SIZE(gpg_format); i++)
117 for (j = 0; gpg_format[i].sigs[j]; j++)
118 if (starts_with(sig, gpg_format[i].sigs[j]))
119 return gpg_format + i;
120 return NULL;
123 void signature_check_clear(struct signature_check *sigc)
125 FREE_AND_NULL(sigc->payload);
126 FREE_AND_NULL(sigc->output);
127 FREE_AND_NULL(sigc->gpg_status);
128 FREE_AND_NULL(sigc->signer);
129 FREE_AND_NULL(sigc->key);
130 FREE_AND_NULL(sigc->fingerprint);
131 FREE_AND_NULL(sigc->primary_key_fingerprint);
134 /* An exclusive status -- only one of them can appear in output */
135 #define GPG_STATUS_EXCLUSIVE (1<<0)
136 /* The status includes key identifier */
137 #define GPG_STATUS_KEYID (1<<1)
138 /* The status includes user identifier */
139 #define GPG_STATUS_UID (1<<2)
140 /* The status includes key fingerprints */
141 #define GPG_STATUS_FINGERPRINT (1<<3)
142 /* The status includes trust level */
143 #define GPG_STATUS_TRUST_LEVEL (1<<4)
145 /* Short-hand for standard exclusive *SIG status with keyid & UID */
146 #define GPG_STATUS_STDSIG (GPG_STATUS_EXCLUSIVE|GPG_STATUS_KEYID|GPG_STATUS_UID)
148 static struct {
149 char result;
150 const char *check;
151 unsigned int flags;
152 } sigcheck_gpg_status[] = {
153 { 'G', "GOODSIG ", GPG_STATUS_STDSIG },
154 { 'B', "BADSIG ", GPG_STATUS_STDSIG },
155 { 'E', "ERRSIG ", GPG_STATUS_EXCLUSIVE|GPG_STATUS_KEYID },
156 { 'X', "EXPSIG ", GPG_STATUS_STDSIG },
157 { 'Y', "EXPKEYSIG ", GPG_STATUS_STDSIG },
158 { 'R', "REVKEYSIG ", GPG_STATUS_STDSIG },
159 { 0, "VALIDSIG ", GPG_STATUS_FINGERPRINT },
160 { 0, "TRUST_", GPG_STATUS_TRUST_LEVEL },
163 static struct {
164 const char *key;
165 enum signature_trust_level value;
166 } sigcheck_gpg_trust_level[] = {
167 { "UNDEFINED", TRUST_UNDEFINED },
168 { "NEVER", TRUST_NEVER },
169 { "MARGINAL", TRUST_MARGINAL },
170 { "FULLY", TRUST_FULLY },
171 { "ULTIMATE", TRUST_ULTIMATE },
174 static void replace_cstring(char **field, const char *line, const char *next)
176 free(*field);
178 if (line && next)
179 *field = xmemdupz(line, next - line);
180 else
181 *field = NULL;
184 static int parse_gpg_trust_level(const char *level,
185 enum signature_trust_level *res)
187 size_t i;
189 for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_trust_level); i++) {
190 if (!strcmp(sigcheck_gpg_trust_level[i].key, level)) {
191 *res = sigcheck_gpg_trust_level[i].value;
192 return 0;
195 return 1;
198 static void parse_gpg_output(struct signature_check *sigc)
200 const char *buf = sigc->gpg_status;
201 const char *line, *next;
202 int i, j;
203 int seen_exclusive_status = 0;
205 /* Iterate over all lines */
206 for (line = buf; *line; line = strchrnul(line+1, '\n')) {
207 while (*line == '\n')
208 line++;
209 if (!*line)
210 break;
212 /* Skip lines that don't start with GNUPG status */
213 if (!skip_prefix(line, "[GNUPG:] ", &line))
214 continue;
216 /* Iterate over all search strings */
217 for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) {
218 if (skip_prefix(line, sigcheck_gpg_status[i].check, &line)) {
220 * GOODSIG, BADSIG etc. can occur only once for
221 * each signature. Therefore, if we had more
222 * than one then we're dealing with multiple
223 * signatures. We don't support them
224 * currently, and they're rather hard to
225 * create, so something is likely fishy and we
226 * should reject them altogether.
228 if (sigcheck_gpg_status[i].flags & GPG_STATUS_EXCLUSIVE) {
229 if (seen_exclusive_status++)
230 goto error;
233 if (sigcheck_gpg_status[i].result)
234 sigc->result = sigcheck_gpg_status[i].result;
235 /* Do we have key information? */
236 if (sigcheck_gpg_status[i].flags & GPG_STATUS_KEYID) {
237 next = strchrnul(line, ' ');
238 replace_cstring(&sigc->key, line, next);
239 /* Do we have signer information? */
240 if (*next && (sigcheck_gpg_status[i].flags & GPG_STATUS_UID)) {
241 line = next + 1;
242 next = strchrnul(line, '\n');
243 replace_cstring(&sigc->signer, line, next);
247 /* Do we have trust level? */
248 if (sigcheck_gpg_status[i].flags & GPG_STATUS_TRUST_LEVEL) {
250 * GPG v1 and v2 differs in how the
251 * TRUST_ lines are written. Some
252 * trust lines contain no additional
253 * space-separated information for v1.
255 size_t trust_size = strcspn(line, " \n");
256 char *trust = xmemdupz(line, trust_size);
258 if (parse_gpg_trust_level(trust, &sigc->trust_level)) {
259 free(trust);
260 goto error;
262 free(trust);
265 /* Do we have fingerprint? */
266 if (sigcheck_gpg_status[i].flags & GPG_STATUS_FINGERPRINT) {
267 const char *limit;
268 char **field;
270 next = strchrnul(line, ' ');
271 replace_cstring(&sigc->fingerprint, line, next);
274 * Skip interim fields. The search is
275 * limited to the same line since only
276 * OpenPGP signatures has a field with
277 * the primary fingerprint.
279 limit = strchrnul(line, '\n');
280 for (j = 9; j > 0; j--) {
281 if (!*next || limit <= next)
282 break;
283 line = next + 1;
284 next = strchrnul(line, ' ');
287 field = &sigc->primary_key_fingerprint;
288 if (!j) {
289 next = strchrnul(line, '\n');
290 replace_cstring(field, line, next);
291 } else {
292 replace_cstring(field, NULL, NULL);
296 break;
300 return;
302 error:
303 sigc->result = 'E';
304 /* Clear partial data to avoid confusion */
305 FREE_AND_NULL(sigc->primary_key_fingerprint);
306 FREE_AND_NULL(sigc->fingerprint);
307 FREE_AND_NULL(sigc->signer);
308 FREE_AND_NULL(sigc->key);
311 static int verify_gpg_signed_buffer(struct signature_check *sigc,
312 struct gpg_format *fmt, const char *payload,
313 size_t payload_size, const char *signature,
314 size_t signature_size)
316 struct child_process gpg = CHILD_PROCESS_INIT;
317 struct tempfile *temp;
318 int ret;
319 struct strbuf gpg_stdout = STRBUF_INIT;
320 struct strbuf gpg_stderr = STRBUF_INIT;
322 temp = mks_tempfile_t(".git_vtag_tmpXXXXXX");
323 if (!temp)
324 return error_errno(_("could not create temporary file"));
325 if (write_in_full(temp->fd, signature, signature_size) < 0 ||
326 close_tempfile_gently(temp) < 0) {
327 error_errno(_("failed writing detached signature to '%s'"),
328 temp->filename.buf);
329 delete_tempfile(&temp);
330 return -1;
333 strvec_push(&gpg.args, fmt->program);
334 strvec_pushv(&gpg.args, fmt->verify_args);
335 strvec_pushl(&gpg.args,
336 "--status-fd=1",
337 "--verify", temp->filename.buf, "-",
338 NULL);
340 sigchain_push(SIGPIPE, SIG_IGN);
341 ret = pipe_command(&gpg, payload, payload_size, &gpg_stdout, 0,
342 &gpg_stderr, 0);
343 sigchain_pop(SIGPIPE);
345 delete_tempfile(&temp);
347 ret |= !strstr(gpg_stdout.buf, "\n[GNUPG:] GOODSIG ");
348 sigc->payload = xmemdupz(payload, payload_size);
349 sigc->output = strbuf_detach(&gpg_stderr, NULL);
350 sigc->gpg_status = strbuf_detach(&gpg_stdout, NULL);
352 parse_gpg_output(sigc);
354 strbuf_release(&gpg_stdout);
355 strbuf_release(&gpg_stderr);
357 return ret;
360 int check_signature(const char *payload, size_t plen, const char *signature,
361 size_t slen, struct signature_check *sigc)
363 struct gpg_format *fmt;
364 int status;
366 sigc->result = 'N';
367 sigc->trust_level = -1;
369 fmt = get_format_by_sig(signature);
370 if (!fmt)
371 die(_("bad/incompatible signature '%s'"), signature);
373 status = fmt->verify_signed_buffer(sigc, fmt, payload, plen, signature,
374 slen);
376 if (status && !sigc->output)
377 return !!status;
379 status |= sigc->result != 'G';
380 status |= sigc->trust_level < configured_min_trust_level;
382 return !!status;
385 void print_signature_buffer(const struct signature_check *sigc, unsigned flags)
387 const char *output = flags & GPG_VERIFY_RAW ? sigc->gpg_status :
388 sigc->output;
390 if (flags & GPG_VERIFY_VERBOSE && sigc->payload)
391 fputs(sigc->payload, stdout);
393 if (output)
394 fputs(output, stderr);
397 size_t parse_signed_buffer(const char *buf, size_t size)
399 size_t len = 0;
400 size_t match = size;
401 while (len < size) {
402 const char *eol;
404 if (get_format_by_sig(buf + len))
405 match = len;
407 eol = memchr(buf + len, '\n', size - len);
408 len += eol ? eol - (buf + len) + 1 : size - len;
410 return match;
413 int parse_signature(const char *buf, size_t size, struct strbuf *payload, struct strbuf *signature)
415 size_t match = parse_signed_buffer(buf, size);
416 if (match != size) {
417 strbuf_add(payload, buf, match);
418 remove_signature(payload);
419 strbuf_add(signature, buf + match, size - match);
420 return 1;
422 return 0;
425 void set_signing_key(const char *key)
427 free(configured_signing_key);
428 configured_signing_key = xstrdup(key);
431 int git_gpg_config(const char *var, const char *value, void *cb)
433 struct gpg_format *fmt = NULL;
434 char *fmtname = NULL;
435 char *trust;
436 int ret;
438 if (!strcmp(var, "user.signingkey")) {
439 if (!value)
440 return config_error_nonbool(var);
441 set_signing_key(value);
442 return 0;
445 if (!strcmp(var, "gpg.format")) {
446 if (!value)
447 return config_error_nonbool(var);
448 fmt = get_format_by_name(value);
449 if (!fmt)
450 return error("unsupported value for %s: %s",
451 var, value);
452 use_format = fmt;
453 return 0;
456 if (!strcmp(var, "gpg.mintrustlevel")) {
457 if (!value)
458 return config_error_nonbool(var);
460 trust = xstrdup_toupper(value);
461 ret = parse_gpg_trust_level(trust, &configured_min_trust_level);
462 free(trust);
464 if (ret)
465 return error("unsupported value for %s: %s", var,
466 value);
467 return 0;
470 if (!strcmp(var, "gpg.ssh.defaultkeycommand")) {
471 if (!value)
472 return config_error_nonbool(var);
473 return git_config_string(&ssh_default_key_command, var, value);
476 if (!strcmp(var, "gpg.program") || !strcmp(var, "gpg.openpgp.program"))
477 fmtname = "openpgp";
479 if (!strcmp(var, "gpg.x509.program"))
480 fmtname = "x509";
482 if (!strcmp(var, "gpg.ssh.program"))
483 fmtname = "ssh";
485 if (fmtname) {
486 fmt = get_format_by_name(fmtname);
487 return git_config_string(&fmt->program, var, value);
490 return 0;
493 static char *get_ssh_key_fingerprint(const char *signing_key)
495 struct child_process ssh_keygen = CHILD_PROCESS_INIT;
496 int ret = -1;
497 struct strbuf fingerprint_stdout = STRBUF_INIT;
498 struct strbuf **fingerprint;
501 * With SSH Signing this can contain a filename or a public key
502 * For textual representation we usually want a fingerprint
504 if (starts_with(signing_key, "ssh-")) {
505 strvec_pushl(&ssh_keygen.args, "ssh-keygen", "-lf", "-", NULL);
506 ret = pipe_command(&ssh_keygen, signing_key,
507 strlen(signing_key), &fingerprint_stdout, 0,
508 NULL, 0);
509 } else {
510 strvec_pushl(&ssh_keygen.args, "ssh-keygen", "-lf",
511 configured_signing_key, NULL);
512 ret = pipe_command(&ssh_keygen, NULL, 0, &fingerprint_stdout, 0,
513 NULL, 0);
516 if (!!ret)
517 die_errno(_("failed to get the ssh fingerprint for key '%s'"),
518 signing_key);
520 fingerprint = strbuf_split_max(&fingerprint_stdout, ' ', 3);
521 if (!fingerprint[1])
522 die_errno(_("failed to get the ssh fingerprint for key '%s'"),
523 signing_key);
525 return strbuf_detach(fingerprint[1], NULL);
528 /* Returns the first public key from an ssh-agent to use for signing */
529 static const char *get_default_ssh_signing_key(void)
531 struct child_process ssh_default_key = CHILD_PROCESS_INIT;
532 int ret = -1;
533 struct strbuf key_stdout = STRBUF_INIT, key_stderr = STRBUF_INIT;
534 struct strbuf **keys;
535 char *key_command = NULL;
536 const char **argv;
537 int n;
538 char *default_key = NULL;
540 if (!ssh_default_key_command)
541 die(_("either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"));
543 key_command = xstrdup(ssh_default_key_command);
544 n = split_cmdline(key_command, &argv);
546 if (n < 0)
547 die("malformed build-time gpg.ssh.defaultKeyCommand: %s",
548 split_cmdline_strerror(n));
550 strvec_pushv(&ssh_default_key.args, argv);
551 ret = pipe_command(&ssh_default_key, NULL, 0, &key_stdout, 0,
552 &key_stderr, 0);
554 if (!ret) {
555 keys = strbuf_split_max(&key_stdout, '\n', 2);
556 if (keys[0] && starts_with(keys[0]->buf, "ssh-")) {
557 default_key = strbuf_detach(keys[0], NULL);
558 } else {
559 warning(_("gpg.ssh.defaultKeycommand succeeded but returned no keys: %s %s"),
560 key_stderr.buf, key_stdout.buf);
563 strbuf_list_free(keys);
564 } else {
565 warning(_("gpg.ssh.defaultKeyCommand failed: %s %s"),
566 key_stderr.buf, key_stdout.buf);
569 free(key_command);
570 free(argv);
571 strbuf_release(&key_stdout);
573 return default_key;
576 static const char *get_ssh_key_id(void) {
577 return get_ssh_key_fingerprint(get_signing_key());
580 /* Returns a textual but unique representation of the signing key */
581 const char *get_signing_key_id(void)
583 if (use_format->get_key_id) {
584 return use_format->get_key_id();
587 /* GPG/GPGSM only store a key id on this variable */
588 return get_signing_key();
591 const char *get_signing_key(void)
593 if (configured_signing_key)
594 return configured_signing_key;
595 if (use_format->get_default_key) {
596 return use_format->get_default_key();
599 return git_committer_info(IDENT_STRICT | IDENT_NO_DATE);
602 int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key)
604 return use_format->sign_buffer(buffer, signature, signing_key);
608 * Strip CR from the line endings, in case we are on Windows.
609 * NEEDSWORK: make it trim only CRs before LFs and rename
611 static void remove_cr_after(struct strbuf *buffer, size_t offset)
613 size_t i, j;
615 for (i = j = offset; i < buffer->len; i++) {
616 if (buffer->buf[i] != '\r') {
617 if (i != j)
618 buffer->buf[j] = buffer->buf[i];
619 j++;
622 strbuf_setlen(buffer, j);
625 static int sign_buffer_gpg(struct strbuf *buffer, struct strbuf *signature,
626 const char *signing_key)
628 struct child_process gpg = CHILD_PROCESS_INIT;
629 int ret;
630 size_t bottom;
631 struct strbuf gpg_status = STRBUF_INIT;
633 strvec_pushl(&gpg.args,
634 use_format->program,
635 "--status-fd=2",
636 "-bsau", signing_key,
637 NULL);
639 bottom = signature->len;
642 * When the username signingkey is bad, program could be terminated
643 * because gpg exits without reading and then write gets SIGPIPE.
645 sigchain_push(SIGPIPE, SIG_IGN);
646 ret = pipe_command(&gpg, buffer->buf, buffer->len,
647 signature, 1024, &gpg_status, 0);
648 sigchain_pop(SIGPIPE);
650 ret |= !strstr(gpg_status.buf, "\n[GNUPG:] SIG_CREATED ");
651 strbuf_release(&gpg_status);
652 if (ret)
653 return error(_("gpg failed to sign the data"));
655 /* Strip CR from the line endings, in case we are on Windows. */
656 remove_cr_after(signature, bottom);
658 return 0;
661 static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
662 const char *signing_key)
664 struct child_process signer = CHILD_PROCESS_INIT;
665 int ret = -1;
666 size_t bottom, keylen;
667 struct strbuf signer_stderr = STRBUF_INIT;
668 struct tempfile *key_file = NULL, *buffer_file = NULL;
669 char *ssh_signing_key_file = NULL;
670 struct strbuf ssh_signature_filename = STRBUF_INIT;
672 if (!signing_key || signing_key[0] == '\0')
673 return error(
674 _("user.signingkey needs to be set for ssh signing"));
676 if (starts_with(signing_key, "ssh-")) {
677 /* A literal ssh key */
678 key_file = mks_tempfile_t(".git_signing_key_tmpXXXXXX");
679 if (!key_file)
680 return error_errno(
681 _("could not create temporary file"));
682 keylen = strlen(signing_key);
683 if (write_in_full(key_file->fd, signing_key, keylen) < 0 ||
684 close_tempfile_gently(key_file) < 0) {
685 error_errno(_("failed writing ssh signing key to '%s'"),
686 key_file->filename.buf);
687 goto out;
689 ssh_signing_key_file = strbuf_detach(&key_file->filename, NULL);
690 } else {
691 /* We assume a file */
692 ssh_signing_key_file = expand_user_path(signing_key, 1);
695 buffer_file = mks_tempfile_t(".git_signing_buffer_tmpXXXXXX");
696 if (!buffer_file) {
697 error_errno(_("could not create temporary file"));
698 goto out;
701 if (write_in_full(buffer_file->fd, buffer->buf, buffer->len) < 0 ||
702 close_tempfile_gently(buffer_file) < 0) {
703 error_errno(_("failed writing ssh signing key buffer to '%s'"),
704 buffer_file->filename.buf);
705 goto out;
708 strvec_pushl(&signer.args, use_format->program,
709 "-Y", "sign",
710 "-n", "git",
711 "-f", ssh_signing_key_file,
712 buffer_file->filename.buf,
713 NULL);
715 sigchain_push(SIGPIPE, SIG_IGN);
716 ret = pipe_command(&signer, NULL, 0, NULL, 0, &signer_stderr, 0);
717 sigchain_pop(SIGPIPE);
719 if (ret) {
720 if (strstr(signer_stderr.buf, "usage:"))
721 error(_("ssh-keygen -Y sign is needed for ssh signing (available in openssh version 8.2p1+)"));
723 error("%s", signer_stderr.buf);
724 goto out;
727 bottom = signature->len;
729 strbuf_addbuf(&ssh_signature_filename, &buffer_file->filename);
730 strbuf_addstr(&ssh_signature_filename, ".sig");
731 if (strbuf_read_file(signature, ssh_signature_filename.buf, 0) < 0) {
732 error_errno(
733 _("failed reading ssh signing data buffer from '%s'"),
734 ssh_signature_filename.buf);
736 unlink_or_warn(ssh_signature_filename.buf);
738 /* Strip CR from the line endings, in case we are on Windows. */
739 remove_cr_after(signature, bottom);
741 out:
742 if (key_file)
743 delete_tempfile(&key_file);
744 if (buffer_file)
745 delete_tempfile(&buffer_file);
746 strbuf_release(&signer_stderr);
747 strbuf_release(&ssh_signature_filename);
748 FREE_AND_NULL(ssh_signing_key_file);
749 return ret;