]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/bat_conf.cpp
0f8dcc2c9bda16a8477045eb7fa0fafc5d4108ad
[bacula/bacula] / bacula / src / qt-console / bat_conf.cpp
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2016 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 User Agent
21  *    some parts may be split into separate files such as
22  *    the schedule configuration (sch_config.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  *     Kern Sibbald, January MM, September MM
39  *
40  */
41
42 #include "bacula.h"
43 #include "bat_conf.h"
44
45 /* Define the first and last resource ID record
46  * types. Note, these should be unique for each
47  * daemon though not a requirement.
48  */
49 int32_t r_first = R_FIRST;
50 int32_t r_last  = R_LAST;
51 static RES *sres_head[R_LAST - R_FIRST + 1];
52 RES **res_head = sres_head;
53
54 /* Forward referenced subroutines */
55
56
57 /* We build the current resource here as we are
58  * scanning the resource configuration definition,
59  * then move it to allocated memory when the resource
60  * scan is complete.
61  */
62 #if defined(_MSC_VER)
63 extern "C" URES res_all; /* declare as C to avoid name mangling by visual c */
64 #endif
65 URES res_all;
66 int32_t res_all_size = sizeof(res_all);
67
68 /* Definition of records permitted within each
69  * resource with the routine to process the record
70  * information.
71  */
72 static RES_ITEM dir_items[] = {
73    {"name",        store_name,     ITEM(dir_res.hdr.name), 0, ITEM_REQUIRED, 0},
74    {"description", store_str,      ITEM(dir_res.hdr.desc), 0, 0, 0},
75    {"dirport",     store_pint32,   ITEM(dir_res.DIRport),  0, ITEM_DEFAULT, 9101},
76    {"address",     store_str,      ITEM(dir_res.address),  0, ITEM_REQUIRED, 0},
77    {"password",    store_password, ITEM(dir_res.password), 0, 0, 0},
78    {"tlsauthenticate",store_bool,    ITEM(dir_res.tls_authenticate), 0, 0, 0},
79    {"tlsenable",      store_bool,    ITEM(dir_res.tls_enable), 0, 0, 0},
80    {"tlsrequire",     store_bool,    ITEM(dir_res.tls_require), 0, 0, 0},
81    {"tlscacertificatefile", store_dir, ITEM(dir_res.tls_ca_certfile), 0, 0, 0},
82    {"tlscacertificatedir", store_dir,  ITEM(dir_res.tls_ca_certdir), 0, 0, 0},
83    {"tlscertificate", store_dir,       ITEM(dir_res.tls_certfile), 0, 0, 0},
84    {"tlskey",         store_dir,       ITEM(dir_res.tls_keyfile), 0, 0, 0},
85    {"heartbeatinterval", store_time, ITEM(dir_res.heartbeat_interval), 0, ITEM_DEFAULT, 5 * 60},
86    {NULL, NULL, {0}, 0, 0, 0}
87 };
88
89 static RES_ITEM con_items[] = {
90    {"name",        store_name,     ITEM(con_res.hdr.name), 0, ITEM_REQUIRED, 0},
91    {"description", store_str,      ITEM(con_res.hdr.desc), 0, 0, 0},
92    {"password",    store_password, ITEM(con_res.password), 0, ITEM_REQUIRED, 0},
93    {"tlsauthenticate",store_bool,    ITEM(con_res.tls_authenticate), 0, 0, 0},
94    {"tlsenable",      store_bool,    ITEM(con_res.tls_enable), 0, 0, 0},
95    {"tlsrequire",     store_bool,    ITEM(con_res.tls_require), 0, 0, 0},
96    {"tlscacertificatefile", store_dir, ITEM(con_res.tls_ca_certfile), 0, 0, 0},
97    {"tlscacertificatedir", store_dir,  ITEM(con_res.tls_ca_certdir), 0, 0, 0},
98    {"tlscertificate", store_dir,       ITEM(con_res.tls_certfile), 0, 0, 0},
99    {"tlskey",         store_dir,       ITEM(con_res.tls_keyfile), 0, 0, 0},
100    {"heartbeatinterval", store_time, ITEM(con_res.heartbeat_interval), 0, ITEM_DEFAULT, 5 * 60},
101    {"director",       store_str,       ITEM(con_res.director), 0, 0, 0},
102    {NULL, NULL, {0}, 0, 0, 0}
103 };
104
105 static RES_ITEM con_font_items[] = {
106    {"name",        store_name,     ITEM(con_font.hdr.name), 0, ITEM_REQUIRED, 0},
107    {"description", store_str,      ITEM(con_font.hdr.desc), 0, 0, 0},
108    {"font",        store_str,      ITEM(con_font.fontface), 0, 0, 0},
109    {NULL, NULL, {0}, 0, 0, 0}
110 };
111
112
113 /*
114  * This is the master resource definition.
115  * It must have one item for each of the resources.
116  */
117 RES_TABLE resources[] = {
118    {"director",      dir_items,   R_DIRECTOR},
119    {"console",       con_items,   R_CONSOLE},
120    {"consolefont",   con_font_items, R_CONSOLE_FONT},
121    {NULL,            NULL,        0}
122 };
123
124
125 /* Dump contents of resource */
126 void dump_resource(int type, RES *ares, void sendit(void *sock, const char *fmt, ...), void *sock)
127 {
128    URES *res = (URES *)ares;
129    bool recurse = true;
130
131    if (res == NULL) {
132       printf(_("No record for %d %s\n"), type, res_to_str(type));
133       return;
134    }
135    if (type < 0) {                    /* no recursion */
136       type = - type;
137       recurse = false;
138    }
139    switch (type) {
140    case R_DIRECTOR:
141       printf(_("Director: name=%s address=%s DIRport=%d\n"), ares->name,
142               res->dir_res.address, res->dir_res.DIRport);
143       break;
144    case R_CONSOLE:
145       printf(_("Console: name=%s\n"), ares->name);
146       break;
147    case R_CONSOLE_FONT:
148       printf(_("ConsoleFont: name=%s font face=%s\n"),
149              ares->name, NPRT(res->con_font.fontface));
150       break;
151    default:
152       printf(_("Unknown resource type %d\n"), type);
153    }
154    if (recurse && res->dir_res.hdr.next) {
155       dump_resource(type, res->dir_res.hdr.next, sendit, sock);
156    }
157 }
158
159 /*
160  * Free memory of resource.
161  * NB, we don't need to worry about freeing any references
162  * to other resources as they will be freed when that
163  * resource chain is traversed.  Mainly we worry about freeing
164  * allocated strings (names).
165  */
166 void free_resource(RES *sres, int type)
167 {
168    RES *nres;
169    URES *res = (URES *)sres;
170
171    if (res == NULL)
172       return;
173
174    /* common stuff -- free the resource name */
175    nres = (RES *)res->dir_res.hdr.next;
176    if (res->dir_res.hdr.name) {
177       free(res->dir_res.hdr.name);
178    }
179    if (res->dir_res.hdr.desc) {
180       free(res->dir_res.hdr.desc);
181    }
182
183    switch (type) {
184    case R_DIRECTOR:
185       if (res->dir_res.address) {
186          free(res->dir_res.address);
187       }
188       if (res->dir_res.tls_ctx) { 
189          free_tls_context(res->dir_res.tls_ctx);
190       }
191       if (res->dir_res.tls_ca_certfile) {
192          free(res->dir_res.tls_ca_certfile);
193       }
194       if (res->dir_res.tls_ca_certdir) {
195          free(res->dir_res.tls_ca_certdir);
196       }
197       if (res->dir_res.tls_certfile) {
198          free(res->dir_res.tls_certfile);
199       }
200       if (res->dir_res.tls_keyfile) {
201          free(res->dir_res.tls_keyfile);
202       }
203       break;
204    case R_CONSOLE:
205       if (res->con_res.password) {
206          free(res->con_res.password);
207       }
208       if (res->con_res.tls_ctx) { 
209          free_tls_context(res->con_res.tls_ctx);
210       }
211       if (res->con_res.tls_ca_certfile) {
212          free(res->con_res.tls_ca_certfile);
213       }
214       if (res->con_res.tls_ca_certdir) {
215          free(res->con_res.tls_ca_certdir);
216       }
217       if (res->con_res.tls_certfile) {
218          free(res->con_res.tls_certfile);
219       }
220       if (res->con_res.tls_keyfile) {
221          free(res->con_res.tls_keyfile);
222       }
223       if (res->con_res.director) {
224          free(res->con_res.director);
225       }
226       break;
227    case R_CONSOLE_FONT:
228       if (res->con_font.fontface) {
229          free(res->con_font.fontface);
230       }
231       break;
232    default:
233       printf(_("Unknown resource type %d\n"), type);
234    }
235    /* Common stuff again -- free the resource, recurse to next one */
236    if (res) {
237       free(res);
238    }
239    if (nres) {
240       free_resource(nres, type);
241    }
242 }
243
244 /* Save the new resource by chaining it into the head list for
245  * the resource. If this is pass 2, we update any resource
246  * pointers (currently only in the Job resource).
247  */
248 void save_resource(int type, RES_ITEM *items, int pass)
249 {
250    URES *res;
251    int rindex = type - r_first;
252    int i, size = 0;
253    int error = 0;
254
255    /*
256     * Ensure that all required items are present
257     */
258    for (i=0; items[i].name; i++) {
259       if (items[i].flags & ITEM_REQUIRED) {
260             if (!bit_is_set(i, res_all.dir_res.hdr.item_present)) {
261                Emsg2(M_ABORT, 0, _("%s item is required in %s resource, but not found.\n"),
262                  items[i].name, resources[rindex]);
263              }
264       }
265    }
266
267    /* During pass 2, we looked up pointers to all the resources
268     * referrenced in the current resource, , now we
269     * must copy their address from the static record to the allocated
270     * record.
271     */
272    if (pass == 2) {
273       switch (type) {
274       /* Resources not containing a resource */
275       case R_DIRECTOR:
276          break;
277
278       case R_CONSOLE:
279       case R_CONSOLE_FONT:
280          break;
281
282       default:
283          Emsg1(M_ERROR, 0, _("Unknown resource type %d\n"), type);
284          error = 1;
285          break;
286       }
287       /* Note, the resoure name was already saved during pass 1,
288        * so here, we can just release it.
289        */
290       if (res_all.dir_res.hdr.name) {
291          free(res_all.dir_res.hdr.name);
292          res_all.dir_res.hdr.name = NULL;
293       }
294       if (res_all.dir_res.hdr.desc) {
295          free(res_all.dir_res.hdr.desc);
296          res_all.dir_res.hdr.desc = NULL;
297       }
298       return;
299    }
300
301    /* The following code is only executed during pass 1 */
302    switch (type) {
303    case R_DIRECTOR:
304       size = sizeof(DIRRES);
305       break;
306    case R_CONSOLE_FONT:
307       size = sizeof(CONFONTRES);
308       break;
309    case R_CONSOLE:
310       size = sizeof(CONRES);
311       break;
312    default:
313       printf(_("Unknown resource type %d\n"), type);
314       error = 1;
315       break;
316    }
317    /* Common */
318    if (!error) {
319       res = (URES *)malloc(size);
320       memcpy(res, &res_all, size);
321       if (!res_head[rindex]) {
322          res_head[rindex] = (RES *)res; /* store first entry */
323       } else {
324          RES *next, *last;
325          /* Add new res to end of chain */
326          for (last=next=res_head[rindex]; next; next=next->next) {
327             last = next;
328             if (strcmp(next->name, res->dir_res.hdr.name) == 0) {
329                Emsg2(M_ERROR_TERM, 0,
330                   _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
331                   resources[rindex].name, res->dir_res.hdr.name);
332             }
333          }
334          last->next = (RES *)res;
335          Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
336                res->dir_res.hdr.name);
337       }
338    }
339 }
340
341 bool parse_bat_config(CONFIG *config, const char *configfile, int exit_code)
342 {
343    config->init(configfile, NULL, exit_code, (void *)&res_all, res_all_size,
344       r_first, r_last, resources, res_head);
345    return config->parse_config();
346 }