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} |