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