3 * Copyright (c) 2012 The FreeBSD Foundation
6 * This software was developed by Pawel Jakub Dawidek under sponsorship from
7 * the FreeBSD Foundation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <config/config.h>
33 #include <sys/types.h>
34 #include <sys/queue.h>
35 #include <sys/sysctl.h>
37 #include <arpa/inet.h>
46 #include <compat/strlcpy.h>
49 #include "auditdistd.h"
58 static struct adist_config *lconfig;
59 static struct adist_host *curhost;
60 #define SECTION_GLOBAL 0
61 #define SECTION_SENDER 1
62 #define SECTION_RECEIVER 2
63 static int cursection;
66 static char depth1_source[ADIST_ADDRSIZE];
67 static int depth1_checksum;
68 static int depth1_compression;
69 /* Sender and receiver sections. */
70 static char depth1_directory[PATH_MAX];
72 static bool adjust_directory(char *path);
73 static bool family_supported(int family);
75 extern void yyrestart(FILE *);
89 %token RECEIVER REMOTE
94 %type <num> checksum_type
95 %type <num> compression_type
126 name_statement: NAME STR
128 PJDLOG_RASSERT(depth == 0,
129 "The name variable can only be specificed in the global section.");
131 if (lconfig->adc_name[0] != '\0') {
132 pjdlog_error("The name variable is specified twice.");
136 if (strlcpy(lconfig->adc_name, $2,
137 sizeof(lconfig->adc_name)) >=
138 sizeof(lconfig->adc_name)) {
139 pjdlog_error("The name value is too long.");
147 pidfile_statement: PIDFILE STR
149 PJDLOG_RASSERT(depth == 0,
150 "The pidfile variable can only be specificed in the global section.");
152 if (lconfig->adc_pidfile[0] != '\0') {
153 pjdlog_error("The pidfile variable is specified twice.");
157 if (strcmp($2, "none") != 0 && $2[0] != '/') {
158 pjdlog_error("The pidfile variable must be set to absolute pathname or \"none\".");
162 if (strlcpy(lconfig->adc_pidfile, $2,
163 sizeof(lconfig->adc_pidfile)) >=
164 sizeof(lconfig->adc_pidfile)) {
165 pjdlog_error("The pidfile value is too long.");
173 timeout_statement: TIMEOUT NUM
175 PJDLOG_ASSERT(depth == 0);
177 lconfig->adc_timeout = $2;
181 sender_statement: SENDER sender_start sender_entries CB
183 PJDLOG_ASSERT(depth == 0);
184 PJDLOG_ASSERT(cursection == SECTION_SENDER);
186 /* Configure defaults. */
187 if (depth1_checksum == -1)
188 depth1_checksum = ADIST_CHECKSUM_NONE;
189 if (depth1_compression == -1)
190 depth1_compression = ADIST_COMPRESSION_NONE;
191 if (depth1_directory[0] == '\0') {
192 (void)strlcpy(depth1_directory, ADIST_DIRECTORY_SENDER,
193 sizeof(depth1_directory));
195 /* Empty depth1_source is ok. */
196 TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
197 if (curhost->adh_role != ADIST_ROLE_SENDER)
199 if (curhost->adh_checksum == -1)
200 curhost->adh_checksum = depth1_checksum;
201 if (curhost->adh_compression == -1)
202 curhost->adh_compression = depth1_compression;
203 if (curhost->adh_directory[0] == '\0') {
204 (void)strlcpy(curhost->adh_directory,
206 sizeof(curhost->adh_directory));
208 if (curhost->adh_localaddr[0] == '\0') {
209 (void)strlcpy(curhost->adh_localaddr,
211 sizeof(curhost->adh_localaddr));
214 cursection = SECTION_GLOBAL;
220 PJDLOG_ASSERT(depth == 1);
221 PJDLOG_ASSERT(cursection == SECTION_GLOBAL);
223 cursection = SECTION_SENDER;
224 depth1_checksum = -1;
225 depth1_compression = -1;
226 depth1_source[0] = '\0';
227 depth1_directory[0] = '\0';
229 #ifndef HAVE_AUDIT_SYSCALLS
230 pjdlog_error("Sender functionality is not available.");
238 sender_entries sender_entry
249 compression_statement
252 sender_host_statement
255 receiver_statement: RECEIVER receiver_start receiver_entries CB
257 PJDLOG_ASSERT(depth == 0);
258 PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
261 * If not listen addresses were specified,
262 * configure default ones.
264 if (TAILQ_EMPTY(&lconfig->adc_listen)) {
265 struct adist_listen *lst;
267 if (family_supported(AF_INET)) {
268 lst = calloc(1, sizeof(*lst));
270 pjdlog_error("Unable to allocate memory for listen address.");
273 (void)strlcpy(lst->adl_addr,
274 ADIST_LISTEN_TLS_TCP4,
275 sizeof(lst->adl_addr));
276 TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
279 "No IPv4 support in the kernel, not listening on IPv4 address.");
281 if (family_supported(AF_INET6)) {
282 lst = calloc(1, sizeof(*lst));
284 pjdlog_error("Unable to allocate memory for listen address.");
287 (void)strlcpy(lst->adl_addr,
288 ADIST_LISTEN_TLS_TCP6,
289 sizeof(lst->adl_addr));
290 TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
293 "No IPv6 support in the kernel, not listening on IPv6 address.");
295 if (TAILQ_EMPTY(&lconfig->adc_listen)) {
296 pjdlog_error("No address to listen on.");
300 /* Configure defaults. */
301 if (depth1_directory[0] == '\0') {
302 (void)strlcpy(depth1_directory,
303 ADIST_DIRECTORY_RECEIVER,
304 sizeof(depth1_directory));
306 TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
307 if (curhost->adh_role != ADIST_ROLE_RECEIVER)
309 if (curhost->adh_directory[0] == '\0') {
310 if (snprintf(curhost->adh_directory,
311 sizeof(curhost->adh_directory), "%s/%s",
312 depth1_directory, curhost->adh_name) >=
313 (ssize_t)sizeof(curhost->adh_directory)) {
314 pjdlog_error("Directory value is too long.");
319 cursection = SECTION_GLOBAL;
325 PJDLOG_ASSERT(depth == 1);
326 PJDLOG_ASSERT(cursection == SECTION_GLOBAL);
328 cursection = SECTION_RECEIVER;
329 depth1_directory[0] = '\0';
335 receiver_entries receiver_entry
347 receiver_host_statement
351 checksum_statement: CHECKSUM checksum_type
353 PJDLOG_ASSERT(cursection == SECTION_SENDER);
357 depth1_checksum = $2;
360 PJDLOG_ASSERT(curhost != NULL);
361 curhost->adh_checksum = $2;
364 PJDLOG_ABORT("checksum at wrong depth level");
370 NONE { $$ = ADIST_CHECKSUM_NONE; }
372 CRC32 { $$ = ADIST_CHECKSUM_CRC32; }
374 SHA256 { $$ = ADIST_CHECKSUM_SHA256; }
377 compression_statement: COMPRESSION compression_type
379 PJDLOG_ASSERT(cursection == SECTION_SENDER);
383 depth1_compression = $2;
386 PJDLOG_ASSERT(curhost != NULL);
387 curhost->adh_compression = $2;
390 PJDLOG_ABORT("compression at wrong depth level");
396 NONE { $$ = ADIST_COMPRESSION_NONE; }
398 LZF { $$ = ADIST_COMPRESSION_LZF; }
402 directory_statement: DIRECTORY STR
404 PJDLOG_ASSERT(cursection == SECTION_SENDER ||
405 cursection == SECTION_RECEIVER);
409 if (strlcpy(depth1_directory, $2,
410 sizeof(depth1_directory)) >=
411 sizeof(depth1_directory)) {
412 pjdlog_error("Directory value is too long.");
416 if (!adjust_directory(depth1_directory))
420 if (cursection == SECTION_SENDER || $2[0] == '/') {
421 if (strlcpy(curhost->adh_directory, $2,
422 sizeof(curhost->adh_directory)) >=
423 sizeof(curhost->adh_directory)) {
424 pjdlog_error("Directory value is too long.");
428 } else /* if (cursection == SECTION_RECEIVER) */ {
429 if (depth1_directory[0] == '\0') {
430 pjdlog_error("Directory path must be absolute.");
434 if (snprintf(curhost->adh_directory,
435 sizeof(curhost->adh_directory), "%s/%s",
436 depth1_directory, $2) >=
437 (ssize_t)sizeof(curhost->adh_directory)) {
438 pjdlog_error("Directory value is too long.");
445 PJDLOG_ABORT("directory at wrong depth level");
451 source_statement: SOURCE STR
453 PJDLOG_RASSERT(cursection == SECTION_SENDER,
454 "The source variable must be in sender section.");
458 if (strlcpy(depth1_source, $2,
459 sizeof(depth1_source)) >=
460 sizeof(depth1_source)) {
461 pjdlog_error("Source value is too long.");
467 if (strlcpy(curhost->adh_localaddr, $2,
468 sizeof(curhost->adh_localaddr)) >=
469 sizeof(curhost->adh_localaddr)) {
470 pjdlog_error("Source value is too long.");
480 fingerprint_statement: FINGERPRINT STR
482 PJDLOG_ASSERT(cursection == SECTION_SENDER);
483 PJDLOG_ASSERT(depth == 2);
485 if (strncasecmp($2, "SHA256=", 7) != 0) {
486 pjdlog_error("Invalid fingerprint value.");
490 if (strlcpy(curhost->adh_fingerprint, $2,
491 sizeof(curhost->adh_fingerprint)) >=
492 sizeof(curhost->adh_fingerprint)) {
493 pjdlog_error("Fingerprint value is too long.");
501 password_statement: PASSWORD STR
503 PJDLOG_ASSERT(cursection == SECTION_SENDER ||
504 cursection == SECTION_RECEIVER);
505 PJDLOG_ASSERT(depth == 2);
507 if (strlcpy(curhost->adh_password, $2,
508 sizeof(curhost->adh_password)) >=
509 sizeof(curhost->adh_password)) {
510 pjdlog_error("Password value is too long.");
511 bzero($2, strlen($2));
515 bzero($2, strlen($2));
520 certfile_statement: CERTFILE STR
522 PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
523 PJDLOG_ASSERT(depth == 1);
525 if (strlcpy(lconfig->adc_certfile, $2,
526 sizeof(lconfig->adc_certfile)) >=
527 sizeof(lconfig->adc_certfile)) {
528 pjdlog_error("Certfile value is too long.");
536 keyfile_statement: KEYFILE STR
538 PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
539 PJDLOG_ASSERT(depth == 1);
541 if (strlcpy(lconfig->adc_keyfile, $2,
542 sizeof(lconfig->adc_keyfile)) >=
543 sizeof(lconfig->adc_keyfile)) {
544 pjdlog_error("Keyfile value is too long.");
552 listen_statement: LISTEN STR
554 struct adist_listen *lst;
556 PJDLOG_ASSERT(depth == 1);
557 PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
559 lst = calloc(1, sizeof(*lst));
561 pjdlog_error("Unable to allocate memory for listen address.");
565 if (strlcpy(lst->adl_addr, $2, sizeof(lst->adl_addr)) >=
566 sizeof(lst->adl_addr)) {
567 pjdlog_error("listen argument is too long.");
572 TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
577 sender_host_statement: HOST host_start OB sender_host_entries CB
579 /* Put it onto host list. */
580 TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next);
585 receiver_host_statement: HOST host_start OB receiver_host_entries CB
587 /* Put it onto host list. */
588 TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next);
595 /* Check if there is no duplicate entry. */
596 TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
597 if (strcmp(curhost->adh_name, $1) != 0)
599 if (curhost->adh_role == ADIST_ROLE_SENDER &&
600 cursection == SECTION_RECEIVER) {
603 if (curhost->adh_role == ADIST_ROLE_RECEIVER &&
604 cursection == SECTION_SENDER) {
607 pjdlog_error("%s host %s is configured more than once.",
608 curhost->adh_role == ADIST_ROLE_SENDER ?
609 "Sender" : "Receiver", curhost->adh_name);
614 curhost = calloc(1, sizeof(*curhost));
615 if (curhost == NULL) {
616 pjdlog_error("Unable to allocate memory for host configuration.");
620 if (strlcpy(curhost->adh_name, $1, sizeof(curhost->adh_name)) >=
621 sizeof(curhost->adh_name)) {
622 pjdlog_error("Host name is too long.");
627 curhost->adh_role = cursection == SECTION_SENDER ?
628 ADIST_ROLE_SENDER : ADIST_ROLE_RECEIVER;
629 curhost->adh_version = ADIST_VERSION;
630 curhost->adh_localaddr[0] = '\0';
631 curhost->adh_remoteaddr[0] = '\0';
632 curhost->adh_remote = NULL;
633 curhost->adh_directory[0] = '\0';
634 curhost->adh_password[0] = '\0';
635 curhost->adh_fingerprint[0] = '\0';
636 curhost->adh_worker_pid = 0;
637 curhost->adh_conn = NULL;
643 sender_host_entries sender_host_entry
653 fingerprint_statement
660 compression_statement
664 receiver_host_entries:
666 receiver_host_entries receiver_host_entry
677 remote_statement: REMOTE STR
679 PJDLOG_ASSERT(depth == 2);
680 PJDLOG_ASSERT(cursection == SECTION_SENDER ||
681 cursection == SECTION_RECEIVER);
683 if (strlcpy(curhost->adh_remoteaddr, $2,
684 sizeof(curhost->adh_remoteaddr)) >=
685 sizeof(curhost->adh_remoteaddr)) {
686 pjdlog_error("Remote value is too long.");
697 family_supported(int family)
701 sock = socket(family, SOCK_STREAM, 0);
702 if (sock == -1 && errno == EPROTONOSUPPORT)
710 adjust_directory(char *path)
717 pjdlog_error("Directory path is empty.");
720 if (path[len - 1] != '/')
725 if (path[0] != '/') {
726 pjdlog_error("Directory path must be absolute.");
733 my_name(char *name, size_t size)
735 char buf[MAXHOSTNAMELEN];
738 if (gethostname(buf, sizeof(buf)) < 0) {
739 pjdlog_errno(LOG_ERR, "gethostname() failed");
743 /* First component of the host name. */
744 pos = strchr(buf, '.');
746 (void)strlcpy(name, buf, size);
748 (void)strlcpy(name, buf, MIN((size_t)(pos - buf + 1), size));
750 if (name[0] == '\0') {
751 pjdlog_error("Empty host name.");
759 yyerror(const char *str)
762 pjdlog_error("Unable to parse configuration file at line %d near '%s': %s",
763 lineno, yytext, str);
766 struct adist_config *
767 yy_config_parse(const char *config, bool exitonerror)
772 cursection = SECTION_GLOBAL;
776 lconfig = calloc(1, sizeof(*lconfig));
777 if (lconfig == NULL) {
778 pjdlog_error("Unable to allocate memory for configuration.");
783 TAILQ_INIT(&lconfig->adc_hosts);
784 TAILQ_INIT(&lconfig->adc_listen);
785 lconfig->adc_name[0] = '\0';
786 lconfig->adc_timeout = -1;
787 lconfig->adc_pidfile[0] = '\0';
788 lconfig->adc_certfile[0] = '\0';
789 lconfig->adc_keyfile[0] = '\0';
791 yyin = fopen(config, "r");
793 pjdlog_errno(LOG_ERR, "Unable to open configuration file %s",
795 yy_config_free(lconfig);
804 yy_config_free(lconfig);
811 * Let's see if everything is set up.
813 if (lconfig->adc_name[0] == '\0' && my_name(lconfig->adc_name,
814 sizeof(lconfig->adc_name)) == -1) {
815 yy_config_free(lconfig);
820 if (lconfig->adc_timeout == -1)
821 lconfig->adc_timeout = ADIST_TIMEOUT;
822 if (lconfig->adc_pidfile[0] == '\0') {
823 (void)strlcpy(lconfig->adc_pidfile, ADIST_PIDFILE,
824 sizeof(lconfig->adc_pidfile));
826 if (lconfig->adc_certfile[0] == '\0') {
827 (void)strlcpy(lconfig->adc_certfile, ADIST_CERTFILE,
828 sizeof(lconfig->adc_certfile));
830 if (lconfig->adc_keyfile[0] == '\0') {
831 (void)strlcpy(lconfig->adc_keyfile, ADIST_KEYFILE,
832 sizeof(lconfig->adc_keyfile));
839 yy_config_free(struct adist_config *config)
841 struct adist_host *adhost;
842 struct adist_listen *lst;
844 while ((lst = TAILQ_FIRST(&config->adc_listen)) != NULL) {
845 TAILQ_REMOVE(&config->adc_listen, lst, adl_next);
848 while ((adhost = TAILQ_FIRST(&config->adc_hosts)) != NULL) {
849 TAILQ_REMOVE(&config->adc_hosts, adhost, adh_next);
850 bzero(adhost, sizeof(*adhost));