git

Форк
0
/
gpg-interface.c 
1113 строк · 29.3 Кб
1
#define USE_THE_REPOSITORY_VARIABLE
2

3
#include "git-compat-util.h"
4
#include "commit.h"
5
#include "config.h"
6
#include "date.h"
7
#include "gettext.h"
8
#include "run-command.h"
9
#include "strbuf.h"
10
#include "dir.h"
11
#include "ident.h"
12
#include "gpg-interface.h"
13
#include "path.h"
14
#include "sigchain.h"
15
#include "tempfile.h"
16
#include "alias.h"
17

18
static int git_gpg_config(const char *, const char *,
19
			  const struct config_context *, void *);
20

21
static void gpg_interface_lazy_init(void)
22
{
23
	static int done;
24

25
	if (done)
26
		return;
27
	done = 1;
28
	git_config(git_gpg_config, NULL);
29
}
30

31
static char *configured_signing_key;
32
static char *ssh_default_key_command;
33
static char *ssh_allowed_signers;
34
static char *ssh_revocation_file;
35
static enum signature_trust_level configured_min_trust_level = TRUST_UNDEFINED;
36

37
struct gpg_format {
38
	const char *name;
39
	const char *program;
40
	const char **verify_args;
41
	const char **sigs;
42
	int (*verify_signed_buffer)(struct signature_check *sigc,
43
				    struct gpg_format *fmt,
44
				    const char *signature,
45
				    size_t signature_size);
46
	int (*sign_buffer)(struct strbuf *buffer, struct strbuf *signature,
47
			   const char *signing_key);
48
	const char *(*get_default_key)(void);
49
	const char *(*get_key_id)(void);
50
};
51

52
static const char *openpgp_verify_args[] = {
53
	"--keyid-format=long",
54
	NULL
55
};
56
static const char *openpgp_sigs[] = {
57
	"-----BEGIN PGP SIGNATURE-----",
58
	"-----BEGIN PGP MESSAGE-----",
59
	NULL
60
};
61

62
static const char *x509_verify_args[] = {
63
	NULL
64
};
65
static const char *x509_sigs[] = {
66
	"-----BEGIN SIGNED MESSAGE-----",
67
	NULL
68
};
69

70
static const char *ssh_verify_args[] = { NULL };
71
static const char *ssh_sigs[] = {
72
	"-----BEGIN SSH SIGNATURE-----",
73
	NULL
74
};
75

76
static int verify_gpg_signed_buffer(struct signature_check *sigc,
77
				    struct gpg_format *fmt,
78
				    const char *signature,
79
				    size_t signature_size);
80
static int verify_ssh_signed_buffer(struct signature_check *sigc,
81
				    struct gpg_format *fmt,
82
				    const char *signature,
83
				    size_t signature_size);
84
static int sign_buffer_gpg(struct strbuf *buffer, struct strbuf *signature,
85
			   const char *signing_key);
86
static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
87
			   const char *signing_key);
88

89
static const char *get_default_ssh_signing_key(void);
90

91
static const char *get_ssh_key_id(void);
92

93
static struct gpg_format gpg_format[] = {
94
	{
95
		.name = "openpgp",
96
		.program = "gpg",
97
		.verify_args = openpgp_verify_args,
98
		.sigs = openpgp_sigs,
99
		.verify_signed_buffer = verify_gpg_signed_buffer,
100
		.sign_buffer = sign_buffer_gpg,
101
		.get_default_key = NULL,
102
		.get_key_id = NULL,
103
	},
104
	{
105
		.name = "x509",
106
		.program = "gpgsm",
107
		.verify_args = x509_verify_args,
108
		.sigs = x509_sigs,
109
		.verify_signed_buffer = verify_gpg_signed_buffer,
110
		.sign_buffer = sign_buffer_gpg,
111
		.get_default_key = NULL,
112
		.get_key_id = NULL,
113
	},
114
	{
115
		.name = "ssh",
116
		.program = "ssh-keygen",
117
		.verify_args = ssh_verify_args,
118
		.sigs = ssh_sigs,
119
		.verify_signed_buffer = verify_ssh_signed_buffer,
120
		.sign_buffer = sign_buffer_ssh,
121
		.get_default_key = get_default_ssh_signing_key,
122
		.get_key_id = get_ssh_key_id,
123
	},
124
};
125

126
static struct gpg_format *use_format = &gpg_format[0];
127

128
static struct gpg_format *get_format_by_name(const char *str)
129
{
130
	int i;
131

132
	for (i = 0; i < ARRAY_SIZE(gpg_format); i++)
133
		if (!strcmp(gpg_format[i].name, str))
134
			return gpg_format + i;
135
	return NULL;
136
}
137

138
static struct gpg_format *get_format_by_sig(const char *sig)
139
{
140
	int i, j;
141

142
	for (i = 0; i < ARRAY_SIZE(gpg_format); i++)
143
		for (j = 0; gpg_format[i].sigs[j]; j++)
144
			if (starts_with(sig, gpg_format[i].sigs[j]))
145
				return gpg_format + i;
146
	return NULL;
147
}
148

