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 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 RES_HEAD **res_head;
52
53 /* Forward referenced subroutines */
54
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 #if defined(_MSC_VER)
62 extern "C" URES res_all; /* declare as C to avoid name mangling by visual c */
63 #endif
64 URES res_all;
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 static RES_ITEM dir_items[] = {
72 {"name", store_name, ITEM(dir_res.hdr.name), 0, ITEM_REQUIRED, 0},
73 {"description", store_str, ITEM(dir_res.hdr.desc), 0, 0, 0},
74 {"dirport", store_pint32, ITEM(dir_res.DIRport), 0, ITEM_DEFAULT, 9101},
75 {"address", store_str, ITEM(dir_res.address), 0, ITEM_REQUIRED, 0},
76 {"password", store_password, ITEM(dir_res.password), 0, 0, 0},
77 {"tlsauthenticate",store_bool, ITEM(dir_res.tls_authenticate), 0, 0, 0},
78 {"tlsenable", store_bool, ITEM(dir_res.tls_enable), 0, 0, 0},
79 {"tlspskenable", store_bool, ITEM(dir_res.tls_psk_enable), 0, ITEM_DEFAULT, true},
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 {"tlspskenable", store_bool, ITEM(con_res.tls_psk_enable), 0, ITEM_DEFAULT, true},
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 {"CommCompression", store_bool, ITEM(con_res.comm_compression), 0, ITEM_DEFAULT, true},
104 {NULL, NULL, {0}, 0, 0, 0}
105 };
106
107 static RES_ITEM con_font_items[] = {
108 {"name", store_name, ITEM(con_font.hdr.name), 0, ITEM_REQUIRED, 0},
109 {"description", store_str, ITEM(con_font.hdr.desc), 0, 0, 0},
110 {"font", store_str, ITEM(con_font.fontface), 0, 0, 0},
111 {NULL, NULL, {0}, 0, 0, 0}
112 };
113
114
115 /*
116 * This is the master resource definition.
117 * It must have one item for each of the resources.
118 */
119 RES_TABLE resources[] = {
120 {"director", dir_items, R_DIRECTOR},
121 {"console", con_items, R_CONSOLE},
122 {"consolefont", con_font_items, R_CONSOLE_FONT},
123 {NULL, NULL, 0}
124 };
125
126
127 /* Dump contents of resource */
dump_resource(int type,RES * ares,void sendit (void * sock,const char * fmt,...),void * sock)128 void dump_resource(int type, RES *ares, void sendit(void *sock, const char *fmt, ...), void *sock)
129 {
130 RES *next;
131 URES *res = (URES *)ares;
132 bool recurse = true;
133
134 if (res == NULL) {
135 printf(_("No record for %d %s\n"), type, res_to_str(type));
136 return;
137 }
138 if (type < 0) { /* no recursion */
139 type = - type;
140 recurse = false;
141 }
142 switch (type) {
143 case R_DIRECTOR:
144 printf(_("Director: name=%s address=%s DIRport=%d\n"), ares->name,
145 res->dir_res.address, res->dir_res.DIRport);
146 break;
147 case R_CONSOLE:
148 printf(_("Console: name=%s\n"), ares->name);
149 break;
150 case R_CONSOLE_FONT:
151 printf(_("ConsoleFont: name=%s font face=%s\n"),
152 ares->name, NPRT(res->con_font.fontface));
153 break;
154 default:
155 printf(_("Unknown resource type %d\n"), type);
156 }
157 if (recurse) {
158 next = GetNextRes(0, (RES *)res);
159 if (next) {
160 dump_resource(type, next, sendit, sock);
161 }
162 }
163 }
164
165 /*
166 * Free memory of resource.
167 * NB, we don't need to worry about freeing any references
168 * to other resources as they will be freed when that
169 * resource chain is traversed. Mainly we worry about freeing
170 * allocated strings (names).
171 */
free_resource(RES * sres,int type)172 void free_resource(RES *sres, int type)
173 {
174 URES *res = (URES *)sres;
175
176 if (res == NULL)
177 return;
178
179 /* common stuff -- free the resource name */
180 if (res->dir_res.hdr.name) {
181 free(res->dir_res.hdr.name);
182 }
183 if (res->dir_res.hdr.desc) {
184 free(res->dir_res.hdr.desc);
185 }
186
187 switch (type) {
188 case R_DIRECTOR:
189 if (res->dir_res.address) {
190 free(res->dir_res.address);
191 }
192 if (res->dir_res.tls_ctx) {
193 free_tls_context(res->dir_res.tls_ctx);
194 }
195 if (res->dir_res.psk_ctx) {
196 free_psk_context(res->dir_res.psk_ctx);
197 }
198 if (res->dir_res.tls_ca_certfile) {
199 free(res->dir_res.tls_ca_certfile);
200 }
201 if (res->dir_res.tls_ca_certdir) {
202 free(res->dir_res.tls_ca_certdir);
203 }
204 if (res->dir_res.tls_certfile) {
205 free(res->dir_res.tls_certfile);
206 }
207 if (res->dir_res.tls_keyfile) {
208 free(res->dir_res.tls_keyfile);
209 }
210 break;
211 case R_CONSOLE:
212 if (res->con_res.password) {
213 free(res->con_res.password);
214 }
215 if (res->con_res.tls_ctx) {
216 free_tls_context(res->con_res.tls_ctx);
217 }
218 if (res->con_res.psk_ctx) {
219 free_psk_context(res->con_res.psk_ctx);
220 }
221 if (res->con_res.tls_ca_certfile) {
222 free(res->con_res.tls_ca_certfile);
223 }
224 if (res->con_res.tls_ca_certdir) {
225 free(res->con_res.tls_ca_certdir);
226 }
227 if (res->con_res.tls_certfile) {
228 free(res->con_res.tls_certfile);
229 }
230 if (res->con_res.tls_keyfile) {
231 free(res->con_res.tls_keyfile);
232 }
233 if (res->con_res.director) {
234 free(res->con_res.director);
235 }
236 break;
237 case R_CONSOLE_FONT:
238 if (res->con_font.fontface) {
239 free(res->con_font.fontface);
240 }
241 break;
242 default:
243 printf(_("Unknown resource type %d\n"), type);
244 }
245 /* Common stuff again -- free the resource, recurse to next one */
246 if (res) {
247 free(res);
248 }
249 }
250
251 /* Save the new resource by chaining it into the head list for
252 * the resource. If this is pass 2, we update any resource
253 * pointers (currently only in the Job resource).
254 */
save_resource(CONFIG * config,int type,RES_ITEM * items,int pass)255 bool save_resource(CONFIG *config, int type, RES_ITEM *items, int pass)
256 {
257 int rindex = type - r_first;
258 int i, size = 0;
259 int error = 0;
260
261 /*
262 * Ensure that all required items are present
263 */
264 for (i=0; items[i].name; i++) {
265 if (items[i].flags & ITEM_REQUIRED) {
266 if (!bit_is_set(i, res_all.dir_res.hdr.item_present)) {
267 Mmsg(config->m_errmsg, _("\"%s\" directive is required in \"%s\" resource, but not found.\n"),
268 items[i].name, resources[rindex].name);
269 return false;
270 }
271 }
272 }
273
274 /* During pass 2, we looked up pointers to all the resources
275 * referrenced in the current resource, , now we
276 * must copy their address from the static record to the allocated
277 * record.
278 */
279 if (pass == 2) {
280 switch (type) {
281 /* Resources not containing a resource */
282 case R_DIRECTOR:
283 break;
284
285 case R_CONSOLE:
286 case R_CONSOLE_FONT:
287 break;
288
289 default:
290 Emsg1(M_ERROR, 0, _("Unknown resource type %d\n"), type);
291 error = 1;
292 break;
293 }
294 /* Note, the resoure name was already saved during pass 1,
295 * so here, we can just release it.
296 */
297 if (res_all.dir_res.hdr.name) {
298 free(res_all.dir_res.hdr.name);
299 res_all.dir_res.hdr.name = NULL;
300 }
301 if (res_all.dir_res.hdr.desc) {
302 free(res_all.dir_res.hdr.desc);
303 res_all.dir_res.hdr.desc = NULL;
304 }
305 return true;
306 }
307
308 /* The following code is only executed during pass 1 */
309 switch (type) {
310 case R_DIRECTOR:
311 size = sizeof(DIRRES);
312 break;
313 case R_CONSOLE_FONT:
314 size = sizeof(CONFONTRES);
315 break;
316 case R_CONSOLE:
317 size = sizeof(CONRES);
318 break;
319 default:
320 printf(_("Unknown resource type %d\n"), type);
321 error = 1;
322 break;
323 }
324 /* Common */
325 if (!error) {
326 if (!config->insert_res(rindex, size)) {
327 return false;
328 }
329 }
330 return true;
331 }
332
parse_bat_config(CONFIG * config,const char * configfile,int exit_code)333 bool parse_bat_config(CONFIG *config, const char *configfile, int exit_code)
334 {
335 config->init(configfile, NULL, exit_code, (void *)&res_all, res_all_size,
336 r_first, r_last, resources, &res_head);
337 return config->parse_config();
338 }
339