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