1 /*
2    Bacula(R) - The Network Backup Solution
3 
4    Copyright (C) 2000-2020 Kern Sibbald
5 
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8 
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13 
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16 
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20 *   Main configuration file parser for Bacula Tray Monitor.
21 *
22 *   Adapted from dird_conf.c
23 *
24 *   Note, the configuration file parser consists of three parts
25 *
26 *   1. The generic lexical scanner in lib/lex.c and lib/lex.h
27 *
28 *   2. The generic config  scanner in lib/parse_config.c and
29 *       lib/parse_config.h.
30 *       These files contain the parser code, some utility
31 *       routines, and the common store routines (name, int,
32 *       string).
33 *
34 *   3. The daemon specific file, which contains the Resource
35 *       definitions as well as any specific store routines
36 *       for the resource records.
37 *
38 *     Nicolas Boichat, August MMIV
39 *
40 */
41 
42 #include "common.h"
43 #include "tray_conf.h"
44 
45 worker *worker_start();
46 void worker_stop(worker *);
47 
48 /* Define the first and last resource ID record
49 * types. Note, these should be unique for each
50 * daemon though not a requirement.
51 */
52 int32_t r_first = R_FIRST;
53 int32_t r_last  = R_LAST;
54 RES_HEAD **res_head;
55 
56 /* We build the current resource here as we are
57 * scanning the resource configuration definition,
58 * then move it to allocated memory when the resource
59 * scan is complete.
60 */
61 URES res_all;
62 int32_t res_all_size = sizeof(res_all);
63 
64 
65 /* Definition of records permitted within each
66 * resource with the routine to process the record
67 * information.  NOTE! quoted names must be in lower case.
68 */
69 /*
70 *    Monitor Resource
71 *
72 *   name           handler     value                 code flags    default_value
73 */
74 static RES_ITEM mon_items[] = {
75    {"Name",        store_name,     ITEM(res_monitor.hdr.name), 0, ITEM_REQUIRED, 0},
76    {"Description", store_str,      ITEM(res_monitor.hdr.desc), 0, 0, 0},
77    {"requiressl",  store_bool,     ITEM(res_monitor.require_ssl), 1, ITEM_DEFAULT, 0},
78    {"RefreshInterval",  store_time,ITEM(res_monitor.RefreshInterval),    0, ITEM_DEFAULT, 60},
79    {"CommCompression",  store_bool, ITEM(res_monitor.comm_compression), 0, ITEM_DEFAULT, true},
80    {"CommandDirectory", store_dir, ITEM(res_monitor.command_dir), 0, 0, 0},
81    {"DisplayAdvancedOptions", store_bool, ITEM(res_monitor.display_advanced_options), 0, 0, 0},
82    {NULL, NULL, {0}, 0, 0, 0}
83 };
84 
85 /*  Director's that we can contact */
86 static RES_ITEM dir_items[] = {
87    {"Name",        store_name,     ITEM(res_main.hdr.name), 0, ITEM_REQUIRED, 0},
88    {"Description", store_str,      ITEM(res_main.hdr.desc), 0, 0, 0},
89    {"Port",        store_pint32,   ITEM(res_main.port),     0, ITEM_DEFAULT, 9101},
90    {"Address",     store_str,      ITEM(res_main.address),  0, ITEM_REQUIRED, 0},
91    {"Password",    store_password, ITEM(res_main.password), 0, ITEM_REQUIRED, 0},
92    {"Monitor",  store_bool,       ITEM(res_main.use_monitor), 0, ITEM_DEFAULT, 0},
93    {"ConnectTimeout", store_time,ITEM(res_main.connect_timeout),   0, ITEM_DEFAULT, 10},
94    {"UseSetIp", store_bool,      ITEM(res_main.use_setip),  0, 0, 0},
95    {"TlsEnable",      store_bool,    ITEM(res_main.tls_enable), 0, 0, 0},
96    {"TlsPskEnable",   store_bool,    ITEM(res_main.tls_psk_enable), 0, ITEM_DEFAULT, tls_psk_default},
97    {"TlsCaCertificateFile", store_dir, ITEM(res_main.tls_ca_certfile), 0, 0, 0},
98    {"TlsCaCertificateDir", store_dir,  ITEM(res_main.tls_ca_certdir), 0, 0, 0},
99    {"TlsCertificate", store_dir,       ITEM(res_main.tls_certfile), 0, 0, 0},
100    {"TlsKey",         store_dir,       ITEM(res_main.tls_keyfile), 0, 0, 0},
101 
102    {NULL, NULL, {0}, 0, 0, 0}
103 };
104 
105 /*
106 *    Client or File daemon resource
107 *
108 *   name           handler     value                 code flags    default_value
109 */
110 
111 static RES_ITEM cli_items[] = {
112    {"Name",     store_name,       ITEM(res_main.hdr.name), 0, ITEM_REQUIRED, 0},
113    {"Description", store_str,     ITEM(res_main.hdr.desc), 0, 0, 0},
114    {"Address",  store_str,        ITEM(res_main.address),  0, ITEM_REQUIRED, 0},
115    {"Port",     store_pint32,     ITEM(res_main.port),   0, ITEM_DEFAULT, 9102},
116    {"Password", store_password,   ITEM(res_main.password), 0, ITEM_REQUIRED, 0},
117    {"ConnectTimeout", store_time,ITEM(res_main.connect_timeout),   0, ITEM_DEFAULT, 10},
118    {"Remote",   store_bool,       ITEM(res_main.use_remote), 0, ITEM_DEFAULT, 0},
119    {"Monitor",  store_bool,       ITEM(res_main.use_monitor), 0, ITEM_DEFAULT, 0},
120    {"Managed",  store_bool,       ITEM(res_main.managed), 0, ITEM_DEFAULT, 0},
121    {"TlsEnable",      store_bool,    ITEM(res_main.tls_enable), 0, 0, 0},
122    {"TlsPskEnable",   store_bool,    ITEM(res_main.tls_psk_enable), 0, ITEM_DEFAULT, tls_psk_default},
123    {"TlsCaCertificateFile", store_dir, ITEM(res_main.tls_ca_certfile), 0, 0, 0},
124    {"TlsCaCertificateDir", store_dir,  ITEM(res_main.tls_ca_certdir), 0, 0, 0},
125    {"TlsCertificate", store_dir,       ITEM(res_main.tls_certfile), 0, 0, 0},
126    {"TlsKey",         store_dir,       ITEM(res_main.tls_keyfile), 0, 0, 0},
127    {NULL, NULL, {0}, 0, 0, 0}
128 };
129 
130 /* Storage daemon resource
131 *
132 *   name           handler     value                 code flags    default_value
133 */
134 static RES_ITEM store_items[] = {
135    {"Name",        store_name,     ITEM(res_main.hdr.name),   0, ITEM_REQUIRED, 0},
136    {"Description", store_str,      ITEM(res_main.hdr.desc),   0, 0, 0},
137    {"Port",      store_pint32,   ITEM(res_main.port),     0, ITEM_DEFAULT, 9103},
138    {"Address",     store_str,      ITEM(res_main.address),    0, ITEM_REQUIRED, 0},
139    {"Password",    store_password, ITEM(res_main.password),   0, ITEM_REQUIRED, 0},
140    {"ConnectTimeout", store_time,ITEM(res_main.connect_timeout),   0, ITEM_DEFAULT, 10},
141    {"Monitor",  store_bool,       ITEM(res_main.use_monitor), 0, ITEM_DEFAULT, 0},
142    {"TlsEnable",      store_bool,    ITEM(res_main.tls_enable), 0, 0, 0},
143    {"TlsPskEnable",   store_bool,    ITEM(res_main.tls_psk_enable), 0, ITEM_DEFAULT, tls_psk_default},
144    {"TlsCaCertificateFile", store_dir, ITEM(res_main.tls_ca_certfile), 0, 0, 0},
145    {"TlsCaCertificateDir", store_dir,  ITEM(res_main.tls_ca_certdir), 0, 0, 0},
146    {"TlsCertificate", store_dir,       ITEM(res_main.tls_certfile), 0, 0, 0},
147    {"TlsKey",         store_dir,       ITEM(res_main.tls_keyfile), 0, 0, 0},
148    {NULL, NULL, {0}, 0, 0, 0}
149 };
150 
151 /*
152 * This is the master resource definition.
153 * It must have one item for each of the resources.
154 *
155 *  NOTE!!! keep it in the same order as the R_codes
156 *    or eliminate all resources[rindex].name
157 *
158 *  name      items        rcode        res_head
159 */
160 RES_TABLE resources[] = {
161    {"monitor",      mon_items,    R_MONITOR},
162    {"director",     dir_items,    R_DIRECTOR},
163    {"client",       cli_items,    R_CLIENT},
164    {"storage",      store_items,  R_STORAGE},
165    {NULL,           NULL,         0}
166 };
167 
168 /* Dump contents of resource */
dump_resource(int type,RES * ares,void sendit (void * sock,const char * fmt,...),void * sock)169 void dump_resource(int type, RES *ares, void sendit(void *sock, const char *fmt, ...), void *sock)
170 {
171    RES *next;
172    URES *res = (URES *)ares;
173    bool recurse = true;
174 
175    if (res == NULL) {
176       sendit(sock, _("No %s resource defined\n"), res_to_str(type));
177       return;
178    }
179    if (type < 0) {                    /* no recursion */
180       type = - type;
181       recurse = false;
182    }
183    switch (type) {
184    case R_MONITOR:
185       sendit(sock, _("Monitor: name=%s\n"), ares->name);
186       break;
187    case R_DIRECTOR:
188       sendit(sock, _("Director: name=%s address=%s port=%d\n"),
189              res->res_main.hdr.name, res->res_main.address, res->res_main.port);
190       break;
191    case R_CLIENT:
192       sendit(sock, _("Client: name=%s address=%s port=%d\n"),
193              res->res_main.hdr.name, res->res_main.address, res->res_main.port);
194       break;
195    case R_STORAGE:
196       sendit(sock, _("Storage: name=%s address=%s port=%d\n"),
197              res->res_main.hdr.name, res->res_main.address, res->res_main.port);
198       break;
199    default:
200       sendit(sock, _("Unknown resource type %d in dump_resource.\n"), type);
201       break;
202    }
203    if (recurse) {
204       next = GetNextRes(0, (RES *)res);
205       if (next) {
206          dump_resource(type, next, sendit, sock);
207       }
208    }
209 }
210 
211 /*
212 * Free memory of resource -- called when daemon terminates.
213 * NB, we don't need to worry about freeing any references
214 * to other resources as they will be freed when that
215 * resource chain is traversed.  Mainly we worry about freeing
216 * allocated strings (names).
217 */
free_resource(RES * sres,int type)218 void free_resource(RES *sres, int type)
219 {
220    URES *res = (URES *)sres;
221 
222    if (res == NULL)
223       return;
224    /* common stuff -- free the resource name and description */
225    if (res->res_monitor.hdr.name) {
226       free(res->res_monitor.hdr.name);
227    }
228    if (res->res_monitor.hdr.desc) {
229       free(res->res_monitor.hdr.desc);
230    }
231 
232    switch (type) {
233    case R_MONITOR:
234       if (res->res_monitor.password) {
235          free(res->res_monitor.password);
236       }
237       if (res->res_monitor.command_dir) {
238          free(res->res_monitor.command_dir);
239       }
240       break;
241    case R_DIRECTOR:
242    case R_CLIENT:
243    case R_STORAGE:
244       delete res->res_main.mutex;
245       free_bsock(res->res_main.bs);
246       if (res->res_main.wrk) {
247          worker_stop(res->res_main.wrk);
248          res->res_main.wrk = NULL;
249       }
250       if (res->res_main.address) {
251          free(res->res_main.address);
252       }
253       if (res->res_main.tls_ctx) {
254          free_tls_context(res->res_main.tls_ctx);
255       }
256       if (res->res_main.tls_ca_certfile) {
257          free(res->res_main.tls_ca_certfile);
258       }
259       if (res->res_main.tls_ca_certdir) {
260          free(res->res_main.tls_ca_certdir);
261       }
262       if (res->res_main.tls_certfile) {
263          free(res->res_main.tls_certfile);
264       }
265       if (res->res_main.tls_keyfile) {
266          free(res->res_main.tls_keyfile);
267       }
268       if (res->res_main.jobs) {
269          delete res->res_main.jobs;
270       }
271       if (res->res_main.clients) {
272          delete res->res_main.clients;
273       }
274       if (res->res_main.filesets) {
275          delete res->res_main.filesets;
276       }
277       if (res->res_main.pools) {
278          delete res->res_main.pools;
279       }
280       if (res->res_main.storages) {
281          delete res->res_main.storages;
282       }
283       if (res->res_main.running_jobs) {
284          delete res->res_main.terminated_jobs;
285       }
286       break;
287    default:
288       printf(_("Unknown resource type %d in free_resource.\n"), type);
289    }
290 
291    /* Common stuff again -- free the resource, recurse to next one */
292    if (res) {
293       free(res);
294    }
295 }
296 
297 /*
298 * Save the new resource by chaining it into the head list for
299 * the resource. If this is pass 2, we update any resource
300 * pointers because they may not have been defined until
301 * later in pass 1.
302 */
save_resource(CONFIG * config,int type,RES_ITEM * items,int pass)303 bool save_resource(CONFIG *config, int type, RES_ITEM *items, int pass)
304 {
305    int rindex = type - r_first;
306    int i, size;
307    int error = 0;
308 
309    /*
310    * Ensure that all required items are present
311    */
312    for (i=0; items[i].name; i++) {
313       if (items[i].flags & ITEM_REQUIRED) {
314          if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
315             Mmsg(config->m_errmsg, _("\"%s\" directive is required in \"%s\" resource, but not found.\n"),
316                  items[i].name, resources[rindex].name);
317             return false;
318          }
319       }
320       /* If this triggers, take a look at lib/parse_conf.h */
321       if (i >= MAX_RES_ITEMS) {
322          Mmsg(config->m_errmsg, _("Too many directives in \"%s\" resource\n"), resources[rindex].name);
323          return false;
324       }
325    }
326 
327    /*
328    * During pass 2 in each "store" routine, we looked up pointers
329    * to all the resources referrenced in the current resource, now we
330    * must copy their addresses from the static record to the allocated
331    * record.
332    */
333    if (pass == 2) {
334       switch (type) {
335       /* Resources not containing a resource */
336       case R_STORAGE:
337       case R_DIRECTOR:
338       case R_CLIENT:
339       case R_MONITOR:
340          break;
341       default:
342          Emsg1(M_ERROR, 0, _("Unknown resource type %d in save_resource.\n"), type);
343          error = 1;
344          break;
345       }
346       /* Note, the resource name was already saved during pass 1,
347       * so here, we can just release it.
348       */
349       if (res_all.res_monitor.hdr.name) {
350          free(res_all.res_monitor.hdr.name);
351          res_all.res_monitor.hdr.name = NULL;
352       }
353       if (res_all.res_monitor.hdr.desc) {
354          free(res_all.res_monitor.hdr.desc);
355          res_all.res_monitor.hdr.desc = NULL;
356       }
357       return true;
358    }
359 
360    /*
361    * The following code is only executed during pass 1
362    */
363    switch (type) {
364    case R_MONITOR:
365       size = sizeof(MONITOR);
366       break;
367    case R_CLIENT:
368    case R_STORAGE:
369    case R_DIRECTOR:
370       // We need to initialize the mutex
371       res_all.res_main.mutex = new QMutex();
372       res_all.res_main.wrk = worker_start();
373       size = sizeof(RESMON);
374       break;
375    default:
376       printf(_("Unknown resource type %d in save_resource.\n"), type);
377       error = 1;
378       size = 1;
379       break;
380    }
381    /* Common */
382    if (!error) {
383       res_all.res_main.type = type;
384       if (!config->insert_res(rindex, size)) {
385          return false;
386       }
387    }
388    return true;
389 }
390 
parse_tmon_config(CONFIG * config,const char * configfile,int exit_code)391 bool parse_tmon_config(CONFIG *config, const char *configfile, int exit_code)
392 {
393    config->init(configfile, error_handler, exit_code,
394                 (void *)&res_all, res_all_size,
395       r_first, r_last, resources, &res_head);
396    return config->parse_config();
397 }
398