2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
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.
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.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Main configuration file parser for Bacula File Daemon (Client)
22 * some parts may be split into separate files such as
23 * the schedule configuration (sch_config.c).
25 * Note, the configuration file parser consists of three parts
27 * 1. The generic lexical scanner in lib/lex.c and lib/lex.h
29 * 2. The generic config scanner in lib/parse_config.c and
31 * These files contain the parser code, some utility
32 * routines, and the common store routines (name, int,
35 * 3. The daemon specific file, which contains the Resource
36 * definitions as well as any specific store routines
37 * for the resource records.
39 * Kern Sibbald, September MM
46 /* Define the first and last resource ID record
47 * types. Note, these should be unique for each
48 * daemon though not a requirement.
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;
56 /* Forward referenced subroutines */
59 /* We build the current resource here as we are
60 * scanning the resource configuration definition,
61 * then move it to allocated memory when the resource
65 extern "C" { // work around visual compiler mangling variables
71 int32_t res_all_size = sizeof(res_all);
73 /* Forward definition for encyption cipher/digest type */
74 static void store_cipher_type(LEX *lc, RES_ITEM *item, int index, int pass);
75 static void store_digest_type(LEX *lc, RES_ITEM *item, int index, int pass);
77 /* Definition of records permitted within each
78 * resource with the routine to process the record
82 /* Client or File daemon "Global" resources */
83 static RES_ITEM cli_items[] = {
84 {"Name", store_name, ITEM(res_client.hdr.name), 0, ITEM_REQUIRED, 0},
85 {"Description", store_str, ITEM(res_client.hdr.desc), 0, 0, 0},
86 {"FdPort", store_addresses_port, ITEM(res_client.FDaddrs), 0, ITEM_DEFAULT, 9102},
87 {"FdAddress", store_addresses_address, ITEM(res_client.FDaddrs), 0, ITEM_DEFAULT, 9102},
88 {"FdAddresses", store_addresses, ITEM(res_client.FDaddrs), 0, ITEM_DEFAULT, 9102},
89 {"FdSourceAddress", store_addresses_address, ITEM(res_client.FDsrc_addr), 0, ITEM_DEFAULT, 0},
91 {"WorkingDirectory", store_dir, ITEM(res_client.working_directory), 0, ITEM_REQUIRED, 0},
92 {"PidDirectory", store_dir, ITEM(res_client.pid_directory), 0, ITEM_REQUIRED, 0},
93 {"SubsysDirectory", store_dir, ITEM(res_client.subsys_directory), 0, 0, 0},
94 {"PluginDirectory", store_dir, ITEM(res_client.plugin_directory), 0, 0, 0},
95 {"SnapshotCommand", store_str, ITEM(res_client.snapshot_command), 0, 0, 0},
96 {"ScriptsDirectory", store_dir, ITEM(res_client.scripts_directory), 0, 0, 0},
97 {"MaximumConcurrentJobs", store_pint32, ITEM(res_client.MaxConcurrentJobs), 0, ITEM_DEFAULT, 20},
98 {"Messages", store_res, ITEM(res_client.messages), R_MSGS, 0, 0},
99 {"SdConnectTimeout", store_time,ITEM(res_client.SDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
100 {"HeartbeatInterval", store_time, ITEM(res_client.heartbeat_interval), 0, ITEM_DEFAULT, 5 * 60},
101 {"MaximumNetWorkBufferSize", store_pint32, ITEM(res_client.max_network_buffer_size), 0, 0, 0},
102 #ifdef DATA_ENCRYPTION
103 {"PkiSignatures", store_bool, ITEM(res_client.pki_sign), 0, ITEM_DEFAULT, 0},
104 {"PkiEncryption", store_bool, ITEM(res_client.pki_encrypt), 0, ITEM_DEFAULT, 0},
105 {"PkiKeyPair", store_dir, ITEM(res_client.pki_keypair_file), 0, 0, 0},
106 {"PkiSigner", store_alist_str, ITEM(res_client.pki_signing_key_files), 0, 0, 0},
107 {"PkiMasterKey", store_alist_str, ITEM(res_client.pki_master_key_files), 0, 0, 0},
108 {"PkiCipher", store_cipher_type, ITEM(res_client.pki_cipher), 0, 0, 0},
109 {"PkiDigest", store_digest_type, ITEM(res_client.pki_digest), 0, 0, 0},
111 {"TlsAuthenticate", store_bool, ITEM(res_client.tls_authenticate), 0, 0, 0},
112 {"TlsEnable", store_bool, ITEM(res_client.tls_enable), 0, 0, 0},
113 {"TlsRequire", store_bool, ITEM(res_client.tls_require), 0, 0, 0},
114 {"TlsCaCertificateFile", store_dir, ITEM(res_client.tls_ca_certfile), 0, 0, 0},
115 {"TlsCaCertificateDir", store_dir, ITEM(res_client.tls_ca_certdir), 0, 0, 0},
116 {"TlsCertificate", store_dir, ITEM(res_client.tls_certfile), 0, 0, 0},
117 {"TlsKey", store_dir, ITEM(res_client.tls_keyfile), 0, 0, 0},
118 {"VerId", store_str, ITEM(res_client.verid), 0, 0, 0},
119 {"MaximumBandwidthPerJob",store_speed, ITEM(res_client.max_bandwidth_per_job), 0, 0, 0},
120 {"DisableCommand", store_alist_str, ITEM(res_client.disable_cmds), 0, 0, 0},
121 {NULL, NULL, {0}, 0, 0, 0}
124 /* Directors that can use our services */
125 static RES_ITEM dir_items[] = {
126 {"Name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
127 {"Description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
128 {"Password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
129 {"Address", store_str, ITEM(res_dir.address), 0, 0, 0},
130 {"Monitor", store_bool, ITEM(res_dir.monitor), 0, ITEM_DEFAULT, 0},
131 {"TlsAuthenticate", store_bool, ITEM(res_dir.tls_authenticate), 0, 0, 0},
132 {"TlsEnable", store_bool, ITEM(res_dir.tls_enable), 0, 0, 0},
133 {"TlsRequire", store_bool, ITEM(res_dir.tls_require), 0, 0, 0},
134 {"TlsVerifyPeer", store_bool, ITEM(res_dir.tls_verify_peer), 0, ITEM_DEFAULT, 1},
135 {"TlsCaCertificateFile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
136 {"TlsCaCertificateDir", store_dir, ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
137 {"TlsCertificate", store_dir, ITEM(res_dir.tls_certfile), 0, 0, 0},
138 {"TlsKey", store_dir, ITEM(res_dir.tls_keyfile), 0, 0, 0},
139 {"TlsDhFile", store_dir, ITEM(res_dir.tls_dhfile), 0, 0, 0},
140 {"TlsAllowedCn", store_alist_str, ITEM(res_dir.tls_allowed_cns), 0, 0, 0},
141 {"MaximumBandwidthPerJob", store_speed, ITEM(res_dir.max_bandwidth_per_job), 0, 0, 0},
142 {"DisableCommand", store_alist_str, ITEM(res_dir.disable_cmds), 0, 0, 0},
143 {NULL, NULL, {0}, 0, 0, 0}
146 /* Message resource */
147 extern RES_ITEM msgs_items[];
150 * This is the master resource definition.
151 * It must have one item for each of the resources.
153 RES_TABLE resources[] = {
154 {"Director", dir_items, R_DIRECTOR},
155 {"FileDaemon", cli_items, R_CLIENT},
156 {"Messages", msgs_items, R_MSGS},
157 {"Client", cli_items, R_CLIENT}, /* alias for filedaemon */
161 /* Cipher/Digest keyword structure */
163 const char *type_name;
167 struct s_ct ciphertypes[] = {
168 {"aes128", CRYPTO_CIPHER_AES_128_CBC},
169 {"aes192", CRYPTO_CIPHER_AES_192_CBC},
170 {"aes256", CRYPTO_CIPHER_AES_256_CBC},
171 {"blowfish", CRYPTO_CIPHER_BLOWFISH_CBC},
175 struct s_ct digesttypes[] = {
176 {"md5", CRYPTO_DIGEST_MD5},
177 {"sha1", CRYPTO_DIGEST_SHA1},
178 {"sha256", CRYPTO_DIGEST_SHA256},
179 // {"sha512", CRYPTO_DIGEST_SHA512}, /* Not working yet */
187 static void store_cipher_type(LEX *lc, RES_ITEM *item, int index, int pass)
191 lex_get_token(lc, T_NAME);
192 /* Store the type both pass 1 and pass 2 */
193 for (i=0; ciphertypes[i].type_name; i++) {
194 if (strcasecmp(lc->str, ciphertypes[i].type_name) == 0) {
195 *(uint32_t *)(item->value) = ciphertypes[i].type_value;
201 scan_err1(lc, _("Expected a Cipher Type keyword, got: %s"), lc->str);
204 set_bit(index, res_all.hdr.item_present);
211 static void store_digest_type(LEX *lc, RES_ITEM *item, int index, int pass)
215 lex_get_token(lc, T_NAME);
216 /* Store the type both pass 1 and pass 2 */
217 for (i=0; digesttypes[i].type_name; i++) {
218 if (strcasecmp(lc->str, digesttypes[i].type_name) == 0) {
219 *(uint32_t *)(item->value) = digesttypes[i].type_value;
225 scan_err1(lc, _("Expected a Cipher Type keyword, got: %s"), lc->str);
228 set_bit(index, res_all.hdr.item_present);
231 /* Dump contents of resource */
232 void dump_resource(int type, RES *ares, void sendit(void *sock, const char *fmt, ...), void *sock)
234 URES *res = (URES *)ares;
238 sendit(sock, "No record for %d %s\n", type, res_to_str(type));
241 if (type < 0) { /* no recursion */
247 sendit(sock, "Director: name=%s password=%s\n", ares->name,
248 res->res_dir.password);
251 sendit(sock, "Client: name=%s FDport=%d\n", ares->name,
252 get_first_port_host_order(res->res_client.FDaddrs));
255 sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
256 if (res->res_msgs.mail_cmd)
257 sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
258 if (res->res_msgs.operator_cmd)
259 sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
262 sendit(sock, "Unknown resource type %d\n", type);
264 ares = GetNextRes(type, ares);
265 if (recurse && res->res_dir.hdr.next) {
266 dump_resource(type, res->res_dir.hdr.next, sendit, sock);
272 * Free memory of resource.
273 * NB, we don't need to worry about freeing any references
274 * to other resources as they will be freed when that
275 * resource chain is traversed. Mainly we worry about freeing
276 * allocated strings (names).
278 void free_resource(RES *sres, int type)
281 URES *res = (URES *)sres;
287 /* common stuff -- free the resource name */
288 nres = (RES *)res->res_dir.hdr.next;
289 if (res->res_dir.hdr.name) {
290 free(res->res_dir.hdr.name);
292 if (res->res_dir.hdr.desc) {
293 free(res->res_dir.hdr.desc);
297 if (res->res_dir.password) {
298 free(res->res_dir.password);
300 if (res->res_dir.address) {
301 free(res->res_dir.address);
303 if (res->res_dir.tls_ctx) {
304 free_tls_context(res->res_dir.tls_ctx);
306 if (res->res_dir.tls_ca_certfile) {
307 free(res->res_dir.tls_ca_certfile);
309 if (res->res_dir.tls_ca_certdir) {
310 free(res->res_dir.tls_ca_certdir);
312 if (res->res_dir.tls_certfile) {
313 free(res->res_dir.tls_certfile);
315 if (res->res_dir.tls_keyfile) {
316 free(res->res_dir.tls_keyfile);
318 if (res->res_dir.tls_dhfile) {
319 free(res->res_dir.tls_dhfile);
321 if (res->res_dir.tls_allowed_cns) {
322 delete res->res_dir.tls_allowed_cns;
324 if (res->res_dir.disable_cmds) {
325 delete res->res_dir.disable_cmds;
327 if (res->res_dir.disabled_cmds_array) {
328 free(res->res_dir.disabled_cmds_array);
332 if (res->res_client.working_directory) {
333 free(res->res_client.working_directory);
335 if (res->res_client.pid_directory) {
336 free(res->res_client.pid_directory);
338 if (res->res_client.subsys_directory) {
339 free(res->res_client.subsys_directory);
341 if (res->res_client.scripts_directory) {
342 free(res->res_client.scripts_directory);
344 if (res->res_client.plugin_directory) {
345 free(res->res_client.plugin_directory);
347 if (res->res_client.FDaddrs) {
348 free_addresses(res->res_client.FDaddrs);
350 if (res->res_client.FDsrc_addr) {
351 free_addresses(res->res_client.FDsrc_addr);
353 if (res->res_client.snapshot_command) {
354 free(res->res_client.snapshot_command);
356 if (res->res_client.pki_keypair_file) {
357 free(res->res_client.pki_keypair_file);
359 if (res->res_client.pki_keypair) {
360 crypto_keypair_free(res->res_client.pki_keypair);
363 if (res->res_client.pki_signing_key_files) {
364 delete res->res_client.pki_signing_key_files;
366 if (res->res_client.pki_signers) {
367 X509_KEYPAIR *keypair;
368 foreach_alist(keypair, res->res_client.pki_signers) {
369 crypto_keypair_free(keypair);
371 delete res->res_client.pki_signers;
374 if (res->res_client.pki_master_key_files) {
375 delete res->res_client.pki_master_key_files;
378 if (res->res_client.pki_recipients) {
379 X509_KEYPAIR *keypair;
380 foreach_alist(keypair, res->res_client.pki_recipients) {
381 crypto_keypair_free(keypair);
383 delete res->res_client.pki_recipients;
386 if (res->res_client.tls_ctx) {
387 free_tls_context(res->res_client.tls_ctx);
389 if (res->res_client.tls_ca_certfile) {
390 free(res->res_client.tls_ca_certfile);
392 if (res->res_client.tls_ca_certdir) {
393 free(res->res_client.tls_ca_certdir);
395 if (res->res_client.tls_certfile) {
396 free(res->res_client.tls_certfile);
398 if (res->res_client.tls_keyfile) {
399 free(res->res_client.tls_keyfile);
401 if (res->res_client.disable_cmds) {
402 delete res->res_client.disable_cmds;
404 if (res->res_client.disabled_cmds_array) {
405 free(res->res_client.disabled_cmds_array);
407 if (res->res_client.verid) {
408 free(res->res_client.verid);
412 if (res->res_msgs.mail_cmd) {
413 free(res->res_msgs.mail_cmd);
415 if (res->res_msgs.operator_cmd) {
416 free(res->res_msgs.operator_cmd);
418 free_msgs_res((MSGS *)res); /* free message resource */
422 printf(_("Unknown resource type %d\n"), type);
424 /* Common stuff again -- free the resource, recurse to next one */
429 free_resource(nres, type);
433 /* Save the new resource by chaining it into the head list for
434 * the resource. If this is pass 2, we update any resource
435 * pointers (currently only in the Job resource).
437 void save_resource(int type, RES_ITEM *items, int pass)
440 int rindex = type - r_first;
445 * Ensure that all required items are present
447 for (i=0; items[i].name; i++) {
448 if (items[i].flags & ITEM_REQUIRED) {
449 if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
450 Emsg2(M_ERROR_TERM, 0, _("%s item is required in %s resource, but not found.\n"),
451 items[i].name, resources[rindex]);
456 /* During pass 2, we looked up pointers to all the resources
457 * referrenced in the current resource, , now we
458 * must copy their address from the static record to the allocated
463 /* Resources not containing a resource */
467 /* Resources containing another resource */
469 if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
470 Emsg1(M_ABORT, 0, _("Cannot find Director resource %s\n"), res_all.res_dir.hdr.name);
472 res->res_dir.tls_allowed_cns = res_all.res_dir.tls_allowed_cns;
473 res->res_dir.disable_cmds = res_all.res_dir.disable_cmds;
476 if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_dir.hdr.name)) == NULL) {
477 Emsg1(M_ABORT, 0, _("Cannot find Client resource %s\n"), res_all.res_dir.hdr.name);
479 res->res_client.pki_signing_key_files = res_all.res_client.pki_signing_key_files;
480 res->res_client.pki_master_key_files = res_all.res_client.pki_master_key_files;
482 res->res_client.pki_signers = res_all.res_client.pki_signers;
483 res->res_client.pki_recipients = res_all.res_client.pki_recipients;
485 res->res_client.messages = res_all.res_client.messages;
486 res->res_client.disable_cmds = res_all.res_client.disable_cmds;
489 Emsg1(M_ERROR, 0, _("Unknown resource type %d\n"), type);
493 /* Note, the resoure name was already saved during pass 1,
494 * so here, we can just release it.
496 if (res_all.res_dir.hdr.name) {
497 free(res_all.res_dir.hdr.name);
498 res_all.res_dir.hdr.name = NULL;
500 if (res_all.res_dir.hdr.desc) {
501 free(res_all.res_dir.hdr.desc);
502 res_all.res_dir.hdr.desc = NULL;
507 /* The following code is only executed on pass 1 */
510 size = sizeof(DIRRES);
513 size = sizeof(CLIENT);
519 printf(_("Unknown resource type %d\n"), type);
526 res = (URES *)malloc(size);
527 memcpy(res, &res_all, size);
528 if (!res_head[rindex]) {
529 res_head[rindex] = (RES *)res; /* store first entry */
532 /* Add new res to end of chain */
533 for (last=next=res_head[rindex]; next; next=next->next) {
535 if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
536 Emsg2(M_ERROR_TERM, 0,
537 _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
538 resources[rindex].name, res->res_dir.hdr.name);
541 last->next = (RES *)res;
542 Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
543 res->res_dir.hdr.name);
548 bool parse_fd_config(CONFIG *config, const char *configfile, int exit_code)
550 config->init(configfile, NULL, exit_code, (void *)&res_all, res_all_size,
551 r_first, r_last, resources, res_head);
552 return config->parse_config();