1*aa772005SRobert Watson %{
2*aa772005SRobert Watson /*-
3*aa772005SRobert Watson * Copyright (c) 2012 The FreeBSD Foundation
4*aa772005SRobert Watson * All rights reserved.
5*aa772005SRobert Watson *
6*aa772005SRobert Watson * This software was developed by Pawel Jakub Dawidek under sponsorship from
7*aa772005SRobert Watson * the FreeBSD Foundation.
8*aa772005SRobert Watson *
9*aa772005SRobert Watson * Redistribution and use in source and binary forms, with or without
10*aa772005SRobert Watson * modification, are permitted provided that the following conditions
11*aa772005SRobert Watson * are met:
12*aa772005SRobert Watson * 1. Redistributions of source code must retain the above copyright
13*aa772005SRobert Watson * notice, this list of conditions and the following disclaimer.
14*aa772005SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright
15*aa772005SRobert Watson * notice, this list of conditions and the following disclaimer in the
16*aa772005SRobert Watson * documentation and/or other materials provided with the distribution.
17*aa772005SRobert Watson *
18*aa772005SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19*aa772005SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*aa772005SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*aa772005SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22*aa772005SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*aa772005SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*aa772005SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*aa772005SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*aa772005SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*aa772005SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*aa772005SRobert Watson * SUCH DAMAGE.
29*aa772005SRobert Watson */
30*aa772005SRobert Watson
31*aa772005SRobert Watson #include <config/config.h>
32*aa772005SRobert Watson
33*aa772005SRobert Watson #include <sys/types.h>
34*aa772005SRobert Watson #include <sys/queue.h>
35*aa772005SRobert Watson #include <sys/sysctl.h>
36*aa772005SRobert Watson
37*aa772005SRobert Watson #include <arpa/inet.h>
38*aa772005SRobert Watson
39*aa772005SRobert Watson #include <err.h>
40*aa772005SRobert Watson #include <errno.h>
41*aa772005SRobert Watson #include <stdio.h>
42*aa772005SRobert Watson #include <string.h>
43*aa772005SRobert Watson #include <sysexits.h>
44*aa772005SRobert Watson #include <unistd.h>
45*aa772005SRobert Watson #ifndef HAVE_STRLCPY
46*aa772005SRobert Watson #include <compat/strlcpy.h>
47*aa772005SRobert Watson #endif
48*aa772005SRobert Watson
49*aa772005SRobert Watson #include "auditdistd.h"
50*aa772005SRobert Watson #include "pjdlog.h"
51*aa772005SRobert Watson
52*aa772005SRobert Watson extern int depth;
53*aa772005SRobert Watson extern int lineno;
54*aa772005SRobert Watson
55*aa772005SRobert Watson extern FILE *yyin;
56*aa772005SRobert Watson extern char *yytext;
57*aa772005SRobert Watson
58*aa772005SRobert Watson static struct adist_config *lconfig;
59*aa772005SRobert Watson static struct adist_host *curhost;
60*aa772005SRobert Watson #define SECTION_GLOBAL 0
61*aa772005SRobert Watson #define SECTION_SENDER 1
62*aa772005SRobert Watson #define SECTION_RECEIVER 2
63*aa772005SRobert Watson static int cursection;
64*aa772005SRobert Watson
65*aa772005SRobert Watson /* Sender section. */
66*aa772005SRobert Watson static char depth1_source[ADIST_ADDRSIZE];
67*aa772005SRobert Watson static int depth1_checksum;
68*aa772005SRobert Watson static int depth1_compression;
69*aa772005SRobert Watson /* Sender and receiver sections. */
70*aa772005SRobert Watson static char depth1_directory[PATH_MAX];
71*aa772005SRobert Watson
72*aa772005SRobert Watson static bool adjust_directory(char *path);
73*aa772005SRobert Watson static bool family_supported(int family);
74*aa772005SRobert Watson
75*aa772005SRobert Watson extern void yyrestart(FILE *);
76*aa772005SRobert Watson %}
77*aa772005SRobert Watson
78*aa772005SRobert Watson %token CB
79*aa772005SRobert Watson %token CERTFILE
80*aa772005SRobert Watson %token DIRECTORY
81*aa772005SRobert Watson %token FINGERPRINT
82*aa772005SRobert Watson %token HOST
83*aa772005SRobert Watson %token KEYFILE
84*aa772005SRobert Watson %token LISTEN
85*aa772005SRobert Watson %token NAME
86*aa772005SRobert Watson %token OB
87*aa772005SRobert Watson %token PASSWORD
88*aa772005SRobert Watson %token PIDFILE
89*aa772005SRobert Watson %token RECEIVER REMOTE
90*aa772005SRobert Watson %token SENDER SOURCE
91*aa772005SRobert Watson %token TIMEOUT
92*aa772005SRobert Watson
93*aa772005SRobert Watson /*
94*aa772005SRobert Watson %type <num> checksum_type
95*aa772005SRobert Watson %type <num> compression_type
96*aa772005SRobert Watson */
97*aa772005SRobert Watson
98*aa772005SRobert Watson %union
99*aa772005SRobert Watson {
100*aa772005SRobert Watson int num;
101*aa772005SRobert Watson char *str;
102*aa772005SRobert Watson }
103*aa772005SRobert Watson
104*aa772005SRobert Watson %token <num> NUM
105*aa772005SRobert Watson %token <str> STR
106*aa772005SRobert Watson
107*aa772005SRobert Watson %%
108*aa772005SRobert Watson
109*aa772005SRobert Watson statements:
110*aa772005SRobert Watson |
111*aa772005SRobert Watson statements statement
112*aa772005SRobert Watson ;
113*aa772005SRobert Watson
114*aa772005SRobert Watson statement:
115*aa772005SRobert Watson name_statement
116*aa772005SRobert Watson |
117*aa772005SRobert Watson pidfile_statement
118*aa772005SRobert Watson |
119*aa772005SRobert Watson timeout_statement
120*aa772005SRobert Watson |
121*aa772005SRobert Watson sender_statement
122*aa772005SRobert Watson |
123*aa772005SRobert Watson receiver_statement
124*aa772005SRobert Watson ;
125*aa772005SRobert Watson
126*aa772005SRobert Watson name_statement: NAME STR
127*aa772005SRobert Watson {
128*aa772005SRobert Watson PJDLOG_RASSERT(depth == 0,
129*aa772005SRobert Watson "The name variable can only be specificed in the global section.");
130*aa772005SRobert Watson
131*aa772005SRobert Watson if (lconfig->adc_name[0] != '\0') {
132*aa772005SRobert Watson pjdlog_error("The name variable is specified twice.");
133*aa772005SRobert Watson free($2);
134*aa772005SRobert Watson return (1);
135*aa772005SRobert Watson }
136*aa772005SRobert Watson if (strlcpy(lconfig->adc_name, $2,
137*aa772005SRobert Watson sizeof(lconfig->adc_name)) >=
138*aa772005SRobert Watson sizeof(lconfig->adc_name)) {
139*aa772005SRobert Watson pjdlog_error("The name value is too long.");
140*aa772005SRobert Watson free($2);
141*aa772005SRobert Watson return (1);
142*aa772005SRobert Watson }
143*aa772005SRobert Watson free($2);
144*aa772005SRobert Watson }
145*aa772005SRobert Watson ;
146*aa772005SRobert Watson
147*aa772005SRobert Watson pidfile_statement: PIDFILE STR
148*aa772005SRobert Watson {
149*aa772005SRobert Watson PJDLOG_RASSERT(depth == 0,
150*aa772005SRobert Watson "The pidfile variable can only be specificed in the global section.");
151*aa772005SRobert Watson
152*aa772005SRobert Watson if (lconfig->adc_pidfile[0] != '\0') {
153*aa772005SRobert Watson pjdlog_error("The pidfile variable is specified twice.");
154*aa772005SRobert Watson free($2);
155*aa772005SRobert Watson return (1);
156*aa772005SRobert Watson }
157*aa772005SRobert Watson if (strcmp($2, "none") != 0 && $2[0] != '/') {
158*aa772005SRobert Watson pjdlog_error("The pidfile variable must be set to absolute pathname or \"none\".");
159*aa772005SRobert Watson free($2);
160*aa772005SRobert Watson return (1);
161*aa772005SRobert Watson }
162*aa772005SRobert Watson if (strlcpy(lconfig->adc_pidfile, $2,
163*aa772005SRobert Watson sizeof(lconfig->adc_pidfile)) >=
164*aa772005SRobert Watson sizeof(lconfig->adc_pidfile)) {
165*aa772005SRobert Watson pjdlog_error("The pidfile value is too long.");
166*aa772005SRobert Watson free($2);
167*aa772005SRobert Watson return (1);
168*aa772005SRobert Watson }
169*aa772005SRobert Watson free($2);
170*aa772005SRobert Watson }
171*aa772005SRobert Watson ;
172*aa772005SRobert Watson
173*aa772005SRobert Watson timeout_statement: TIMEOUT NUM
174*aa772005SRobert Watson {
175*aa772005SRobert Watson PJDLOG_ASSERT(depth == 0);
176*aa772005SRobert Watson
177*aa772005SRobert Watson lconfig->adc_timeout = $2;
178*aa772005SRobert Watson }
179*aa772005SRobert Watson ;
180*aa772005SRobert Watson
181*aa772005SRobert Watson sender_statement: SENDER sender_start sender_entries CB
182*aa772005SRobert Watson {
183*aa772005SRobert Watson PJDLOG_ASSERT(depth == 0);
184*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_SENDER);
185*aa772005SRobert Watson
186*aa772005SRobert Watson /* Configure defaults. */
187*aa772005SRobert Watson if (depth1_checksum == -1)
188*aa772005SRobert Watson depth1_checksum = ADIST_CHECKSUM_NONE;
189*aa772005SRobert Watson if (depth1_compression == -1)
190*aa772005SRobert Watson depth1_compression = ADIST_COMPRESSION_NONE;
191*aa772005SRobert Watson if (depth1_directory[0] == '\0') {
192*aa772005SRobert Watson (void)strlcpy(depth1_directory, ADIST_DIRECTORY_SENDER,
193*aa772005SRobert Watson sizeof(depth1_directory));
194*aa772005SRobert Watson }
195*aa772005SRobert Watson /* Empty depth1_source is ok. */
196*aa772005SRobert Watson TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
197*aa772005SRobert Watson if (curhost->adh_role != ADIST_ROLE_SENDER)
198*aa772005SRobert Watson continue;
199*aa772005SRobert Watson if (curhost->adh_checksum == -1)
200*aa772005SRobert Watson curhost->adh_checksum = depth1_checksum;
201*aa772005SRobert Watson if (curhost->adh_compression == -1)
202*aa772005SRobert Watson curhost->adh_compression = depth1_compression;
203*aa772005SRobert Watson if (curhost->adh_directory[0] == '\0') {
204*aa772005SRobert Watson (void)strlcpy(curhost->adh_directory,
205*aa772005SRobert Watson depth1_directory,
206*aa772005SRobert Watson sizeof(curhost->adh_directory));
207*aa772005SRobert Watson }
208*aa772005SRobert Watson if (curhost->adh_localaddr[0] == '\0') {
209*aa772005SRobert Watson (void)strlcpy(curhost->adh_localaddr,
210*aa772005SRobert Watson depth1_source,
211*aa772005SRobert Watson sizeof(curhost->adh_localaddr));
212*aa772005SRobert Watson }
213*aa772005SRobert Watson }
214*aa772005SRobert Watson cursection = SECTION_GLOBAL;
215*aa772005SRobert Watson }
216*aa772005SRobert Watson ;
217*aa772005SRobert Watson
218*aa772005SRobert Watson sender_start: OB
219*aa772005SRobert Watson {
220*aa772005SRobert Watson PJDLOG_ASSERT(depth == 1);
221*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_GLOBAL);
222*aa772005SRobert Watson
223*aa772005SRobert Watson cursection = SECTION_SENDER;
224*aa772005SRobert Watson depth1_checksum = -1;
225*aa772005SRobert Watson depth1_compression = -1;
226*aa772005SRobert Watson depth1_source[0] = '\0';
227*aa772005SRobert Watson depth1_directory[0] = '\0';
228*aa772005SRobert Watson
229*aa772005SRobert Watson #ifndef HAVE_AUDIT_SYSCALLS
230*aa772005SRobert Watson pjdlog_error("Sender functionality is not available.");
231*aa772005SRobert Watson return (1);
232*aa772005SRobert Watson #endif
233*aa772005SRobert Watson }
234*aa772005SRobert Watson ;
235*aa772005SRobert Watson
236*aa772005SRobert Watson sender_entries:
237*aa772005SRobert Watson |
238*aa772005SRobert Watson sender_entries sender_entry
239*aa772005SRobert Watson ;
240*aa772005SRobert Watson
241*aa772005SRobert Watson sender_entry:
242*aa772005SRobert Watson source_statement
243*aa772005SRobert Watson |
244*aa772005SRobert Watson directory_statement
245*aa772005SRobert Watson /*
246*aa772005SRobert Watson |
247*aa772005SRobert Watson checksum_statement
248*aa772005SRobert Watson |
249*aa772005SRobert Watson compression_statement
250*aa772005SRobert Watson */
251*aa772005SRobert Watson |
252*aa772005SRobert Watson sender_host_statement
253*aa772005SRobert Watson ;
254*aa772005SRobert Watson
255*aa772005SRobert Watson receiver_statement: RECEIVER receiver_start receiver_entries CB
256*aa772005SRobert Watson {
257*aa772005SRobert Watson PJDLOG_ASSERT(depth == 0);
258*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
259*aa772005SRobert Watson
260*aa772005SRobert Watson /*
261*aa772005SRobert Watson * If not listen addresses were specified,
262*aa772005SRobert Watson * configure default ones.
263*aa772005SRobert Watson */
264*aa772005SRobert Watson if (TAILQ_EMPTY(&lconfig->adc_listen)) {
265*aa772005SRobert Watson struct adist_listen *lst;
266*aa772005SRobert Watson
267*aa772005SRobert Watson if (family_supported(AF_INET)) {
268*aa772005SRobert Watson lst = calloc(1, sizeof(*lst));
269*aa772005SRobert Watson if (lst == NULL) {
270*aa772005SRobert Watson pjdlog_error("Unable to allocate memory for listen address.");
271*aa772005SRobert Watson return (1);
272*aa772005SRobert Watson }
273*aa772005SRobert Watson (void)strlcpy(lst->adl_addr,
274*aa772005SRobert Watson ADIST_LISTEN_TLS_TCP4,
275*aa772005SRobert Watson sizeof(lst->adl_addr));
276*aa772005SRobert Watson TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
277*aa772005SRobert Watson } else {
278*aa772005SRobert Watson pjdlog_debug(1,
279*aa772005SRobert Watson "No IPv4 support in the kernel, not listening on IPv4 address.");
280*aa772005SRobert Watson }
281*aa772005SRobert Watson if (family_supported(AF_INET6)) {
282*aa772005SRobert Watson lst = calloc(1, sizeof(*lst));
283*aa772005SRobert Watson if (lst == NULL) {
284*aa772005SRobert Watson pjdlog_error("Unable to allocate memory for listen address.");
285*aa772005SRobert Watson return (1);
286*aa772005SRobert Watson }
287*aa772005SRobert Watson (void)strlcpy(lst->adl_addr,
288*aa772005SRobert Watson ADIST_LISTEN_TLS_TCP6,
289*aa772005SRobert Watson sizeof(lst->adl_addr));
290*aa772005SRobert Watson TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
291*aa772005SRobert Watson } else {
292*aa772005SRobert Watson pjdlog_debug(1,
293*aa772005SRobert Watson "No IPv6 support in the kernel, not listening on IPv6 address.");
294*aa772005SRobert Watson }
295*aa772005SRobert Watson if (TAILQ_EMPTY(&lconfig->adc_listen)) {
296*aa772005SRobert Watson pjdlog_error("No address to listen on.");
297*aa772005SRobert Watson return (1);
298*aa772005SRobert Watson }
299*aa772005SRobert Watson }
300*aa772005SRobert Watson /* Configure defaults. */
301*aa772005SRobert Watson if (depth1_directory[0] == '\0') {
302*aa772005SRobert Watson (void)strlcpy(depth1_directory,
303*aa772005SRobert Watson ADIST_DIRECTORY_RECEIVER,
304*aa772005SRobert Watson sizeof(depth1_directory));
305*aa772005SRobert Watson }
306*aa772005SRobert Watson TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
307*aa772005SRobert Watson if (curhost->adh_role != ADIST_ROLE_RECEIVER)
308*aa772005SRobert Watson continue;
309*aa772005SRobert Watson if (curhost->adh_directory[0] == '\0') {
310*aa772005SRobert Watson if (snprintf(curhost->adh_directory,
311*aa772005SRobert Watson sizeof(curhost->adh_directory), "%s/%s",
312*aa772005SRobert Watson depth1_directory, curhost->adh_name) >=
313*aa772005SRobert Watson (ssize_t)sizeof(curhost->adh_directory)) {
314*aa772005SRobert Watson pjdlog_error("Directory value is too long.");
315*aa772005SRobert Watson return (1);
316*aa772005SRobert Watson }
317*aa772005SRobert Watson }
318*aa772005SRobert Watson }
319*aa772005SRobert Watson cursection = SECTION_GLOBAL;
320*aa772005SRobert Watson }
321*aa772005SRobert Watson ;
322*aa772005SRobert Watson
323*aa772005SRobert Watson receiver_start: OB
324*aa772005SRobert Watson {
325*aa772005SRobert Watson PJDLOG_ASSERT(depth == 1);
326*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_GLOBAL);
327*aa772005SRobert Watson
328*aa772005SRobert Watson cursection = SECTION_RECEIVER;
329*aa772005SRobert Watson depth1_directory[0] = '\0';
330*aa772005SRobert Watson }
331*aa772005SRobert Watson ;
332*aa772005SRobert Watson
333*aa772005SRobert Watson receiver_entries:
334*aa772005SRobert Watson |
335*aa772005SRobert Watson receiver_entries receiver_entry
336*aa772005SRobert Watson ;
337*aa772005SRobert Watson
338*aa772005SRobert Watson receiver_entry:
339*aa772005SRobert Watson listen_statement
340*aa772005SRobert Watson |
341*aa772005SRobert Watson directory_statement
342*aa772005SRobert Watson |
343*aa772005SRobert Watson certfile_statement
344*aa772005SRobert Watson |
345*aa772005SRobert Watson keyfile_statement
346*aa772005SRobert Watson |
347*aa772005SRobert Watson receiver_host_statement
348*aa772005SRobert Watson ;
349*aa772005SRobert Watson
350*aa772005SRobert Watson /*
351*aa772005SRobert Watson checksum_statement: CHECKSUM checksum_type
352*aa772005SRobert Watson {
353*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_SENDER);
354*aa772005SRobert Watson
355*aa772005SRobert Watson switch (depth) {
356*aa772005SRobert Watson case 1:
357*aa772005SRobert Watson depth1_checksum = $2;
358*aa772005SRobert Watson break;
359*aa772005SRobert Watson case 2:
360*aa772005SRobert Watson PJDLOG_ASSERT(curhost != NULL);
361*aa772005SRobert Watson curhost->adh_checksum = $2;
362*aa772005SRobert Watson break;
363*aa772005SRobert Watson default:
364*aa772005SRobert Watson PJDLOG_ABORT("checksum at wrong depth level");
365*aa772005SRobert Watson }
366*aa772005SRobert Watson }
367*aa772005SRobert Watson ;
368*aa772005SRobert Watson
369*aa772005SRobert Watson checksum_type:
370*aa772005SRobert Watson NONE { $$ = ADIST_CHECKSUM_NONE; }
371*aa772005SRobert Watson |
372*aa772005SRobert Watson CRC32 { $$ = ADIST_CHECKSUM_CRC32; }
373*aa772005SRobert Watson |
374*aa772005SRobert Watson SHA256 { $$ = ADIST_CHECKSUM_SHA256; }
375*aa772005SRobert Watson ;
376*aa772005SRobert Watson
377*aa772005SRobert Watson compression_statement: COMPRESSION compression_type
378*aa772005SRobert Watson {
379*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_SENDER);
380*aa772005SRobert Watson
381*aa772005SRobert Watson switch (depth) {
382*aa772005SRobert Watson case 1:
383*aa772005SRobert Watson depth1_compression = $2;
384*aa772005SRobert Watson break;
385*aa772005SRobert Watson case 2:
386*aa772005SRobert Watson PJDLOG_ASSERT(curhost != NULL);
387*aa772005SRobert Watson curhost->adh_compression = $2;
388*aa772005SRobert Watson break;
389*aa772005SRobert Watson default:
390*aa772005SRobert Watson PJDLOG_ABORT("compression at wrong depth level");
391*aa772005SRobert Watson }
392*aa772005SRobert Watson }
393*aa772005SRobert Watson ;
394*aa772005SRobert Watson
395*aa772005SRobert Watson compression_type:
396*aa772005SRobert Watson NONE { $$ = ADIST_COMPRESSION_NONE; }
397*aa772005SRobert Watson |
398*aa772005SRobert Watson LZF { $$ = ADIST_COMPRESSION_LZF; }
399*aa772005SRobert Watson ;
400*aa772005SRobert Watson */
401*aa772005SRobert Watson
402*aa772005SRobert Watson directory_statement: DIRECTORY STR
403*aa772005SRobert Watson {
404*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_SENDER ||
405*aa772005SRobert Watson cursection == SECTION_RECEIVER);
406*aa772005SRobert Watson
407*aa772005SRobert Watson switch (depth) {
408*aa772005SRobert Watson case 1:
409*aa772005SRobert Watson if (strlcpy(depth1_directory, $2,
410*aa772005SRobert Watson sizeof(depth1_directory)) >=
411*aa772005SRobert Watson sizeof(depth1_directory)) {
412*aa772005SRobert Watson pjdlog_error("Directory value is too long.");
413*aa772005SRobert Watson free($2);
414*aa772005SRobert Watson return (1);
415*aa772005SRobert Watson }
416*aa772005SRobert Watson if (!adjust_directory(depth1_directory))
417*aa772005SRobert Watson return (1);
418*aa772005SRobert Watson break;
419*aa772005SRobert Watson case 2:
420*aa772005SRobert Watson if (cursection == SECTION_SENDER || $2[0] == '/') {
421*aa772005SRobert Watson if (strlcpy(curhost->adh_directory, $2,
422*aa772005SRobert Watson sizeof(curhost->adh_directory)) >=
423*aa772005SRobert Watson sizeof(curhost->adh_directory)) {
424*aa772005SRobert Watson pjdlog_error("Directory value is too long.");
425*aa772005SRobert Watson free($2);
426*aa772005SRobert Watson return (1);
427*aa772005SRobert Watson }
428*aa772005SRobert Watson } else /* if (cursection == SECTION_RECEIVER) */ {
429*aa772005SRobert Watson if (depth1_directory[0] == '\0') {
430*aa772005SRobert Watson pjdlog_error("Directory path must be absolute.");
431*aa772005SRobert Watson free($2);
432*aa772005SRobert Watson return (1);
433*aa772005SRobert Watson }
434*aa772005SRobert Watson if (snprintf(curhost->adh_directory,
435*aa772005SRobert Watson sizeof(curhost->adh_directory), "%s/%s",
436*aa772005SRobert Watson depth1_directory, $2) >=
437*aa772005SRobert Watson (ssize_t)sizeof(curhost->adh_directory)) {
438*aa772005SRobert Watson pjdlog_error("Directory value is too long.");
439*aa772005SRobert Watson free($2);
440*aa772005SRobert Watson return (1);
441*aa772005SRobert Watson }
442*aa772005SRobert Watson }
443*aa772005SRobert Watson break;
444*aa772005SRobert Watson default:
445*aa772005SRobert Watson PJDLOG_ABORT("directory at wrong depth level");
446*aa772005SRobert Watson }
447*aa772005SRobert Watson free($2);
448*aa772005SRobert Watson }
449*aa772005SRobert Watson ;
450*aa772005SRobert Watson
451*aa772005SRobert Watson source_statement: SOURCE STR
452*aa772005SRobert Watson {
453*aa772005SRobert Watson PJDLOG_RASSERT(cursection == SECTION_SENDER,
454*aa772005SRobert Watson "The source variable must be in sender section.");
455*aa772005SRobert Watson
456*aa772005SRobert Watson switch (depth) {
457*aa772005SRobert Watson case 1:
458*aa772005SRobert Watson if (strlcpy(depth1_source, $2,
459*aa772005SRobert Watson sizeof(depth1_source)) >=
460*aa772005SRobert Watson sizeof(depth1_source)) {
461*aa772005SRobert Watson pjdlog_error("Source value is too long.");
462*aa772005SRobert Watson free($2);
463*aa772005SRobert Watson return (1);
464*aa772005SRobert Watson }
465*aa772005SRobert Watson break;
466*aa772005SRobert Watson case 2:
467*aa772005SRobert Watson if (strlcpy(curhost->adh_localaddr, $2,
468*aa772005SRobert Watson sizeof(curhost->adh_localaddr)) >=
469*aa772005SRobert Watson sizeof(curhost->adh_localaddr)) {
470*aa772005SRobert Watson pjdlog_error("Source value is too long.");
471*aa772005SRobert Watson free($2);
472*aa772005SRobert Watson return (1);
473*aa772005SRobert Watson }
474*aa772005SRobert Watson break;
475*aa772005SRobert Watson }
476*aa772005SRobert Watson free($2);
477*aa772005SRobert Watson }
478*aa772005SRobert Watson ;
479*aa772005SRobert Watson
480*aa772005SRobert Watson fingerprint_statement: FINGERPRINT STR
481*aa772005SRobert Watson {
482*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_SENDER);
483*aa772005SRobert Watson PJDLOG_ASSERT(depth == 2);
484*aa772005SRobert Watson
485*aa772005SRobert Watson if (strncasecmp($2, "SHA256=", 7) != 0) {
486*aa772005SRobert Watson pjdlog_error("Invalid fingerprint value.");
487*aa772005SRobert Watson free($2);
488*aa772005SRobert Watson return (1);
489*aa772005SRobert Watson }
490*aa772005SRobert Watson if (strlcpy(curhost->adh_fingerprint, $2,
491*aa772005SRobert Watson sizeof(curhost->adh_fingerprint)) >=
492*aa772005SRobert Watson sizeof(curhost->adh_fingerprint)) {
493*aa772005SRobert Watson pjdlog_error("Fingerprint value is too long.");
494*aa772005SRobert Watson free($2);
495*aa772005SRobert Watson return (1);
496*aa772005SRobert Watson }
497*aa772005SRobert Watson free($2);
498*aa772005SRobert Watson }
499*aa772005SRobert Watson ;
500*aa772005SRobert Watson
501*aa772005SRobert Watson password_statement: PASSWORD STR
502*aa772005SRobert Watson {
503*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_SENDER ||
504*aa772005SRobert Watson cursection == SECTION_RECEIVER);
505*aa772005SRobert Watson PJDLOG_ASSERT(depth == 2);
506*aa772005SRobert Watson
507*aa772005SRobert Watson if (strlcpy(curhost->adh_password, $2,
508*aa772005SRobert Watson sizeof(curhost->adh_password)) >=
509*aa772005SRobert Watson sizeof(curhost->adh_password)) {
510*aa772005SRobert Watson pjdlog_error("Password value is too long.");
511*aa772005SRobert Watson bzero($2, strlen($2));
512*aa772005SRobert Watson free($2);
513*aa772005SRobert Watson return (1);
514*aa772005SRobert Watson }
515*aa772005SRobert Watson bzero($2, strlen($2));
516*aa772005SRobert Watson free($2);
517*aa772005SRobert Watson }
518*aa772005SRobert Watson ;
519*aa772005SRobert Watson
520*aa772005SRobert Watson certfile_statement: CERTFILE STR
521*aa772005SRobert Watson {
522*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
523*aa772005SRobert Watson PJDLOG_ASSERT(depth == 1);
524*aa772005SRobert Watson
525*aa772005SRobert Watson if (strlcpy(lconfig->adc_certfile, $2,
526*aa772005SRobert Watson sizeof(lconfig->adc_certfile)) >=
527*aa772005SRobert Watson sizeof(lconfig->adc_certfile)) {
528*aa772005SRobert Watson pjdlog_error("Certfile value is too long.");
529*aa772005SRobert Watson free($2);
530*aa772005SRobert Watson return (1);
531*aa772005SRobert Watson }
532*aa772005SRobert Watson free($2);
533*aa772005SRobert Watson }
534*aa772005SRobert Watson ;
535*aa772005SRobert Watson
536*aa772005SRobert Watson keyfile_statement: KEYFILE STR
537*aa772005SRobert Watson {
538*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
539*aa772005SRobert Watson PJDLOG_ASSERT(depth == 1);
540*aa772005SRobert Watson
541*aa772005SRobert Watson if (strlcpy(lconfig->adc_keyfile, $2,
542*aa772005SRobert Watson sizeof(lconfig->adc_keyfile)) >=
543*aa772005SRobert Watson sizeof(lconfig->adc_keyfile)) {
544*aa772005SRobert Watson pjdlog_error("Keyfile value is too long.");
545*aa772005SRobert Watson free($2);
546*aa772005SRobert Watson return (1);
547*aa772005SRobert Watson }
548*aa772005SRobert Watson free($2);
549*aa772005SRobert Watson }
550*aa772005SRobert Watson ;
551*aa772005SRobert Watson
552*aa772005SRobert Watson listen_statement: LISTEN STR
553*aa772005SRobert Watson {
554*aa772005SRobert Watson struct adist_listen *lst;
555*aa772005SRobert Watson
556*aa772005SRobert Watson PJDLOG_ASSERT(depth == 1);
557*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
558*aa772005SRobert Watson
559*aa772005SRobert Watson lst = calloc(1, sizeof(*lst));
560*aa772005SRobert Watson if (lst == NULL) {
561*aa772005SRobert Watson pjdlog_error("Unable to allocate memory for listen address.");
562*aa772005SRobert Watson free($2);
563*aa772005SRobert Watson return (1);
564*aa772005SRobert Watson }
565*aa772005SRobert Watson if (strlcpy(lst->adl_addr, $2, sizeof(lst->adl_addr)) >=
566*aa772005SRobert Watson sizeof(lst->adl_addr)) {
567*aa772005SRobert Watson pjdlog_error("listen argument is too long.");
568*aa772005SRobert Watson free($2);
569*aa772005SRobert Watson free(lst);
570*aa772005SRobert Watson return (1);
571*aa772005SRobert Watson }
572*aa772005SRobert Watson TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
573*aa772005SRobert Watson free($2);
574*aa772005SRobert Watson }
575*aa772005SRobert Watson ;
576*aa772005SRobert Watson
577*aa772005SRobert Watson sender_host_statement: HOST host_start OB sender_host_entries CB
578*aa772005SRobert Watson {
579*aa772005SRobert Watson /* Put it onto host list. */
580*aa772005SRobert Watson TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next);
581*aa772005SRobert Watson curhost = NULL;
582*aa772005SRobert Watson }
583*aa772005SRobert Watson ;
584*aa772005SRobert Watson
585*aa772005SRobert Watson receiver_host_statement: HOST host_start OB receiver_host_entries CB
586*aa772005SRobert Watson {
587*aa772005SRobert Watson /* Put it onto host list. */
588*aa772005SRobert Watson TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next);
589*aa772005SRobert Watson curhost = NULL;
590*aa772005SRobert Watson }
591*aa772005SRobert Watson ;
592*aa772005SRobert Watson
593*aa772005SRobert Watson host_start: STR
594*aa772005SRobert Watson {
595*aa772005SRobert Watson /* Check if there is no duplicate entry. */
596*aa772005SRobert Watson TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
597*aa772005SRobert Watson if (strcmp(curhost->adh_name, $1) != 0)
598*aa772005SRobert Watson continue;
599*aa772005SRobert Watson if (curhost->adh_role == ADIST_ROLE_SENDER &&
600*aa772005SRobert Watson cursection == SECTION_RECEIVER) {
601*aa772005SRobert Watson continue;
602*aa772005SRobert Watson }
603*aa772005SRobert Watson if (curhost->adh_role == ADIST_ROLE_RECEIVER &&
604*aa772005SRobert Watson cursection == SECTION_SENDER) {
605*aa772005SRobert Watson continue;
606*aa772005SRobert Watson }
607*aa772005SRobert Watson pjdlog_error("%s host %s is configured more than once.",
608*aa772005SRobert Watson curhost->adh_role == ADIST_ROLE_SENDER ?
609*aa772005SRobert Watson "Sender" : "Receiver", curhost->adh_name);
610*aa772005SRobert Watson free($1);
611*aa772005SRobert Watson return (1);
612*aa772005SRobert Watson }
613*aa772005SRobert Watson
614*aa772005SRobert Watson curhost = calloc(1, sizeof(*curhost));
615*aa772005SRobert Watson if (curhost == NULL) {
616*aa772005SRobert Watson pjdlog_error("Unable to allocate memory for host configuration.");
617*aa772005SRobert Watson free($1);
618*aa772005SRobert Watson return (1);
619*aa772005SRobert Watson }
620*aa772005SRobert Watson if (strlcpy(curhost->adh_name, $1, sizeof(curhost->adh_name)) >=
621*aa772005SRobert Watson sizeof(curhost->adh_name)) {
622*aa772005SRobert Watson pjdlog_error("Host name is too long.");
623*aa772005SRobert Watson free($1);
624*aa772005SRobert Watson return (1);
625*aa772005SRobert Watson }
626*aa772005SRobert Watson free($1);
627*aa772005SRobert Watson curhost->adh_role = cursection == SECTION_SENDER ?
628*aa772005SRobert Watson ADIST_ROLE_SENDER : ADIST_ROLE_RECEIVER;
629*aa772005SRobert Watson curhost->adh_version = ADIST_VERSION;
630*aa772005SRobert Watson curhost->adh_localaddr[0] = '\0';
631*aa772005SRobert Watson curhost->adh_remoteaddr[0] = '\0';
632*aa772005SRobert Watson curhost->adh_remote = NULL;
633*aa772005SRobert Watson curhost->adh_directory[0] = '\0';
634*aa772005SRobert Watson curhost->adh_password[0] = '\0';
635*aa772005SRobert Watson curhost->adh_fingerprint[0] = '\0';
636*aa772005SRobert Watson curhost->adh_worker_pid = 0;
637*aa772005SRobert Watson curhost->adh_conn = NULL;
638*aa772005SRobert Watson }
639*aa772005SRobert Watson ;
640*aa772005SRobert Watson
641*aa772005SRobert Watson sender_host_entries:
642*aa772005SRobert Watson |
643*aa772005SRobert Watson sender_host_entries sender_host_entry
644*aa772005SRobert Watson ;
645*aa772005SRobert Watson
646*aa772005SRobert Watson sender_host_entry:
647*aa772005SRobert Watson source_statement
648*aa772005SRobert Watson |
649*aa772005SRobert Watson remote_statement
650*aa772005SRobert Watson |
651*aa772005SRobert Watson directory_statement
652*aa772005SRobert Watson |
653*aa772005SRobert Watson fingerprint_statement
654*aa772005SRobert Watson |
655*aa772005SRobert Watson password_statement
656*aa772005SRobert Watson /*
657*aa772005SRobert Watson |
658*aa772005SRobert Watson checksum_statement
659*aa772005SRobert Watson |
660*aa772005SRobert Watson compression_statement
661*aa772005SRobert Watson */
662*aa772005SRobert Watson ;
663*aa772005SRobert Watson
664*aa772005SRobert Watson receiver_host_entries:
665*aa772005SRobert Watson |
666*aa772005SRobert Watson receiver_host_entries receiver_host_entry
667*aa772005SRobert Watson ;
668*aa772005SRobert Watson
669*aa772005SRobert Watson receiver_host_entry:
670*aa772005SRobert Watson remote_statement
671*aa772005SRobert Watson |
672*aa772005SRobert Watson directory_statement
673*aa772005SRobert Watson |
674*aa772005SRobert Watson password_statement
675*aa772005SRobert Watson ;
676*aa772005SRobert Watson
677*aa772005SRobert Watson remote_statement: REMOTE STR
678*aa772005SRobert Watson {
679*aa772005SRobert Watson PJDLOG_ASSERT(depth == 2);
680*aa772005SRobert Watson PJDLOG_ASSERT(cursection == SECTION_SENDER ||
681*aa772005SRobert Watson cursection == SECTION_RECEIVER);
682*aa772005SRobert Watson
683*aa772005SRobert Watson if (strlcpy(curhost->adh_remoteaddr, $2,
684*aa772005SRobert Watson sizeof(curhost->adh_remoteaddr)) >=
685*aa772005SRobert Watson sizeof(curhost->adh_remoteaddr)) {
686*aa772005SRobert Watson pjdlog_error("Remote value is too long.");
687*aa772005SRobert Watson free($2);
688*aa772005SRobert Watson return (1);
689*aa772005SRobert Watson }
690*aa772005SRobert Watson free($2);
691*aa772005SRobert Watson }
692*aa772005SRobert Watson ;
693*aa772005SRobert Watson
694*aa772005SRobert Watson %%
695*aa772005SRobert Watson
696*aa772005SRobert Watson static bool
697*aa772005SRobert Watson family_supported(int family)
698*aa772005SRobert Watson {
699*aa772005SRobert Watson int sock;
700*aa772005SRobert Watson
701*aa772005SRobert Watson sock = socket(family, SOCK_STREAM, 0);
702*aa772005SRobert Watson if (sock == -1 && errno == EPROTONOSUPPORT)
703*aa772005SRobert Watson return (false);
704*aa772005SRobert Watson if (sock >= 0)
705*aa772005SRobert Watson (void)close(sock);
706*aa772005SRobert Watson return (true);
707*aa772005SRobert Watson }
708*aa772005SRobert Watson
709*aa772005SRobert Watson static bool
adjust_directory(char * path)710*aa772005SRobert Watson adjust_directory(char *path)
711*aa772005SRobert Watson {
712*aa772005SRobert Watson size_t len;
713*aa772005SRobert Watson
714*aa772005SRobert Watson len = strlen(path);
715*aa772005SRobert Watson for (;;) {
716*aa772005SRobert Watson if (len == 0) {
717*aa772005SRobert Watson pjdlog_error("Directory path is empty.");
718*aa772005SRobert Watson return (false);
719*aa772005SRobert Watson }
720*aa772005SRobert Watson if (path[len - 1] != '/')
721*aa772005SRobert Watson break;
722*aa772005SRobert Watson len--;
723*aa772005SRobert Watson path[len] = '\0';
724*aa772005SRobert Watson }
725*aa772005SRobert Watson if (path[0] != '/') {
726*aa772005SRobert Watson pjdlog_error("Directory path must be absolute.");
727*aa772005SRobert Watson return (false);
728*aa772005SRobert Watson }
729*aa772005SRobert Watson return (true);
730*aa772005SRobert Watson }
731*aa772005SRobert Watson
732*aa772005SRobert Watson static int
my_name(char * name,size_t size)733*aa772005SRobert Watson my_name(char *name, size_t size)
734*aa772005SRobert Watson {
735*aa772005SRobert Watson char buf[MAXHOSTNAMELEN];
736*aa772005SRobert Watson char *pos;
737*aa772005SRobert Watson
738*aa772005SRobert Watson if (gethostname(buf, sizeof(buf)) < 0) {
739*aa772005SRobert Watson pjdlog_errno(LOG_ERR, "gethostname() failed");
740*aa772005SRobert Watson return (-1);
741*aa772005SRobert Watson }
742*aa772005SRobert Watson
743*aa772005SRobert Watson /* First component of the host name. */
744*aa772005SRobert Watson pos = strchr(buf, '.');
745*aa772005SRobert Watson if (pos == NULL)
746*aa772005SRobert Watson (void)strlcpy(name, buf, size);
747*aa772005SRobert Watson else
748*aa772005SRobert Watson (void)strlcpy(name, buf, MIN((size_t)(pos - buf + 1), size));
749*aa772005SRobert Watson
750*aa772005SRobert Watson if (name[0] == '\0') {
751*aa772005SRobert Watson pjdlog_error("Empty host name.");
752*aa772005SRobert Watson return (-1);
753*aa772005SRobert Watson }
754*aa772005SRobert Watson
755*aa772005SRobert Watson return (0);
756*aa772005SRobert Watson }
757*aa772005SRobert Watson
758*aa772005SRobert Watson void
yyerror(const char * str)759*aa772005SRobert Watson yyerror(const char *str)
760*aa772005SRobert Watson {
761*aa772005SRobert Watson
762*aa772005SRobert Watson pjdlog_error("Unable to parse configuration file at line %d near '%s': %s",
763*aa772005SRobert Watson lineno, yytext, str);
764*aa772005SRobert Watson }
765*aa772005SRobert Watson
766*aa772005SRobert Watson struct adist_config *
yy_config_parse(const char * config,bool exitonerror)767*aa772005SRobert Watson yy_config_parse(const char *config, bool exitonerror)
768*aa772005SRobert Watson {
769*aa772005SRobert Watson int ret;
770*aa772005SRobert Watson
771*aa772005SRobert Watson curhost = NULL;
772*aa772005SRobert Watson cursection = SECTION_GLOBAL;
773*aa772005SRobert Watson depth = 0;
774*aa772005SRobert Watson lineno = 0;
775*aa772005SRobert Watson
776*aa772005SRobert Watson lconfig = calloc(1, sizeof(*lconfig));
777*aa772005SRobert Watson if (lconfig == NULL) {
778*aa772005SRobert Watson pjdlog_error("Unable to allocate memory for configuration.");
779*aa772005SRobert Watson if (exitonerror)
780*aa772005SRobert Watson exit(EX_TEMPFAIL);
781*aa772005SRobert Watson return (NULL);
782*aa772005SRobert Watson }
783*aa772005SRobert Watson TAILQ_INIT(&lconfig->adc_hosts);
784*aa772005SRobert Watson TAILQ_INIT(&lconfig->adc_listen);
785*aa772005SRobert Watson lconfig->adc_name[0] = '\0';
786*aa772005SRobert Watson lconfig->adc_timeout = -1;
787*aa772005SRobert Watson lconfig->adc_pidfile[0] = '\0';
788*aa772005SRobert Watson lconfig->adc_certfile[0] = '\0';
789*aa772005SRobert Watson lconfig->adc_keyfile[0] = '\0';
790*aa772005SRobert Watson
791*aa772005SRobert Watson yyin = fopen(config, "r");
792*aa772005SRobert Watson if (yyin == NULL) {
793*aa772005SRobert Watson pjdlog_errno(LOG_ERR, "Unable to open configuration file %s",
794*aa772005SRobert Watson config);
795*aa772005SRobert Watson yy_config_free(lconfig);
796*aa772005SRobert Watson if (exitonerror)
797*aa772005SRobert Watson exit(EX_OSFILE);
798*aa772005SRobert Watson return (NULL);
799*aa772005SRobert Watson }
800*aa772005SRobert Watson yyrestart(yyin);
801*aa772005SRobert Watson ret = yyparse();
802*aa772005SRobert Watson fclose(yyin);
803*aa772005SRobert Watson if (ret != 0) {
804*aa772005SRobert Watson yy_config_free(lconfig);
805*aa772005SRobert Watson if (exitonerror)
806*aa772005SRobert Watson exit(EX_CONFIG);
807*aa772005SRobert Watson return (NULL);
808*aa772005SRobert Watson }
809*aa772005SRobert Watson
810*aa772005SRobert Watson /*
811*aa772005SRobert Watson * Let's see if everything is set up.
812*aa772005SRobert Watson */
813*aa772005SRobert Watson if (lconfig->adc_name[0] == '\0' && my_name(lconfig->adc_name,
814*aa772005SRobert Watson sizeof(lconfig->adc_name)) == -1) {
815*aa772005SRobert Watson yy_config_free(lconfig);
816*aa772005SRobert Watson if (exitonerror)
817*aa772005SRobert Watson exit(EX_CONFIG);
818*aa772005SRobert Watson return (NULL);
819*aa772005SRobert Watson }
820*aa772005SRobert Watson if (lconfig->adc_timeout == -1)
821*aa772005SRobert Watson lconfig->adc_timeout = ADIST_TIMEOUT;
822*aa772005SRobert Watson if (lconfig->adc_pidfile[0] == '\0') {
823*aa772005SRobert Watson (void)strlcpy(lconfig->adc_pidfile, ADIST_PIDFILE,
824*aa772005SRobert Watson sizeof(lconfig->adc_pidfile));
825*aa772005SRobert Watson }
826*aa772005SRobert Watson if (lconfig->adc_certfile[0] == '\0') {
827*aa772005SRobert Watson (void)strlcpy(lconfig->adc_certfile, ADIST_CERTFILE,
828*aa772005SRobert Watson sizeof(lconfig->adc_certfile));
829*aa772005SRobert Watson }
830*aa772005SRobert Watson if (lconfig->adc_keyfile[0] == '\0') {
831*aa772005SRobert Watson (void)strlcpy(lconfig->adc_keyfile, ADIST_KEYFILE,
832*aa772005SRobert Watson sizeof(lconfig->adc_keyfile));
833*aa772005SRobert Watson }
834*aa772005SRobert Watson
835*aa772005SRobert Watson return (lconfig);
836*aa772005SRobert Watson }
837*aa772005SRobert Watson
838*aa772005SRobert Watson void
yy_config_free(struct adist_config * config)839*aa772005SRobert Watson yy_config_free(struct adist_config *config)
840*aa772005SRobert Watson {
841*aa772005SRobert Watson struct adist_host *adhost;
842*aa772005SRobert Watson struct adist_listen *lst;
843*aa772005SRobert Watson
844*aa772005SRobert Watson while ((lst = TAILQ_FIRST(&config->adc_listen)) != NULL) {
845*aa772005SRobert Watson TAILQ_REMOVE(&config->adc_listen, lst, adl_next);
846*aa772005SRobert Watson free(lst);
847*aa772005SRobert Watson }
848*aa772005SRobert Watson while ((adhost = TAILQ_FIRST(&config->adc_hosts)) != NULL) {
849*aa772005SRobert Watson TAILQ_REMOVE(&config->adc_hosts, adhost, adh_next);
850*aa772005SRobert Watson bzero(adhost, sizeof(*adhost));
851*aa772005SRobert Watson free(adhost);
852*aa772005SRobert Watson }
853*aa772005SRobert Watson free(config);
854*aa772005SRobert Watson }
855