149
void signature_check_clear(struct signature_check *sigc)
150
{
151
	FREE_AND_NULL(sigc->payload);
152
	FREE_AND_NULL(sigc->output);
153
	FREE_AND_NULL(sigc->gpg_status);
154
	FREE_AND_NULL(sigc->signer);
155
	FREE_AND_NULL(sigc->key);
156
	FREE_AND_NULL(sigc->fingerprint);
157
	FREE_AND_NULL(sigc->primary_key_fingerprint);
158
}
159

160
/* An exclusive status -- only one of them can appear in output */
161
#define GPG_STATUS_EXCLUSIVE	(1<<0)
162
/* The status includes key identifier */
163
#define GPG_STATUS_KEYID	(1<<1)
164
/* The status includes user identifier */
165
#define GPG_STATUS_UID		(1<<2)
166
/* The status includes key fingerprints */
167
#define GPG_STATUS_FINGERPRINT	(1<<3)
168
/* The status includes trust level */
169
#define GPG_STATUS_TRUST_LEVEL	(1<<4)
170

171
/* Short-hand for standard exclusive *SIG status with keyid & UID */
172
#define GPG_STATUS_STDSIG	(GPG_STATUS_EXCLUSIVE|GPG_STATUS_KEYID|GPG_STATUS_UID)
173

174
static struct {
175
	char result;
176
	const char *check;
177
	unsigned int flags;
178
} sigcheck_gpg_status[] = {
179
	{ 'G', "GOODSIG ", GPG_STATUS_STDSIG },
180
	{ 'B', "BADSIG ", GPG_STATUS_STDSIG },
181
	{ 'E', "ERRSIG ", GPG_STATUS_EXCLUSIVE|GPG_STATUS_KEYID },
182
	{ 'X', "EXPSIG ", GPG_STATUS_STDSIG },
183
	{ 'Y', "EXPKEYSIG ", GPG_STATUS_STDSIG },
184
	{ 'R', "REVKEYSIG ", GPG_STATUS_STDSIG },
185
	{ 0, "VALIDSIG ", GPG_STATUS_FINGERPRINT },
186
	{ 0, "TRUST_", GPG_STATUS_TRUST_LEVEL },
187
};
188

189
/* Keep the order same as enum signature_trust_level */
190
static struct sigcheck_gpg_trust_level {
191
	const char *key;
192
	const char *display_key;
193
	enum signature_trust_level value;
194
} sigcheck_gpg_trust_level[] = {
195
	{ "UNDEFINED", "undefined", TRUST_UNDEFINED },
196
	{ "NEVER", "never", TRUST_NEVER },
197
	{ "MARGINAL", "marginal", TRUST_MARGINAL },
198
	{ "FULLY", "fully", TRUST_FULLY },
199
	{ "ULTIMATE", "ultimate", TRUST_ULTIMATE },
200
};
201

202
static void replace_cstring(char **field, const char *line, const char *next)
203
{
204
	free(*field);
205

206
	if (line && next)
207
		*field = xmemdupz(line, next - line);
208
	else
209
		*field = NULL;
210
}
211

212
static int parse_gpg_trust_level(const char *level,
213
				 enum signature_trust_level *res)
214
{
215
	size_t i;
216

217
	for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_trust_level); i++) {
218
		if (!strcmp(sigcheck_gpg_trust_level[i].key, level)) {
219
			*res = sigcheck_gpg_trust_level[i].value;
220
			return 0;
221
		}
222
	}
223
	return 1;
224
}
225

226
static void parse_gpg_output(struct signature_check *sigc)
227
{
228
	const char *buf = sigc->gpg_status;
229
	const char *line, *next;
230
	int i, j;
231
	int seen_exclusive_status = 0;
232

233
	/* Iterate over all lines */
234
	for (line = buf; *line; line = strchrnul(line+1, '\n')) {
235
		while (*line == '\n')
236
			line++;
237
		if (!*line)
238
			break;
239

240
		/* Skip lines that don't start with GNUPG status */
241
		if (!skip_prefix(line, "[GNUPG:] ", &line))
242
			continue;
243

244
		/* Iterate over all search strings */
245
		for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) {
246
			if (skip_prefix(line, sigcheck_gpg_status[i].check, &line)) {
247
				/*
248
				 * GOODSIG, BADSIG etc. can occur only once for
249
				 * each signature.  Therefore, if we had more
250
				 * than one then we're dealing with multiple
251
				 * signatures.  We don't support them
252
				 * currently, and they're rather hard to
253
				 * create, so something is likely fishy and we
254
				 * should reject them altogether.
255
				 */
256
				if (sigcheck_gpg_status[i].flags & GPG_STATUS_EXCLUSIVE) {
257
					if (seen_exclusive_status++)
258
						goto error;
259
				}
260

261
				if (sigcheck_gpg_status[i].result)
262
					sigc->result = sigcheck_gpg_status[i].result;
263
				/* Do we have key information? */
264
				if (sigcheck_gpg_status[i].flags & GPG_STATUS_KEYID) {
265
					next = strchrnul(line, ' ');
266
					replace_cstring(&sigc->key, line, next);
267
					/* Do we have signer information? */
268
					if (*next && (sigcheck_gpg_status[i].flags & GPG_STATUS_UID)) {
269
						line = next + 1;
270
						next = strchrnul(line, '\n');
271
						replace_cstring(&sigc->signer, line, next);
272
					}
273
				}
274

275
				/* Do we have trust level? */
276
				if (sigcheck_gpg_status[i].flags & GPG_STATUS_TRUST_LEVEL) {
277
					/*
278
					 * GPG v1 and v2 differs in how the
279
					 * TRUST_ lines are written.  Some
280
					 * trust lines contain no additional
281
					 * space-separated information for v1.
282
					 */
283
					size_t trust_size = strcspn(line, " \n");
284
					char *trust = xmemdupz(line, trust_size);
285

286
					if (parse_gpg_trust_level(trust, &sigc->trust_level)) {
287
						free(trust);
288
						goto error;
289
					}
290
					free(trust);
291
				}
292

293
				/* Do we have fingerprint? */
294
				if (sigcheck_gpg_status[i].flags & GPG_STATUS_FINGERPRINT) {
295
					const char *limit;
296
					char **field;
297

298
					next = strchrnul(line, ' ');
299
					replace_cstring(&sigc->fingerprint, line, next);
300

301
					/*
302
					 * Skip interim fields.  The search is
303
					 * limited to the same line since only
304
					 * OpenPGP signatures has a field with
305
					 * the primary fingerprint.
306
					 */
307
					limit = strchrnul(line, '\n');
308
					for (j = 9; j > 0; j--) {
309
						if (!*next || limit <= next)
310
							break;
311
						line = next + 1;
312
						next = strchrnul(line, ' ');
313
					}
314

315
					field = &sigc->primary_key_fingerprint;
316
					if (!j) {
317
						next = strchrnul(line, '\n');
318
						replace_cstring(field, line, next);
319
					} else {
320
						replace_cstring(field, NULL, NULL);
321
					}
322
				}
323

324
				break;
325
			}
326
		}
327
	}
