Skip to content

Commit

Permalink
Some preliminary work for allowing to have audit events.
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco van Wieringen committed Feb 17, 2015
1 parent 1c7dfd9 commit 3e1bbfe
Show file tree
Hide file tree
Showing 19 changed files with 594 additions and 317 deletions.
14 changes: 7 additions & 7 deletions src/dird/Makefile.in
Expand Up @@ -32,17 +32,17 @@ SVRSRCS = admin.c authenticate.c autoprune.c backup.c bsr.c catreq.c \
dir_plugins.c dird_conf.c dird.c expand.c fd_cmds.c getmsg.c \
inc_conf.c job.c jobq.c migrate.c mountreq.c msgchan.c \
ndmp_dma.c newvol.c next_vol.c quota.c recycle.c restore.c \
run_conf.c sd_cmds.c scheduler.c stats.c ua_acl.c ua_cmds.c \
ua_dotcmds.c ua_input.c ua_impexp.c ua_label.c ua_output.c \
ua_prune.c ua_purge.c ua_query.c ua_restore.c ua_run.c \
ua_select.c ua_server.c ua_status.c ua_tree.c ua_update.c \
vbackup.c verify.c
run_conf.c sd_cmds.c scheduler.c stats.c ua_acl.c ua_audit.c \
ua_cmds.c ua_dotcmds.c ua_input.c ua_impexp.c ua_label.c \
ua_output.c ua_prune.c ua_purge.c ua_query.c ua_restore.c \
ua_run.c ua_select.c ua_server.c ua_status.c ua_tree.c \
ua_update.c vbackup.c verify.c
SVROBJS = $(SVRSRCS:.c=.o)

DBCHKSRCS = dbcheck.c dird_conf.c ua_acl.c run_conf.c inc_conf.c
DBCHKSRCS = dbcheck.c dird_conf.c ua_acl.c ua_audit.c run_conf.c inc_conf.c
DBCHKOBJS = $(DBCHKSRCS:.c=.o)

TSTFNDSRCS = testfind.c dird_conf.c ua_acl.c run_conf.c inc_conf.c
TSTFNDSRCS = testfind.c dird_conf.c ua_acl.c ua_audit.c run_conf.c inc_conf.c
TSTFNDOBJS = $(TSTFNDSRCS:.c=.o)

INCLUDES += -I$(srcdir) -I$(basedir) -I$(basedir)/include
Expand Down
16 changes: 8 additions & 8 deletions src/dird/bareos-dir.conf.in
Expand Up @@ -251,11 +251,11 @@ Messages {
Name = Standard
mailcommand = "@sbindir@/bsmtp -h @smtp_host@ -f \"\(Bareos\) \<%r\>\" -s \"Bareos: %t %e of %c %l\" %r"
operatorcommand = "@sbindir@/bsmtp -h @smtp_host@ -f \"\(Bareos\) \<%r\>\" -s \"Bareos: Intervention needed for %j\" %r"
mail = @job_email@ = all, !skipped # (#02)
mail = @job_email@ = all, !skipped, !audit # (#02)
operator = @job_email@ = mount # (#03)
console = all, !skipped, !saved
append = "@logdir@/bareos.log" = all, !skipped
catalog = all
console = all, !skipped, !saved, !audit
append = "@logdir@/bareos.log" = all, !skipped, !audit
catalog = all, !audit
}

