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
30 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/parse.y#5 $
33 #include <config/config.h>
35 #include <sys/types.h>
36 #include <sys/queue.h>
37 #include <sys/sysctl.h>
39 #include <arpa/inet.h>
48 #include <compat/strlcpy.h>
51 #include "auditdistd.h"
59 extern int yyparse(void);
61 static struct adist_config *lconfig;
62 static struct adist_host *curhost;
63 #define SECTION_GLOBAL 0
64 #define SECTION_SENDER 1
65 #define SECTION_RECEIVER 2
66 static int cursection;
69 static char depth1_source[ADIST_ADDRSIZE];
70 static int depth1_checksum;
71 static int depth1_compression;
72 /* Sender and receiver sections. */
73 static char depth1_directory[PATH_MAX];
75 static bool adjust_directory(char *path);
76 static bool family_supported(int family);
78 extern void yyrestart(FILE *);
92 %token RECEIVER REMOTE
97 %type <num> checksum_type
98 %type <num> compression_type
129 name_statement: NAME STR
131 PJDLOG_RASSERT(depth == 0,
132 "The name variable can only be specificed in the global section.");
134 if (lconfig->adc_name[0] != '\0') {
135 pjdlog_error("The name variable is specified twice.");
139 if (strlcpy(lconfig->adc_name, $2,
140 sizeof(lconfig->adc_name)) >=
141 sizeof(lconfig->adc_name)) {
142 pjdlog_error("The name value is too long.");
150 pidfile_statement: PIDFILE STR
152 PJDLOG_RASSERT(depth == 0,
153 "The pidfile variable can only be specificed in the global section.");
155 if (lconfig->adc_pidfile[0] != '\0') {
156 pjdlog_error("The pidfile variable is specified twice.");
160 if (strcmp($2, "none") != 0 && $2[0] != '/') {
161 pjdlog_error("The pidfile variable must be set to absolute pathname or \"none\".");
165 if (strlcpy(lconfig->adc_pidfile, $2,
166 sizeof(lconfig->adc_pidfile)) >=
167 sizeof(lconfig->adc_pidfile)) {
168 pjdlog_error("The pidfile value is too long.");
176 timeout_statement: TIMEOUT NUM
178 PJDLOG_ASSERT(depth == 0);
180 lconfig->adc_timeout = $2;
184 sender_statement: SENDER sender_start sender_entries CB
186 PJDLOG_ASSERT(depth == 0);
187 PJDLOG_ASSERT(cursection == SECTION_SENDER);
189 /* Configure defaults. */
190 if (depth1_checksum == -1)
191 depth1_checksum = ADIST_CHECKSUM_NONE;
192 if (depth1_compression == -1)
193 depth1_compression = ADIST_COMPRESSION_NONE;
194 if (depth1_directory[0] == '\0') {
195 (void)strlcpy(depth1_directory, ADIST_DIRECTORY_SENDER,
196 sizeof(depth1_directory));
198 /* Empty depth1_source is ok. */
199 TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
200 if (curhost->adh_role != ADIST_ROLE_SENDER)
202 if (curhost->adh_checksum == -1)
203 curhost->adh_checksum = depth1_checksum;
204 if (curhost->adh_compression == -1)
205 curhost->adh_compression = depth1_compression;
206 if (curhost->adh_directory[0] == '\0') {
207 (void)strlcpy(curhost->adh_directory,
209 sizeof(curhost->adh_directory));
211 if (curhost->adh_localaddr[0] == '\0') {
212 (void)strlcpy(curhost->adh_localaddr,
214 sizeof(curhost->adh_localaddr));
217 cursection = SECTION_GLOBAL;
223 PJDLOG_ASSERT(depth == 1);
224 PJDLOG_ASSERT(cursection == SECTION_GLOBAL);
226 cursection = SECTION_SENDER;
227 depth1_checksum = -1;
228 depth1_compression = -1;
229 depth1_source[0] = '\0';
230 depth1_directory[0] = '\0';
232 #ifndef HAVE_AUDIT_SYSCALLS
233 pjdlog_error("Sender functionality is not available.");
241 sender_entries sender_entry
252 compression_statement
255 sender_host_statement
258 receiver_statement: RECEIVER receiver_start receiver_entries CB
260 PJDLOG_ASSERT(depth == 0);
261 PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
264 * If not listen addresses were specified,
265 * configure default ones.
267 if (TAILQ_EMPTY(&lconfig->adc_listen)) {
268 struct adist_listen *lst;
270 if (family_supported(AF_INET)) {
271 lst = calloc(1, sizeof(*lst));
273 pjdlog_error("Unable to allocate memory for listen address.");
276 (void)strlcpy(lst->adl_addr,
277 ADIST_LISTEN_TLS_TCP4,
278 sizeof(lst->adl_addr));
279 TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
282 "No IPv4 support in the kernel, not listening on IPv4 address.");
284 if (family_supported(AF_INET6)) {
285 lst = calloc(1, sizeof(*lst));
287 pjdlog_error("Unable to allocate memory for listen address.");
290 (void)strlcpy(lst->adl_addr,
291 ADIST_LISTEN_TLS_TCP6,
292 sizeof(lst->adl_addr));
293 TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
296 "No IPv6 support in the kernel, not listening on IPv6 address.");
298 if (TAILQ_EMPTY(&lconfig->adc_listen)) {
299 pjdlog_error("No address to listen on.");
303 /* Configure defaults. */
304 if (depth1_directory[0] == '\0') {
305 (void)strlcpy(depth1_directory,
306 ADIST_DIRECTORY_RECEIVER,
307 sizeof(depth1_directory));
309 TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
310 if (curhost->adh_role != ADIST_ROLE_RECEIVER)
312 if (curhost->adh_directory[0] == '\0') {
313 if (snprintf(curhost->adh_directory,
314 sizeof(curhost->adh_directory), "%s/%s",
315 depth1_directory, curhost->adh_name) >=
316 (ssize_t)sizeof(curhost->adh_directory)) {
317 pjdlog_error("Directory value is too long.");
322 cursection = SECTION_GLOBAL;
328 PJDLOG_ASSERT(depth == 1);
329 PJDLOG_ASSERT(cursection == SECTION_GLOBAL);
331 cursection = SECTION_RECEIVER;
332 depth1_directory[0] = '\0';
338 receiver_entries receiver_entry
350 receiver_host_statement
354 checksum_statement: CHECKSUM checksum_type
356 PJDLOG_ASSERT(cursection == SECTION_SENDER);
360 depth1_checksum = $2;
363 PJDLOG_ASSERT(curhost != NULL);
364 curhost->adh_checksum = $2;
367 PJDLOG_ABORT("checksum at wrong depth level");
373 NONE { $$ = ADIST_CHECKSUM_NONE; }
375 CRC32 { $$ = ADIST_CHECKSUM_CRC32; }
377 SHA256 { $$ = ADIST_CHECKSUM_SHA256; }
380 compression_statement: COMPRESSION compression_type
382 PJDLOG_ASSERT(cursection == SECTION_SENDER);
386 depth1_compression = $2;
389 PJDLOG_ASSERT(curhost != NULL);
390 curhost->adh_compression = $2;
393 PJDLOG_ABORT("compression at wrong depth level");
399 NONE { $$ = ADIST_COMPRESSION_NONE; }
401 LZF { $$ = ADIST_COMPRESSION_LZF; }
405 directory_statement: DIRECTORY STR
407 PJDLOG_ASSERT(cursection == SECTION_SENDER ||
408 cursection == SECTION_RECEIVER);
412 if (strlcpy(depth1_directory, $2,
413 sizeof(depth1_directory)) >=
414 sizeof(depth1_directory)) {
415 pjdlog_error("Directory value is too long.");
419 if (!adjust_directory(depth1_directory))
423 if (cursection == SECTION_SENDER || $2[0] == '/') {
424 if (strlcpy(curhost->adh_directory, $2,
425 sizeof(curhost->adh_directory)) >=
426 sizeof(curhost->adh_directory)) {
427 pjdlog_error("Directory value is too long.");
431 } else /* if (cursection == SECTION_RECEIVER) */ {
432 if (depth1_directory[0] == '\0') {
433 pjdlog_error("Directory path must be absolute.");
437 if (snprintf(curhost->adh_directory,
438 sizeof(curhost->adh_directory), "%s/%s",
439 depth1_directory, $2) >=
440 (ssize_t)sizeof(curhost->adh_directory)) {
441 pjdlog_error("Directory value is too long.");
448 PJDLOG_ABORT("directory at wrong depth level");
454 source_statement: SOURCE STR
456 PJDLOG_RASSERT(cursection == SECTION_SENDER,
457 "The source variable must be in sender section.");
461 if (strlcpy(depth1_source, $2,
462 sizeof(depth1_source)) >=
463 sizeof(depth1_source)) {
464 pjdlog_error("Source value is too long.");
470 if (strlcpy(curhost->adh_localaddr, $2,
471 sizeof(curhost->adh_localaddr)) >=
472 sizeof(curhost->adh_localaddr)) {
473 pjdlog_error("Source value is too long.");
483 fingerprint_statement: FINGERPRINT STR
485 PJDLOG_ASSERT(cursection == SECTION_SENDER);
486 PJDLOG_ASSERT(depth == 2);
488 if (strncasecmp($2, "SHA256=", 7) != 0) {
489 pjdlog_error("Invalid fingerprint value.");
493 if (strlcpy(curhost->adh_fingerprint, $2,
494 sizeof(curhost->adh_fingerprint)) >=
495 sizeof(curhost->adh_fingerprint)) {
496 pjdlog_error("Fingerprint value is too long.");
504 password_statement: PASSWORD STR
506 PJDLOG_ASSERT(cursection == SECTION_SENDER ||
507 cursection == SECTION_RECEIVER);
508 PJDLOG_ASSERT(depth == 2);
510 if (strlcpy(curhost->adh_password, $2,
511 sizeof(curhost->adh_password)) >=
512 sizeof(curhost->adh_password)) {
513 pjdlog_error("Password value is too long.");
514 bzero($2, strlen($2));
518 bzero($2, strlen($2));
523 certfile_statement: CERTFILE STR
525 PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
526 PJDLOG_ASSERT(depth == 1);
528 if (strlcpy(lconfig->adc_certfile, $2,
529 sizeof(lconfig->adc_certfile)) >=
530 sizeof(lconfig->adc_certfile)) {
531 pjdlog_error("Certfile value is too long.");
539 keyfile_statement: KEYFILE STR
541 PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
542 PJDLOG_ASSERT(depth == 1);
544 if (strlcpy(lconfig->adc_keyfile, $2,
545 sizeof(lconfig->adc_keyfile)) >=
546 sizeof(lconfig->adc_keyfile)) {
547 pjdlog_error("Keyfile value is too long.");
555 listen_statement: LISTEN STR
557 struct adist_listen *lst;
559 PJDLOG_ASSERT(depth == 1);
560 PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
562 lst = calloc(1, sizeof(*lst));
564 pjdlog_error("Unable to allocate memory for listen address.");
568 if (strlcpy(lst->adl_addr, $2, sizeof(lst->adl_addr)) >=
569 sizeof(lst->adl_addr)) {
570 pjdlog_error("listen argument is too long.");
575 TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
580 sender_host_statement: HOST host_start OB sender_host_entries CB
582 /* Put it onto host list. */
583 TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next);
588 receiver_host_statement: HOST host_start OB receiver_host_entries CB
590 /* Put it onto host list. */
591 TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next);
598 /* Check if there is no duplicate entry. */
599 TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
600 if (strcmp(curhost->adh_name, $1) != 0)
602 if (curhost->adh_role == ADIST_ROLE_SENDER &&
603 cursection == SECTION_RECEIVER) {
606 if (curhost->adh_role == ADIST_ROLE_RECEIVER &&
607 cursection == SECTION_SENDER) {
610 pjdlog_error("%s host %s is configured more than once.",
611 curhost->adh_role == ADIST_ROLE_SENDER ?
612 "Sender" : "Receiver", curhost->adh_name);
617 curhost = calloc(1, sizeof(*curhost));
618 if (curhost == NULL) {
619 pjdlog_error("Unable to allocate memory for host configuration.");
623 if (strlcpy(curhost->adh_name, $1, sizeof(curhost->adh_name)) >=
624 sizeof(curhost->adh_name)) {
625 pjdlog_error("Host name is too long.");
630 curhost->adh_role = cursection == SECTION_SENDER ?
631 ADIST_ROLE_SENDER : ADIST_ROLE_RECEIVER;
632 curhost->adh_version = ADIST_VERSION;
633 curhost->adh_localaddr[0] = '\0';
634 curhost->adh_remoteaddr[0] = '\0';
635 curhost->adh_remote = NULL;
636 curhost->adh_directory[0] = '\0';
637 curhost->adh_password[0] = '\0';
638 curhost->adh_fingerprint[0] = '\0';
639 curhost->adh_worker_pid = 0;
640 curhost->adh_conn = NULL;
646 sender_host_entries sender_host_entry
656 fingerprint_statement
663 compression_statement
667 receiver_host_entries:
669 receiver_host_entries receiver_host_entry
680 remote_statement: REMOTE STR
682 PJDLOG_ASSERT(depth == 2);
683 PJDLOG_ASSERT(cursection == SECTION_SENDER ||
684 cursection == SECTION_RECEIVER);
686 if (strlcpy(curhost->adh_remoteaddr, $2,
687 sizeof(curhost->adh_remoteaddr)) >=
688 sizeof(curhost->adh_remoteaddr)) {
689 pjdlog_error("Remote value is too long.");
700 family_supported(int family)
704 sock = socket(family, SOCK_STREAM, 0);
705 if (sock == -1 && errno == EPROTONOSUPPORT)
713 adjust_directory(char *path)
720 pjdlog_error("Directory path is empty.");
723 if (path[len - 1] != '/')
728 if (path[0] != '/') {
729 pjdlog_error("Directory path must be absolute.");
736 my_name(char *name, size_t size)
738 char buf[MAXHOSTNAMELEN];
741 if (gethostname(buf, sizeof(buf)) < 0) {
742 pjdlog_errno(LOG_ERR, "gethostname() failed");
746 /* First component of the host name. */
747 pos = strchr(buf, '.');
749 (void)strlcpy(name, buf, size);
751 (void)strlcpy(name, buf, MIN((size_t)(pos - buf + 1), size));
753 if (name[0] == '\0') {
754 pjdlog_error("Empty host name.");
762 yyerror(const char *str)
765 pjdlog_error("Unable to parse configuration file at line %d near '%s': %s",
766 lineno, yytext, str);
769 struct adist_config *
770 yy_config_parse(const char *config, bool exitonerror)
775 cursection = SECTION_GLOBAL;
779 lconfig = calloc(1, sizeof(*lconfig));
780 if (lconfig == NULL) {
781 pjdlog_error("Unable to allocate memory for configuration.");
786 TAILQ_INIT(&lconfig->adc_hosts);
787 TAILQ_INIT(&lconfig->adc_listen);
788 lconfig->adc_name[0] = '\0';
789 lconfig->adc_timeout = -1;
790 lconfig->adc_pidfile[0] = '\0';
791 lconfig->adc_certfile[0] = '\0';
792 lconfig->adc_keyfile[0] = '\0';
794 yyin = fopen(config, "r");
796 pjdlog_errno(LOG_ERR, "Unable to open configuration file %s",
798 yy_config_free(lconfig);
807 yy_config_free(lconfig);
814 * Let's see if everything is set up.
816 if (lconfig->adc_name[0] == '\0' && my_name(lconfig->adc_name,
817 sizeof(lconfig->adc_name)) == -1) {
818 yy_config_free(lconfig);
823 if (lconfig->adc_timeout == -1)
824 lconfig->adc_timeout = ADIST_TIMEOUT;
825 if (lconfig->adc_pidfile[0] == '\0') {
826 (void)strlcpy(lconfig->adc_pidfile, ADIST_PIDFILE,
827 sizeof(lconfig->adc_pidfile));
829 if (lconfig->adc_certfile[0] == '\0') {
830 (void)strlcpy(lconfig->adc_certfile, ADIST_CERTFILE,
831 sizeof(lconfig->adc_certfile));
833 if (lconfig->adc_keyfile[0] == '\0') {
834 (void)strlcpy(lconfig->adc_keyfile, ADIST_KEYFILE,
835 sizeof(lconfig->adc_keyfile));
842 yy_config_free(struct adist_config *config)
844 struct adist_host *adhost;
845 struct adist_listen *lst;
847 while ((lst = TAILQ_FIRST(&config->adc_listen)) != NULL) {
848 TAILQ_REMOVE(&config->adc_listen, lst, adl_next);
851 while ((adhost = TAILQ_FIRST(&config->adc_hosts)) != NULL) {
852 TAILQ_REMOVE(&config->adc_hosts, adhost, adh_next);
853 bzero(adhost, sizeof(*adhost));