]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/bat_conf.cpp
29f2489068870aa2215a17e691d78801e3ca1ff8
[bacula/bacula] / bacula / src / qt-console / bat_conf.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation plus additions
11    that are listed in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *   Main configuration file parser for Bacula User Agent
30  *    some parts may be split into separate files such as
31  *    the schedule configuration (sch_config.c).
32  *
33  *   Note, the configuration file parser consists of three parts
34  *
35  *   1. The generic lexical scanner in lib/lex.c and lib/lex.h
36  *
37  *   2. The generic config  scanner in lib/parse_config.c and
38  *      lib/parse_config.h.
39  *      These files contain the parser code, some utility
40  *      routines, and the common store routines (name, int,
41  *      string).
42  *
43  *   3. The daemon specific file, which contains the Resource
44  *      definitions as well as any specific store routines
45  *      for the resource records.
46  *
47  *     Kern Sibbald, January MM, September MM
48  *
49  *     Version $Id$
50  */
51
52 #include "bacula.h"
53 #include "bat_conf.h"
54
55 /* Define the first and last resource ID record
56  * types. Note, these should be unique for each
57  * daemon though not a requirement.
58  */
59 int r_first = R_FIRST;
60 int r_last  = R_LAST;
61 static RES *sres_head[R_LAST - R_FIRST + 1];
62 RES **res_head = sres_head;
63
64 /* Forward referenced subroutines */
65
66
67 /* We build the current resource here as we are
68  * scanning the resource configuration definition,
69  * then move it to allocated memory when the resource
70  * scan is complete.
71  */
72 URES res_all;
73 int  res_all_size = sizeof(res_all);
74
75 /* Definition of records permitted within each
76  * resource with the routine to process the record
77  * information.
78  */
79 static RES_ITEM dir_items[] = {
80    {"name",        store_name,     ITEM(dir_res.hdr.name), 0, ITEM_REQUIRED, 0},
81    {"description", store_str,      ITEM(dir_res.hdr.desc), 0, 0, 0},
82    {"dirport",     store_int,      ITEM(dir_res.DIRport),  0, ITEM_DEFAULT, 9101},
83    {"address",     store_str,      ITEM(dir_res.address),  0, ITEM_REQUIRED, 0},
84    {"password",    store_password, ITEM(dir_res.password), 0, 0, 0},
85    {"tlsenable",      store_bit,     ITEM(dir_res.tls_enable), 1, 0, 0},
86    {"tlsrequire",     store_bit,     ITEM(dir_res.tls_require), 1, 0, 0},
87    {"tlscacertificatefile", store_dir, ITEM(dir_res.tls_ca_certfile), 0, 0, 0},
88    {"tlscacertificatedir", store_dir,  ITEM(dir_res.tls_ca_certdir), 0, 0, 0},
89    {"tlscertificate", store_dir,       ITEM(dir_res.tls_certfile), 0, 0, 0},
90    {"tlskey",         store_dir,       ITEM(dir_res.tls_keyfile), 0, 0, 0},
91    {"heartbeatinterval", store_time, ITEM(dir_res.heartbeat_interval), 0, ITEM_DEFAULT, 0},
92    {NULL, NULL, {0}, 0, 0, 0}
93 };
94
95 static RES_ITEM con_items[] = {
96    {"name",        store_name,     ITEM(con_res.hdr.name), 0, ITEM_REQUIRED, 0},
97    {"description", store_str,      ITEM(con_res.hdr.desc), 0, 0, 0},
98    {"password",    store_password, ITEM(con_res.password), 0, ITEM_REQUIRED, 0},
99    {"tlsenable",      store_bit,     ITEM(con_res.tls_enable), 1, 0, 0},
100    {"tlsrequire",     store_bit,     ITEM(con_res.tls_require), 1, 0, 0},
101    {"tlscacertificatefile", store_dir, ITEM(con_res.tls_ca_certfile), 0, 0, 0},
102    {"tlscacertificatedir", store_dir,  ITEM(con_res.tls_ca_certdir), 0, 0, 0},
103    {"tlscertificate", store_dir,       ITEM(con_res.tls_certfile), 0, 0, 0},
104    {"tlskey",         store_dir,       ITEM(con_res.tls_keyfile), 0, 0, 0},
105    {"heartbeatinterval", store_time, ITEM(con_res.heartbeat_interval), 0, ITEM_DEFAULT, 0},
106    {NULL, NULL, {0}, 0, 0, 0}
107 };
108
109 static RES_ITEM con_font_items[] = {
110    {"name",        store_name,     ITEM(con_font.hdr.name), 0, ITEM_REQUIRED, 0},
111    {"description", store_str,      ITEM(con_font.hdr.desc), 0, 0, 0},
112    {"font",        store_str,      ITEM(con_font.fontface), 0, 0, 0},
113    {"requiressl",  store_bit,    ITEM(con_font.require_ssl), 1, ITEM_DEFAULT, 0},
114    {NULL, NULL, {0}, 0, 0, 0}
115 };
116
117
118 /*
119  * This is the master resource definition.
120  * It must have one item for each of the resources.
121  */
122 RES_TABLE resources[] = {
123    {"director",      dir_items,   R_DIRECTOR},
124    {"console",       con_items,   R_CONSOLE},
125    {"consolefont",   con_font_items, R_CONSOLE_FONT},
126    {NULL,            NULL,        0}
127 };
128
129
130 /* Dump contents of resource */
131 void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
132 {
133    URES *res = (URES *)reshdr;
134    bool recurse = true;
135
136    if (res == NULL) {
137       printf(_("No record for %d %s\n"), type, res_to_str(type));
138       return;
139    }
140    if (type < 0) {                    /* no recursion */
141       type = - type;
142       recurse = false;
143    }
144    switch (type) {
145    case R_DIRECTOR:
146       printf(_("Director: name=%s address=%s DIRport=%d\n"), reshdr->name,
147               res->dir_res.address, res->dir_res.DIRport);
148       break;
149    case R_CONSOLE:
150       printf(_("Console: name=%s\n"), reshdr->name);
151       break;
152    case R_CONSOLE_FONT:
153       printf(_("ConsoleFont: name=%s font face=%s\n"),
154              reshdr->name, NPRT(res->con_font.fontface));
155       break;
156    default:
157       printf(_("Unknown resource type %d\n"), type);
158    }
159    if (recurse && res->dir_res.hdr.next) {
160       dump_resource(type, res->dir_res.hdr.next, sendit, sock);
161    }
162 }
163
164 /*
165  * Free memory of resource.
166  * NB, we don't need to worry about freeing any references
167  * to other resources as they will be freed when that
168  * resource chain is traversed.  Mainly we worry about freeing
169  * allocated strings (names).
170  */
171 void free_resource(RES *sres, int type)
172 {
173    RES *nres;
174    URES *res = (URES *)sres;
175
176    if (res == NULL)
177       return;
178
179    /* common stuff -- free the resource name */
180    nres = (RES *)res->dir_res.hdr.next;
181    if (res->dir_res.hdr.name) {
182       free(res->dir_res.hdr.name);
183    }
184    if (res->dir_res.hdr.desc) {
185       free(res->dir_res.hdr.desc);
186    }
187
188    switch (type) {
189    case R_DIRECTOR:
190       if (res->dir_res.address) {
191          free(res->dir_res.address);
192       }
193       if (res->dir_res.tls_ctx) { 
194          free_tls_context(res->dir_res.tls_ctx);
195       }
196       if (res->dir_res.tls_ca_certfile) {
197          free(res->dir_res.tls_ca_certfile);
198       }
199       if (res->dir_res.tls_ca_certdir) {
200          free(res->dir_res.tls_ca_certdir);
201       }
202       if (res->dir_res.tls_certfile) {
203          free(res->dir_res.tls_certfile);
204       }
205       if (res->dir_res.tls_keyfile) {
206          free(res->dir_res.tls_keyfile);
207       }
208       break;
209    case R_CONSOLE:
210       if (res->con_res.password) {
211          free(res->con_res.password);
212       }
213       if (res->con_res.tls_ctx) { 
214          free_tls_context(res->con_res.tls_ctx);
215       }
216       if (res->con_res.tls_ca_certfile) {
217          free(res->con_res.tls_ca_certfile);
218       }
219       if (res->con_res.tls_ca_certdir) {
220          free(res->con_res.tls_ca_certdir);
221       }
222       if (res->con_res.tls_certfile) {
223          free(res->con_res.tls_certfile);
224       }
225       if (res->con_res.tls_keyfile) {
226          free(res->con_res.tls_keyfile);
227       }
228       break;
229    case R_CONSOLE_FONT:
230       if (res->con_font.fontface) {
231          free(res->con_font.fontface);
232       }
233       break;
234    default:
235       printf(_("Unknown resource type %d\n"), type);
236    }
237    /* Common stuff again -- free the resource, recurse to next one */
238    free(res);
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 }