328
	return;
329

330
error:
331
	sigc->result = 'E';
332
	/* Clear partial data to avoid confusion */
333
	FREE_AND_NULL(sigc->primary_key_fingerprint);
334
	FREE_AND_NULL(sigc->fingerprint);
335
	FREE_AND_NULL(sigc->signer);
336
	FREE_AND_NULL(sigc->key);
337
}
338

339
static int verify_gpg_signed_buffer(struct signature_check *sigc,
340
				    struct gpg_format *fmt,
341
				    const char *signature,
342
				    size_t signature_size)
343
{
344
	struct child_process gpg = CHILD_PROCESS_INIT;
345
	struct tempfile *temp;
346
	int ret;
347
	struct strbuf gpg_stdout = STRBUF_INIT;
348
	struct strbuf gpg_stderr = STRBUF_INIT;
349

350
	temp = mks_tempfile_t(".git_vtag_tmpXXXXXX");
351
	if (!temp)
352
		return error_errno(_("could not create temporary file"));
353
	if (write_in_full(temp->fd, signature, signature_size) < 0 ||
354
	    close_tempfile_gently(temp) < 0) {
355
		error_errno(_("failed writing detached signature to '%s'"),
356
			    temp->filename.buf);
357
		delete_tempfile(&temp);
358
		return -1;
359
	}
360

361
	strvec_push(&gpg.args, fmt->program);
362
	strvec_pushv(&gpg.args, fmt->verify_args);
363
	strvec_pushl(&gpg.args,
364
		     "--status-fd=1",
365
		     "--verify", temp->filename.buf, "-",
366
		     NULL);
367

368
	sigchain_push(SIGPIPE, SIG_IGN);
369
	ret = pipe_command(&gpg, sigc->payload, sigc->payload_len, &gpg_stdout, 0,
370
			   &gpg_stderr, 0);
371
	sigchain_pop(SIGPIPE);
372

373
	delete_tempfile(&temp);
374

375
	ret |= !strstr(gpg_stdout.buf, "\n[GNUPG:] GOODSIG ");
376
	sigc->output = strbuf_detach(&gpg_stderr, NULL);
377
	sigc->gpg_status = strbuf_detach(&gpg_stdout, NULL);
378

379
	parse_gpg_output(sigc);
380

381
	strbuf_release(&gpg_stdout);
382
	strbuf_release(&gpg_stderr);
383

384
	return ret;
385
}
386

387
static void parse_ssh_output(struct signature_check *sigc)
388
{
389
	const char *line, *principal, *search;
390
	char *to_free;
391
	char *key = NULL;
392

393
	/*
394
	 * ssh-keygen output should be:
395
	 * Good "git" signature for PRINCIPAL with RSA key SHA256:FINGERPRINT
396
	 *
397
	 * or for valid but unknown keys:
398
	 * Good "git" signature with RSA key SHA256:FINGERPRINT
399
	 *
400
	 * Note that "PRINCIPAL" can contain whitespace, "RSA" and
401
	 * "SHA256" part could be a different token that names of
402
	 * the algorithms used, and "FINGERPRINT" is a hexadecimal
403
	 * string.  By finding the last occurence of " with ", we can
404
	 * reliably parse out the PRINCIPAL.
405
	 */
406
	sigc->result = 'B';
407
	sigc->trust_level = TRUST_NEVER;
408

409
	line = to_free = xmemdupz(sigc->output, strcspn(sigc->output, "\n"));
410

411
	if (skip_prefix(line, "Good \"git\" signature for ", &line)) {
412
		/* Search for the last "with" to get the full principal */
413
		principal = line;
414
		do {
415
			search = strstr(line, " with ");
416
			if (search)
417
				line = search + 1;
418
		} while (search != NULL);
419
		if (line == principal)
420
			goto cleanup;
421

422
		/* Valid signature and known principal */
423
		sigc->result = 'G';
424
		sigc->trust_level = TRUST_FULLY;
425
		sigc->signer = xmemdupz(principal, line - principal - 1);
426
	} else if (skip_prefix(line, "Good \"git\" signature with ", &line)) {
427
		/* Valid signature, but key unknown */
428
		sigc->result = 'G';
429
		sigc->trust_level = TRUST_UNDEFINED;
430
	} else {
431
		goto cleanup;
432
	}
433

434
	key = strstr(line, "key ");
435
	if (key) {
436
		sigc->fingerprint = xstrdup(strstr(line, "key ") + 4);
437
		sigc->key = xstrdup(sigc->fingerprint);
438
	} else {
439
		/*
440
		 * Output did not match what we expected
441
		 * Treat the signature as bad
442
		 */
443
		sigc->result = 'B';
444
	}
445

446
cleanup:
447
	free(to_free);
448
}
449

