From: Junio C Hamano Date: Fri, 2 Nov 2018 15:53:57 +0000 (+0900) Subject: Merge branch 'mg/gpg-parse-tighten' X-Git-Tag: v2.20.0-rc0~79 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/02561896de9d4cd2354e825bf7e6304a3c19d1c3?ds=inline;hp=--cc Merge branch 'mg/gpg-parse-tighten' Detect and reject a signature block that has more than one GPG signature. * mg/gpg-parse-tighten: gpg-interface.c: detect and reject multiple signatures on commits --- 02561896de9d4cd2354e825bf7e6304a3c19d1c3 diff --cc gpg-interface.c index db17d65f8a,efe2c0d386..d72a43b774 --- a/gpg-interface.c +++ b/gpg-interface.c @@@ -92,28 -96,42 +96,42 @@@ static struct static void parse_gpg_output(struct signature_check *sigc) { const char *buf = sigc->gpg_status; + const char *line, *next; int i; - - /* Iterate over all search strings */ - for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) { - const char *found, *next; - - if (!skip_prefix(buf, sigcheck_gpg_status[i].check + 1, &found)) { - found = strstr(buf, sigcheck_gpg_status[i].check); - if (!found) - continue; - found += strlen(sigcheck_gpg_status[i].check); - } - sigc->result = sigcheck_gpg_status[i].result; - /* The trust messages are not followed by key/signer information */ - if (sigc->result != 'U') { - next = strchrnul(found, ' '); - sigc->key = xmemdupz(found, next - found); - /* The ERRSIG message is not followed by signer information */ - if (*next && sigc-> result != 'E') { - found = next + 1; - next = strchrnul(found, '\n'); - sigc->signer = xmemdupz(found, next - found); + int seen_exclusive_status = 0; + + /* Iterate over all lines */ + for (line = buf; *line; line = strchrnul(line+1, '\n')) { + while (*line == '\n') + line++; + /* Skip lines that don't start with GNUPG status */ + if (!skip_prefix(line, "[GNUPG:] ", &line)) + continue; + + /* Iterate over all search strings */ + for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) { + if (skip_prefix(line, sigcheck_gpg_status[i].check, &line)) { + if (sigcheck_gpg_status[i].flags & GPG_STATUS_EXCLUSIVE) { - if (++seen_exclusive_status > 1) ++ if (seen_exclusive_status++) + goto found_duplicate_status; + } + + sigc->result = sigcheck_gpg_status[i].result; + /* The trust messages are not followed by key/signer information */ + if (sigc->result != 'U') { + next = strchrnul(line, ' '); + free(sigc->key); + sigc->key = xmemdupz(line, next - line); + /* The ERRSIG message is not followed by signer information */ + if (*next && sigc->result != 'E') { + line = next + 1; + next = strchrnul(line, '\n'); + free(sigc->signer); + sigc->signer = xmemdupz(line, next - line); + } + } + + break; } } }