Browse code

- Use the new configuration file parser

Jan Janak authored on 06/06/2008 00:03:06
Showing 4 changed files
... ...
@@ -30,733 +30,57 @@
30 30
  *
31 31
  */
32 32
 
33
-#include <stdio.h>
34
-#include <libgen.h>
35
-#include "../../mem/mem.h"
36
-#include "../../dprint.h"
37
-#include "../../trim.h"
38
-#include "../../ut.h"
39
-#include "../../resolve.h"
40 33
 #include "tls_config.h"
41
-#include "tls_util.h"
42 34
 #include "tls_domain.h"
43 35
 #include "tls_mod.h"
36
+#include "tls_util.h"
44 37
 
45
-#define MAX_TOKEN_LEN 256
46
-
47
-
48
-/*
49
- * Parser state
50
- */
51
-static struct {
52
-	FILE* f;
53
-	char* file;
54
-	int line;
55
-	int col;
56
-
57
-	tls_cfg_t* cfg;       /* Current configuration data */
58
-	tls_domain_t* domain; /* Current domain in the configuration data */
59
-} pstate;
60
-
61
-
62
-/*
63
- * Structure representing lexical token
64
- */
65
-typedef struct token {
66
-	char buf [MAX_TOKEN_LEN];
67
-	int type;  /* Token type */
68
-	str val;   /* Token value */
69
-
70
-	struct {   /* Position of first and last character of
71
-		    * token in file
72
-		    */
73
-		int line;
74
-		int col;
75
-	} start, end;
76
-} token_t;
77
-
78
-
79
-typedef int (*parser_func_f)(token_t* token);
80
-
81
-
82
-struct parser_tab {
83
-	str token;
84
-	union {
85
-		int ival;
86
-		str sval;
87
-		parser_func_f fval;
88
-	} u;
89
-};
90
-
91
-static struct parser_tab option_name[];
92
-static struct parser_tab token_method[];
93
-static struct parser_tab token_bool[];
94
-static struct parser_tab token_type[];
95
-static struct parser_tab token_default[];
96
-
97
-/*
98
- * States of lexical scanner
99
- */
100
-enum st {
101
-	ST_S,  /* Begin */
102
-	ST_A,  /* Alphanumeric */
103
-	ST_AE, /* Alphanumeric escaped */
104
-	ST_Q,  /* Quoted */
105
-	ST_QE, /* Quoted escaped */
106
-	ST_C,  /* Comment */
107
-	ST_CE, /* Comment escaped */
108
-	ST_E,  /* Escaped */
109
-};
110
-
111
-
112
-/* Extended tokens can contain also delimiters,
113
- * in addition to alpha-numeric characters,
114
- * this is used on the righ side of assignments
115
- * where no quotes are used
116
- */
117
-#define EXTENDED_ALPHA_TOKEN (1 << 0)
118
-
119
-
120
-/*
121
- * Test for alphanumeric characters
122
- */
123
-#define IS_ALPHA(c) \
124
-    (((c) >= 'a' && (c) <= 'z') || \
125
-     ((c) >= 'A' && (c) <= 'Z') || \
126
-     ((c) >= '0' && (c) <= '9') || \
127
-     (c) == '_')
128
-
129
-
130
-/*
131
- * Test for delimiter characters
132
- */
133
-#define IS_DELIM(c) \
134
-    ((c) == '=' || \
135
-     (c) == ':' || \
136
-     (c) == ';' || \
137
-     (c) == '.' || \
138
-     (c) == ',' || \
139
-     (c) == '?' || \
140
-     (c) == '[' || \
141
-     (c) == ']' || \
142
-     (c) == '/' || \
143
-     (c) == '@' || \
144
-     (c) == '!' || \
145
-     (c) == '$' || \
146
-     (c) == '%' || \
147
-     (c) == '&' || \
148
-     (c) == '*' || \
149
-     (c) == '(' || \
150
-     (c) == ')' || \
151
-     (c) == '-' || \
152
-     (c) == '+' || \
153
-     (c) == '|' || \
154
-     (c) == '\'')
155
-
156
-/* Whitespace characters */
157
-#define IS_WHITESPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r') 
158
-#define IS_QUOTE(c)      ((c) == '\"')  /* Quote characters */
159
-#define IS_COMMENT(c)    ((c) == '#')   /* Characters that start comments */
160
-#define IS_ESCAPE(c)     ((c) == '\\')  /* Escape characters */
161
-#define IS_EOL(c)        ((c) == '\n')  /* End of line */
162
-
163
-
164
-/*
165
- * Append character to the value of current
166
- * token
167
- */
168
-#define PUSH(c)                                    \
169
-    if (token->val.len >= MAX_TOKEN_LEN) {         \
170
-        ERR("%s:%d:%d: Token too long\n",          \
171
-	    pstate.file, pstate.line, pstate.col); \
172
-        return -1;                                 \
173
-    }                                              \
174
-    if (token->val.len == 0) {                     \
175
-         token->start.line = pstate.line;          \
176
-         token->start.col = pstate.col;            \
177
-    }                                              \
178
-    token->val.s[token->val.len++] = (c);
179
-
180
-
181
-/*
182
- * Return current token from the lexical analyzer
183
- */    
184
-#define RETURN(c)                  \
185
-    token->end.line = pstate.line; \
186
-    token->end.col = pstate.col;   \
187
-    token->type = (c);             \
188
-    print_token(token);            \
189
-    return 1;
190
-
191
-
192
-/*
193
- * Get next character and update counters
194
- */
195
-#define READ_CHAR         \
196
-     c = fgetc(pstate.f); \
197
-     if (IS_EOL(c)) {     \
198
-         pstate.line++;   \
199
-	 pstate.col = 0;  \
200
-     } else {             \
201
-	 pstate.col++;    \
202
-     }
203
-
204
-
205
-enum {
206
-	TOKEN_EOF = -1,
207
-	TOKEN_ALPHA = -2,
208
-	TOKEN_STRING = -3
209
-};
210
-
211
-
212
-static void print_token(struct token* token)
213
-{
214
-	DBG("token(%d, '%.*s', <%d,%d>-<%d,%d>)\n", 
215
-	    token->type, token->val.len, ZSW(token->val.s),
216
-	    token->start.line, token->start.col, 
217
-	    token->end.line, token->end.col);
218
-}
219
-
220
-
221
-int tls_lex(token_t* token, unsigned int flags)
222
-{
223
-	static int look_ahead = EOF;
224
-	int c;
225
-	enum st state;
226
-
227
-	state = ST_S;
228
-	
229
-	token->val.s = token->buf;
230
-	token->val.len = 0;
231
-
232
-	if (look_ahead != EOF) {
233
-		c = look_ahead;
234
-		look_ahead = EOF;
235
-	} else {
236
-		READ_CHAR;
237
-	}
238
-
239
-	while(c != EOF) {
240
-		switch(state) {
241
-		case ST_S:
242
-			if (flags & EXTENDED_ALPHA_TOKEN) {
243
-				if (IS_WHITESPACE(c)) {
244
-					     /* Do nothing */
245
-				} else if (IS_ALPHA(c) ||
246
-					   IS_ESCAPE(c) ||
247
-					   IS_DELIM(c)) {
248
-					PUSH(c);
249
-					state = ST_A;
250
-				} else if (IS_QUOTE(c)) {
251
-					state = ST_Q;
252
-				} else if (IS_COMMENT(c)) {
253
-					state = ST_C;
254
-				} else if (IS_EOL(c)) {
255
-					PUSH(c);
256
-					RETURN(c);
257
-				} else {
258
-					ERR("%s:%d:%d: Invalid character 0x%x\n", 
259
-					    pstate.file, pstate.line, pstate.col, c);
260
-					return -1;
261
-				}
262
-			} else {
263
-				if (IS_WHITESPACE(c)) {
264
-					     /* Do nothing */
265
-				} else if (IS_ALPHA(c)) {
266
-					PUSH(c);
267
-					state = ST_A;
268
-				} else if (IS_QUOTE(c)) {
269
-					state = ST_Q;
270
-				} else if (IS_COMMENT(c)) {
271
-					state = ST_C;
272
-				} else if (IS_ESCAPE(c)) {
273
-					state = ST_E;
274
-				} else if (IS_DELIM(c) || IS_EOL(c)) {
275
-					PUSH(c);
276
-					RETURN(c);
277
-				} else {
278
-					ERR("%s:%d:%d: Invalid character 0x%x\n", 
279
-					    pstate.file, pstate.line, pstate.col, c);
280
-					return -1;
281
-				}
282
-			}
283
-			break;
284
-
285
-		case ST_A:
286
-			if (flags & EXTENDED_ALPHA_TOKEN) {
287
-				if (IS_ALPHA(c) ||
288
-				    IS_DELIM(c) ||
289
-				    IS_QUOTE(c)) {
290
-					PUSH(c);
291
-				} else if (IS_ESCAPE(c)) {
292
-					state = ST_AE;
293
-				} else if (IS_COMMENT(c) || IS_EOL(c) || IS_WHITESPACE(c)) {
294
-					look_ahead = c;
295
-					RETURN(TOKEN_ALPHA);
296
-				} else {
297
-					ERR("%s:%d:%d: Invalid character 0x%x\n", 
298
-					    pstate.file, pstate.line, pstate.col, c);
299
-					return -1;
300
-				}
301
-			} else {
302
-				if (IS_ALPHA(c)) {
303
-					PUSH(c);
304
-				} else if (IS_ESCAPE(c)) {
305
-					state = ST_AE;
306
-				} else if (IS_WHITESPACE(c) ||
307
-					   IS_DELIM(c) ||
308
-					   IS_QUOTE(c) ||
309
-					   IS_COMMENT(c) ||
310
-					   IS_EOL(c)) {
311
-					look_ahead = c;
312
-					RETURN(TOKEN_ALPHA);
313
-				} else {
314
-					ERR("%s:%d:%d: Invalid character 0x%x\n", 
315
-					    pstate.file, pstate.line, pstate.col, c);
316
-					return -1;
317
-				}
318
-			}
319
-			break;
320
-
321
-		case ST_AE:
322
-			if (IS_COMMENT(c) ||
323
-			    IS_QUOTE(c) ||
324
-			    IS_ESCAPE(c)) {
325
-				PUSH(c);
326
-			} else if (c == 'r') {
327
-				PUSH('\r');
328
-			} else if (c == 'n') {
329
-				PUSH('\n');
330
-			} else if (c == 't') {
331
-				PUSH('\t');
332
-			} else if (c == ' ') {
333
-				PUSH(' ');
334
-			} else if (IS_EOL(c)) {
335
-				     /* Do nothing */
336
-			} else {
337
-				ERR("%s:%d:%d: Unsupported escape character 0x%x\n", 
338
-				    pstate.file, pstate.line, pstate.col, c);
339
-				return -1;
340
-			}
341
-			state = ST_A;
342
-			break;
343
-
344
-		case ST_Q:
345
-			if (IS_QUOTE(c)) {
346
-				RETURN(TOKEN_STRING);
347
-			} else if (IS_ESCAPE(c)) {
348
-				state = ST_QE;
349
-				break;
350
-			} else {
351
-				PUSH(c);
352
-			}
353
-			break;
354
-
355
-		case ST_QE:
356
-			if (IS_ESCAPE(c) ||
357
-			    IS_QUOTE(c)) {
358
-				PUSH(c);
359
-			} else if (c == 'n') {
360
-				PUSH('\n');
361
-			} else if (c == 'r') {
362
-				PUSH('\r');
363
-			} else if (c == 't') {
364
-				PUSH('\t');
365
-			} else if (IS_EOL(c)) {
366
-				     /* Do nothing */
367
-			} else {
368
-				ERR("%s:%d:%d: Unsupported escape character 0x%x\n", 
369
-				    pstate.file, pstate.line, pstate.col, c);
370
-				return -1;
371
-			}
372
-			state = ST_Q;
373
-			break;
374
-
375
-		case ST_C:
376
-			if (IS_ESCAPE(c)) {
377
-				state = ST_CE;
378
-			} else if (IS_EOL(c)) {
379
-				state = ST_S;
380
-				continue; /* Do not read a new char, return EOL */
381
-			} else {
382
-				     /* Do nothing */
383
-			}
384
-			break;
385
-
386
-		case ST_CE:
387
-			state = ST_C;
388
-			break;
389
-
390
-		case ST_E:
391
-			if (IS_COMMENT(c) ||
392
-			    IS_QUOTE(c) ||
393
-			    IS_ESCAPE(c)) {
394
-				PUSH(c);
395
-				RETURN(c);
396
-			} else if (c == 'r') {
397
-				PUSH('\r');
398
-				RETURN('\r');
399
-			} else if (c == 'n') {
400
-				PUSH('\n');
401
-				RETURN('\n');
402
-			} else if (c == 't') {
403
-				PUSH('\t');
404
-				RETURN('\t');
405
-			} else if (c == ' ') {
406
-				PUSH(' ');
407
-				RETURN(' ');
408
-			} else if (IS_EOL(c)) {
409
-				     /* Escped eol means no eol */
410
-				state = ST_S;
411
-			} else {
412
-				ERR("%s:%d:%d: Unsupported escape character 0x%x\n", 
413
-				    pstate.file, pstate.line, pstate.col, c);
414
-				return -1;
415
-			}
416
-			break;
417
-		}
418
-
419
-		READ_CHAR;
420
-	};
421
-
422
-	switch(state) {
423
-	case ST_S: 
424
-	case ST_C:
425
-	case ST_CE:
426
-		return 0;
427
-
428
-	case ST_A:
429
-		RETURN(TOKEN_ALPHA);
430
-
431
-	case ST_Q:
432
-		ERR("%s:%d:%d: Premature end of file, missing closing quote in"
433
-				" string constant\n", pstate.file, pstate.line, pstate.col);
434
-		return -1;
435
-
436
-	case ST_QE:
437
-	case ST_E:
438
-	case ST_AE:
439
-		ERR("%s:%d:%d: Premature end of file, missing escaped character\n", 
440
-		    pstate.file, pstate.line, pstate.col);
441
-		return -1;
442
-	}
443
-	BUG("%s:%d:%d: invalid state %d\n",
444
-			pstate.file, pstate.line, pstate.col, state);
445
-		return -1;
446
-}
447
-
448
-
449
-static struct parser_tab* lookup_token(struct parser_tab* table, str* token)
450
-{
451
-	struct parser_tab* ptr;
452
-
453
-	ptr = table;
454
-	while(ptr->token.s && ptr->token.len) {
455
-		if (token->len == ptr->token.len && 
456
-		    !strncasecmp(token->s, ptr->token.s, token->len)) {
457
-			return ptr;
458
-		}
459
-		ptr++;
460
-	}
461
-	return 0;
462
-}
463
-
464
-static int parse_string_val(str* res, token_t* token)
465
-{
466
-	int ret;
467
-	static token_t t;
468
-
469
-	ret = tls_lex(&t, 0);
470
-	if (ret < 0) return -1;
471
-	if (ret == 0) {
472
-		LOG(L_ERR, "ERROR:%s:%d:%d: Option value missing\n", 
473
-		    pstate.file, token->start.line, token->start.col);
474
-		return -1;
475
-	}
476
-
477
-	if (t.type != '=') {
478
-		LOG(L_ERR, "ERROR:%s:%d:%d: Syntax error, '=' expected\n", 
479
-		    pstate.file, t.start.line, t.start.col);
480
-		return -1;
481
-	}
482
-
483
-	ret = tls_lex(&t, EXTENDED_ALPHA_TOKEN);
484
-	if (ret < 0) return -1;
485
-	if (ret == 0) {
486
-		LOG(L_ERR, "ERROR:%s:%d:%d: Option value missing\n",
487
-		    pstate.file, t.start.line, t.start.col);
488
-		return -1;
489
-	}	
490
-
491
-	if (t.type != TOKEN_ALPHA && t.type != TOKEN_STRING) {
492
-		LOG(L_ERR, "ERROR:%s:%d:%d: Invalid option value '%.*s'\n", 
493
-		    pstate.file, t.start.line, t.start.col,
494
-		    t.val.len, ZSW(t.val.s));
495
-		return -1;
496
-	}
497
-
498
-	*res = t.val;;
499
-	return 0;
500
-}
501
-
502
-
503
-/*
504
- * Parse method option
505
- */
506
-static int parse_method_opt(token_t* token)
507
-{
508
-	int ret;
509
-	token_t t;
510
-	struct parser_tab* r;
511
-
512
-	ret = tls_lex(&t, 0);
513
-	if (ret < 0) return -1;
514
-	if (ret == 0) {
515
-		LOG(L_ERR, "ERROR:%s:%d:%d: Option value missing\n", 
516
-		    pstate.file, token->start.line, token->start.col);
517
-		return -1;
518
-	}
519
-
520
-	if (t.type != '=') {
521
-		LOG(L_ERR, "ERROR:%s:%d:%d: Syntax error, '=' expected\n", 
522
-		    pstate.file, t.start.line, t.start.col);
523
-		return -1;
524
-	}
525
-
526
-	ret = tls_lex(&t, EXTENDED_ALPHA_TOKEN);
527
-	if (ret < 0) return -1;
528
-	if (ret == 0) {
529
-		LOG(L_ERR, "ERROR:%s:%d:%d: Option value missing\n",
530
-		    pstate.file, t.start.line, t.start.col);
531
-		return -1;
532
-	}	
533
-
534
-	if (t.type != TOKEN_ALPHA && t.type != TOKEN_STRING) {
535
-		LOG(L_ERR, "ERROR:%s:%d:%d: Invalid option value '%.*s'\n", 
536
-		    pstate.file, t.start.line, t.start.col,
537
-		    t.val.len, ZSW(t.val.s));
538
-		return -1;
539
-	}
540
-
541
-	r = lookup_token(token_method, &t.val);
542
-	if (!r) {
543
-		LOG(L_ERR, "ERROR:%s:%d:%d: Invalid option value '%.*s'\n", 
544
-		    pstate.file, t.start.line, t.start.col,
545
-		    t.val.len, ZSW(t.val.s));
546
-		return -1;
547
-	}
548
-
549
-	pstate.domain->method = r->u.ival;
550
-	return 0;
551
-}
552
-
553
-
554
-/*
555
- * Parse boolean option value
556
- */
557
-static int parse_bool_val(int* res, token_t* token)
558
-{
559
-	int ret;
560
-	token_t t;
561
-	struct parser_tab* r;
562
-	
563
-	ret = tls_lex(&t, 0);
564
-	if (ret < 0) return -1;
565
-
566
-	     /* No token or EOL means that the option did not have value, and
567
-	      * since we are parsing a boolean option we would assume true
568
-	      */
569
-	if (ret == 0 || t.type == '\n') {
570
-		*res = 1;
571
-		return 0;
572
-	}
573
-	
574
-	if (t.type != '=') {
575
-		LOG(L_ERR, "ERROR:%s:%d:%d: Syntax error, '=' expected\n", 
576
-		    pstate.file, t.start.line, t.start.col);
577
-		return -1;
578
-	}
579
-
580
-	ret = tls_lex(&t, EXTENDED_ALPHA_TOKEN);
581
-	if (ret < 0) return -1;
582
-	if (ret == 0) {
583
-		LOG(L_ERR, "ERROR:%s:%d:%d: Option value missing\n", 
584
-		    pstate.file, t.start.line, t.start.col);
585
-		return -1;
586
-	}
587
-
588
-	if (t.type != TOKEN_ALPHA && t.type != TOKEN_STRING) {
589
-		LOG(L_ERR, "ERROR:%s:%d:%d: Invalid option value '%.*s', boolean expected\n", 
590
-		    pstate.file, t.start.line, t.start.col,
591
-		    t.val.len, ZSW(t.val.s));
592
-		return -1;
593
-	}
594
-
595
-	r = lookup_token(token_bool, &t.val);
596
-	if (!r) {
597
-		LOG(L_ERR, "ERROR:%s:%d:%d: Invalid option value '%.*s', boolean expected\n", 
598
-		    pstate.file, t.start.line, t.start.col,
599
-		    t.val.len, ZSW(t.val.s));
600
-		return -1;
601
-	}
602
-	
603
-	*res = r->u.ival;
604
-	return 0;
605
-
606
-}
607
-
608
-
609
-static int parse_verify_cert_opt(token_t* token)
610
-{
611
-	int ret;
612
-	if (parse_bool_val(&ret, token) < 0) return -1;
613
-	pstate.domain->verify_cert  = ret;
614
-	return 0;
615
-}
616
-
617
-
618
-static int parse_verify_depth_opt(token_t* token)
619
-{
620
-	unsigned int val;
621
-	int ret;
622
-	token_t t;
623
-
624
-	ret = tls_lex(&t, 0);
625
-	if (ret < 0) return -1;
626
-	if (ret == 0) {
627
-		LOG(L_ERR, "ERROR:%s:%d:%d: Option value missing\n", 
628
-		    pstate.file, token->start.line, token->start.col);
629
-		return -1;
630
-	}
631
-
632
-	if (t.type != '=') {
633
-		LOG(L_ERR, "ERROR:%s:%d:%d: Syntax error, '=' expected\n", 
634
-		    pstate.file, t.start.line, t.start.col);
635
-		return -1;
636
-	}
637
-
638
-	ret = tls_lex(&t, EXTENDED_ALPHA_TOKEN);
639
-	if (ret < 0) return -1;
640
-	if (ret == 0) {
641
-		LOG(L_ERR, "ERROR:%s:%d:%d: Option value missing\n", 
642
-		    pstate.file, t.start.line, t.start.col);
643
-		return -1;
644
-	}	
645
-
646
-	if (t.type != TOKEN_ALPHA) {
647
-		LOG(L_ERR, "ERROR:%s:%d:%d: Invalid option value '%.*s', number expected\n", 
648
-		    pstate.file, t.start.line, t.start.col,
649
-		    t.val.len, ZSW(t.val.s));
650
-		return -1;
651
-	}
652
-
653
-	if (str2int(&t.val, &val) < 0) {
654
-		LOG(L_ERR, "ERROR:%s:%d:%d: Invalid number '%.*s'\n", 
655
-		    pstate.file, t.start.line, t.start.col,
656
-		    t.val.len, ZSW(t.val.s));
657
-
658
-		return -1;
659
-	}
660
-	pstate.domain->verify_depth = val;
661
-	return 0;
662
-}
663
-
664
-
665
-static int parse_req_cert_opt(token_t* token)
666
-{
667
-	int ret;
668
-	if (parse_bool_val(&ret, token) < 0) return -1;
669
-	pstate.domain->require_cert  = ret;
670
-	return 0;
671
-}
672
-
673
-
674
-/*
675
- * Parse filename value, the function would add CFG_DIR prefix
676
- * if the filename does not start with /. The result is allocated
677
- * using shm_malloc and must be freed using shm_free
678
- */
679
-static char* parse_file_val(token_t* token)
680
-{
681
-	char* file, *res;
682
-	str val;
683
-	if (parse_string_val(&val, token) < 0) return 0;
684
-	file = get_abs_pathname(&tls_cfg_file, &val);
685
-	if (!file) return 0;
686
-	if (shm_asciiz_dup(&res, file) < 0) {
687
-		free(file);
688
-		return 0;
689
-	}
690
-	free(file);
691
-	return res;
692
-}
693
-
38
+#include "../../cfg_parser.h"
694 39
 
