75
FREE_AND_NULL(sigc->key);
76
}
77
78
+/* An exclusive status -- only one of them can appear in output */
79
+#define GPG_STATUS_EXCLUSIVE (1<<0)
80
+
81
static struct {
82
char result;
83
const char *check;
84
+ unsigned int flags;
85
} sigcheck_gpg_status[] = {
82
- { 'G', "\n[GNUPG:] GOODSIG " },
83
- { 'B', "\n[GNUPG:] BADSIG " },
84
- { 'U', "\n[GNUPG:] TRUST_NEVER" },
85
- { 'U', "\n[GNUPG:] TRUST_UNDEFINED" },
86
- { 'E', "\n[GNUPG:] ERRSIG "},
87
- { 'X', "\n[GNUPG:] EXPSIG "},
88
- { 'Y', "\n[GNUPG:] EXPKEYSIG "},
89
- { 'R', "\n[GNUPG:] REVKEYSIG "},
86
+ { 'G', "GOODSIG ", GPG_STATUS_EXCLUSIVE },
87
+ { 'B', "BADSIG ", GPG_STATUS_EXCLUSIVE },
88
+ { 'U', "TRUST_NEVER", 0 },
89
+ { 'U', "TRUST_UNDEFINED", 0 },
90
+ { 'E', "ERRSIG ", GPG_STATUS_EXCLUSIVE },
91
+ { 'X', "EXPSIG ", GPG_STATUS_EXCLUSIVE },
92
+ { 'Y', "EXPKEYSIG ", GPG_STATUS_EXCLUSIVE },
93
+ { 'R', "REVKEYSIG ", GPG_STATUS_EXCLUSIVE },
94
};
95
96
static void parse_gpg_output(struct signature_check *sigc)
97
{
98
const char *buf = sigc->gpg_status;
99
+ const char *line, *next;
100
int i;
96
-
97
- /* Iterate over all search strings */
98
- for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) {
99
- const char *found, *next;
100
-
101
- if (!skip_prefix(buf, sigcheck_gpg_status[i].check + 1, &found)) {
102
- found = strstr(buf, sigcheck_gpg_status[i].check);
103
- if (!found)
104
- continue;
105
- found += strlen(sigcheck_gpg_status[i].check);
106
- }
107
- sigc->result = sigcheck_gpg_status[i].result;
108
- /* The trust messages are not followed by key/signer information */
109
- if (sigc->result != 'U') {
110
- next = strchrnul(found, ' ');
111
- sigc->key = xmemdupz(found, next - found);
112
- /* The ERRSIG message is not followed by signer information */
113
- if (*next && sigc-> result != 'E') {
114
- found = next + 1;
115
- next = strchrnul(found, '\n');
116
- sigc->signer = xmemdupz(found, next - found);
101
+ int seen_exclusive_status = 0;
102
+
103
+ /* Iterate over all lines */
104
+ for (line = buf; *line; line = strchrnul(line+1, '\n')) {
105
+ while (*line == '\n')
106
+ line++;
107
+ /* Skip lines that don't start with GNUPG status */
108
+ if (!skip_prefix(line, "[GNUPG:] ", &line))
109
+ continue;
110
+
111
+ /* Iterate over all search strings */
112
+ for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) {
113
+ if (skip_prefix(line, sigcheck_gpg_status[i].check, &line)) {
114
+ if (sigcheck_gpg_status[i].flags & GPG_STATUS_EXCLUSIVE) {
115
+ if (++seen_exclusive_status > 1)
116
+ goto found_duplicate_status;
117
+ }
118
+
119
+ sigc->result = sigcheck_gpg_status[i].result;
120
+ /* The trust messages are not followed by key/signer information */
121
+ if (sigc->result != 'U') {
122
+ next = strchrnul(line, ' ');
123
+ free(sigc->key);
124
+ sigc->key = xmemdupz(line, next - line);
125
+ /* The ERRSIG message is not followed by signer information */
126
+ if (*next && sigc->result != 'E') {
127
+ line = next + 1;
128
+ next = strchrnul(line, '\n');
129
+ free(sigc->signer);
130
+ sigc->signer = xmemdupz(line, next - line);
131
+ }
132
+ }
133
+
134
+ break;
135
}
136
}
137
}
138
+ return;
139
+
140
+found_duplicate_status:
141
+ /*
142
+ * GOODSIG, BADSIG etc. can occur only once for each signature.
143
+ * Therefore, if we had more than one then we're dealing with multiple
144
+ * signatures. We don't support them currently, and they're rather
145
+ * hard to create, so something is likely fishy and we should reject
146
+ * them altogether.
147
+ */
148
+ sigc->result = 'E';
149
+ /* Clear partial data to avoid confusion */
150
+ FREE_AND_NULL(sigc->signer);
151
+ FREE_AND_NULL(sigc->key);
152
}
153
154
int check_signature(const char *payload, size_t plen, const char *signature,