2 8d1b399b 2021-07-22 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
3 8d1b399b 2021-07-22 op * Copyright (c) 2018 Florian Obser <florian@openbsd.org>
4 8d1b399b 2021-07-22 op * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
5 8d1b399b 2021-07-22 op * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
6 8d1b399b 2021-07-22 op * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
7 8d1b399b 2021-07-22 op * Copyright (c) 2001 Markus Friedl. All rights reserved.
8 8d1b399b 2021-07-22 op * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
9 8d1b399b 2021-07-22 op * Copyright (c) 2001 Theo de Raadt. All rights reserved.
11 8d1b399b 2021-07-22 op * Permission to use, copy, modify, and distribute this software for any
12 8d1b399b 2021-07-22 op * purpose with or without fee is hereby granted, provided that the above
13 8d1b399b 2021-07-22 op * copyright notice and this permission notice appear in all copies.
15 8d1b399b 2021-07-22 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16 8d1b399b 2021-07-22 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 8d1b399b 2021-07-22 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18 8d1b399b 2021-07-22 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 8d1b399b 2021-07-22 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 8d1b399b 2021-07-22 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 8d1b399b 2021-07-22 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 8d1b399b 2021-07-22 op #include "compat.h"
27 8d1b399b 2021-07-22 op #include <sys/stat.h>
29 8d1b399b 2021-07-22 op #include <ctype.h>
30 8d1b399b 2021-07-22 op #include <err.h>
31 8d1b399b 2021-07-22 op #include <errno.h>
32 8d1b399b 2021-07-22 op #include <event.h>
33 8d1b399b 2021-07-22 op #include <inttypes.h>
34 8d1b399b 2021-07-22 op #include <limits.h>
35 8d1b399b 2021-07-22 op #include <stdarg.h>
36 8d1b399b 2021-07-22 op #include <stdio.h>
37 8d1b399b 2021-07-22 op #include <stdlib.h>
38 8d1b399b 2021-07-22 op #include <string.h>
39 8d1b399b 2021-07-22 op #include <syslog.h>
40 8d1b399b 2021-07-22 op #include <unistd.h>
42 8d1b399b 2021-07-22 op #include "log.h"
43 8d1b399b 2021-07-22 op #include "kamid.h"
44 8d1b399b 2021-07-22 op #include "table.h"
45 8d1b399b 2021-07-22 op #include "utils.h"
47 8d1b399b 2021-07-22 op TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
48 8d1b399b 2021-07-22 op static struct file {
49 8d1b399b 2021-07-22 op TAILQ_ENTRY(file) entry;
52 8d1b399b 2021-07-22 op size_t ungetpos;
53 8d1b399b 2021-07-22 op size_t ungetsize;
54 8d1b399b 2021-07-22 op u_char *ungetbuf;
55 8d1b399b 2021-07-22 op int eof_reached;
58 8d1b399b 2021-07-22 op } *file, *topfile;
59 8d1b399b 2021-07-22 op struct file *pushfile(const char *, int);
60 8d1b399b 2021-07-22 op int popfile(void);
61 8d1b399b 2021-07-22 op int check_file_secrecy(int, const char *);
62 8d1b399b 2021-07-22 op int yyparse(void);
63 8d1b399b 2021-07-22 op int yylex(void);
64 8d1b399b 2021-07-22 op int yyerror(const char *, ...)
65 8d1b399b 2021-07-22 op __attribute__((__format__ (printf, 1, 2)))
66 8d1b399b 2021-07-22 op __attribute__((__nonnull__ (1)));
67 8d1b399b 2021-07-22 op int kw_cmp(const void *, const void *);
68 8d1b399b 2021-07-22 op int lookup(char *);
69 8d1b399b 2021-07-22 op int igetc(void);
70 8d1b399b 2021-07-22 op int lgetc(int);
71 8d1b399b 2021-07-22 op void lungetc(int);
72 8d1b399b 2021-07-22 op int findeol(void);
74 8d1b399b 2021-07-22 op TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
76 8d1b399b 2021-07-22 op TAILQ_ENTRY(sym) entry;
83 8d1b399b 2021-07-22 op int symset(const char *, const char *, int);
84 8d1b399b 2021-07-22 op char *symget(const char *);
86 8d1b399b 2021-07-22 op void clear_config(struct kd_conf *xconf);
88 8d1b399b 2021-07-22 op static void add_table(const char *, const char *, const char *);
89 8d1b399b 2021-07-22 op static struct table *findtable(const char *name);
90 8d1b399b 2021-07-22 op static void add_cert(const char *, const char *);
91 8d1b399b 2021-07-22 op static void add_key(const char *, const char *);
92 8d1b399b 2021-07-22 op static void add_listen(const char *, uint32_t, const char *, struct table *);
94 8d1b399b 2021-07-22 op static uint32_t counter;
95 8d1b399b 2021-07-22 op static struct table *table;
96 8d1b399b 2021-07-22 op static struct kd_conf *conf;
97 8d1b399b 2021-07-22 op static int errors;
99 8d1b399b 2021-07-22 op typedef struct {
101 8d1b399b 2021-07-22 op int64_t number;
102 8d1b399b 2021-07-22 op char *string;
103 8d1b399b 2021-07-22 op struct table *table;
113 8d1b399b 2021-07-22 op %token INCLUDE
115 8d1b399b 2021-07-22 op %token LISTEN
118 8d1b399b 2021-07-22 op %token PKI PORT
119 8d1b399b 2021-07-22 op %token TABLE TLS
122 8d1b399b 2021-07-22 op %token <v.string> STRING
123 8d1b399b 2021-07-22 op %token <v.number> NUMBER
124 8d1b399b 2021-07-22 op %type <v.number> yesno
125 8d1b399b 2021-07-22 op %type <v.string> string
126 8d1b399b 2021-07-22 op %type <v.table> tableref
130 8d1b399b 2021-07-22 op grammar : /* empty */
131 8d1b399b 2021-07-22 op | grammar include '\n'
132 8d1b399b 2021-07-22 op | grammar '\n'
133 8d1b399b 2021-07-22 op | grammar table '\n'
134 8d1b399b 2021-07-22 op | grammar pki '\n'
135 8d1b399b 2021-07-22 op | grammar listen '\n'
136 8d1b399b 2021-07-22 op | grammar varset '\n'
137 8d1b399b 2021-07-22 op | grammar error '\n' { file->errors++; }
140 8d1b399b 2021-07-22 op include : INCLUDE STRING {
141 8d1b399b 2021-07-22 op struct file *nfile;
143 8d1b399b 2021-07-22 op if ((nfile = pushfile($2, 0)) == NULL) {
144 8d1b399b 2021-07-22 op yyerror("failed to include file %s", $2);
150 8d1b399b 2021-07-22 op file = nfile;
151 8d1b399b 2021-07-22 op lungetc('\n');
155 8d1b399b 2021-07-22 op string : string STRING {
156 8d1b399b 2021-07-22 op if (asprintf(&$$, "%s %s", $1, $2) == -1) {
159 8d1b399b 2021-07-22 op yyerror("string: asprintf");
168 8d1b399b 2021-07-22 op yesno : YES { $$ = 1; }
169 8d1b399b 2021-07-22 op | NO { $$ = 0; }
172 8d1b399b 2021-07-22 op optnl : '\n' optnl /* zero or more newlines */
176 8d1b399b 2021-07-22 op nl : '\n' optnl /* one or more newlines */
179 8d1b399b 2021-07-22 op arrow : '=' '>' ;
181 8d1b399b 2021-07-22 op comma : ',' optnl
185 8d1b399b 2021-07-22 op varset : STRING '=' string {
186 8d1b399b 2021-07-22 op char *s = $1;
188 8d1b399b 2021-07-22 op printf("%s = \"%s\"\n", $1, $3);
189 8d1b399b 2021-07-22 op while (*s++) {
190 8d1b399b 2021-07-22 op if (isspace((unsigned char)*s)) {
191 8d1b399b 2021-07-22 op yyerror("macro name cannot contain "
192 8d1b399b 2021-07-22 op "whitespace");
198 8d1b399b 2021-07-22 op if (symset($1, $3, 0) == -1)
199 8d1b399b 2021-07-22 op fatal("cannot store variable");
205 8d1b399b 2021-07-22 op pki : PKI STRING CERT STRING { add_cert($2, $4); }
206 8d1b399b 2021-07-22 op | PKI STRING KEY STRING { add_key($2, $4); }
209 8d1b399b 2021-07-22 op table_kp : string arrow string {
210 8d1b399b 2021-07-22 op if (table_add(table, $1, $3) == -1)
211 8d1b399b 2021-07-22 op yyerror("can't add to table %s",
212 8d1b399b 2021-07-22 op table->t_name);
218 8d1b399b 2021-07-22 op table_kps : table_kp
219 8d1b399b 2021-07-22 op | table_kp comma table_kps
222 8d1b399b 2021-07-22 op stringel : STRING {
223 8d1b399b 2021-07-22 op if (table_add(table, $1, NULL) == -1)
224 8d1b399b 2021-07-22 op yyerror("can't add to table %s",
225 8d1b399b 2021-07-22 op table->t_name);
230 8d1b399b 2021-07-22 op string_list : stringel
231 8d1b399b 2021-07-22 op | stringel comma string_list
234 8d1b399b 2021-07-22 op table_vals : table_kps
235 8d1b399b 2021-07-22 op | string_list
238 8d1b399b 2021-07-22 op table : TABLE STRING STRING {
241 8d1b399b 2021-07-22 op if ((p = strchr($3, ':')) == NULL) {
242 8d1b399b 2021-07-22 op yyerror("invalid table %s", $2);
247 8d1b399b 2021-07-22 op add_table($2, $3, p+1);
251 8d1b399b 2021-07-22 op | TABLE STRING {
252 8d1b399b 2021-07-22 op add_table($2, "static", NULL);
253 8d1b399b 2021-07-22 op } '{' table_vals '}' {
254 8d1b399b 2021-07-22 op table = NULL;
258 8d1b399b 2021-07-22 op tableref : '<' STRING '>' {
259 8d1b399b 2021-07-22 op $$ = findtable($2);
261 8d1b399b 2021-07-22 op if ($$ == NULL)
266 8d1b399b 2021-07-22 op listen : LISTEN ON STRING PORT NUMBER TLS PKI STRING /* AUTH tableref */ {
267 8d1b399b 2021-07-22 op char *iface = $3;
268 8d1b399b 2021-07-22 op uint32_t port = $5;
269 8d1b399b 2021-07-22 op char *pki = $8;
270 8d1b399b 2021-07-22 op struct table *auth = NULL; /* $10 */
272 8d1b399b 2021-07-22 op add_listen(iface, port, pki, auth);
280 8d1b399b 2021-07-22 op struct keywords {
281 8d1b399b 2021-07-22 op const char *k_name;
286 8d1b399b 2021-07-22 op yyerror(const char *fmt, ...)
291 8d1b399b 2021-07-22 op file->errors++;
292 8d1b399b 2021-07-22 op va_start(ap, fmt);
293 8d1b399b 2021-07-22 op if (vasprintf(&msg, fmt, ap) == -1)
294 8d1b399b 2021-07-22 op fatalx("yyerror vasprintf");
296 8d1b399b 2021-07-22 op logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
302 8d1b399b 2021-07-22 op kw_cmp(const void *k, const void *e)
304 8d1b399b 2021-07-22 op return strcmp(k, ((const struct keywords *)e)->k_name);
308 8d1b399b 2021-07-22 op lookup(char *s)
310 8d1b399b 2021-07-22 op /* This has to be sorted always. */
311 8d1b399b 2021-07-22 op static const struct keywords keywords[] = {
312 8d1b399b 2021-07-22 op {"auth", AUTH},
313 8d1b399b 2021-07-22 op {"cert", CERT},
314 8d1b399b 2021-07-22 op {"include", INCLUDE},
315 8d1b399b 2021-07-22 op {"key", KEY},
316 8d1b399b 2021-07-22 op {"listen", LISTEN},
319 8d1b399b 2021-07-22 op {"pki", PKI},
320 8d1b399b 2021-07-22 op {"port", PORT},
321 8d1b399b 2021-07-22 op {"table", TABLE},
322 8d1b399b 2021-07-22 op {"tls", TLS},
323 8d1b399b 2021-07-22 op {"yes", YES},
325 8d1b399b 2021-07-22 op const struct keywords *p;
327 8d1b399b 2021-07-22 op p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
328 8d1b399b 2021-07-22 op sizeof(keywords[0]), kw_cmp);
331 8d1b399b 2021-07-22 op return p->k_val;
333 8d1b399b 2021-07-22 op return STRING;
336 8d1b399b 2021-07-22 op #define START_EXPAND 1
337 8d1b399b 2021-07-22 op #define DONE_EXPAND 2
339 8d1b399b 2021-07-22 op static int expanding;
347 8d1b399b 2021-07-22 op if (file->ungetpos > 0)
348 8d1b399b 2021-07-22 op c = file->ungetbuf[--file->ungetpos];
350 8d1b399b 2021-07-22 op c = getc(file->stream);
352 8d1b399b 2021-07-22 op if (c == START_EXPAND)
353 8d1b399b 2021-07-22 op expanding = 1;
354 8d1b399b 2021-07-22 op else if (c == DONE_EXPAND)
355 8d1b399b 2021-07-22 op expanding = 0;
363 8d1b399b 2021-07-22 op lgetc(int quotec)
367 8d1b399b 2021-07-22 op if (quotec) {
368 8d1b399b 2021-07-22 op if ((c = igetc()) == EOF) {
369 8d1b399b 2021-07-22 op yyerror("reached end of file while parsing "
370 8d1b399b 2021-07-22 op "quoted string");
371 8d1b399b 2021-07-22 op if (file == topfile || popfile() == EOF)
373 8d1b399b 2021-07-22 op return quotec;
378 8d1b399b 2021-07-22 op while ((c = igetc()) == '\\') {
379 8d1b399b 2021-07-22 op next = igetc();
380 8d1b399b 2021-07-22 op if (next != '\n') {
384 8d1b399b 2021-07-22 op yylval.lineno = file->lineno;
385 8d1b399b 2021-07-22 op file->lineno++;
388 8d1b399b 2021-07-22 op if (c == EOF) {
390 8d1b399b 2021-07-22 op * Fake EOL when hit EOF for the first time. This gets line
391 8d1b399b 2021-07-22 op * count right if last line in included file is syntactically
392 8d1b399b 2021-07-22 op * invalid and has no newline.
394 8d1b399b 2021-07-22 op if (file->eof_reached == 0) {
395 8d1b399b 2021-07-22 op file->eof_reached = 1;
398 8d1b399b 2021-07-22 op while (c == EOF) {
399 8d1b399b 2021-07-22 op if (file == topfile || popfile() == EOF)
408 8d1b399b 2021-07-22 op lungetc(int c)
410 8d1b399b 2021-07-22 op if (c == EOF)
413 8d1b399b 2021-07-22 op if (file->ungetpos >= file->ungetsize) {
414 8d1b399b 2021-07-22 op void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
415 8d1b399b 2021-07-22 op if (p == NULL)
416 8d1b399b 2021-07-22 op err(1, "lungetc");
417 8d1b399b 2021-07-22 op file->ungetbuf = p;
418 8d1b399b 2021-07-22 op file->ungetsize *= 2;
420 8d1b399b 2021-07-22 op file->ungetbuf[file->ungetpos++] = c;
424 8d1b399b 2021-07-22 op findeol(void)
428 8d1b399b 2021-07-22 op /* Skip to either EOF or the first real EOL. */
430 8d1b399b 2021-07-22 op c = lgetc(0);
431 8d1b399b 2021-07-22 op if (c == '\n') {
432 8d1b399b 2021-07-22 op file->lineno++;
435 8d1b399b 2021-07-22 op if (c == EOF)
438 8d1b399b 2021-07-22 op return ERROR;
444 8d1b399b 2021-07-22 op unsigned char buf[8096];
445 8d1b399b 2021-07-22 op unsigned char *p, *val;
446 8d1b399b 2021-07-22 op int quotec, next, c;
451 8d1b399b 2021-07-22 op while ((c = lgetc(0)) == ' ' || c == '\t')
452 8d1b399b 2021-07-22 op ; /* nothing */
454 8d1b399b 2021-07-22 op yylval.lineno = file->lineno;
455 8d1b399b 2021-07-22 op if (c == '#')
456 8d1b399b 2021-07-22 op while ((c = lgetc(0)) != '\n' && c != EOF)
457 8d1b399b 2021-07-22 op ; /* nothing */
458 8d1b399b 2021-07-22 op if (c == '$' && !expanding) {
460 8d1b399b 2021-07-22 op if ((c = lgetc(0)) == EOF)
463 8d1b399b 2021-07-22 op if (p + 1 >= buf + sizeof(buf) - 1) {
464 8d1b399b 2021-07-22 op yyerror("string too long");
465 8d1b399b 2021-07-22 op return findeol();
467 8d1b399b 2021-07-22 op if (isalnum(c) || c == '_') {
475 8d1b399b 2021-07-22 op val = symget(buf);
476 8d1b399b 2021-07-22 op if (val == NULL) {
477 8d1b399b 2021-07-22 op yyerror("macro '%s' not defined", buf);
478 8d1b399b 2021-07-22 op return findeol();
480 8d1b399b 2021-07-22 op p = val + strlen(val) - 1;
481 8d1b399b 2021-07-22 op lungetc(DONE_EXPAND);
482 8d1b399b 2021-07-22 op while (p >= val) {
486 8d1b399b 2021-07-22 op lungetc(START_EXPAND);
495 8d1b399b 2021-07-22 op if ((c = lgetc(quotec)) == EOF)
497 8d1b399b 2021-07-22 op if (c == '\n') {
498 8d1b399b 2021-07-22 op file->lineno++;
500 8d1b399b 2021-07-22 op } else if (c == '\\') {
501 8d1b399b 2021-07-22 op if ((next = lgetc(quotec)) == EOF)
503 8d1b399b 2021-07-22 op if (next == quotec || next == ' ' ||
504 8d1b399b 2021-07-22 op next == '\t')
506 8d1b399b 2021-07-22 op else if (next == '\n') {
507 8d1b399b 2021-07-22 op file->lineno++;
510 8d1b399b 2021-07-22 op lungetc(next);
511 8d1b399b 2021-07-22 op } else if (c == quotec) {
514 8d1b399b 2021-07-22 op } else if (c == '\0') {
515 8d1b399b 2021-07-22 op yyerror("syntax error");
516 8d1b399b 2021-07-22 op return findeol();
518 8d1b399b 2021-07-22 op if (p + 1 >= buf + sizeof(buf) - 1) {
519 8d1b399b 2021-07-22 op yyerror("string too long");
520 8d1b399b 2021-07-22 op return findeol();
524 8d1b399b 2021-07-22 op yylval.v.string = strdup(buf);
525 8d1b399b 2021-07-22 op if (yylval.v.string == NULL)
526 8d1b399b 2021-07-22 op err(1, "yylex: strdup");
527 8d1b399b 2021-07-22 op return STRING;
530 8d1b399b 2021-07-22 op #define allowed_to_end_number(x) \
531 8d1b399b 2021-07-22 op (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
533 8d1b399b 2021-07-22 op if (c == '-' || isdigit(c)) {
536 8d1b399b 2021-07-22 op if ((size_t)(p-buf) >= sizeof(buf)) {
537 8d1b399b 2021-07-22 op yyerror("string too long");
538 8d1b399b 2021-07-22 op return findeol();
540 8d1b399b 2021-07-22 op } while ((c = lgetc(0)) != EOF && isdigit(c));
542 8d1b399b 2021-07-22 op if (p == buf + 1 && buf[0] == '-')
543 8d1b399b 2021-07-22 op goto nodigits;
544 8d1b399b 2021-07-22 op if (c == EOF || allowed_to_end_number(c)) {
545 8d1b399b 2021-07-22 op const char *errstr = NULL;
548 8d1b399b 2021-07-22 op yylval.v.number = strtonum(buf, LLONG_MIN,
549 8d1b399b 2021-07-22 op LLONG_MAX, &errstr);
550 8d1b399b 2021-07-22 op if (errstr) {
551 8d1b399b 2021-07-22 op yyerror("\"%s\" invalid number: %s",
552 8d1b399b 2021-07-22 op buf, errstr);
553 8d1b399b 2021-07-22 op return findeol();
555 8d1b399b 2021-07-22 op return NUMBER;
558 8d1b399b 2021-07-22 op while (p > buf + 1)
559 8d1b399b 2021-07-22 op lungetc(*--p);
561 8d1b399b 2021-07-22 op if (c == '-')
566 8d1b399b 2021-07-22 op #define allowed_in_string(x) \
567 8d1b399b 2021-07-22 op (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
568 8d1b399b 2021-07-22 op x != '{' && x != '}' && \
569 8d1b399b 2021-07-22 op x != '!' && x != '=' && x != '#' && \
572 8d1b399b 2021-07-22 op if (isalnum(c) || c == ':' || c == '_') {
575 8d1b399b 2021-07-22 op if ((size_t)(p-buf) >= sizeof(buf)) {
576 8d1b399b 2021-07-22 op yyerror("string too long");
577 8d1b399b 2021-07-22 op return findeol();
579 8d1b399b 2021-07-22 op } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
582 8d1b399b 2021-07-22 op if ((token = lookup(buf)) == STRING)
583 8d1b399b 2021-07-22 op if ((yylval.v.string = strdup(buf)) == NULL)
584 8d1b399b 2021-07-22 op err(1, "yylex: strdup");
585 8d1b399b 2021-07-22 op return token;
587 8d1b399b 2021-07-22 op if (c == '\n') {
588 8d1b399b 2021-07-22 op yylval.lineno = file->lineno;
589 8d1b399b 2021-07-22 op file->lineno++;
591 8d1b399b 2021-07-22 op if (c == EOF)
597 8d1b399b 2021-07-22 op check_file_secrecy(int fd, const char *fname)
599 8d1b399b 2021-07-22 op struct stat st;
601 8d1b399b 2021-07-22 op if (fstat(fd, &st)) {
602 8d1b399b 2021-07-22 op log_warn("cannot stat %s", fname);
605 8d1b399b 2021-07-22 op if (st.st_uid != 0 && st.st_uid != getuid()) {
606 8d1b399b 2021-07-22 op log_warnx("%s: owner not root or current user", fname);
609 8d1b399b 2021-07-22 op if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
610 8d1b399b 2021-07-22 op log_warnx("%s: group writable or world read/writable", fname);
616 8d1b399b 2021-07-22 op struct file *
617 8d1b399b 2021-07-22 op pushfile(const char *name, int secret)
619 8d1b399b 2021-07-22 op struct file *nfile;
621 8d1b399b 2021-07-22 op if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
622 8d1b399b 2021-07-22 op log_warn("calloc");
625 8d1b399b 2021-07-22 op if ((nfile->name = strdup(name)) == NULL) {
626 8d1b399b 2021-07-22 op log_warn("strdup");
630 8d1b399b 2021-07-22 op if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
631 8d1b399b 2021-07-22 op log_warn("%s", nfile->name);
632 8d1b399b 2021-07-22 op free(nfile->name);
635 8d1b399b 2021-07-22 op } else if (secret &&
636 8d1b399b 2021-07-22 op check_file_secrecy(fileno(nfile->stream), nfile->name)) {
637 8d1b399b 2021-07-22 op fclose(nfile->stream);
638 8d1b399b 2021-07-22 op free(nfile->name);
642 8d1b399b 2021-07-22 op nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
643 8d1b399b 2021-07-22 op nfile->ungetsize = 16;
644 8d1b399b 2021-07-22 op nfile->ungetbuf = malloc(nfile->ungetsize);
645 8d1b399b 2021-07-22 op if (nfile->ungetbuf == NULL) {
646 8d1b399b 2021-07-22 op log_warn("malloc");
647 8d1b399b 2021-07-22 op fclose(nfile->stream);
648 8d1b399b 2021-07-22 op free(nfile->name);
652 8d1b399b 2021-07-22 op TAILQ_INSERT_TAIL(&files, nfile, entry);
653 8d1b399b 2021-07-22 op return nfile;
657 8d1b399b 2021-07-22 op popfile(void)
659 8d1b399b 2021-07-22 op struct file *prev;
661 8d1b399b 2021-07-22 op if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
662 8d1b399b 2021-07-22 op prev->errors += file->errors;
664 8d1b399b 2021-07-22 op TAILQ_REMOVE(&files, file, entry);
665 8d1b399b 2021-07-22 op fclose(file->stream);
666 8d1b399b 2021-07-22 op free(file->name);
667 8d1b399b 2021-07-22 op free(file->ungetbuf);
670 8d1b399b 2021-07-22 op return file ? 0 : EOF;
673 8d1b399b 2021-07-22 op struct kd_conf *
674 8d1b399b 2021-07-22 op parse_config(const char *filename)
676 8d1b399b 2021-07-22 op struct sym *sym, *next;
679 8d1b399b 2021-07-22 op conf = config_new_empty();
681 8d1b399b 2021-07-22 op file = pushfile(filename, 0);
682 8d1b399b 2021-07-22 op if (file == NULL) {
686 8d1b399b 2021-07-22 op topfile = file;
689 8d1b399b 2021-07-22 op errors = file->errors;
692 8d1b399b 2021-07-22 op /* Free macros and check which have not been used. */
693 8d1b399b 2021-07-22 op TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
694 8d1b399b 2021-07-22 op if (verbose && !sym->used)
695 8d1b399b 2021-07-22 op fprintf(stderr, "warning: macro '%s' not used\n",
697 8d1b399b 2021-07-22 op if (!sym->persist) {
698 8d1b399b 2021-07-22 op free(sym->nam);
699 8d1b399b 2021-07-22 op free(sym->val);
700 8d1b399b 2021-07-22 op TAILQ_REMOVE(&symhead, sym, entry);
705 8d1b399b 2021-07-22 op if (errors) {
706 8d1b399b 2021-07-22 op clear_config(conf);
714 8d1b399b 2021-07-22 op symset(const char *nam, const char *val, int persist)
716 8d1b399b 2021-07-22 op struct sym *sym;
718 8d1b399b 2021-07-22 op TAILQ_FOREACH(sym, &symhead, entry) {
719 8d1b399b 2021-07-22 op if (strcmp(nam, sym->nam) == 0)
723 8d1b399b 2021-07-22 op if (sym != NULL) {
724 8d1b399b 2021-07-22 op if (sym->persist == 1)
727 8d1b399b 2021-07-22 op free(sym->nam);
728 8d1b399b 2021-07-22 op free(sym->val);
729 8d1b399b 2021-07-22 op TAILQ_REMOVE(&symhead, sym, entry);
733 8d1b399b 2021-07-22 op if ((sym = calloc(1, sizeof(*sym))) == NULL)
736 8d1b399b 2021-07-22 op sym->nam = strdup(nam);
737 8d1b399b 2021-07-22 op if (sym->nam == NULL) {
741 8d1b399b 2021-07-22 op sym->val = strdup(val);
742 8d1b399b 2021-07-22 op if (sym->val == NULL) {
743 8d1b399b 2021-07-22 op free(sym->nam);
747 8d1b399b 2021-07-22 op sym->used = 0;
748 8d1b399b 2021-07-22 op sym->persist = persist;
749 8d1b399b 2021-07-22 op TAILQ_INSERT_TAIL(&symhead, sym, entry);
754 8d1b399b 2021-07-22 op cmdline_symset(char *s)
756 8d1b399b 2021-07-22 op char *sym, *val;
759 8d1b399b 2021-07-22 op if ((val = strrchr(s, '=')) == NULL)
761 8d1b399b 2021-07-22 op sym = strndup(s, val - s);
762 8d1b399b 2021-07-22 op if (sym == NULL)
763 8d1b399b 2021-07-22 op errx(1, "%s: strndup", __func__);
764 8d1b399b 2021-07-22 op ret = symset(sym, val + 1, 1);
771 8d1b399b 2021-07-22 op symget(const char *nam)
773 8d1b399b 2021-07-22 op struct sym *sym;
775 8d1b399b 2021-07-22 op TAILQ_FOREACH(sym, &symhead, entry) {
776 8d1b399b 2021-07-22 op if (strcmp(nam, sym->nam) == 0) {
777 8d1b399b 2021-07-22 op sym->used = 1;
778 8d1b399b 2021-07-22 op return sym->val;
785 8d1b399b 2021-07-22 op clear_config(struct kd_conf *xconf)
787 8d1b399b 2021-07-22 op /* free stuff? */
793 8d1b399b 2021-07-22 op add_table(const char *name, const char *type, const char *path)
795 8d1b399b 2021-07-22 op if (table_open(conf, name, type, path) == -1)
796 8d1b399b 2021-07-22 op yyerror("can't initialize table %s", name);
797 8d1b399b 2021-07-22 op table = SIMPLEQ_FIRST(&conf->table_head)->table;
800 8d1b399b 2021-07-22 op static struct table *
801 8d1b399b 2021-07-22 op findtable(const char *name)
803 8d1b399b 2021-07-22 op struct kd_tables_conf *i;
805 8d1b399b 2021-07-22 op SIMPLEQ_FOREACH(i, &conf->table_head, entry) {
806 8d1b399b 2021-07-22 op if (!strcmp(i->table->t_name, name))
807 8d1b399b 2021-07-22 op return i->table;
810 8d1b399b 2021-07-22 op yyerror("unknown table %s", name);
815 8d1b399b 2021-07-22 op add_cert(const char *name, const char *path)
817 8d1b399b 2021-07-22 op struct kd_pki_conf *pki;
819 8d1b399b 2021-07-22 op SIMPLEQ_FOREACH(pki, &conf->pki_head, entry) {
820 8d1b399b 2021-07-22 op if (strcmp(name, pki->name) != 0)
823 8d1b399b 2021-07-22 op if (pki->cert != NULL) {
824 8d1b399b 2021-07-22 op yyerror("duplicate `pki %s cert'", name);
831 8d1b399b 2021-07-22 op pki = xcalloc(1, sizeof(*pki));
832 8d1b399b 2021-07-22 op strlcpy(pki->name, name, sizeof(pki->name));
833 8d1b399b 2021-07-22 op SIMPLEQ_INSERT_HEAD(&conf->pki_head, pki, entry);
836 8d1b399b 2021-07-22 op if ((pki->cert = tls_load_file(path, &pki->certlen, NULL)) == NULL)
841 8d1b399b 2021-07-22 op add_key(const char *name, const char *path)
843 8d1b399b 2021-07-22 op struct kd_pki_conf *pki;
845 8d1b399b 2021-07-22 op SIMPLEQ_FOREACH(pki, &conf->pki_head, entry) {
846 8d1b399b 2021-07-22 op if (strcmp(name, pki->name) != 0)
849 8d1b399b 2021-07-22 op if (pki->key != NULL) {
850 8d1b399b 2021-07-22 op yyerror("duplicate `pki %s key'", name);
857 8d1b399b 2021-07-22 op pki = xcalloc(1, sizeof(*pki));
858 8d1b399b 2021-07-22 op strlcpy(pki->name, name, sizeof(pki->name));
859 8d1b399b 2021-07-22 op SIMPLEQ_INSERT_HEAD(&conf->pki_head, pki, entry);
862 8d1b399b 2021-07-22 op if ((pki->key = tls_load_file(path, &pki->keylen, NULL)) == NULL)
867 8d1b399b 2021-07-22 op add_listen(const char *iface, uint32_t portno, const char *pki, struct table *auth)
869 8d1b399b 2021-07-22 op struct kd_listen_conf *l;
871 8d1b399b 2021-07-22 op if (portno >= UINT16_MAX)
872 8d1b399b 2021-07-22 op fatalx("invalid port number: %"PRIu32, portno);
874 8d1b399b 2021-07-22 op l = xcalloc(1, sizeof(*l));
876 8d1b399b 2021-07-22 op l->id = counter++;
878 8d1b399b 2021-07-22 op strlcpy(l->iface, iface, sizeof(l->iface));
879 8d1b399b 2021-07-22 op l->port = portno;
880 8d1b399b 2021-07-22 op l->auth_table = auth;
881 8d1b399b 2021-07-22 op strlcpy(l->pki, pki, sizeof(l->pki));
883 8d1b399b 2021-07-22 op SIMPLEQ_INSERT_HEAD(&conf->listen_head, l, entry);