predicates are part of the grammar now; in non-root case, predicates are

evaluated only once; in root case, predicates and variable expansion are
dynamic.
This commit is contained in:
provos 2002-10-08 14:49:23 +00:00
parent a8909a2b8b
commit 89afc325c0
12 changed files with 385 additions and 181 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: filter.c,v 1.8 2002/10/06 03:16:25 provos Exp $ */
/* $NetBSD: filter.c,v 1.9 2002/10/08 14:49:23 provos Exp $ */
/* $OpenBSD: filter.c,v 1.16 2002/08/08 21:18:20 provos Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -30,7 +30,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: filter.c,v 1.8 2002/10/06 03:16:25 provos Exp $");
__RCSID("$NetBSD: filter.c,v 1.9 2002/10/08 14:49:23 provos Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -53,33 +53,38 @@ extern int allow;
extern int noalias;
extern int connected;
extern char cwd[];
extern char home[];
extern char username[];
static void logic_free(struct logic *);
static int filter_match(struct intercept_tlq *, struct logic *);
static int filter_match(struct intercept_pid *, struct intercept_tlq *,
struct logic *);
static void filter_review(struct filterq *);
static void filter_templates(const char *);
static int filter_template(int, struct policy *, int);
static int filter_quickpredicate(struct filter *);
static void filter_policyrecord(struct policy *, struct filter *, const char *,
const char *, char *);
static void filter_replace(char *, size_t, char *, char *);
static int
filter_match(struct intercept_tlq *tls, struct logic *logic)
filter_match(struct intercept_pid *icpid, struct intercept_tlq *tls,
struct logic *logic)
{
struct intercept_translate *tl;
int off = 0;
int off = 0, res;
switch (logic->op) {
case LOGIC_NOT:
return (!filter_match(tls, logic->left));
return (!filter_match(icpid, tls, logic->left));
case LOGIC_OR:
if (filter_match(tls, logic->left))
if (filter_match(icpid, tls, logic->left))
return (1);
return (filter_match(tls, logic->right));
return (filter_match(icpid, tls, logic->right));
case LOGIC_AND:
if (!filter_match(tls, logic->left))
if (!filter_match(icpid, tls, logic->left))
return (0);
return (filter_match(tls, logic->right));
return (filter_match(icpid, tls, logic->right));
default:
break;
}
@ -88,6 +93,9 @@ filter_match(struct intercept_tlq *tls, struct logic *logic)
if (logic->type == NULL)
goto match;
if (tls == NULL)
errx(1, "filter_match has no translators");
TAILQ_FOREACH(tl, tls, next) {
if (!tl->trans_valid)
return (0);
@ -105,11 +113,47 @@ filter_match(struct intercept_tlq *tls, struct logic *logic)
return (0);
match:
return (logic->filter_match(tl, logic));
/* We need to do dynamic expansion on the data */
if (logic->filterdata && (logic->flags & LOGIC_NEEDEXPAND)) {
char *old = logic->filterdata;
size_t oldlen = logic->filterlen;
logic->filterdata = filter_dynamicexpand(icpid, old);
logic->filterlen = strlen(logic->filterdata) + 1;
res = logic->filter_match(tl, logic);
logic->filterdata = old;
logic->filterlen = oldlen;
} else
res = logic->filter_match(tl, logic);
return (res);
}
/* Evaluate filter predicate */
int
filter_predicate(struct intercept_pid *icpid, struct predicate *pdc)
{
int negative;
int res = 0;
if (!pdc->p_flags)
return (1);
negative = pdc->p_flags & PREDIC_NEGATIVE;
if (pdc->p_flags & PREDIC_UID)
res = icpid->uid == pdc->p_uid;
else if (pdc->p_flags & PREDIC_GID)
res = icpid->uid == pdc->p_uid;
return (negative ? !res : res);
}
short
filter_evaluate(struct intercept_tlq *tls, struct filterq *fls, int *pflags)
filter_evaluate(struct intercept_tlq *tls, struct filterq *fls,
struct intercept_pid *icpid)
{
struct filter *filter, *last = NULL;
short action, laction = 0;
@ -117,7 +161,8 @@ filter_evaluate(struct intercept_tlq *tls, struct filterq *fls, int *pflags)
TAILQ_FOREACH(filter, fls, next) {
action = filter->match_action;
if (filter_match(tls, filter->logicroot)) {
if (filter_predicate(icpid, &filter->match_predicate) &&
filter_match(icpid, tls, filter->logicroot)) {
/* Profile feedback optimization */
filter->match_count++;
if (last != NULL && last->match_action == action &&
@ -128,7 +173,7 @@ filter_evaluate(struct intercept_tlq *tls, struct filterq *fls, int *pflags)
if (action == ICPOLICY_NEVER)
action = filter->match_error;
*pflags = filter->match_flags;
icpid->uflags = filter->match_flags;
return (action);
}
@ -351,6 +396,28 @@ filter_modifypolicy(int fd, int policynr, const char *emulation,
}
}
/* In non-root case, evaluate predicates early */
static int
filter_quickpredicate(struct filter *filter)
{
struct predicate *pdc;
struct intercept_pid icpid;
pdc = &filter->match_predicate;
if (!pdc->p_flags)
return (1);
intercept_setpid(&icpid);
if (!filter_predicate(&icpid, pdc))
return (0);
memset(pdc, 0, sizeof(filter->match_predicate));
return (1);
}
int
filter_prepolicy(int fd, struct policy *policy)
{
@ -358,6 +425,7 @@ filter_prepolicy(int fd, struct policy *policy)
struct filter *filter, *parsed;
struct filterq *fls;
short action, future;
extern int iamroot;
/* Commit all matching pre-filters */
for (filter = TAILQ_FIRST(&policy->prefilters);
@ -376,9 +444,11 @@ filter_prepolicy(int fd, struct policy *policy)
__func__, __LINE__, filter->rule);
if (future == ICPOLICY_ASK) {
fls = systrace_policyflq(policy, policy->emulation,
filter->name);
TAILQ_INSERT_TAIL(fls, parsed, next);
if (iamroot || filter_quickpredicate(parsed)) {
fls = systrace_policyflq(policy,
policy->emulation, filter->name);
TAILQ_INSERT_TAIL(fls, parsed, next);
}
} else {
filter_modifypolicy(fd, policy->policynr,
policy->emulation, filter->name, future);
@ -398,7 +468,7 @@ filter_prepolicy(int fd, struct policy *policy)
short
filter_ask(int fd, struct intercept_tlq *tls, struct filterq *fls,
int policynr, const char *emulation, const char *name,
char *output, short *pfuture, int *pflags)
char *output, short *pfuture, struct intercept_pid *icpid)
{
char line[2*MAXPATHLEN], *p;
struct filter *filter;
@ -407,7 +477,7 @@ filter_ask(int fd, struct intercept_tlq *tls, struct filterq *fls,
int first = 1;
*pfuture = ICPOLICY_ASK;
*pflags = 0;
icpid->uflags = 0;
if ((policy = systrace_findpolnr(policynr)) == NULL)
errx(1, "%s:%d: no policy %d", __func__, __LINE__, policynr);
@ -505,10 +575,10 @@ filter_ask(int fd, struct intercept_tlq *tls, struct filterq *fls,
continue;
}
if (fls == NULL)
action = ICPOLICY_PERMIT;
if (fls != NULL)
action = filter_evaluate(tls, fls, icpid);
else
action = filter_evaluate(tls, fls, pflags);
action = ICPOLICY_PERMIT;
if (action == ICPOLICY_ASK) {
printf("Filter unmatched.\n");
continue;
@ -532,7 +602,7 @@ filter_ask(int fd, struct intercept_tlq *tls, struct filterq *fls,
continue;
TAILQ_INSERT_TAIL(fls, filter, next);
action = filter_evaluate(tls, fls, pflags);
action = filter_evaluate(tls, fls, icpid);
if (action == ICPOLICY_ASK) {
TAILQ_REMOVE(fls, filter, next);
printf("Filter unmatched. Freeing it\n");
@ -563,23 +633,45 @@ char *
filter_expand(char *data)
{
static char expand[2*MAXPATHLEN];
char *what;
if (data != NULL)
strlcpy(expand, data, sizeof(expand));
what = getenv("HOME");
if (what != NULL)
filter_replace(expand, sizeof(expand), "$HOME", what);
what = getenv("USER");
if (what != NULL)
filter_replace(expand, sizeof(expand), "$USER", what);
strlcpy(expand, data, sizeof(expand));
filter_replace(expand, sizeof(expand), "$HOME", home);
filter_replace(expand, sizeof(expand), "$USER", username);
filter_replace(expand, sizeof(expand), "$CWD", cwd);
return (expand);
}
char *
filter_dynamicexpand(struct intercept_pid *icpid, char *data)
{
static char expand[2*MAXPATHLEN];
strlcpy(expand, data, sizeof(expand));
filter_replace(expand, sizeof(expand), "$HOME", icpid->home);
filter_replace(expand, sizeof(expand), "$USER", icpid->username);
filter_replace(expand, sizeof(expand), "$CWD", icpid->cwd);
return (expand);
}
/* Checks if the string needs expansion */
int
filter_needexpand(char *data)
{
if (strstr(data, "$HOME") != NULL)
return (1);
if (strstr(data, "$USER") != NULL)
return (1);
if (strstr(data, "$CWD") != NULL)
return (1);
return (0);
}
int
filter_fnmatch(struct intercept_translate *tl, struct logic *logic)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: intercept.c,v 1.6 2002/09/17 04:54:36 itojun Exp $ */
/* $NetBSD: intercept.c,v 1.7 2002/10/08 14:49:23 provos Exp $ */
/* $OpenBSD: intercept.c,v 1.29 2002/08/28 03:30:27 itojun Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -30,7 +30,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: intercept.c,v 1.6 2002/09/17 04:54:36 itojun Exp $");
__RCSID("$NetBSD: intercept.c,v 1.7 2002/10/08 14:49:23 provos Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -48,6 +48,7 @@ __RCSID("$NetBSD: intercept.c,v 1.6 2002/09/17 04:54:36 itojun Exp $");
#include <errno.h>
#include <err.h>
#include <libgen.h>
#include <pwd.h>
#include "intercept.h"
@ -233,6 +234,21 @@ sigusr1_handler(int signum)
/* all we need to do is pretend to handle it */
}
void
intercept_setpid(struct intercept_pid *icpid)
{
struct passwd *pw;
icpid->uid = getuid();
icpid->gid = getgid();
if (getcwd(icpid->cwd, sizeof(icpid->cwd)) == NULL)
err(1, "getcwd");
if ((pw = getpwuid(icpid->uid)) == NULL)
err(1, "getpwuid");
strlcpy(icpid->username, pw->pw_name, sizeof(icpid->username));
strlcpy(icpid->home, pw->pw_dir, sizeof(icpid->home));
}
pid_t
intercept_run(int bg, int fd, char *path, char *const argv[])
{
@ -300,10 +316,8 @@ intercept_run(int bg, int fd, char *path, char *const argv[])
if ((icpid = intercept_getpid(pid)) == NULL)
err(1, "intercept_getpid");
/* Set uid and gid information */
icpid->uid = getuid();
icpid->gid = getgid();
icpid->flags |= ICFLAGS_UIDKNOWN | ICFLAGS_GIDKNOWN;
/* Set up user related information */
intercept_setpid(icpid);
/* Setup done, restore signal handling state */
if (signal(SIGUSR1, ohandler) == SIG_ERR) {
@ -529,6 +543,7 @@ char *
intercept_filename(int fd, pid_t pid, void *addr, int userp)
{
static char cwd[2*MAXPATHLEN];
struct intercept_pid *icpid;
char *name;
name = intercept_get_string(fd, pid, addr);
@ -544,6 +559,12 @@ intercept_filename(int fd, pid_t pid, void *addr, int userp)
err(1, "%s: getcwd", __func__);
}
/* Update cwd for process */
if ((icpid = intercept_getpid(pid)) == NULL)
err(1, "intercept_getpid");
if (strlcpy(icpid->cwd, cwd, sizeof(icpid->cwd)) >= sizeof(icpid->cwd))
errx(1, "cwd too long");
if (name[0] != '/') {
if (strlcat(cwd, "/", sizeof(cwd)) >= sizeof(cwd))
goto error;
@ -671,8 +692,6 @@ intercept_syscall(int fd, pid_t pid, u_int16_t seqnr, int policynr,
/* We need to know the result from this system call */
flags = ICFLAGS_RESULT;
} else if (!strcmp(name, "setuid") || !strcmp(name, "setgid")) {
flags = ICFLAGS_RESULT;
}
sc = intercept_sccb_find(emulation, name);
@ -727,19 +746,8 @@ intercept_syscall_result(int fd, pid_t pid, u_int16_t seqnr, int policynr,
(*intercept_newimagecb)(fd, pid, policynr, emulation,
icpid->name, intercept_newimagecbarg);
} else if (!strcmp("setuid", name)) {
register_t reg;
intercept.getarg(0, args, argsize, (void **)&reg);
icpid->uid = reg;
icpid->flags |= ICFLAGS_UIDKNOWN;
} else if (!strcmp("setgid", name)) {
register_t reg;
intercept.getarg(0, args, argsize, (void **)&reg);
icpid->gid = reg;
icpid->flags |= ICFLAGS_GIDKNOWN;
}
out:
/* Resume execution of the process */
intercept.answer(fd, pid, seqnr, 0, 0, 0);
@ -803,10 +811,34 @@ intercept_child_info(pid_t opid, pid_t npid)
inpid->ppid = opid;
/* Copy some information */
inpid->flags = ipid->flags;
inpid->uid = ipid->uid;
inpid->gid = ipid->gid;
strlcpy(inpid->username, ipid->username, sizeof(inpid->username));
strlcpy(inpid->home, ipid->home, sizeof(inpid->home));
strlcpy(inpid->cwd, ipid->cwd, sizeof(inpid->cwd));
/* XXX - keeps track of emulation */
intercept.clonepid(ipid, inpid);
}
void
intercept_ugid(struct intercept_pid *icpid, uid_t uid, gid_t gid)
{
/* Update current home dir */
if (icpid->uid != uid) {
struct passwd *pw;
if ((pw = getpwuid(uid)) == NULL) {
snprintf(icpid->username, sizeof(icpid->username),
"uid %d", uid);
strlcpy(icpid->home, "/", sizeof(icpid->home));
} else {
strlcpy(icpid->username, pw->pw_name,
sizeof(icpid->username));
strlcpy(icpid->home, pw->pw_dir, sizeof(icpid->home));
}
}
icpid->uid = uid;
icpid->gid = gid;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: intercept.h,v 1.4 2002/08/28 03:52:45 itojun Exp $ */
/* $NetBSD: intercept.h,v 1.5 2002/10/08 14:49:24 provos Exp $ */
/* $OpenBSD: intercept.h,v 1.11 2002/08/04 04:15:50 provos Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -32,6 +32,7 @@
#ifndef _INTERCEPT_H_
#define _INTERCEPT_H_
#include <sys/param.h>
#include <sys/queue.h>
struct intercept_pid;
@ -84,13 +85,13 @@ struct intercept_pid {
char *name; /* name of current process image */
char *newname; /* image name to be committed by execve */
#define ICFLAGS_UIDKNOWN 0x01
#define ICFLAGS_GIDKNOWN 0x02
int flags;
uid_t uid; /* current uid */
gid_t gid; /* current gid */
char username[MAXLOGNAME];
char home[MAXPATHLEN]; /* current home dir for uid */
char cwd[MAXPATHLEN]; /* current working directory */
void *data;
int uflags; /* Flags that can be used by external application */
@ -175,5 +176,7 @@ void intercept_syscall(int, pid_t, u_int16_t, int, const char *, int,
const char *, void *, int);
void intercept_syscall_result(int, pid_t, u_int16_t, int, const char *, int,
const char *, void *, int, int, void *);
void intercept_ugid(struct intercept_pid *, uid_t, gid_t);
void intercept_setpid(struct intercept_pid *);
#endif /* _INTERCEPT_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: lex.l,v 1.3 2002/08/28 03:52:45 itojun Exp $ */
/* $NetBSD: lex.l,v 1.4 2002/10/08 14:49:24 provos Exp $ */
/* $OpenBSD: lex.l,v 1.9 2002/08/04 04:15:50 provos Exp $ */
/*
@ -34,7 +34,7 @@
%{
#include <sys/cdefs.h>
__RCSID("$NetBSD: lex.l,v 1.3 2002/08/28 03:52:45 itojun Exp $");
__RCSID("$NetBSD: lex.l,v 1.4 2002/10/08 14:49:24 provos Exp $");
#include <sys/types.h>
#include <sys/tree.h>
@ -94,6 +94,12 @@ true { return TRUE; }
"->" { return THEN; }
\( { return LBRACE; }
\) { return RBRACE; }
if { return IF; }
user { return USER; }
group { return GROUP; }
"," { return COMMA; }
"=" { return EQUAL; }
"!=" { return NEQUAL; }
[\$A-Za-z][\.\(\)\/A-Za-z_\-0-9]* { yylval.string = strdup(yytext); return STRING; }
[0-9]+ { yylval.number = atoi(yytext); return NUMBER; }
\"[^\"]+\" { char line[1024];

View File

@ -1,4 +1,4 @@
/* $NetBSD: netbsd-syscalls.c,v 1.7 2002/08/28 03:52:45 itojun Exp $ */
/* $NetBSD: netbsd-syscalls.c,v 1.8 2002/10/08 14:49:24 provos Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: netbsd-syscalls.c,v 1.7 2002/08/28 03:52:45 itojun Exp $");
__RCSID("$NetBSD: netbsd-syscalls.c,v 1.8 2002/10/08 14:49:24 provos Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -614,6 +614,17 @@ nbsd_read(int fd)
err(1, "%s:%d: answer", __func__, __LINE__);
break;
case SYSTR_MSG_UGID: {
struct str_msg_ugid *msg_ugid;
msg_ugid = &msg.msg_data.msg_ugid;
intercept_ugid(icpid, msg_ugid->uid, msg_ugid->uid);
if (nbsd_answer(fd, pid, seqnr, 0, 0, 0) == -1)
err(1, "%s:%d: answer", __func__, __LINE__);
break;
}
case SYSTR_MSG_CHILD:
intercept_child_info(msg.msg_pid,
msg.msg_data.msg_child.new_pid);

View File

@ -1,4 +1,4 @@
/* $NetBSD: openbsd-syscalls.c,v 1.3 2002/08/28 03:52:46 itojun Exp $ */
/* $NetBSD: openbsd-syscalls.c,v 1.4 2002/10/08 14:49:24 provos Exp $ */
/* $OpenBSD: openbsd-syscalls.c,v 1.12 2002/08/28 03:30:27 itojun Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -596,6 +596,17 @@ obsd_read(int fd)
err(1, "%s:%d: answer", __func__, __LINE__);
break;
case SYSTR_MSG_UGID: {
struct str_msg_ugid *msg_ugid;
msg_ugid = &msg.msg_data.msg_ugid;
intercept_ugid(icpid, msg_ugid->uid, msg_ugid->uid);
if (obsd_answer(fd, pid, seqnr, 0, 0, 0) == -1)
err(1, "%s:%d: answer", __func__, __LINE__);
break;
}
case SYSTR_MSG_CHILD:
intercept_child_info(msg.msg_pid,
msg.msg_data.msg_child.new_pid);

View File

@ -1,4 +1,4 @@
/* $NetBSD: parse.y,v 1.3 2002/08/28 03:52:46 itojun Exp $ */
/* $NetBSD: parse.y,v 1.4 2002/10/08 14:49:24 provos Exp $ */
/* $OpenBSD: parse.y,v 1.9 2002/08/04 04:15:50 provos Exp $ */
/*
@ -32,7 +32,7 @@
*/
%{
#include <sys/cdefs.h>
__RCSID("$NetBSD: parse.y,v 1.3 2002/08/28 03:52:46 itojun Exp $");
__RCSID("$NetBSD: parse.y,v 1.4 2002/10/08 14:49:24 provos Exp $");
#include <sys/types.h>
@ -44,6 +44,9 @@ __RCSID("$NetBSD: parse.y,v 1.3 2002/08/28 03:52:46 itojun Exp $");
#include <err.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include "intercept.h"
#include "systrace.h"
@ -66,7 +69,7 @@ extern int myoff;
%}
%token AND OR NOT LBRACE RBRACE LSQBRACE RSQBRACE THEN MATCH PERMIT DENY
%token EQ NEQ TRUE SUB NSUB INPATH LOG
%token EQ NEQ TRUE SUB NSUB INPATH LOG COMMA IF USER GROUP EQUAL NEQUAL
%token <string> STRING
%token <string> CMDSTRING
%token <number> NUMBER
@ -76,15 +79,17 @@ extern int myoff;
%type <number> typeoff
%type <number> logcode
%type <string> errorcode
%type <predicate> predicate
%union {
int number;
char *string;
short action;
struct logic *logic;
struct predicate predicate;
}
%%
fullexpression : expression THEN action errorcode logcode
fullexpression : expression THEN action errorcode logcode predicate
{
int flags = 0, errorcode = SYSTRACE_EPERM;
@ -123,6 +128,7 @@ fullexpression : expression THEN action errorcode logcode
myfilter->match_action = $3;
myfilter->match_error = errorcode;
myfilter->match_flags = flags;
myfilter->match_predicate = $6;
}
;
@ -146,6 +152,59 @@ logcode : /* Empty */
}
;
predicate : /* Empty */
{
memset(&$$, 0, sizeof($$));
}
| COMMA IF USER EQUAL STRING
{
struct passwd *pw;
memset(&$$, 0, sizeof($$));
if ((pw = getpwnam($5)) == NULL) {
yyerror("Unknown user %s", $5);
break;
}
$$.p_uid = pw->pw_uid;
$$.p_flags = PREDIC_UID;
}
| COMMA IF USER NEQUAL STRING
{
struct passwd *pw;
memset(&$$, 0, sizeof($$));
if ((pw = getpwnam($5)) == NULL) {
yyerror("Unknown user %s", $5);
break;
}
$$.p_uid = pw->pw_uid;
$$.p_flags = PREDIC_UID | PREDIC_NEGATIVE;
}
| COMMA IF GROUP EQUAL STRING
{
struct group *gr;
memset(&$$, 0, sizeof($$));
if ((gr = getgrnam($5)) == NULL) {
yyerror("Unknown group %s", $5);
break;
}
$$.p_gid = gr->gr_gid;
$$.p_flags = PREDIC_GID;
}
| COMMA IF GROUP NEQUAL STRING
{
struct group *gr;
memset(&$$, 0, sizeof($$));
if ((gr = getgrnam($5)) == NULL) {
yyerror("Unknown group %s", $5);
break;
}
$$.p_gid = gr->gr_gid;
$$.p_flags = PREDIC_GID | PREDIC_NEGATIVE;
}
expression : symbol
{
$$ = $1;
@ -306,6 +365,8 @@ struct logic *
parse_newsymbol(char *type, int typeoff, char *data)
{
struct logic *node;
int iamroot = getuid() == 0;
node = calloc(1, sizeof(struct logic));
if (node == NULL) {
@ -316,8 +377,15 @@ parse_newsymbol(char *type, int typeoff, char *data)
node->type = type;
node->typeoff = typeoff;
if (data) {
node->filterdata = strdup(filter_expand(data));
free(data);
/* For the root user, variable expansion may change */
if (iamroot) {
node->filterdata = data;
if (filter_needexpand(data))
node->flags |= LOGIC_NEEDEXPAND;
} else {
node->filterdata = strdup(filter_expand(data));
free(data);
}
if (node->filterdata == NULL) {
yyerror("strdup");
return (NULL);

View File

@ -1,4 +1,4 @@
/* $NetBSD: policy.c,v 1.7 2002/09/23 04:35:41 itojun Exp $ */
/* $NetBSD: policy.c,v 1.8 2002/10/08 14:49:24 provos Exp $ */
/* $OpenBSD: policy.c,v 1.15 2002/08/07 00:34:17 vincent Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -30,7 +30,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: policy.c,v 1.7 2002/09/23 04:35:41 itojun Exp $");
__RCSID("$NetBSD: policy.c,v 1.8 2002/10/08 14:49:24 provos Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -55,8 +55,8 @@ static int policycompare(struct policy *, struct policy *);
static int polnrcompare(struct policy *, struct policy *);
static char *systrace_policyfilename(char *, const char *);
static char *systrace_policyline(char *line);
static int systrace_policyprocess(struct policy *, char *);
static int systrace_predicatematch(char *);
static int systrace_policyprocess(struct policy *,
char *);
static int systrace_writepolicy(struct policy *);
int systrace_templatedir(void);
@ -411,6 +411,7 @@ systrace_readtemplate(char *filename, struct policy *policy,
if ((fp = fopen(filename, "r")) == NULL)
return (NULL);
/* Set up pid with current information */
while (fgets(line, sizeof(line), fp)) {
linenumber++;
@ -477,59 +478,6 @@ systrace_readtemplate(char *filename, struct policy *policy,
goto out;
}
int
systrace_predicatematch(char *p)
{
extern char *username;
int i, res, neg;
res = 0;
neg = 0;
if (!strncasecmp(p, "user", 4)) {
/* Match against user name */
p += 4;
p += strspn(p, " \t");
if (!strncmp(p, "=", 1)) {
p += 1;
neg = 0;
} else if (!strncmp(p, "!=", 2)) {
p += 2;
neg = 1;
} else
return (-1);
p += strspn(p, " \t");
res = (!strcmp(p, username));
} else if (!strncasecmp(p, "group", 5)) {
/* Match against group list */
p += 5;
p += strspn(p, " \t");
if (!strncmp(p, "=", 1)) {
p += 1;
neg = 0;
} else if (!strncmp(p, "!=", 2)) {
p += 2;
neg = 1;
} else
return (-1);
p += strspn(p, " \t");
for (i = 0; i < ngroups; i++) {
if (!strcmp(p, groupnames[i])) {
res = 1;
break;
}
}
} else
return (-1);
if (neg)
res = !res;
return (res);
}
/* Removes trailing whitespace and comments from the input line */
static char *
@ -573,9 +521,13 @@ systrace_policyline(char *line)
static int
systrace_policyprocess(struct policy *policy, char *p)
{
char line[_POSIX2_LINE_MAX];
char *name, *emulation, *rule;
struct filter *filter, *parsed;
short action, future;
int resolved = 0, res;
/* Delay predicate evaluation if we are root */
emulation = strsep(&p, "-");
if (p == NULL || *p == '\0')
@ -591,25 +543,22 @@ systrace_policyprocess(struct policy *policy, char *p)
rule = p;
if ((p = strrchr(p, ',')) != NULL && !strncasecmp(p, ", if", 4)) {
int match;
*p = '\0';
res = filter_parse_simple(rule, &action, &future);
*p = ',';
if (res == 0) {
/* Need to make a real policy out of it */
snprintf(line, sizeof(line), "true then %s", rule);
rule = line;
}
} else if (filter_parse_simple(rule, &action, &future) == 0)
resolved = 1;
/* Process predicates */
p += 4;
p += strspn(p, " \t");
match = systrace_predicatematch(p);
if (match == -1)
return (-1);
/* If the predicate does not match skip rule */
if (!match)
return (0);
}
if (filter_parse_simple(rule, &action, &future) == -1) {
/* If the simple parser did not match, try real parser */
if (!resolved) {
if (parse_filter(rule, &parsed) == -1)
return (-1);
filter_free(parsed);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: systrace.c,v 1.9 2002/10/08 02:47:59 itojun Exp $ */
/* $NetBSD: systrace.c,v 1.10 2002/10/08 14:49:24 provos Exp $ */
/* $OpenBSD: systrace.c,v 1.32 2002/08/05 23:27:53 provos Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -45,6 +45,7 @@
#include <string.h>
#include <err.h>
#include <errno.h>
#include <pwd.h>
#include "intercept.h"
#include "systrace.h"
@ -58,13 +59,36 @@ int automatic = 0; /* Do not run interactively */
int allow = 0; /* Allow all and generate */
int userpolicy = 1; /* Permit user defined policies */
int noalias = 0; /* Do not do system call aliasing */
char *username = NULL; /* Username in automatic mode */
char cwd[MAXPATHLEN]; /* Current working directory of process */
int iamroot = 0; /* Set if we are running as root */
char cwd[MAXPATHLEN]; /* Current working directory */
char home[MAXPATHLEN]; /* Home directory of user */
char username[MAXLOGNAME]; /* Username: predicate match and expansion */
static void child_handler(int);
static void usage(void);
static int requestor_start(char *);
void
systrace_parameters(void)
{
struct passwd *pw;
uid_t uid = getuid();
iamroot = getuid() == 0;
/* Find out current username. */
if ((pw = getpwuid(uid)) == NULL)
snprintf(username, sizeof(username), "uid %u", uid);
else
snprintf(username, sizeof(username), "%s", pw->pw_name);
strlcpy(home, pw->pw_dir, sizeof(home));
/* Determine current working directory for filtering */
if (getcwd(cwd, sizeof(cwd)) == NULL)
err(1, "getcwd");
}
/*
* Generate human readable output and setup replacements if available.
*/
@ -151,7 +175,7 @@ trans_cb(int fd, pid_t pid, int policynr,
if ((pflq = systrace_policyflq(policy, emulation, name)) == NULL)
errx(1, "%s:%d: no filter queue", __func__, __LINE__);
action = filter_evaluate(tls, pflq, &ipid->uflags);
action = filter_evaluate(tls, pflq, ipid);
if (action != ICPOLICY_ASK)
goto replace;
@ -178,7 +202,7 @@ trans_cb(int fd, pid_t pid, int policynr,
alias->aemul, alias->aname)) == NULL)
errx(1, "%s:%d: no filter queue", __func__, __LINE__);
action = filter_evaluate(tls, pflq, &ipid->uflags);
action = filter_evaluate(tls, pflq, ipid);
if (action != ICPOLICY_ASK)
goto replace;
@ -194,7 +218,7 @@ trans_cb(int fd, pid_t pid, int policynr,
}
action = filter_ask(fd, tls, pflq, policynr, emulation, name,
output, &future, &ipid->uflags);
output, &future, ipid);
if (future != ICPOLICY_ASK)
filter_modifypolicy(fd, policynr, emulation, name, future);
@ -219,7 +243,7 @@ trans_cb(int fd, pid_t pid, int policynr,
if (log)
syslog(LOG_WARNING, "%s user: %s, prog: %s",
action < ICPOLICY_NEVER ? "permit" : "deny",
username, output);
ipid->username, output);
return (action);
}
@ -231,6 +255,7 @@ gen_cb(int fd, pid_t pid, int policynr, const char *name, int code,
char output[_POSIX2_LINE_MAX];
struct policy *policy;
struct intercept_pid *ipid;
struct filterq *pflq = NULL;
short action = ICPOLICY_PERMIT;
short future;
int len, off, log = 0;
@ -256,6 +281,13 @@ gen_cb(int fd, pid_t pid, int policynr, const char *name, int code,
if (len > 0)
snprintf(output + off, len, ", args: %d", argsize);
if ((pflq = systrace_policyflq(policy, emulation, name)) == NULL)
errx(1, "%s:%d: no filter queue", __func__, __LINE__);
action = filter_evaluate(NULL, pflq, ipid);
if (action != ICPOLICY_ASK)
goto out;
if (policy->flags & POLICY_UNSUPERVISED) {
action = ICPOLICY_NEVER;
log = 1;
@ -263,7 +295,7 @@ gen_cb(int fd, pid_t pid, int policynr, const char *name, int code,
}
action = filter_ask(fd, NULL, NULL, policynr, emulation, name,
output, &future, &ipid->uflags);
output, &future, ipid);
if (future != ICPOLICY_ASK)
systrace_modifypolicy(fd, policynr, name, future);
@ -278,7 +310,7 @@ gen_cb(int fd, pid_t pid, int policynr, const char *name, int code,
if (log)
syslog(LOG_WARNING, "%s user: %s, prog: %s",
action < ICPOLICY_NEVER ? "permit" : "deny",
username, output);
ipid->username, output);
return (action);
}
@ -471,12 +503,7 @@ main(int argc, char **argv)
if (argc == 0 || (pidattach && *argv[0] != '/'))
usage();
/* Username for automatic mode, and policy predicates */
username = uid_to_name(getuid());
/* Determine current working directory for filtering */
if (getcwd(cwd, sizeof(cwd)) == NULL)
err(1, "getcwd");
systrace_parameters();
/* Local initalization */
systrace_initalias();

View File

@ -1,4 +1,4 @@
/* $NetBSD: systrace.h,v 1.5 2002/09/23 04:35:42 itojun Exp $ */
/* $NetBSD: systrace.h,v 1.6 2002/10/08 14:49:24 provos Exp $ */
/* $OpenBSD: systrace.h,v 1.14 2002/08/05 23:27:53 provos Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -44,11 +44,14 @@ struct logic {
struct logic *right;
char *type;
int typeoff;
int flags;
void *filterdata;
size_t filterlen;
int (*filter_match)(struct intercept_translate *, struct logic *);
};
#define LOGIC_NEEDEXPAND 0x01
struct filter {
TAILQ_ENTRY(filter) next;
TAILQ_ENTRY(filter) policy_next;
@ -61,6 +64,15 @@ struct filter {
int match_error;
int match_flags;
int match_count; /* Number of times this filter matched */
struct predicate {
#define PREDIC_UID 0x01
#define PREDIC_GID 0x02
#define PREDIC_NEGATIVE 0x10
int p_flags;
uid_t p_uid;
gid_t p_gid;
} match_predicate;
};
TAILQ_HEAD(filterq, filter);
@ -113,6 +125,7 @@ TAILQ_HEAD(tmplqueue, template);
#define PROCESS_DETACH 0x02 /* Process gets detached */
#define SYSCALL_LOG 0x04 /* Log this system call */
void systrace_parameters(void);
int systrace_initpolicy(char *, char *);
void systrace_setupdir(char *);
struct template *systrace_readtemplate(char *, struct policy *,
@ -167,16 +180,20 @@ struct systrace_revalias {
struct systrace_revalias *systrace_reverse(const char *, const char *);
struct systrace_revalias *systrace_find_reverse(const char *, const char *);
short filter_evaluate(struct intercept_tlq *, struct filterq *, int *);
short filter_evaluate(struct intercept_tlq *, struct filterq *,
struct intercept_pid *);
short filter_ask(int, struct intercept_tlq *, struct filterq *, int,
const char *, const char *, char *, short *, int *);
const char *, const char *, char *, short *, struct intercept_pid *);
void filter_free(struct filter *);
void filter_modifypolicy(int, int, const char *, const char *, short);
int filter_predicate(struct intercept_pid *, struct predicate *);
int filter_parse_simple(char *, short *, short *);
int filter_parse(char *, struct filter **);
int filter_prepolicy(int, struct policy *);
char *filter_expand(char *data);
char *filter_expand(char *);
char *filter_dynamicexpand(struct intercept_pid *, char *);
int filter_needexpand(char *);
int parse_filter(char *, struct filter **);

View File

@ -1,4 +1,4 @@
/* $NetBSD: util.c,v 1.2 2002/07/30 16:29:31 itojun Exp $ */
/* $NetBSD: util.c,v 1.3 2002/10/08 14:49:24 provos Exp $ */
/* $OpenBSD: util.c,v 1.8 2002/07/19 14:38:58 itojun Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -30,13 +30,12 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: util.c,v 1.2 2002/07/30 16:29:31 itojun Exp $");
__RCSID("$NetBSD: util.c,v 1.3 2002/10/08 14:49:24 provos Exp $");
#include <sys/types.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <pwd.h>
#include "util.h"
@ -74,21 +73,6 @@ strrpl(char *str, size_t size, char *match, char *value)
return (p);
}
char *
uid_to_name(uid_t uid)
{
static char buf[128];
struct passwd *pw;
if ((pw = getpwuid(uid)) == NULL)
snprintf(buf, sizeof(buf), "uid %u", uid);
else
snprintf(buf, sizeof(buf), "%s", pw->pw_name);
return (buf);
}
/* simplify_path is from pdksh and apparently in the public domain */
/* ISABSPATH() means path is fully and completely specified,

View File

@ -1,4 +1,4 @@
/* $NetBSD: util.h,v 1.2 2002/07/30 16:29:31 itojun Exp $ */
/* $NetBSD: util.h,v 1.3 2002/10/08 14:49:24 provos Exp $ */
/* $OpenBSD: util.h,v 1.1 2002/07/19 14:38:58 itojun Exp $ */
/*
@ -31,6 +31,10 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _UTIL_H_
#define _UTIL_H_
void simplify_path(char *);
char *uid_to_name(uid_t);
char *strrpl(char *, size_t, char *, char *);
#endif /* !_UTIL_H_ */