450
static int verify_ssh_signed_buffer(struct signature_check *sigc,
451
				    struct gpg_format *fmt,
452
				    const char *signature,
453
				    size_t signature_size)
454
{
455
	struct child_process ssh_keygen = CHILD_PROCESS_INIT;
456
	struct tempfile *buffer_file;
457
	int ret = -1;
458
	const char *line;
459
	char *principal;
460
	struct strbuf ssh_principals_out = STRBUF_INIT;
461
	struct strbuf ssh_principals_err = STRBUF_INIT;
462
	struct strbuf ssh_keygen_out = STRBUF_INIT;
463
	struct strbuf ssh_keygen_err = STRBUF_INIT;
464
	struct strbuf verify_time = STRBUF_INIT;
465
	const struct date_mode verify_date_mode = {
466
		.type = DATE_STRFTIME,
467
		.strftime_fmt = "%Y%m%d%H%M%S",
468
		/* SSH signing key validity has no timezone information - Use the local timezone */
469
		.local = 1,
470
	};
471

472
	if (!ssh_allowed_signers) {
473
		error(_("gpg.ssh.allowedSignersFile needs to be configured and exist for ssh signature verification"));
474
		return -1;
475
	}
476

477
	buffer_file = mks_tempfile_t(".git_vtag_tmpXXXXXX");
478
	if (!buffer_file)
479
		return error_errno(_("could not create temporary file"));
480
	if (write_in_full(buffer_file->fd, signature, signature_size) < 0 ||
481
	    close_tempfile_gently(buffer_file) < 0) {
482
		error_errno(_("failed writing detached signature to '%s'"),
483
			    buffer_file->filename.buf);
484
		delete_tempfile(&buffer_file);
485
		return -1;
486
	}
487

488
	if (sigc->payload_timestamp)
489
		strbuf_addf(&verify_time, "-Overify-time=%s",
490
			show_date(sigc->payload_timestamp, 0, verify_date_mode));
491

492
	/* Find the principal from the signers */
493
	strvec_pushl(&ssh_keygen.args, fmt->program,
494
		     "-Y", "find-principals",
495
		     "-f", ssh_allowed_signers,
496
		     "-s", buffer_file->filename.buf,
497
		     verify_time.buf,
498
		     NULL);
499
	ret = pipe_command(&ssh_keygen, NULL, 0, &ssh_principals_out, 0,
500
			   &ssh_principals_err, 0);
501
	if (ret && strstr(ssh_principals_err.buf, "usage:")) {
502
		error(_("ssh-keygen -Y find-principals/verify is needed for ssh signature verification (available in openssh version 8.2p1+)"));
503
		goto out;
504
	}
505
	if (ret || !ssh_principals_out.len) {
506
		/*
507
		 * We did not find a matching principal in the allowedSigners
508
		 * Check without validation
509
		 */
510
		child_process_init(&ssh_keygen);
511
		strvec_pushl(&ssh_keygen.args, fmt->program,
512
			     "-Y", "check-novalidate",
513
			     "-n", "git",
514
			     "-s", buffer_file->filename.buf,
515
			     verify_time.buf,
516
			     NULL);
517
		pipe_command(&ssh_keygen, sigc->payload, sigc->payload_len,
518
				   &ssh_keygen_out, 0, &ssh_keygen_err, 0);
519

520
		/*
521
		 * Fail on unknown keys
522
		 * we still call check-novalidate to display the signature info
523
		 */
524
		ret = -1;
525
	} else {
526
		/* Check every principal we found (one per line) */
527
		const char *next;
528
		for (line = ssh_principals_out.buf;
529
		     *line;
530
		     line = next) {
531
			const char *end_of_text;
532

533
			next = end_of_text = strchrnul(line, '\n');
534

535
			 /* Did we find a LF, and did we have CR before it? */
536
			if (*end_of_text &&
537
			    line < end_of_text &&
538
			    end_of_text[-1] == '\r')
539
				end_of_text--;
540

541
			/* Unless we hit NUL, skip over the LF we found */
542
			if (*next)
543
				next++;
544

545
			/* Not all lines are data.  Skip empty ones */
546
			if (line == end_of_text)
547
				continue;
548

549
			/* We now know we have an non-empty line. Process it */
550
			principal = xmemdupz(line, end_of_text - line);
551

552
			child_process_init(&ssh_keygen);
553
			strbuf_release(&ssh_keygen_out);
554
			strbuf_release(&ssh_keygen_err);
555
			strvec_push(&ssh_keygen.args, fmt->program);
556
			/*
557
			 * We found principals
558
			 * Try with each until we find a match
559
			 */
560
			strvec_pushl(&ssh_keygen.args, "-Y", "verify",
561
				     "-n", "git",
562
				     "-f", ssh_allowed_signers,
563
				     "-I", principal,
564
				     "-s", buffer_file->filename.buf,
565
				     verify_time.buf,
566
				     NULL);
567

568
			if (ssh_revocation_file) {
569
				if (file_exists(ssh_revocation_file)) {
570
					strvec_pushl(&ssh_keygen.args, "-r",
571
						     ssh_revocation_file, NULL);
572
				} else {
573
					warning(_("ssh signing revocation file configured but not found: %s"),
574
						ssh_revocation_file);
575
				}
576
			}
577

578
			sigchain_push(SIGPIPE, SIG_IGN);
579
			ret = pipe_command(&ssh_keygen, sigc->payload, sigc->payload_len,
580
					   &ssh_keygen_out, 0, &ssh_keygen_err, 0);
581
			sigchain_pop(SIGPIPE);
582

583
			FREE_AND_NULL(principal);
584

585
			if (!ret)
586
				ret = !starts_with(ssh_keygen_out.buf, "Good");
587

588
			if (!ret)
589
				break;
590
		}
591
	}
592

593
	strbuf_stripspace(&ssh_keygen_out, NULL);
594
	strbuf_stripspace(&ssh_keygen_err, NULL);
595
	/* Add stderr outputs to show the user actual ssh-keygen errors */
596
	strbuf_add(&ssh_keygen_out, ssh_principals_err.buf, ssh_principals_err.len);
597
	strbuf_add(&ssh_keygen_out, ssh_keygen_err.buf, ssh_keygen_err.len);
598
	sigc->output = strbuf_detach(&ssh_keygen_out, NULL);
599
	sigc->gpg_status = xstrdup(sigc->output);
600

601
	parse_ssh_output(sigc);
602

603
out:
604
	if (buffer_file)
605
		delete_tempfile(&buffer_file);
606
	strbuf_release(&ssh_principals_out);
607
	strbuf_release(&ssh_principals_err);
608
	strbuf_release(&ssh_keygen_out);
609
	strbuf_release(&ssh_keygen_err);
610
	strbuf_release(&verify_time);
611

612
	return ret;
613
}
614

