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
check_perms(const char * path)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 *
conf_new_from_file(const char * path)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