gpg-interface: improve interface for parsing tags
We have a function which parses a buffer with a signature at the end, parse_signature, and this function is used for signed tags. However, we'll need to store values for multiple algorithms, and we'll do this by using a header for the non-default algorithm. Adjust the parse_signature interface to store the parsed data in two strbufs and turn the existing function into parse_signed_buffer. The latter is still used in places where we know we always have a signed buffer, such as push certs. Adjust all the callers to deal with this new interface. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									1fb5cf0da6
								
							
						
					
					
						commit
						482c119186
					
				|  | @ -764,7 +764,7 @@ static void prepare_push_cert_sha1(struct child_process *proc) | ||||||
|  |  | ||||||
| 		memset(&sigcheck, '\0', sizeof(sigcheck)); | 		memset(&sigcheck, '\0', sizeof(sigcheck)); | ||||||
|  |  | ||||||
| 		bogs = parse_signature(push_cert.buf, push_cert.len); | 		bogs = parse_signed_buffer(push_cert.buf, push_cert.len); | ||||||
| 		check_signature(push_cert.buf, bogs, push_cert.buf + bogs, | 		check_signature(push_cert.buf, bogs, push_cert.buf + bogs, | ||||||
| 				push_cert.len - bogs, &sigcheck); | 				push_cert.len - bogs, &sigcheck); | ||||||
|  |  | ||||||
|  | @ -2050,7 +2050,7 @@ static void queue_commands_from_cert(struct command **tail, | ||||||
| 		die("malformed push certificate %.*s", 100, push_cert->buf); | 		die("malformed push certificate %.*s", 100, push_cert->buf); | ||||||
| 	else | 	else | ||||||
| 		boc += 2; | 		boc += 2; | ||||||
| 	eoc = push_cert->buf + parse_signature(push_cert->buf, push_cert->len); | 	eoc = push_cert->buf + parse_signed_buffer(push_cert->buf, push_cert->len); | ||||||
|  |  | ||||||
| 	while (boc < eoc) { | 	while (boc < eoc) { | ||||||
| 		const char *eol = memchr(boc, '\n', eoc - boc); | 		const char *eol = memchr(boc, '\n', eoc - boc); | ||||||
|  |  | ||||||
|  | @ -174,11 +174,17 @@ static void write_tag_body(int fd, const struct object_id *oid) | ||||||
| { | { | ||||||
| 	unsigned long size; | 	unsigned long size; | ||||||
| 	enum object_type type; | 	enum object_type type; | ||||||
| 	char *buf, *sp; | 	char *buf, *sp, *orig; | ||||||
|  | 	struct strbuf payload = STRBUF_INIT; | ||||||
|  | 	struct strbuf signature = STRBUF_INIT; | ||||||
|  |  | ||||||
| 	buf = read_object_file(oid, &type, &size); | 	orig = buf = read_object_file(oid, &type, &size); | ||||||
| 	if (!buf) | 	if (!buf) | ||||||
| 		return; | 		return; | ||||||
|  | 	if (parse_signature(buf, size, &payload, &signature)) { | ||||||
|  | 		buf = payload.buf; | ||||||
|  | 		size = payload.len; | ||||||
|  | 	} | ||||||
| 	/* skip header */ | 	/* skip header */ | ||||||
| 	sp = strstr(buf, "\n\n"); | 	sp = strstr(buf, "\n\n"); | ||||||
|  |  | ||||||
|  | @ -187,9 +193,11 @@ static void write_tag_body(int fd, const struct object_id *oid) | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	sp += 2; /* skip the 2 LFs */ | 	sp += 2; /* skip the 2 LFs */ | ||||||
| 	write_or_die(fd, sp, parse_signature(sp, buf + size - sp)); | 	write_or_die(fd, sp, buf + size - sp); | ||||||
|  |  | ||||||
| 	free(buf); | 	free(orig); | ||||||
|  | 	strbuf_release(&payload); | ||||||
|  | 	strbuf_release(&signature); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int build_tag_object(struct strbuf *buf, int sign, struct object_id *result) | static int build_tag_object(struct strbuf *buf, int sign, struct object_id *result) | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								commit.c
								
								
								
								
							
							
						
						
									
										9
									
								
								commit.c
								
								
								
								
							|  | @ -1136,8 +1136,10 @@ static void handle_signed_tag(struct commit *parent, struct commit_extra_header | ||||||
| 	struct merge_remote_desc *desc; | 	struct merge_remote_desc *desc; | ||||||
| 	struct commit_extra_header *mergetag; | 	struct commit_extra_header *mergetag; | ||||||
| 	char *buf; | 	char *buf; | ||||||
| 	unsigned long size, len; | 	unsigned long size; | ||||||
| 	enum object_type type; | 	enum object_type type; | ||||||
|  | 	struct strbuf payload = STRBUF_INIT; | ||||||
|  | 	struct strbuf signature = STRBUF_INIT; | ||||||
|  |  | ||||||
| 	desc = merge_remote_util(parent); | 	desc = merge_remote_util(parent); | ||||||
| 	if (!desc || !desc->obj) | 	if (!desc || !desc->obj) | ||||||
|  | @ -1145,8 +1147,7 @@ static void handle_signed_tag(struct commit *parent, struct commit_extra_header | ||||||
| 	buf = read_object_file(&desc->obj->oid, &type, &size); | 	buf = read_object_file(&desc->obj->oid, &type, &size); | ||||||
| 	if (!buf || type != OBJ_TAG) | 	if (!buf || type != OBJ_TAG) | ||||||
| 		goto free_return; | 		goto free_return; | ||||||
| 	len = parse_signature(buf, size); | 	if (!parse_signature(buf, size, &payload, &signature)) | ||||||
| 	if (size == len) |  | ||||||
| 		goto free_return; | 		goto free_return; | ||||||
| 	/* | 	/* | ||||||
| 	 * We could verify this signature and either omit the tag when | 	 * We could verify this signature and either omit the tag when | ||||||
|  | @ -1165,6 +1166,8 @@ static void handle_signed_tag(struct commit *parent, struct commit_extra_header | ||||||
|  |  | ||||||
| 	**tail = mergetag; | 	**tail = mergetag; | ||||||
| 	*tail = &mergetag->next; | 	*tail = &mergetag->next; | ||||||
|  | 	strbuf_release(&payload); | ||||||
|  | 	strbuf_release(&signature); | ||||||
| 	return; | 	return; | ||||||
|  |  | ||||||
| free_return: | free_return: | ||||||
|  |  | ||||||
|  | @ -509,22 +509,28 @@ static void fmt_merge_msg_sigs(struct strbuf *out) | ||||||
| 	for (i = 0; i < origins.nr; i++) { | 	for (i = 0; i < origins.nr; i++) { | ||||||
| 		struct object_id *oid = origins.items[i].util; | 		struct object_id *oid = origins.items[i].util; | ||||||
| 		enum object_type type; | 		enum object_type type; | ||||||
| 		unsigned long size, len; | 		unsigned long size; | ||||||
| 		char *buf = read_object_file(oid, &type, &size); | 		char *buf = read_object_file(oid, &type, &size); | ||||||
|  | 		char *origbuf = buf; | ||||||
|  | 		unsigned long len = size; | ||||||
| 		struct signature_check sigc = { NULL }; | 		struct signature_check sigc = { NULL }; | ||||||
| 		struct strbuf sig = STRBUF_INIT; | 		struct strbuf payload = STRBUF_INIT, sig = STRBUF_INIT; | ||||||
|  |  | ||||||
| 		if (!buf || type != OBJ_TAG) | 		if (!buf || type != OBJ_TAG) | ||||||
| 			goto next; | 			goto next; | ||||||
| 		len = parse_signature(buf, size); |  | ||||||
|  |  | ||||||
| 		if (size == len) | 		if (!parse_signature(buf, size, &payload, &sig)) | ||||||
| 			; /* merely annotated */ | 			;/* merely annotated */ | ||||||
| 		else if (check_signature(buf, len, buf + len, size - len, &sigc) && | 		else { | ||||||
| 			!sigc.gpg_output) | 			buf = payload.buf; | ||||||
| 			strbuf_addstr(&sig, "gpg verification failed.\n"); | 			len = payload.len; | ||||||
| 		else | 			if (check_signature(payload.buf, payload.len, sig.buf, | ||||||
| 			strbuf_addstr(&sig, sigc.gpg_output); | 					 sig.len, &sigc) && | ||||||
|  | 				!sigc.gpg_output) | ||||||
|  | 				strbuf_addstr(&sig, "gpg verification failed.\n"); | ||||||
|  | 			else | ||||||
|  | 				strbuf_addstr(&sig, sigc.gpg_output); | ||||||
|  | 		} | ||||||
| 		signature_check_clear(&sigc); | 		signature_check_clear(&sigc); | ||||||
|  |  | ||||||
| 		if (!tag_number++) { | 		if (!tag_number++) { | ||||||
|  | @ -547,9 +553,10 @@ static void fmt_merge_msg_sigs(struct strbuf *out) | ||||||
| 					strlen(origins.items[i].string)); | 					strlen(origins.items[i].string)); | ||||||
| 			fmt_tag_signature(&tagbuf, &sig, buf, len); | 			fmt_tag_signature(&tagbuf, &sig, buf, len); | ||||||
| 		} | 		} | ||||||
|  | 		strbuf_release(&payload); | ||||||
| 		strbuf_release(&sig); | 		strbuf_release(&sig); | ||||||
| 	next: | 	next: | ||||||
| 		free(buf); | 		free(origbuf); | ||||||
| 	} | 	} | ||||||
| 	if (tagbuf.len) { | 	if (tagbuf.len) { | ||||||
| 		strbuf_addch(out, '\n'); | 		strbuf_addch(out, '\n'); | ||||||
|  |  | ||||||
|  | @ -345,7 +345,7 @@ void print_signature_buffer(const struct signature_check *sigc, unsigned flags) | ||||||
| 		fputs(output, stderr); | 		fputs(output, stderr); | ||||||
| } | } | ||||||
|  |  | ||||||
| size_t parse_signature(const char *buf, size_t size) | size_t parse_signed_buffer(const char *buf, size_t size) | ||||||
| { | { | ||||||
| 	size_t len = 0; | 	size_t len = 0; | ||||||
| 	size_t match = size; | 	size_t match = size; | ||||||
|  | @ -361,6 +361,17 @@ size_t parse_signature(const char *buf, size_t size) | ||||||
| 	return match; | 	return match; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int parse_signature(const char *buf, size_t size, struct strbuf *payload, struct strbuf *signature) | ||||||
|  | { | ||||||
|  | 	size_t match = parse_signed_buffer(buf, size); | ||||||
|  | 	if (match != size) { | ||||||
|  | 		strbuf_add(payload, buf, match); | ||||||
|  | 		strbuf_add(signature, buf + match, size - match); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| void set_signing_key(const char *key) | void set_signing_key(const char *key) | ||||||
| { | { | ||||||
| 	free(configured_signing_key); | 	free(configured_signing_key); | ||||||
|  |  | ||||||
|  | @ -37,13 +37,20 @@ struct signature_check { | ||||||
|  |  | ||||||
| void signature_check_clear(struct signature_check *sigc); | void signature_check_clear(struct signature_check *sigc); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Look at a GPG signed tag object.  If such a signature exists, store it in | ||||||
|  |  * signature and the signed content in payload.  Return 1 if a signature was | ||||||
|  |  * found, and 0 otherwise. | ||||||
|  |  */ | ||||||
|  | int parse_signature(const char *buf, size_t size, struct strbuf *payload, struct strbuf *signature); | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Look at GPG signed content (e.g. a signed tag object), whose |  * Look at GPG signed content (e.g. a signed tag object), whose | ||||||
|  * payload is followed by a detached signature on it.  Return the |  * payload is followed by a detached signature on it.  Return the | ||||||
|  * offset where the embedded detached signature begins, or the end of |  * offset where the embedded detached signature begins, or the end of | ||||||
|  * the data when there is no such signature. |  * the data when there is no such signature. | ||||||
|  */ |  */ | ||||||
| size_t parse_signature(const char *buf, size_t size); | size_t parse_signed_buffer(const char *buf, size_t size); | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Create a detached signature for the contents of "buffer" and append |  * Create a detached signature for the contents of "buffer" and append | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								log-tree.c
								
								
								
								
							
							
						
						
									
										13
									
								
								log-tree.c
								
								
								
								
							|  | @ -548,7 +548,8 @@ static int show_one_mergetag(struct commit *commit, | ||||||
| 	struct strbuf verify_message; | 	struct strbuf verify_message; | ||||||
| 	struct signature_check sigc = { 0 }; | 	struct signature_check sigc = { 0 }; | ||||||
| 	int status, nth; | 	int status, nth; | ||||||
| 	size_t payload_size; | 	struct strbuf payload = STRBUF_INIT; | ||||||
|  | 	struct strbuf signature = STRBUF_INIT; | ||||||
|  |  | ||||||
| 	hash_object_file(the_hash_algo, extra->value, extra->len, | 	hash_object_file(the_hash_algo, extra->value, extra->len, | ||||||
| 			 type_name(OBJ_TAG), &oid); | 			 type_name(OBJ_TAG), &oid); | ||||||
|  | @ -571,13 +572,11 @@ static int show_one_mergetag(struct commit *commit, | ||||||
| 		strbuf_addf(&verify_message, | 		strbuf_addf(&verify_message, | ||||||
| 			    "parent #%d, tagged '%s'\n", nth + 1, tag->tag); | 			    "parent #%d, tagged '%s'\n", nth + 1, tag->tag); | ||||||
|  |  | ||||||
| 	payload_size = parse_signature(extra->value, extra->len); |  | ||||||
| 	status = -1; | 	status = -1; | ||||||
| 	if (extra->len > payload_size) { | 	if (parse_signature(extra->value, extra->len, &payload, &signature)) { | ||||||
| 		/* could have a good signature */ | 		/* could have a good signature */ | ||||||
| 		status = check_signature(extra->value, payload_size, | 		status = check_signature(payload.buf, payload.len, | ||||||
| 					 extra->value + payload_size, | 					 signature.buf, signature.len, &sigc); | ||||||
| 					 extra->len - payload_size, &sigc); |  | ||||||
| 		if (sigc.gpg_output) | 		if (sigc.gpg_output) | ||||||
| 			strbuf_addstr(&verify_message, sigc.gpg_output); | 			strbuf_addstr(&verify_message, sigc.gpg_output); | ||||||
| 		else | 		else | ||||||
|  | @ -588,6 +587,8 @@ static int show_one_mergetag(struct commit *commit, | ||||||
|  |  | ||||||
| 	show_sig_lines(opt, status, verify_message.buf); | 	show_sig_lines(opt, status, verify_message.buf); | ||||||
| 	strbuf_release(&verify_message); | 	strbuf_release(&verify_message); | ||||||
|  | 	strbuf_release(&payload); | ||||||
|  | 	strbuf_release(&signature); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								ref-filter.c
								
								
								
								
							
							
						
						
									
										18
									
								
								ref-filter.c
								
								
								
								
							|  | @ -1215,7 +1215,13 @@ static void find_subpos(const char *buf, | ||||||
| 			size_t *nonsiglen, | 			size_t *nonsiglen, | ||||||
| 			const char **sig, size_t *siglen) | 			const char **sig, size_t *siglen) | ||||||
| { | { | ||||||
|  | 	struct strbuf payload = STRBUF_INIT; | ||||||
|  | 	struct strbuf signature = STRBUF_INIT; | ||||||
| 	const char *eol; | 	const char *eol; | ||||||
|  | 	const char *end = buf + strlen(buf); | ||||||
|  | 	const char *sigstart; | ||||||
|  |  | ||||||
|  |  | ||||||
| 	/* skip past header until we hit empty line */ | 	/* skip past header until we hit empty line */ | ||||||
| 	while (*buf && *buf != '\n') { | 	while (*buf && *buf != '\n') { | ||||||
| 		eol = strchrnul(buf, '\n'); | 		eol = strchrnul(buf, '\n'); | ||||||
|  | @ -1228,14 +1234,15 @@ static void find_subpos(const char *buf, | ||||||
| 		buf++; | 		buf++; | ||||||
|  |  | ||||||
| 	/* parse signature first; we might not even have a subject line */ | 	/* parse signature first; we might not even have a subject line */ | ||||||
| 	*sig = buf + parse_signature(buf, strlen(buf)); | 	parse_signature(buf, end - buf, &payload, &signature); | ||||||
| 	*siglen = strlen(*sig); | 	*sig = strbuf_detach(&signature, siglen); | ||||||
|  | 	sigstart = buf + parse_signed_buffer(buf, strlen(buf)); | ||||||
|  |  | ||||||
| 	/* subject is first non-empty line */ | 	/* subject is first non-empty line */ | ||||||
| 	*sub = buf; | 	*sub = buf; | ||||||
| 	/* subject goes to first empty line before signature begins */ | 	/* subject goes to first empty line before signature begins */ | ||||||
| 	if ((eol = strstr(*sub, "\n\n"))) { | 	if ((eol = strstr(*sub, "\n\n"))) { | ||||||
| 		eol = eol < *sig ? eol : *sig; | 		eol = eol < sigstart ? eol : sigstart; | ||||||
| 	/* check if message uses CRLF */ | 	/* check if message uses CRLF */ | ||||||
| 	} else if (! (eol = strstr(*sub, "\r\n\r\n"))) { | 	} else if (! (eol = strstr(*sub, "\r\n\r\n"))) { | ||||||
| 		/* treat whole message as subject */ | 		/* treat whole message as subject */ | ||||||
|  | @ -1253,7 +1260,7 @@ static void find_subpos(const char *buf, | ||||||
| 		buf++; | 		buf++; | ||||||
| 	*body = buf; | 	*body = buf; | ||||||
| 	*bodylen = strlen(buf); | 	*bodylen = strlen(buf); | ||||||
| 	*nonsiglen = *sig - buf; | 	*nonsiglen = sigstart - buf; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  | @ -1291,6 +1298,7 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf) | ||||||
| 		struct used_atom *atom = &used_atom[i]; | 		struct used_atom *atom = &used_atom[i]; | ||||||
| 		const char *name = atom->name; | 		const char *name = atom->name; | ||||||
| 		struct atom_value *v = &val[i]; | 		struct atom_value *v = &val[i]; | ||||||
|  |  | ||||||
| 		if (!!deref != (*name == '*')) | 		if (!!deref != (*name == '*')) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (deref) | 		if (deref) | ||||||
|  | @ -1336,7 +1344,9 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf) | ||||||
| 			v->s = strbuf_detach(&s, NULL); | 			v->s = strbuf_detach(&s, NULL); | ||||||
| 		} else if (atom->u.contents.option == C_BARE) | 		} else if (atom->u.contents.option == C_BARE) | ||||||
| 			v->s = xstrdup(subpos); | 			v->s = xstrdup(subpos); | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  | 	free((void *)sigpos); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								tag.c
								
								
								
								
							
							
						
						
									
										15
									
								
								tag.c
								
								
								
								
							|  | @ -13,26 +13,27 @@ const char *tag_type = "tag"; | ||||||
| static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags) | static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags) | ||||||
| { | { | ||||||
| 	struct signature_check sigc; | 	struct signature_check sigc; | ||||||
| 	size_t payload_size; | 	struct strbuf payload = STRBUF_INIT; | ||||||
|  | 	struct strbuf signature = STRBUF_INIT; | ||||||
| 	int ret; | 	int ret; | ||||||
|  |  | ||||||
| 	memset(&sigc, 0, sizeof(sigc)); | 	memset(&sigc, 0, sizeof(sigc)); | ||||||
|  |  | ||||||
| 	payload_size = parse_signature(buf, size); | 	if (!parse_signature(buf, size, &payload, &signature)) { | ||||||
|  |  | ||||||
| 	if (size == payload_size) { |  | ||||||
| 		if (flags & GPG_VERIFY_VERBOSE) | 		if (flags & GPG_VERIFY_VERBOSE) | ||||||
| 			write_in_full(1, buf, payload_size); | 			write_in_full(1, buf, size); | ||||||
| 		return error("no signature found"); | 		return error("no signature found"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ret = check_signature(buf, payload_size, buf + payload_size, | 	ret = check_signature(payload.buf, payload.len, signature.buf, | ||||||
| 				size - payload_size, &sigc); | 				signature.len, &sigc); | ||||||
|  |  | ||||||
| 	if (!(flags & GPG_VERIFY_OMIT_STATUS)) | 	if (!(flags & GPG_VERIFY_OMIT_STATUS)) | ||||||
| 		print_signature_buffer(&sigc, flags); | 		print_signature_buffer(&sigc, flags); | ||||||
|  |  | ||||||
| 	signature_check_clear(&sigc); | 	signature_check_clear(&sigc); | ||||||
|  | 	strbuf_release(&payload); | ||||||
|  | 	strbuf_release(&signature); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 brian m. carlson
						brian m. carlson