1243730Srwatson%{ 2243730Srwatson/*- 3243730Srwatson * Copyright (c) 2012 The FreeBSD Foundation 4243730Srwatson * All rights reserved. 5243730Srwatson * 6243730Srwatson * This software was developed by Pawel Jakub Dawidek under sponsorship from 7243730Srwatson * the FreeBSD Foundation. 8243730Srwatson * 9243730Srwatson * Redistribution and use in source and binary forms, with or without 10243730Srwatson * modification, are permitted provided that the following conditions 11243730Srwatson * are met: 12243730Srwatson * 1. Redistributions of source code must retain the above copyright 13243730Srwatson * notice, this list of conditions and the following disclaimer. 14243730Srwatson * 2. Redistributions in binary form must reproduce the above copyright 15243730Srwatson * notice, this list of conditions and the following disclaimer in the 16243730Srwatson * documentation and/or other materials provided with the distribution. 17243730Srwatson * 18243730Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19243730Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20243730Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21243730Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22243730Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23243730Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24243730Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25243730Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26243730Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27243730Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28243730Srwatson * SUCH DAMAGE. 29243730Srwatson * 30243734Srwatson * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/parse.y#5 $ 31243730Srwatson */ 32243730Srwatson 33243734Srwatson#include <config/config.h> 34243730Srwatson 35243730Srwatson#include <sys/types.h> 36243730Srwatson#include <sys/queue.h> 37243730Srwatson#include <sys/sysctl.h> 38243730Srwatson 39243730Srwatson#include <arpa/inet.h> 40243730Srwatson 41243730Srwatson#include <err.h> 42243730Srwatson#include <errno.h> 43243730Srwatson#include <stdio.h> 44243730Srwatson#include <string.h> 45243730Srwatson#include <sysexits.h> 46243730Srwatson#include <unistd.h> 47243730Srwatson#ifndef HAVE_STRLCPY 48243730Srwatson#include <compat/strlcpy.h> 49243730Srwatson#endif 50243730Srwatson 51243730Srwatson#include "auditdistd.h" 52243734Srwatson#include "pjdlog.h" 53243730Srwatson 54243730Srwatsonextern int depth; 55243730Srwatsonextern int lineno; 56243730Srwatson 57243730Srwatsonextern FILE *yyin; 58243730Srwatsonextern char *yytext; 59243730Srwatson 60243730Srwatsonstatic struct adist_config *lconfig; 61243730Srwatsonstatic struct adist_host *curhost; 62243730Srwatson#define SECTION_GLOBAL 0 63243730Srwatson#define SECTION_SENDER 1 64243730Srwatson#define SECTION_RECEIVER 2 65243730Srwatsonstatic int cursection; 66243730Srwatson 67243730Srwatson/* Sender section. */ 68243730Srwatsonstatic char depth1_source[ADIST_ADDRSIZE]; 69243730Srwatsonstatic int depth1_checksum; 70243730Srwatsonstatic int depth1_compression; 71243730Srwatson/* Sender and receiver sections. */ 72243730Srwatsonstatic char depth1_directory[PATH_MAX]; 73243730Srwatson 74243730Srwatsonstatic bool adjust_directory(char *path); 75243730Srwatsonstatic bool family_supported(int family); 76243730Srwatson 77243730Srwatsonextern void yyrestart(FILE *); 78243730Srwatson%} 79243730Srwatson 80243730Srwatson%token CB 81243730Srwatson%token CERTFILE 82243730Srwatson%token DIRECTORY 83243730Srwatson%token FINGERPRINT 84243730Srwatson%token HOST 85243730Srwatson%token KEYFILE 86243730Srwatson%token LISTEN 87243730Srwatson%token NAME 88243730Srwatson%token OB 89243730Srwatson%token PASSWORD 90243730Srwatson%token PIDFILE 91243730Srwatson%token RECEIVER REMOTE 92243730Srwatson%token SENDER SOURCE 93243730Srwatson%token TIMEOUT 94243730Srwatson 95243730Srwatson/* 96243730Srwatson%type <num> checksum_type 97243730Srwatson%type <num> compression_type 98243730Srwatson*/ 99243730Srwatson 100243730Srwatson%union 101243730Srwatson{ 102243730Srwatson int num; 103243730Srwatson char *str; 104243730Srwatson} 105243730Srwatson 106243730Srwatson%token <num> NUM 107243730Srwatson%token <str> STR 108243730Srwatson 109243730Srwatson%% 110243730Srwatson 111243730Srwatsonstatements: 112243730Srwatson | 113243730Srwatson statements statement 114243730Srwatson ; 115243730Srwatson 116243730Srwatsonstatement: 117243730Srwatson name_statement 118243730Srwatson | 119243730Srwatson pidfile_statement 120243730Srwatson | 121243730Srwatson timeout_statement 122243730Srwatson | 123243730Srwatson sender_statement 124243730Srwatson | 125243730Srwatson receiver_statement 126243730Srwatson ; 127243730Srwatson 128243730Srwatsonname_statement: NAME STR 129243730Srwatson { 130243730Srwatson PJDLOG_RASSERT(depth == 0, 131243730Srwatson "The name variable can only be specificed in the global section."); 132243730Srwatson 133243730Srwatson if (lconfig->adc_name[0] != '\0') { 134243730Srwatson pjdlog_error("The name variable is specified twice."); 135243730Srwatson free($2); 136243730Srwatson return (1); 137243730Srwatson } 138243730Srwatson if (strlcpy(lconfig->adc_name, $2, 139243730Srwatson sizeof(lconfig->adc_name)) >= 140243730Srwatson sizeof(lconfig->adc_name)) { 141243730Srwatson pjdlog_error("The name value is too long."); 142243730Srwatson free($2); 143243730Srwatson return (1); 144243730Srwatson } 145243730Srwatson free($2); 146243730Srwatson } 147243730Srwatson ; 148243730Srwatson 149243730Srwatsonpidfile_statement: PIDFILE STR 150243730Srwatson { 151243730Srwatson PJDLOG_RASSERT(depth == 0, 152243730Srwatson "The pidfile variable can only be specificed in the global section."); 153243730Srwatson 154243730Srwatson if (lconfig->adc_pidfile[0] != '\0') { 155243730Srwatson pjdlog_error("The pidfile variable is specified twice."); 156243730Srwatson free($2); 157243730Srwatson return (1); 158243730Srwatson } 159243730Srwatson if (strcmp($2, "none") != 0 && $2[0] != '/') { 160243730Srwatson pjdlog_error("The pidfile variable must be set to absolute pathname or \"none\"."); 161243730Srwatson free($2); 162243730Srwatson return (1); 163243730Srwatson } 164243730Srwatson if (strlcpy(lconfig->adc_pidfile, $2, 165243730Srwatson sizeof(lconfig->adc_pidfile)) >= 166243730Srwatson sizeof(lconfig->adc_pidfile)) { 167243730Srwatson pjdlog_error("The pidfile value is too long."); 168243730Srwatson free($2); 169243730Srwatson return (1); 170243730Srwatson } 171243730Srwatson free($2); 172243730Srwatson } 173243730Srwatson ; 174243730Srwatson 175243730Srwatsontimeout_statement: TIMEOUT NUM 176243730Srwatson { 177243730Srwatson PJDLOG_ASSERT(depth == 0); 178243730Srwatson 179243730Srwatson lconfig->adc_timeout = $2; 180243730Srwatson } 181243730Srwatson ; 182243730Srwatson 183243730Srwatsonsender_statement: SENDER sender_start sender_entries CB 184243730Srwatson { 185243730Srwatson PJDLOG_ASSERT(depth == 0); 186243730Srwatson PJDLOG_ASSERT(cursection == SECTION_SENDER); 187243730Srwatson 188243730Srwatson /* Configure defaults. */ 189243730Srwatson if (depth1_checksum == -1) 190243730Srwatson depth1_checksum = ADIST_CHECKSUM_NONE; 191243730Srwatson if (depth1_compression == -1) 192243730Srwatson depth1_compression = ADIST_COMPRESSION_NONE; 193243730Srwatson if (depth1_directory[0] == '\0') { 194243730Srwatson (void)strlcpy(depth1_directory, ADIST_DIRECTORY_SENDER, 195243730Srwatson sizeof(depth1_directory)); 196243730Srwatson } 197243730Srwatson /* Empty depth1_source is ok. */ 198243730Srwatson TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { 199243730Srwatson if (curhost->adh_role != ADIST_ROLE_SENDER) 200243730Srwatson continue; 201243730Srwatson if (curhost->adh_checksum == -1) 202243730Srwatson curhost->adh_checksum = depth1_checksum; 203243730Srwatson if (curhost->adh_compression == -1) 204243730Srwatson curhost->adh_compression = depth1_compression; 205243730Srwatson if (curhost->adh_directory[0] == '\0') { 206243730Srwatson (void)strlcpy(curhost->adh_directory, 207243730Srwatson depth1_directory, 208243730Srwatson sizeof(curhost->adh_directory)); 209243730Srwatson } 210243730Srwatson if (curhost->adh_localaddr[0] == '\0') { 211243730Srwatson (void)strlcpy(curhost->adh_localaddr, 212243730Srwatson depth1_source, 213243730Srwatson sizeof(curhost->adh_localaddr)); 214243730Srwatson } 215243730Srwatson } 216243730Srwatson cursection = SECTION_GLOBAL; 217243730Srwatson } 218243730Srwatson ; 219243730Srwatson 220243730Srwatsonsender_start: OB 221243730Srwatson { 222243730Srwatson PJDLOG_ASSERT(depth == 1); 223243730Srwatson PJDLOG_ASSERT(cursection == SECTION_GLOBAL); 224243730Srwatson 225243730Srwatson cursection = SECTION_SENDER; 226243730Srwatson depth1_checksum = -1; 227243730Srwatson depth1_compression = -1; 228243730Srwatson depth1_source[0] = '\0'; 229243730Srwatson depth1_directory[0] = '\0'; 230243730Srwatson 231243730Srwatson#ifndef HAVE_AUDIT_SYSCALLS 232243730Srwatson pjdlog_error("Sender functionality is not available."); 233243730Srwatson return (1); 234243730Srwatson#endif 235243730Srwatson } 236243730Srwatson ; 237243730Srwatson 238243730Srwatsonsender_entries: 239243730Srwatson | 240243730Srwatson sender_entries sender_entry 241243730Srwatson ; 242243730Srwatson 243243730Srwatsonsender_entry: 244243730Srwatson source_statement 245243730Srwatson | 246243730Srwatson directory_statement 247243730Srwatson/* 248243730Srwatson | 249243730Srwatson checksum_statement 250243730Srwatson | 251243730Srwatson compression_statement 252243730Srwatson*/ 253243730Srwatson | 254243730Srwatson sender_host_statement 255243730Srwatson ; 256243730Srwatson 257243730Srwatsonreceiver_statement: RECEIVER receiver_start receiver_entries CB 258243730Srwatson { 259243730Srwatson PJDLOG_ASSERT(depth == 0); 260243730Srwatson PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 261243730Srwatson 262243730Srwatson /* 263243730Srwatson * If not listen addresses were specified, 264243730Srwatson * configure default ones. 265243730Srwatson */ 266243730Srwatson if (TAILQ_EMPTY(&lconfig->adc_listen)) { 267243730Srwatson struct adist_listen *lst; 268243730Srwatson 269243730Srwatson if (family_supported(AF_INET)) { 270243730Srwatson lst = calloc(1, sizeof(*lst)); 271243730Srwatson if (lst == NULL) { 272243730Srwatson pjdlog_error("Unable to allocate memory for listen address."); 273243730Srwatson return (1); 274243730Srwatson } 275243730Srwatson (void)strlcpy(lst->adl_addr, 276243730Srwatson ADIST_LISTEN_TLS_TCP4, 277243730Srwatson sizeof(lst->adl_addr)); 278243730Srwatson TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); 279243730Srwatson } else { 280243730Srwatson pjdlog_debug(1, 281243730Srwatson "No IPv4 support in the kernel, not listening on IPv4 address."); 282243730Srwatson } 283243730Srwatson if (family_supported(AF_INET6)) { 284243730Srwatson lst = calloc(1, sizeof(*lst)); 285243730Srwatson if (lst == NULL) { 286243730Srwatson pjdlog_error("Unable to allocate memory for listen address."); 287243730Srwatson return (1); 288243730Srwatson } 289243730Srwatson (void)strlcpy(lst->adl_addr, 290243730Srwatson ADIST_LISTEN_TLS_TCP6, 291243730Srwatson sizeof(lst->adl_addr)); 292243730Srwatson TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); 293243730Srwatson } else { 294243730Srwatson pjdlog_debug(1, 295243730Srwatson "No IPv6 support in the kernel, not listening on IPv6 address."); 296243730Srwatson } 297243730Srwatson if (TAILQ_EMPTY(&lconfig->adc_listen)) { 298243730Srwatson pjdlog_error("No address to listen on."); 299243730Srwatson return (1); 300243730Srwatson } 301243730Srwatson } 302243730Srwatson /* Configure defaults. */ 303243730Srwatson if (depth1_directory[0] == '\0') { 304243730Srwatson (void)strlcpy(depth1_directory, 305243730Srwatson ADIST_DIRECTORY_RECEIVER, 306243730Srwatson sizeof(depth1_directory)); 307243730Srwatson } 308243730Srwatson TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { 309243730Srwatson if (curhost->adh_role != ADIST_ROLE_RECEIVER) 310243730Srwatson continue; 311243730Srwatson if (curhost->adh_directory[0] == '\0') { 312243730Srwatson if (snprintf(curhost->adh_directory, 313243730Srwatson sizeof(curhost->adh_directory), "%s/%s", 314243730Srwatson depth1_directory, curhost->adh_name) >= 315243730Srwatson (ssize_t)sizeof(curhost->adh_directory)) { 316243730Srwatson pjdlog_error("Directory value is too long."); 317243730Srwatson return (1); 318243730Srwatson } 319243730Srwatson } 320243730Srwatson } 321243730Srwatson cursection = SECTION_GLOBAL; 322243730Srwatson } 323243730Srwatson ; 324243730Srwatson 325243730Srwatsonreceiver_start: OB 326243730Srwatson { 327243730Srwatson PJDLOG_ASSERT(depth == 1); 328243730Srwatson PJDLOG_ASSERT(cursection == SECTION_GLOBAL); 329243730Srwatson 330243730Srwatson cursection = SECTION_RECEIVER; 331243730Srwatson depth1_directory[0] = '\0'; 332243730Srwatson } 333243730Srwatson ; 334243730Srwatson 335243730Srwatsonreceiver_entries: 336243730Srwatson | 337243730Srwatson receiver_entries receiver_entry 338243730Srwatson ; 339243730Srwatson 340243730Srwatsonreceiver_entry: 341243730Srwatson listen_statement 342243730Srwatson | 343243730Srwatson directory_statement 344243730Srwatson | 345243730Srwatson certfile_statement 346243730Srwatson | 347243730Srwatson keyfile_statement 348243730Srwatson | 349243730Srwatson receiver_host_statement 350243730Srwatson ; 351243730Srwatson 352243730Srwatson/* 353243730Srwatsonchecksum_statement: CHECKSUM checksum_type 354243730Srwatson { 355243730Srwatson PJDLOG_ASSERT(cursection == SECTION_SENDER); 356243730Srwatson 357243730Srwatson switch (depth) { 358243730Srwatson case 1: 359243730Srwatson depth1_checksum = $2; 360243730Srwatson break; 361243730Srwatson case 2: 362243730Srwatson PJDLOG_ASSERT(curhost != NULL); 363243730Srwatson curhost->adh_checksum = $2; 364243730Srwatson break; 365243730Srwatson default: 366243730Srwatson PJDLOG_ABORT("checksum at wrong depth level"); 367243730Srwatson } 368243730Srwatson } 369243730Srwatson ; 370243730Srwatson 371243730Srwatsonchecksum_type: 372243730Srwatson NONE { $$ = ADIST_CHECKSUM_NONE; } 373243730Srwatson | 374243730Srwatson CRC32 { $$ = ADIST_CHECKSUM_CRC32; } 375243730Srwatson | 376243730Srwatson SHA256 { $$ = ADIST_CHECKSUM_SHA256; } 377243730Srwatson ; 378243730Srwatson 379243730Srwatsoncompression_statement: COMPRESSION compression_type 380243730Srwatson { 381243730Srwatson PJDLOG_ASSERT(cursection == SECTION_SENDER); 382243730Srwatson 383243730Srwatson switch (depth) { 384243730Srwatson case 1: 385243730Srwatson depth1_compression = $2; 386243730Srwatson break; 387243730Srwatson case 2: 388243730Srwatson PJDLOG_ASSERT(curhost != NULL); 389243730Srwatson curhost->adh_compression = $2; 390243730Srwatson break; 391243730Srwatson default: 392243730Srwatson PJDLOG_ABORT("compression at wrong depth level"); 393243730Srwatson } 394243730Srwatson } 395243730Srwatson ; 396243730Srwatson 397243730Srwatsoncompression_type: 398243730Srwatson NONE { $$ = ADIST_COMPRESSION_NONE; } 399243730Srwatson | 400243730Srwatson LZF { $$ = ADIST_COMPRESSION_LZF; } 401243730Srwatson ; 402243730Srwatson*/ 403243730Srwatson 404243730Srwatsondirectory_statement: DIRECTORY STR 405243730Srwatson { 406243730Srwatson PJDLOG_ASSERT(cursection == SECTION_SENDER || 407243730Srwatson cursection == SECTION_RECEIVER); 408243730Srwatson 409243730Srwatson switch (depth) { 410243730Srwatson case 1: 411243730Srwatson if (strlcpy(depth1_directory, $2, 412243730Srwatson sizeof(depth1_directory)) >= 413243730Srwatson sizeof(depth1_directory)) { 414243730Srwatson pjdlog_error("Directory value is too long."); 415243730Srwatson free($2); 416243730Srwatson return (1); 417243730Srwatson } 418243730Srwatson if (!adjust_directory(depth1_directory)) 419243730Srwatson return (1); 420243730Srwatson break; 421243730Srwatson case 2: 422243730Srwatson if (cursection == SECTION_SENDER || $2[0] == '/') { 423243730Srwatson if (strlcpy(curhost->adh_directory, $2, 424243730Srwatson sizeof(curhost->adh_directory)) >= 425243730Srwatson sizeof(curhost->adh_directory)) { 426243730Srwatson pjdlog_error("Directory value is too long."); 427243730Srwatson free($2); 428243730Srwatson return (1); 429243730Srwatson } 430243730Srwatson } else /* if (cursection == SECTION_RECEIVER) */ { 431243730Srwatson if (depth1_directory[0] == '\0') { 432243730Srwatson pjdlog_error("Directory path must be absolute."); 433243730Srwatson free($2); 434243730Srwatson return (1); 435243730Srwatson } 436243730Srwatson if (snprintf(curhost->adh_directory, 437243730Srwatson sizeof(curhost->adh_directory), "%s/%s", 438243730Srwatson depth1_directory, $2) >= 439243730Srwatson (ssize_t)sizeof(curhost->adh_directory)) { 440243730Srwatson pjdlog_error("Directory value is too long."); 441243730Srwatson free($2); 442243730Srwatson return (1); 443243730Srwatson } 444243730Srwatson } 445243730Srwatson break; 446243730Srwatson default: 447243730Srwatson PJDLOG_ABORT("directory at wrong depth level"); 448243730Srwatson } 449243730Srwatson free($2); 450243730Srwatson } 451243730Srwatson ; 452243730Srwatson 453243730Srwatsonsource_statement: SOURCE STR 454243730Srwatson { 455243730Srwatson PJDLOG_RASSERT(cursection == SECTION_SENDER, 456243730Srwatson "The source variable must be in sender section."); 457243730Srwatson 458243730Srwatson switch (depth) { 459243730Srwatson case 1: 460243730Srwatson if (strlcpy(depth1_source, $2, 461243730Srwatson sizeof(depth1_source)) >= 462243730Srwatson sizeof(depth1_source)) { 463243730Srwatson pjdlog_error("Source value is too long."); 464243730Srwatson free($2); 465243730Srwatson return (1); 466243730Srwatson } 467243730Srwatson break; 468243730Srwatson case 2: 469243730Srwatson if (strlcpy(curhost->adh_localaddr, $2, 470243730Srwatson sizeof(curhost->adh_localaddr)) >= 471243730Srwatson sizeof(curhost->adh_localaddr)) { 472243730Srwatson pjdlog_error("Source value is too long."); 473243730Srwatson free($2); 474243730Srwatson return (1); 475243730Srwatson } 476243730Srwatson break; 477243730Srwatson } 478243730Srwatson free($2); 479243730Srwatson } 480243730Srwatson ; 481243730Srwatson 482243730Srwatsonfingerprint_statement: FINGERPRINT STR 483243730Srwatson { 484243730Srwatson PJDLOG_ASSERT(cursection == SECTION_SENDER); 485243730Srwatson PJDLOG_ASSERT(depth == 2); 486243730Srwatson 487243730Srwatson if (strncasecmp($2, "SHA256=", 7) != 0) { 488243730Srwatson pjdlog_error("Invalid fingerprint value."); 489243730Srwatson free($2); 490243730Srwatson return (1); 491243730Srwatson } 492243730Srwatson if (strlcpy(curhost->adh_fingerprint, $2, 493243730Srwatson sizeof(curhost->adh_fingerprint)) >= 494243730Srwatson sizeof(curhost->adh_fingerprint)) { 495243730Srwatson pjdlog_error("Fingerprint value is too long."); 496243730Srwatson free($2); 497243730Srwatson return (1); 498243730Srwatson } 499243730Srwatson free($2); 500243730Srwatson } 501243730Srwatson ; 502243730Srwatson 503243730Srwatsonpassword_statement: PASSWORD STR 504243730Srwatson { 505243730Srwatson PJDLOG_ASSERT(cursection == SECTION_SENDER || 506243730Srwatson cursection == SECTION_RECEIVER); 507243730Srwatson PJDLOG_ASSERT(depth == 2); 508243730Srwatson 509243730Srwatson if (strlcpy(curhost->adh_password, $2, 510243730Srwatson sizeof(curhost->adh_password)) >= 511243730Srwatson sizeof(curhost->adh_password)) { 512243730Srwatson pjdlog_error("Password value is too long."); 513243730Srwatson bzero($2, strlen($2)); 514243730Srwatson free($2); 515243730Srwatson return (1); 516243730Srwatson } 517243730Srwatson bzero($2, strlen($2)); 518243730Srwatson free($2); 519243730Srwatson } 520243730Srwatson ; 521243730Srwatson 522243730Srwatsoncertfile_statement: CERTFILE STR 523243730Srwatson { 524243730Srwatson PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 525243730Srwatson PJDLOG_ASSERT(depth == 1); 526243730Srwatson 527243730Srwatson if (strlcpy(lconfig->adc_certfile, $2, 528243730Srwatson sizeof(lconfig->adc_certfile)) >= 529243730Srwatson sizeof(lconfig->adc_certfile)) { 530243730Srwatson pjdlog_error("Certfile value is too long."); 531243730Srwatson free($2); 532243730Srwatson return (1); 533243730Srwatson } 534243730Srwatson free($2); 535243730Srwatson } 536243730Srwatson ; 537243730Srwatson 538243730Srwatsonkeyfile_statement: KEYFILE STR 539243730Srwatson { 540243730Srwatson PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 541243730Srwatson PJDLOG_ASSERT(depth == 1); 542243730Srwatson 543243730Srwatson if (strlcpy(lconfig->adc_keyfile, $2, 544243730Srwatson sizeof(lconfig->adc_keyfile)) >= 545243730Srwatson sizeof(lconfig->adc_keyfile)) { 546243730Srwatson pjdlog_error("Keyfile value is too long."); 547243730Srwatson free($2); 548243730Srwatson return (1); 549243730Srwatson } 550243730Srwatson free($2); 551243730Srwatson } 552243730Srwatson ; 553243730Srwatson 554243730Srwatsonlisten_statement: LISTEN STR 555243730Srwatson { 556243730Srwatson struct adist_listen *lst; 557243730Srwatson 558243730Srwatson PJDLOG_ASSERT(depth == 1); 559243730Srwatson PJDLOG_ASSERT(cursection == SECTION_RECEIVER); 560243730Srwatson 561243730Srwatson lst = calloc(1, sizeof(*lst)); 562243730Srwatson if (lst == NULL) { 563243730Srwatson pjdlog_error("Unable to allocate memory for listen address."); 564243730Srwatson free($2); 565243730Srwatson return (1); 566243730Srwatson } 567243730Srwatson if (strlcpy(lst->adl_addr, $2, sizeof(lst->adl_addr)) >= 568243730Srwatson sizeof(lst->adl_addr)) { 569243730Srwatson pjdlog_error("listen argument is too long."); 570243730Srwatson free($2); 571243730Srwatson free(lst); 572243730Srwatson return (1); 573243730Srwatson } 574243730Srwatson TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next); 575243730Srwatson free($2); 576243730Srwatson } 577243730Srwatson ; 578243730Srwatson 579243730Srwatsonsender_host_statement: HOST host_start OB sender_host_entries CB 580243730Srwatson { 581243730Srwatson /* Put it onto host list. */ 582243730Srwatson TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next); 583243730Srwatson curhost = NULL; 584243730Srwatson } 585243730Srwatson ; 586243730Srwatson 587243730Srwatsonreceiver_host_statement: HOST host_start OB receiver_host_entries CB 588243730Srwatson { 589243730Srwatson /* Put it onto host list. */ 590243730Srwatson TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next); 591243730Srwatson curhost = NULL; 592243730Srwatson } 593243730Srwatson ; 594243730Srwatson 595243730Srwatsonhost_start: STR 596243730Srwatson { 597243730Srwatson /* Check if there is no duplicate entry. */ 598243730Srwatson TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) { 599243730Srwatson if (strcmp(curhost->adh_name, $1) != 0) 600243730Srwatson continue; 601243730Srwatson if (curhost->adh_role == ADIST_ROLE_SENDER && 602243730Srwatson cursection == SECTION_RECEIVER) { 603243730Srwatson continue; 604243730Srwatson } 605243730Srwatson if (curhost->adh_role == ADIST_ROLE_RECEIVER && 606243730Srwatson cursection == SECTION_SENDER) { 607243730Srwatson continue; 608243730Srwatson } 609243730Srwatson pjdlog_error("%s host %s is configured more than once.", 610243730Srwatson curhost->adh_role == ADIST_ROLE_SENDER ? 611243730Srwatson "Sender" : "Receiver", curhost->adh_name); 612243730Srwatson free($1); 613243730Srwatson return (1); 614243730Srwatson } 615243730Srwatson 616243730Srwatson curhost = calloc(1, sizeof(*curhost)); 617243730Srwatson if (curhost == NULL) { 618243730Srwatson pjdlog_error("Unable to allocate memory for host configuration."); 619243730Srwatson free($1); 620243730Srwatson return (1); 621243730Srwatson } 622243730Srwatson if (strlcpy(curhost->adh_name, $1, sizeof(curhost->adh_name)) >= 623243730Srwatson sizeof(curhost->adh_name)) { 624243730Srwatson pjdlog_error("Host name is too long."); 625243730Srwatson free($1); 626243730Srwatson return (1); 627243730Srwatson } 628243730Srwatson free($1); 629243730Srwatson curhost->adh_role = cursection == SECTION_SENDER ? 630243730Srwatson ADIST_ROLE_SENDER : ADIST_ROLE_RECEIVER; 631243730Srwatson curhost->adh_version = ADIST_VERSION; 632243730Srwatson curhost->adh_localaddr[0] = '\0'; 633243730Srwatson curhost->adh_remoteaddr[0] = '\0'; 634243730Srwatson curhost->adh_remote = NULL; 635243730Srwatson curhost->adh_directory[0] = '\0'; 636243730Srwatson curhost->adh_password[0] = '\0'; 637243730Srwatson curhost->adh_fingerprint[0] = '\0'; 638243730Srwatson curhost->adh_worker_pid = 0; 639243730Srwatson curhost->adh_conn = NULL; 640243730Srwatson } 641243730Srwatson ; 642243730Srwatson 643243730Srwatsonsender_host_entries: 644243730Srwatson | 645243730Srwatson sender_host_entries sender_host_entry 646243730Srwatson ; 647243730Srwatson 648243730Srwatsonsender_host_entry: 649243730Srwatson source_statement 650243730Srwatson | 651243730Srwatson remote_statement 652243730Srwatson | 653243730Srwatson directory_statement 654243730Srwatson | 655243730Srwatson fingerprint_statement 656243730Srwatson | 657243730Srwatson password_statement 658243730Srwatson/* 659243730Srwatson | 660243730Srwatson checksum_statement 661243730Srwatson | 662243730Srwatson compression_statement 663243730Srwatson*/ 664243730Srwatson ; 665243730Srwatson 666243730Srwatsonreceiver_host_entries: 667243730Srwatson | 668243730Srwatson receiver_host_entries receiver_host_entry 669243730Srwatson ; 670243730Srwatson 671243730Srwatsonreceiver_host_entry: 672243730Srwatson remote_statement 673243730Srwatson | 674243730Srwatson directory_statement 675243730Srwatson | 676243730Srwatson password_statement 677243730Srwatson ; 678243730Srwatson 679243730Srwatsonremote_statement: REMOTE STR 680243730Srwatson { 681243730Srwatson PJDLOG_ASSERT(depth == 2); 682243730Srwatson PJDLOG_ASSERT(cursection == SECTION_SENDER || 683243730Srwatson cursection == SECTION_RECEIVER); 684243730Srwatson 685243730Srwatson if (strlcpy(curhost->adh_remoteaddr, $2, 686243730Srwatson sizeof(curhost->adh_remoteaddr)) >= 687243730Srwatson sizeof(curhost->adh_remoteaddr)) { 688243730Srwatson pjdlog_error("Remote value is too long."); 689243730Srwatson free($2); 690243730Srwatson return (1); 691243730Srwatson } 692243730Srwatson free($2); 693243730Srwatson } 694243730Srwatson ; 695243730Srwatson 696243730Srwatson%% 697243730Srwatson 698243730Srwatsonstatic bool 699243730Srwatsonfamily_supported(int family) 700243730Srwatson{ 701243730Srwatson int sock; 702243730Srwatson 703243730Srwatson sock = socket(family, SOCK_STREAM, 0); 704243730Srwatson if (sock == -1 && errno == EPROTONOSUPPORT) 705243730Srwatson return (false); 706243730Srwatson if (sock >= 0) 707243730Srwatson (void)close(sock); 708243730Srwatson return (true); 709243730Srwatson} 710243730Srwatson 711243730Srwatsonstatic bool 712243730Srwatsonadjust_directory(char *path) 713243730Srwatson{ 714243730Srwatson size_t len; 715243730Srwatson 716243730Srwatson len = strlen(path); 717243730Srwatson for (;;) { 718243730Srwatson if (len == 0) { 719243730Srwatson pjdlog_error("Directory path is empty."); 720243730Srwatson return (false); 721243730Srwatson } 722243730Srwatson if (path[len - 1] != '/') 723243730Srwatson break; 724243730Srwatson len--; 725243730Srwatson path[len] = '\0'; 726243730Srwatson } 727243730Srwatson if (path[0] != '/') { 728243730Srwatson pjdlog_error("Directory path must be absolute."); 729243730Srwatson return (false); 730243730Srwatson } 731243730Srwatson return (true); 732243730Srwatson} 733243730Srwatson 734243730Srwatsonstatic int 735243730Srwatsonmy_name(char *name, size_t size) 736243730Srwatson{ 737243730Srwatson char buf[MAXHOSTNAMELEN]; 738243730Srwatson char *pos; 739243730Srwatson 740243730Srwatson if (gethostname(buf, sizeof(buf)) < 0) { 741243730Srwatson pjdlog_errno(LOG_ERR, "gethostname() failed"); 742243730Srwatson return (-1); 743243730Srwatson } 744243730Srwatson 745243730Srwatson /* First component of the host name. */ 746243730Srwatson pos = strchr(buf, '.'); 747243730Srwatson if (pos == NULL) 748243730Srwatson (void)strlcpy(name, buf, size); 749243730Srwatson else 750243730Srwatson (void)strlcpy(name, buf, MIN((size_t)(pos - buf + 1), size)); 751243730Srwatson 752243730Srwatson if (name[0] == '\0') { 753243730Srwatson pjdlog_error("Empty host name."); 754243730Srwatson return (-1); 755243730Srwatson } 756243730Srwatson 757243730Srwatson return (0); 758243730Srwatson} 759243730Srwatson 760243730Srwatsonvoid 761243730Srwatsonyyerror(const char *str) 762243730Srwatson{ 763243730Srwatson 764243730Srwatson pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", 765243730Srwatson lineno, yytext, str); 766243730Srwatson} 767243730Srwatson 768243730Srwatsonstruct adist_config * 769243730Srwatsonyy_config_parse(const char *config, bool exitonerror) 770243730Srwatson{ 771243730Srwatson int ret; 772243730Srwatson 773243730Srwatson curhost = NULL; 774243730Srwatson cursection = SECTION_GLOBAL; 775243730Srwatson depth = 0; 776243730Srwatson lineno = 0; 777243730Srwatson 778243730Srwatson lconfig = calloc(1, sizeof(*lconfig)); 779243730Srwatson if (lconfig == NULL) { 780243730Srwatson pjdlog_error("Unable to allocate memory for configuration."); 781243730Srwatson if (exitonerror) 782243730Srwatson exit(EX_TEMPFAIL); 783243730Srwatson return (NULL); 784243730Srwatson } 785243730Srwatson TAILQ_INIT(&lconfig->adc_hosts); 786243730Srwatson TAILQ_INIT(&lconfig->adc_listen); 787243730Srwatson lconfig->adc_name[0] = '\0'; 788243730Srwatson lconfig->adc_timeout = -1; 789243730Srwatson lconfig->adc_pidfile[0] = '\0'; 790243730Srwatson lconfig->adc_certfile[0] = '\0'; 791243730Srwatson lconfig->adc_keyfile[0] = '\0'; 792243730Srwatson 793243730Srwatson yyin = fopen(config, "r"); 794243730Srwatson if (yyin == NULL) { 795243730Srwatson pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", 796243730Srwatson config); 797243730Srwatson yy_config_free(lconfig); 798243730Srwatson if (exitonerror) 799243730Srwatson exit(EX_OSFILE); 800243730Srwatson return (NULL); 801243730Srwatson } 802243730Srwatson yyrestart(yyin); 803243730Srwatson ret = yyparse(); 804243730Srwatson fclose(yyin); 805243730Srwatson if (ret != 0) { 806243730Srwatson yy_config_free(lconfig); 807243730Srwatson if (exitonerror) 808243730Srwatson exit(EX_CONFIG); 809243730Srwatson return (NULL); 810243730Srwatson } 811243730Srwatson 812243730Srwatson /* 813243730Srwatson * Let's see if everything is set up. 814243730Srwatson */ 815243730Srwatson if (lconfig->adc_name[0] == '\0' && my_name(lconfig->adc_name, 816243730Srwatson sizeof(lconfig->adc_name)) == -1) { 817243730Srwatson yy_config_free(lconfig); 818243730Srwatson if (exitonerror) 819243730Srwatson exit(EX_CONFIG); 820243730Srwatson return (NULL); 821243730Srwatson } 822243730Srwatson if (lconfig->adc_timeout == -1) 823243730Srwatson lconfig->adc_timeout = ADIST_TIMEOUT; 824243730Srwatson if (lconfig->adc_pidfile[0] == '\0') { 825243730Srwatson (void)strlcpy(lconfig->adc_pidfile, ADIST_PIDFILE, 826243730Srwatson sizeof(lconfig->adc_pidfile)); 827243730Srwatson } 828243730Srwatson if (lconfig->adc_certfile[0] == '\0') { 829243730Srwatson (void)strlcpy(lconfig->adc_certfile, ADIST_CERTFILE, 830243730Srwatson sizeof(lconfig->adc_certfile)); 831243730Srwatson } 832243730Srwatson if (lconfig->adc_keyfile[0] == '\0') { 833243730Srwatson (void)strlcpy(lconfig->adc_keyfile, ADIST_KEYFILE, 834243730Srwatson sizeof(lconfig->adc_keyfile)); 835243730Srwatson } 836243730Srwatson 837243730Srwatson return (lconfig); 838243730Srwatson} 839243730Srwatson 840243730Srwatsonvoid 841243730Srwatsonyy_config_free(struct adist_config *config) 842243730Srwatson{ 843243730Srwatson struct adist_host *adhost; 844243730Srwatson struct adist_listen *lst; 845243730Srwatson 846243730Srwatson while ((lst = TAILQ_FIRST(&config->adc_listen)) != NULL) { 847243730Srwatson TAILQ_REMOVE(&config->adc_listen, lst, adl_next); 848243730Srwatson free(lst); 849243730Srwatson } 850243730Srwatson while ((adhost = TAILQ_FIRST(&config->adc_hosts)) != NULL) { 851243730Srwatson TAILQ_REMOVE(&config->adc_hosts, adhost, adh_next); 852243730Srwatson bzero(adhost, sizeof(*adhost)); 853243730Srwatson free(adhost); 854243730Srwatson } 855243730Srwatson free(config); 856243730Srwatson} 857