Skip to content

Commit

Permalink
prune command: extend ACL checking
Browse files Browse the repository at this point in the history
Only allow prune, when console has unrestricted ACLs
on Jobs and Storages.
It is possible to make them finer,
by checking the resources of the result set.
However, currently this is not seen necessary.
Other ACLs are checked at the subcommands.
  • Loading branch information
joergsteffens committed Nov 17, 2016
1 parent 5c198a6 commit 40e4255
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 16 deletions.
8 changes: 6 additions & 2 deletions src/dird/ua_cmds.c
Expand Up @@ -320,11 +320,15 @@ static struct ua_cmdstruct commands[] = {
{ NT_("move"), move_cmd, _("Move slots in an autochanger"),
NT_("storage=<storage-name> srcslots=<slot-selection> dstslots=<slot-selection>"), true, true },
{ NT_("prune"), prune_cmd, _("Prune records from catalog"),
NT_("files | jobs | jobtype=<jobtype> | pool=<pool-name> | client=<client-name> | volume=<volume-name> | directory=<directory> | recursive"), true, true },
NT_("files [client=<client>] [pool=<pool>] [yes] |\n"
"jobs [client=<client>] [pool=<pool>] [jobtype=<jobtype>] [yes] |\n"
"volume [=volume] [pool=<pool>] [yes] |\n"
"stats [yes] |\n"
"directory [=directory] [client=<client>] [recursive] [yes]"), true, true },
{ NT_("purge"), purge_cmd, _("Purge records from catalog"),
NT_("[files [job=<job> | jobid=<jobid> | client=<client> | volume=<volume>]] |\n"
"[jobs [client=<client> | volume=<volume>]] |\n"
"[volume [=<volume>] [storage=<storage>] [pool=<pool> | allpools] [devicetype=<type>] [drive=<drivenum>] [action=<action>]] |\n"
"[volume[=<volume>] [storage=<storage>] [pool=<pool> | allpools] [devicetype=<type>] [drive=<drivenum>] [action=<action>]] |\n"
"[quota [client=<client>]]"), true, true },
{ NT_("quit"), quit_cmd, _("Terminate Bconsole session"),
NT_(""), false, false },
Expand Down
63 changes: 51 additions & 12 deletions src/dird/ua_prune.c
Expand Up @@ -3,7 +3,7 @@
Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
Copyright (C) 2011-2012 Planets Communications B.V.
Copyright (C) 2013-2013 Bareos GmbH & Co. KG
Copyright (C) 2013-2016 Bareos GmbH & Co. KG
This program is Free Software; you can redistribute it and/or
modify it under the terms of version three of the GNU Affero General Public
Expand Down Expand Up @@ -90,12 +90,6 @@ int file_delete_handler(void *ctx, int num_fields, char **row)

/*
* Prune records from database
*
* prune files client=xxx [pool=yyy]
* prune jobs client=xxx [pool=yyy]
* prune volume=xxx
* prune stats
* prune directory=xxx [client=xxx] [recursive]
*/
bool prune_cmd(UAContext *ua, const char *cmd)
{
Expand All @@ -105,6 +99,7 @@ bool prune_cmd(UAContext *ua, const char *cmd)
MEDIA_DBR mr;
utime_t retention;
int kw;
const char *permission_denied_message = _("Permission denied: need full %s permission.\n");
static const char *keywords[] = {
NT_("Files"),
NT_("Jobs"),
Expand All @@ -114,6 +109,21 @@ bool prune_cmd(UAContext *ua, const char *cmd)
NULL
};

/*
* All prune commands might target jobs that reside on different storages.
* Instead of checking all of them,
* we require full permission on jobs and storages.
* Client and Pool permissions are checked at the individual subcommands.
*/
if (ua->acl_has_restrictions(Job_ACL)) {
ua->error_msg(permission_denied_message, "job");
return false;
}
if (ua->acl_has_restrictions(Storage_ACL)) {
ua->error_msg(permission_denied_message, "storage");
return false;
}

if (!open_client_db(ua, true)) {
return false;
}
Expand All @@ -134,11 +144,12 @@ bool prune_cmd(UAContext *ua, const char *cmd)

switch (kw) {
case 0: /* prune files */

if (!(client = get_client_resource(ua))) {
return false;
}

if (find_arg_with_value(ua, NT_("pool")) >= 0) {
if ((find_arg_with_value(ua, NT_("pool")) >= 0) || ua->acl_has_restrictions(Pool_ACL)) {
pool = get_pool_resource(ua);
} else {
pool = NULL;
Expand All @@ -165,7 +176,7 @@ bool prune_cmd(UAContext *ua, const char *cmd)
return false;
}

if (find_arg_with_value(ua, NT_("pool")) >= 0) {
if ((find_arg_with_value(ua, NT_("pool")) >= 0) || ua->acl_has_restrictions(Pool_ACL)) {
pool = get_pool_resource(ua);
} else {
pool = NULL;
Expand All @@ -174,8 +185,15 @@ bool prune_cmd(UAContext *ua, const char *cmd)
/*
* Ask what jobtype to prune.
*/
if (!get_user_job_type_selection(ua, &jobtype) || jobtype == -1) {
return (jobtype == -1) ? true : false;
if (!get_user_job_type_selection(ua, &jobtype)) {
return false;
}

/*
* Verify that result jobtype is valid (this should always be the case).
*/
if (jobtype < 0) {
return false;
}

/*
Expand All @@ -192,6 +210,12 @@ bool prune_cmd(UAContext *ua, const char *cmd)
return prune_jobs(ua, client, pool, jobtype);
}
case 2: /* prune volume */

if (ua->acl_has_restrictions(Client_ACL)) {
ua->error_msg(permission_denied_message, "client");
return false;
}

if (!select_pool_and_media_dbr(ua, &pr, &mr)) {
return false;
}
Expand All @@ -213,13 +237,28 @@ bool prune_cmd(UAContext *ua, const char *cmd)

retention = me->stats_retention;

if (ua->acl_has_restrictions(Client_ACL)) {
ua->error_msg(permission_denied_message, "client");
return false;
}
if (ua->acl_has_restrictions(Pool_ACL)) {
ua->error_msg(permission_denied_message, "pool");
return false;
}

if (!confirm_retention(ua, &retention, "Statistics")) {
return false;
}

return prune_stats(ua, retention);
case 4: /* prune directory */
if (find_arg_with_value(ua, NT_("client")) >= 0) {

if (ua->acl_has_restrictions(Pool_ACL)) {
ua->error_msg(permission_denied_message, "pool");
return false;
}

if ((find_arg_with_value(ua, NT_("client")) >= 0) || ua->acl_has_restrictions(Client_ACL)) {
if (!(client = get_client_resource(ua))) {
return false;
}
Expand Down
6 changes: 4 additions & 2 deletions src/dird/ua_select.c
Expand Up @@ -1827,6 +1827,9 @@ bool get_user_job_type_selection(UAContext *ua, int *jobtype)
int i;
char job_type[MAX_NAME_LENGTH];

/* set returning jobtype to invalid */
*jobtype = -1;

if ((i = find_arg_with_value(ua, NT_("jobtype"))) >= 0) {
bstrncpy(job_type, ua->argv[i], sizeof(job_type));
} else {
Expand All @@ -1836,8 +1839,7 @@ bool get_user_job_type_selection(UAContext *ua, int *jobtype)
}

if (do_prompt(ua, _("JobType"), _("Select Job Type"), job_type, sizeof(job_type)) < 0) {
*jobtype = -1;
return true;
return false;
}
}

Expand Down

0 comments on commit 40e4255

Please sign in to comment.