@@ -75,48 +75,80 @@ void signature_check_clear(struct signature_check *sigc)
75
75
FREE_AND_NULL (sigc -> key );
76
76
}
77
77
78
+ /* An exclusive status -- only one of them can appear in output */
79
+ #define GPG_STATUS_EXCLUSIVE (1<<0)
80
+
78
81
static struct {
79
82
char result ;
80
83
const char * check ;
84
+ unsigned int flags ;
81
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 },
90
94
};
91
95
92
96
static void parse_gpg_output (struct signature_check * sigc )
93
97
{
94
98
const char * buf = sigc -> gpg_status ;
99
+ const char * line , * next ;
95
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 ++ )
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 ;
117
135
}
118
136
}
119
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 );
120
152
}
121
153
122
154
int check_signature (const char * payload , size_t plen , const char * signature ,
0 commit comments