1 %{ 2 /*- 3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4 * 5 * Copyright (c) 2012 The FreeBSD Foundation 6 * All rights reserved. 7 * 8 * This software was developed by Edward Tomasz Napierala under sponsorship 9 * from the FreeBSD Foundation. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD$ 33 */ 34 35 #include <sys/queue.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <assert.h> 39 #include <stdio.h> 40 #include <stdint.h> 41 #include <stdlib.h> 42 #include <string.h> 43 44 #include <libxo/xo.h> 45 46 #include "iscsictl.h" 47 48 extern FILE *yyin; 49 extern char *yytext; 50 extern int lineno; 51 52 static struct conf *conf; 53 static struct target *target; 54 55 extern void yyerror(const char *); 56 extern int yylex(void); 57 extern void yyrestart(FILE *); 58 59 %} 60 61 %token AUTH_METHOD ENABLE HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS 62 %token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET 63 %token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD 64 %token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET 65 66 %union 67 { 68 char *str; 69 } 70 71 %token <str> STR 72 73 %% 74 75 targets: 76 | 77 targets target 78 ; 79 80 target: STR OPENING_BRACKET target_entries CLOSING_BRACKET 81 { 82 if (target_find(conf, $1) != NULL) 83 xo_errx(1, "duplicated target %s", $1); 84 target->t_nickname = $1; 85 target = target_new(conf); 86 } 87 ; 88 89 target_entries: 90 | 91 target_entries target_entry 92 | 93 target_entries target_entry SEMICOLON 94 ; 95 96 target_entry: 97 target_name 98 | 99 target_address 100 | 101 initiator_name 102 | 103 initiator_address 104 | 105 initiator_alias 106 | 107 user 108 | 109 secret 110 | 111 mutual_user 112 | 113 mutual_secret 114 | 115 auth_method 116 | 117 header_digest 118 | 119 data_digest 120 | 121 session_type 122 | 123 enable 124 | 125 offload 126 | 127 protocol 128 | 129 ignored 130 ; 131 132 target_name: TARGET_NAME EQUALS STR 133 { 134 if (target->t_name != NULL) 135 xo_errx(1, "duplicated TargetName at line %d", lineno); 136 target->t_name = $3; 137 } 138 ; 139 140 target_address: TARGET_ADDRESS EQUALS STR 141 { 142 if (target->t_address != NULL) 143 xo_errx(1, "duplicated TargetAddress at line %d", lineno); 144 target->t_address = $3; 145 } 146 ; 147 148 initiator_name: INITIATOR_NAME EQUALS STR 149 { 150 if (target->t_initiator_name != NULL) 151 xo_errx(1, "duplicated InitiatorName at line %d", lineno); 152 target->t_initiator_name = $3; 153 } 154 ; 155 156 initiator_address: INITIATOR_ADDRESS EQUALS STR 157 { 158 if (target->t_initiator_address != NULL) 159 xo_errx(1, "duplicated InitiatorAddress at line %d", lineno); 160 target->t_initiator_address = $3; 161 } 162 ; 163 164 initiator_alias: INITIATOR_ALIAS EQUALS STR 165 { 166 if (target->t_initiator_alias != NULL) 167 xo_errx(1, "duplicated InitiatorAlias at line %d", lineno); 168 target->t_initiator_alias = $3; 169 } 170 ; 171 172 user: USER EQUALS STR 173 { 174 if (target->t_user != NULL) 175 xo_errx(1, "duplicated chapIName at line %d", lineno); 176 target->t_user = $3; 177 } 178 ; 179 180 secret: SECRET EQUALS STR 181 { 182 if (target->t_secret != NULL) 183 xo_errx(1, "duplicated chapSecret at line %d", lineno); 184 target->t_secret = $3; 185 } 186 ; 187 188 mutual_user: MUTUAL_USER EQUALS STR 189 { 190 if (target->t_mutual_user != NULL) 191 xo_errx(1, "duplicated tgtChapName at line %d", lineno); 192 target->t_mutual_user = $3; 193 } 194 ; 195 196 mutual_secret: MUTUAL_SECRET EQUALS STR 197 { 198 if (target->t_mutual_secret != NULL) 199 xo_errx(1, "duplicated tgtChapSecret at line %d", lineno); 200 target->t_mutual_secret = $3; 201 } 202 ; 203 204 auth_method: AUTH_METHOD EQUALS STR 205 { 206 if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED) 207 xo_errx(1, "duplicated AuthMethod at line %d", lineno); 208 if (strcasecmp($3, "none") == 0) 209 target->t_auth_method = AUTH_METHOD_NONE; 210 else if (strcasecmp($3, "chap") == 0) 211 target->t_auth_method = AUTH_METHOD_CHAP; 212 else 213 xo_errx(1, "invalid AuthMethod at line %d; " 214 "must be either \"none\" or \"CHAP\"", lineno); 215 } 216 ; 217 218 header_digest: HEADER_DIGEST EQUALS STR 219 { 220 if (target->t_header_digest != DIGEST_UNSPECIFIED) 221 xo_errx(1, "duplicated HeaderDigest at line %d", lineno); 222 if (strcasecmp($3, "none") == 0) 223 target->t_header_digest = DIGEST_NONE; 224 else if (strcasecmp($3, "CRC32C") == 0) 225 target->t_header_digest = DIGEST_CRC32C; 226 else 227 xo_errx(1, "invalid HeaderDigest at line %d; " 228 "must be either \"none\" or \"CRC32C\"", lineno); 229 } 230 ; 231 232 data_digest: DATA_DIGEST EQUALS STR 233 { 234 if (target->t_data_digest != DIGEST_UNSPECIFIED) 235 xo_errx(1, "duplicated DataDigest at line %d", lineno); 236 if (strcasecmp($3, "none") == 0) 237 target->t_data_digest = DIGEST_NONE; 238 else if (strcasecmp($3, "CRC32C") == 0) 239 target->t_data_digest = DIGEST_CRC32C; 240 else 241 xo_errx(1, "invalid DataDigest at line %d; " 242 "must be either \"none\" or \"CRC32C\"", lineno); 243 } 244 ; 245 246 session_type: SESSION_TYPE EQUALS STR 247 { 248 if (target->t_session_type != SESSION_TYPE_UNSPECIFIED) 249 xo_errx(1, "duplicated SessionType at line %d", lineno); 250 if (strcasecmp($3, "normal") == 0) 251 target->t_session_type = SESSION_TYPE_NORMAL; 252 else if (strcasecmp($3, "discovery") == 0) 253 target->t_session_type = SESSION_TYPE_DISCOVERY; 254 else 255 xo_errx(1, "invalid SessionType at line %d; " 256 "must be either \"normal\" or \"discovery\"", lineno); 257 } 258 ; 259 260 enable: ENABLE EQUALS STR 261 { 262 if (target->t_enable != ENABLE_UNSPECIFIED) 263 xo_errx(1, "duplicated enable at line %d", lineno); 264 target->t_enable = parse_enable($3); 265 if (target->t_enable == ENABLE_UNSPECIFIED) 266 xo_errx(1, "invalid enable at line %d; " 267 "must be either \"on\" or \"off\"", lineno); 268 } 269 ; 270 271 offload: OFFLOAD EQUALS STR 272 { 273 if (target->t_offload != NULL) 274 xo_errx(1, "duplicated offload at line %d", lineno); 275 target->t_offload = $3; 276 } 277 ; 278 279 protocol: PROTOCOL EQUALS STR 280 { 281 if (target->t_protocol != PROTOCOL_UNSPECIFIED) 282 xo_errx(1, "duplicated protocol at line %d", lineno); 283 if (strcasecmp($3, "iscsi") == 0) 284 target->t_protocol = PROTOCOL_ISCSI; 285 else if (strcasecmp($3, "iser") == 0) 286 target->t_protocol = PROTOCOL_ISER; 287 else 288 xo_errx(1, "invalid protocol at line %d; " 289 "must be either \"iscsi\" or \"iser\"", lineno); 290 } 291 ; 292 293 ignored: IGNORED EQUALS STR 294 { 295 xo_warnx("obsolete statement ignored at line %d", lineno); 296 } 297 ; 298 299 %% 300 301 void 302 yyerror(const char *str) 303 { 304 305 xo_errx(1, "error in configuration file at line %d near '%s': %s", 306 lineno, yytext, str); 307 } 308 309 static void 310 check_perms(const char *path) 311 { 312 struct stat sb; 313 int error; 314 315 error = stat(path, &sb); 316 if (error != 0) { 317 xo_warn("stat"); 318 return; 319 } 320 if (sb.st_mode & S_IWOTH) { 321 xo_warnx("%s is world-writable", path); 322 } else if (sb.st_mode & S_IROTH) { 323 xo_warnx("%s is world-readable", path); 324 } else if (sb.st_mode & S_IXOTH) { 325 /* 326 * Ok, this one doesn't matter, but still do it, 327 * just for consistency. 328 */ 329 xo_warnx("%s is world-executable", path); 330 } 331 332 /* 333 * XXX: Should we also check for owner != 0? 334 */ 335 } 336 337 struct conf * 338 conf_new_from_file(const char *path) 339 { 340 int error; 341 342 conf = conf_new(); 343 target = target_new(conf); 344 345 yyin = fopen(path, "r"); 346 if (yyin == NULL) 347 xo_err(1, "unable to open configuration file %s", path); 348 check_perms(path); 349 lineno = 1; 350 yyrestart(yyin); 351 error = yyparse(); 352 assert(error == 0); 353 fclose(yyin); 354 355 assert(target->t_nickname == NULL); 356 target_delete(target); 357 358 conf_verify(conf); 359 360 return (conf); 361 } 362