12671ee73SJamie Gritton %{
22671ee73SJamie Gritton /*-
34d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
41de7b4b8SPedro F. Giffuni *
5d8352076SJamie Gritton * Copyright (c) 2011 James Gritton
62671ee73SJamie Gritton * All rights reserved.
72671ee73SJamie Gritton *
82671ee73SJamie Gritton * Redistribution and use in source and binary forms, with or without
92671ee73SJamie Gritton * modification, are permitted provided that the following conditions
102671ee73SJamie Gritton * are met:
112671ee73SJamie Gritton * 1. Redistributions of source code must retain the above copyright
122671ee73SJamie Gritton * notice, this list of conditions and the following disclaimer.
132671ee73SJamie Gritton * 2. Redistributions in binary form must reproduce the above copyright
142671ee73SJamie Gritton * notice, this list of conditions and the following disclaimer in the
152671ee73SJamie Gritton * documentation and/or other materials provided with the distribution.
162671ee73SJamie Gritton *
172671ee73SJamie Gritton * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
182671ee73SJamie Gritton * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
192671ee73SJamie Gritton * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
202671ee73SJamie Gritton * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
212671ee73SJamie Gritton * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
222671ee73SJamie Gritton * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
232671ee73SJamie Gritton * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
242671ee73SJamie Gritton * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
252671ee73SJamie Gritton * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
262671ee73SJamie Gritton * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
272671ee73SJamie Gritton * SUCH DAMAGE.
282671ee73SJamie Gritton */
292671ee73SJamie Gritton
302671ee73SJamie Gritton #include <sys/cdefs.h>
31086e0149SJamie Gritton #include <err.h>
322671ee73SJamie Gritton #include <stdlib.h>
332671ee73SJamie Gritton #include <string.h>
342671ee73SJamie Gritton
352671ee73SJamie Gritton #include "jailp.h"
362671ee73SJamie Gritton
372671ee73SJamie Gritton #ifdef DEBUG
382671ee73SJamie Gritton #define YYDEBUG 1
392671ee73SJamie Gritton #endif
40097db30aSJamie Gritton
41097db30aSJamie Gritton static struct cfjail *current_jail;
42097db30aSJamie Gritton static struct cfjail *global_jail;
432671ee73SJamie Gritton %}
442671ee73SJamie Gritton
452671ee73SJamie Gritton %union {
462671ee73SJamie Gritton struct cfparam *p;
472671ee73SJamie Gritton struct cfstrings *ss;
482671ee73SJamie Gritton struct cfstring *s;
492671ee73SJamie Gritton char *cs;
502671ee73SJamie Gritton }
512671ee73SJamie Gritton
522671ee73SJamie Gritton %token PLEQ
532671ee73SJamie Gritton %token <cs> STR STR1 VAR VAR1
542671ee73SJamie Gritton
552671ee73SJamie Gritton %type <p> param name
562671ee73SJamie Gritton %type <ss> value
572671ee73SJamie Gritton %type <s> string
582671ee73SJamie Gritton
59086e0149SJamie Gritton %pure-parser
60086e0149SJamie Gritton
61086e0149SJamie Gritton %lex-param { void *scanner }
62086e0149SJamie Gritton %parse-param { void *scanner }
63086e0149SJamie Gritton
642671ee73SJamie Gritton %%
652671ee73SJamie Gritton
662671ee73SJamie Gritton /*
67097db30aSJamie Gritton * A config file is a list of jails and parameters. Parameters are
68097db30aSJamie Gritton * added to the current jail, otherwise to a global pesudo-jail.
692671ee73SJamie Gritton */
702671ee73SJamie Gritton conf :
712671ee73SJamie Gritton | conf jail
722671ee73SJamie Gritton | conf param ';'
732671ee73SJamie Gritton {
74e82a6294SJamie Gritton if (!special_param($2, scanner)) {
75097db30aSJamie Gritton struct cfjail *j = current_jail;
762671ee73SJamie Gritton
77097db30aSJamie Gritton if (j == NULL) {
78097db30aSJamie Gritton if (global_jail == NULL) {
79097db30aSJamie Gritton global_jail = add_jail();
80097db30aSJamie Gritton global_jail->name = estrdup("*");
81097db30aSJamie Gritton }
82097db30aSJamie Gritton j = global_jail;
832671ee73SJamie Gritton }
842671ee73SJamie Gritton TAILQ_INSERT_TAIL(&j->params, $2, tq);
852671ee73SJamie Gritton }
86e82a6294SJamie Gritton }
872671ee73SJamie Gritton | conf ';'
88097db30aSJamie Gritton ;
892671ee73SJamie Gritton
90097db30aSJamie Gritton jail : jail_name '{' conf '}'
912671ee73SJamie Gritton {
92097db30aSJamie Gritton current_jail = current_jail->cfparent;
932671ee73SJamie Gritton }
942671ee73SJamie Gritton ;
952671ee73SJamie Gritton
96097db30aSJamie Gritton jail_name : STR
972671ee73SJamie Gritton {
98097db30aSJamie Gritton struct cfjail *j = add_jail();
99097db30aSJamie Gritton
100097db30aSJamie Gritton if (current_jail == NULL)
101097db30aSJamie Gritton j->name = $1;
102097db30aSJamie Gritton else {
103097db30aSJamie Gritton /*
104097db30aSJamie Gritton * A nested jail definition becomes
105097db30aSJamie Gritton * a hierarchically-named sub-jail.
106097db30aSJamie Gritton */
107097db30aSJamie Gritton size_t parentlen = strlen(current_jail->name);
108097db30aSJamie Gritton j->name = emalloc(parentlen + strlen($1) + 2);
109097db30aSJamie Gritton strcpy(j->name, current_jail->name);
110097db30aSJamie Gritton j->name[parentlen++] = '.';
111097db30aSJamie Gritton strcpy(j->name + parentlen, $1);
112097db30aSJamie Gritton free($1);
1132671ee73SJamie Gritton }
114097db30aSJamie Gritton j->cfparent = current_jail;
115097db30aSJamie Gritton current_jail = j;
1162671ee73SJamie Gritton }
1172671ee73SJamie Gritton ;
1182671ee73SJamie Gritton
1192671ee73SJamie Gritton /*
1202671ee73SJamie Gritton * Parameters have a name and an optional list of value strings,
121463a577bSEitan Adler * which may have "+=" or "=" preceding them.
1222671ee73SJamie Gritton */
1232671ee73SJamie Gritton param : name
1242671ee73SJamie Gritton {
1252671ee73SJamie Gritton $$ = $1;
1262671ee73SJamie Gritton }
1272671ee73SJamie Gritton | name '=' value
1282671ee73SJamie Gritton {
1292671ee73SJamie Gritton $$ = $1;
1302a194551SJamie Gritton TAILQ_CONCAT(&$$->val, $3, tq);
1312671ee73SJamie Gritton free($3);
1322671ee73SJamie Gritton }
1332671ee73SJamie Gritton | name PLEQ value
1342671ee73SJamie Gritton {
1352671ee73SJamie Gritton $$ = $1;
1362a194551SJamie Gritton TAILQ_CONCAT(&$$->val, $3, tq);
1372671ee73SJamie Gritton $$->flags |= PF_APPEND;
1382671ee73SJamie Gritton free($3);
1392671ee73SJamie Gritton }
1402671ee73SJamie Gritton | name value
1412671ee73SJamie Gritton {
1422671ee73SJamie Gritton $$ = $1;
1432a194551SJamie Gritton TAILQ_CONCAT(&$$->val, $2, tq);
144e82a6294SJamie Gritton $$->flags |= PF_NAMEVAL;
1452671ee73SJamie Gritton free($2);
1462671ee73SJamie Gritton }
1472671ee73SJamie Gritton | error
1482671ee73SJamie Gritton ;
1492671ee73SJamie Gritton
1502671ee73SJamie Gritton /*
1512671ee73SJamie Gritton * A parameter has a fixed name. A variable definition looks just like a
1522671ee73SJamie Gritton * parameter except that the name is a variable.
1532671ee73SJamie Gritton */
1542671ee73SJamie Gritton name : STR
1552671ee73SJamie Gritton {
1562671ee73SJamie Gritton $$ = emalloc(sizeof(struct cfparam));
1572671ee73SJamie Gritton $$->name = $1;
1582a194551SJamie Gritton TAILQ_INIT(&$$->val);
1592671ee73SJamie Gritton $$->flags = 0;
1602671ee73SJamie Gritton }
1612671ee73SJamie Gritton | VAR
1622671ee73SJamie Gritton {
1632671ee73SJamie Gritton $$ = emalloc(sizeof(struct cfparam));
1642671ee73SJamie Gritton $$->name = $1;
1652a194551SJamie Gritton TAILQ_INIT(&$$->val);
1662671ee73SJamie Gritton $$->flags = PF_VAR;
1672671ee73SJamie Gritton }
1682671ee73SJamie Gritton ;
1692671ee73SJamie Gritton
1702671ee73SJamie Gritton value : string
1712671ee73SJamie Gritton {
1722671ee73SJamie Gritton $$ = emalloc(sizeof(struct cfstrings));
1732a194551SJamie Gritton TAILQ_INIT($$);
1742a194551SJamie Gritton TAILQ_INSERT_TAIL($$, $1, tq);
1752671ee73SJamie Gritton }
1762671ee73SJamie Gritton | value ',' string
1772671ee73SJamie Gritton {
1782671ee73SJamie Gritton $$ = $1;
1792a194551SJamie Gritton TAILQ_INSERT_TAIL($$, $3, tq);
1802671ee73SJamie Gritton }
1812671ee73SJamie Gritton ;
1822671ee73SJamie Gritton
1832671ee73SJamie Gritton /*
1842671ee73SJamie Gritton * Strings may be passed in pieces, because of quoting and/or variable
1852671ee73SJamie Gritton * interpolation. Reassemble them into a single string.
1862671ee73SJamie Gritton */
1872671ee73SJamie Gritton string : STR
1882671ee73SJamie Gritton {
1892671ee73SJamie Gritton $$ = emalloc(sizeof(struct cfstring));
1902671ee73SJamie Gritton $$->s = $1;
1912671ee73SJamie Gritton $$->len = strlen($1);
1922671ee73SJamie Gritton STAILQ_INIT(&$$->vars);
1932671ee73SJamie Gritton }
1942671ee73SJamie Gritton | VAR
1952671ee73SJamie Gritton {
1962671ee73SJamie Gritton struct cfvar *v;
1972671ee73SJamie Gritton
1982671ee73SJamie Gritton $$ = emalloc(sizeof(struct cfstring));
1992671ee73SJamie Gritton $$->s = estrdup("");
2002671ee73SJamie Gritton $$->len = 0;
2012671ee73SJamie Gritton STAILQ_INIT(&$$->vars);
2022671ee73SJamie Gritton v = emalloc(sizeof(struct cfvar));
2032671ee73SJamie Gritton v->name = $1;
2042671ee73SJamie Gritton v->pos = 0;
2052671ee73SJamie Gritton STAILQ_INSERT_TAIL(&$$->vars, v, tq);
2062671ee73SJamie Gritton }
2072671ee73SJamie Gritton | string STR1
2082671ee73SJamie Gritton {
2092671ee73SJamie Gritton size_t len1;
2102671ee73SJamie Gritton
2112671ee73SJamie Gritton $$ = $1;
2122671ee73SJamie Gritton len1 = strlen($2);
2132671ee73SJamie Gritton $$->s = erealloc($$->s, $$->len + len1 + 1);
2142671ee73SJamie Gritton strcpy($$->s + $$->len, $2);
2152671ee73SJamie Gritton free($2);
2162671ee73SJamie Gritton $$->len += len1;
2172671ee73SJamie Gritton }
2182671ee73SJamie Gritton | string VAR1
2192671ee73SJamie Gritton {
2202671ee73SJamie Gritton struct cfvar *v;
2212671ee73SJamie Gritton
2222671ee73SJamie Gritton $$ = $1;
2232671ee73SJamie Gritton v = emalloc(sizeof(struct cfvar));
2242671ee73SJamie Gritton v->name = $2;
2252671ee73SJamie Gritton v->pos = $$->len;
2262671ee73SJamie Gritton STAILQ_INSERT_TAIL(&$$->vars, v, tq);
2272671ee73SJamie Gritton }
2282671ee73SJamie Gritton ;
2292671ee73SJamie Gritton
2302671ee73SJamie Gritton %%
231086e0149SJamie Gritton
232086e0149SJamie Gritton extern int YYLEX_DECL();
233086e0149SJamie Gritton
234086e0149SJamie Gritton static void
YYERROR_DECL()235086e0149SJamie Gritton YYERROR_DECL()
236086e0149SJamie Gritton {
237*768149ffSJamie Gritton struct cflex *cflex = yyget_extra(scanner);
238*768149ffSJamie Gritton
239086e0149SJamie Gritton if (!yyget_text(scanner))
240086e0149SJamie Gritton warnx("%s line %d: %s",
241*768149ffSJamie Gritton cflex->cfname, yyget_lineno(scanner), s);
242086e0149SJamie Gritton else if (!yyget_text(scanner)[0])
243086e0149SJamie Gritton warnx("%s: unexpected EOF",
244*768149ffSJamie Gritton cflex->cfname);
245086e0149SJamie Gritton else
246086e0149SJamie Gritton warnx("%s line %d: %s: %s",
247*768149ffSJamie Gritton cflex->cfname, yyget_lineno(scanner),
248086e0149SJamie Gritton yyget_text(scanner), s);
249*768149ffSJamie Gritton cflex->error = 1;
250086e0149SJamie Gritton }
251e82a6294SJamie Gritton
252e82a6294SJamie Gritton /* Handle special parameters (i.e. the include directive).
253e82a6294SJamie Gritton * Return true if the parameter was specially handled.
254e82a6294SJamie Gritton */
255e82a6294SJamie Gritton static int
special_param(struct cfparam * p,void * scanner)256e82a6294SJamie Gritton special_param(struct cfparam *p, void *scanner)
257e82a6294SJamie Gritton {
258e82a6294SJamie Gritton if ((p->flags & (PF_VAR | PF_APPEND | PF_NAMEVAL)) != PF_NAMEVAL
259e82a6294SJamie Gritton || strcmp(p->name, ".include"))
260e82a6294SJamie Gritton return 0;
261e82a6294SJamie Gritton struct cfstring *s;
262e82a6294SJamie Gritton TAILQ_FOREACH(s, &p->val, tq) {
263e82a6294SJamie Gritton if (STAILQ_EMPTY(&s->vars))
264e82a6294SJamie Gritton include_config(scanner, s->s);
265e82a6294SJamie Gritton else {
266e82a6294SJamie Gritton warnx("%s line %d: "
267e82a6294SJamie Gritton "variables not permitted in '.include' filename",
268e82a6294SJamie Gritton yyget_extra(scanner)->cfname,
269e82a6294SJamie Gritton yyget_lineno(scanner));
270e82a6294SJamie Gritton yyget_extra(scanner)->error = 1;
271e82a6294SJamie Gritton }
272e82a6294SJamie Gritton }
273e82a6294SJamie Gritton free_param_strings(p);
274e82a6294SJamie Gritton free(p);
275e82a6294SJamie Gritton return 1;
276e82a6294SJamie Gritton }
277