695
-static int parse_pkey_opt(token_t* token)
696
-{
697
-	char* file;
698
-	file = parse_file_val(token);
699
-	if (!file) return -1;
700
-	pstate.domain->pkey_file = file;
701
-	return 0;
702
-}
703
-
704
-static int parse_ca_list_opt(token_t* token)
705
-{
706
-	char* file;
707
-	file = parse_file_val(token);
708
-	if (!file) return -1;
709
-	pstate.domain->ca_file = file;
710
-	return 0;
711
-}
40
+#include "../../resolve.h"
41
+#include "../../mem/mem.h"
42
+#include "../../dprint.h"
43
+#include "../../trim.h"
44
+#include "../../ut.h"
712 45
 
713
-static int parse_cert_opt(token_t* token)
714
-{
715
-	char* file;
716
-	file = parse_file_val(token);
717
-	if (!file) return -1;
718
-	pstate.domain->cert_file = file;
719
-	return 0;
720
-}
46
+static tls_cfg_t* cfg = NULL;
47
+static tls_domain_t* domain = NULL;
721 48
 
722
-static int parse_cipher_list_opt(token_t* token)
723
-{
724
-	str val;
725
-	if (parse_string_val(&val, token) < 0) return -1;
726
-	if (shm_str_dup(&pstate.domain->cipher_list, &val) < 0) return -1;
727
-	return 0;
728
-}
729 49
 
