parse.y revision 243730
1139825Simp%{ 2148078Srwatson/*- 3148078Srwatson * Copyright (c) 2012 The FreeBSD Foundation 4148078Srwatson * All rights reserved. 592654Sjeff * 692654Sjeff * This software was developed by Pawel Jakub Dawidek under sponsorship from 792654Sjeff * the FreeBSD Foundation. 892654Sjeff * 992654Sjeff * Redistribution and use in source and binary forms, with or without 1092654Sjeff * modification, are permitted provided that the following conditions 1192654Sjeff * are met: 1292654Sjeff * 1. Redistributions of source code must retain the above copyright 1392654Sjeff * notice, this list of conditions and the following disclaimer. 1492654Sjeff * 2. Redistributions in binary form must reproduce the above copyright 1592654Sjeff * notice, this list of conditions and the following disclaimer in the 1692654Sjeff * documentation and/or other materials provided with the distribution. 1792654Sjeff * 1892654Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1992654Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2092654Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2192654Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2292654Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2392654Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2492654Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2592654Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2692654Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2792654Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2892654Sjeff * SUCH DAMAGE. 2992654Sjeff * 3092654Sjeff * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/parse.y#3 $ 3192654Sjeff */ 3292654Sjeff 3392654Sjeff#include "config.h" 3492654Sjeff 3592654Sjeff#include <sys/types.h> 3692654Sjeff#include <sys/queue.h> 3792654Sjeff#include <sys/sysctl.h> 3892654Sjeff 3992654Sjeff#include <arpa/inet.h> 4092654Sjeff 4192654Sjeff#include <err.h> 42184546Skeramida#include <errno.h> 4392654Sjeff#include <stdio.h> 4492654Sjeff#include <string.h> 4592654Sjeff#include <sysexits.h> 4692654Sjeff#include <unistd.h> 47129906Sbmilekic#ifndef HAVE_STRLCPY 4892654Sjeff#include <compat/strlcpy.h> 4992654Sjeff#endif 5092654Sjeff 51166213Smohans#include <pjdlog.h> 52166213Smohans 53244024Spjd#include "auditdistd.h" 5492654Sjeff 5592654Sjeffextern int depth; 5692654Sjeffextern int lineno; 5792654Sjeff 5892654Sjeffextern FILE *yyin; 5992654Sjeffextern char *yytext; 60132987Sgreen 61244024Spjdstatic struct adist_config *lconfig; 6292654Sjeffstatic struct adist_host *curhost; 63132987Sgreen#define SECTION_GLOBAL 0 64132987Sgreen#define SECTION_SENDER 1 6592654Sjeff#define SECTION_RECEIVER 2 6692654Sjeffstatic int cursection; 6792654Sjeff 68105689Ssheldonh/* Sender section. */ 6992654Sjeffstatic char depth1_source[ADIST_ADDRSIZE]; 70132987Sgreenstatic int depth1_checksum; 7192654Sjeffstatic int depth1_compression; 7292654Sjeff/* Sender and receiver sections. */ 7392654Sjeffstatic char depth1_directory[PATH_MAX]; 7492654Sjeff 7592654Sjeffstatic bool adjust_directory(char *path); 7692654Sjeffstatic bool family_supported(int family); 7792654Sjeff 7892654Sjeffextern void yyrestart(FILE *); 79244024Spjd%} 8092654Sjeff 8192654Sjeff%token CB 8292654Sjeff%token CERTFILE 8392654Sjeff%token DIRECTORY 8492654Sjeff%token FINGERPRINT 8592654Sjeff%token HOST 8692654Sjeff%token KEYFILE 8792654Sjeff%token LISTEN 8892654Sjeff%token NAME 8992654Sjeff%token OB 90244024Spjd%token PASSWORD 9192654Sjeff%token PIDFILE 9292654Sjeff%token RECEIVER REMOTE 9392654Sjeff%token SENDER SOURCE 9492654Sjeff%token TIMEOUT 9592654Sjeff 96132987Sgreen/* 97244024Spjd%type <num> checksum_type 9892654Sjeff%type <num> compression_type 99132987Sgreen*/ 100132987Sgreen 10192654Sjeff%union 10292654Sjeff{ 103244024Spjd int num; 104184546Skeramida char *str; 105184546Skeramida} 10692654Sjeff 107132987Sgreen%token <num> NUM 10892654Sjeff%token <str> STR 10992654Sjeff 11092654Sjeff%% 11192654Sjeff 11292654Sjeffstatements: 113244024Spjd | 11492654Sjeff statements statement 11592654Sjeff ; 11692654Sjeff 11792654Sjeffstatement: 11892654Sjeff name_statement 11992654Sjeff | 12092654Sjeff pidfile_statement 12192654Sjeff | 122184546Skeramida timeout_statement 12392654Sjeff | 12492654Sjeff sender_statement 12592654Sjeff | 12692654Sjeff receiver_statement 127251826Sjeff ; 128251826Sjeff 129251826Sjeffname_statement: NAME STR 130251826Sjeff { 131251826Sjeff PJDLOG_RASSERT(depth == 0, 132251826Sjeff "The name variable can only be specificed in the global section."); 133251826Sjeff 134251826Sjeff if (lconfig->adc_name[0] != '\0') { 135251826Sjeff pjdlog_error("The name variable is specified twice."); 136251826Sjeff free($2); 13792654Sjeff return (1); 13892654Sjeff } 139244024Spjd if (strlcpy(lconfig->adc_name, $2, 14092654Sjeff sizeof(lconfig->adc_name)) >= 14192654Sjeff sizeof(lconfig->adc_name)) { 14292654Sjeff pjdlog_error("The name value is too long."); 14392654Sjeff free($2); 14492654Sjeff return (1); 145184546Skeramida } 14692654Sjeff free($2); 147105689Ssheldonh } 14892654Sjeff ; 14992654Sjeff 15092654Sjeffpidfile_statement: PIDFILE STR 15192654Sjeff { 15292654Sjeff PJDLOG_RASSERT(depth == 0, 15392654Sjeff "The pidfile variable can only be specificed in the global section."); 15492654Sjeff 15592654Sjeff if (lconfig->adc_pidfile[0] != '\0') { 15692654Sjeff pjdlog_error("The pidfile variable is specified twice."); 15792654Sjeff free($2); 15892654Sjeff return (1); 15992654Sjeff } 16092654Sjeff if (strcmp($2, "none") != 0 && $2[0] != '/') { 16192654Sjeff pjdlog_error("The pidfile variable must be set to absolute pathname or \"none\"."); 162184546Skeramida free($2); 16392654Sjeff return (1); 16492654Sjeff } 165184546Skeramida if (strlcpy(lconfig->adc_pidfile, $2, 16692654Sjeff sizeof(lconfig->adc_pidfile)) >= 16792654Sjeff sizeof(lconfig->adc_pidfile)) { 16892654Sjeff pjdlog_error("The pidfile value is too long."); 16992654Sjeff free($2); 170184546Skeramida return (1); 17192654Sjeff } 172184546Skeramida free($2); 17392654Sjeff } 17492654Sjeff ; 17592654Sjeff 17692654Sjefftimeout_statement: TIMEOUT NUM 17792654Sjeff { 178242152Smdf PJDLOG_ASSERT(depth == 0); 179242152Smdf 180249313Sglebius lconfig->adc_timeout = $2; 18192654Sjeff } 182120223Sjeff ; 183129906Sbmilekic 184129906Sbmilekicsender_statement: SENDER sender_start sender_entries CB 185129906Sbmilekic { 186184546Skeramida PJDLOG_ASSERT(depth == 0); 187129906Sbmilekic PJDLOG_ASSERT(cursection == SECTION_SENDER); 188184546Skeramida 189129906Sbmilekic /* Configure defaults. */ 190129906Sbmilekic if (depth1_checksum == -1) 191129906Sbmilekic depth1_checksum = ADIST_CHECKSUM_NONE; 192129906Sbmilekic if (depth1_compression == -1) 193129906Sbmilekic depth1_compression = ADIST_COMPRESSION_NONE; 194129906Sbmilekic if (depth1_directory[0] == '\0') { 195129906Sbmilekic (void)strlcpy(depth1_directory, ADIST_DIRECTORY_SENDER, 196129906Sbmilekic sizeof(depth1_directory)); 197129906Sbmilekic } 198129906Sbmilekic /* Empty depth1_source is ok. */ 199129906Sbmilekic TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { 200129906Sbmilekic if (curhost->adh_role != ADIST_ROLE_SENDER) 201129906Sbmilekic continue; 202129906Sbmilekic if (curhost->adh_checksum == -1) 203129906Sbmilekic curhost->adh_checksum = depth1_checksum; 204129906Sbmilekic if (curhost->adh_compression == -1) 205129906Sbmilekic curhost->adh_compression = depth1_compression; 206129913Sbmilekic if (curhost->adh_directory[0] == '\0') { 207129913Sbmilekic (void)strlcpy(curhost->adh_directory, 208129913Sbmilekic depth1_directory, 209129906Sbmilekic sizeof(curhost->adh_directory)); 210129906Sbmilekic } 211129906Sbmilekic if (curhost->adh_localaddr[0] == '\0') { 212129906Sbmilekic (void)strlcpy(curhost->adh_localaddr, 213129906Sbmilekic depth1_source, 214129906Sbmilekic sizeof(curhost->adh_localaddr)); 215129906Sbmilekic } 216129906Sbmilekic } 217129906Sbmilekic cursection = SECTION_GLOBAL; 218187681Sjeff } 219187681Sjeff ; 220187681Sjeff 221187681Sjeffsender_start: OB 222187681Sjeff { 223187681Sjeff PJDLOG_ASSERT(depth == 1); 224244024Spjd PJDLOG_ASSERT(cursection == SECTION_GLOBAL); 225187681Sjeff 226187681Sjeff cursection = SECTION_SENDER; 227187681Sjeff depth1_checksum = -1; 228187681Sjeff depth1_compression = -1; 229251826Sjeff depth1_source[0] = '\0'; 230251826Sjeff depth1_directory[0] = '\0'; 231251826Sjeff 232251826Sjeff#ifndef HAVE_AUDIT_SYSCALLS 233251826Sjeff pjdlog_error("Sender functionality is not available."); 234251826Sjeff return (1); 235251826Sjeff#endif 236251826Sjeff } 237252040Sjeff ; 238251826Sjeff 239251826Sjeffsender_entries: 240251826Sjeff | 241251826Sjeff sender_entries sender_entry 242120223Sjeff ; 243120223Sjeff 244120223Sjeffsender_entry: 245148072Ssilby source_statement 246120223Sjeff | 24792654Sjeff directory_statement 24892654Sjeff/* 24992654Sjeff | 250184546Skeramida checksum_statement 25192654Sjeff | 25292654Sjeff compression_statement 25392654Sjeff*/ 25492654Sjeff | 25595758Sjeff sender_host_statement 256103531Sjeff ; 257103531Sjeff 258103531Sjeffreceiver_statement: RECEIVER receiver_start receiver_entries CB 259103531Sjeff { 260103531Sjeff PJDLOG_ASSERT(depth == 0); 261103531Sjeff PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 262103531Sjeff 263103531Sjeff /* 264129906Sbmilekic * If not listen addresses were specified, 265129906Sbmilekic * configure default ones. 266129906Sbmilekic */ 267187681Sjeff if (TAILQ_EMPTY(&lconfig->adc_listen)) { 268187681Sjeff struct adist_listen *lst; 269187681Sjeff 270187681Sjeff if (family_supported(AF_INET)) { 271187681Sjeff lst = calloc(1, sizeof(*lst)); 272187681Sjeff if (lst == NULL) { 273187681Sjeff pjdlog_error("Unable to allocate memory for listen address."); 274230623Skmacy return (1); 275230623Skmacy } 276230623Skmacy (void)strlcpy(lst->adl_addr, 277230623Skmacy ADIST_LISTEN_TLS_TCP4, 278249264Sglebius sizeof(lst->adl_addr)); 279249264Sglebius TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); 280249264Sglebius } else { 281249264Sglebius pjdlog_debug(1, 28292654Sjeff "No IPv4 support in the kernel, not listening on IPv4 address."); 283187681Sjeff } 284187681Sjeff if (family_supported(AF_INET6)) { 285187681Sjeff lst = calloc(1, sizeof(*lst)); 286187681Sjeff if (lst == NULL) { 287187681Sjeff pjdlog_error("Unable to allocate memory for listen address."); 288187681Sjeff return (1); 289226313Sglebius } 290249264Sglebius (void)strlcpy(lst->adl_addr, 291187681Sjeff ADIST_LISTEN_TLS_TCP6, 29292654Sjeff sizeof(lst->adl_addr)); 29392654Sjeff TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); 29492654Sjeff } else { 29592654Sjeff pjdlog_debug(1, 29692654Sjeff "No IPv6 support in the kernel, not listening on IPv6 address."); 29792654Sjeff } 298166654Srwatson if (TAILQ_EMPTY(&lconfig->adc_listen)) { 29992654Sjeff pjdlog_error("No address to listen on."); 30092654Sjeff return (1); 30194161Sjeff } 30292654Sjeff } 30392654Sjeff /* Configure defaults. */ 30492654Sjeff if (depth1_directory[0] == '\0') { 30592654Sjeff (void)strlcpy(depth1_directory, 30692654Sjeff ADIST_DIRECTORY_RECEIVER, 30794161Sjeff sizeof(depth1_directory)); 30892654Sjeff } 30992654Sjeff TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { 31092654Sjeff if (curhost->adh_role != ADIST_ROLE_RECEIVER) 31192654Sjeff continue; 31292654Sjeff if (curhost->adh_directory[0] == '\0') { 31392654Sjeff if (snprintf(curhost->adh_directory, 31492654Sjeff sizeof(curhost->adh_directory), "%s/%s", 31595766Sjeff depth1_directory, curhost->adh_name) >= 31692654Sjeff (ssize_t)sizeof(curhost->adh_directory)) { 31792654Sjeff pjdlog_error("Directory value is too long."); 318184546Skeramida return (1); 319184546Skeramida } 320184546Skeramida } 32192654Sjeff } 32292654Sjeff cursection = SECTION_GLOBAL; 32395766Sjeff } 32492654Sjeff ; 32592654Sjeff 32692654Sjeffreceiver_start: OB 32792654Sjeff { 32892654Sjeff PJDLOG_ASSERT(depth == 1); 32992654Sjeff PJDLOG_ASSERT(cursection == SECTION_GLOBAL); 33092654Sjeff 33195766Sjeff cursection = SECTION_RECEIVER; 33292654Sjeff depth1_directory[0] = '\0'; 33392654Sjeff } 33495766Sjeff ; 33592654Sjeff 33695766Sjeffreceiver_entries: 33792654Sjeff | 33892654Sjeff receiver_entries receiver_entry 33992654Sjeff ; 34092654Sjeff 34192654Sjeffreceiver_entry: 34292654Sjeff listen_statement 34392654Sjeff | 34492654Sjeff directory_statement 34592654Sjeff | 34692654Sjeff certfile_statement 34792654Sjeff | 34892654Sjeff keyfile_statement 34992654Sjeff | 35092654Sjeff receiver_host_statement 35192654Sjeff ; 35292654Sjeff 35392654Sjeff/* 35492654Sjeffchecksum_statement: CHECKSUM checksum_type 35592654Sjeff { 35692654Sjeff PJDLOG_ASSERT(cursection == SECTION_SENDER); 35792654Sjeff 35892654Sjeff switch (depth) { 35992654Sjeff case 1: 36092654Sjeff depth1_checksum = $2; 36192654Sjeff break; 36292654Sjeff case 2: 36392654Sjeff PJDLOG_ASSERT(curhost != NULL); 364100326Smarkm curhost->adh_checksum = $2; 36592654Sjeff break; 36692654Sjeff default: 36792654Sjeff PJDLOG_ABORT("checksum at wrong depth level"); 36892654Sjeff } 36992654Sjeff } 37092654Sjeff ; 37192654Sjeff 37292654Sjeffchecksum_type: 37392654Sjeff NONE { $$ = ADIST_CHECKSUM_NONE; } 37492654Sjeff | 37592654Sjeff CRC32 { $$ = ADIST_CHECKSUM_CRC32; } 376184546Skeramida | 377184546Skeramida SHA256 { $$ = ADIST_CHECKSUM_SHA256; } 37892654Sjeff ; 37992654Sjeff 38092654Sjeffcompression_statement: COMPRESSION compression_type 38192654Sjeff { 382184546Skeramida PJDLOG_ASSERT(cursection == SECTION_SENDER); 38392654Sjeff 38492654Sjeff switch (depth) { 385249313Sglebius case 1: 38692654Sjeff depth1_compression = $2; 38792654Sjeff break; 38892654Sjeff case 2: 38992654Sjeff PJDLOG_ASSERT(curhost != NULL); 39092654Sjeff curhost->adh_compression = $2; 391184546Skeramida break; 392184546Skeramida default: 393184546Skeramida PJDLOG_ABORT("compression at wrong depth level"); 39492654Sjeff } 39592654Sjeff } 39692654Sjeff ; 39792654Sjeff 398249313Sglebiuscompression_type: 39992654Sjeff NONE { $$ = ADIST_COMPRESSION_NONE; } 40092654Sjeff | 40192654Sjeff LZF { $$ = ADIST_COMPRESSION_LZF; } 40292654Sjeff ; 40392654Sjeff*/ 40492654Sjeff 40592654Sjeffdirectory_statement: DIRECTORY STR 40692654Sjeff { 40792654Sjeff PJDLOG_ASSERT(cursection == SECTION_SENDER || 40892654Sjeff cursection == SECTION_RECEIVER); 40992654Sjeff 41092654Sjeff switch (depth) { 41192654Sjeff case 1: 41292654Sjeff if (strlcpy(depth1_directory, $2, 41392654Sjeff sizeof(depth1_directory)) >= 414151104Sdes sizeof(depth1_directory)) { 41592654Sjeff pjdlog_error("Directory value is too long."); 41692654Sjeff free($2); 41792654Sjeff return (1); 418151104Sdes } 41992654Sjeff if (!adjust_directory(depth1_directory)) 42092654Sjeff return (1); 42192654Sjeff break; 42292654Sjeff case 2: 42392654Sjeff if (cursection == SECTION_SENDER || $2[0] == '/') { 42492654Sjeff if (strlcpy(curhost->adh_directory, $2, 425103531Sjeff sizeof(curhost->adh_directory)) >= 42692654Sjeff sizeof(curhost->adh_directory)) { 42792654Sjeff pjdlog_error("Directory value is too long."); 42892654Sjeff free($2); 42992654Sjeff return (1); 43092654Sjeff } 431103531Sjeff } else /* if (cursection == SECTION_RECEIVER) */ { 43292654Sjeff if (depth1_directory[0] == '\0') { 433244024Spjd pjdlog_error("Directory path must be absolute."); 434103531Sjeff free($2); 43592654Sjeff return (1); 43692654Sjeff } 43792654Sjeff if (snprintf(curhost->adh_directory, 43892654Sjeff sizeof(curhost->adh_directory), "%s/%s", 43992654Sjeff depth1_directory, $2) >= 44092654Sjeff (ssize_t)sizeof(curhost->adh_directory)) { 44192654Sjeff pjdlog_error("Directory value is too long."); 44292654Sjeff free($2); 44392654Sjeff return (1); 44492654Sjeff } 44592654Sjeff } 44692654Sjeff break; 44792654Sjeff default: 44892654Sjeff PJDLOG_ABORT("directory at wrong depth level"); 44992654Sjeff } 450166654Srwatson free($2); 451166654Srwatson } 452166654Srwatson ; 453166654Srwatson 454166654Srwatsonsource_statement: SOURCE STR 455166654Srwatson { 456166654Srwatson PJDLOG_RASSERT(cursection == SECTION_SENDER, 457166654Srwatson "The source variable must be in sender section."); 458166654Srwatson 459166654Srwatson switch (depth) { 460166654Srwatson case 1: 461166654Srwatson if (strlcpy(depth1_source, $2, 462247360Sattilio sizeof(depth1_source)) >= 463247360Sattilio sizeof(depth1_source)) { 46492654Sjeff pjdlog_error("Source value is too long."); 46592654Sjeff free($2); 466184546Skeramida return (1); 467247360Sattilio } 46892654Sjeff break; 46992654Sjeff case 2: 470247360Sattilio if (strlcpy(curhost->adh_localaddr, $2, 47192654Sjeff sizeof(curhost->adh_localaddr)) >= 47292654Sjeff sizeof(curhost->adh_localaddr)) { 47392654Sjeff pjdlog_error("Source value is too long."); 474247360Sattilio free($2); 475247360Sattilio return (1); 476247360Sattilio } 47792654Sjeff break; 478247360Sattilio } 47992654Sjeff free($2); 48092758Sjeff } 48192758Sjeff ; 48292758Sjeff 48392758Sjefffingerprint_statement: FINGERPRINT STR 48492758Sjeff { 485213911Slstewart PJDLOG_ASSERT(cursection == SECTION_SENDER); 48692758Sjeff PJDLOG_ASSERT(depth == 2); 48792758Sjeff 488213911Slstewart if (strncasecmp($2, "SHA256=", 7) != 0) { 48992758Sjeff pjdlog_error("Invalid fingerprint value."); 490213911Slstewart free($2); 49192654Sjeff return (1); 49292654Sjeff } 493211396Sandre if (strlcpy(curhost->adh_fingerprint, $2, 494211396Sandre sizeof(curhost->adh_fingerprint)) >= 495211396Sandre sizeof(curhost->adh_fingerprint)) { 496211396Sandre pjdlog_error("Fingerprint value is too long."); 497211396Sandre free($2); 498211396Sandre return (1); 499211396Sandre } 500211396Sandre free($2); 501211396Sandre } 502211396Sandre ; 503211396Sandre 504211396Sandrepassword_statement: PASSWORD STR 505243998Spjd { 506243998Spjd PJDLOG_ASSERT(cursection == SECTION_SENDER || 507243998Spjd cursection == SECTION_RECEIVER); 508243998Spjd PJDLOG_ASSERT(depth == 2); 509243998Spjd 510243998Spjd if (strlcpy(curhost->adh_password, $2, 511243998Spjd sizeof(curhost->adh_password)) >= 512243998Spjd sizeof(curhost->adh_password)) { 513243998Spjd pjdlog_error("Password value is too long."); 514243998Spjd bzero($2, strlen($2)); 515243998Spjd free($2); 516243998Spjd return (1); 517213910Slstewart } 518213910Slstewart bzero($2, strlen($2)); 519213910Slstewart free($2); 520213910Slstewart } 521213910Slstewart ; 522213910Slstewart 523213910Slstewartcertfile_statement: CERTFILE STR 524213910Slstewart { 525213910Slstewart PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 526213910Slstewart PJDLOG_ASSERT(depth == 1); 527213910Slstewart 528129906Sbmilekic if (strlcpy(lconfig->adc_certfile, $2, 529129906Sbmilekic sizeof(lconfig->adc_certfile)) >= 530129906Sbmilekic sizeof(lconfig->adc_certfile)) { 531129906Sbmilekic pjdlog_error("Certfile value is too long."); 532184546Skeramida free($2); 533129906Sbmilekic return (1); 534129906Sbmilekic } 535129906Sbmilekic free($2); 536129906Sbmilekic } 537129906Sbmilekic ; 538129906Sbmilekic 539129906Sbmilekickeyfile_statement: KEYFILE STR 540129906Sbmilekic { 541129906Sbmilekic PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 542129906Sbmilekic PJDLOG_ASSERT(depth == 1); 543184546Skeramida 544184546Skeramida if (strlcpy(lconfig->adc_keyfile, $2, 545129906Sbmilekic sizeof(lconfig->adc_keyfile)) >= 546129906Sbmilekic sizeof(lconfig->adc_keyfile)) { 547129906Sbmilekic pjdlog_error("Keyfile value is too long."); 548129906Sbmilekic free($2); 549129906Sbmilekic return (1); 550247360Sattilio } 55192654Sjeff free($2); 55292654Sjeff } 553184546Skeramida ; 55492654Sjeff 55592654Sjefflisten_statement: LISTEN STR 55692654Sjeff { 55792654Sjeff struct adist_listen *lst; 55892654Sjeff 55992654Sjeff PJDLOG_ASSERT(depth == 1); 56092654Sjeff PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 56192654Sjeff 56292654Sjeff lst = calloc(1, sizeof(*lst)); 56392654Sjeff if (lst == NULL) { 56492654Sjeff pjdlog_error("Unable to allocate memory for listen address."); 56592654Sjeff free($2); 56692654Sjeff return (1); 56792654Sjeff } 56892654Sjeff if (strlcpy(lst->adl_addr, $2, sizeof(lst->adl_addr)) >= 56992654Sjeff sizeof(lst->adl_addr)) { 57092654Sjeff pjdlog_error("listen argument is too long."); 57192654Sjeff free($2); 57292654Sjeff free(lst); 57392654Sjeff return (1); 57492654Sjeff } 57592654Sjeff TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); 57692654Sjeff free($2); 57792654Sjeff } 57892654Sjeff ; 57992654Sjeff 58092654Sjeffsender_host_statement: HOST host_start OB sender_host_entries CB 581184546Skeramida { 58292654Sjeff /* Put it onto host list. */ 58392654Sjeff TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next); 58492654Sjeff curhost = NULL; 585177921Salc } 58692654Sjeff ; 58794157Sjeff 58892654Sjeffreceiver_host_statement: HOST host_start OB receiver_host_entries CB 58992654Sjeff { 59092654Sjeff /* Put it onto host list. */ 59192654Sjeff TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next); 59292654Sjeff curhost = NULL; 59392654Sjeff } 59492654Sjeff ; 59592654Sjeff 59692654Sjeffhost_start: STR 59792654Sjeff { 59892654Sjeff /* Check if there is no duplicate entry. */ 59992654Sjeff TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { 60092654Sjeff if (strcmp(curhost->adh_name, $1) != 0) 60192654Sjeff continue; 60292654Sjeff if (curhost->adh_role == ADIST_ROLE_SENDER && 60392654Sjeff cursection == SECTION_RECEIVER) { 60492654Sjeff continue; 605129906Sbmilekic } 606129906Sbmilekic if (curhost->adh_role == ADIST_ROLE_RECEIVER && 607129906Sbmilekic cursection == SECTION_SENDER) { 608129906Sbmilekic continue; 609129906Sbmilekic } 610129906Sbmilekic pjdlog_error("%s host %s is configured more than once.", 611129906Sbmilekic curhost->adh_role == ADIST_ROLE_SENDER ? 612244024Spjd "Sender" : "Receiver", curhost->adh_name); 613129906Sbmilekic free($1); 614129906Sbmilekic return (1); 615129906Sbmilekic } 616249313Sglebius 617129906Sbmilekic curhost = calloc(1, sizeof(*curhost)); 618249313Sglebius if (curhost == NULL) { 61992654Sjeff pjdlog_error("Unable to allocate memory for host configuration."); 620147996Srwatson free($1); 621165809Sjhb return (1); 622165809Sjhb } 623165809Sjhb if (strlcpy(curhost->adh_name, $1, sizeof(curhost->adh_name)) >= 624165809Sjhb sizeof(curhost->adh_name)) { 625165809Sjhb pjdlog_error("Host name is too long."); 626165809Sjhb free($1); 627244024Spjd return (1); 628165809Sjhb } 629165809Sjhb free($1); 630166213Smohans curhost->adh_role = cursection == SECTION_SENDER ? 631165809Sjhb ADIST_ROLE_SENDER : ADIST_ROLE_RECEIVER; 632165809Sjhb curhost->adh_version = ADIST_VERSION; 633147996Srwatson curhost->adh_localaddr[0] = '\0'; 634184546Skeramida curhost->adh_remoteaddr[0] = '\0'; 635184546Skeramida curhost->adh_remote = NULL; 636147996Srwatson curhost->adh_directory[0] = '\0'; 637147996Srwatson curhost->adh_password[0] = '\0'; 638147996Srwatson curhost->adh_fingerprint[0] = '\0'; 639249313Sglebius curhost->adh_worker_pid = 0; 640249313Sglebius curhost->adh_conn = NULL; 641249313Sglebius } 642249313Sglebius ; 643147996Srwatson 644147996Srwatsonsender_host_entries: 645148371Srwatson | 646148371Srwatson sender_host_entries sender_host_entry 647147996Srwatson ; 648147996Srwatson 649147996Srwatsonsender_host_entry: 650147996Srwatson source_statement 651148371Srwatson | 652249313Sglebius remote_statement 653249313Sglebius | 654249313Sglebius directory_statement 655249313Sglebius | 656249313Sglebius fingerprint_statement 657147996Srwatson | 658147996Srwatson password_statement 659147996Srwatson/* 660147996Srwatson | 661249313Sglebius checksum_statement 662249313Sglebius | 663249313Sglebius compression_statement 664249313Sglebius*/ 665249313Sglebius ; 666249313Sglebius 667249313Sglebiusreceiver_host_entries: 668249313Sglebius | 669249313Sglebius receiver_host_entries receiver_host_entry 670249313Sglebius ; 671147996Srwatson 672147996Srwatsonreceiver_host_entry: 673147996Srwatson remote_statement 674249313Sglebius | 675249313Sglebius directory_statement 676249313Sglebius | 677249313Sglebius password_statement 678147996Srwatson ; 679147996Srwatson 68092654Sjeffremote_statement: REMOTE STR 681 { 682 PJDLOG_ASSERT(depth == 2); 683 PJDLOG_ASSERT(cursection == SECTION_SENDER || 684 cursection == SECTION_RECEIVER); 685 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."); 690 free($2); 691 return (1); 692 } 693 free($2); 694 } 695 ; 696 697%% 698 699static bool 700family_supported(int family) 701{ 702 int sock; 703 704 sock = socket(family, SOCK_STREAM, 0); 705 if (sock == -1 && errno == EPROTONOSUPPORT) 706 return (false); 707 if (sock >= 0) 708 (void)close(sock); 709 return (true); 710} 711 712static bool 713adjust_directory(char *path) 714{ 715 size_t len; 716 717 len = strlen(path); 718 for (;;) { 719 if (len == 0) { 720 pjdlog_error("Directory path is empty."); 721 return (false); 722 } 723 if (path[len - 1] != '/') 724 break; 725 len--; 726 path[len] = '\0'; 727 } 728 if (path[0] != '/') { 729 pjdlog_error("Directory path must be absolute."); 730 return (false); 731 } 732 return (true); 733} 734 735static int 736my_name(char *name, size_t size) 737{ 738 char buf[MAXHOSTNAMELEN]; 739 char *pos; 740 741 if (gethostname(buf, sizeof(buf)) < 0) { 742 pjdlog_errno(LOG_ERR, "gethostname() failed"); 743 return (-1); 744 } 745 746 /* First component of the host name. */ 747 pos = strchr(buf, '.'); 748 if (pos == NULL) 749 (void)strlcpy(name, buf, size); 750 else 751 (void)strlcpy(name, buf, MIN((size_t)(pos - buf + 1), size)); 752 753 if (name[0] == '\0') { 754 pjdlog_error("Empty host name."); 755 return (-1); 756 } 757 758 return (0); 759} 760 761void 762yyerror(const char *str) 763{ 764 765 pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", 766 lineno, yytext, str); 767} 768 769struct adist_config * 770yy_config_parse(const char *config, bool exitonerror) 771{ 772 int ret; 773 774 curhost = NULL; 775 cursection = SECTION_GLOBAL; 776 depth = 0; 777 lineno = 0; 778 779 lconfig = calloc(1, sizeof(*lconfig)); 780 if (lconfig == NULL) { 781 pjdlog_error("Unable to allocate memory for configuration."); 782 if (exitonerror) 783 exit(EX_TEMPFAIL); 784 return (NULL); 785 } 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'; 793 794 yyin = fopen(config, "r"); 795 if (yyin == NULL) { 796 pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", 797 config); 798 yy_config_free(lconfig); 799 if (exitonerror) 800 exit(EX_OSFILE); 801 return (NULL); 802 } 803 yyrestart(yyin); 804 ret = yyparse(); 805 fclose(yyin); 806 if (ret != 0) { 807 yy_config_free(lconfig); 808 if (exitonerror) 809 exit(EX_CONFIG); 810 return (NULL); 811 } 812 813 /* 814 * Let's see if everything is set up. 815 */ 816 if (lconfig->adc_name[0] == '\0' && my_name(lconfig->adc_name, 817 sizeof(lconfig->adc_name)) == -1) { 818 yy_config_free(lconfig); 819 if (exitonerror) 820 exit(EX_CONFIG); 821 return (NULL); 822 } 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)); 828 } 829 if (lconfig->adc_certfile[0] == '\0') { 830 (void)strlcpy(lconfig->adc_certfile, ADIST_CERTFILE, 831 sizeof(lconfig->adc_certfile)); 832 } 833 if (lconfig->adc_keyfile[0] == '\0') { 834 (void)strlcpy(lconfig->adc_keyfile, ADIST_KEYFILE, 835 sizeof(lconfig->adc_keyfile)); 836 } 837 838 return (lconfig); 839} 840 841void 842yy_config_free(struct adist_config *config) 843{ 844 struct adist_host *adhost; 845 struct adist_listen *lst; 846 847 while ((lst = TAILQ_FIRST(&config->adc_listen)) != NULL) { 848 TAILQ_REMOVE(&config->adc_listen, lst, adl_next); 849 free(lst); 850 } 851 while ((adhost = TAILQ_FIRST(&config->adc_hosts)) != NULL) { 852 TAILQ_REMOVE(&config->adc_hosts, adhost, adh_next); 853 bzero(adhost, sizeof(*adhost)); 854 free(adhost); 855 } 856 free(config); 857} 858