From owner-p4-projects@FreeBSD.ORG Sun Feb 17 17:43:31 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 2665A16A46C; Sun, 17 Feb 2008 17:43:31 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DE6EE16A420 for ; Sun, 17 Feb 2008 17:43:30 +0000 (UTC) (envelope-from csjp@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id D34B613C45E for ; Sun, 17 Feb 2008 17:43:25 +0000 (UTC) (envelope-from csjp@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m1HHhP3w062268 for ; Sun, 17 Feb 2008 17:43:25 GMT (envelope-from csjp@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m1HHhPJX062260 for perforce@freebsd.org; Sun, 17 Feb 2008 17:43:25 GMT (envelope-from csjp@freebsd.org) Date: Sun, 17 Feb 2008 17:43:25 GMT Message-Id: <200802171743.m1HHhPJX062260@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to csjp@freebsd.org using -f From: "Christian S.J. Peron" To: Perforce Change Reviews Cc: Subject: PERFORCE change 135579 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 17 Feb 2008 17:43:31 -0000 http://perforce.freebsd.org/chv.cgi?CH=135579 Change 135579 by csjp@csjp_xor on 2008/02/17 17:42:30 Lets try that again, but this time on the correct branch. Affected files ... .. //depot/projects/trustedbsd/bsmtrace/Makefile#2 edit .. //depot/projects/trustedbsd/bsmtrace/README#2 edit .. //depot/projects/trustedbsd/bsmtrace/bsm.c#2 edit .. //depot/projects/trustedbsd/bsmtrace/bsmtrace.c#2 edit .. //depot/projects/trustedbsd/bsmtrace/bsmtrace.conf#2 edit .. //depot/projects/trustedbsd/bsmtrace/bsmtrace.conf.5#2 edit .. //depot/projects/trustedbsd/bsmtrace/bsmtrace.ebnf#2 edit .. //depot/projects/trustedbsd/bsmtrace/bsmtrace.h#2 edit .. //depot/projects/trustedbsd/bsmtrace/conf.c#2 edit .. //depot/projects/trustedbsd/bsmtrace/deuce.h#2 edit .. //depot/projects/trustedbsd/bsmtrace/grammar.y#2 edit .. //depot/projects/trustedbsd/bsmtrace/includes.h#2 edit .. //depot/projects/trustedbsd/bsmtrace/log.c#2 edit .. //depot/projects/trustedbsd/bsmtrace/pipe.c#1 add .. //depot/projects/trustedbsd/bsmtrace/pipe.h#1 add .. //depot/projects/trustedbsd/bsmtrace/token.l#2 edit .. //depot/projects/trustedbsd/bsmtrace/trigger.c#2 edit Differences ... ==== //depot/projects/trustedbsd/bsmtrace/Makefile#2 (text+ko) ==== @@ -1,18 +1,18 @@ -# $Id: Makefile,v 1.7 2007/04/13 14:45:12 csjp Exp $ +# $Id: Makefile,v 1.8 2007/07/13 00:03:50 csjp Exp $ CC = gcc CFLAGS = -Wall -g TARGETS = bsmtrace -OBJ = bsm.o bsmtrace.o conf.o y.tab.o lex.yy.o log.o trigger.o +OBJ = bsm.o bsmtrace.o conf.o y.tab.o lex.yy.o log.o pipe.o trigger.o PREFIX = /usr/local LIBS = -lbsm -.ifdef PCRE -CFLAGS += -I /usr/local/include -CFLAGS += -L /usr/local/lib -CFLAGS += -D PCRE -LIBS += -lpcre -.endif +#.ifdef PCRE +#CFLAGS += -I /usr/local/include +#CFLAGS += -L /usr/local/lib +#CFLAGS += -D PCRE +#LIBS += -lpcre +#.endif all: $(TARGETS) ==== //depot/projects/trustedbsd/bsmtrace/README#2 (text+ko) ==== ==== //depot/projects/trustedbsd/bsmtrace/bsm.c#2 (text+ko) ==== @@ -3,7 +3,7 @@ * Copyright (c) 2007 Christian S.J. Peron * All rights reserved. * - * $Id: bsm.c,v 1.44 2007/04/15 01:23:49 csjp Exp $ + * $Id: bsm.c,v 1.45 2007/10/09 02:24:30 csjp Exp $ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -122,8 +122,7 @@ * on the object we are interested in, but a write on some anonymous * object has occured, should we still raise an alert? */ - if (bd->br_path == NULL) - return (0); + /* * Check to see if the user has supplied any objects. If not, then this * is a member match. @@ -132,6 +131,12 @@ if (ap->a_cnt == 0) return (1); /* + * We are interested in particular objects, but the audit record has + * not supplied any. We will treat this as a fail to match. + */ + if (bd->br_path == NULL) + return (0); + /* * Otherwise, the record contains a pathname which may be represented as * a static string, or as a pcre. */ @@ -185,7 +190,7 @@ * sequence, use stderr. This really needs to be fixed to look at what * if anything is specified in the global logging options. */ - if (TAILQ_EMPTY(&bs->bs_log_channel)) { + if (TAILQ_EMPTY(&bs->bs_log_channel) && opts.Fflag != 0) { log_bsm_stderr(NULL, bs, bd); return; } @@ -361,12 +366,38 @@ #endif } +/* + * Implement a function which produces random values with an interesting + * property. This function will produce a random value, where the probability + * of this value being between 0 and size is specified by prob. + * + * Let v be > 0 and < 1 (random value) + * Let P (probability) be > 0 and < 1 + * + * Rv = v * (range / P); + * + */ +static float +bsm_rand_bias(float size, float prob) +{ + unsigned int val; + float r; + + val = arc4random(); + r = (float)val; + while (r > 1) + r = r / 10; + return (r * (size / prob)); +} + static struct bsm_sequence * bsm_sequence_clone(struct bsm_sequence *bs, u_int subj, struct bsm_record_data *bd) { struct bsm_sequence *bs_new; struct bsm_state *bm; + float size, prob; + int rnd; bs_new = bsm_dyn_sequence_find(bs, bd, subj); if (bs_new != NULL) { @@ -403,6 +434,18 @@ bm->bm_raw = bsm_copy_record_data(bd); bm->bm_raw_len = bd->br_raw_len; bs_new->bs_cur_state = TAILQ_NEXT(bm, bm_glue); + /* + * Handle the randomization of the timeout window here. + */ + if (bs_new->bs_seq_time_wnd != 0) { + size = bs_new->bs_seq_time_wnd; + if (bs_new->bs_seq_time_wnd_prob > 0) + prob = (float)bs_new->bs_seq_time_wnd_prob / 100; + else + prob = (float)(65 / 100); + rnd = bsm_rand_bias(size, prob); + bs_new->bs_timeout = bs_new->bs_timeout + rnd; + } return (bs_new); } @@ -490,7 +533,7 @@ bsm_loop(char *atrail) { struct bsm_record_data bd; - int reclen, bytesread; + int reclen, bytesread, recsread; u_char *bsm_rec; tokenstr_t tok; FILE *fp; @@ -501,10 +544,22 @@ fp = fopen(opts.aflag, "r"); if (fp == NULL) bsmtrace_error(1, "%s: %s", opts.aflag, strerror(errno)); + if (strcmp(opts.aflag, DEFAULT_AUDIT_TRAIL) == 0) + audit_pipe_fd = fileno(fp); + dprintf("opened '%s' for audit monitoring\n", opts.aflag); /* * Process the BSM record, one token at a time. */ + recsread = 0; while ((reclen = au_read_rec(fp, &bsm_rec)) != -1) { + /* + * If we are reading data from the audit pipe, we need check + * how many records, if any have been dropped by the kernel. + * If any record loss has been identified, pipe_analyze_loss() + * should increase the internal audit pipe queue length. + */ + if (audit_pipe_fd > 0 && (recsread % 50) == 0) + pipe_analyze_loss(audit_pipe_fd); bzero(&bd, sizeof(bd)); bd.br_raw = bsm_rec; bd.br_raw_len = reclen; @@ -581,6 +636,7 @@ } bsm_sequence_scan(&bd); free(bsm_rec); + recsread++; } - fclose(fp); + (void) fclose(fp); } ==== //depot/projects/trustedbsd/bsmtrace/bsmtrace.c#2 (text+ko) ==== @@ -3,7 +3,7 @@ * Copyright (c) 2007 Christian S.J. Peron * All rights reserved. * - * $Id: bsmtrace.c,v 1.18 2007/04/13 14:45:12 csjp Exp $ + * $Id: bsmtrace.c,v 1.19 2007/10/09 02:22:15 csjp Exp $ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -48,7 +48,7 @@ (void) sprintf(pidbuf, "%d", getpid()); if (write(fd, pidbuf, strlen(pidbuf)) < 0) bsmtrace_error(1, "write pid file faled"); - close(fd); + (void) close(fd); } /* @@ -68,7 +68,7 @@ else pri = LOG_WARNING; va_start(ap, fmt); - vsnprintf(fmtbuf, sizeof(fmtbuf), fmt, ap); + (void) vsnprintf(fmtbuf, sizeof(fmtbuf), fmt, ap); va_end(ap); syslog(pri, "%s: %s", flag != 0 ? "fatal" : "warning", fmtbuf); /* if we are not yet a daemon, we also write the error message @@ -87,6 +87,7 @@ void bsmtrace_exit(int x) { + exit(x); } @@ -99,10 +100,22 @@ if (!opts.dflag) return; va_start(ap, fmt); - memset(buf, 0, sizeof(buf)); - vsnprintf(buf, sizeof(buf) - 1, fmt, ap); + (void) memset(buf, 0, sizeof(buf)); + (void) vsnprintf(buf, sizeof(buf) - 1, fmt, ap); va_end(ap); - fprintf(stderr, "debug: %s", buf); + (void) fprintf(stderr, "debug: %s", buf); + (void) fflush(stderr); +} + +void +bsmtrace_handle_sigint(int sig) +{ + + if (audit_pipe_fd != 0) { + (void) fputs("\n", stderr); + pipe_report_stats(audit_pipe_fd); + } + bsmtrace_exit(1); } void @@ -115,13 +128,30 @@ openlog("bsmtrace", LOG_NDELAY | LOG_PID, LOG_AUTH | LOG_ALERT); } +static void +bsmtrace_seed(void) +{ + unsigned long seed; + int fd; + + fd = open("/dev/random", O_RDONLY); + if (fd < 0) + bsmtrace_error(1, "open random device failed"); + if (read(fd, &seed, sizeof(seed)) != sizeof(seed)) + bsmtrace_error(1, "read random device failed"); + srandom(seed); + (void) close(fd); +} + int main(int argc, char *argv[]) { int ret, fd; char ch; - signal(SIGCHLD, SIG_IGN); /* Ignore dying children */ + bsmtrace_seed(); + (void) signal(SIGCHLD, SIG_IGN); /* Ignore dying children */ + (void) signal(SIGINT, bsmtrace_handle_sigint); set_default_settings(&opts); while ((ch = getopt(argc, argv, "Fa:bdf:hp:v")) != -1) { switch (ch) { @@ -172,7 +202,9 @@ (void) dup2(fd, STDERR_FILENO); if (fd > 2) (void) close(fd); - setsid(); + if (setsid() < 0) + bsmtrace_error(1, "setsid failed: %s", + strerror(errno)); bsmtrace_write_pidfile(opts.pflag); daemonized = 1; } ==== //depot/projects/trustedbsd/bsmtrace/bsmtrace.conf#2 (text+ko) ==== @@ -67,9 +67,13 @@ # ############################################################ +# +# +# XXX add a sequence which detects system accounts executing code +# +# sequence firewall.change.attempt { subject not $fwadmins; - log { $bsm; }; state { event $execution; object $fwtools; @@ -79,7 +83,6 @@ sequence non.trusted.exec { subject any; - log { $bsm; }; state { event $execution; object not $trusteddirs; @@ -90,7 +93,6 @@ sequence mktemp.race { subject any; - log { $bsm; }; state { event { AUE_SYMLINK; }; object $opendirs; @@ -104,7 +106,7 @@ state { event $login; status failure; - multiplier 5; + multiplier 2; }; state { event $login; @@ -114,7 +116,6 @@ sequence httpd.exec { subject { nobody; }; - log { $bsm; }; state { event { AUE_SOCKET; }; status success; @@ -131,7 +132,7 @@ sequence named.exec { subject { bind; }; - log { $bsm; }; + scope process; state { event { AUE_SOCKET; }; status success; @@ -146,24 +147,47 @@ }; }; +sequence failed.file.write { + subject { csjp; }; + state { + event { fw; }; + status failure; + }; +}; + # -# Test for PCRE's +# This is a comment # -#sequence passwd.access { -# subject any; -# log { $bsm; }; -# state { -# event { fr; }; -# status any; -# object { ^/etc/pass[Ww][Dd]; }; -# }; -#}; -#sequence etc.access { -# subject any; -# log { $bsm; }; -# state { -# event { fr; }; -# status any; -# object { ^/[Ee][Tt][Cc]/*; }; -# }; -#}; +sequence five.config.file.read { + subject { csjp; }; + serial 2343445445; + timeout 60 seconds; + scope global; + priority 100; + state { + event { fr; }; + status any; + object { /etc; }; + trigger "/usr/bin/logger config file read"; + multiplier 5; + }; +}; + +sequence passwd.access { + subject any; + state { + event { fr; }; + status any; + object { /etc/pass[Ww][Dd]; }; + multiplier 5; + }; +}; + +sequence etc.access { + subject any; + state { + event { fr; }; + status any; + object { /[Ee][Tt][Cc]/*; }; + }; +}; ==== //depot/projects/trustedbsd/bsmtrace/bsmtrace.conf.5#2 (text+ko) ==== @@ -90,6 +90,8 @@ ::= "sequence" "{" "subject" ["not"] ( | ( | "any")) ";" ["timeout" ";"] + ["timeout-window" ";"] + ["timeout-probability" ";"] ["priority" ";"] ["log" ( | ) ";"] ["serial" ";"] ==== //depot/projects/trustedbsd/bsmtrace/bsmtrace.ebnf#2 (text+ko) ==== @@ -55,6 +55,8 @@ ::= "sequence" "{" "subject" ["not"] ( | ( | "any")) ";" ["timeout" ";"] + ["timeout-window" ";"] + ["timeout-probability" ";"] ["priority" ";"] ["log" ( | ) ";"] ["serial" ";"] ==== //depot/projects/trustedbsd/bsmtrace/bsmtrace.h#2 (text+ko) ==== @@ -28,7 +28,7 @@ #ifndef BSM_TRACE_H_ #define BSM_TRACE_H_ -#define BSMTRACE_VERSION "BSMTRACE 1.0.0-BETA" +#define BSMTRACE_VERSION "BSMTRACE 1.2.0-HEAD" struct g_conf { char *aflag; int bflag; @@ -39,6 +39,7 @@ }; struct g_conf opts; +int audit_pipe_fd; /* XXX not happy about this global */ void bsmtrace_error(int, char *, ...); void bsmtrace_exit(int); ==== //depot/projects/trustedbsd/bsmtrace/conf.c#2 (text+ko) ==== @@ -97,7 +97,7 @@ yyin = f; TAILQ_INIT(&bsm_set_head); yyparse(); - fclose(f); + (void) fclose(f); } /* ==== //depot/projects/trustedbsd/bsmtrace/deuce.h#2 (text+ko) ==== @@ -131,6 +131,8 @@ int bs_seq_scope; pid_t bs_seq_scope_data; int bs_seq_serial; + int bs_seq_time_wnd; + int bs_seq_time_wnd_prob; }; struct bsm_record_data { ==== //depot/projects/trustedbsd/bsmtrace/grammar.y#2 (text+ko) ==== @@ -51,9 +51,10 @@ %token STATUS MULTIPLIER OBRACE EBRACE SEMICOLON COMMA SUBJECT %token STRING ANY SUCCESS FAILURE INTEGER TIMEOUT NOT HOURS MINUTES DAYS %token PRIORITY WEEKS SECONDS NONE QUOTE OPBRACKET EPBRACKET LOGCHAN -%token DIRECTORY LOG SCOPE SERIAL +%token DIRECTORY LOG SCOPE SERIAL TIMEOUTWND TIMEOUTPROB %type status_spec SUCCESS FAILURE INTEGER multiplier_spec timeout_spec -%type serial_spec negate_spec priority_spec scope_spec +%type serial_spec negate_spec priority_spec scope_spec timeout_wnd_spec +%type timeout_prob_spec time_spec %type STRING %type set_list set_list_ent %type anon_set @@ -207,33 +208,54 @@ } ; -timeout_spec: - TIMEOUT INTEGER SECONDS SEMICOLON +timeout_prob_spec: + TIMEOUTPROB INTEGER SEMICOLON + { + $$ = $2; + } + ; + +timeout_wnd_spec: + TIMEOUTWND time_spec SEMICOLON { $$ = $2; } - | TIMEOUT INTEGER HOURS SEMICOLON + ; + +time_spec: + INTEGER SECONDS + { + $$ = $1; + } + | INTEGER HOURS { - $$ = $2 * 3600; + $$ = $1 * 3600; } - | TIMEOUT INTEGER MINUTES SEMICOLON + | INTEGER MINUTES { - $$ = $2 * 60; + $$ = $1 * 60; } - | TIMEOUT INTEGER DAYS SEMICOLON + | INTEGER DAYS { - $$ = $2 * 3600 * 24; + $$ = $1 * 3600 * 24; } - | TIMEOUT INTEGER WEEKS SEMICOLON + | INTEGER WEEKS { - $$ = $2 * 3600 * 24 * 7; + $$ = $1 * 3600 * 24 * 7; } - | TIMEOUT NONE SEMICOLON + | NONE { $$ = 0; } ; +timeout_spec: + TIMEOUT time_spec SEMICOLON + { + $$ = $2; + } + ; + sequence_def: SEQUENCE { @@ -337,8 +359,19 @@ } | sequence_options serial_spec { + assert(bs_state != NULL); bs_state->bs_seq_serial = $2; } + | sequence_options timeout_wnd_spec + { + assert(bs_state != NULL); + bs_state->bs_seq_time_wnd = $2; + } + | sequence_options timeout_prob_spec + { + assert(bs_state != NULL); + bs_state->bs_seq_time_wnd_prob = $2; + } ; type_spec: ==== //depot/projects/trustedbsd/bsmtrace/includes.h#2 (text+ko) ==== @@ -3,7 +3,7 @@ * Copyright (c) 2007 Christian S.J. Peron * All rights reserved. * - * $Id: includes.h,v 1.4 2007/04/13 14:45:12 csjp Exp $ + * $Id: includes.h,v 1.5 2007/07/13 00:03:50 csjp Exp $ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,6 +33,11 @@ #endif #include #include +#include +#include +#include +#include +#include #include #include @@ -50,7 +55,9 @@ #include #include +#ifndef __APPLE__ #include +#endif #ifdef PCRE #include #endif @@ -64,4 +71,5 @@ #include "conf.h" #include "bsm.h" #include "log.h" +#include "pipe.h" #include "trigger.h" ==== //depot/projects/trustedbsd/bsmtrace/log.c#2 (text+ko) ==== @@ -104,18 +104,18 @@ struct bsm_state *bm; (void) snprintf(dir, MAXPATHLEN, - "%s/%s", lc->log_data.bsm_log_dir, - bs->bs_label); + "%s/%s", lc->log_data.bsm_log_dir, bs->bs_label); error = stat(dir, &sb); if (error < 0 && errno == ENOENT) { if (mkdir(dir, S_IRWXU) < 0) bsmtrace_error(1, "mkdir failed"); } else if (error < 0) bsmtrace_error(1, "stat failed"); - (void) sprintf(path, "%s/%d.%d", dir, br->br_sec, br->br_usec); + (void) sprintf(path, "%s/%d.%d.%lu", + dir, br->br_sec, br->br_usec, random()); fd = open(path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); if (fd < 0) - bsmtrace_error(1, "open failed"); + bsmtrace_error(1, "open: %s: %s", path, strerror(errno)); /* * The logic here becomes a bit complex. We need to check to see if * this is a single state sequence, and if it is, log the BSM record @@ -126,13 +126,13 @@ if ((bs->bs_seq_flags & BSM_SEQUENCE_PARENT) != 0) { if (write(fd, br->br_raw, br->br_raw_len) < 0) bsmtrace_error(1, "write failed"); - close(fd); + (void) close(fd); return (0); } TAILQ_FOREACH(bm, &bs->bs_mhead, bm_glue) if (write(fd, bm->bm_raw, bm->bm_raw_len) < 0) bsmtrace_error(1, "write failed"); - close(fd); + (void) close(fd); return (0); } ==== //depot/projects/trustedbsd/bsmtrace/token.l#2 (text+ko) ==== @@ -64,6 +64,8 @@ subject return (SUBJECT); success return (SUCCESS); timeout return (TIMEOUT); +timeout-window return (TIMEOUTWND); +timeout-prob return (TIMEOUTPROB); trigger return (TRIGGER); weeks return (WEEKS); {integer} { ==== //depot/projects/trustedbsd/bsmtrace/trigger.c#2 (text+ko) ==== @@ -72,15 +72,15 @@ switch (expptr->val) { case EXP_USER: if ((pw = getpwuid(bd->br_auid)) == NULL) - strlcpy(token, "non-attributable", + (void) strlcpy(token, "non-attributable", sizeof(token)); else - strlcpy(token, pw->pw_name, + (void) strlcpy(token, pw->pw_name, sizeof(token)); break; case EXP_OBJECT: if (bd->br_path != NULL) - strlcpy(token, bd->br_path, + (void) strlcpy(token, bd->br_path, sizeof(token)); else { free(ret); @@ -90,7 +90,7 @@ default: assert(0); } - strlcat(ret, token, allocated); + (void) strlcat(ret, token, allocated); p1 = ret + strlen(ret); } else *(p1++) = *(p0++);