- Document Pool keyword for restore.
For 1.33
+- Implement alist processing for ACLs from Console.
- Finish code passing files=nnn to restore start.
- Add Console usr permissions -- do by adding regex filters for
jobs, clients, storage, ...
/*
* Authenticate Director
*/
-int authenticate_director(JCR *jcr, DIRRES *director, char *name)
+int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons)
{
BSOCK *dir = jcr->dir_bsock;
int ssl_need = BNET_SSL_NONE;
char bashed_name[MAX_NAME_LENGTH];
+ char *password;
/*
* Send my name to the Director then do authentication
*/
- bstrncpy(bashed_name, name, sizeof(bashed_name));
- bash_spaces(bashed_name);
+ if (cons) {
+ bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name));
+ bash_spaces(bashed_name);
+ password = cons->password;
+ } else {
+ bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name));
+ password = director->password;
+ }
bnet_fsend(dir, hello, bashed_name);
- if (!cram_md5_get_auth(dir, director->password, ssl_need) ||
- !cram_md5_auth(dir, director->password, ssl_need)) {
+ if (!cram_md5_get_auth(dir, password, ssl_need) ||
+ !cram_md5_auth(dir, password, ssl_need)) {
sendit( _("Director authorization problem.\n"
"Most likely the passwords do not agree.\n"));
return 0;
#endif
/* Imported functions */
-int authenticate_director(JCR *jcr, DIRRES *director, char *name);
+int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons);
LockRes();
CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
UnlockRes();
- char *con_name;
- if (cons) {
- con_name = cons->hdr.name;
- } else {
- con_name = "*UserAgent*";
- }
- if (!authenticate_director(&jcr, dir, con_name)) {
+ if (!authenticate_director(&jcr, dir, cons)) {
fprintf(stderr, "ERR=%s", UA_sock->msg);
terminate_console(0);
return 1;
{"rcfile", store_dir, ITEM(res_cons.rc_file), 0, 0, 0},
{"historyfile", store_dir, ITEM(res_cons.hist_file), 0, 0, 0},
{"requiressl", store_yesno, ITEM(res_cons.require_ssl), 1, ITEM_DEFAULT, 0},
+ {"password", store_password, ITEM(res_cons.password), 0, ITEM_REQUIRED, 0},
{NULL, NULL, NULL, 0, 0, 0}
};
{"name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
{"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
{"dirport", store_int, ITEM(res_dir.DIRport), 0, ITEM_DEFAULT, 9101},
- {"address", store_str, ITEM(res_dir.address), 0, ITEM_REQUIRED, 0},
+ {"address", store_str, ITEM(res_dir.address), 0, 0, 0},
{"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
{"enablessl", store_yesno, ITEM(res_dir.enable_ssl), 1, ITEM_DEFAULT, 0},
{NULL, NULL, NULL, 0, 0, 0}
char *rc_file; /* startup file */
char *hist_file; /* command history file */
int require_ssl; /* Require SSL on all connections */
+ char *password; /* UA server password */
};
typedef struct s_res_con CONRES;
jobq.c mountreq.c msgchan.c next_vol.c newvol.c \
recycle.c restore.c run_conf.c \
scheduler.c sql_cmds.c \
- ua_cmds.c ua_dotcmds.c \
+ ua_acl.c ua_cmds.c ua_dotcmds.c \
ua_query.c \
ua_input.c ua_label.c ua_output.c ua_prune.c \
ua_purge.c ua_restore.c ua_run.c \
jobq.o mountreq.o msgchan.o next_vol.o newvol.o \
recycle.o restore.o run_conf.o \
scheduler.o sql_cmds.o \
- ua_cmds.o ua_dotcmds.o \
+ ua_acl.o ua_cmds.o ua_dotcmds.o \
ua_query.o \
ua_input.o ua_label.o ua_output.o ua_prune.o \
ua_purge.o ua_restore.o ua_run.o \
# and to the console
Messages {
Name = Standard
+#
+# NOTE! If you send to two email or more email addresses, you will need
+# to replace the %r in the from field (-f part) with a single valid
+# email address in both the mailcommand and the operatorcommand.
+#
mailcommand = "@sbindir@/bsmtp -h @smtp_host@ -f \"\(Bacula\) %r\" -s \"Bacula: %t %e of %c %l\" %r"
operatorcommand = "@sbindir@/bsmtp -h @smtp_host@ -f \"\(Bacula\) %r\" -s \"Bacula: Intervention needed for %j\" %r"
mail = @job_email@ = all, !skipped
void store_jobtype(LEX *lc, struct res_items *item, int index, int pass);
void store_level(LEX *lc, struct res_items *item, int index, int pass);
void store_replace(LEX *lc, struct res_items *item, int index, int pass);
+void store_acl(LEX *lc, struct res_items *item, int index, int pass);
/* We build the current resource here as we are
{"description", store_str, ITEM(res_con.hdr.desc), 0, 0, 0},
{"enablessl", store_yesno, ITEM(res_con.enable_ssl), 1, ITEM_DEFAULT, 0},
{"password", store_password, ITEM(res_con.password), 0, ITEM_REQUIRED, 0},
+ {"jobacl", store_acl, ITEM(res_con.ACL_lists), Job_ACL, 0, 0},
+ {"clientacl", store_acl, ITEM(res_con.ACL_lists), Client_ACL, 0, 0},
+ {"storageacl", store_acl, ITEM(res_con.ACL_lists), Storage_ACL, 0, 0},
+ {"scheduleacl", store_acl, ITEM(res_con.ACL_lists), Schedule_ACL, 0, 0},
+ {"runacl", store_acl, ITEM(res_con.ACL_lists), Run_ACL, 0, 0},
+ {"poolacl", store_acl, ITEM(res_con.ACL_lists), Pool_ACL, 0, 0},
+ {"commandacl", store_acl, ITEM(res_con.ACL_lists), Command_ACL, 0, 0},
+ {"filesetacl", store_acl, ITEM(res_con.ACL_lists), FileSet_ACL, 0, 0},
+ {"catalogacl", store_acl, ITEM(res_con.ACL_lists), Catalog_ACL, 0, 0},
{NULL, NULL, NULL, 0, 0, 0}
};
{NULL, NULL, NULL, 0, 0, 0}
};
-/* Group resource -- not implemented
- *
- * name handler value code flags default_value
- */
-static struct res_items group_items[] = {
- {"name", store_name, ITEM(res_group.hdr.name), 0, ITEM_REQUIRED, 0},
- {"description", store_str, ITEM(res_group.hdr.desc), 0, 0, 0},
- {NULL, NULL, NULL, 0, 0, 0}
-};
-
/* Pool resource
*
* name handler value code flags default_value
{"catalog", cat_items, R_CATALOG, NULL},
{"schedule", sch_items, R_SCHEDULE, NULL},
{"fileset", fs_items, R_FILESET, NULL},
- {"group", group_items, R_GROUP, NULL},
{"pool", pool_items, R_POOL, NULL},
{"messages", msgs_items, R_MSGS, NULL},
{"counter", counter_items, R_COUNTER, NULL},
static char level_no[30];
char *str = level_no;
- sprintf(level_no, "%d", level); /* default if not found */
+ bsnprintf(level_no, sizeof(level_no), "%d", level); /* default if not found */
for (i=0; joblevels[i].level_name; i++) {
if (level == joblevels[i].level) {
str = joblevels[i].level_name;
if (res->res_sch.run) {
int i;
RUN *run = res->res_sch.run;
- char buf[1000], num[10];
+ char buf[1000], num[30];
sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
if (!run) {
break;
bstrncpy(buf, " hour=", sizeof(buf));
for (i=0; i<24; i++) {
if (bit_is_set(i, run->hour)) {
- sprintf(num, "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
bstrncpy(buf, " mday=", sizeof(buf));
for (i=0; i<31; i++) {
if (bit_is_set(i, run->mday)) {
- sprintf(num, "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
bstrncpy(buf, " month=", sizeof(buf));
for (i=0; i<12; i++) {
if (bit_is_set(i, run->month)) {
- sprintf(num, "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
bstrncpy(buf, " wday=", sizeof(buf));
for (i=0; i<7; i++) {
if (bit_is_set(i, run->wday)) {
- sprintf(num, "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
bstrncpy(buf, " wom=", sizeof(buf));
for (i=0; i<5; i++) {
if (bit_is_set(i, run->wom)) {
- sprintf(num, "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
bstrncpy(buf, " woy=", sizeof(buf));
for (i=0; i<54; i++) {
if (bit_is_set(i, run->woy)) {
- sprintf(num, "%d ", i);
+ bsnprintf(num, sizeof(num), "%d ", i);
bstrncat(buf, num, sizeof(buf));
}
}
sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
}
break;
- case R_GROUP:
- sendit(sock, "Group: name=%s\n", res->res_group.hdr.name);
- break;
case R_POOL:
sendit(sock, "Pool: name=%s PoolType=%s\n", res->res_pool.hdr.name,
res->res_pool.pool_type);
if (res->res_con.password) {
free(res->res_con.password);
}
+ for (int i=0; i<Num_ACL; i++) {
+ if (res->res_con.ACL_lists[i]) {
+ delete res->res_con.ACL_lists[i];
+ res->res_con.ACL_lists[i] = NULL;
+ }
+ }
break;
case R_CLIENT:
if (res->res_client.address) {
free_msgs_res((MSGS *)res); /* free message resource */
res = NULL;
break;
- case R_GROUP:
- break;
default:
printf("Unknown resource type %d in free_resource.\n", type);
}
case R_CONSOLE:
case R_CATALOG:
case R_STORAGE:
- case R_GROUP:
case R_POOL:
case R_MSGS:
case R_FILESET:
case R_SCHEDULE:
size = sizeof(SCHED);
break;
- case R_GROUP:
- size = sizeof(GROUP);
- break;
case R_POOL:
size = sizeof(POOL);
break;
set_bit(index, res_all.hdr.item_present);
}
+/*
+ * Store ACL (access control list)
+ *
+ */
+void store_acl(LEX *lc, struct res_items *item, int index, int pass)
+{
+ int token;
+
+ for (;;) {
+ token = lex_get_token(lc, T_NAME);
+ if (pass == 1) {
+ if (((alist **)item->value)[item->code] == NULL) {
+ ((alist **)item->value)[item->code] = new alist(10, owned_by_alist);
+// Dmsg1(400, "Defined new ACL alist at %d\n", item->code);
+ }
+ ((alist **)item->value)[item->code]->append(bstrdup(lc->str));
+// Dmsg2(400, "Appended to %d %s\n", item->code, lc->str);
+ }
+ token = lex_get_token(lc, T_ALL);
+ if (token == T_COMMA) {
+ continue; /* get another ACL */
+ }
+ break;
+ }
+ set_bit(index, res_all.hdr.item_present);
+}
+
+
#ifdef old_deprecated_code
/*
* Store backup/verify info for Job record
/*
* Resource codes -- they must be sequential for indexing
*/
-#define R_FIRST 1001
-
-#define R_DIRECTOR 1001
-#define R_CLIENT 1002
-#define R_JOB 1003
-#define R_STORAGE 1004
-#define R_CATALOG 1005
-#define R_SCHEDULE 1006
-#define R_FILESET 1007
-#define R_GROUP 1008
-#define R_POOL 1009
-#define R_MSGS 1010
-#define R_COUNTER 1011
-#define R_CONSOLE 1012
-#define R_JOBDEFS 1013
-
-#define R_LAST R_JOBDEFS
+enum {
+ R_DIRECTOR = 1001,
+ R_CLIENT,
+ R_JOB,
+ R_STORAGE,
+ R_CATALOG,
+ R_SCHEDULE,
+ R_FILESET,
+ R_POOL,
+ R_MSGS,
+ R_COUNTER,
+ R_CONSOLE,
+ R_JOBDEFS
+};
+
+#define R_FIRST R_DIRECTOR
+#define R_LAST R_JOBDEFS
/*
* Some resource attributes
utime_t SDConnectTimeout; /* timeout in seconds */
};
+
+/*
+ * Console ACL positions
+ */
+enum {
+ Job_ACL = 0,
+ Client_ACL,
+ Storage_ACL,
+ Schedule_ACL,
+ Run_ACL,
+ Pool_ACL,
+ Command_ACL,
+ FileSet_ACL,
+ Catalog_ACL,
+ Num_ACL /* keep last */
+};
+
/*
* Console Resource
*/
RES hdr;
char *password; /* UA server password */
int enable_ssl; /* Use SSL */
+ alist *ACL_lists[Num_ACL]; /* pointers to ACLs */
};
RUN *run;
};
-/*
- * Group Resource (not used)
- *
- */
-struct GROUP {
- RES hdr;
-};
-
/*
* Counter Resource
*/
JOB res_job;
FILESET res_fs;
SCHED res_sch;
- GROUP res_group;
POOL res_pool;
MSGS res_msgs;
COUNTER res_counter;
/* fd_cmds.c */
extern int connect_to_file_daemon(JCR *jcr, int retry_interval,
- int max_retry_time, int verbose);
+ int max_retry_time, int verbose);
extern int send_include_list(JCR *jcr);
extern int send_exclude_list(JCR *jcr);
extern int send_bootstrap_file(JCR *jcr);
extern int get_attributes_and_put_in_catalog(JCR *jcr);
extern int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId);
extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname,
- char *link, char *attr, int stream);
+ char *link, char *attr, int stream);
extern void get_level_since_time(JCR *jcr, char *since, int since_len);
extern int send_run_before_and_after_commands(JCR *jcr);
/* msgchan.c */
extern int connect_to_storage_daemon(JCR *jcr, int retry_interval,
- int max_retry_time, int verbose);
+ int max_retry_time, int verbose);
extern int start_storage_daemon_job(JCR *jcr);
extern int start_storage_daemon_message_thread(JCR *jcr);
extern int bget_dirmsg(BSOCK *bs);
/* newvol.c */
int newVolume(JCR *jcr, MEDIA_DBR *mr);
+/* ua_acl.c */
+bool acl_access_ok(UAContext *ua, int acl, char *item);
+bool acl_access_ok(UAContext *ua, int acl, char *item, int len);
+
/* ua_cmds.c */
int do_a_command(UAContext *ua, char *cmd);
int do_a_dot_command(UAContext *ua, char *cmd);
void free_ua_context(UAContext *ua);
/* ua_select.c */
-STORE *select_storage_resource(UAContext *ua);
-JOB *select_job_resource(UAContext *ua);
-JOB *select_restore_job_resource(UAContext *ua);
-CLIENT *select_client_resource(UAContext *ua);
+STORE *select_storage_resource(UAContext *ua);
+JOB *select_job_resource(UAContext *ua);
+JOB *select_restore_job_resource(UAContext *ua);
+CLIENT *select_client_resource(UAContext *ua);
FILESET *select_fileset_resource(UAContext *ua);
-int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
-int select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
-int select_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
-
-void start_prompt(UAContext *ua, char *msg);
-void add_prompt(UAContext *ua, char *prompt);
-int do_prompt(UAContext *ua, char *automsg, char *msg, char *prompt, int max_prompt);
-CAT *get_catalog_resource(UAContext *ua);
+int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+int select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
+int select_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+
+void start_prompt(UAContext *ua, char *msg);
+void add_prompt(UAContext *ua, char *prompt);
+int do_prompt(UAContext *ua, char *automsg, char *msg, char *prompt, int max_prompt);
+CAT *get_catalog_resource(UAContext *ua);
STORE *get_storage_resource(UAContext *ua, int use_default);
-int get_media_type(UAContext *ua, char *MediaType, int max_media);
-int get_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+int get_media_type(UAContext *ua, char *MediaType, int max_media);
+int get_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
POOL *get_pool_resource(UAContext *ua);
POOL *select_pool_resource(UAContext *ua);
CLIENT *get_client_resource(UAContext *ua);
-int get_job_dbr(UAContext *ua, JOB_DBR *jr);
+int get_job_dbr(UAContext *ua, JOB_DBR *jr);
int find_arg_keyword(UAContext *ua, char **list);
int find_arg(UAContext *ua, char *keyword);
#ifndef __UA_H_
#define __UA_H_ 1
-
struct UAContext {
BSOCK *UA_sock;
BSOCK *sd;
UAContext *ua;
};
-
#endif
--- /dev/null
+/*
+ *
+ * Bacula Director -- User Agent Access Control List (ACL) handling
+ *
+ * Kern Sibbald, January MMIV
+ *
+ * Version $Id$
+ */
+
+/*
+ Copyright (C) 2004 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "dird.h"
+
+/*
+ * Check if access is permitted to item in acl
+ */
+bool acl_access_ok(UAContext *ua, int acl, char *item)
+{
+ return acl_access_ok(ua, acl, item, strlen(item));
+}
+
+
+bool acl_access_ok(UAContext *ua, int acl, char *item, int len)
+{
+ if (!ua->cons) {
+ Dmsg0(400, "Root cons access OK.\n");
+ return true; /* No cons resource -> root console OK for everything */
+ }
+ alist *list = ua->cons->ACL_lists[acl];
+ if (!list) {
+ return false; /* List empty, reject */
+ }
+ for (int i=0; i<list->size(); i++) {
+ if (strncasecmp(item, (char *)list->get(i), len) == 0) {
+ Dmsg3(400, "Found %s in %d %s\n", item, acl, (char *)list->get(i));
+ return true;
+ }
+ }
+ return false;
+}
{
unsigned int i;
int len, stat;
- int found;
+ bool found = false;
- found = 0;
stat = 1;
- Dmsg1(120, "Command: %s\n", ua->UA_sock->msg);
+ Dmsg1(200, "Command: %s\n", ua->UA_sock->msg);
if (ua->argc == 0) {
return 1;
}
len = strlen(ua->argk[0]);
for (i=0; i<comsize; i++) { /* search for command */
if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
+ if (!acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
+ break;
+ }
stat = (*commands[i].func)(ua, cmd); /* go execute command */
- found = 1;
+ found = true;
break;
}
}
if (!found) {
- pm_strcat(&ua->UA_sock->msg, _(": is an illegal command\n"));
- ua->UA_sock->msglen = strlen(ua->UA_sock->msg);
- bnet_send(ua->UA_sock);
+ bnet_fsend(ua->UA_sock, _("%s: is an illegal command.\n"), ua->argk[0]);
}
return stat;
}
{N_("catalogs"), R_CATALOG},
{N_("schedules"), R_SCHEDULE},
{N_("filesets"), R_FILESET},
- {N_("groups"), R_GROUP},
{N_("pools"), R_POOL},
{N_("messages"), R_MSGS},
{N_("all"), -1},
start_prompt(ua, _("The defined Storage resources are:\n"));
LockRes();
foreach_res(store, R_STORAGE) {
- add_prompt(ua, store->hdr.name);
+ if (acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
+ add_prompt(ua, store->hdr.name);
+ }
}
UnlockRes();
do_prompt(ua, _("Storage"), _("Select Storage resource"), name, sizeof(name));
start_prompt(ua, _("The defined FileSet resources are:\n"));
LockRes();
foreach_res(fs, R_FILESET) {
- add_prompt(ua, fs->hdr.name);
+ if (acl_access_ok(ua, FileSet_ACL, fs->hdr.name)) {
+ add_prompt(ua, fs->hdr.name);
+ }
}
UnlockRes();
do_prompt(ua, _("FileSet"), _("Select FileSet resource"), name, sizeof(name));
for (i=1; i<ua->argc; i++) {
if (strcasecmp(ua->argk[i], _("catalog")) == 0 && ua->argv[i]) {
- catalog = (CAT *)GetResWithName(R_CATALOG, ua->argv[i]);
- break;
+ if (acl_access_ok(ua, Catalog_ACL, ua->argv[i])) {
+ catalog = (CAT *)GetResWithName(R_CATALOG, ua->argv[i]);
+ break;
+ }
}
}
if (!catalog) {
start_prompt(ua, _("The defined Catalog resources are:\n"));
LockRes();
foreach_res(catalog, R_CATALOG) {
- add_prompt(ua, catalog->hdr.name);
+ if (acl_access_ok(ua, Catalog_ACL, catalog->hdr.name)) {
+ add_prompt(ua, catalog->hdr.name);
+ }
}
UnlockRes();
do_prompt(ua, _("Catalog"), _("Select Catalog resource"), name, sizeof(name));
start_prompt(ua, _("The defined Job resources are:\n"));
LockRes();
foreach_res(job, R_JOB) {
- add_prompt(ua, job->hdr.name);
+ if (acl_access_ok(ua, Job_ACL, job->hdr.name)) {
+ add_prompt(ua, job->hdr.name);
+ }
}
UnlockRes();
do_prompt(ua, _("Job"), _("Select Job resource"), name, sizeof(name));
start_prompt(ua, _("The defined Restore Job resources are:\n"));
LockRes();
foreach_res(job, R_JOB) {
- if (job->JobType == JT_RESTORE) {
+ if (job->JobType == JT_RESTORE && acl_access_ok(ua, Job_ACL, job->hdr.name)) {
add_prompt(ua, job->hdr.name);
}
}
start_prompt(ua, _("The defined Client resources are:\n"));
LockRes();
foreach_res(client, R_CLIENT) {
- add_prompt(ua, client->hdr.name);
+ if (acl_access_ok(ua, Client_ACL, client->hdr.name)) {
+ add_prompt(ua, client->hdr.name);
+ }
}
UnlockRes();
do_prompt(ua, _("Client"), _("Select Client (File daemon) resource"), name, sizeof(name));
for (i=1; i<ua->argc; i++) {
if ((strcasecmp(ua->argk[i], _("client")) == 0 ||
strcasecmp(ua->argk[i], _("fd")) == 0) && ua->argv[i]) {
+ if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
+ break;
+ }
client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
if (client) {
return client;
for (i=1; i<ua->argc; i++) {
if ((strcasecmp(ua->argk[i], _("client")) == 0 ||
strcasecmp(ua->argk[i], _("fd")) == 0) && ua->argv[i]) {
+ if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
+ break;
+ }
bstrncpy(cr->Name, ua->argv[i], sizeof(cr->Name));
if (!db_get_client_record(ua->jcr, ua->db, cr)) {
bsendmsg(ua, _("Could not find Client \"%s\": ERR=%s"), ua->argv[i],
start_prompt(ua, _("Defined Clients:\n"));
for (i=0; i < num_clients; i++) {
ocr.ClientId = ids[i];
- if (!db_get_client_record(ua->jcr, ua->db, &ocr)) {
+ if (!db_get_client_record(ua->jcr, ua->db, &ocr) ||
+ !acl_access_ok(ua, Client_ACL, ocr.Name)) {
continue;
}
add_prompt(ua, ocr.Name);
int get_pool_dbr(UAContext *ua, POOL_DBR *pr)
{
if (pr->Name[0]) { /* If name already supplied */
- if (db_get_pool_record(ua->jcr, ua->db, pr)) {
+ if (db_get_pool_record(ua->jcr, ua->db, pr) &&
+ acl_access_ok(ua, Pool_ACL, pr->Name)) {
return pr->PoolId;
}
bsendmsg(ua, _("Could not find Pool \"%s\": ERR=%s"), pr->Name, db_strerror(ua->db));
uint32_t *ids;
for (i=1; i<ua->argc; i++) {
- if (strcasecmp(ua->argk[i], _("pool")) == 0 && ua->argv[i]) {
+ if (strcasecmp(ua->argk[i], _("pool")) == 0 && ua->argv[i] &&
+ acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
bstrncpy(pr->Name, ua->argv[i], sizeof(pr->Name));
if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
bsendmsg(ua, _("Could not find Pool \"%s\": ERR=%s"), ua->argv[i],
start_prompt(ua, _("Defined Pools:\n"));
for (i=0; i < num_pools; i++) {
opr.PoolId = ids[i];
- if (!db_get_pool_record(ua->jcr, ua->db, &opr)) {
+ if (!db_get_pool_record(ua->jcr, ua->db, &opr) ||
+ !acl_access_ok(ua, Pool_ACL, opr.Name)) {
continue;
}
add_prompt(ua, opr.Name);
start_prompt(ua, _("The defined Pool resources are:\n"));
LockRes();
foreach_res(pool, R_POOL) {
- add_prompt(ua, pool->hdr.name);
+ if (acl_access_ok(ua, Pool_ACL, pool->hdr.name)) {
+ add_prompt(ua, pool->hdr.name);
+ }
}
UnlockRes();
do_prompt(ua, _("Pool"), _("Select Pool resource"), name, sizeof(name));
int i;
i = find_arg_with_value(ua, "pool");
- if (i >= 0) {
+ if (i >= 0 && acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]);
if (pool) {
return pool;
jr->JobId = 0;
bstrncpy(jr->Job, ua->argv[i], sizeof(jr->Job));
} else if (strcasecmp(ua->argk[i], _("jobid")) == 0 && ua->argv[i]) {
- jr->JobId = atoi(ua->argv[i]);
+ jr->JobId = str_to_int64(ua->argv[i]);
} else {
continue;
}
break;
} else if (strcasecmp(ua->argk[i], _("jobid")) == 0) {
- jobid = atoi(ua->argv[i]);
+ jobid = str_to_int64(ua->argv[i]);
if (jobid <= 0) {
bsendmsg(ua, _("Expecting jobid=nn command, got: %s\n"), ua->argk[i]);
return NULL;
}
}
}
-
+ if (store && !acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
+ store = NULL;
+ }
+
if (!store && store_name) {
store = (STORE *)GetResWithName(R_STORAGE, store_name);
if (!store) {
bsendmsg(ua, "Storage resource \"%s\": not found\n", store_name);
}
}
+ if (store && !acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
+ store = NULL;
+ }
/* No keywords found, so present a selection list */
if (!store) {
store = select_storage_resource(ua);
/*
* Authenticate Director
*/
-int authenticate_director(JCR *jcr, DIRRES *director, char *name)
+int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons)
{
BSOCK *dir = jcr->dir_bsock;
int ssl_need = BNET_SSL_NONE;
char bashed_name[MAX_NAME_LENGTH];
+ char *password;
/*
* Send my name to the Director then do authentication
*/
- bstrncpy(bashed_name, name, sizeof(bashed_name));
- bash_spaces(bashed_name);
+ if (cons) {
+ bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name));
+ bash_spaces(bashed_name);
+ password = cons->password;
+ } else {
+ bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name));
+ password = director->password;
+ }
bnet_fsend(dir, hello, bashed_name);
- if (!cram_md5_get_auth(dir, director->password, ssl_need) ||
- !cram_md5_auth(dir, director->password, ssl_need)) {
+ if (!cram_md5_get_auth(dir, password, ssl_need) ||
+ !cram_md5_auth(dir, password, ssl_need)) {
printf(_("%s: Director authorization problem.\n"), my_name);
set_text(_("Director authorization problem.\n"), -1);
return 0;
#include "support.h"
/* Imported functions */
-int authenticate_director(JCR *jcr, DIRRES *director, char *name);
+int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons);
/* Exported variables */
GtkWidget *app1; /* application window */
LockRes();
ndir = 0;
- for (dir=NULL; (dir = (DIRRES *)GetNextRes(R_DIRECTOR, (RES *)dir)); ) {
+ foreach_res(dir, R_DIRECTOR) {
ndir++;
}
UnlockRes();
Without that I don't how to speak to the Director :-(\n"), configfile);
}
- if (test_config) {
- terminate_console(0);
- exit(0);
- }
app1 = create_app1();
*/
LockRes();
- for (con = NULL; (con = (CONRES *)GetNextRes(R_CONSOLE, (RES *)con)); ) {
+ foreach_res(con, R_CONSOLE) {
+ if (!con->fontface) {
+ Dmsg1(400, "No fontface for %s\n", con->hdr.name);
+ continue;
+ }
text_font = gdk_font_load(con->fontface);
if (text_font == NULL) {
- Dmsg2(404, "Load of requested ConsoleFont \"%s\" (%s) failed!\n",
+ Dmsg2(400, "Load of requested ConsoleFont \"%s\" (%s) failed!\n",
con->hdr.name, con->fontface);
} else {
- Dmsg2(404, "ConsoleFont \"%s\" (%s) loaded.\n",
+ Dmsg2(400, "ConsoleFont \"%s\" (%s) loaded.\n",
con->hdr.name, con->fontface);
break;
}
UnlockRes();
if (text_font == NULL) {
- Dmsg1(100, "Attempting to load fallback font %s\n",
+ Dmsg1(400, "Attempting to load fallback font %s\n",
"-misc-fixed-medium-r-normal-*-*-130-*-*-c-*-iso8859-1");
text_font = gdk_font_load("-misc-fixed-medium-r-normal-*-*-130-*-*-c-*-iso8859-1");
}
gtk_widget_modify_font (status1, font_desc);
pango_font_description_free (font_desc);
+ if (test_config) {
+ terminate_console(0);
+ exit(0);
+ }
+
initial = gtk_timeout_add(100, initial_connect_to_director, (gpointer)NULL);
gtk_main();
LockRes();
CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
UnlockRes();
- char *con_name;
- if (cons) {
- con_name = cons->hdr.name;
- } else {
- con_name = "*UserAgent*";
- }
- if (!authenticate_director(&jcr, dir, con_name)) {
+ if (!authenticate_director(&jcr, dir, cons)) {
set_text(UA_sock->msg, UA_sock->msglen);
return 0;
}
* 1. The generic lexical scanner in lib/lex.c and lib/lex.h
*
* 2. The generic config scanner in lib/parse_config.c and
- * lib/parse_config.h.
- * These files contain the parser code, some utility
- * routines, and the common store routines (name, int,
- * string).
+ * lib/parse_config.h.
+ * These files contain the parser code, some utility
+ * routines, and the common store routines (name, int,
+ * string).
*
* 3. The daemon specific file, which contains the Resource
- * definitions as well as any specific store routines
- * for the resource records.
+ * definitions as well as any specific store routines
+ * for the resource records.
*
* Kern Sibbald, January MM, September MM
*
{"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
{"dirport", store_int, ITEM(res_dir.DIRport), 0, ITEM_DEFAULT, 9101},
{"address", store_str, ITEM(res_dir.address), 0, ITEM_REQUIRED, 0},
- {"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
+ {"password", store_password, ITEM(res_dir.password), 0, 0, 0},
{"enablessl", store_yesno, ITEM(res_dir.enable_ssl), 1, ITEM_DEFAULT, 0},
{NULL, NULL, NULL, 0, 0, 0}
};
static struct res_items con_items[] = {
{"name", store_name, ITEM(con_dir.hdr.name), 0, ITEM_REQUIRED, 0},
{"description", store_str, ITEM(con_dir.hdr.desc), 0, 0, 0},
- {"font", store_str, ITEM(con_dir.fontface), 0, ITEM_REQUIRED, 0},
+ {"font", store_str, ITEM(con_dir.fontface), 0, 0, 0},
+ {"password", store_password, ITEM(con_dir.password), 0, ITEM_REQUIRED, 0},
{"requiressl", store_yesno, ITEM(con_dir.require_ssl), 1, ITEM_DEFAULT, 0},
{NULL, NULL, NULL, 0, 0, 0}
};
*/
struct s_res resources[] = {
{"director", dir_items, R_DIRECTOR, NULL},
- {"consolefont", con_items, R_CONSOLE, NULL},
- {NULL, NULL, 0, NULL}
+ {"console", con_items, R_CONSOLE, NULL},
+ {NULL, NULL, 0, NULL}
};
printf("No record for %d %s\n", type, res_to_str(type));
return;
}
- if (type < 0) { /* no recursion */
+ if (type < 0) { /* no recursion */
type = - type;
recurse = 0;
}
switch (type) {
case R_DIRECTOR:
printf("Director: name=%s address=%s DIRport=%d\n", reshdr->name,
- res->res_dir.address, res->res_dir.DIRport);
+ res->res_dir.address, res->res_dir.DIRport);
break;
case R_CONSOLE:
printf("Console: name=%s font face=%s\n",
- reshdr->name, NPRT(res->con_dir.fontface));
+ reshdr->name, NPRT(res->con_dir.fontface));
break;
default:
printf("Unknown resource type %d\n", type);
switch (type) {
case R_DIRECTOR:
if (res->res_dir.address) {
- free(res->res_dir.address);
+ free(res->res_dir.address);
}
break;
case R_CONSOLE:
if (res->con_dir.fontface) {
- free(res->con_dir.fontface);
+ free(res->con_dir.fontface);
}
break;
default:
*/
for (i=0; items[i].name; i++) {
if (items[i].flags & ITEM_REQUIRED) {
- if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
+ if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
Emsg2(M_ABORT, 0, "%s item is required in %s resource, but not found.\n",
- items[i].name, resources[rindex]);
- }
+ items[i].name, resources[rindex]);
+ }
}
}
switch (type) {
/* Resources not containing a resource */
case R_DIRECTOR:
- break;
+ break;
case R_CONSOLE:
- break;
+ break;
default:
Emsg1(M_ERROR, 0, "Unknown resource type %d\n", type);
- error = 1;
- break;
+ error = 1;
+ break;
}
/* Note, the resoure name was already saved during pass 1,
* so here, we can just release it.
*/
if (res_all.res_dir.hdr.name) {
- free(res_all.res_dir.hdr.name);
- res_all.res_dir.hdr.name = NULL;
+ free(res_all.res_dir.hdr.name);
+ res_all.res_dir.hdr.name = NULL;
}
if (res_all.res_dir.hdr.desc) {
- free(res_all.res_dir.hdr.desc);
- res_all.res_dir.hdr.desc = NULL;
+ free(res_all.res_dir.hdr.desc);
+ res_all.res_dir.hdr.desc = NULL;
}
return;
}
res = (URES *)malloc(size);
memcpy(res, &res_all, size);
if (!resources[rindex].res_head) {
- resources[rindex].res_head = (RES *)res; /* store first entry */
+ resources[rindex].res_head = (RES *)res; /* store first entry */
} else {
- RES *next;
- /* Add new res to end of chain */
- for (next=resources[rindex].res_head; next->next; next=next->next) {
- if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
- Emsg2(M_ERROR_TERM, 0,
+ RES *next;
+ /* Add new res to end of chain */
+ for (next=resources[rindex].res_head; next->next; next=next->next) {
+ if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
+ Emsg2(M_ERROR_TERM, 0,
_("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
- resources[rindex].name, res->res_dir.hdr.name);
- }
- }
- next->next = (RES *)res;
+ resources[rindex].name, res->res_dir.hdr.name);
+ }
+ }
+ next->next = (RES *)res;
Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
- res->res_dir.hdr.name);
+ res->res_dir.hdr.name);
}
}
}
/*
* Resource codes -- they must be sequential for indexing
*/
-#define R_FIRST 1001
-#define R_DIRECTOR 1001
-#define R_CONSOLE 1002
+enum {
+ R_DIRECTOR = 1001,
+ R_CONSOLE,
+};
-#define R_LAST R_CONSOLE
+#define R_FIRST R_DIRECTOR
+#define R_LAST R_CONSOLE
/*
* Some resource attributes
struct s_con_dir {
RES hdr;
char *fontface; /* Console Font specification */
+ char *password; /* UA server password */
int require_ssl; /* Require SSL on all connections */
};
typedef struct s_con_dir CONRES;
*/
+/* Second arg of init */
+enum {
+ owned_by_alist = true,
+ not_owned_by_alist = false
+};
+
+
/*
* Array list -- much like a simplified STL vector
* array of pointers to inserted items
va_end(arg_ptr);
if (lc->line_no > lc->begin_line_no) {
- sprintf(more, _("Problem probably begins at Line %d.\n"), lc->begin_line_no);
+ bsnprintf(more, sizeof(more),
+ _("Problem probably begins at line %d.\n"), lc->begin_line_no);
} else {
more[0] = 0;
}
e_msg(file, line, M_ERROR_TERM, 0, _("Config error: %s\n\
- : Line %d, col %d of file %s\n%s\n%s"),
+ : line %d, col %d of file %s\n%s\n%s"),
buf, lc->line_no, lc->col_no, lc->fname, lc->line, more);
}
{
if (lf->str_len >= MAXSTRING-3) {
Emsg3(M_ERROR_TERM, 0, _(
- "Token too long, file: %s, line %d, begins at line %d\n"),
+ _("Config token too long, file: %s, line %d, begins at line %d\n")),
lf->fname, lf->line_no, lf->begin_line_no);
}
lf->str[lf->str_len++] = ch;
static uint32_t scan_pint(LEX *lf, char *str)
{
- double dval = 0;
+ int64_t val = 0;
if (!is_a_number(str)) {
scan_err1(lf, "expected a positive integer number, got: %s", str);
/* NOT REACHED */
} else {
errno = 0;
- dval = strtod(str, NULL);
- if (errno != 0 || dval < 0) {
+ val = str_to_int64(str);
+ if (errno != 0 || val < 0) {
scan_err1(lf, "expected a postive integer number, got: %s", str);
/* NOT REACHED */
}
}
- return (uint32_t)dval;
+ return (uint32_t)val;
}
/*
break;
}
errno = 0;
- lf->int32_val = (int32_t)strtod(lf->str, NULL);
+ lf->int32_val = (int32_t)str_to_int64(lf->str);
if (errno != 0) {
scan_err2(lf, "expected an integer number, got %s: %s",
lex_tok_to_str(token), lf->str);
break;
}
errno = 0;
- lf->int64_val = (int64_t)strtod(lf->str, NULL);
+ lf->int64_val = str_to_int64(lf->str);
if (errno != 0) {
scan_err2(lf, "expected an integer number, got %s: %s",
lex_tok_to_str(token), lf->str);
token = lex_get_token(lc, T_NAME); /* scan destination */
dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
if (dest[0] != 0) {
- strcat(dest, " "); /* separate multiple destinations with space */
+ pm_strcat(&dest, " "); /* separate multiple destinations with space */
dest_len++;
}
- strcat(dest, lc->str);
+ pm_strcat(&dest, lc->str);
dest_len += lc->str_len;
Dmsg2(100, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
token = lex_get_token(lc, T_ALL);