parse.y revision 262840
118334Speter%{
252298Sobrien/*-
318334Speter * Copyright (c) 2012 The FreeBSD Foundation
418334Speter * All rights reserved.
518334Speter *
618334Speter * This software was developed by Edward Tomasz Napierala under sponsorship
718334Speter * from the FreeBSD Foundation.
818334Speter *
918334Speter * Redistribution and use in source and binary forms, with or without
1018334Speter * modification, are permitted provided that the following conditions
1118334Speter * are met:
1218334Speter * 1. Redistributions of source code must retain the above copyright
1318334Speter *    notice, this list of conditions and the following disclaimer.
1418334Speter * 2. Redistributions in binary form must reproduce the above copyright
1518334Speter *    notice, this list of conditions and the following disclaimer in the
1618334Speter *    documentation and/or other materials provided with the distribution.
1718334Speter *
1818334Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1918334Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2018334Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2152298Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2252298Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2318334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2418334Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2518334Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2618334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2718334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2818334Speter * SUCH DAMAGE.
2918334Speter *
3018334Speter * $FreeBSD: stable/10/usr.bin/iscsictl/parse.y 262840 2014-03-06 11:05:35Z trasz $
3150448Sobrien */
3250448Sobrien
3350448Sobrien#include <sys/queue.h>
3450448Sobrien#include <sys/types.h>
3518334Speter#include <sys/stat.h>
3618334Speter#include <assert.h>
3718334Speter#include <err.h>
3818334Speter#include <stdio.h>
3918334Speter#include <stdint.h>
4050448Sobrien#include <stdlib.h>
4118334Speter#include <string.h>
4218334Speter
4318334Speter#include "iscsictl.h"
4452298Sobrien
4552298Sobrienextern FILE *yyin;
4618334Speterextern char *yytext;
4752298Sobrienextern int lineno;
4852298Sobrien
4952298Sobrienstatic struct conf *conf;
5052298Sobrienstatic struct target *target;
5152298Sobrien
5250448Sobrienextern void	yyerror(const char *);
5350448Sobrienextern int	yylex(void);
5450448Sobrienextern void	yyrestart(FILE *);
5550448Sobrien
5618334Speter%}
5718334Speter
5818334Speter%token AUTH_METHOD HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
5918334Speter%token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
6018334Speter%token MUTUAL_USER MUTUAL_SECRET SESSION_TYPE PROTOCOL IGNORED
6118334Speter%token EQUALS OPENING_BRACKET CLOSING_BRACKET
6218334Speter
6318334Speter%union
6452298Sobrien{
6552298Sobrien	char *str;
6650448Sobrien}
6750448Sobrien
6850448Sobrien%token <str> STR
6918334Speter
7050448Sobrien%%
7118334Speter
7250448Sobrientargets:
7352298Sobrien	|
7418334Speter	targets target
7550448Sobrien	;
7652298Sobrien
7718334Spetertarget:		STR OPENING_BRACKET target_entries CLOSING_BRACKET
7818334Speter	{
7918334Speter		if (target_find(conf, $1) != NULL)
8018334Speter			errx(1, "duplicated target %s", $1);
8118334Speter		target->t_nickname = $1;
8218334Speter		target = target_new(conf);
8318334Speter	}
8452298Sobrien	;
8550448Sobrien
8650448Sobrientarget_entries:
8750448Sobrien	|
8850448Sobrien	target_entries target_entry
8950448Sobrien	;
9050448Sobrien
9150448Sobrientarget_entry:
9252298Sobrien	target_name
9318334Speter	|
9450448Sobrien	target_address
9518334Speter	|
9618334Speter	initiator_name
9718334Speter	|
9850448Sobrien	initiator_address
9950448Sobrien	|
10018334Speter	initiator_alias
10118334Speter	|
10250448Sobrien	user
10350448Sobrien	|
10450448Sobrien	secret
10550448Sobrien	|
10650448Sobrien	mutual_user
10718334Speter	|
10850448Sobrien	mutual_secret
10950448Sobrien	|
11052298Sobrien	auth_method
11152298Sobrien	|
11252298Sobrien	header_digest
11350448Sobrien	|
11418334Speter	data_digest
11518334Speter	|
11618334Speter	session_type
11750448Sobrien	|
11818334Speter	protocol
11918334Speter	|
12018334Speter	ignored
12118334Speter	;
12218334Speter
12318334Spetertarget_name:	TARGET_NAME EQUALS STR
12418334Speter	{
12518334Speter		if (target->t_name != NULL)
12618334Speter			errx(1, "duplicated TargetName at line %d", lineno);
12752298Sobrien		target->t_name = $3;
12852298Sobrien	}
12952298Sobrien	;
13018334Speter
13118334Spetertarget_address:	TARGET_ADDRESS EQUALS STR
13218334Speter	{
13318334Speter		if (target->t_address != NULL)
13418334Speter			errx(1, "duplicated TargetAddress at line %d", lineno);
13518334Speter		target->t_address = $3;
13618334Speter	}
13718334Speter	;
13818334Speter
13918334Speterinitiator_name:	INITIATOR_NAME EQUALS STR
14018334Speter	{
14118334Speter		if (target->t_initiator_name != NULL)
14218334Speter			errx(1, "duplicated InitiatorName at line %d", lineno);
14350448Sobrien		target->t_initiator_name = $3;
14418334Speter	}
14518334Speter	;
14618334Speter
14750448Sobrieninitiator_address:	INITIATOR_ADDRESS EQUALS STR
14818334Speter	{
14918334Speter		if (target->t_initiator_address != NULL)
15018334Speter			errx(1, "duplicated InitiatorAddress at line %d", lineno);
15118334Speter		target->t_initiator_address = $3;
15218334Speter	}
15318334Speter	;
15418334Speter
15550448Sobrieninitiator_alias:	INITIATOR_ALIAS EQUALS STR
15650448Sobrien	{
15718334Speter		if (target->t_initiator_alias != NULL)
15818334Speter			errx(1, "duplicated InitiatorAlias at line %d", lineno);
15950448Sobrien		target->t_initiator_alias = $3;
16050448Sobrien	}
16118334Speter	;
16252298Sobrien
16350448Sobrienuser:		USER EQUALS STR
16418334Speter	{
16518334Speter		if (target->t_user != NULL)
16618334Speter			errx(1, "duplicated chapIName at line %d", lineno);
16718334Speter		target->t_user = $3;
16818334Speter	}
16918334Speter	;
17018334Speter
17118334Spetersecret:		SECRET EQUALS STR
17252298Sobrien	{
17318334Speter		if (target->t_secret != NULL)
17418334Speter			errx(1, "duplicated chapSecret at line %d", lineno);
17518334Speter		target->t_secret = $3;
17618334Speter	}
17750448Sobrien	;
17818334Speter
17918334Spetermutual_user:	MUTUAL_USER EQUALS STR
18050448Sobrien	{
18150448Sobrien		if (target->t_mutual_user != NULL)
18218334Speter			errx(1, "duplicated tgtChapName at line %d", lineno);
18350448Sobrien		target->t_mutual_user = $3;
18450448Sobrien	}
18550448Sobrien	;
18618334Speter
18718334Spetermutual_secret:	MUTUAL_SECRET EQUALS STR
18818334Speter	{
18918334Speter		if (target->t_mutual_secret != NULL)
19050448Sobrien			errx(1, "duplicated tgtChapSecret at line %d", lineno);
19150448Sobrien		target->t_mutual_secret = $3;
19250448Sobrien	}
19350448Sobrien	;
19450448Sobrien
19550448Sobrienauth_method:	AUTH_METHOD EQUALS STR
19650448Sobrien	{
19750448Sobrien		if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED)
19850448Sobrien			errx(1, "duplicated AuthMethod at line %d", lineno);
19950448Sobrien		if (strcasecmp($3, "none") == 0)
20050448Sobrien			target->t_auth_method = AUTH_METHOD_NONE;
20150448Sobrien		else if (strcasecmp($3, "chap") == 0)
20250448Sobrien			target->t_auth_method = AUTH_METHOD_CHAP;
20350448Sobrien		else
20450448Sobrien			errx(1, "invalid AuthMethod at line %d; "
20552298Sobrien			    "must be either \"none\" or \"CHAP\"", lineno);
20650448Sobrien	}
20750448Sobrien	;
20850448Sobrien
20950448Sobrienheader_digest:	HEADER_DIGEST EQUALS STR
21050448Sobrien	{
21150448Sobrien		if (target->t_header_digest != DIGEST_UNSPECIFIED)
21250448Sobrien			errx(1, "duplicated HeaderDigest at line %d", lineno);
21350448Sobrien		if (strcasecmp($3, "none") == 0)
21450448Sobrien			target->t_header_digest = DIGEST_NONE;
21550448Sobrien		else if (strcasecmp($3, "CRC32C") == 0)
21650448Sobrien			target->t_header_digest = DIGEST_CRC32C;
21750448Sobrien		else
21850448Sobrien			errx(1, "invalid HeaderDigest at line %d; "
21950448Sobrien			    "must be either \"none\" or \"CRC32C\"", lineno);
22018334Speter	}
22118334Speter	;
22218334Speter
22318334Speterdata_digest:	DATA_DIGEST EQUALS STR
22418334Speter	{
22518334Speter		if (target->t_data_digest != DIGEST_UNSPECIFIED)
22618334Speter			errx(1, "duplicated DataDigest at line %d", lineno);
22718334Speter		if (strcasecmp($3, "none") == 0)
22818334Speter			target->t_data_digest = DIGEST_NONE;
22918334Speter		else if (strcasecmp($3, "CRC32C") == 0)
23018334Speter			target->t_data_digest = DIGEST_CRC32C;
23118334Speter		else
23218334Speter			errx(1, "invalid DataDigest at line %d; "
23318334Speter			    "must be either \"none\" or \"CRC32C\"", lineno);
23418334Speter	}
23518334Speter	;
23618334Speter
23750448Sobriensession_type:	SESSION_TYPE EQUALS STR
23850448Sobrien	{
23950448Sobrien		if (target->t_session_type != SESSION_TYPE_UNSPECIFIED)
24050448Sobrien			errx(1, "duplicated SessionType at line %d", lineno);
24150448Sobrien		if (strcasecmp($3, "normal") == 0)
24250448Sobrien			target->t_session_type = SESSION_TYPE_NORMAL;
24350448Sobrien		else if (strcasecmp($3, "discovery") == 0)
24450448Sobrien			target->t_session_type = SESSION_TYPE_DISCOVERY;
24550448Sobrien		else
24650448Sobrien			errx(1, "invalid SessionType at line %d; "
24750448Sobrien			    "must be either \"normal\" or \"discovery\"", lineno);
24850448Sobrien	}
24952298Sobrien	;
25050448Sobrien
25152298Sobrienprotocol:	PROTOCOL EQUALS STR
25252298Sobrien	{
25350448Sobrien		if (target->t_protocol != PROTOCOL_UNSPECIFIED)
25450448Sobrien			errx(1, "duplicated protocol at line %d", lineno);
25550448Sobrien		if (strcasecmp($3, "iscsi") == 0)
25650448Sobrien			target->t_protocol = PROTOCOL_ISCSI;
25750448Sobrien		else if (strcasecmp($3, "iser") == 0)
25818334Speter			target->t_protocol = PROTOCOL_ISER;
25918334Speter		else
26018334Speter			errx(1, "invalid protocol at line %d; "
26118334Speter			    "must be either \"iscsi\" or \"iser\"", lineno);
26250448Sobrien	}
26318334Speter	;
26418334Speter
26518334Speterignored:	IGNORED EQUALS STR
26618334Speter	{
26750448Sobrien		warnx("obsolete statement ignored at line %d", lineno);
26818334Speter	}
26950448Sobrien	;
27018334Speter
27150448Sobrien%%
27218334Speter
27350448Sobrienvoid
27418334Speteryyerror(const char *str)
27550448Sobrien{
27652298Sobrien
27752298Sobrien	errx(1, "error in configuration file at line %d near '%s': %s",
27852298Sobrien	    lineno, yytext, str);
27952298Sobrien}
28052298Sobrien
28152298Sobrienstatic void
28252298Sobriencheck_perms(const char *path)
28352298Sobrien{
28418334Speter	struct stat sb;
28552298Sobrien	int error;
28618334Speter
28718334Speter	error = stat(path, &sb);
28818334Speter	if (error != 0) {
28918334Speter		warn("stat");
29052298Sobrien		return;
29118334Speter	}
29250448Sobrien	if (sb.st_mode & S_IWOTH) {
29350448Sobrien		warnx("%s is world-writable", path);
29450448Sobrien	} else if (sb.st_mode & S_IROTH) {
29552298Sobrien		warnx("%s is world-readable", path);
29652298Sobrien	} else if (sb.st_mode & S_IXOTH) {
29752298Sobrien		/*
29818334Speter		 * Ok, this one doesn't matter, but still do it,
29918334Speter		 * just for consistency.
30018334Speter		 */
30150448Sobrien		warnx("%s is world-executable", path);
30250448Sobrien	}
30318334Speter
30418334Speter	/*
30552298Sobrien	 * XXX: Should we also check for owner != 0?
30652298Sobrien	 */
30718334Speter}
30818334Speter
30918334Speterstruct conf *
31052298Sobrienconf_new_from_file(const char *path)
31152298Sobrien{
31252298Sobrien	int error;
31352298Sobrien
31452298Sobrien	conf = conf_new();
31552298Sobrien	target = target_new(conf);
31652298Sobrien
31752298Sobrien	yyin = fopen(path, "r");
31852298Sobrien	if (yyin == NULL)
31952298Sobrien		err(1, "unable to open configuration file %s", path);
32052298Sobrien	check_perms(path);
32152298Sobrien	lineno = 1;
32252298Sobrien	yyrestart(yyin);
32318334Speter	error = yyparse();
32418334Speter	assert(error == 0);
32518334Speter	fclose(yyin);
32618334Speter
32718334Speter	assert(target->t_nickname == NULL);
32818334Speter	target_delete(target);
32918334Speter
33050448Sobrien	conf_verify(conf);
33150448Sobrien
33250448Sobrien	return (conf);
33350448Sobrien}
33418334Speter