730
-static int parse_ipv6(struct ip_addr* ip, token_t* token)
50
+static int parse_ipv6(struct ip_addr* ip, cfg_token_t* token, 
51
+					  cfg_parser_t* st)
731 52
 {
732 53
 	int ret;
733
-	token_t t;
54
+	cfg_token_t t;
734 55
 	struct ip_addr* ipv6;
735 56
 	str ip6_str;
736 57
 
737
-	ip6_str.s=t.val.s;
58
+	ip6_str.s = t.val.s;
738 59
 	while(1) {
739
-		ret = tls_lex(&t, 0);
60
+		ret = cfg_get_token(&t, st, 0);
740 61
 		if (ret <= 0) goto err;
741 62
 		if (t.type == ']') break;
742
-		if (t.type != TOKEN_ALPHA && t.type != ':') goto err;
63
+		if (t.type != CFG_TOKEN_ALPHA && t.type != ':') goto err;
743 64
 	}
744
-	ip6_str.len=(int)(long)(t.val.s-ip6_str.s);
65
+	ip6_str.len = (int)(long)(t.val.s - ip6_str.s);
745 66
 
746
-	ipv6=str2ip6(&ip6_str);
747
-	if (ipv6==0)  goto err;
748
-	*ip=*ipv6;
67
+	ipv6 = str2ip6(&ip6_str);
68
+	if (ipv6 == 0) goto err;
69
+	*ip = *ipv6;
749 70
 	return 0;
71
+
750 72
  err:
751
-	LOG(L_ERR, "ERROR:%s:%d:%d: Invalid IPv6 address\n", 
752
-	    pstate.file, token->start.line, token->start.col);
73
+	ERR("%s:%d:%d: Invalid IPv6 address\n", 
74
+	    st->file, token->start.line, token->start.col);
753 75
 	return -1;
754 76
 }
