@@ -132,7 +132,46 @@ static bool qubes_is_key_byte(unsigned char c) {
132
132
}
133
133
}
134
134
135
- int qubes_toml_config_parse (const char * config_full_path , int * wait_for_session , char * * user )
135
+ static void toml_invalid_type (enum toml_type ty , const char * file , size_t lineno , const char * msg )
136
+ {
137
+ const char * bad_type ;
138
+ switch (ty ) {
139
+ case TOML_TYPE_INVALID :
140
+ bad_type = "<invalid value>" ;
141
+ break ;
142
+ case TOML_TYPE_BOOL :
143
+ bad_type = "Boolean" ;
144
+ break ;
145
+ case TOML_TYPE_INTEGER :
146
+ bad_type = "Integer" ;
147
+ break ;
148
+ case TOML_TYPE_STRING :
149
+ bad_type = "String" ;
150
+ break ;
151
+ default :
152
+ abort ();
153
+ }
154
+ LOG (ERROR , "%s:%zu: %s not valid for %s" , file , lineno , bad_type , msg );
155
+ }
156
+
157
+ static bool toml_check_dup_key (bool * seen_already , const char * file , size_t lineno , const char * msg )
158
+ {
159
+ if (* seen_already ) {
160
+ LOG (ERROR , "%s:%zu: Key %s already seen" , file , lineno , msg );
161
+ return true;
162
+ }
163
+ * seen_already = true;
164
+ return false;
165
+ }
166
+
167
+ static void toml_value_free (union toml_data * value , enum toml_type ty ) {
168
+ if (ty == TOML_TYPE_STRING ) {
169
+ free (value -> string );
170
+ value -> string = NULL ;
171
+ }
172
+ }
173
+
174
+ int qubes_toml_config_parse (const char * config_full_path , bool * wait_for_session , char * * user )
136
175
{
137
176
int result = -1 ; /* assume problem */
138
177
FILE * config_file = fopen (config_full_path , "re" );
@@ -147,6 +186,21 @@ int qubes_toml_config_parse(const char *config_full_path, int *wait_for_session,
147
186
ssize_t signed_linelen ;
148
187
bool seen_wait_for_session = false;
149
188
bool seen_user = false;
189
+ * wait_for_session = 0 ;
190
+ #define CHECK_DUP_KEY (v ) do { \
191
+ if (toml_check_dup_key(&(v), config_full_path, lineno, current_line)) { \
192
+ toml_value_free(&value, ty); \
193
+ goto bad; \
194
+ } \
195
+ } while (0);
196
+ #define CHECK_TYPE (v , msg ) do { \
197
+ if ((v) != ty) { \
198
+ toml_invalid_type(v, config_full_path, lineno, msg); \
199
+ toml_value_free(&value, ty); \
200
+ goto bad; \
201
+ } \
202
+ } while (0);
203
+
150
204
while ((signed_linelen = getline (& current_line , & bufsize , config_file )) != -1 ) {
151
205
lineno ++ ;
152
206
/* Other negative values are invalid. If nothing at all is read that means EOF. */
@@ -218,55 +272,30 @@ int qubes_toml_config_parse(const char *config_full_path, int *wait_for_session,
218
272
current_line [key_len ] = '\0' ;
219
273
union toml_data value ;
220
274
enum toml_type ty = parse_toml_value (config_full_path , lineno , key_cursor , & value );
275
+ if (ty == TOML_TYPE_INVALID )
276
+ goto bad ;
221
277
222
278
if (strcmp (current_line , "wait-for-session" ) == 0 ) {
223
- if (seen_wait_for_session ) {
224
- LOG (ERROR , "%s:%zu: Key '%s' appears more than once" , config_full_path , lineno , current_line );
225
- goto bad ;
226
- }
227
- seen_wait_for_session = true;
228
- if (ty == TOML_TYPE_BOOL ) {
229
- * wait_for_session = (int )value .boolean ;
230
- continue ;
231
- } else if (ty == TOML_TYPE_INTEGER ) {
279
+ CHECK_DUP_KEY (seen_wait_for_session );
280
+ if (ty == TOML_TYPE_INTEGER ) {
232
281
if (value .integer < 2 ) {
233
282
* wait_for_session = (int )value .integer ;
234
283
continue ;
235
284
}
236
- LOG (ERROR , "Integer value %llu used when a boolean was expected" , value .integer );
237
- } else if (ty == TOML_TYPE_STRING ) {
238
- LOG (ERROR , "String value '%s' not valid for 'wait-for-session'" , value .string );
239
- free (value .string );
240
- value .string = NULL ;
241
- }
242
- } else if (strcmp (current_line , "force-user" ) == 0 ) {
243
- if (seen_user ) {
244
- LOG (ERROR , "%s:%zu: Key '%s' appears more than once" , config_full_path , lineno , current_line );
245
- goto bad ;
246
- }
247
- seen_user = true;
248
- char * bad_type ;
249
- switch (ty ) {
250
- case TOML_TYPE_INVALID :
285
+ LOG (ERROR , "%s:%zu: Unsupported integer value %llu for boolean" , config_full_path , lineno , value .integer );
251
286
goto bad ;
252
- case TOML_TYPE_BOOL :
253
- bad_type = "Boolean" ;
254
- break ;
255
- case TOML_TYPE_INTEGER :
256
- bad_type = "Integer" ;
257
- break ;
258
- case TOML_TYPE_STRING :
259
- * user = value .string ;
260
- continue ;
261
- default :
262
- abort ();
287
+ } else {
288
+ CHECK_TYPE (TOML_TYPE_BOOL , "wait-for-session" );
289
+ * wait_for_session = value .boolean ;
263
290
}
264
- LOG (ERROR , "%s:%zu: %s not valid for user name or user ID" , config_full_path , lineno , bad_type );
291
+ } else if (strcmp (current_line , "force-user" ) == 0 ) {
292
+ CHECK_DUP_KEY (seen_user );
293
+ CHECK_TYPE (TOML_TYPE_STRING , "user name or user ID" );
294
+ * user = value .string ;
265
295
} else {
266
296
LOG (ERROR , "%s:%zu: Unsupported key %s" , config_full_path , lineno , current_line );
267
- continue ;
297
+ toml_value_free ( & value , ty ) ;
268
298
}
269
- goto bad ;
270
299
}
271
300
272
301
result = 1 ;
0 commit comments