parse.y revision 262841
1255570Strasz%{ 2255570Strasz/*- 3255570Strasz * Copyright (c) 2012 The FreeBSD Foundation 4255570Strasz * All rights reserved. 5255570Strasz * 6255570Strasz * This software was developed by Edward Tomasz Napierala under sponsorship 7255570Strasz * from the FreeBSD Foundation. 8255570Strasz * 9255570Strasz * Redistribution and use in source and binary forms, with or without 10255570Strasz * modification, are permitted provided that the following conditions 11255570Strasz * are met: 12255570Strasz * 1. Redistributions of source code must retain the above copyright 13255570Strasz * notice, this list of conditions and the following disclaimer. 14255570Strasz * 2. Redistributions in binary form must reproduce the above copyright 15255570Strasz * notice, this list of conditions and the following disclaimer in the 16255570Strasz * documentation and/or other materials provided with the distribution. 17255570Strasz * 18255570Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19255570Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20255570Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21255570Strasz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22255570Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23255570Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24255570Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25255570Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26255570Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27255570Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28255570Strasz * SUCH DAMAGE. 29255570Strasz * 30255570Strasz * $FreeBSD: stable/10/usr.bin/iscsictl/parse.y 262841 2014-03-06 11:07:51Z trasz $ 31255570Strasz */ 32255570Strasz 33255570Strasz#include <sys/queue.h> 34255570Strasz#include <sys/types.h> 35255570Strasz#include <sys/stat.h> 36255570Strasz#include <assert.h> 37255570Strasz#include <err.h> 38255570Strasz#include <stdio.h> 39255570Strasz#include <stdint.h> 40255570Strasz#include <stdlib.h> 41255570Strasz#include <string.h> 42255570Strasz 43255570Strasz#include "iscsictl.h" 44255570Strasz 45255570Straszextern FILE *yyin; 46255570Straszextern char *yytext; 47255570Straszextern int lineno; 48255570Strasz 49255570Straszstatic struct conf *conf; 50255570Straszstatic struct target *target; 51255570Strasz 52255570Straszextern void yyerror(const char *); 53255570Straszextern int yylex(void); 54255570Straszextern void yyrestart(FILE *); 55255570Strasz 56255570Strasz%} 57255570Strasz 58255570Strasz%token AUTH_METHOD HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS 59255570Strasz%token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET 60262841Strasz%token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL IGNORED 61255570Strasz%token EQUALS OPENING_BRACKET CLOSING_BRACKET 62255570Strasz 63255570Strasz%union 64255570Strasz{ 65255570Strasz char *str; 66255570Strasz} 67255570Strasz 68255570Strasz%token <str> STR 69255570Strasz 70255570Strasz%% 71255570Strasz 72262838Strasztargets: 73255570Strasz | 74262838Strasz targets target 75255570Strasz ; 76255570Strasz 77262838Strasztarget: STR OPENING_BRACKET target_entries CLOSING_BRACKET 78255570Strasz { 79255570Strasz if (target_find(conf, $1) != NULL) 80255570Strasz errx(1, "duplicated target %s", $1); 81255570Strasz target->t_nickname = $1; 82255570Strasz target = target_new(conf); 83255570Strasz } 84255570Strasz ; 85255570Strasz 86255570Strasztarget_entries: 87255570Strasz | 88255570Strasz target_entries target_entry 89262841Strasz | 90262841Strasz target_entries target_entry SEMICOLON 91255570Strasz ; 92255570Strasz 93255570Strasztarget_entry: 94262838Strasz target_name 95255570Strasz | 96262838Strasz target_address 97255570Strasz | 98262838Strasz initiator_name 99255570Strasz | 100262838Strasz initiator_address 101255570Strasz | 102262838Strasz initiator_alias 103255570Strasz | 104262838Strasz user 105255570Strasz | 106262838Strasz secret 107255570Strasz | 108262838Strasz mutual_user 109255570Strasz | 110262838Strasz mutual_secret 111255570Strasz | 112262838Strasz auth_method 113255570Strasz | 114262838Strasz header_digest 115255570Strasz | 116262838Strasz data_digest 117255570Strasz | 118262838Strasz session_type 119255570Strasz | 120262838Strasz protocol 121255570Strasz | 122262838Strasz ignored 123255570Strasz ; 124255570Strasz 125262838Strasztarget_name: TARGET_NAME EQUALS STR 126255570Strasz { 127255570Strasz if (target->t_name != NULL) 128262840Strasz errx(1, "duplicated TargetName at line %d", lineno); 129255570Strasz target->t_name = $3; 130255570Strasz } 131255570Strasz ; 132255570Strasz 133262838Strasztarget_address: TARGET_ADDRESS EQUALS STR 134255570Strasz { 135255570Strasz if (target->t_address != NULL) 136262840Strasz errx(1, "duplicated TargetAddress at line %d", lineno); 137255570Strasz target->t_address = $3; 138255570Strasz } 139255570Strasz ; 140255570Strasz 141262838Straszinitiator_name: INITIATOR_NAME EQUALS STR 142255570Strasz { 143255570Strasz if (target->t_initiator_name != NULL) 144262840Strasz errx(1, "duplicated InitiatorName at line %d", lineno); 145255570Strasz target->t_initiator_name = $3; 146255570Strasz } 147255570Strasz ; 148255570Strasz 149262838Straszinitiator_address: INITIATOR_ADDRESS EQUALS STR 150255570Strasz { 151255570Strasz if (target->t_initiator_address != NULL) 152262840Strasz errx(1, "duplicated InitiatorAddress at line %d", lineno); 153255570Strasz target->t_initiator_address = $3; 154255570Strasz } 155255570Strasz ; 156255570Strasz 157262838Straszinitiator_alias: INITIATOR_ALIAS EQUALS STR 158255570Strasz { 159255570Strasz if (target->t_initiator_alias != NULL) 160262840Strasz errx(1, "duplicated InitiatorAlias at line %d", lineno); 161255570Strasz target->t_initiator_alias = $3; 162255570Strasz } 163255570Strasz ; 164255570Strasz 165262838Straszuser: USER EQUALS STR 166255570Strasz { 167255570Strasz if (target->t_user != NULL) 168262840Strasz errx(1, "duplicated chapIName at line %d", lineno); 169255570Strasz target->t_user = $3; 170255570Strasz } 171255570Strasz ; 172255570Strasz 173262838Straszsecret: SECRET EQUALS STR 174255570Strasz { 175255570Strasz if (target->t_secret != NULL) 176262840Strasz errx(1, "duplicated chapSecret at line %d", lineno); 177255570Strasz target->t_secret = $3; 178255570Strasz } 179255570Strasz ; 180255570Strasz 181262838Straszmutual_user: MUTUAL_USER EQUALS STR 182255570Strasz { 183255570Strasz if (target->t_mutual_user != NULL) 184262840Strasz errx(1, "duplicated tgtChapName at line %d", lineno); 185255570Strasz target->t_mutual_user = $3; 186255570Strasz } 187255570Strasz ; 188255570Strasz 189262838Straszmutual_secret: MUTUAL_SECRET EQUALS STR 190255570Strasz { 191255570Strasz if (target->t_mutual_secret != NULL) 192262840Strasz errx(1, "duplicated tgtChapSecret at line %d", lineno); 193255570Strasz target->t_mutual_secret = $3; 194255570Strasz } 195255570Strasz ; 196255570Strasz 197262838Straszauth_method: AUTH_METHOD EQUALS STR 198255570Strasz { 199255570Strasz if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED) 200262840Strasz errx(1, "duplicated AuthMethod at line %d", lineno); 201255570Strasz if (strcasecmp($3, "none") == 0) 202255570Strasz target->t_auth_method = AUTH_METHOD_NONE; 203255570Strasz else if (strcasecmp($3, "chap") == 0) 204255570Strasz target->t_auth_method = AUTH_METHOD_CHAP; 205255570Strasz else 206255570Strasz errx(1, "invalid AuthMethod at line %d; " 207262840Strasz "must be either \"none\" or \"CHAP\"", lineno); 208255570Strasz } 209255570Strasz ; 210255570Strasz 211262838Straszheader_digest: HEADER_DIGEST EQUALS STR 212255570Strasz { 213255570Strasz if (target->t_header_digest != DIGEST_UNSPECIFIED) 214262840Strasz errx(1, "duplicated HeaderDigest at line %d", lineno); 215255570Strasz if (strcasecmp($3, "none") == 0) 216255570Strasz target->t_header_digest = DIGEST_NONE; 217255570Strasz else if (strcasecmp($3, "CRC32C") == 0) 218255570Strasz target->t_header_digest = DIGEST_CRC32C; 219255570Strasz else 220255570Strasz errx(1, "invalid HeaderDigest at line %d; " 221262840Strasz "must be either \"none\" or \"CRC32C\"", lineno); 222255570Strasz } 223255570Strasz ; 224255570Strasz 225262838Straszdata_digest: DATA_DIGEST EQUALS STR 226255570Strasz { 227255570Strasz if (target->t_data_digest != DIGEST_UNSPECIFIED) 228262840Strasz errx(1, "duplicated DataDigest at line %d", lineno); 229255570Strasz if (strcasecmp($3, "none") == 0) 230255570Strasz target->t_data_digest = DIGEST_NONE; 231255570Strasz else if (strcasecmp($3, "CRC32C") == 0) 232255570Strasz target->t_data_digest = DIGEST_CRC32C; 233255570Strasz else 234255570Strasz errx(1, "invalid DataDigest at line %d; " 235262840Strasz "must be either \"none\" or \"CRC32C\"", lineno); 236255570Strasz } 237255570Strasz ; 238255570Strasz 239262838Straszsession_type: SESSION_TYPE EQUALS STR 240255570Strasz { 241255570Strasz if (target->t_session_type != SESSION_TYPE_UNSPECIFIED) 242262840Strasz errx(1, "duplicated SessionType at line %d", lineno); 243255570Strasz if (strcasecmp($3, "normal") == 0) 244255570Strasz target->t_session_type = SESSION_TYPE_NORMAL; 245255570Strasz else if (strcasecmp($3, "discovery") == 0) 246255570Strasz target->t_session_type = SESSION_TYPE_DISCOVERY; 247255570Strasz else 248255570Strasz errx(1, "invalid SessionType at line %d; " 249262840Strasz "must be either \"normal\" or \"discovery\"", lineno); 250255570Strasz } 251255570Strasz ; 252255570Strasz 253262838Straszprotocol: PROTOCOL EQUALS STR 254255570Strasz { 255255570Strasz if (target->t_protocol != PROTOCOL_UNSPECIFIED) 256262840Strasz errx(1, "duplicated protocol at line %d", lineno); 257255570Strasz if (strcasecmp($3, "iscsi") == 0) 258255570Strasz target->t_protocol = PROTOCOL_ISCSI; 259255570Strasz else if (strcasecmp($3, "iser") == 0) 260255570Strasz target->t_protocol = PROTOCOL_ISER; 261255570Strasz else 262255570Strasz errx(1, "invalid protocol at line %d; " 263262840Strasz "must be either \"iscsi\" or \"iser\"", lineno); 264255570Strasz } 265255570Strasz ; 266255570Strasz 267262838Straszignored: IGNORED EQUALS STR 268255570Strasz { 269262840Strasz warnx("obsolete statement ignored at line %d", lineno); 270255570Strasz } 271255570Strasz ; 272255570Strasz 273255570Strasz%% 274255570Strasz 275255570Straszvoid 276255570Straszyyerror(const char *str) 277255570Strasz{ 278255570Strasz 279255570Strasz errx(1, "error in configuration file at line %d near '%s': %s", 280262840Strasz lineno, yytext, str); 281255570Strasz} 282255570Strasz 283255570Straszstatic void 284255570Straszcheck_perms(const char *path) 285255570Strasz{ 286255570Strasz struct stat sb; 287255570Strasz int error; 288255570Strasz 289255570Strasz error = stat(path, &sb); 290255570Strasz if (error != 0) { 291255570Strasz warn("stat"); 292255570Strasz return; 293255570Strasz } 294255570Strasz if (sb.st_mode & S_IWOTH) { 295255570Strasz warnx("%s is world-writable", path); 296255570Strasz } else if (sb.st_mode & S_IROTH) { 297255570Strasz warnx("%s is world-readable", path); 298255570Strasz } else if (sb.st_mode & S_IXOTH) { 299255570Strasz /* 300255570Strasz * Ok, this one doesn't matter, but still do it, 301255570Strasz * just for consistency. 302255570Strasz */ 303255570Strasz warnx("%s is world-executable", path); 304255570Strasz } 305255570Strasz 306255570Strasz /* 307255570Strasz * XXX: Should we also check for owner != 0? 308255570Strasz */ 309255570Strasz} 310255570Strasz 311255570Straszstruct conf * 312255570Straszconf_new_from_file(const char *path) 313255570Strasz{ 314255570Strasz int error; 315255570Strasz 316255570Strasz conf = conf_new(); 317255570Strasz target = target_new(conf); 318255570Strasz 319255570Strasz yyin = fopen(path, "r"); 320255570Strasz if (yyin == NULL) 321255570Strasz err(1, "unable to open configuration file %s", path); 322255570Strasz check_perms(path); 323262840Strasz lineno = 1; 324255570Strasz yyrestart(yyin); 325255570Strasz error = yyparse(); 326255570Strasz assert(error == 0); 327255570Strasz fclose(yyin); 328255570Strasz 329255570Strasz assert(target->t_nickname == NULL); 330255570Strasz target_delete(target); 331255570Strasz 332255570Strasz conf_verify(conf); 333255570Strasz 334255570Strasz return (conf); 335255570Strasz} 336