615
static int parse_payload_metadata(struct signature_check *sigc)
616
{
617
	const char *ident_line = NULL;
618
	size_t ident_len;
619
	struct ident_split ident;
620
	const char *signer_header;
621

622
	switch (sigc->payload_type) {
623
	case SIGNATURE_PAYLOAD_COMMIT:
624
		signer_header = "committer";
625
		break;
626
	case SIGNATURE_PAYLOAD_TAG:
627
		signer_header = "tagger";
628
		break;
629
	case SIGNATURE_PAYLOAD_UNDEFINED:
630
	case SIGNATURE_PAYLOAD_PUSH_CERT:
631
		/* Ignore payloads we don't want to parse */
632
		return 0;
633
	default:
634
		BUG("invalid value for sigc->payload_type");
635
	}
636

637
	ident_line = find_commit_header(sigc->payload, signer_header, &ident_len);
638
	if (!ident_line || !ident_len)
639
		return 1;
640

641
	if (split_ident_line(&ident, ident_line, ident_len))
642
		return 1;
643

644
	if (!sigc->payload_timestamp && ident.date_begin && ident.date_end)
645
		sigc->payload_timestamp = parse_timestamp(ident.date_begin, NULL, 10);
646

647
	return 0;
648
}
649

650
int check_signature(struct signature_check *sigc,
651
		    const char *signature, size_t slen)
652
{
653
	struct gpg_format *fmt;
654
	int status;
655

656
	gpg_interface_lazy_init();
657

658
	sigc->result = 'N';
659
	sigc->trust_level = TRUST_UNDEFINED;
660

661
	fmt = get_format_by_sig(signature);
662
	if (!fmt)
663
		die(_("bad/incompatible signature '%s'"), signature);
664

665
	if (parse_payload_metadata(sigc))
666
		return 1;
667

668
	status = fmt->verify_signed_buffer(sigc, fmt, signature, slen);
669

670
	if (status && !sigc->output)
671
		return !!status;
672

673
	status |= sigc->result != 'G';
674
	status |= sigc->trust_level < configured_min_trust_level;
675

676
	return !!status;
677
}
678

679
void print_signature_buffer(const struct signature_check *sigc, unsigned flags)
680
{
681
	const char *output = flags & GPG_VERIFY_RAW ? sigc->gpg_status :
682
							    sigc->output;
683

684
	if (flags & GPG_VERIFY_VERBOSE && sigc->payload)
685
		fwrite(sigc->payload, 1, sigc->payload_len, stdout);
686

687
	if (output)
688
		fputs(output, stderr);
689
}
690

