@@ -64,6 +64,15 @@ enum tlshd_tags_fsm_state_index {
6464 PS_DOCUMENT ,
6565 PS_TOP_LEVEL ,
6666
67+ PS_FILTERS ,
68+ PS_FILTER ,
69+ PS_FILTER_KEYS ,
70+ PS_FILTER_KEY ,
71+ PS_FILTER_TYPE_VALUE ,
72+ PS_FILTER_PATTERN_VALUE ,
73+ PS_FILTER_PURPOSE_LIST ,
74+ PS_FILTER_KEY_USAGE ,
75+
6776 PS_UNEXPECTED_INPUT_TOKEN ,
6877 PS_FAILURE ,
6978};
@@ -79,10 +88,25 @@ struct tlshd_tags_filter_type {
7988
8089static GHashTable * tlshd_tags_filter_type_hash ;
8190
91+ struct tlshd_tags_filter {
92+ gchar * fi_name ;
93+ struct tlshd_tags_filter_type * fi_filter_type ;
94+
95+ /* filter arguments */
96+ gchar * fi_pattern ;
97+ GPatternSpec * fi_pattern_spec ;
98+ unsigned int fi_purpose_mask ;
99+ time_t fi_time ;
100+ };
101+
102+ static GHashTable * tlshd_tags_filter_hash ;
103+
82104struct tlshd_tags_parser_state {
83105 yaml_event_t ps_yaml_event ;
84106
85107 enum tlshd_tags_fsm_state_index ps_fsm_state ;
108+
109+ struct tlshd_tags_filter * ps_current_filter ;
86110};
87111
88112static enum tlshd_tags_fsm_state_index
@@ -91,10 +115,205 @@ tlshd_tags_top_level(struct tlshd_tags_parser_state *current)
91115 const yaml_event_t * event = & current -> ps_yaml_event ;
92116 const char * mapping = (const char * )event -> data .scalar .value ;
93117
118+ if (strcmp (mapping , "filters" ) == 0 )
119+ return PS_FILTERS ;
120+
94121 tlshd_log_error ("Unexpected mapping name: %s\n" , mapping );
95122 return PS_UNEXPECTED_INPUT_TOKEN ;
96123}
97124
125+ /* --- Filters --- */
126+
127+ static void tlshd_tags_filter_free (struct tlshd_tags_filter * filter )
128+ {
129+ if (!filter )
130+ return ;
131+
132+ if (tlshd_debug > 3 )
133+ tlshd_log_debug ("Removing filter '%s' from the filter hash" ,
134+ filter -> fi_name );
135+
136+ if (filter -> fi_pattern_spec )
137+ g_pattern_spec_free (filter -> fi_pattern_spec );
138+ g_free (filter -> fi_pattern );
139+ g_free (filter -> fi_name );
140+ g_free (filter );
141+ }
142+
143+ static void tlshd_tags_filter_hash_destroy (void )
144+ {
145+ GHashTableIter iter ;
146+ gpointer key , value ;
147+
148+ if (!tlshd_tags_filter_hash )
149+ return ;
150+
151+ g_hash_table_iter_init (& iter , tlshd_tags_filter_hash );
152+ while (g_hash_table_iter_next (& iter , & key , & value ))
153+ tlshd_tags_filter_free ((struct tlshd_tags_filter * )value );
154+
155+ g_hash_table_destroy (tlshd_tags_filter_hash );
156+ tlshd_tags_filter_hash = NULL ;
157+ }
158+
159+ static bool
160+ tlshd_tags_filter_hash_init (void )
161+ {
162+ tlshd_tags_filter_hash = g_hash_table_new (g_str_hash , g_str_equal );
163+ return tlshd_tags_filter_hash != NULL ;
164+ }
165+
166+ static enum tlshd_tags_fsm_state_index
167+ tlshd_tags_filter_create (struct tlshd_tags_parser_state * current )
168+ {
169+ const yaml_event_t * event = & current -> ps_yaml_event ;
170+ struct tlshd_tags_filter * filter ;
171+
172+ filter = g_malloc0 (sizeof (* filter ));
173+ if (!filter ) {
174+ tlshd_log_error ("Failed to allocate new filter\n" );
175+ return PS_FAILURE ;
176+ }
177+
178+ filter -> fi_name = g_strdup ((const char * )event -> data .scalar .value );
179+ if (!filter -> fi_name ) {
180+ free (filter );
181+ tlshd_log_error ("Failed to allocate new filter\n" );
182+ return PS_FAILURE ;
183+ }
184+
185+ current -> ps_current_filter = filter ;
186+ return PS_FILTER_KEYS ;
187+ }
188+
189+ static enum tlshd_tags_fsm_state_index
190+ tlshd_tags_filter_type_add (struct tlshd_tags_parser_state * current )
191+ {
192+ const yaml_event_t * event = & current -> ps_yaml_event ;
193+ const char * name = (const char * )event -> data .scalar .value ;
194+
195+ if (!current -> ps_current_filter ) {
196+ tlshd_log_error ("No current filter\n" );
197+ return PS_FAILURE ;
198+ }
199+
200+ if (current -> ps_current_filter -> fi_filter_type ) {
201+ tlshd_log_error ("Filter type already set for filter '%s'\n" ,
202+ name );
203+ return PS_FAILURE ;
204+ }
205+
206+ gconstpointer key = (gconstpointer )name ;
207+ gpointer filter_type ;
208+
209+ filter_type = g_hash_table_lookup (tlshd_tags_filter_type_hash , key );
210+ if (!filter_type ) {
211+ tlshd_log_debug ("Filter type '%s' is not supported" , name );
212+ return PS_UNEXPECTED_INPUT_TOKEN ;
213+ }
214+
215+ current -> ps_current_filter -> fi_filter_type = filter_type ;
216+ return PS_FILTER_KEY ;
217+ }
218+
219+ static enum tlshd_tags_fsm_state_index
220+ tlshd_tags_filter_key_set (struct tlshd_tags_parser_state * current )
221+ {
222+ const yaml_event_t * event = & current -> ps_yaml_event ;
223+ const char * key = (const char * )event -> data .scalar .value ;
224+
225+ if (strcmp (key , "type" ) == 0 )
226+ return PS_FILTER_TYPE_VALUE ;
227+ else if (strcmp (key , "pattern" ) == 0 )
228+ return PS_FILTER_PATTERN_VALUE ;
229+ else if (strcmp (key , "purpose" ) == 0 )
230+ return PS_FILTER_PURPOSE_LIST ;
231+
232+ tlshd_log_error ("Unexpected token: %s\n" , key );
233+ return PS_UNEXPECTED_INPUT_TOKEN ;
234+ }
235+
236+ static enum tlshd_tags_fsm_state_index
237+ tlshd_tags_filter_pattern_set (struct tlshd_tags_parser_state * current )
238+ {
239+ const yaml_event_t * event = & current -> ps_yaml_event ;
240+ const char * pattern = (const char * )event -> data .scalar .value ;
241+
242+ if (!current -> ps_current_filter ) {
243+ tlshd_log_error ("No current filter\n" );
244+ return PS_FAILURE ;
245+ }
246+
247+ current -> ps_current_filter -> fi_pattern = g_strdup (pattern );
248+ if (!current -> ps_current_filter -> fi_pattern ) {
249+ tlshd_log_error ("Failed to allocate filter pattern\n" );
250+ return PS_FAILURE ;
251+ }
252+
253+ return PS_FILTER_KEY ;
254+ }
255+
256+ static enum tlshd_tags_fsm_state_index
257+ tlshd_tags_filter_key_usage_set (struct tlshd_tags_parser_state * current )
258+ {
259+ const yaml_event_t * event = & current -> ps_yaml_event ;
260+ const char * name = (const char * )event -> data .scalar .value ;
261+ unsigned int key_usage = 0 ;
262+
263+ if (strcmp (name , "digitalSignature" ) == 0 )
264+ key_usage = GNUTLS_KEY_DIGITAL_SIGNATURE ;
265+ else if (strcmp (name , "nonRepudiation" ) == 0 )
266+ key_usage = GNUTLS_KEY_NON_REPUDIATION ;
267+ else if (strcmp (name , "keyEncipherment" ) == 0 )
268+ key_usage = GNUTLS_KEY_KEY_ENCIPHERMENT ;
269+ else if (strcmp (name , "dataEncipherment" ) == 0 )
270+ key_usage = GNUTLS_KEY_DATA_ENCIPHERMENT ;
271+ else if (strcmp (name , "keyAgreement" ) == 0 )
272+ key_usage = GNUTLS_KEY_KEY_AGREEMENT ;
273+ else if (strcmp (name , "keyCertSign" ) == 0 )
274+ key_usage = GNUTLS_KEY_KEY_CERT_SIGN ;
275+ else if (strcmp (name , "cRLSign" ) == 0 )
276+ key_usage = GNUTLS_KEY_CRL_SIGN ;
277+ else if (strcmp (name , "encipherOnly" ) == 0 )
278+ key_usage = GNUTLS_KEY_ENCIPHER_ONLY ;
279+ else if (strcmp (name , "decipherOnly" ) == 0 )
280+ key_usage = GNUTLS_KEY_DECIPHER_ONLY ;
281+ else {
282+ tlshd_log_error ("Unrecognized key usage: %s\n" , name );
283+ return PS_UNEXPECTED_INPUT_TOKEN ;
284+ }
285+
286+ current -> ps_current_filter -> fi_purpose_mask |= key_usage ;
287+ return PS_FILTER_KEY_USAGE ;
288+ }
289+
290+ static enum tlshd_tags_fsm_state_index
291+ tlshd_tags_filter_finalize (struct tlshd_tags_parser_state * current )
292+ {
293+ struct tlshd_tags_filter * filter = current -> ps_current_filter ;
294+
295+ if (!filter ) {
296+ tlshd_log_error ("No current filter\n" );
297+ return PS_FAILURE ;
298+ }
299+
300+ if (!filter -> fi_filter_type -> ft_validate ) {
301+ tlshd_log_error ("Filter '%s' filter type is not yet implemented." ,
302+ filter -> fi_name );
303+ return PS_FILTER ;
304+ }
305+ if (!filter -> fi_filter_type -> ft_validate (filter ))
306+ return PS_FAILURE ;
307+
308+ if (tlshd_debug > 3 )
309+ tlshd_log_debug ("Adding filter '%s' to the filter hash" ,
310+ filter -> fi_name );
311+ g_hash_table_insert (tlshd_tags_filter_hash , filter -> fi_name ,
312+ (gpointer )filter );
313+ current -> ps_current_filter = NULL ;
314+ return PS_FILTER ;
315+ }
316+
98317/* --- FSM states --- */
99318
100319typedef enum tlshd_tags_fsm_state_index
@@ -137,6 +356,41 @@ static const struct tlshd_tags_fsm_transition tlshd_tags_transitions_top_level[]
137356 NEXT_STATE (YAML_MAPPING_END_EVENT , PS_DOCUMENT ),
138357};
139358
359+ static const struct tlshd_tags_fsm_transition tlshd_tags_transitions_filters [] = {
360+ NEXT_STATE (YAML_MAPPING_START_EVENT , PS_FILTER ),
361+ };
362+
363+ static const struct tlshd_tags_fsm_transition tlshd_tags_transitions_filter [] = {
364+ NEXT_ACTION (YAML_SCALAR_EVENT , tlshd_tags_filter_create ),
365+ NEXT_STATE (YAML_MAPPING_END_EVENT , PS_TOP_LEVEL ),
366+ };
367+
368+ static const struct tlshd_tags_fsm_transition tlshd_tags_transitions_filter_keys [] = {
369+ NEXT_STATE (YAML_MAPPING_START_EVENT , PS_FILTER_KEY ),
370+ };
371+
372+ static const struct tlshd_tags_fsm_transition tlshd_tags_transitions_filter_key [] = {
373+ NEXT_ACTION (YAML_SCALAR_EVENT , tlshd_tags_filter_key_set ),
374+ NEXT_ACTION (YAML_MAPPING_END_EVENT , tlshd_tags_filter_finalize ),
375+ };
376+
377+ static const struct tlshd_tags_fsm_transition tlshd_tags_transitions_filter_type_value [] = {
378+ NEXT_ACTION (YAML_SCALAR_EVENT , tlshd_tags_filter_type_add ),
379+ };
380+
381+ static const struct tlshd_tags_fsm_transition tlshd_tags_transitions_filter_pattern_value [] = {
382+ NEXT_ACTION (YAML_SCALAR_EVENT , tlshd_tags_filter_pattern_set ),
383+ };
384+
385+ static const struct tlshd_tags_fsm_transition tlshd_tags_transitions_filter_purpose_list [] = {
386+ NEXT_STATE (YAML_SEQUENCE_START_EVENT , PS_FILTER_KEY_USAGE ),
387+ };
388+
389+ static const struct tlshd_tags_fsm_transition tlshd_tags_transitions_filter_key_usage [] = {
390+ NEXT_ACTION (YAML_SCALAR_EVENT , tlshd_tags_filter_key_usage_set ),
391+ NEXT_STATE (YAML_SEQUENCE_END_EVENT , PS_FILTER_KEY ),
392+ };
393+
140394struct tlshd_tags_fsm_state {
141395 const char * ts_name ;
142396 const struct tlshd_tags_fsm_transition * ts_transitions ;
@@ -162,6 +416,14 @@ static const struct tlshd_tags_fsm_state tlshd_tags_fsm_state_table[] = {
162416 FSM_STATE (PS_STREAM , tlshd_tags_transitions_stream ),
163417 FSM_STATE (PS_DOCUMENT , tlshd_tags_transitions_document ),
164418 FSM_STATE (PS_TOP_LEVEL , tlshd_tags_transitions_top_level ),
419+ FSM_STATE (PS_FILTERS , tlshd_tags_transitions_filters ),
420+ FSM_STATE (PS_FILTER , tlshd_tags_transitions_filter ),
421+ FSM_STATE (PS_FILTER_KEYS , tlshd_tags_transitions_filter_keys ),
422+ FSM_STATE (PS_FILTER_KEY , tlshd_tags_transitions_filter_key ),
423+ FSM_STATE (PS_FILTER_TYPE_VALUE , tlshd_tags_transitions_filter_type_value ),
424+ FSM_STATE (PS_FILTER_PATTERN_VALUE , tlshd_tags_transitions_filter_pattern_value ),
425+ FSM_STATE (PS_FILTER_PURPOSE_LIST , tlshd_tags_transitions_filter_purpose_list ),
426+ FSM_STATE (PS_FILTER_KEY_USAGE , tlshd_tags_transitions_filter_key_usage ),
165427 TERMINAL_STATE (PS_UNEXPECTED_INPUT_TOKEN ),
166428 TERMINAL_STATE (PS_FAILURE ),
167429};
@@ -396,12 +658,16 @@ void tlshd_tags_config_init(const char *tagsdir)
396658{
397659 if (!tlshd_tags_filter_type_hash_init ())
398660 return ;
661+ if (!tlshd_tags_filter_hash_init ())
662+ goto filter_type_hash ;
399663
400664 if (!tlshd_tags_read_directory (tagsdir ))
401- goto filter_type_hash ;
665+ goto filter_hash ;
402666
403667 return ;
404668
669+ filter_hash :
670+ tlshd_tags_filter_hash_destroy ();
405671filter_type_hash :
406672 tlshd_tags_filter_type_hash_destroy ();
407673}
@@ -412,5 +678,6 @@ void tlshd_tags_config_init(const char *tagsdir)
412678 */
413679void tlshd_tags_config_shutdown (void )
414680{
681+ tlshd_tags_filter_hash_destroy ();
415682 tlshd_tags_filter_type_hash_destroy ();
416683}
0 commit comments