#
Expand All @@ -264,12 +264,12 @@ Messages {
Messages {
Name = Daemon
mailcommand = "@sbindir@/bsmtp -h @smtp_host@ -f \"\(Bareos\) \<%r\>\" -s \"Bareos daemon message\" %r"
mail = @job_email@ = all, !skipped # (#02)
console = all, !skipped, !saved
append = "@logdir@/bareos.log" = all, !skipped
mail = @job_email@ = all, !skipped, !audit # (#02)
console = all, !skipped, !saved, !audit
append = "@logdir@/bareos.log" = all, !skipped, !audit
append = "@logdir@/bareos-audit.log" = audit
}


#
# Full Pool definition
#
Expand Down
68 changes: 55 additions & 13 deletions src/dird/dird_conf.c
Expand Up @@ -130,6 +130,8 @@ static RES_ITEM dir_items[] = {
{ "ndmpsnooping", CFG_TYPE_BOOL, ITEM(res_dir.ndmp_snooping), 0, 0, NULL },
{ "ndmploglevel", CFG_TYPE_PINT32, ITEM(res_dir.ndmp_loglevel), 0, CFG_ITEM_DEFAULT, "4" },
{ "absolutejobtimeout", CFG_TYPE_PINT32, ITEM(res_dir.jcr_watchdog_time), 0, 0, NULL },
{ "auditing", CFG_TYPE_BOOL, ITEM(res_dir.auditing), 0, CFG_ITEM_DEFAULT, "true" },
{ "auditevents", CFG_TYPE_AUDIT, ITEM(res_dir.audit_events), 0, 0, NULL },
{ NULL, 0, { 0 }, 0, 0, NULL }
};

Expand Down Expand Up @@ -676,9 +678,9 @@ static inline void print_config_runscript(RES_ITEM *item, POOL_MEM &cfg_str)
{
POOL_MEM temp;
RUNSCRIPT* runscript;
alist* list;
list = (alist *) *(item->value);
alist *list;

list = *item->alistvalue;
if (bstrcmp(item->name, "runscript")) {
if (list != NULL) {
foreach_alist(runscript, list) {
Expand Down Expand Up @@ -1654,6 +1656,9 @@ void free_resource(RES *sres, int type)
if (res->res_dir.keyencrkey) {
free(res->res_dir.keyencrkey);
}
if (res->res_dir.audit_events) {
delete res->res_dir.audit_events;
}
break;
case R_DEVICE:
case R_COUNTER:
Expand Down Expand Up @@ -2161,6 +2166,7 @@ bool populate_jobdefs()
JOBRES *jobdefs = job->jobdefs;
if (jobdefs->storage && !job->storage) {
STORERES *store;

job->storage = New(alist(10, not_owned_by_alist));
foreach_alist(store, jobdefs->storage) {
job->storage->append(store);
Expand Down Expand Up @@ -2675,15 +2681,20 @@ static void store_autopassword(LEX *lc, RES_ITEM *item, int index, int pass)
static void store_acl(LEX *lc, RES_ITEM *item, int index, int pass)
{
int token;
alist *list;

if (pass == 1) {
if (!item->alistvalue[item->code]) {
item->alistvalue[item->code] = New(alist(10, owned_by_alist));
Dmsg1(900, "Defined new ACL alist at %d\n", item->code);
}
}
list = item->alistvalue[item->code];

for (;;) {
lex_get_token(lc, T_STRING);
if (pass == 1) {
if (((alist **)item->value)[item->code] == NULL) {
((alist **)item->value)[item->code] = New(alist(10, owned_by_alist));
Dmsg1(900, "Defined new ACL alist at %d\n", item->code);
}
((alist **)item->value)[item->code]->append(bstrdup(lc->str));
list->append(bstrdup(lc->str));
Dmsg2(900, "Appended to %d %s\n", item->code, lc->str);
}
token = lex_get_token(lc, T_ALL);
Expand All @@ -2695,6 +2706,34 @@ static void store_acl(LEX *lc, RES_ITEM *item, int index, int pass)
set_bit(index, res_all.hdr.item_present);
}

/*
* Store Audit event.
*/
static void store_audit(LEX *lc, RES_ITEM *item, int index, int pass)
{
int token;
alist *list;

if (pass == 1) {
if (!*item->alistvalue) {
*(item->alistvalue) = New(alist(10, owned_by_alist));
}
}
list = *item->alistvalue;

for (;;) {
lex_get_token(lc, T_STRING);
if (pass == 1) {
list->append(bstrdup(lc->str));
}
token = lex_get_token(lc, T_ALL);
if (token == T_COMMA) {
continue;
}
break;
}
set_bit(index, res_all.hdr.item_present);
}
/*
* Store a runscript->when in a bit field
*/
Expand All @@ -2703,7 +2742,7 @@ static void store_runscript_when(LEX *lc, RES_ITEM *item, int index, int pass)
lex_get_token(lc, T_NAME);

if (bstrcasecmp(lc->str, "before")) {
*(item->ui32value) = SCRIPT_Before ;
*(item->ui32value) = SCRIPT_Before;
} else if (bstrcasecmp(lc->str, "after")) {
*(item->ui32value) = SCRIPT_After;
} else if (bstrcasecmp(lc->str, "aftervss")) {
Expand Down Expand Up @@ -2766,7 +2805,7 @@ static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass)
static void store_short_runscript(LEX *lc, RES_ITEM *item, int index, int pass)
{
lex_get_token(lc, T_STRING);
alist **runscripts = (alist **)(item->value) ;
alist **runscripts = item->alistvalue;

if (pass == 2) {
RUNSCRIPT *script = new_runscript();
Expand Down Expand Up @@ -2838,7 +2877,7 @@ static void store_runscript(LEX *lc, RES_ITEM *item, int index, int pass)
{
char *c;
int token, i, t;
alist **runscripts = (alist **)(item->value) ;
alist **runscripts = item->alistvalue;

Dmsg1(200, "store_runscript: begin store_runscript pass=%i\n", pass);

Expand Down Expand Up @@ -3058,6 +3097,9 @@ static void parse_config_cb(LEX *lc, RES_ITEM *item, int index, int pass)
case CFG_TYPE_ACL:
store_acl(lc, item, index, pass);
break;
case CFG_TYPE_AUDIT:
store_audit(lc, item, index, pass);
break;
case CFG_TYPE_AUTHPROTOCOLTYPE:
store_authprotocoltype(lc, item, index, pass);
break;
Expand Down Expand Up @@ -3120,7 +3162,7 @@ static void print_config_cb(RES_ITEM *items, int i, POOL_MEM &cfg_str)
alist* list;
POOL_MEM res_names;

list = (alist *) *(items[i].value);
list = *(items[i].alistvalue);
if (list != NULL) {
Mmsg(temp, "%s = ", items[i].name);
indent_config_item(cfg_str, 1, temp.c_str());
Expand Down Expand Up @@ -3153,10 +3195,10 @@ static void print_config_cb(RES_ITEM *items, int i, POOL_MEM &cfg_str)
case CFG_TYPE_ACL: {
int cnt = 0;
char *value;
alist* list;
alist *list;
POOL_MEM acl;

list = ((alist **)items[i].value)[items[i].code] ;
list = items[i].alistvalue[items[i].code];
if (list != NULL) {
Mmsg(temp, "%s = ", items[i].name);
indent_config_item(cfg_str, 1, temp.c_str());
Expand Down
37 changes: 20 additions & 17 deletions src/dird/dird_conf.h
Expand Up @@ -33,23 +33,24 @@
*/
enum {
CFG_TYPE_ACL = 50, /* User Access Control List */
CFG_TYPE_AUTHPROTOCOLTYPE = 51, /* Authentication Protocol */
CFG_TYPE_AUTHTYPE = 52, /* Authentication Type */
CFG_TYPE_DEVICE = 53, /* Device resource */
CFG_TYPE_JOBTYPE = 54, /* Type of Job */
CFG_TYPE_PROTOCOLTYPE = 55, /* Protocol */
CFG_TYPE_LEVEL = 56, /* Backup Level */
CFG_TYPE_REPLACE = 57, /* Replace option */
CFG_TYPE_SHRTRUNSCRIPT = 58, /* Short Runscript definition */
CFG_TYPE_RUNSCRIPT = 59, /* Runscript */
CFG_TYPE_RUNSCRIPT_CMD = 60, /* Runscript Command */
CFG_TYPE_RUNSCRIPT_TARGET = 61, /* Runscript Target (Host) */
CFG_TYPE_RUNSCRIPT_BOOL = 62, /* Runscript Boolean */
CFG_TYPE_RUNSCRIPT_WHEN = 63, /* Runscript When expression */
CFG_TYPE_MIGTYPE = 64, /* Migration Type */
CFG_TYPE_INCEXC = 65, /* Include/Exclude item */
CFG_TYPE_RUN = 66, /* Schedule Run Command */
CFG_TYPE_ACTIONONPURGE = 67, /* Action to perform on Purge */
CFG_TYPE_AUDIT = 51, /* Auditing Command List */
CFG_TYPE_AUTHPROTOCOLTYPE = 52, /* Authentication Protocol */
CFG_TYPE_AUTHTYPE = 53, /* Authentication Type */
CFG_TYPE_DEVICE = 54, /* Device resource */
CFG_TYPE_JOBTYPE = 55, /* Type of Job */
CFG_TYPE_PROTOCOLTYPE = 56, /* Protocol */
CFG_TYPE_LEVEL = 57, /* Backup Level */
CFG_TYPE_REPLACE = 58, /* Replace option */
CFG_TYPE_SHRTRUNSCRIPT = 59, /* Short Runscript definition */
CFG_TYPE_RUNSCRIPT = 60, /* Runscript */
CFG_TYPE_RUNSCRIPT_CMD = 61, /* Runscript Command */
CFG_TYPE_RUNSCRIPT_TARGET = 62, /* Runscript Target (Host) */
CFG_TYPE_RUNSCRIPT_BOOL = 63, /* Runscript Boolean */
CFG_TYPE_RUNSCRIPT_WHEN = 64, /* Runscript When expression */
CFG_TYPE_MIGTYPE = 65, /* Migration Type */
CFG_TYPE_INCEXC = 66, /* Include/Exclude item */
CFG_TYPE_RUN = 67, /* Schedule Run Command */
CFG_TYPE_ACTIONONPURGE = 68, /* Action to perform on Purge */

CFG_TYPE_FNAME = 80, /* Filename */
CFG_TYPE_PLUGINNAME = 81, /* Pluginname */
Expand Down Expand Up @@ -166,6 +167,8 @@ class DIRRES: public BRSRES {
bool nokeepalive; /* Don't use SO_KEEPALIVE on sockets */
bool omit_defaults; /* Omit config variables with default values when dumping the config */
bool ndmp_snooping; /* NDMP Protocol specific snooping enabled */
bool auditing; /* Auditing enabled */
alist *audit_events; /* Specific audit events to enable */
uint32_t ndmp_loglevel; /* NDMP Protocol specific loglevel to use */
uint32_t subscriptions; /* Number of subscribtions available */
uint32_t subscriptions_used; /* Number of subscribtions used */
Expand Down
10 changes: 8 additions & 2 deletions src/dird/protos.h
Expand Up @@ -235,8 +235,14 @@ void stop_statistics_thread();
void stats_job_started();

/* ua_acl.c */
bool acl_access_ok(UAContext *ua, int acl, const char *item);
bool acl_access_ok(UAContext *ua, int acl, const char *item, int len);
bool acl_access_ok(UAContext *ua, int acl, const char *item, bool audit_event = false);
bool acl_access_ok(UAContext *ua, int acl, const char *item, int len, bool audit_event = false);

/* ua_audit.c */
bool audit_event_wanted(UAContext *ua, bool audit_event_enabled);
void log_audit_event_acl_failure(UAContext *ua, int acl, const char *item);
void log_audit_event_acl_success(UAContext *ua, int acl, const char *item);
void log_audit_event_cmdline(UAContext *ua);

/* ua_cmds.c */
bool do_a_command(UAContext *ua);
Expand Down
70 changes: 51 additions & 19 deletions src/dird/ua_acl.c
Expand Up @@ -30,46 +30,78 @@
/*
* Check if access is permitted to item in acl
*/
bool acl_access_ok(UAContext *ua, int acl, const char *item)
bool acl_access_ok(UAContext *ua, int acl, const char *item, bool audit_event)
{
return acl_access_ok(ua, acl, item, strlen(item));
return acl_access_ok(ua, acl, item, strlen(item), audit_event);
}


/* This version expects the length of the item which we must check. */
bool acl_access_ok(UAContext *ua, int acl, const char *item, int len)
/*
* This version expects the length of the item which we must check.
*/
bool acl_access_ok(UAContext *ua, int acl, const char *item, int len, bool audit_event)
{
/* The resource name contains nasty characters */
if (acl != Where_ACL && acl != PluginOptions_ACL && !is_name_valid(item, NULL)) {
Dmsg1(1400, "Access denied for item=%s\n", item);
return false;
bool retval = false;
alist *list;

/*
* The resource name contains nasty characters
*/
switch (acl) {
case Where_ACL:
case PluginOptions_ACL:
break;
default:
if (!is_name_valid(item, NULL)) {
Dmsg1(1400, "Access denied for item=%s\n", item);
goto bail_out;
}
break;
}

/* If no console resource => default console and all is permitted */
/*
* If no console resource => default console and all is permitted
*/
if (!ua->cons) {
Dmsg0(1400, "Root cons access OK.\n");
return true; /* No cons resource -> root console OK for everything */
retval = true; /* No cons resource -> root console OK for everything */
goto bail_out;
}

alist *list = ua->cons->ACL_lists[acl];
if (!list) { /* empty list */
list = ua->cons->ACL_lists[acl];
if (!list) { /* Empty list */
/*
* Empty list for Where => empty where accept anything.
* For any other list, reject everything.
*/
if (len == 0 && acl == Where_ACL) {
return true; /* Empty list for Where => empty where */
retval = true;
}
return false; /* List empty, reject everything */
goto bail_out;
}

/* Special case *all* gives full access */
/*
* Special case *all* gives full access
*/
if (list->size() == 1 && bstrcasecmp("*all*", (char *)list->get(0))) {
return true;
goto bail_out;
}

/* Search list for item */
/*
* Search list for item
*/
for (int i=0; i<list->size(); i++) {
if (bstrcasecmp(item, (char *)list->get(i))) {
Dmsg3(1400, "ACL found %s in %d %s\n", item, acl, (char *)list->get(i));
return true;
retval = true;
goto bail_out;
}
}
return false;

bail_out:
if (audit_event && !retval) {
log_audit_event_acl_failure(ua, acl, item);
}

return retval;
}

0 comments on commit 3e1bbfe

Please sign in to comment.