691
size_t parse_signed_buffer(const char *buf, size_t size)
692
{
693
	size_t len = 0;
694
	size_t match = size;
695
	while (len < size) {
696
		const char *eol;
697

698
		if (get_format_by_sig(buf + len))
699
			match = len;
700

701
		eol = memchr(buf + len, '\n', size - len);
702
		len += eol ? eol - (buf + len) + 1 : size - len;
703
	}
704
	return match;
705
}
706

707
int parse_signature(const char *buf, size_t size, struct strbuf *payload, struct strbuf *signature)
708
{
709
	size_t match = parse_signed_buffer(buf, size);
710
	if (match != size) {
711
		strbuf_add(payload, buf, match);
712
		remove_signature(payload);
713
		strbuf_add(signature, buf + match, size - match);
714
		return 1;
715
	}
716
	return 0;
717
}
718

719
void set_signing_key(const char *key)
720
{
721
	gpg_interface_lazy_init();
722

723
	free(configured_signing_key);
724
	configured_signing_key = xstrdup(key);
725
}
726

727
static int git_gpg_config(const char *var, const char *value,
728
			  const struct config_context *ctx UNUSED,
729
			  void *cb UNUSED)
730
{
731
	struct gpg_format *fmt = NULL;
732
	const char *fmtname = NULL;
733
	char *trust;
734
	int ret;
735

736
	if (!strcmp(var, "user.signingkey")) {
737
		if (!value)
738
			return config_error_nonbool(var);
739
		set_signing_key(value);
740
		return 0;
741
	}
742

743
	if (!strcmp(var, "gpg.format")) {
744
		if (!value)
745
			return config_error_nonbool(var);
746
		fmt = get_format_by_name(value);
747
		if (!fmt)
748
			return error(_("invalid value for '%s': '%s'"),
749
				     var, value);
750
		use_format = fmt;
751
		return 0;
752
	}
753

754
	if (!strcmp(var, "gpg.mintrustlevel")) {
755
		if (!value)
756
			return config_error_nonbool(var);
757

758
		trust = xstrdup_toupper(value);
759
		ret = parse_gpg_trust_level(trust, &configured_min_trust_level);
760
		free(trust);
761

762
		if (ret)
763
			return error(_("invalid value for '%s': '%s'"),
764
				     var, value);
765
		return 0;
766
	}
767

768
	if (!strcmp(var, "gpg.ssh.defaultkeycommand"))
769
		return git_config_string(&ssh_default_key_command, var, value);
770

771
	if (!strcmp(var, "gpg.ssh.allowedsignersfile"))
772
		return git_config_pathname(&ssh_allowed_signers, var, value);
773

774
	if (!strcmp(var, "gpg.ssh.revocationfile"))
775
		return git_config_pathname(&ssh_revocation_file, var, value);
776

777
	if (!strcmp(var, "gpg.program") || !strcmp(var, "gpg.openpgp.program"))
778
		fmtname = "openpgp";
779

780
	if (!strcmp(var, "gpg.x509.program"))
781
		fmtname = "x509";
782

783
	if (!strcmp(var, "gpg.ssh.program"))
784
		fmtname = "ssh";
785

786
	if (fmtname) {
787
		fmt = get_format_by_name(fmtname);
788
		return git_config_string((char **) &fmt->program, var, value);
789
	}
790

791
	return 0;
792
}
793

794
/*
795
 * Returns 1 if `string` contains a literal ssh key, 0 otherwise
796
 * `key` will be set to the start of the actual key if a prefix is present.
797
 */
798
static int is_literal_ssh_key(const char *string, const char **key)
799
{
800
	if (skip_prefix(string, "key::", key))
801
		return 1;
802
	if (starts_with(string, "ssh-")) {
803
		*key = string;
804
		return 1;
805
	}
806
	return 0;
807
}
808

809
static char *get_ssh_key_fingerprint(const char *signing_key)
810
{
811
	struct child_process ssh_keygen = CHILD_PROCESS_INIT;
812
	int ret = -1;
813
	struct strbuf fingerprint_stdout = STRBUF_INIT;
814
	struct strbuf **fingerprint;
815
	char *fingerprint_ret;
816
	const char *literal_key = NULL;
817

818
	/*
819
	 * With SSH Signing this can contain a filename or a public key
820
	 * For textual representation we usually want a fingerprint
821
	 */
822
	if (is_literal_ssh_key(signing_key, &literal_key)) {
823
		strvec_pushl(&ssh_keygen.args, "ssh-keygen", "-lf", "-", NULL);
824
		ret = pipe_command(&ssh_keygen, literal_key,
825
				   strlen(literal_key), &fingerprint_stdout, 0,
826
				   NULL, 0);
827
	} else {
828
		strvec_pushl(&ssh_keygen.args, "ssh-keygen", "-lf",
829
			     configured_signing_key, NULL);
830
		ret = pipe_command(&ssh_keygen, NULL, 0, &fingerprint_stdout, 0,
831
				   NULL, 0);
832
	}
833

834
	if (!!ret)
835
		die_errno(_("failed to get the ssh fingerprint for key '%s'"),
836
			  signing_key);
837

838
	fingerprint = strbuf_split_max(&fingerprint_stdout, ' ', 3);
839
	if (!fingerprint[1])
840
		die_errno(_("failed to get the ssh fingerprint for key '%s'"),
841
			  signing_key);
842

843
	fingerprint_ret = strbuf_detach(fingerprint[1], NULL);
844
	strbuf_list_free(fingerprint);
845
	strbuf_release(&fingerprint_stdout);
846
	return fingerprint_ret;
847
}
848

