parse.y revision 262840
1100280Sgordon%{
2100280Sgordon/*-
3118638Sfjoe * Copyright (c) 2012 The FreeBSD Foundation
466830Sobrien * All rights reserved.
566830Sobrien *
666830Sobrien * This software was developed by Edward Tomasz Napierala under sponsorship
766830Sobrien * from the FreeBSD Foundation.
866830Sobrien *
966830Sobrien * Redistribution and use in source and binary forms, with or without
1066830Sobrien * modification, are permitted provided that the following conditions
1166830Sobrien * are met:
1266830Sobrien * 1. Redistributions of source code must retain the above copyright
1366830Sobrien *    notice, this list of conditions and the following disclaimer.
1466830Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1566830Sobrien *    notice, this list of conditions and the following disclaimer in the
1666830Sobrien *    documentation and/or other materials provided with the distribution.
1766830Sobrien *
1866830Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1966830Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2066830Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2166830Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2266830Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2366830Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2466830Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2566830Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2666830Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2751231Ssheldonh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28100280Sgordon * SUCH DAMAGE.
29108191Sdillon *
30127663Sluigi * $FreeBSD: stable/10/usr.bin/iscsictl/parse.y 262840 2014-03-06 11:05:35Z trasz $
31108191Sdillon */
32108191Sdillon
33127663Sluigi#include <sys/queue.h>
34127663Sluigi#include <sys/types.h>
35127663Sluigi#include <sys/stat.h>
36127663Sluigi#include <assert.h>
37108191Sdillon#include <err.h>
38127663Sluigi#include <stdio.h>
39127663Sluigi#include <stdint.h>
40127663Sluigi#include <stdlib.h>
41108191Sdillon#include <string.h>
42127663Sluigi
43127663Sluigi#include "iscsictl.h"
44127663Sluigi
45127663Sluigiextern FILE *yyin;
46149170Sbrooksextern char *yytext;
47127663Sluigiextern int lineno;
48127663Sluigi
49127663Sluigistatic struct conf *conf;
50127663Sluigistatic struct target *target;
51127663Sluigi
52127663Sluigiextern void	yyerror(const char *);
53149170Sbrooksextern int	yylex(void);
54130151Sschweikhextern void	yyrestart(FILE *);
55127663Sluigi
56127663Sluigi%}
57149170Sbrooks
58149170Sbrooks%token AUTH_METHOD HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
59108191Sdillon%token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
60127663Sluigi%token MUTUAL_USER MUTUAL_SECRET SESSION_TYPE PROTOCOL IGNORED
61127663Sluigi%token EQUALS OPENING_BRACKET CLOSING_BRACKET
62126787Sphk
63127663Sluigi%union
64108191Sdillon{
65127663Sluigi	char *str;
66127663Sluigi}
67127663Sluigi
68127663Sluigi%token <str> STR
69127663Sluigi
70127663Sluigi%%
71108191Sdillon
72179014Sbmstargets:
73179014Sbms	|
74179014Sbms	targets target
75179014Sbms	;
76182895Sbms
77182895Sbmstarget:		STR OPENING_BRACKET target_entries CLOSING_BRACKET
78182895Sbms	{
79182895Sbms		if (target_find(conf, $1) != NULL)
80182895Sbms			errx(1, "duplicated target %s", $1);
81182895Sbms		target->t_nickname = $1;
82182895Sbms		target = target_new(conf);
83182895Sbms	}
84182895Sbms	;
85182895Sbms
86127663Sluigitarget_entries:
87164862Sluigi	|
88164862Sluigi	target_entries target_entry
89164862Sluigi	;
90164862Sluigi
91164862Sluigitarget_entry:
92164862Sluigi	target_name
93164862Sluigi	|
94161824Sbrooks	target_address
95161824Sbrooks	|
96161824Sbrooks	initiator_name
97108191Sdillon	|
98127663Sluigi	initiator_address
99127663Sluigi	|
100127663Sluigi	initiator_alias
101127663Sluigi	|
102127663Sluigi	user
103127663Sluigi	|
104127663Sluigi	secret
105127663Sluigi	|
106127663Sluigi	mutual_user
107127663Sluigi	|
108108191Sdillon	mutual_secret
109127663Sluigi	|
110127663Sluigi	auth_method
111127663Sluigi	|
112127663Sluigi	header_digest
113108191Sdillon	|
114127663Sluigi	data_digest
115127663Sluigi	|
116127663Sluigi	session_type
117127663Sluigi	|
118161824Sbrooks	protocol
119161824Sbrooks	|
120161824Sbrooks	ignored
121161824Sbrooks	;
122161824Sbrooks
123208060Sdougbtarget_name:	TARGET_NAME EQUALS STR
124127663Sluigi	{
125127663Sluigi		if (target->t_name != NULL)
126161533Sru			errx(1, "duplicated TargetName at line %d", lineno);
127161533Sru		target->t_name = $3;
128161533Sru	}
129161533Sru	;
130161533Sru
131161533Srutarget_address:	TARGET_ADDRESS EQUALS STR
132127663Sluigi	{
133161533Sru		if (target->t_address != NULL)
134161533Sru			errx(1, "duplicated TargetAddress at line %d", lineno);
135161533Sru		target->t_address = $3;
136161533Sru	}
137161533Sru	;
138161533Sru
139127663Sluigiinitiator_name:	INITIATOR_NAME EQUALS STR
140127663Sluigi	{
141127663Sluigi		if (target->t_initiator_name != NULL)
142127663Sluigi			errx(1, "duplicated InitiatorName at line %d", lineno);
143127663Sluigi		target->t_initiator_name = $3;
144126868Sbrooks	}
145127663Sluigi	;
146127663Sluigi
147108191Sdilloninitiator_address:	INITIATOR_ADDRESS EQUALS STR
148100280Sgordon	{
149100280Sgordon		if (target->t_initiator_address != NULL)
150164862Sluigi			errx(1, "duplicated InitiatorAddress at line %d", lineno);
151164862Sluigi		target->t_initiator_address = $3;
152164862Sluigi	}
153164862Sluigi	;
154164862Sluigi
155164862Sluigiinitiator_alias:	INITIATOR_ALIAS EQUALS STR
156164862Sluigi	{
157164862Sluigi		if (target->t_initiator_alias != NULL)
15843803Sdillon			errx(1, "duplicated InitiatorAlias at line %d", lineno);
15943803Sdillon		target->t_initiator_alias = $3;
16043803Sdillon	}
16143803Sdillon	;
16243803Sdillon
16343803Sdillonuser:		USER EQUALS STR
164179014Sbms	{
16551231Ssheldonh		if (target->t_user != NULL)
166108191Sdillon			errx(1, "duplicated chapIName at line %d", lineno);
167179014Sbms		target->t_user = $3;
168179014Sbms	}
169179014Sbms	;
170108191Sdillon
171108191Sdillonsecret:		SECRET EQUALS STR
172108191Sdillon	{
173108191Sdillon		if (target->t_secret != NULL)
174108191Sdillon			errx(1, "duplicated chapSecret at line %d", lineno);
175108191Sdillon		target->t_secret = $3;
176108191Sdillon	}
177108191Sdillon	;
178108191Sdillon
17943803Sdillonmutual_user:	MUTUAL_USER EQUALS STR
18043803Sdillon	{
181164862Sluigi		if (target->t_mutual_user != NULL)
182164862Sluigi			errx(1, "duplicated tgtChapName at line %d", lineno);
183164862Sluigi		target->t_mutual_user = $3;
184164862Sluigi	}
185164862Sluigi	;
186164862Sluigi
187164862Sluigimutual_secret:	MUTUAL_SECRET EQUALS STR
188164862Sluigi	{
189164862Sluigi		if (target->t_mutual_secret != NULL)
190164862Sluigi			errx(1, "duplicated tgtChapSecret at line %d", lineno);
191164862Sluigi		target->t_mutual_secret = $3;
192164862Sluigi	}
193164862Sluigi	;
194164862Sluigi
195164862Sluigiauth_method:	AUTH_METHOD EQUALS STR
196164862Sluigi	{
197164862Sluigi		if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED)
198108191Sdillon			errx(1, "duplicated AuthMethod at line %d", lineno);
199108191Sdillon		if (strcasecmp($3, "none") == 0)
200108191Sdillon			target->t_auth_method = AUTH_METHOD_NONE;
201154239Sbrooks		else if (strcasecmp($3, "chap") == 0)
20275931Simp			target->t_auth_method = AUTH_METHOD_CHAP;
20375931Simp		else
204108191Sdillon			errx(1, "invalid AuthMethod at line %d; "
205108191Sdillon			    "must be either \"none\" or \"CHAP\"", lineno);
206108191Sdillon	}
207164862Sluigi	;
208110942Sjhay
209121014Skrisheader_digest:	HEADER_DIGEST EQUALS STR
210108191Sdillon	{
211108191Sdillon		if (target->t_header_digest != DIGEST_UNSPECIFIED)
212108191Sdillon			errx(1, "duplicated HeaderDigest at line %d", lineno);
213164862Sluigi		if (strcasecmp($3, "none") == 0)
214108191Sdillon			target->t_header_digest = DIGEST_NONE;
215108191Sdillon		else if (strcasecmp($3, "CRC32C") == 0)
216108191Sdillon			target->t_header_digest = DIGEST_CRC32C;
217108191Sdillon		else
218108191Sdillon			errx(1, "invalid HeaderDigest at line %d; "
21943803Sdillon			    "must be either \"none\" or \"CRC32C\"", lineno);
22043803Sdillon	}
22155520Sluigi	;
22243803Sdillon
22351231Ssheldonhdata_digest:	DATA_DIGEST EQUALS STR
22443803Sdillon	{
22555520Sluigi		if (target->t_data_digest != DIGEST_UNSPECIFIED)
22655520Sluigi			errx(1, "duplicated DataDigest at line %d", lineno);
22755520Sluigi		if (strcasecmp($3, "none") == 0)
228149170Sbrooks			target->t_data_digest = DIGEST_NONE;
229126787Sphk		else if (strcasecmp($3, "CRC32C") == 0)
230126787Sphk			target->t_data_digest = DIGEST_CRC32C;
231126787Sphk		else
232128706Sru			errx(1, "invalid DataDigest at line %d; "
233126787Sphk			    "must be either \"none\" or \"CRC32C\"", lineno);
234126787Sphk	}
235126787Sphk	;
236126787Sphk
237126787Sphksession_type:	SESSION_TYPE EQUALS STR
238126787Sphk	{
239126787Sphk		if (target->t_session_type != SESSION_TYPE_UNSPECIFIED)
240126787Sphk			errx(1, "duplicated SessionType at line %d", lineno);
241126787Sphk		if (strcasecmp($3, "normal") == 0)
242126787Sphk			target->t_session_type = SESSION_TYPE_NORMAL;
243126787Sphk		else if (strcasecmp($3, "discovery") == 0)
244126787Sphk			target->t_session_type = SESSION_TYPE_DISCOVERY;
245126787Sphk		else
246149170Sbrooks			errx(1, "invalid SessionType at line %d; "
247150169Srwatson			    "must be either \"normal\" or \"discovery\"", lineno);
248127657Sluigi	}
249149170Sbrooks	;
250126787Sphk
25143803Sdillonprotocol:	PROTOCOL EQUALS STR
252164862Sluigi	{
253121067Sdougb		if (target->t_protocol != PROTOCOL_UNSPECIFIED)
254128706Sru			errx(1, "duplicated protocol at line %d", lineno);
255117087Sbrooks		if (strcasecmp($3, "iscsi") == 0)
256117087Sbrooks			target->t_protocol = PROTOCOL_ISCSI;
257117087Sbrooks		else if (strcasecmp($3, "iser") == 0)
258117087Sbrooks			target->t_protocol = PROTOCOL_ISER;
259117087Sbrooks		else
260117087Sbrooks			errx(1, "invalid protocol at line %d; "
261117087Sbrooks			    "must be either \"iscsi\" or \"iser\"", lineno);
262117087Sbrooks	}
263127657Sluigi	;
264149170Sbrooks
265149170Sbrooksignored:	IGNORED EQUALS STR
266149170Sbrooks	{
267149170Sbrooks		warnx("obsolete statement ignored at line %d", lineno);
268149170Sbrooks	}
269149170Sbrooks	;
270149170Sbrooks
271149170Sbrooks%%
272149170Sbrooks
273149170Sbrooksvoid
274127657Sluigiyyerror(const char *str)
275161824Sbrooks{
276164862Sluigi
277126868Sbrooks	errx(1, "error in configuration file at line %d near '%s': %s",
278108191Sdillon	    lineno, yytext, str);
279121067Sdougb}
280108191Sdillon
28143803Sdillonstatic void
282108191Sdilloncheck_perms(const char *path)
283108191Sdillon{
284108191Sdillon	struct stat sb;
285108191Sdillon	int error;
286108191Sdillon
287108191Sdillon	error = stat(path, &sb);
288108191Sdillon	if (error != 0) {
289108191Sdillon		warn("stat");
290108191Sdillon		return;
291108191Sdillon	}
292108191Sdillon	if (sb.st_mode & S_IWOTH) {
293117087Sbrooks		warnx("%s is world-writable", path);
294117087Sbrooks	} else if (sb.st_mode & S_IROTH) {
295117087Sbrooks		warnx("%s is world-readable", path);
296117087Sbrooks	} else if (sb.st_mode & S_IXOTH) {
297108191Sdillon		/*
298164862Sluigi		 * Ok, this one doesn't matter, but still do it,
299127657Sluigi		 * just for consistency.
300108191Sdillon		 */
301164862Sluigi		warnx("%s is world-executable", path);
302164862Sluigi	}
303108191Sdillon
304108191Sdillon	/*
305164862Sluigi	 * XXX: Should we also check for owner != 0?
30643803Sdillon	 */
307164862Sluigi}
308164862Sluigi
309182895Sbmsstruct conf *
310182895Sbmsconf_new_from_file(const char *path)
311182895Sbms{
312182895Sbms	int error;
313182895Sbms
314182895Sbms	conf = conf_new();
315182895Sbms	target = target_new(conf);
316182895Sbms
317182895Sbms	yyin = fopen(path, "r");
318182895Sbms	if (yyin == NULL)
319182895Sbms		err(1, "unable to open configuration file %s", path);
320182895Sbms	check_perms(path);
321182895Sbms	lineno = 1;
322182895Sbms	yyrestart(yyin);
323182895Sbms	error = yyparse();
324182895Sbms	assert(error == 0);
325182895Sbms	fclose(yyin);
326182895Sbms
327182895Sbms	assert(target->t_nickname == NULL);
328182895Sbms	target_delete(target);
329182895Sbms
330182895Sbms	conf_verify(conf);
331182895Sbms
332182895Sbms	return (conf);
333182895Sbms}
334182895Sbms