]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/console/console_conf.c
1bdda9357e7ee6fb43a27e40d51e1f0aea2d109a
[bacula/bacula] / bacula / src / console / console_conf.c
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 and included
11    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
50 #include "bacula.h"
51 #include "console_conf.h"
52
53 /* Define the first and last resource ID record
54  * types. Note, these should be unique for each
55  * daemon though not a requirement.
56  */
57 int r_first = R_FIRST;
58 int r_last  = R_LAST;
59 static RES *sres_head[R_LAST - R_FIRST + 1];
60 RES **res_head = sres_head;
61
62 /* Forward referenced subroutines */
63
64
65 /* We build the current resource here as we are
66  * scanning the resource configuration definition,
67  * then move it to allocated memory when the resource
68  * scan is complete.
69  */
70 #if defined(_MSC_VER)
71 extern "C" { // work around visual compiler mangling variables
72     URES res_all;
73 }
74 #else
75 URES res_all;
76 #endif
77 int  res_all_size = sizeof(res_all);
78
79 /* Definition of records permitted within each
80  * resource with the routine to process the record
81  * information.
82  */
83
84 /*  Console "globals" */
85 static RES_ITEM cons_items[] = {
86    {"name",           store_name,     ITEM(res_cons.hdr.name), 0, ITEM_REQUIRED, 0},
87    {"description",    store_str,      ITEM(res_cons.hdr.desc), 0, 0, 0},
88    {"rcfile",         store_dir,      ITEM(res_cons.rc_file), 0, 0, 0},
89    {"historyfile",    store_dir,      ITEM(res_cons.hist_file), 0, 0, 0},
90    {"password",       store_password, ITEM(res_cons.password), 0, ITEM_REQUIRED, 0},
91    {"tlsauthenticate",store_bool,    ITEM(res_cons.tls_authenticate), 0, 0, 0},
92    {"tlsenable",      store_bool,    ITEM(res_cons.tls_enable), 0, 0, 0},
93    {"tlsrequire",     store_bool,    ITEM(res_cons.tls_require), 0, 0, 0},
94    {"tlscacertificatefile", store_dir, ITEM(res_cons.tls_ca_certfile), 0, 0, 0},
95    {"tlscacertificatedir", store_dir,  ITEM(res_cons.tls_ca_certdir), 0, 0, 0},
96    {"tlscertificate", store_dir,       ITEM(res_cons.tls_certfile), 0, 0, 0},
97    {"tlskey",         store_dir,       ITEM(res_cons.tls_keyfile), 0, 0, 0},
98    {"director",       store_str,       ITEM(res_cons.director), 0, 0, 0},
99    {"heartbeatinterval", store_time, ITEM(res_cons.heartbeat_interval), 0, ITEM_DEFAULT, 0},
100    {NULL, NULL, {0}, 0, 0, 0}
101 };
102
103
104 /*  Director's that we can contact */
105 static RES_ITEM dir_items[] = {
106    {"name",           store_name,      ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
107    {"description",    store_str,       ITEM(res_dir.hdr.desc), 0, 0, 0},
108    {"dirport",        store_int,       ITEM(res_dir.DIRport),  0, ITEM_DEFAULT, 9101},
109    {"address",        store_str,       ITEM(res_dir.address),  0, 0, 0},
110    {"password",       store_password,  ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
111    {"tlsauthenticate",store_bool,    ITEM(res_dir.tls_enable), 0, 0, 0},
112    {"tlsenable",      store_bool,    ITEM(res_dir.tls_enable), 0, 0, 0},
113    {"tlsrequire",     store_bool,    ITEM(res_dir.tls_require), 0, 0, 0},
114    {"tlscacertificatefile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
115    {"tlscacertificatedir", store_dir,  ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
116    {"tlscertificate", store_dir,       ITEM(res_dir.tls_certfile), 0, 0, 0},
117    {"tlskey",         store_dir,       ITEM(res_dir.tls_keyfile), 0, 0, 0},
118    {"heartbeatinterval", store_time, ITEM(res_dir.heartbeat_interval), 0, ITEM_DEFAULT, 0},
119    {NULL, NULL, {0}, 0, 0, 0}
120 };
121
122 /*
123  * This is the master resource definition.
124  * It must have one item for each of the resources.
125  */
126 RES_TABLE resources[] = {
127    {"console",       cons_items,  R_CONSOLE},
128    {"director",      dir_items,   R_DIRECTOR},
129    {NULL,            NULL,        0}
130 };
131
132
133 /* Dump contents of resource */
134 void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
135 {
136    URES *res = (URES *)reshdr;
137    bool recurse = true;
138
139    if (res == NULL) {
140       printf(_("No record for %d %s\n"), type, res_to_str(type));
141       return;
142    }
143    if (type < 0) {                    /* no recursion */
144       type = - type;
145       recurse = false;
146    }
147    switch (type) {
148    case R_CONSOLE:
149       printf(_("Console: name=%s rcfile=%s histfile=%s\n"), reshdr->name,
150              res->res_cons.rc_file, res->res_cons.hist_file);
151       break;
152    case R_DIRECTOR:
153       printf(_("Director: name=%s address=%s DIRport=%d\n"), reshdr->name,
154               res->res_dir.address, res->res_dir.DIRport);
155       break;
156    default:
157       printf(_("Unknown resource type %d\n"), type);
158    }
159    if (recurse && res->res_dir.hdr.next) {
160       dump_resource(type, res->res_dir.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->res_dir.hdr.next;
181    if (res->res_dir.hdr.name) {
182       free(res->res_dir.hdr.name);
183    }
184    if (res->res_dir.hdr.desc) {
185       free(res->res_dir.hdr.desc);
186    }
187
188    switch (type) {
189    case R_CONSOLE:
190       if (res->res_cons.rc_file) {
191          free(res->res_cons.rc_file);
192       }
193       if (res->res_cons.hist_file) {
194          free(res->res_cons.hist_file);
195       }
196       if (res->res_cons.tls_ctx) { 
197          free_tls_context(res->res_cons.tls_ctx);
198       }
199       if (res->res_cons.tls_ca_certfile) {
200          free(res->res_cons.tls_ca_certfile);
201       }
202       if (res->res_cons.tls_ca_certdir) {
203          free(res->res_cons.tls_ca_certdir);
204       }
205       if (res->res_cons.tls_certfile) {
206          free(res->res_cons.tls_certfile);
207       }
208       if (res->res_cons.tls_keyfile) {
209          free(res->res_cons.tls_keyfile);
210       }
211       break;
212    case R_DIRECTOR:
213       if (res->res_dir.address) {
214          free(res->res_dir.address);
215       }
216       if (res->res_dir.tls_ctx) { 
217          free_tls_context(res->res_dir.tls_ctx);
218       }
219       if (res->res_dir.tls_ca_certfile) {
220          free(res->res_dir.tls_ca_certfile);
221       }
222       if (res->res_dir.tls_ca_certdir) {
223          free(res->res_dir.tls_ca_certdir);
224       }
225       if (res->res_dir.tls_certfile) {
226          free(res->res_dir.tls_certfile);
227       }
228       if (res->res_dir.tls_keyfile) {
229          free(res->res_dir.tls_keyfile);
230       }
231       break;
232    default:
233       printf(_("Unknown resource type %d\n"), type);
234    }
235    /* Common stuff again -- free the resource, recurse to next one */
236    free(res);
237    if (nres) {
238       free_resource(nres, type);
239    }
240 }
241
242 /* Save the new resource by chaining it into the head list for
243  * the resource. If this is pass 2, we update any resource
244  * pointers (currently only in the Job resource).
245  */
246 void save_resource(int type, RES_ITEM *items, int pass)
247 {
248    URES *res;
249    int rindex = type - r_first;
250    int i, size;
251    int error = 0;
252
253    /*
254     * Ensure that all required items are present
255     */
256    for (i=0; items[i].name; i++) {
257       if (items[i].flags & ITEM_REQUIRED) {
258             if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
259                Emsg2(M_ABORT, 0, _("%s item is required in %s resource, but not found.\n"),
260                  items[i].name, resources[rindex]);
261              }
262       }
263    }
264
265    /* During pass 2, we looked up pointers to all the resources
266     * referrenced in the current resource, , now we
267     * must copy their address from the static record to the allocated
268     * record.
269     */
270    if (pass == 2) {
271       switch (type) {
272          /* Resources not containing a resource */
273          case R_CONSOLE:
274          case R_DIRECTOR:
275             break;
276
277          default:
278             Emsg1(M_ERROR, 0, _("Unknown resource type %d\n"), type);
279             error = 1;
280             break;
281       }
282       /* Note, the resoure name was already saved during pass 1,
283        * so here, we can just release it.
284        */
285       if (res_all.res_dir.hdr.name) {
286          free(res_all.res_dir.hdr.name);
287          res_all.res_dir.hdr.name = NULL;
288       }
289       if (res_all.res_dir.hdr.desc) {
290          free(res_all.res_dir.hdr.desc);
291          res_all.res_dir.hdr.desc = NULL;
292       }
293       return;
294    }
295
296    /* The following code is only executed during pass 1 */
297    switch (type) {
298    case R_CONSOLE:
299       size = sizeof(CONRES);
300       break;
301    case R_DIRECTOR:
302       size = sizeof(DIRRES);
303       break;
304    default:
305       printf(_("Unknown resource type %d\n"), type);
306       error = 1;
307       size = 1;
308       break;
309    }
310    /* Common */
311    if (!error) {
312       res = (URES *)malloc(size);
313       memcpy(res, &res_all, size);
314       if (!res_head[rindex]) {
315          res_head[rindex] = (RES *)res; /* store first entry */
316       } else {
317          RES *next, *last;
318          for (last=next=res_head[rindex]; next; next=next->next) {
319             last = next;
320             if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
321                Emsg2(M_ERROR_TERM, 0,
322                   _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
323                   resources[rindex].name, res->res_dir.hdr.name);
324             }
325          }
326          last->next = (RES *)res;
327          Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
328                res->res_dir.hdr.name);
329       }
330    }
331 }