1255570Strasz%{ 2255570Strasz/*- 3330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4330449Seadler * 5255570Strasz * Copyright (c) 2012 The FreeBSD Foundation 6255570Strasz * All rights reserved. 7255570Strasz * 8255570Strasz * This software was developed by Edward Tomasz Napierala under sponsorship 9255570Strasz * from the FreeBSD Foundation. 10255570Strasz * 11255570Strasz * Redistribution and use in source and binary forms, with or without 12255570Strasz * modification, are permitted provided that the following conditions 13255570Strasz * are met: 14255570Strasz * 1. Redistributions of source code must retain the above copyright 15255570Strasz * notice, this list of conditions and the following disclaimer. 16255570Strasz * 2. Redistributions in binary form must reproduce the above copyright 17255570Strasz * notice, this list of conditions and the following disclaimer in the 18255570Strasz * documentation and/or other materials provided with the distribution. 19255570Strasz * 20255570Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21255570Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22255570Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23255570Strasz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24255570Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25255570Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26255570Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27255570Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28255570Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29255570Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30255570Strasz * SUCH DAMAGE. 31255570Strasz * 32255570Strasz * $FreeBSD: stable/11/usr.bin/iscsictl/parse.y 330449 2018-03-05 07:26:05Z eadler $ 33255570Strasz */ 34255570Strasz 35255570Strasz#include <sys/queue.h> 36255570Strasz#include <sys/types.h> 37255570Strasz#include <sys/stat.h> 38255570Strasz#include <assert.h> 39255570Strasz#include <stdio.h> 40255570Strasz#include <stdint.h> 41255570Strasz#include <stdlib.h> 42255570Strasz#include <string.h> 43255570Strasz 44281461Strasz#include <libxo/xo.h> 45281461Strasz 46255570Strasz#include "iscsictl.h" 47255570Strasz 48255570Straszextern FILE *yyin; 49255570Straszextern char *yytext; 50255570Straszextern int lineno; 51255570Strasz 52255570Straszstatic struct conf *conf; 53255570Straszstatic struct target *target; 54255570Strasz 55255570Straszextern void yyerror(const char *); 56255570Straszextern int yylex(void); 57255570Straszextern void yyrestart(FILE *); 58255570Strasz 59255570Strasz%} 60255570Strasz 61301033Strasz%token AUTH_METHOD ENABLE HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS 62255570Strasz%token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET 63278232Strasz%token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD 64278232Strasz%token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET 65255570Strasz 66255570Strasz%union 67255570Strasz{ 68255570Strasz char *str; 69255570Strasz} 70255570Strasz 71255570Strasz%token <str> STR 72255570Strasz 73255570Strasz%% 74255570Strasz 75261711Strasztargets: 76255570Strasz | 77261711Strasz targets target 78255570Strasz ; 79255570Strasz 80261711Strasztarget: STR OPENING_BRACKET target_entries CLOSING_BRACKET 81255570Strasz { 82255570Strasz if (target_find(conf, $1) != NULL) 83281461Strasz xo_errx(1, "duplicated target %s", $1); 84255570Strasz target->t_nickname = $1; 85255570Strasz target = target_new(conf); 86255570Strasz } 87255570Strasz ; 88255570Strasz 89255570Strasztarget_entries: 90255570Strasz | 91255570Strasz target_entries target_entry 92261714Strasz | 93261714Strasz target_entries target_entry SEMICOLON 94255570Strasz ; 95255570Strasz 96255570Strasztarget_entry: 97261711Strasz target_name 98255570Strasz | 99261711Strasz target_address 100255570Strasz | 101261711Strasz initiator_name 102255570Strasz | 103261711Strasz initiator_address 104255570Strasz | 105261711Strasz initiator_alias 106255570Strasz | 107261711Strasz user 108255570Strasz | 109261711Strasz secret 110255570Strasz | 111261711Strasz mutual_user 112255570Strasz | 113261711Strasz mutual_secret 114255570Strasz | 115261711Strasz auth_method 116255570Strasz | 117261711Strasz header_digest 118255570Strasz | 119261711Strasz data_digest 120255570Strasz | 121261711Strasz session_type 122255570Strasz | 123301033Strasz enable 124301033Strasz | 125278232Strasz offload 126278232Strasz | 127261711Strasz protocol 128255570Strasz | 129261711Strasz ignored 130255570Strasz ; 131255570Strasz 132261711Strasztarget_name: TARGET_NAME EQUALS STR 133255570Strasz { 134255570Strasz if (target->t_name != NULL) 135281461Strasz xo_errx(1, "duplicated TargetName at line %d", lineno); 136255570Strasz target->t_name = $3; 137255570Strasz } 138255570Strasz ; 139255570Strasz 140261711Strasztarget_address: TARGET_ADDRESS EQUALS STR 141255570Strasz { 142255570Strasz if (target->t_address != NULL) 143281461Strasz xo_errx(1, "duplicated TargetAddress at line %d", lineno); 144255570Strasz target->t_address = $3; 145255570Strasz } 146255570Strasz ; 147255570Strasz 148261711Straszinitiator_name: INITIATOR_NAME EQUALS STR 149255570Strasz { 150255570Strasz if (target->t_initiator_name != NULL) 151281461Strasz xo_errx(1, "duplicated InitiatorName at line %d", lineno); 152255570Strasz target->t_initiator_name = $3; 153255570Strasz } 154255570Strasz ; 155255570Strasz 156261711Straszinitiator_address: INITIATOR_ADDRESS EQUALS STR 157255570Strasz { 158255570Strasz if (target->t_initiator_address != NULL) 159281461Strasz xo_errx(1, "duplicated InitiatorAddress at line %d", lineno); 160255570Strasz target->t_initiator_address = $3; 161255570Strasz } 162255570Strasz ; 163255570Strasz 164261711Straszinitiator_alias: INITIATOR_ALIAS EQUALS STR 165255570Strasz { 166255570Strasz if (target->t_initiator_alias != NULL) 167281461Strasz xo_errx(1, "duplicated InitiatorAlias at line %d", lineno); 168255570Strasz target->t_initiator_alias = $3; 169255570Strasz } 170255570Strasz ; 171255570Strasz 172261711Straszuser: USER EQUALS STR 173255570Strasz { 174255570Strasz if (target->t_user != NULL) 175281461Strasz xo_errx(1, "duplicated chapIName at line %d", lineno); 176255570Strasz target->t_user = $3; 177255570Strasz } 178255570Strasz ; 179255570Strasz 180261711Straszsecret: SECRET EQUALS STR 181255570Strasz { 182255570Strasz if (target->t_secret != NULL) 183281461Strasz xo_errx(1, "duplicated chapSecret at line %d", lineno); 184255570Strasz target->t_secret = $3; 185255570Strasz } 186255570Strasz ; 187255570Strasz 188261711Straszmutual_user: MUTUAL_USER EQUALS STR 189255570Strasz { 190255570Strasz if (target->t_mutual_user != NULL) 191281461Strasz xo_errx(1, "duplicated tgtChapName at line %d", lineno); 192255570Strasz target->t_mutual_user = $3; 193255570Strasz } 194255570Strasz ; 195255570Strasz 196261711Straszmutual_secret: MUTUAL_SECRET EQUALS STR 197255570Strasz { 198255570Strasz if (target->t_mutual_secret != NULL) 199281461Strasz xo_errx(1, "duplicated tgtChapSecret at line %d", lineno); 200255570Strasz target->t_mutual_secret = $3; 201255570Strasz } 202255570Strasz ; 203255570Strasz 204261711Straszauth_method: AUTH_METHOD EQUALS STR 205255570Strasz { 206255570Strasz if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED) 207281461Strasz xo_errx(1, "duplicated AuthMethod at line %d", lineno); 208255570Strasz if (strcasecmp($3, "none") == 0) 209255570Strasz target->t_auth_method = AUTH_METHOD_NONE; 210255570Strasz else if (strcasecmp($3, "chap") == 0) 211255570Strasz target->t_auth_method = AUTH_METHOD_CHAP; 212255570Strasz else 213281461Strasz xo_errx(1, "invalid AuthMethod at line %d; " 214261713Strasz "must be either \"none\" or \"CHAP\"", lineno); 215255570Strasz } 216255570Strasz ; 217255570Strasz 218261711Straszheader_digest: HEADER_DIGEST EQUALS STR 219255570Strasz { 220255570Strasz if (target->t_header_digest != DIGEST_UNSPECIFIED) 221281461Strasz xo_errx(1, "duplicated HeaderDigest at line %d", lineno); 222255570Strasz if (strcasecmp($3, "none") == 0) 223255570Strasz target->t_header_digest = DIGEST_NONE; 224255570Strasz else if (strcasecmp($3, "CRC32C") == 0) 225255570Strasz target->t_header_digest = DIGEST_CRC32C; 226255570Strasz else 227281461Strasz xo_errx(1, "invalid HeaderDigest at line %d; " 228261713Strasz "must be either \"none\" or \"CRC32C\"", lineno); 229255570Strasz } 230255570Strasz ; 231255570Strasz 232261711Straszdata_digest: DATA_DIGEST EQUALS STR 233255570Strasz { 234255570Strasz if (target->t_data_digest != DIGEST_UNSPECIFIED) 235281461Strasz xo_errx(1, "duplicated DataDigest at line %d", lineno); 236255570Strasz if (strcasecmp($3, "none") == 0) 237255570Strasz target->t_data_digest = DIGEST_NONE; 238255570Strasz else if (strcasecmp($3, "CRC32C") == 0) 239255570Strasz target->t_data_digest = DIGEST_CRC32C; 240255570Strasz else 241281461Strasz xo_errx(1, "invalid DataDigest at line %d; " 242261713Strasz "must be either \"none\" or \"CRC32C\"", lineno); 243255570Strasz } 244255570Strasz ; 245255570Strasz 246261711Straszsession_type: SESSION_TYPE EQUALS STR 247255570Strasz { 248255570Strasz if (target->t_session_type != SESSION_TYPE_UNSPECIFIED) 249281461Strasz xo_errx(1, "duplicated SessionType at line %d", lineno); 250255570Strasz if (strcasecmp($3, "normal") == 0) 251255570Strasz target->t_session_type = SESSION_TYPE_NORMAL; 252255570Strasz else if (strcasecmp($3, "discovery") == 0) 253255570Strasz target->t_session_type = SESSION_TYPE_DISCOVERY; 254255570Strasz else 255281461Strasz xo_errx(1, "invalid SessionType at line %d; " 256261713Strasz "must be either \"normal\" or \"discovery\"", lineno); 257255570Strasz } 258255570Strasz ; 259255570Strasz 260301033Straszenable: ENABLE EQUALS STR 261301033Strasz { 262301033Strasz if (target->t_enable != ENABLE_UNSPECIFIED) 263301033Strasz xo_errx(1, "duplicated enable at line %d", lineno); 264301033Strasz target->t_enable = parse_enable($3); 265301033Strasz if (target->t_enable == ENABLE_UNSPECIFIED) 266301033Strasz xo_errx(1, "invalid enable at line %d; " 267301033Strasz "must be either \"on\" or \"off\"", lineno); 268301033Strasz } 269301033Strasz ; 270301033Strasz 271278232Straszoffload: OFFLOAD EQUALS STR 272278232Strasz { 273278232Strasz if (target->t_offload != NULL) 274281461Strasz xo_errx(1, "duplicated offload at line %d", lineno); 275278232Strasz target->t_offload = $3; 276278232Strasz } 277278232Strasz ; 278278232Strasz 279261711Straszprotocol: PROTOCOL EQUALS STR 280255570Strasz { 281255570Strasz if (target->t_protocol != PROTOCOL_UNSPECIFIED) 282281461Strasz xo_errx(1, "duplicated protocol at line %d", lineno); 283255570Strasz if (strcasecmp($3, "iscsi") == 0) 284255570Strasz target->t_protocol = PROTOCOL_ISCSI; 285255570Strasz else if (strcasecmp($3, "iser") == 0) 286255570Strasz target->t_protocol = PROTOCOL_ISER; 287255570Strasz else 288281461Strasz xo_errx(1, "invalid protocol at line %d; " 289261713Strasz "must be either \"iscsi\" or \"iser\"", lineno); 290255570Strasz } 291255570Strasz ; 292255570Strasz 293261711Straszignored: IGNORED EQUALS STR 294255570Strasz { 295281461Strasz xo_warnx("obsolete statement ignored at line %d", lineno); 296255570Strasz } 297255570Strasz ; 298255570Strasz 299255570Strasz%% 300255570Strasz 301255570Straszvoid 302255570Straszyyerror(const char *str) 303255570Strasz{ 304255570Strasz 305281461Strasz xo_errx(1, "error in configuration file at line %d near '%s': %s", 306261713Strasz lineno, yytext, str); 307255570Strasz} 308255570Strasz 309255570Straszstatic void 310255570Straszcheck_perms(const char *path) 311255570Strasz{ 312255570Strasz struct stat sb; 313255570Strasz int error; 314255570Strasz 315255570Strasz error = stat(path, &sb); 316255570Strasz if (error != 0) { 317281461Strasz xo_warn("stat"); 318255570Strasz return; 319255570Strasz } 320255570Strasz if (sb.st_mode & S_IWOTH) { 321281461Strasz xo_warnx("%s is world-writable", path); 322255570Strasz } else if (sb.st_mode & S_IROTH) { 323281461Strasz xo_warnx("%s is world-readable", path); 324255570Strasz } else if (sb.st_mode & S_IXOTH) { 325255570Strasz /* 326255570Strasz * Ok, this one doesn't matter, but still do it, 327255570Strasz * just for consistency. 328255570Strasz */ 329281461Strasz xo_warnx("%s is world-executable", path); 330255570Strasz } 331255570Strasz 332255570Strasz /* 333255570Strasz * XXX: Should we also check for owner != 0? 334255570Strasz */ 335255570Strasz} 336255570Strasz 337255570Straszstruct conf * 338255570Straszconf_new_from_file(const char *path) 339255570Strasz{ 340255570Strasz int error; 341255570Strasz 342255570Strasz conf = conf_new(); 343255570Strasz target = target_new(conf); 344255570Strasz 345255570Strasz yyin = fopen(path, "r"); 346255570Strasz if (yyin == NULL) 347281461Strasz xo_err(1, "unable to open configuration file %s", path); 348255570Strasz check_perms(path); 349261713Strasz lineno = 1; 350255570Strasz yyrestart(yyin); 351255570Strasz error = yyparse(); 352255570Strasz assert(error == 0); 353255570Strasz fclose(yyin); 354255570Strasz 355255570Strasz assert(target->t_nickname == NULL); 356255570Strasz target_delete(target); 357255570Strasz 358255570Strasz conf_verify(conf); 359255570Strasz 360255570Strasz return (conf); 361255570Strasz} 362