Deleted Added
sdiff udiff text old ( 214783 ) new ( 223188 )
full compact
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 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:
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 }
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 }
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;
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);
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 }
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 */
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 }
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);
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 }
358 if (!(flags & PF_APPEND) || TAILQ_EMPTY(&nss))
359 free_param_strings(dp);
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);
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) ^
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{
407 if (p == NULL || TAILQ_EMPTY(&p->val))
408 return 0;
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{
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) {
451 if (!TAILQ_EMPTY(&p->val) && (p->flags & (PF_BOOL | PF_INT))) {
452 val = TAILQ_LAST(&p->val, cfstrings)->s;
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;
567 TAILQ_FOREACH(s, &j->intparams[KP_IP4_ADDR + isip6]->val, tq) {
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) {
612 TAILQ_FOREACH(s, &j->intparams[IP_MOUNT_FSTAB]->val, tq) {
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 }
670 if (TAILQ_EMPTY(&p->val))
671 value = NULL;
672 else if (!jp->jp_elemlen ||
673 !TAILQ_NEXT(TAILQ_FIRST(&p->val), tq)) {
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 */
680 value = TAILQ_LAST(&p->val, cfstrings)->s;
681 } else {
682 /*
683 * Convert arrays into comma-separated strings, which
684 * jailparam_import will then convert back into arrays.
685 */
686 vallen = 0;
687 TAILQ_FOREACH(s, &p->val, tq)
688 vallen += s->len + 1;
689 value = alloca(vallen);
690 cs = value;
691 TAILQ_FOREACH_SAFE(s, &p->val, tq, ts) {
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
798 while ((s = TAILQ_FIRST(&p->val))) {
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 }
805 TAILQ_REMOVE(&p->val, s, tq);
806 free(s);
807 }
808}