849
/* Returns the first public key from an ssh-agent to use for signing */
850
static const char *get_default_ssh_signing_key(void)
851
{
852
	struct child_process ssh_default_key = CHILD_PROCESS_INIT;
853
	int ret = -1;
854
	struct strbuf key_stdout = STRBUF_INIT, key_stderr = STRBUF_INIT;
855
	struct strbuf **keys;
856
	char *key_command = NULL;
857
	const char **argv;
858
	int n;
859
	char *default_key = NULL;
860
	const char *literal_key = NULL;
861

862
	if (!ssh_default_key_command)
863
		die(_("either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"));
864

865
	key_command = xstrdup(ssh_default_key_command);
866
	n = split_cmdline(key_command, &argv);
867

868
	if (n < 0)
869
		die("malformed build-time gpg.ssh.defaultKeyCommand: %s",
870
		    split_cmdline_strerror(n));
871

872
	strvec_pushv(&ssh_default_key.args, argv);
873
	ret = pipe_command(&ssh_default_key, NULL, 0, &key_stdout, 0,
874
			   &key_stderr, 0);
875

876
	if (!ret) {
877
		keys = strbuf_split_max(&key_stdout, '\n', 2);
878
		if (keys[0] && is_literal_ssh_key(keys[0]->buf, &literal_key)) {
879
			/*
880
			 * We only use `is_literal_ssh_key` here to check validity
881
			 * The prefix will be stripped when the key is used.
882
			 */
883
			default_key = strbuf_detach(keys[0], NULL);
884
		} else {
885
			warning(_("gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"),
886
				key_stderr.buf, key_stdout.buf);
887
		}
888

889
		strbuf_list_free(keys);
890
	} else {
891
		warning(_("gpg.ssh.defaultKeyCommand failed: %s %s"),
892
			key_stderr.buf, key_stdout.buf);
893
	}
894

895
	free(key_command);
896
	free(argv);
897
	strbuf_release(&key_stdout);
898

899
	return default_key;
900
}
901

902
static const char *get_ssh_key_id(void) {
903
	return get_ssh_key_fingerprint(get_signing_key());
904
}
905

906
/* Returns a textual but unique representation of the signing key */
907
const char *get_signing_key_id(void)
908
{
909
	gpg_interface_lazy_init();
910

911
	if (use_format->get_key_id) {
912
		return use_format->get_key_id();
913
	}
914

915
	/* GPG/GPGSM only store a key id on this variable */
916
	return get_signing_key();
917
}
918

919
const char *get_signing_key(void)
920
{
921
	gpg_interface_lazy_init();
922

923
	if (configured_signing_key)
924
		return configured_signing_key;
925
	if (use_format->get_default_key) {
926
		return use_format->get_default_key();
927
	}
928

929
	return git_committer_info(IDENT_STRICT | IDENT_NO_DATE);
930
}
931

932
const char *gpg_trust_level_to_str(enum signature_trust_level level)
933
{
934
	struct sigcheck_gpg_trust_level *trust;
935

936
	if (level < 0 || level >= ARRAY_SIZE(sigcheck_gpg_trust_level))
937
		BUG("invalid trust level requested %d", level);
938

939
	trust = &sigcheck_gpg_trust_level[level];
940
	if (trust->value != level)
941
		BUG("sigcheck_gpg_trust_level[] unsorted");
942

943
	return sigcheck_gpg_trust_level[level].display_key;
944
}
945

946
int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key)
947
{
948
	gpg_interface_lazy_init();
949

950
	return use_format->sign_buffer(buffer, signature, signing_key);
951
}
952

953
/*
954
 * Strip CR from the line endings, in case we are on Windows.
955
 * NEEDSWORK: make it trim only CRs before LFs and rename
956
 */
957
static void remove_cr_after(struct strbuf *buffer, size_t offset)
958
{
959
	size_t i, j;
960

961
	for (i = j = offset; i < buffer->len; i++) {
962
		if (buffer->buf[i] != '\r') {
963
			if (i != j)
964
				buffer->buf[j] = buffer->buf[i];
965
			j++;
966
		}
967
	}
968
	strbuf_setlen(buffer, j);
969
}
970

971
static int sign_buffer_gpg(struct strbuf *buffer, struct strbuf *signature,
972
			  const char *signing_key)
