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