755 77
 
756
-static int parse_ipv4(struct ip_addr* ip, token_t* token)
78
+
79
+static int parse_ipv4(struct ip_addr* ip, cfg_token_t* token, 
80
+					  cfg_parser_t* st)
757 81
 {
758 82
 	int ret, i;
759
-	token_t  t;
83
+	cfg_token_t  t;
760 84
 	unsigned int v;
761 85
 
762 86
 	ip->af = AF_INET;
... ...
@@ -768,13 +92,13 @@ static int parse_ipv4(struct ip_addr* ip, token_t* token)
768 92
 	ip->u.addr[0] = v;
769 93
 
770 94
 	for(i = 1; i < 4; i++) {
771
-		ret = tls_lex(&t, 0);
95
+		ret = cfg_get_token(&t, st, 0);
772 96
 		if (ret < 0) return -1;
773 97
 		if (ret == 0 || t.type != '.')  goto err;
774 98
 		
775
-		ret = tls_lex(&t, 0);
99
+		ret = cfg_get_token(&t, st, 0);
776 100
 		if (ret < 0) return -1;
777
-		if (ret == 0 || t.type != TOKEN_ALPHA) goto err;
101
+		if (ret == 0 || t.type != CFG_TOKEN_ALPHA) goto err;
778 102
 		if (str2int(&t.val, &v) < 0)  goto err;
779 103
 		if (v < 0 || v > 255) goto err;
780 104
 		ip->u.addr[i] = v;
... ...
@@ -782,80 +106,150 @@ static int parse_ipv4(struct ip_addr* ip, token_t* token)
782 106
 
783 107
 	return 0;
784 108
  err:
785
-	LOG(L_ERR, "ERROR:%s:%d:%d: Invalid IPv4 address\n", 
786
-	    pstate.file, token->start.line, token->start.col);
109
+	ERR("%s:%d:%d: Invalid IPv4 address\n", 
110
+	    st->file, token->start.line, token->start.col);
787 111
 	return -1;
788 112
 }
789 113
 
790
-static int parse_hostport(int* type, struct ip_addr* ip, unsigned int* port, token_t* token)
114
+
115
+static cfg_option_t methods[] = { 
116
+	{"SSLv2",  .val = TLS_USE_SSLv2},
117
+	{"SSLv3",  .val = TLS_USE_SSLv3},
118
+	{"SSLv23", .val = TLS_USE_SSLv23},
119
+	{"TLSv1",  .val = TLS_USE_TLSv1},
120
+	{0}
121
+};
122
+
123
+
124
+static cfg_option_t domain_types[] = {
125
+	{"server", .val = TLS_DOMAIN_SRV},
126
+	{"srv",    .val = TLS_DOMAIN_SRV},
127
+	{"s",      .val = TLS_DOMAIN_SRV},
128
+	{"client", .val = TLS_DOMAIN_CLI},
129
+	{"cli",    .val = TLS_DOMAIN_CLI},
130
+	{"c",      .val = TLS_DOMAIN_CLI}, 
131
+	{0}
132
+};
133
+
134
+
135
+static cfg_option_t token_default[] = { 
136
+	{"default"},
137
+	{"def"},
138
+	{"*"},
139
+	{0}
140
+};
141
+
142
+
143
+static cfg_option_t options[] = {
144
+	{"method",              .param = methods, .f = cfg_parse_enum_val},
145
+	{"tls_method",          .param = methods, .f = cfg_parse_enum_val},
146
+	{"verify_certificate",  .f = cfg_parse_bool_val},
147
+	{"verify_cert",         .f = cfg_parse_bool_val},
148
+	{"verify_depth",        .f = cfg_parse_int_val},
149
+	{"require_certificate", .f = cfg_parse_bool_val},
150
+	{"require_cert",        .f = cfg_parse_bool_val},
151
+	{"private_key",         .f = cfg_parse_str_val, .flags = CFG_STR_SHMMEM},
152
+	{"pkey_file",           .f = cfg_parse_str_val, .flags = CFG_STR_SHMMEM},
153
+	{"calist_file",         .f = cfg_parse_str_val, .flags = CFG_STR_SHMMEM},
154
+	{"certificate",         .f = cfg_parse_str_val, .flags = CFG_STR_SHMMEM},
155
+	{"cert_file",           .f = cfg_parse_str_val, .flags = CFG_STR_SHMMEM},
156
+	{"cipher_list",         .f = cfg_parse_str_val, .flags = CFG_STR_SHMMEM},
157
+	{"ca_list",             .f = cfg_parse_str_val, .flags = CFG_STR_SHMMEM},
158
+	{0}
159
+};
160
+
161
+
162
+static void update_opt_variables(void)
163
+{
164
+	int i;
165
+	for(i = 0; methods[i].name; i++) {
166
+		methods[i].param = &domain->method;
167
+	}
168
+	options[2].param = &domain->verify_cert;
169
+	options[3].param = &domain->verify_cert;
170
+	options[4].param = &domain->verify_depth;
171
+	options[5].param = &domain->require_cert;
172
+	options[6].param = &domain->require_cert;
173
+	options[7].param = &domain->pkey_file;
174
+	options[8].param = &domain->pkey_file;
175
+	options[9].param = &domain->ca_file;
176
+	options[10].param = &domain->cert_file;
177
+	options[11].param = &domain->cert_file;
178
+	options[12].param = &domain->cipher_list;
179
+	options[13].param = &domain->ca_file;
180
+}
181
+
182
+
183
+static int parse_hostport(int* type, struct ip_addr* ip, unsigned int* port, 
184
+						  cfg_token_t* token, cfg_parser_t* st)
791 185
 {
792 186
 	int ret;
793
-	token_t t;
794
-	struct parser_tab* r;
187
+	cfg_token_t t;
188
+    cfg_option_t* opt;
795 189
 
796
-	ret = tls_lex(&t, 0);
190
+	ret = cfg_get_token(&t, st, 0);
797 191
 	if (ret < 0) return -1;
798 192
 	if (ret == 0) {
799
-		LOG(L_ERR, "ERROR:%s:%d:%d: Missing IP address\n", 
800
-		    pstate.file, token->start.line, token->start.col);
193
+		ERR("%s:%d:%d: Missing IP address\n", st->file, 
194
+			token->start.line, token->start.col);
801 195
 		return -1;
802 196
 	}
803 197
 
804 198
 	if (t.type == '[') {
805
-		if (parse_ipv6(ip, &t) < 0) return -1;
806
-	} else if (t.type == TOKEN_ALPHA) {
807
-		r = lookup_token(token_default, &t.val);
808
-		if (r) {
199
+		if (parse_ipv6(ip, &t, st) < 0) return -1;
200
+	} else if (t.type == CFG_TOKEN_ALPHA) {
201
+		opt = cfg_lookup_token(token_default, &t.val);
202
+		if (opt) {
809 203
 			*type = TLS_DOMAIN_DEF;
810 204
 			     /* Default domain */
811 205
 			return 0;
812 206
 		} else {
813
-			if (parse_ipv4(ip, &t) < 0) return -1;
207
+			if (parse_ipv4(ip, &t, st) < 0) return -1;
814 208
 		}
815 209
 	} else {
816
-		LOG(L_ERR, "ERROR:%s:%d:%d: Syntax error, IP address expected\n", 
817
-		    pstate.file, t.start.line, t.start.col);
210
+		ERR("%s:%d:%d: Syntax error, IP address expected\n", 
211
+		    st->file, t.start.line, t.start.col);
818 212
 		return -1;
819 213
 	}
820 214
 	*type = 0;
821 215
 
822 216
 	     /* Parse port */
823
-	ret = tls_lex(&t, 0);
217
+	ret = cfg_get_token(&t, st, 0);
824 218
 	if (ret < 0) return -1;
825 219
 	if (ret == 0) {
826
-		LOG(L_ERR, "ERROR:%s:%d:%d: Syntax error, ':' expected\n", 
827
-		    pstate.file, pstate.line, pstate.col);
220
+		ERR("%s:%d:%d: Syntax error, ':' expected\n", st->file, st->line, 
221
+			st->col);
828 222
 		return -1;
829 223
 	}
830
-
224
+	
831 225
 	if (t.type != ':') {
832
-		LOG(L_ERR, "ERROR:%s:%d:%d: Syntax error, ':' expected\n", 
833
-		    pstate.file, t.start.line, t.start.col);
226
+		ERR("%s:%d:%d: Syntax error, ':' expected\n", 
227
+		    st->file, t.start.line, t.start.col);
834 228
 		return -1;
835 229
 	}	
836
-
837
-	ret = tls_lex(&t, 0);
230
+	
231
+	ret = cfg_get_token(&t, st, 0);
838 232
 	if (ret < 0) return -1;
839 233
 	if (ret == 0) {
840
-		LOG(L_ERR, "ERROR:%s:%d:%d: Premature end of file, port number missing\n", 
841
-		    pstate.file, t.start.line, t.start.col);
234
+		ERR("%s:%d:%d: Premature end of file, port number missing\n", 
235
+		    st->file, t.start.line, t.start.col);
842 236
 		return -1;
843 237
 	}
844
-
845
-	if (t.type != TOKEN_ALPHA || (str2int(&t.val, port) < 0)) {
846
-		LOG(L_ERR, "ERROR:%s:%d:%d: Invalid port number '%.*s'\n", 
847
-		    pstate.file, t.start.line, t.start.col,
848
-		    t.val.len, ZSW(t.val.s));
238
+	
239
+	if (t.type != CFG_TOKEN_ALPHA || (str2int(&t.val, port) < 0)) {
240
+		ERR("%s:%d:%d: Invalid port number '%.*s'\n", 
241
+		    st->file, t.start.line, t.start.col, STR_FMT(&t.val));
849 242
 		return -1;
850 243
 	}		
851 244
 	return 0;
852 245
 }
853 246
 
854
-static int parse_domain(token_t* token)
247
+
248
+static int parse_domain(void* param, cfg_parser_t* st, unsigned int flags)
855 249
 {
856
-	token_t t;
250
+	cfg_token_t t;
857 251
 	int ret;
858
-	struct parser_tab* r;
252
+	cfg_option_t* opt;
859 253
 
860 254
 	int type;
861 255
 	struct ip_addr ip;
... ...
@@ -863,127 +257,70 @@ static int parse_domain(token_t* token)
863 257
 
864 258
 	memset(&ip, 0, sizeof(struct ip_addr));
865 259
 
866
-	ret = tls_lex(&t, 0);
260
+	ret = cfg_get_token(&t, st, 0);
867 261
 	if (ret < 0) return -1;
868 262
 	if (ret == 0) {
869
-		LOG(L_ERR, "ERROR:%s:%d:%d: TLS domain type missing\n", 
870
-		    pstate.file, token->start.line, token->start.col);
263
+		ERR("%s:%d:%d: TLS domain type missing\n", 
264
+		    st->file, st->line, st->col);
871 265
 		return -1;
872 266
 	}
873 267
 
874
-	if (t.type != TOKEN_ALPHA || 
875
-	    ((r = lookup_token(token_type, &t.val)) == NULL)) {
876
-		LOG(L_ERR, "ERROR:%s:%d:%d: Invalid TLS domain type %d:'%.*s'\n", 
877
-		    pstate.file, t.start.line, t.start.col,
878
-		    t.type, t.val.len, ZSW(t.val.s));
268
+	if (t.type != CFG_TOKEN_ALPHA || 
269
+	    ((opt = cfg_lookup_token(domain_types, &t.val)) == NULL)) {
270
+		ERR("%s:%d:%d: Invalid TLS domain type %d:'%.*s'\n", 
271
+		    st->file, t.start.line, t.start.col, t.type, STR_FMT(&t.val));
879 272
 		return -1;
880 273
 	}
881 274
 	
882
-	ret = tls_lex(&t, 0);
275
+	ret = cfg_get_token(&t, st, 0);
883 276
 	if (ret < 0) return -1;
884 277
 	if (ret == 0) {
885
-		LOG(L_ERR, "ERROR:%s:%d:%d: TLS domain IP address missing\n", 
886
-		    pstate.file, t.start.line, t.start.col);
278
+		ERR("%s:%d:%d: TLS domain IP address missing\n", 
279
+		    st->file, st->line, st->col);
887 280
 		return -1;
888 281
 	}
889 282
 	if (t.type != ':') {
890
-		LOG(L_ERR, "ERROR:%s:%d:%d: Syntax error, ':' expected\n", 
891
-		    pstate.file, t.start.line, t.start.col);
283
+		ERR("%s:%d:%d: Syntax error, ':' expected\n", 
284
+		    st->file, t.start.line, t.start.col);
892 285
 		return -1;
893 286
 	}	
894 287
 
895
-	port=0;
896
-	if (parse_hostport(&type, &ip, &port, &t) < 0) return -1;
288
+	port = 0;
289
+	if (parse_hostport(&type, &ip, &port, &t, st) < 0) return -1;
897 290
 
898
-	ret = tls_lex(&t, 0);
291
+	ret = cfg_get_token(&t, st, 0);
899 292
 	if (ret < 0) return -1;
900 293
 	if (ret == 0) {
901
-		LOG(L_ERR, "ERROR:%s:%d:%d: Closing ']' missing\n", 
902
-		    pstate.file, t.start.line, t.start.col);
294
+		ERR("%s:%d:%d: Closing ']' missing\n", 
295
+		    st->file, st->line, st->col);
903 296
 		return -1;
904 297
 	}
905 298
 	if (t.type != ']') {
906
-		LOG(L_ERR, "ERROR:%s:%d:%d: Syntax error, ']' expected\n", 
907
-		    pstate.file, t.start.line, t.start.col);
299
+		ERR("%s:%d:%d: Syntax error, ']' expected\n", 
300
+		    st->file, t.start.line, t.start.col);
908 301
 		return -1;
909 302
 	}	
910 303
 
911
-	pstate.domain = tls_new_domain(r->u.ival | type, &ip, port);
912
-	if (!pstate.domain) {
913
-		LOG(L_ERR, "ERROR:%s:%d: Cannot create TLS domain structure\n", 
914
-		    pstate.file, token->start.line);
304
+	if ((domain = tls_new_domain(opt->val | type, &ip, port)) == NULL) {
305
+		ERR("%s:%d: Cannot create TLS domain structure\n", st->file, st->line);
915 306
 		return -1;
916 307
 	}
917 308
 
918
-	ret = tls_add_domain(pstate.cfg, pstate.domain);
309
+	ret = tls_add_domain(cfg, domain);
919 310
 	if (ret < 0) {
920
-		LOG(L_ERR, "ERROR:%s:%d: Error while creating TLS domain structure\n", 
921
-		    pstate.file, token->start.line);
922
-		tls_free_domain(pstate.domain);
311
+		ERR("%s:%d: Error while creating TLS domain structure\n", st->file, 
312
+			st->line);
313
+		tls_free_domain(domain);
923 314
 		return -1;
924 315
 	} else if (ret == 1) {
925
-		LOG(L_ERR, "ERROR:%s:%d: Duplicate TLS domain (appears earlier in the config file)\n", 
926
-		    pstate.file, token->start.line);
927
-		tls_free_domain(pstate.domain);
316
+		ERR("%s:%d: Duplicate TLS domain (appears earlier in the config file)\n", 
317
+		    st->file, st->line);
318
+		tls_free_domain(domain);
928 319
 		return -1;
929 320
 	}
930
-
931
-	return 0;
932
-}
933
-
934
-static int parse_config(void)
935
-{
936
-	int ret;
937
-	token_t token;
938
-	struct parser_tab* r;
939
-
940
-	while(1) {
941
-		     /* Get option name */
942
-		ret = tls_lex(&token, 0);
943
-		if (ret <= 0) return ret;
944
-
945
-		switch(token.type) {
946
-		case TOKEN_ALPHA:
947
-			if (!pstate.domain) {
948
-				LOG(L_ERR, "ERROR:%s:%d: You need to specify TLS domain first\n", 
949
-				    pstate.file, token.start.line);
950
-				return -1;
951
-			}
952
-
953
-			     /* Lookup the option name */
954
-			r = lookup_token(option_name, &token.val);
955
-			if (!r) {
956
-				LOG(L_ERR, "ERROR:%s:%d: Unsupported option '%.*s'\n", 
957
-				    pstate.file, token.start.line, 
958
-				    token.val.len, ZSW(token.val.s));
959
-				return -1;
960
-			}
961
-			     /* Parse the option value */
962
-			if (r->u.fval(&token) < 0) return -1;
963
-			break;
964
-
965
-		case '[': 
966
-			if (parse_domain(&token) < 0) return -1;
967
-			break;
968
-
969
-			     /* Empty line */
970
-		case '\n': continue;
971
-
972
-		default:
973
-			LOG(L_ERR, "ERROR:%s:%d:%d: Syntax error\n", 
974
-			    pstate.file, token.start.line, token.start.col);
975
-			return -1;
976
-		}
977
-
978
-		     /* Skip EOL */
979
-		ret = tls_lex(&token, 0);
980
-		if (ret <= 0) return ret;
981
-		if (token.type != '\n') {
982
-			LOG(L_ERR, "ERROR:%s:%d:%d: End of line expected\n", 
983
-			    pstate.file, token.start.line, token.start.col);
984
-			return -1;
985
-		}
986
-	}
321
+	
322
+	update_opt_variables();
323
+	cfg_set_options(st, options);
987 324
 	return 0;
988 325
 }
989 326
 
... ...
@@ -993,113 +330,46 @@ static int parse_config(void)
993 330
  */
994 331
 tls_cfg_t* tls_load_config(str* filename)
995 332
 {
996
-	char* file;
333
+	cfg_parser_t* parser;
997 334
 
998
-	file = get_abs_pathname(NULL, filename);
999
-	if (!file) return 0;
335
+	parser = NULL;
336
+	if ((cfg = tls_new_cfg()) == NULL) goto error;
1000 337
 
1001
-	pstate.f = fopen(file, "r");
1002
-	if (pstate.f == NULL) {
1003
-		ERR("Unable to open TLS config file '%s'\n", file);
1004
-		free(file);
1005
-		return 0;
338
+	if ((parser = cfg_parser_init(filename)) == NULL) {
339
+		ERR("tls: Error while initializing configuration file parser.\n");
340
+		goto error;
1006 341
 	}
1007
-	pstate.file = basename(file);
1008
-	pstate.line = 1;
1009
-	pstate.col = 0;
1010
-	pstate.domain = 0;
1011 342
 
1012
-	pstate.cfg = tls_new_cfg();
1013
-	if (!pstate.cfg) goto error;
1014
-	
1015
-	if (parse_config() < 0) goto error;
343
+	cfg_section_parser(parser, parse_domain, NULL);
1016 344
 
1017
-	fclose(pstate.f);
1018
-	free(file);
1019
-	return pstate.cfg;
345
+	if (cfg_parse(parser)) goto error;
346
+	cfg_parser_close(parser);
347
+	return cfg;
1020 348
 
1021 349
  error:
1022
-	free(file);
1023
-	if (pstate.cfg) tls_free_cfg(pstate.cfg);
1024
-	fclose(pstate.f);
350
+	if (parser) cfg_parser_close(parser);
351
+	if (cfg) tls_free_cfg(cfg);
1025 352
 	return 0;
1026 353
 }
1027 354
 
355
+
1028 356
 /*
1029 357
  * Convert TLS method string to integer
1030 358
  */
1031 359
 int tls_parse_method(str* method)
1032 360
 {
1033
-	struct parser_tab* r;
361
+    cfg_option_t* opt;
1034 362
 
1035
-	if (!method) {
1036
-		ERR("BUG: Invalid parameter value\n");
1037
-		return -1;
1038
-	}
363
+    if (!method) {
364
+        BUG("Invalid parameter value\n");
365
+        return -1;
366
+    }
1039 367
 
1040
-	r = lookup_token(token_method, method);
1041
-	if (!r) return -1;
368
+    opt = cfg_lookup_token(methods, method);
369
+    if (!opt) return -1;
1042 370
 
1043
-	return r->u.ival;
371
+    return opt->val;
1044 372
 }
1045 373
 
1046 374
 
1047
-static struct parser_tab token_type[] = {
1048
-	{STR_STATIC_INIT("server"), {.ival = TLS_DOMAIN_SRV}},
1049
-	{STR_STATIC_INIT("srv"),    {.ival = TLS_DOMAIN_SRV}},
1050
-	{STR_STATIC_INIT("s"),      {.ival = TLS_DOMAIN_SRV}},
1051
-	{STR_STATIC_INIT("client"), {.ival = TLS_DOMAIN_CLI}},
1052
-	{STR_STATIC_INIT("cli"),    {.ival = TLS_DOMAIN_CLI}},
1053
-	{STR_STATIC_INIT("c"),      {.ival = TLS_DOMAIN_CLI}}, 
1054
-	{STR_NULL}
1055
-};
1056
-
1057 375
 
1058
-static struct parser_tab token_bool[] = { 
1059
-	{STR_STATIC_INIT("yes"),      {.ival = 1}},
1060
-	{STR_STATIC_INIT("true"),     {.ival = 1}},
1061
-	{STR_STATIC_INIT("enable"),   {.ival = 1}},
1062
-	{STR_STATIC_INIT("enabled"),  {.ival = 1}},
1063
-	{STR_STATIC_INIT("1"),        {.ival = 1}},
1064
-	{STR_STATIC_INIT("on"),       {.ival = 1}},
1065
-	{STR_STATIC_INIT("no"),       {.ival = 0}},
1066
-	{STR_STATIC_INIT("false"),    {.ival = 0}},
1067
-	{STR_STATIC_INIT("disable"),  {.ival = 0}},
1068
-	{STR_STATIC_INIT("disabled"), {.ival = 0}},
1069
-	{STR_STATIC_INIT("0"),        {.ival = 0}},
1070
-	{STR_STATIC_INIT("off"),      {.ival = 0}},
1071
-	{STR_NULL}
1072
-};
1073
-
1074
-static struct parser_tab token_default[] = { 
1075
-	{STR_STATIC_INIT("default")},
1076
-	{STR_STATIC_INIT("def")},
1077
-	{STR_STATIC_INIT("*")},
1078
-	{STR_NULL}
1079
-};
1080
-
1081
-static struct parser_tab token_method[] = { 
1082
-	{STR_STATIC_INIT("SSLv2"),  {.ival = TLS_USE_SSLv2}},
1083
-	{STR_STATIC_INIT("SSLv3"),  {.ival = TLS_USE_SSLv3}},
1084
-	{STR_STATIC_INIT("SSLv23"), {.ival = TLS_USE_SSLv23}},
1085
-	{STR_STATIC_INIT("TLSv1"),  {.ival = TLS_USE_TLSv1}},
1086
-	{STR_NULL}
1087
-};
1088
-
1089
-static struct parser_tab option_name[] = {
1090
-	{STR_STATIC_INIT("method"),              {.fval = parse_method_opt}},
1091
-	{STR_STATIC_INIT("tls_method"),          {.fval = parse_method_opt}},
1092
-	{STR_STATIC_INIT("verify_certificate"),  {.fval = parse_verify_cert_opt}},
1093
-	{STR_STATIC_INIT("verify_cert"),         {.fval = parse_verify_cert_opt}},
1094
-	{STR_STATIC_INIT("verify_depth"),        {.fval = parse_verify_depth_opt}},
1095
-	{STR_STATIC_INIT("require_certificate"), {.fval = parse_req_cert_opt}},
1096
-	{STR_STATIC_INIT("require_cert"),        {.fval = parse_req_cert_opt}},
1097
-	{STR_STATIC_INIT("private_key"),         {.fval = parse_pkey_opt}},
1098
-	{STR_STATIC_INIT("pkey_file"),           {.fval = parse_pkey_opt}},
1099
-	{STR_STATIC_INIT("ca_list"),             {.fval = parse_ca_list_opt}},
1100
-	{STR_STATIC_INIT("calist_file"),         {.fval = parse_ca_list_opt}},
1101
-	{STR_STATIC_INIT("certificate"),         {.fval = parse_cert_opt}},
1102
-	{STR_STATIC_INIT("cert_file"),           {.fval = parse_cert_opt}},
1103
-	{STR_STATIC_INIT("cipher_list"),         {.fval = parse_cipher_list_opt}},
1104
-	{STR_NULL}
1105
-};
... ...
@@ -90,10 +90,10 @@ void tls_free_domain(tls_domain_t* d)
90 90
 		shm_free(d->ctx);
91 91
 	}
92 92
 
93
-	if (d->cipher_list) shm_free(d->cipher_list);
94
-	if (d->ca_file) shm_free(d->ca_file);
95
-	if (d->pkey_file) shm_free(d->pkey_file);
96
-	if (d->cert_file) shm_free(d->cert_file);
93
+	if (d->cipher_list.s) shm_free(d->cipher_list.s);
94
+	if (d->ca_file.s) shm_free(d->ca_file.s);
95
+	if (d->pkey_file.s) shm_free(d->pkey_file.s);
96
+	if (d->cert_file.s) shm_free(d->cert_file.s);
97 97
 	shm_free(d);
98 98
 }
99 99
 
... ...
@@ -179,24 +179,28 @@ static int fill_missing(tls_domain_t* d, tls_domain_t* parent)
179 179
 		return -1;
180 180
 	}
181 181
 	
182
-	if (!d->cert_file && 
183
-	    shm_asciiz_dup(&d->cert_file, parent->cert_file) < 0) return -1;
184
-	LOG(L_INFO, "%s: certificate='%s'\n", tls_domain_str(d), d->cert_file);
182
+	if (!d->cert_file.s && 
183
+	    shm_asciiz_dup(&d->cert_file.s, parent->cert_file.s) < 0) return -1;
184
+	d->cert_file.len = parent->cert_file.len;
185
+	LOG(L_INFO, "%s: certificate='%s'\n", tls_domain_str(d), d->cert_file.s);
185 186
 	
186
-	if (!d->ca_file &&
187
-	    shm_asciiz_dup(&d->ca_file, parent->ca_file) < 0) return -1;
188
-	LOG(L_INFO, "%s: ca_list='%s'\n", tls_domain_str(d), d->ca_file);
187
+	if (!d->ca_file.s &&
188
+	    shm_asciiz_dup(&d->ca_file.s, parent->ca_file.s) < 0) return -1;
189
+	d->ca_file.len = parent->ca_file.len;
190
+	LOG(L_INFO, "%s: ca_list='%s'\n", tls_domain_str(d), d->ca_file.s);
189 191
 	
190 192
 	if (d->require_cert == -1) d->require_cert = parent->require_cert;
191 193
 	LOG(L_INFO, "%s: require_certificate=%d\n", tls_domain_str(d), d->require_cert);
192 194
 	
193
-	if (!d->cipher_list &&
194
-	    shm_asciiz_dup(&d->cipher_list, parent->cipher_list) < 0) return -1;
195
-	LOG(L_INFO, "%s: cipher_list='%s'\n", tls_domain_str(d), d->cipher_list);
195
+	if (!d->cipher_list.s &&
196
+	    shm_asciiz_dup(&d->cipher_list.s, parent->cipher_list.s) < 0) return -1;
197
+	d->cipher_list.len = parent->cipher_list.len;
198
+	LOG(L_INFO, "%s: cipher_list='%s'\n", tls_domain_str(d), d->cipher_list.s);
196 199
 	
197
-	if (!d->pkey_file &&
198
-	    shm_asciiz_dup(&d->pkey_file, parent->pkey_file) < 0) return -1;
199
-	LOG(L_INFO, "%s: private_key='%s'\n", tls_domain_str(d), d->pkey_file);
200
+	if (!d->pkey_file.s &&
201
+	    shm_asciiz_dup(&d->pkey_file.s, parent->pkey_file.s) < 0) return -1;
202
+	d->pkey_file.len = parent->pkey_file.len;
203
+	LOG(L_INFO, "%s: private_key='%s'\n", tls_domain_str(d), d->pkey_file.s);
200 204
 	
201 205
 	if (d->verify_cert == -1) d->verify_cert = parent->verify_cert;
202 206
 	LOG(L_INFO, "%s: verify_certificate=%d\n", tls_domain_str(d), d->verify_cert);
... ...
@@ -216,16 +220,16 @@ static int load_cert(tls_domain_t* d)
216 220
 	int i;
217 221
 	int procs_no;
218 222
 
219
-	if (!d->cert_file) {
223
+	if (!d->cert_file.s) {
220 224
 		DBG("%s: No certificate configured\n", tls_domain_str(d));
221 225
 		return 0;
222 226
 	}
223 227
 
224 228
 	procs_no=get_max_procs();
225 229
 	for(i = 0; i < procs_no; i++) {
226
-		if (!SSL_CTX_use_certificate_chain_file(d->ctx[i], d->cert_file)) {
230
+		if (!SSL_CTX_use_certificate_chain_file(d->ctx[i], d->cert_file.s)) {
227 231
 			ERR("%s: Unable to load certificate file '%s'\n",
228
-			    tls_domain_str(d), d->cert_file);
232
+			    tls_domain_str(d), d->cert_file.s);
229 233
 			TLS_ERR("load_cert:");
230 234
 			return -1;
231 235
 		}
... ...
@@ -243,19 +247,19 @@ static int load_ca_list(tls_domain_t* d)
243 247
 	int i;
244 248
 	int procs_no;
245 249
 
246
-	if (!d->ca_file) {
250
+	if (!d->ca_file.s) {
247 251
 		DBG("%s: No CA list configured\n", tls_domain_str(d));
248 252
 		return 0;
249 253
 	}
250 254
 
251 255
 	procs_no=get_max_procs();
252 256
 	for(i = 0; i < procs_no; i++) {
253
-		if (SSL_CTX_load_verify_locations(d->ctx[i], d->ca_file, 0) != 1) {
254
-			ERR("%s: Unable to load CA list '%s'\n", tls_domain_str(d), d->ca_file);
257
+		if (SSL_CTX_load_verify_locations(d->ctx[i], d->ca_file.s, 0) != 1) {
258
+			ERR("%s: Unable to load CA list '%s'\n", tls_domain_str(d), d->ca_file.s);
255 259
 			TLS_ERR("load_ca_list:");
256 260
 			return -1;
257 261
 		}
258
-		SSL_CTX_set_client_CA_list(d->ctx[i], SSL_load_client_CA_file(d->ca_file));
262
+		SSL_CTX_set_client_CA_list(d->ctx[i], SSL_load_client_CA_file(d->ca_file.s));
259 263
 		if (SSL_CTX_get_client_CA_list(d->ctx[i]) == 0) {
260 264
 			ERR("%s: Error while setting client CA list\n", tls_domain_str(d));
261 265
 			TLS_ERR("load_ca_list:");
... ...
@@ -274,10 +278,10 @@ static int set_cipher_list(tls_domain_t* d)
274 278
 	int i;
275 279
 	int procs_no;
276 280
 
277
-	if (!d->cipher_list) return 0;
281
+	if (!d->cipher_list.s) return 0;
278 282
 	procs_no=get_max_procs();
279 283
 	for(i = 0; i < procs_no; i++) {
280
-		if (SSL_CTX_set_cipher_list(d->ctx[i], d->cipher_list) == 0 ) {
284
+		if (SSL_CTX_set_cipher_list(d->ctx[i], d->cipher_list.s) == 0 ) {
281 285
 			ERR("%s: Failure to set SSL context cipher list\n", tls_domain_str(d));
282 286
 			return -1;
283 287
 		}
... ...
@@ -479,7 +483,7 @@ static int load_private_key(tls_domain_t* d)
479 483
 	int idx, ret_pwd, i;
480 484
 	int procs_no;
481 485
 	
482
-	if (!d->pkey_file) {
486
+	if (!d->pkey_file.s) {
483 487
 		DBG("%s: No private key specified\n", tls_domain_str(d));
484 488
 		return 0;
485 489
 	}
... ...
@@ -487,15 +491,15 @@ static int load_private_key(tls_domain_t* d)
487 491
 	procs_no=get_max_procs();
488 492
 	for(i = 0; i < procs_no; i++) {
489 493
 		SSL_CTX_set_default_passwd_cb(d->ctx[i], passwd_cb);
490
-		SSL_CTX_set_default_passwd_cb_userdata(d->ctx[i], d->pkey_file);
494
+		SSL_CTX_set_default_passwd_cb_userdata(d->ctx[i], d->pkey_file.s);
491 495
 		
492 496
 		for(idx = 0, ret_pwd = 0; idx < NUM_RETRIES; idx++) {
493
-			ret_pwd = SSL_CTX_use_PrivateKey_file(d->ctx[i], d->pkey_file, SSL_FILETYPE_PEM);
497
+			ret_pwd = SSL_CTX_use_PrivateKey_file(d->ctx[i], d->pkey_file.s, SSL_FILETYPE_PEM);
494 498
 			if (ret_pwd) {
495 499
 				break;
496 500
 			} else {
497 501
 				ERR("%s: Unable to load private key '%s'\n",
498
-				    tls_domain_str(d), d->pkey_file);
502
+				    tls_domain_str(d), d->pkey_file.s);
499 503
 				TLS_ERR("load_private_key:");
500 504
 				continue;
501 505
 			}
... ...
@@ -503,21 +507,21 @@ static int load_private_key(tls_domain_t* d)
503 507
 		
504 508
 		if (!ret_pwd) {
505 509
 			ERR("%s: Unable to load private key file '%s'\n", 
506
-			    tls_domain_str(d), d->pkey_file);
510
+			    tls_domain_str(d), d->pkey_file.s);
507 511
 			TLS_ERR("load_private_key:");
508 512
 			return -1;
509 513
 		}
510 514
 		
511 515
 		if (!SSL_CTX_check_private_key(d->ctx[i])) {
512 516
 			ERR("%s: Key '%s' does not match the public key of the certificate\n", 
513
-			    tls_domain_str(d), d->pkey_file);
517
+			    tls_domain_str(d), d->pkey_file.s);
514 518
 			TLS_ERR("load_private_key:");
515 519
 			return -1;
516 520
 		}
517 521
 	}		
518 522
 
519 523
 	DBG("%s: Key '%s' successfuly loaded\n",
520
-	    tls_domain_str(d), d->pkey_file);
524
+	    tls_domain_str(d), d->pkey_file.s);
521 525
 	return 0;
522