Deleted Added
full compact
config.c (214783) config.c (223188)
1/*-
2 * Copyright (c) 2010 James Gritton
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2010 James Gritton
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: projects/jailconf/usr.sbin/jail/config.c 214783 2010-11-04 17:01:21Z jamie $");
28__FBSDID("$FreeBSD: projects/jailconf/usr.sbin/jail/config.c 223188 2011-06-17 16:06:13Z jamie $");
29
30#include <sys/types.h>
31#include <sys/errno.h>
32#include <sys/socket.h>
33#include <sys/sysctl.h>
34
35#include <arpa/inet.h>
36#include <netinet/in.h>

--- 136 unchanged lines hidden (view full) ---

173 TAILQ_FOREACH(p, &opp, tq)
174 add_param(j, p, 0, NULL);
175
176 /* Resolve any variable substitutions. */
177 pgen = 0;
178 TAILQ_FOREACH(p, &j->params, tq) {
179 p->gen = ++pgen;
180 find_vars:
29
30#include <sys/types.h>
31#include <sys/errno.h>
32#include <sys/socket.h>
33#include <sys/sysctl.h>
34
35#include <arpa/inet.h>
36#include <netinet/in.h>

--- 136 unchanged lines hidden (view full) ---

173 TAILQ_FOREACH(p, &opp, tq)
174 add_param(j, p, 0, NULL);
175
176 /* Resolve any variable substitutions. */
177 pgen = 0;
178 TAILQ_FOREACH(p, &j->params, tq) {
179 p->gen = ++pgen;
180 find_vars:
181 STAILQ_FOREACH(s, &p->val, tq) {
181 TAILQ_FOREACH(s, &p->val, tq) {
182 varoff = 0;
183 while ((v = STAILQ_FIRST(&s->vars))) {
184 TAILQ_FOREACH(vp, &j->params, tq)
185 if (!strcmp(vp->name, v->name))
186 break;
187 if (!vp) {
188 jail_warnx(j,
189 "%s: variable \"%s\" not found",

--- 7 unchanged lines hidden (view full) ---

197 }
198 if (vp->flags & PF_BAD)
199 goto bad_var;
200 if (vp->gen == pgen) {
201 jail_warnx(j, "%s: variable loop",
202 v->name);
203 goto bad_var;
204 }
182 varoff = 0;
183 while ((v = STAILQ_FIRST(&s->vars))) {
184 TAILQ_FOREACH(vp, &j->params, tq)
185 if (!strcmp(vp->name, v->name))
186 break;
187 if (!vp) {
188 jail_warnx(j,
189 "%s: variable \"%s\" not found",

--- 7 unchanged lines hidden (view full) ---

197 }
198 if (vp->flags & PF_BAD)
199 goto bad_var;
200 if (vp->gen == pgen) {
201 jail_warnx(j, "%s: variable loop",
202 v->name);
203 goto bad_var;
204 }
205 STAILQ_FOREACH(vs, &vp->val, tq)
205 TAILQ_FOREACH(vs, &vp->val, tq)
206 if (!STAILQ_EMPTY(&vs->vars)) {
207 vp->gen = pgen;
208 TAILQ_REMOVE(&j->params, vp,
209 tq);
210 TAILQ_INSERT_BEFORE(p, vp, tq);
211 p = vp;
212 goto find_vars;
213 }
206 if (!STAILQ_EMPTY(&vs->vars)) {
207 vp->gen = pgen;
208 TAILQ_REMOVE(&j->params, vp,
209 tq);
210 TAILQ_INSERT_BEFORE(p, vp, tq);
211 p = vp;
212 goto find_vars;
213 }
214 vs = STAILQ_FIRST(&vp->val);
215 if (STAILQ_NEXT(vs, tq) != NULL &&
214 vs = TAILQ_FIRST(&vp->val);
215 if (TAILQ_NEXT(vs, tq) != NULL &&
216 (s->s[0] != '\0' ||
217 STAILQ_NEXT(v, tq))) {
218 jail_warnx(j, "%s: array cannot be "
219 "substituted inline",
220 p->name);
221 goto bad_var;
222 }
223 s->s = erealloc(s->s, s->len + vs->len + 1);
224 memmove(s->s + v->pos + varoff + vs->len,
225 s->s + v->pos + varoff,
226 s->len - (v->pos + varoff) + 1);
227 memcpy(s->s + v->pos + varoff, vs->s, vs->len);
228 varoff += vs->len;
229 s->len += vs->len;
216 (s->s[0] != '\0' ||
217 STAILQ_NEXT(v, tq))) {
218 jail_warnx(j, "%s: array cannot be "
219 "substituted inline",
220 p->name);
221 goto bad_var;
222 }
223 s->s = erealloc(s->s, s->len + vs->len + 1);
224 memmove(s->s + v->pos + varoff + vs->len,
225 s->s + v->pos + varoff,
226 s->len - (v->pos + varoff) + 1);
227 memcpy(s->s + v->pos + varoff, vs->s, vs->len);
228 varoff += vs->len;
229 s->len += vs->len;
230 while ((vs = STAILQ_NEXT(vs, tq))) {
230 while ((vs = TAILQ_NEXT(vs, tq))) {
231 ns = emalloc(sizeof(struct cfstring));
232 ns->s = estrdup(vs->s);
233 ns->len = vs->len;
234 STAILQ_INIT(&ns->vars);
231 ns = emalloc(sizeof(struct cfstring));
232 ns->s = estrdup(vs->s);
233 ns->len = vs->len;
234 STAILQ_INIT(&ns->vars);
235 STAILQ_INSERT_AFTER(&p->val, s, ns, tq);
235 TAILQ_INSERT_AFTER(&p->val, s, ns, tq);
236 s = ns;
237 }
238 free_var:
239 free(v->name);
240 STAILQ_REMOVE_HEAD(&s->vars, tq);
241 free(v);
242 }
243 }

--- 49 unchanged lines hidden (view full) ---

293 unsigned flags;
294
295 if (j == NULL) {
296 /* Create a single anonymous jail if one doesn't yet exist. */
297 j = TAILQ_LAST(&cfjails, cfjails);
298 if (j == NULL)
299 j = add_jail();
300 }
236 s = ns;
237 }
238 free_var:
239 free(v->name);
240 STAILQ_REMOVE_HEAD(&s->vars, tq);
241 free(v);
242 }
243 }

--- 49 unchanged lines hidden (view full) ---

293 unsigned flags;
294
295 if (j == NULL) {
296 /* Create a single anonymous jail if one doesn't yet exist. */
297 j = TAILQ_LAST(&cfjails, cfjails);
298 if (j == NULL)
299 j = add_jail();
300 }
301 STAILQ_INIT(&nss);
301 TAILQ_INIT(&nss);
302 if (p != NULL) {
303 name = p->name;
304 flags = p->flags;
305 /*
306 * Make a copy of the parameter's string list,
307 * which may be freed if it's overridden later.
308 */
302 if (p != NULL) {
303 name = p->name;
304 flags = p->flags;
305 /*
306 * Make a copy of the parameter's string list,
307 * which may be freed if it's overridden later.
308 */
309 STAILQ_FOREACH(s, &p->val, tq) {
309 TAILQ_FOREACH(s, &p->val, tq) {
310 ns = emalloc(sizeof(struct cfstring));
311 ns->s = estrdup(s->s);
312 ns->len = s->len;
313 STAILQ_INIT(&ns->vars);
314 STAILQ_FOREACH(v, &s->vars, tq) {
315 nv = emalloc(sizeof(struct cfvar));
316 nv->name = strdup(v->name);
317 nv->pos = v->pos;
318 STAILQ_INSERT_TAIL(&ns->vars, nv, tq);
319 }
310 ns = emalloc(sizeof(struct cfstring));
311 ns->s = estrdup(s->s);
312 ns->len = s->len;
313 STAILQ_INIT(&ns->vars);
314 STAILQ_FOREACH(v, &s->vars, tq) {
315 nv = emalloc(sizeof(struct cfvar));
316 nv->name = strdup(v->name);
317 nv->pos = v->pos;
318 STAILQ_INSERT_TAIL(&ns->vars, nv, tq);
319 }
320 STAILQ_INSERT_TAIL(&nss, ns, tq);
320 TAILQ_INSERT_TAIL(&nss, ns, tq);
321 }
322 } else {
323 flags = PF_APPEND;
324 if (ipnum != 0) {
325 name = intparams[ipnum].name;
326 flags |= intparams[ipnum].flags;
327 } else if ((cs = strchr(value, '='))) {
328 tname = alloca(cs - value + 1);

--- 4 unchanged lines hidden (view full) ---

333 name = value;
334 value = NULL;
335 }
336 if (value != NULL) {
337 ns = emalloc(sizeof(struct cfstring));
338 ns->s = estrdup(value);
339 ns->len = strlen(value);
340 STAILQ_INIT(&ns->vars);
321 }
322 } else {
323 flags = PF_APPEND;
324 if (ipnum != 0) {
325 name = intparams[ipnum].name;
326 flags |= intparams[ipnum].flags;
327 } else if ((cs = strchr(value, '='))) {
328 tname = alloca(cs - value + 1);

--- 4 unchanged lines hidden (view full) ---

333 name = value;
334 value = NULL;
335 }
336 if (value != NULL) {
337 ns = emalloc(sizeof(struct cfstring));
338 ns->s = estrdup(value);
339 ns->len = strlen(value);
340 STAILQ_INIT(&ns->vars);
341 STAILQ_INSERT_TAIL(&nss, ns, tq);
341 TAILQ_INSERT_TAIL(&nss, ns, tq);
342 }
343 }
344
345 /* See if this parameter has already been added. */
346 if (ipnum != 0)
347 dp = j->intparams[ipnum];
348 else
349 TAILQ_FOREACH(dp, &j->params, tq)
350 if (!(dp->flags & PF_CONV) && equalopts(dp->name, name))
351 break;
352 if (dp != NULL) {
353 /* Found it - append or replace. */
354 if (strcmp(dp->name, name)) {
355 free(dp->name);
356 dp->name = estrdup(name);
357 }
342 }
343 }
344
345 /* See if this parameter has already been added. */
346 if (ipnum != 0)
347 dp = j->intparams[ipnum];
348 else
349 TAILQ_FOREACH(dp, &j->params, tq)
350 if (!(dp->flags & PF_CONV) && equalopts(dp->name, name))
351 break;
352 if (dp != NULL) {
353 /* Found it - append or replace. */
354 if (strcmp(dp->name, name)) {
355 free(dp->name);
356 dp->name = estrdup(name);
357 }
358 if (!(flags & PF_APPEND) || STAILQ_EMPTY(&nss))
358 if (!(flags & PF_APPEND) || TAILQ_EMPTY(&nss))
359 free_param_strings(dp);
359 free_param_strings(dp);
360 STAILQ_CONCAT(&dp->val, &nss);
360 TAILQ_CONCAT(&dp->val, &nss, tq);
361 dp->flags |= flags;
362 } else {
363 /* Not found - add it. */
364 np = emalloc(sizeof(struct cfparam));
365 np->name = estrdup(name);
361 dp->flags |= flags;
362 } else {
363 /* Not found - add it. */
364 np = emalloc(sizeof(struct cfparam));
365 np->name = estrdup(name);
366 STAILQ_INIT(&np->val);
367 STAILQ_CONCAT(&np->val, &nss);
366 TAILQ_INIT(&np->val);
367 TAILQ_CONCAT(&np->val, &nss, tq);
368 np->flags = flags;
369 np->gen = 0;
370 TAILQ_INSERT_TAIL(&j->params, np, tq);
371 if (ipnum != 0)
372 j->intparams[ipnum] = np;
373 else
374 for (ipnum = 1; ipnum < IP_NPARAM; ipnum++)
375 if (!(intparams[ipnum].flags & PF_CONV) &&

--- 12 unchanged lines hidden (view full) ---

388bool_param(const struct cfparam *p)
389{
390 const char *cs;
391
392 if (p == NULL)
393 return 0;
394 cs = strrchr(p->name, '.');
395 return !strncmp(cs ? cs + 1 : p->name, "no", 2) ^
368 np->flags = flags;
369 np->gen = 0;
370 TAILQ_INSERT_TAIL(&j->params, np, tq);
371 if (ipnum != 0)
372 j->intparams[ipnum] = np;
373 else
374 for (ipnum = 1; ipnum < IP_NPARAM; ipnum++)
375 if (!(intparams[ipnum].flags & PF_CONV) &&

--- 12 unchanged lines hidden (view full) ---

388bool_param(const struct cfparam *p)
389{
390 const char *cs;
391
392 if (p == NULL)
393 return 0;
394 cs = strrchr(p->name, '.');
395 return !strncmp(cs ? cs + 1 : p->name, "no", 2) ^
396 (STAILQ_EMPTY(&p->val) ||
397 !strcasecmp(STAILQ_LAST(&p->val, cfstring, tq)->s, "true") ||
398 (strtol(STAILQ_LAST(&p->val, cfstring, tq)->s, NULL, 10)));
396 (TAILQ_EMPTY(&p->val) ||
397 !strcasecmp(TAILQ_LAST(&p->val, cfstrings)->s, "true") ||
398 (strtol(TAILQ_LAST(&p->val, cfstrings)->s, NULL, 10)));
399}
400
401/*
402 * Set an integer if a parameter if it exists.
403 */
404int
405int_param(const struct cfparam *p, int *ip)
406{
399}
400
401/*
402 * Set an integer if a parameter if it exists.
403 */
404int
405int_param(const struct cfparam *p, int *ip)
406{
407 if (p == NULL || STAILQ_EMPTY(&p->val))
407 if (p == NULL || TAILQ_EMPTY(&p->val))
408 return 0;
408 return 0;
409 *ip = strtol(STAILQ_LAST(&p->val, cfstring, tq)->s, NULL, 10);
409 *ip = strtol(TAILQ_LAST(&p->val, cfstrings)->s, NULL, 10);
410 return 1;
411}
412
413/*
414 * Return the string value of a scalar parameter if it exists.
415 */
416const char *
417string_param(const struct cfparam *p)
418{
410 return 1;
411}
412
413/*
414 * Return the string value of a scalar parameter if it exists.
415 */
416const char *
417string_param(const struct cfparam *p)
418{
419 return (p && !STAILQ_EMPTY(&p->val)
420 ? STAILQ_LAST(&p->val, cfstring, tq)->s : NULL);
419 return (p && !TAILQ_EMPTY(&p->val)
420 ? TAILQ_LAST(&p->val, cfstrings)->s : NULL);
421}
422
423/*
424 * Check syntax and values of internal parameters. Set some internal
425 * parameters based on the values of others.
426 */
427int
428check_intparams(struct cfjail *j)

--- 14 unchanged lines hidden (view full) ---

443 struct in6_addr addr6;
444 int ip6ok, isip6;
445 char avalue6[INET6_ADDRSTRLEN];
446#endif
447
448 error = 0;
449 /* Check format of boolan and integer values. */
450 TAILQ_FOREACH(p, &j->params, tq) {
421}
422
423/*
424 * Check syntax and values of internal parameters. Set some internal
425 * parameters based on the values of others.
426 */
427int
428check_intparams(struct cfjail *j)

--- 14 unchanged lines hidden (view full) ---

443 struct in6_addr addr6;
444 int ip6ok, isip6;
445 char avalue6[INET6_ADDRSTRLEN];
446#endif
447
448 error = 0;
449 /* Check format of boolan and integer values. */
450 TAILQ_FOREACH(p, &j->params, tq) {
451 if (!STAILQ_EMPTY(&p->val) &&
452 (p->flags & (PF_BOOL | PF_INT))) {
453 val = STAILQ_LAST(&p->val, cfstring, tq)->s;
451 if (!TAILQ_EMPTY(&p->val) && (p->flags & (PF_BOOL | PF_INT))) {
452 val = TAILQ_LAST(&p->val, cfstrings)->s;
454 if (p->flags & PF_BOOL) {
455 if (strcasecmp(val, "false") &&
456 strcasecmp(val, "true") &&
457 ((void)strtol(val, &ep, 10), *ep)) {
458 jail_warnx(j,
459 "%s: unknown boolean value \"%s\"",
460 p->name, val);
461 error = -1;

--- 98 unchanged lines hidden (view full) ---

560 for (isip6 = 0; isip6 <= 1; isip6++)
561#else
562#define isip6 0
563 do
564#endif
565 {
566 if (j->intparams[KP_IP4_ADDR + isip6] == NULL)
567 continue;
453 if (p->flags & PF_BOOL) {
454 if (strcasecmp(val, "false") &&
455 strcasecmp(val, "true") &&
456 ((void)strtol(val, &ep, 10), *ep)) {
457 jail_warnx(j,
458 "%s: unknown boolean value \"%s\"",
459 p->name, val);
460 error = -1;

--- 98 unchanged lines hidden (view full) ---

559 for (isip6 = 0; isip6 <= 1; isip6++)
560#else
561#define isip6 0
562 do
563#endif
564 {
565 if (j->intparams[KP_IP4_ADDR + isip6] == NULL)
566 continue;
568 STAILQ_FOREACH(s, &j->intparams[KP_IP4_ADDR + isip6]->val, tq) {
567 TAILQ_FOREACH(s, &j->intparams[KP_IP4_ADDR + isip6]->val, tq) {
569 cs = strchr(s->s, '|');
570 if (cs || defif)
571 add_param(j, NULL, IP__IP4_IFADDR + isip6,
572 s->s);
573 if (cs) {
574 strcpy(s->s, cs + 1);
575 s->len -= cs + 1 - s->s;
576 }

--- 28 unchanged lines hidden (view full) ---

605 while (0);
606#endif
607
608 /*
609 * Read mount.fstab file(s), and treat each line as its own mount
610 * parameter.
611 */
612 if (j->intparams[IP_MOUNT_FSTAB] != NULL) {
568 cs = strchr(s->s, '|');
569 if (cs || defif)
570 add_param(j, NULL, IP__IP4_IFADDR + isip6,
571 s->s);
572 if (cs) {
573 strcpy(s->s, cs + 1);
574 s->len -= cs + 1 - s->s;
575 }

--- 28 unchanged lines hidden (view full) ---

604 while (0);
605#endif
606
607 /*
608 * Read mount.fstab file(s), and treat each line as its own mount
609 * parameter.
610 */
611 if (j->intparams[IP_MOUNT_FSTAB] != NULL) {
613 STAILQ_FOREACH(s, &j->intparams[IP_MOUNT_FSTAB]->val, tq) {
612 TAILQ_FOREACH(s, &j->intparams[IP_MOUNT_FSTAB]->val, tq) {
614 if (s->len == 0)
615 continue;
616 f = fopen(s->s, "r");
617 if (f == NULL) {
618 jail_warnx(j, "mount.fstab: %s: %s",
619 s->s, strerror(errno));
620 error = -1;
621 continue;

--- 41 unchanged lines hidden (view full) ---

663 TAILQ_FOREACH(p, &j->params, tq) {
664 if (p->flags & PF_INTERNAL)
665 continue;
666 if (jailparam_init(jp, p->name) < 0) {
667 error = -1;
668 jail_warnx(j, "%s", jail_errmsg);
669 continue;
670 }
613 if (s->len == 0)
614 continue;
615 f = fopen(s->s, "r");
616 if (f == NULL) {
617 jail_warnx(j, "mount.fstab: %s: %s",
618 s->s, strerror(errno));
619 error = -1;
620 continue;

--- 41 unchanged lines hidden (view full) ---

662 TAILQ_FOREACH(p, &j->params, tq) {
663 if (p->flags & PF_INTERNAL)
664 continue;
665 if (jailparam_init(jp, p->name) < 0) {
666 error = -1;
667 jail_warnx(j, "%s", jail_errmsg);
668 continue;
669 }
671 if (STAILQ_EMPTY(&p->val))
670 if (TAILQ_EMPTY(&p->val))
672 value = NULL;
673 else if (!jp->jp_elemlen ||
671 value = NULL;
672 else if (!jp->jp_elemlen ||
674 !STAILQ_NEXT(STAILQ_FIRST(&p->val), tq)) {
673 !TAILQ_NEXT(TAILQ_FIRST(&p->val), tq)) {
675 /*
676 * Scalar parameters silently discard multiple (array)
677 * values, keeping only the last value added. This
678 * lets values added from the command line append to
679 * arrays wthout pre-checking the type.
680 */
674 /*
675 * Scalar parameters silently discard multiple (array)
676 * values, keeping only the last value added. This
677 * lets values added from the command line append to
678 * arrays wthout pre-checking the type.
679 */
681 value = STAILQ_LAST(&p->val, cfstring, tq)->s;
680 value = TAILQ_LAST(&p->val, cfstrings)->s;
682 } else {
683 /*
684 * Convert arrays into comma-separated strings, which
685 * jailparam_import will then convert back into arrays.
686 */
687 vallen = 0;
681 } else {
682 /*
683 * Convert arrays into comma-separated strings, which
684 * jailparam_import will then convert back into arrays.
685 */
686 vallen = 0;
688 STAILQ_FOREACH(s, &p->val, tq)
687 TAILQ_FOREACH(s, &p->val, tq)
689 vallen += s->len + 1;
690 value = alloca(vallen);
691 cs = value;
688 vallen += s->len + 1;
689 value = alloca(vallen);
690 cs = value;
692 STAILQ_FOREACH_SAFE(s, &p->val, tq, ts) {
691 TAILQ_FOREACH_SAFE(s, &p->val, tq, ts) {
693 strcpy(cs, s->s);
694 if (ts != NULL) {
695 cs += s->len + 1;
696 cs[-1] = ',';
697 }
698 }
699 }
700 if (jailparam_import(jp, value) < 0) {

--- 90 unchanged lines hidden (view full) ---

791}
792
793static void
794free_param_strings(struct cfparam *p)
795{
796 struct cfstring *s;
797 struct cfvar *v;
798
692 strcpy(cs, s->s);
693 if (ts != NULL) {
694 cs += s->len + 1;
695 cs[-1] = ',';
696 }
697 }
698 }
699 if (jailparam_import(jp, value) < 0) {

--- 90 unchanged lines hidden (view full) ---

790}
791
792static void
793free_param_strings(struct cfparam *p)
794{
795 struct cfstring *s;
796 struct cfvar *v;
797
799 while ((s = STAILQ_FIRST(&p->val))) {
798 while ((s = TAILQ_FIRST(&p->val))) {
800 free(s->s);
801 while ((v = STAILQ_FIRST(&s->vars))) {
802 free(v->name);
803 STAILQ_REMOVE_HEAD(&s->vars, tq);
804 free(v);
805 }
799 free(s->s);
800 while ((v = STAILQ_FIRST(&s->vars))) {
801 free(v->name);
802 STAILQ_REMOVE_HEAD(&s->vars, tq);
803 free(v);
804 }
806 STAILQ_REMOVE_HEAD(&p->val, tq);
805 TAILQ_REMOVE(&p->val, s, tq);
807 free(s);
808 }
809}
806 free(s);
807 }
808}