1 %{
2 #include "config.h"
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 
7 #include "configuration.h"
8 #include "foreign/vas.h"
9 #include "foreign/miniobj.h"
10 #include "foreign/uthash.h"
11 
12 extern int yylex (void);
13 extern int yyparse(hitch_config *);
14 extern FILE *yyin;
15 int yyget_lineno(void);
16 
17 void config_error_set(char *, ...);
18 int config_param_validate(char *k, char *v, hitch_config *cfg,
19     char *file, int line);
20 int front_arg_add(hitch_config *cfg, struct front_arg *fa);
21 struct front_arg *front_arg_new(void);
22 void front_arg_destroy(struct front_arg *fa);
23 struct cfg_cert_file *
24 cfg_cert_file_new(void);
25 void cfg_cert_file_free(struct cfg_cert_file **cfptr);
26 int cfg_cert_vfy(struct cfg_cert_file *cf);
27 void yyerror(hitch_config *, const char *);
28 void cfg_cert_add(struct cfg_cert_file *cf, struct cfg_cert_file **dst);
29 
30 static struct front_arg *cur_fa;
31 static struct cfg_cert_file *cur_pem;
32 extern char input_line[512];
33 
34 %}
35 
36 %union {
37 	int	i;
38 	char	*s;
39 }
40 
41 %token <i> INT
42 %token <i> UINT
43 %token <i> BOOL
44 %token <s> STRING
45 
46 %token TOK_CIPHERS TOK_SSL_ENGINE TOK_PREFER_SERVER_CIPHERS TOK_BACKEND
47 %token TOK_FRONTEND TOK_WORKERS TOK_BACKLOG TOK_KEEPALIVE TOK_CHROOT
48 %token TOK_USER TOK_GROUP TOK_QUIET TOK_SYSLOG TOK_SYSLOG_FACILITY
49 %token TOK_PARAM_SYSLOG_FACILITY TOK_DAEMON TOK_WRITE_IP TOK_WRITE_PROXY
50 %token TOK_WRITE_PROXY_V1 TOK_WRITE_PROXY_V2 TOK_PEM_FILE TOK_PROXY_PROXY
51 %token TOK_BACKEND_CONNECT_TIMEOUT TOK_SSL_HANDSHAKE_TIMEOUT TOK_RECV_BUFSIZE
52 %token TOK_SEND_BUFSIZE TOK_LOG_FILENAME TOK_RING_SLOTS TOK_RING_DATA_LEN
53 %token TOK_PIDFILE TOK_SNI_NOMATCH_ABORT TOK_SSL TOK_TLS TOK_HOST TOK_PORT
54 %token TOK_MATCH_GLOBAL TOK_PB_CERT TOK_PB_OCSP_FILE TOK_OCSP_VERIFY
55 %token TOK_OCSP_DIR TOK_OCSP_RESP_TMO TOK_OCSP_CONN_TMO TOK_ALPN_PROTOS
56 %token TOK_TLS_PROTOS TOK_SSLv3 TOK_TLSv1_0 TOK_TLSv1_1 TOK_TLSv1_2
57 %token TOK_TLSv1_3 TOK_CIPHERSUITES TOK_ECDH_CURVE
58 %token TOK_SESSION_CACHE TOK_SHARED_CACHE_LISTEN TOK_SHARED_CACHE_PEER
59 %token TOK_SHARED_CACHE_IF TOK_PRIVATE_KEY TOK_BACKEND_REFRESH
60 %token TOK_OCSP_REFRESH_INTERVAL TOK_PEM_DIR TOK_PEM_DIR_GLOB
61 %token TOK_LOG_LEVEL TOK_PROXY_TLV TOK_PROXY_AUTHORITY TOK_TFO
62 %token TOK_CLIENT_VERIFY TOK_VERIFY_NONE TOK_VERIFY_OPT TOK_VERIFY_REQ
63 %token TOK_CLIENT_VERIFY_CA TOK_PROXY_CCERT
64 
65 %parse-param { hitch_config *cfg }
66 
67 %%
68 CFG
69 	: CFG_RECORDS
70 	;
71 
72 CFG_RECORDS
73 	: CFG_RECORD
74 	| CFG_RECORDS CFG_RECORD
75 	;
76 
77 CFG_RECORD
78 	: FRONTEND_REC
79 	| BACKEND_REC
80 	| PEM_FILE_REC
81 	| CIPHERS_REC
82 	| CIPHERSUITES_REC
83 	| TLS_REC
84 	| SSL_REC
85 	| TLS_PROTOS_REC
86 	| PREFER_SERVER_CIPHERS_REC
87 	| SSL_ENGINE_REC
88 	| WORKERS_REC
89 	| BACKLOG_REC
90 	| KEEPALIVE_REC
91 	| CHROOT_REC
92 	| USER_REC
93 	| GROUP_REC
94 	| QUIET_REC
95 	| SYSLOG_REC
96 	| SYSLOG_FACILITY_REC
97 	| DAEMON_REC
98 	| WRITE_IP_REC
99 	| WRITE_PROXY_REC
100 	| WRITE_PROXY_V1_REC
101 	| WRITE_PROXY_V2_REC
102 	| PROXY_PROXY_REC
103 	| ALPN_PROTOS_REC
104 	| PROXY_TLV_REC
105 	| PROXY_CCRT_REC
106 	| SNI_NOMATCH_ABORT_REC
107 	| OCSP_VERIFY
108 	| OCSP_RESP_TMO
109 	| OCSP_CONN_TMO
110 	| OCSP_REFRESH_INTERVAL
111 	| OCSP_DIR
112 	| PEM_DIR
113 	| PEM_DIR_GLOB
114 	| SESSION_CACHE_REC
115 	| SHARED_CACHE_LISTEN_REC
116 	| SHARED_CACHE_PEER_REC
117 	| SHARED_CACHE_IF_REC
118 	| LOG_FILENAME_REC
119 	| LOG_LEVEL_REC
120 	| SEND_BUFSIZE_REC
121 	| RECV_BUFSIZE_REC
122 	| BACKEND_REFRESH_REC
123 	| TFO
124 	| ECDH_CURVE_REC
125 	| CLIENT_VERIFY_REC
126 	| CLIENT_VERIFY_CA_REC
127 	;
128 
129 FRONTEND_REC
130 	: TOK_FRONTEND '=' STRING {
131 		/* XXX: passing an empty string for file */
132 		if ($3 && config_param_validate("frontend", $3, cfg, "",
133 		    yyget_lineno()) != 0)
134 			YYABORT;
135 	}
136 	| TOK_FRONTEND '=' '{' {
137 		/* NB: Mid-rule action */
138 		AZ(cur_fa);
139 		cur_fa = front_arg_new();
140 	}
141 	FRONTEND_BLK '}' {
142 		if (front_arg_add(cfg, cur_fa) != 1)
143 			YYABORT;
144 		cur_fa = NULL;
145 	};
146 
147 FRONTEND_BLK: FB_RECS;
148 FB_RECS
149 	: FB_REC
150 	| FB_RECS FB_REC
151 	;
152 
153 FB_REC
154 	: FB_HOST
155 	| FB_PORT
156 	| FB_CERT
157 	| FB_CLIENT_VERIFY
158 	| FB_CLIENT_VERIFY_CA
159 	| FB_MATCH_GLOBAL
160 	| FB_SNI_NOMATCH_ABORT
161 	| FB_TLS
162 	| FB_SSL
163 	| FB_TLS_PROTOS
164 	| FB_CIPHERS
165 	| FB_CIPHERSUITES
166 	| FB_PREF_SRV_CIPH
167 	;
168 
169 FB_HOST: TOK_HOST '=' STRING {
170 	if ($3) {
171 		if (strcmp($3, "*") == 0)
172 			cur_fa->ip = NULL;
173 		else
174 			cur_fa->ip = strdup($3);
175 	}
176 };
177 
178 FB_PORT: TOK_PORT '=' STRING { if ($3) cur_fa->port = strdup($3); };
179 
180 PEM_BLK: PB_RECS;
181 
182 PB_RECS
183 	: PB_REC
184 	| PB_RECS PB_REC
185 	;
186 
187 PB_REC
188 	: PB_CERT
189 	| PB_OCSP_RESP_FILE;
190 	| OCSP_VERIFY
191 	| PRIVATE_KEY
192 	;
193 
194 PB_CERT: TOK_PB_CERT '=' STRING { if ($3) cur_pem->filename = strdup($3); };
195 
196 PB_OCSP_RESP_FILE: TOK_PB_OCSP_FILE '=' STRING {
197 	if ($3)
198 		cur_pem->ocspfn = strdup($3);
199 };
200 
201 OCSP_VERIFY: TOK_OCSP_VERIFY '=' BOOL {
202 	if (cur_pem != NULL)
203 		cur_pem->ocsp_vfy = $3;
204 	else
205 		cfg->OCSP_VFY = $3;
206 };
207 
208 PRIVATE_KEY: TOK_PRIVATE_KEY '=' STRING {
209 	if ($3) cur_pem->priv_key_filename = strdup($3);
210 };
211 
212 PEM_DIR: TOK_PEM_DIR '=' STRING {
213 	if ($3) {
214 		size_t l;
215 		l = strlen($3);
216 		cfg->PEM_DIR = malloc(l + 2);
217 		strcpy(cfg->PEM_DIR, $3);
218 		if (cfg->PEM_DIR[l-1] != '/')
219 			strcat(cfg->PEM_DIR, "/");
220 	}
221 	else
222 		cfg->PEM_DIR = NULL;
223 };
224 
225 PEM_DIR_GLOB: TOK_PEM_DIR_GLOB '=' STRING {
226 	if ($3)
227 		cfg->PEM_DIR_GLOB = strdup($3);
228 	else
229 		cfg->PEM_DIR_GLOB = NULL;
230 
231 };
232 
233 OCSP_DIR: TOK_OCSP_DIR '=' STRING {
234 	if ($3)
235 		cfg->OCSP_DIR = strdup($3);
236 	else
237 		cfg->OCSP_DIR = NULL;
238 };
239 
240 OCSP_RESP_TMO: TOK_OCSP_RESP_TMO '=' UINT {
241 	cfg->OCSP_RESP_TMO = $3;
242 };
243 
244 OCSP_CONN_TMO: TOK_OCSP_CONN_TMO '=' UINT {
245 	cfg->OCSP_CONN_TMO = $3;
246 };
247 
248 OCSP_REFRESH_INTERVAL: TOK_OCSP_REFRESH_INTERVAL '=' UINT {
249 	cfg->OCSP_REFRESH_INTERVAL = $3;
250 }
251 
252 FB_CERT
253 	: TOK_PEM_FILE '=' STRING {
254 		if ($3 != NULL) {
255 			int r;
256 			struct cfg_cert_file *cert;
257 			cert = cfg_cert_file_new();
258 			cert->filename = strdup($3);
259 			r = cfg_cert_vfy(cert);
260 			if (r == 0) {
261 				cfg_cert_file_free(&cert);
262 				YYABORT;
263 			}
264 			cfg_cert_add(cert, &cur_fa->certs);
265 		}
266 	}
267 	| TOK_PEM_FILE '=' '{' {
268 		/* NB: Mid-rule action */
269 		AZ(cur_pem);
270 		cur_pem = cfg_cert_file_new();
271 	}
272 	PEM_BLK '}' {
273 		if (cfg_cert_vfy(cur_pem) != 0)
274 			cfg_cert_add(cur_pem, &cur_fa->certs);
275 		else {
276 			cfg_cert_file_free(&cur_pem);
277 			YYABORT;
278 		}
279 		cur_pem = NULL;
280 	};
281 
282 FB_CLIENT_VERIFY: TOK_CLIENT_VERIFY '=' CLIENT_VERIFY_OPT;
283 
284 FB_CLIENT_VERIFY_CA: TOK_CLIENT_VERIFY_CA '=' STRING {
285 	cur_fa->client_verify_ca = strdup($3);
286 };
287 
288 
289 FB_MATCH_GLOBAL: TOK_MATCH_GLOBAL '=' BOOL { cur_fa->match_global_certs = $3; };
290 
291 FB_SNI_NOMATCH_ABORT:TOK_SNI_NOMATCH_ABORT '=' BOOL {
292 		cur_fa->sni_nomatch_abort = $3;
293 };
294 
295 // this is not optimal, but it was not before, either.
296 FB_TLS: TOK_TLS '=' BOOL {
297 	if (cur_fa->selected_protos != 0) {
298 		fprintf(stderr, "%s (%s, line %d):"
299 		    " It is illegal to specify tls after ssl,"
300 		    " tls or tls-protos.\n",
301 		    __func__, __FILE__, __LINE__);
302 		front_arg_destroy(cur_fa);
303 		cur_fa = NULL;
304 		YYABORT;
305 	}
306 	if ($3)
307 		cur_fa->selected_protos = TLS_OPTION_PROTOS;
308 	else
309 		fprintf(stderr,
310 		    "Warning: tls = off is deprecated and has no effect.\n");
311 }
312 
313 FB_SSL: TOK_SSL '=' BOOL {
314 	if (cur_fa->selected_protos != 0) {
315 		fprintf(stderr, "%s (%s, line %d):"
316 		    " It is illegal to specify ssl after ssl,"
317 		    " tls or tls-protos.\n",
318 		    __func__, __FILE__, __LINE__);
319 		front_arg_destroy(cur_fa);
320 		cur_fa = NULL;
321 		YYABORT;
322 	}
323 	if ($3)
324 		cur_fa->selected_protos = SSL_OPTION_PROTOS;
325 	else
326 		fprintf(stderr,
327 		    "Warning: ssl = off is deprecated and has no effect.\n");
328 }
329 
330 FB_TLS_PROTOS: TOK_TLS_PROTOS {
331 	if (cur_fa->selected_protos != 0) {
332 		fprintf(stderr, "%s (%s, line %d):"
333 		    " It is illegal to specify tls-protos after"
334 		    " ssl, tls or tls-protos\nSelected before was %d\n",
335 		    __func__, __FILE__, __LINE__, cur_fa->selected_protos);
336 		front_arg_destroy(cur_fa);
337 		cur_fa = NULL;
338 		YYABORT;
339 	}
340 } '=' FB_TLS_PROTOS_LIST;
341 
342 FB_TLS_PROTOS_LIST: FB_TLS_PROTO | FB_TLS_PROTOS_LIST FB_TLS_PROTO;
343 FB_TLS_PROTO
344 	: TOK_SSLv3 { cur_fa->selected_protos |= SSLv3_PROTO; }
345 	| TOK_TLSv1_0 { cur_fa->selected_protos |= TLSv1_0_PROTO; }
346 	| TOK_TLSv1_1 { cur_fa->selected_protos |= TLSv1_1_PROTO; }
347 	| TOK_TLSv1_2 { cur_fa->selected_protos |= TLSv1_2_PROTO; }
348 	| TOK_TLSv1_3 { cur_fa->selected_protos |= TLSv1_3_PROTO; };
349 
350 FB_CIPHERS: TOK_CIPHERS '=' STRING {
351 	if ($3) cur_fa->ciphers_tlsv12 = strdup($3);
352 };
353 
354 FB_CIPHERSUITES: TOK_CIPHERSUITES '=' STRING {
355 	if ($3) {
356 		CHECK_OBJ_NOTNULL(cur_fa, FRONT_ARG_MAGIC);
357 		cur_fa->ciphersuites_tlsv13 = strdup($3);
358 	}
359 };
360 
361 FB_PREF_SRV_CIPH: TOK_PREFER_SERVER_CIPHERS '=' BOOL {
362 	cur_fa->prefer_server_ciphers = $3;
363 };
364 
365 QUIET_REC: TOK_QUIET '=' BOOL {
366 	if ($3)
367 		cfg->LOG_LEVEL = 0;
368 	else
369 		cfg->LOG_LEVEL = 1;
370 };
371 
372 WORKERS_REC: TOK_WORKERS '=' UINT { cfg->NCORES = $3; };
373 
374 BACKLOG_REC: TOK_BACKLOG '=' UINT { cfg->BACKLOG = $3; };
375 
376 KEEPALIVE_REC: TOK_KEEPALIVE '=' UINT { cfg->TCP_KEEPALIVE_TIME = $3; };
377 
378 TLS_REC: TOK_TLS '=' BOOL {
379 	if (cfg->SELECTED_TLS_PROTOS != 0) {
380 		fprintf(stderr, "%s (%s, line %d):"
381 		    " It is illegal to specify tls after ssl,"
382 		    " tls or tls-protos\n",
383 		    __func__, __FILE__, __LINE__);
384 		YYABORT;
385 	}
386 	if ($3)
387 		cfg->SELECTED_TLS_PROTOS = TLS_OPTION_PROTOS;
388 	else
389 		fprintf(stderr,
390 		    "Warning: tls = off is deprecated and has no effect.\n");
391 };
392 
393 SSL_REC: TOK_SSL '=' BOOL {
394 	if (cfg->SELECTED_TLS_PROTOS != 0) {
395 		fprintf(stderr, "%s (%s, line %d):"
396 		    " It is illegal to specify ssl after ssl,"
397 		    " tls or tls-protos.\n",
398 		    __func__, __FILE__, __LINE__);
399 		YYABORT;
400 	}
401 	if ($3)
402 		cfg->SELECTED_TLS_PROTOS = SSL_OPTION_PROTOS;
403 	else
404 		fprintf(stderr,
405 		    "Warning: ssl = off is deprecated and has no effect.\n");
406 };
407 
408 TLS_PROTOS_REC: TOK_TLS_PROTOS {
409 	if (cfg->SELECTED_TLS_PROTOS != 0) {
410 		fprintf(stderr, "%s (%s, line %d):"
411 		    " It is illegal to specify tls-protos after"
412 		    " ssl, tls or tls-protos\n",
413 		    __func__, __FILE__, __LINE__);
414 		YYABORT;
415 	}
416 } '=' TLS_PROTOS_LIST;
417 
418 TLS_PROTOS_LIST: TLS_PROTO | TLS_PROTOS_LIST TLS_PROTO;
419 TLS_PROTO
420 	: TOK_SSLv3 { cfg->SELECTED_TLS_PROTOS |= SSLv3_PROTO; }
421 	| TOK_TLSv1_0 { cfg->SELECTED_TLS_PROTOS |= TLSv1_0_PROTO; }
422 	| TOK_TLSv1_1 { cfg->SELECTED_TLS_PROTOS |= TLSv1_1_PROTO; }
423 	| TOK_TLSv1_2 { cfg->SELECTED_TLS_PROTOS |= TLSv1_2_PROTO; }
424 	| TOK_TLSv1_3 { cfg->SELECTED_TLS_PROTOS |= TLSv1_3_PROTO; };
425 
426 SSL_ENGINE_REC: TOK_SSL_ENGINE '=' STRING { if ($3) cfg->ENGINE = strdup($3); };
427 
428 PREFER_SERVER_CIPHERS_REC: TOK_PREFER_SERVER_CIPHERS '=' BOOL {
429 	cfg->PREFER_SERVER_CIPHERS = $3;
430 };
431 
432 CHROOT_REC: TOK_CHROOT '=' STRING {
433 	/* XXX: passing an empty string for file */
434 	if ($3 && config_param_validate("chroot", $3, cfg, "",
435 	    yyget_lineno()) != 0)
436 		YYABORT;
437 };
438 
439 BACKEND_REC: TOK_BACKEND '=' STRING {
440 	/* XXX: passing an empty string for file */
441 	if ($3 && config_param_validate("backend", $3, cfg, "",
442 	    yyget_lineno()) != 0)
443 		YYABORT;
444 };
445 
446 PEM_FILE_REC
447 	: TOK_PEM_FILE '=' STRING {
448 		/* XXX: passing an empty string for file */
449 		if ($3 && config_param_validate("pem-file", $3, cfg, "",
450 		    yyget_lineno()) != 0)
451 			YYABORT;
452 	}
453 	| TOK_PEM_FILE '=' '{' {
454 		/* NB: Mid-rule action */
455 		AZ(cur_pem);
456 		cur_pem = cfg_cert_file_new();
457 	}
458 	PEM_BLK '}' {
459 		if (cfg_cert_vfy(cur_pem) != 0) {
460 			if (cfg->CERT_DEFAULT != NULL) {
461 				struct cfg_cert_file *tmp = cfg->CERT_DEFAULT;
462 				cfg_cert_add(tmp, &cfg->CERT_FILES);
463 			}
464 			cfg->CERT_DEFAULT = cur_pem;
465 		} else {
466 			cfg_cert_file_free(&cur_pem);
467 			YYABORT;
468 		}
469 		cur_pem = NULL;
470 	};
471 
472 SYSLOG_REC: TOK_SYSLOG '=' BOOL { cfg->SYSLOG = $3; };
473 DAEMON_REC: TOK_DAEMON '=' BOOL { cfg->DAEMONIZE = $3; };
474 SNI_NOMATCH_ABORT_REC : TOK_SNI_NOMATCH_ABORT '=' BOOL {
475 	cfg->SNI_NOMATCH_ABORT = $3;
476 };
477 
478 CIPHERS_REC: TOK_CIPHERS '=' STRING {
479 	if ($3) {
480 		cfg->CIPHERS_TLSv12 = strdup($3);
481 	}
482 };
483 
484 CIPHERSUITES_REC: TOK_CIPHERSUITES '=' STRING {
485 	if ($3) {
486 		cfg->CIPHERSUITES_TLSv13 = strdup($3);
487 	}
488 };
489 
490 
491 USER_REC: TOK_USER '=' STRING {
492 	/* XXX: passing an empty string for file */
493 	if ($3 && config_param_validate("user", $3, cfg, "",
494 	    yyget_lineno()) != 0)
495 		YYABORT;
496 };
497 
498 GROUP_REC: TOK_GROUP '=' STRING {
499 	/* XXX: passing an empty string for file */
500 	if ($3 && config_param_validate("group", $3, cfg, "",
501 	    yyget_lineno()) != 0)
502 		YYABORT;
503 };
504 
505 WRITE_IP_REC: TOK_WRITE_IP '=' BOOL { cfg->WRITE_IP_OCTET = $3; };
506 
507 WRITE_PROXY_REC: TOK_WRITE_PROXY '=' BOOL { cfg->WRITE_PROXY_LINE_V2 = $3; };
508 
509 WRITE_PROXY_V1_REC: TOK_WRITE_PROXY_V1 '=' BOOL {
510 	cfg->WRITE_PROXY_LINE_V1 = $3;
511 };
512 
513 WRITE_PROXY_V2_REC: TOK_WRITE_PROXY_V2 '=' BOOL {
514 	cfg->WRITE_PROXY_LINE_V2 = $3;
515 };
516 
517 PROXY_TLV_REC: TOK_PROXY_TLV '=' BOOL { cfg->PROXY_TLV = $3; };
518 
519 PROXY_TLV_REC: TOK_PROXY_AUTHORITY '=' BOOL { cfg->PROXY_AUTHORITY = $3; };
520 
521 PROXY_CCRT_REC: TOK_PROXY_CCERT '=' BOOL { cfg->PROXY_CLIENT_CERT = $3; };
522 
523 PROXY_PROXY_REC: TOK_PROXY_PROXY '=' BOOL { cfg->PROXY_PROXY_LINE = $3; };
524 
525 ALPN_PROTOS_REC: TOK_ALPN_PROTOS '=' STRING {
526 	/* XXX: passing an empty string for file */
527 	if ($3 && config_param_validate("alpn-protos", $3, cfg, "",
528 	    yyget_lineno()) != 0)
529 		YYABORT;
530 };
531 
532 SYSLOG_FACILITY_REC: TOK_SYSLOG_FACILITY '=' STRING {
533 	/* XXX: passing an empty string for file */
534 	if ($3 &&
535 	    config_param_validate("syslog-facility", $3, cfg, "",
536 	    yyget_lineno()) != 0)
537 		YYABORT;
538 };
539 
540 SEND_BUFSIZE_REC: TOK_SEND_BUFSIZE '=' UINT { cfg->SEND_BUFSIZE = $3; };
541 
542 RECV_BUFSIZE_REC: TOK_RECV_BUFSIZE '=' UINT { cfg->RECV_BUFSIZE = $3; };
543 
544 LOG_FILENAME_REC: TOK_LOG_FILENAME '=' STRING {
545 	/* XXX: passing an empty string for file */
546 	if ($3 &&
547 	    config_param_validate("log-filename", $3, cfg, "",
548 	    yyget_lineno()) != 0)
549 		YYABORT;
550 };
551 
552 LOG_LEVEL_REC: TOK_LOG_LEVEL '=' UINT { cfg->LOG_LEVEL = $3; };
553 
554 SESSION_CACHE_REC: TOK_SESSION_CACHE '=' UINT {
555 #ifdef USE_SHARED_CACHE
556 	cfg->SHARED_CACHE = $3;
557 #else
558 	fprintf(stderr, "Hitch needs to be compiled with --enable-sessioncache "
559 			"for '%s'", input_line);
560 	YYABORT;
561 #endif
562 };
563 
564 SHARED_CACHE_LISTEN_REC: TOK_SHARED_CACHE_LISTEN '=' STRING {
565 #ifdef USE_SHARED_CACHE
566 	/* XXX: passing an empty string for file */
567 	if ($3 && config_param_validate("shared-cache-listen", $3, cfg,
568 		"", yyget_lineno()) != 0)
569 		YYABORT;
570 #else
571 	fprintf(stderr, "Hitch needs to be compiled with --enable-sessioncache "
572 			"for '%s'", input_line);
573 	YYABORT;
574 #endif
575 };
576 
577 SHARED_CACHE_PEER_REC: TOK_SHARED_CACHE_PEER  '=' STRING {
578 #ifdef USE_SHARED_CACHE
579 	/* XXX: passing an empty string for file */
580 	if ($3 && config_param_validate("shared-cache-peer", $3, cfg,
581 		"", yyget_lineno()) != 0)
582 		YYABORT;
583 #else
584 	fprintf(stderr, "Hitch needs to be compiled with --enable-sessioncache "
585 			"for '%s'", input_line);
586 	YYABORT;
587 #endif
588 };
589 
590 SHARED_CACHE_IF_REC: TOK_SHARED_CACHE_IF '=' STRING {
591 #ifdef USE_SHARED_CACHE
592 	/* XXX: passing an empty string for file */
593 	if ($3 && config_param_validate("shared-cache-if", $3, cfg,
594 		"", yyget_lineno()) != 0)
595 		YYABORT;
596 #else
597 	fprintf(stderr, "Hitch needs to be compiled with --enable-sessioncache "
598 			"for '%s'", input_line);
599 	YYABORT;
600 #endif
601 };
602 
603 TFO: TOK_TFO '=' BOOL {
604 #ifdef TCP_FASTOPEN_WORKS
605 	{ cfg->TFO = $3; };
606 #else
607 	fprintf(stderr, "Hitch needs to be compiled with --enable-tfo"
608 			"for '%s'", input_line);
609 	YYABORT;
610 #endif
611 };
612 
613 BACKEND_REFRESH_REC: TOK_BACKEND_REFRESH '=' UINT {
614 	cfg->BACKEND_REFRESH_TIME = $3;
615 };
616 
617 ECDH_CURVE_REC: TOK_ECDH_CURVE '=' STRING {
618 	if ($3) {
619 		cfg->ECDH_CURVE = strdup($3);
620 	}
621 };
622 
623 CLIENT_VERIFY_REC: TOK_CLIENT_VERIFY '=' CLIENT_VERIFY_OPT;
624 
625 CLIENT_VERIFY_OPT
626 	: TOK_VERIFY_NONE {
627 		if (cur_fa)
628 			cur_fa->client_verify = SSL_VERIFY_NONE;
629 		else
630 			cfg->CLIENT_VERIFY = SSL_VERIFY_NONE;
631 	}
632 	| TOK_VERIFY_OPT {
633 		if (cur_fa)
634 			cur_fa->client_verify = SSL_VERIFY_PEER;
635 		else
636 			cfg->CLIENT_VERIFY = SSL_VERIFY_PEER;
637 	}
638 	| TOK_VERIFY_REQ {
639 		if (cur_fa)
640 			cur_fa->client_verify =
641 			    SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
642 		else
643 			cfg->CLIENT_VERIFY =
644 			    SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
645 	};
646 
647 CLIENT_VERIFY_CA_REC: TOK_CLIENT_VERIFY_CA '=' STRING {
648 	cfg->CLIENT_VERIFY_CA = strdup($3);
649 };
650 
651 %%
652 
653 void
654 yyerror(hitch_config *cfg, const char *s)
655 {
656 	(void) cfg;
657 
658 	/* Clean up if FRONTEND_BLK parsing failed */
659 	if (cur_fa != NULL)
660 		FREE_OBJ(cur_fa);
661 
662 	config_error_set("Parsing error in line %d: %s: '%s'",
663 	    yyget_lineno(), s, strlen(input_line) > 0 ? input_line : "");
664 }
665