973
{
974
	struct child_process gpg = CHILD_PROCESS_INIT;
975
	int ret;
976
	size_t bottom;
977
	const char *cp;
978
	struct strbuf gpg_status = STRBUF_INIT;
979

980
	strvec_pushl(&gpg.args,
981
		     use_format->program,
982
		     "--status-fd=2",
983
		     "-bsau", signing_key,
984
		     NULL);
985

986
	bottom = signature->len;
987

988
	/*
989
	 * When the username signingkey is bad, program could be terminated
990
	 * because gpg exits without reading and then write gets SIGPIPE.
991
	 */
992
	sigchain_push(SIGPIPE, SIG_IGN);
993
	ret = pipe_command(&gpg, buffer->buf, buffer->len,
994
			   signature, 1024, &gpg_status, 0);
995
	sigchain_pop(SIGPIPE);
996

997
	for (cp = gpg_status.buf;
998
	     cp && (cp = strstr(cp, "[GNUPG:] SIG_CREATED "));
999
	     cp++) {
1000
		if (cp == gpg_status.buf || cp[-1] == '\n')
1001
			break; /* found */
1002
	}
1003
	ret |= !cp;
1004
	if (ret) {
1005
		error(_("gpg failed to sign the data:\n%s"),
1006
		      gpg_status.len ? gpg_status.buf : "(no gpg output)");
1007
		strbuf_release(&gpg_status);
1008
		return -1;
1009
	}
1010
	strbuf_release(&gpg_status);
1011

1012
	/* Strip CR from the line endings, in case we are on Windows. */
1013
	remove_cr_after(signature, bottom);
1014

1015
	return 0;
1016
}
1017

1018
static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
1019
			   const char *signing_key)
1020
{
1021
	struct child_process signer = CHILD_PROCESS_INIT;
1022
	int ret = -1;
1023
	size_t bottom, keylen;
1024
	struct strbuf signer_stderr = STRBUF_INIT;
1025
	struct tempfile *key_file = NULL, *buffer_file = NULL;
1026
	char *ssh_signing_key_file = NULL;
1027
	struct strbuf ssh_signature_filename = STRBUF_INIT;
1028
	const char *literal_key = NULL;
1029
	int literal_ssh_key = 0;
1030

1031
	if (!signing_key || signing_key[0] == '\0')
1032
		return error(
1033
			_("user.signingKey needs to be set for ssh signing"));
1034

1035
	if (is_literal_ssh_key(signing_key, &literal_key)) {
1036
		/* A literal ssh key */
1037
		literal_ssh_key = 1;
1038
		key_file = mks_tempfile_t(".git_signing_key_tmpXXXXXX");
1039
		if (!key_file)
1040
			return error_errno(
1041
				_("could not create temporary file"));
1042
		keylen = strlen(literal_key);
1043
		if (write_in_full(key_file->fd, literal_key, keylen) < 0 ||
1044
		    close_tempfile_gently(key_file) < 0) {
1045
			error_errno(_("failed writing ssh signing key to '%s'"),
1046
				    key_file->filename.buf);
1047
			goto out;
1048
		}
1049
		ssh_signing_key_file = strbuf_detach(&key_file->filename, NULL);
1050
	} else {
1051
		/* We assume a file */
1052
		ssh_signing_key_file = interpolate_path(signing_key, 1);
1053
	}
1054

1055
	buffer_file = mks_tempfile_t(".git_signing_buffer_tmpXXXXXX");
1056
	if (!buffer_file) {
1057
		error_errno(_("could not create temporary file"));
1058
		goto out;
1059
	}
1060

1061
	if (write_in_full(buffer_file->fd, buffer->buf, buffer->len) < 0 ||
1062
	    close_tempfile_gently(buffer_file) < 0) {
1063
		error_errno(_("failed writing ssh signing key buffer to '%s'"),
1064
			    buffer_file->filename.buf);
1065
		goto out;
1066
	}
1067

1068
	strvec_pushl(&signer.args, use_format->program,
1069
		     "-Y", "sign",
1070
		     "-n", "git",
1071
		     "-f", ssh_signing_key_file,
1072
		     NULL);
1073
	if (literal_ssh_key)
1074
		strvec_push(&signer.args, "-U");
1075
	strvec_push(&signer.args, buffer_file->filename.buf);
1076

1077
	sigchain_push(SIGPIPE, SIG_IGN);
1078
	ret = pipe_command(&signer, NULL, 0, NULL, 0, &signer_stderr, 0);
1079
	sigchain_pop(SIGPIPE);
1080

1081
	if (ret) {
1082
		if (strstr(signer_stderr.buf, "usage:"))
1083
			error(_("ssh-keygen -Y sign is needed for ssh signing (available in openssh version 8.2p1+)"));
1084

1085
		ret = error("%s", signer_stderr.buf);
1086
		goto out;
1087
	}
1088

1089
	bottom = signature->len;
1090

1091
	strbuf_addbuf(&ssh_signature_filename, &buffer_file->filename);
1092
	strbuf_addstr(&ssh_signature_filename, ".sig");
1093
	if (strbuf_read_file(signature, ssh_signature_filename.buf, 0) < 0) {
1094
		ret = error_errno(
1095
			_("failed reading ssh signing data buffer from '%s'"),
1096
			ssh_signature_filename.buf);
1097
		goto out;
1098
	}
1099
	/* Strip CR from the line endings, in case we are on Windows. */
1100
	remove_cr_after(signature, bottom);
1101

1102
out:
1103
	if (key_file)
1104
		delete_tempfile(&key_file);
1105
	if (buffer_file)
1106
		delete_tempfile(&buffer_file);
1107
	if (ssh_signature_filename.len)
1108
		unlink_or_warn(ssh_signature_filename.buf);
1109
	strbuf_release(&signer_stderr);
1110
	strbuf_release(&ssh_signature_filename);
1111
	FREE_AND_NULL(ssh_signing_key_file);
1112
	return ret;
1113
}
1114

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.