xref: /freebsd/usr.sbin/ctld/parse.y (revision bc96366c864c07ef352edb92017357917c75b36c)
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 <stdio.h>
38 #include <stdint.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include "ctld.h"
43 
44 extern FILE *yyin;
45 extern char *yytext;
46 extern int lineno;
47 
48 static struct conf *conf = NULL;
49 static struct auth_group *auth_group = NULL;
50 static struct portal_group *portal_group = NULL;
51 static struct target *target = NULL;
52 static struct lun *lun = NULL;
53 
54 extern void	yyerror(const char *);
55 extern int	yylex(void);
56 extern void	yyrestart(FILE *);
57 
58 %}
59 
60 %token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
61 %token CLOSING_BRACKET DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP DISCOVERY_FILTER
62 %token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
63 %token LISTEN LISTEN_ISER LUN MAXPROC OPENING_BRACKET OPTION
64 %token PATH PIDFILE PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR
65 %token TARGET TIMEOUT
66 
67 %union
68 {
69 	char *str;
70 }
71 
72 %token <str> STR
73 
74 %%
75 
76 statements:
77 	|
78 	statements statement
79 	|
80 	statements statement SEMICOLON
81 	;
82 
83 statement:
84 	debug
85 	|
86 	timeout
87 	|
88 	maxproc
89 	|
90 	pidfile
91 	|
92 	isns_server
93 	|
94 	isns_period
95 	|
96 	isns_timeout
97 	|
98 	auth_group
99 	|
100 	portal_group
101 	|
102 	target
103 	;
104 
105 debug:		DEBUG STR
106 	{
107 		uint64_t tmp;
108 
109 		if (expand_number($2, &tmp) != 0) {
110 			yyerror("invalid numeric value");
111 			free($2);
112 			return (1);
113 		}
114 
115 		conf->conf_debug = tmp;
116 	}
117 	;
118 
119 timeout:	TIMEOUT STR
120 	{
121 		uint64_t tmp;
122 
123 		if (expand_number($2, &tmp) != 0) {
124 			yyerror("invalid numeric value");
125 			free($2);
126 			return (1);
127 		}
128 
129 		conf->conf_timeout = tmp;
130 	}
131 	;
132 
133 maxproc:	MAXPROC STR
134 	{
135 		uint64_t tmp;
136 
137 		if (expand_number($2, &tmp) != 0) {
138 			yyerror("invalid numeric value");
139 			free($2);
140 			return (1);
141 		}
142 
143 		conf->conf_maxproc = tmp;
144 	}
145 	;
146 
147 pidfile:	PIDFILE STR
148 	{
149 		if (conf->conf_pidfile_path != NULL) {
150 			log_warnx("pidfile specified more than once");
151 			free($2);
152 			return (1);
153 		}
154 		conf->conf_pidfile_path = $2;
155 	}
156 	;
157 
158 isns_server:	ISNS_SERVER STR
159 	{
160 		int error;
161 
162 		error = isns_new(conf, $2);
163 		free($2);
164 		if (error != 0)
165 			return (1);
166 	}
167 	;
168 
169 isns_period:	ISNS_PERIOD STR
170 	{
171 		uint64_t tmp;
172 
173 		if (expand_number($2, &tmp) != 0) {
174 			yyerror("invalid numeric value");
175 			free($2);
176 			return (1);
177 		}
178 
179 		conf->conf_isns_period = tmp;
180 	}
181 	;
182 
183 isns_timeout:	ISNS_TIMEOUT STR
184 	{
185 		uint64_t tmp;
186 
187 		if (expand_number($2, &tmp) != 0) {
188 			yyerror("invalid numeric value");
189 			free($2);
190 			return (1);
191 		}
192 
193 		conf->conf_isns_timeout = tmp;
194 	}
195 	;
196 
197 auth_group:	AUTH_GROUP auth_group_name
198     OPENING_BRACKET auth_group_entries CLOSING_BRACKET
199 	{
200 		auth_group = NULL;
201 	}
202 	;
203 
204 auth_group_name:	STR
205 	{
206 		/*
207 		 * Make it possible to redefine default
208 		 * auth-group. but only once.
209 		 */
210 		if (strcmp($1, "default") == 0 &&
211 		    conf->conf_default_ag_defined == false) {
212 			auth_group = auth_group_find(conf, $1);
213 			conf->conf_default_ag_defined = true;
214 		} else {
215 			auth_group = auth_group_new(conf, $1);
216 		}
217 		free($1);
218 		if (auth_group == NULL)
219 			return (1);
220 	}
221 	;
222 
223 auth_group_entries:
224 	|
225 	auth_group_entries auth_group_entry
226 	|
227 	auth_group_entries auth_group_entry SEMICOLON
228 	;
229 
230 auth_group_entry:
231 	auth_group_auth_type
232 	|
233 	auth_group_chap
234 	|
235 	auth_group_chap_mutual
236 	|
237 	auth_group_initiator_name
238 	|
239 	auth_group_initiator_portal
240 	;
241 
242 auth_group_auth_type:	AUTH_TYPE STR
243 	{
244 		int error;
245 
246 		error = auth_group_set_type(auth_group, $2);
247 		free($2);
248 		if (error != 0)
249 			return (1);
250 	}
251 	;
252 
253 auth_group_chap:	CHAP STR STR
254 	{
255 		const struct auth *ca;
256 
257 		ca = auth_new_chap(auth_group, $2, $3);
258 		free($2);
259 		free($3);
260 		if (ca == NULL)
261 			return (1);
262 	}
263 	;
264 
265 auth_group_chap_mutual:	CHAP_MUTUAL STR STR STR STR
266 	{
267 		const struct auth *ca;
268 
269 		ca = auth_new_chap_mutual(auth_group, $2, $3, $4, $5);
270 		free($2);
271 		free($3);
272 		free($4);
273 		free($5);
274 		if (ca == NULL)
275 			return (1);
276 	}
277 	;
278 
279 auth_group_initiator_name:	INITIATOR_NAME STR
280 	{
281 		const struct auth_name *an;
282 
283 		an = auth_name_new(auth_group, $2);
284 		free($2);
285 		if (an == NULL)
286 			return (1);
287 	}
288 	;
289 
290 auth_group_initiator_portal:	INITIATOR_PORTAL STR
291 	{
292 		const struct auth_portal *ap;
293 
294 		ap = auth_portal_new(auth_group, $2);
295 		free($2);
296 		if (ap == NULL)
297 			return (1);
298 	}
299 	;
300 
301 portal_group:	PORTAL_GROUP portal_group_name
302     OPENING_BRACKET portal_group_entries CLOSING_BRACKET
303 	{
304 		portal_group = NULL;
305 	}
306 	;
307 
308 portal_group_name:	STR
309 	{
310 		/*
311 		 * Make it possible to redefine default
312 		 * portal-group. but only once.
313 		 */
314 		if (strcmp($1, "default") == 0 &&
315 		    conf->conf_default_pg_defined == false) {
316 			portal_group = portal_group_find(conf, $1);
317 			conf->conf_default_pg_defined = true;
318 		} else {
319 			portal_group = portal_group_new(conf, $1);
320 		}
321 		free($1);
322 		if (portal_group == NULL)
323 			return (1);
324 	}
325 	;
326 
327 portal_group_entries:
328 	|
329 	portal_group_entries portal_group_entry
330 	|
331 	portal_group_entries portal_group_entry SEMICOLON
332 	;
333 
334 portal_group_entry:
335 	portal_group_discovery_auth_group
336 	|
337 	portal_group_discovery_filter
338 	|
339 	portal_group_listen
340 	|
341 	portal_group_listen_iser
342 	|
343 	portal_group_redirect
344 	;
345 
346 portal_group_discovery_auth_group:	DISCOVERY_AUTH_GROUP STR
347 	{
348 		if (portal_group->pg_discovery_auth_group != NULL) {
349 			log_warnx("discovery-auth-group for portal-group "
350 			    "\"%s\" specified more than once",
351 			    portal_group->pg_name);
352 			return (1);
353 		}
354 		portal_group->pg_discovery_auth_group =
355 		    auth_group_find(conf, $2);
356 		if (portal_group->pg_discovery_auth_group == NULL) {
357 			log_warnx("unknown discovery-auth-group \"%s\" "
358 			    "for portal-group \"%s\"",
359 			    $2, portal_group->pg_name);
360 			return (1);
361 		}
362 		free($2);
363 	}
364 	;
365 
366 portal_group_discovery_filter:	DISCOVERY_FILTER STR
367 	{
368 		int error;
369 
370 		error = portal_group_set_filter(portal_group, $2);
371 		free($2);
372 		if (error != 0)
373 			return (1);
374 	}
375 	;
376 
377 portal_group_listen:	LISTEN STR
378 	{
379 		int error;
380 
381 		error = portal_group_add_listen(portal_group, $2, false);
382 		free($2);
383 		if (error != 0)
384 			return (1);
385 	}
386 	;
387 
388 portal_group_listen_iser:	LISTEN_ISER STR
389 	{
390 		int error;
391 
392 		error = portal_group_add_listen(portal_group, $2, true);
393 		free($2);
394 		if (error != 0)
395 			return (1);
396 	}
397 	;
398 
399 portal_group_redirect:	REDIRECT STR
400 	{
401 		int error;
402 
403 		error = portal_group_set_redirection(portal_group, $2);
404 		free($2);
405 		if (error != 0)
406 			return (1);
407 	}
408 	;
409 
410 target:	TARGET target_name
411     OPENING_BRACKET target_entries CLOSING_BRACKET
412 	{
413 		target = NULL;
414 	}
415 	;
416 
417 target_name:	STR
418 	{
419 		target = target_new(conf, $1);
420 		free($1);
421 		if (target == NULL)
422 			return (1);
423 	}
424 	;
425 
426 target_entries:
427 	|
428 	target_entries target_entry
429 	|
430 	target_entries target_entry SEMICOLON
431 	;
432 
433 target_entry:
434 	target_alias
435 	|
436 	target_auth_group
437 	|
438 	target_auth_type
439 	|
440 	target_chap
441 	|
442 	target_chap_mutual
443 	|
444 	target_initiator_name
445 	|
446 	target_initiator_portal
447 	|
448 	target_portal_group
449 	|
450 	target_redirect
451 	|
452 	target_lun
453 	;
454 
455 target_alias:	ALIAS STR
456 	{
457 		if (target->t_alias != NULL) {
458 			log_warnx("alias for target \"%s\" "
459 			    "specified more than once", target->t_name);
460 			return (1);
461 		}
462 		target->t_alias = $2;
463 	}
464 	;
465 
466 target_auth_group:	AUTH_GROUP STR
467 	{
468 		if (target->t_auth_group != NULL) {
469 			if (target->t_auth_group->ag_name != NULL)
470 				log_warnx("auth-group for target \"%s\" "
471 				    "specified more than once", target->t_name);
472 			else
473 				log_warnx("cannot use both auth-group and explicit "
474 				    "authorisations for target \"%s\"",
475 				    target->t_name);
476 			return (1);
477 		}
478 		target->t_auth_group = auth_group_find(conf, $2);
479 		if (target->t_auth_group == NULL) {
480 			log_warnx("unknown auth-group \"%s\" for target "
481 			    "\"%s\"", $2, target->t_name);
482 			return (1);
483 		}
484 		free($2);
485 	}
486 	;
487 
488 target_auth_type:	AUTH_TYPE STR
489 	{
490 		int error;
491 
492 		if (target->t_auth_group != NULL) {
493 			if (target->t_auth_group->ag_name != NULL) {
494 				log_warnx("cannot use both auth-group and "
495 				    "auth-type for target \"%s\"",
496 				    target->t_name);
497 				return (1);
498 			}
499 		} else {
500 			target->t_auth_group = auth_group_new(conf, NULL);
501 			if (target->t_auth_group == NULL) {
502 				free($2);
503 				return (1);
504 			}
505 			target->t_auth_group->ag_target = target;
506 		}
507 		error = auth_group_set_type(target->t_auth_group, $2);
508 		free($2);
509 		if (error != 0)
510 			return (1);
511 	}
512 	;
513 
514 target_chap:	CHAP STR STR
515 	{
516 		const struct auth *ca;
517 
518 		if (target->t_auth_group != NULL) {
519 			if (target->t_auth_group->ag_name != NULL) {
520 				log_warnx("cannot use both auth-group and "
521 				    "chap for target \"%s\"",
522 				    target->t_name);
523 				free($2);
524 				free($3);
525 				return (1);
526 			}
527 		} else {
528 			target->t_auth_group = auth_group_new(conf, NULL);
529 			if (target->t_auth_group == NULL) {
530 				free($2);
531 				free($3);
532 				return (1);
533 			}
534 			target->t_auth_group->ag_target = target;
535 		}
536 		ca = auth_new_chap(target->t_auth_group, $2, $3);
537 		free($2);
538 		free($3);
539 		if (ca == NULL)
540 			return (1);
541 	}
542 	;
543 
544 target_chap_mutual:	CHAP_MUTUAL STR STR STR STR
545 	{
546 		const struct auth *ca;
547 
548 		if (target->t_auth_group != NULL) {
549 			if (target->t_auth_group->ag_name != NULL) {
550 				log_warnx("cannot use both auth-group and "
551 				    "chap-mutual for target \"%s\"",
552 				    target->t_name);
553 				free($2);
554 				free($3);
555 				free($4);
556 				free($5);
557 				return (1);
558 			}
559 		} else {
560 			target->t_auth_group = auth_group_new(conf, NULL);
561 			if (target->t_auth_group == NULL) {
562 				free($2);
563 				free($3);
564 				free($4);
565 				free($5);
566 				return (1);
567 			}
568 			target->t_auth_group->ag_target = target;
569 		}
570 		ca = auth_new_chap_mutual(target->t_auth_group,
571 		    $2, $3, $4, $5);
572 		free($2);
573 		free($3);
574 		free($4);
575 		free($5);
576 		if (ca == NULL)
577 			return (1);
578 	}
579 	;
580 
581 target_initiator_name:	INITIATOR_NAME STR
582 	{
583 		const struct auth_name *an;
584 
585 		if (target->t_auth_group != NULL) {
586 			if (target->t_auth_group->ag_name != NULL) {
587 				log_warnx("cannot use both auth-group and "
588 				    "initiator-name for target \"%s\"",
589 				    target->t_name);
590 				free($2);
591 				return (1);
592 			}
593 		} else {
594 			target->t_auth_group = auth_group_new(conf, NULL);
595 			if (target->t_auth_group == NULL) {
596 				free($2);
597 				return (1);
598 			}
599 			target->t_auth_group->ag_target = target;
600 		}
601 		an = auth_name_new(target->t_auth_group, $2);
602 		free($2);
603 		if (an == NULL)
604 			return (1);
605 	}
606 	;
607 
608 target_initiator_portal:	INITIATOR_PORTAL STR
609 	{
610 		const struct auth_portal *ap;
611 
612 		if (target->t_auth_group != NULL) {
613 			if (target->t_auth_group->ag_name != NULL) {
614 				log_warnx("cannot use both auth-group and "
615 				    "initiator-portal for target \"%s\"",
616 				    target->t_name);
617 				free($2);
618 				return (1);
619 			}
620 		} else {
621 			target->t_auth_group = auth_group_new(conf, NULL);
622 			if (target->t_auth_group == NULL) {
623 				free($2);
624 				return (1);
625 			}
626 			target->t_auth_group->ag_target = target;
627 		}
628 		ap = auth_portal_new(target->t_auth_group, $2);
629 		free($2);
630 		if (ap == NULL)
631 			return (1);
632 	}
633 	;
634 
635 target_portal_group:	PORTAL_GROUP STR
636 	{
637 		if (target->t_portal_group != NULL) {
638 			log_warnx("portal-group for target \"%s\" "
639 			    "specified more than once", target->t_name);
640 			free($2);
641 			return (1);
642 		}
643 		target->t_portal_group = portal_group_find(conf, $2);
644 		if (target->t_portal_group == NULL) {
645 			log_warnx("unknown portal-group \"%s\" for target "
646 			    "\"%s\"", $2, target->t_name);
647 			free($2);
648 			return (1);
649 		}
650 		free($2);
651 	}
652 	;
653 
654 target_redirect:	REDIRECT STR
655 	{
656 		int error;
657 
658 		error = target_set_redirection(target, $2);
659 		free($2);
660 		if (error != 0)
661 			return (1);
662 	}
663 	;
664 
665 target_lun:	LUN lun_number
666     OPENING_BRACKET lun_entries CLOSING_BRACKET
667 	{
668 		lun = NULL;
669 	}
670 	;
671 
672 lun_number:	STR
673 	{
674 		uint64_t tmp;
675 
676 		if (expand_number($1, &tmp) != 0) {
677 			yyerror("invalid numeric value");
678 			free($1);
679 			return (1);
680 		}
681 
682 		lun = lun_new(target, tmp);
683 		if (lun == NULL)
684 			return (1);
685 	}
686 	;
687 
688 lun_entries:
689 	|
690 	lun_entries lun_entry
691 	|
692 	lun_entries lun_entry SEMICOLON
693 	;
694 
695 lun_entry:
696 	lun_backend
697 	|
698 	lun_blocksize
699 	|
700 	lun_device_id
701 	|
702 	lun_option
703 	|
704 	lun_path
705 	|
706 	lun_serial
707 	|
708 	lun_size
709 	;
710 
711 lun_backend:	BACKEND STR
712 	{
713 		if (lun->l_backend != NULL) {
714 			log_warnx("backend for lun %d, target \"%s\" "
715 			    "specified more than once",
716 			    lun->l_lun, target->t_name);
717 			free($2);
718 			return (1);
719 		}
720 		lun_set_backend(lun, $2);
721 		free($2);
722 	}
723 	;
724 
725 lun_blocksize:	BLOCKSIZE STR
726 	{
727 		uint64_t tmp;
728 
729 		if (expand_number($2, &tmp) != 0) {
730 			yyerror("invalid numeric value");
731 			free($2);
732 			return (1);
733 		}
734 
735 		if (lun->l_blocksize != 0) {
736 			log_warnx("blocksize for lun %d, target \"%s\" "
737 			    "specified more than once",
738 			    lun->l_lun, target->t_name);
739 			return (1);
740 		}
741 		lun_set_blocksize(lun, tmp);
742 	}
743 	;
744 
745 lun_device_id:	DEVICE_ID STR
746 	{
747 		if (lun->l_device_id != NULL) {
748 			log_warnx("device_id for lun %d, target \"%s\" "
749 			    "specified more than once",
750 			    lun->l_lun, target->t_name);
751 			free($2);
752 			return (1);
753 		}
754 		lun_set_device_id(lun, $2);
755 		free($2);
756 	}
757 	;
758 
759 lun_option:	OPTION STR STR
760 	{
761 		struct lun_option *clo;
762 
763 		clo = lun_option_new(lun, $2, $3);
764 		free($2);
765 		free($3);
766 		if (clo == NULL)
767 			return (1);
768 	}
769 	;
770 
771 lun_path:	PATH STR
772 	{
773 		if (lun->l_path != NULL) {
774 			log_warnx("path for lun %d, target \"%s\" "
775 			    "specified more than once",
776 			    lun->l_lun, target->t_name);
777 			free($2);
778 			return (1);
779 		}
780 		lun_set_path(lun, $2);
781 		free($2);
782 	}
783 	;
784 
785 lun_serial:	SERIAL STR
786 	{
787 		if (lun->l_serial != NULL) {
788 			log_warnx("serial for lun %d, target \"%s\" "
789 			    "specified more than once",
790 			    lun->l_lun, target->t_name);
791 			free($2);
792 			return (1);
793 		}
794 		lun_set_serial(lun, $2);
795 		free($2);
796 	}
797 	;
798 
799 lun_size:	SIZE STR
800 	{
801 		uint64_t tmp;
802 
803 		if (expand_number($2, &tmp) != 0) {
804 			yyerror("invalid numeric value");
805 			free($2);
806 			return (1);
807 		}
808 
809 		if (lun->l_size != 0) {
810 			log_warnx("size for lun %d, target \"%s\" "
811 			    "specified more than once",
812 			    lun->l_lun, target->t_name);
813 			return (1);
814 		}
815 		lun_set_size(lun, tmp);
816 	}
817 	;
818 %%
819 
820 void
821 yyerror(const char *str)
822 {
823 
824 	log_warnx("error in configuration file at line %d near '%s': %s",
825 	    lineno, yytext, str);
826 }
827 
828 static void
829 check_perms(const char *path)
830 {
831 	struct stat sb;
832 	int error;
833 
834 	error = stat(path, &sb);
835 	if (error != 0) {
836 		log_warn("stat");
837 		return;
838 	}
839 	if (sb.st_mode & S_IWOTH) {
840 		log_warnx("%s is world-writable", path);
841 	} else if (sb.st_mode & S_IROTH) {
842 		log_warnx("%s is world-readable", path);
843 	} else if (sb.st_mode & S_IXOTH) {
844 		/*
845 		 * Ok, this one doesn't matter, but still do it,
846 		 * just for consistency.
847 		 */
848 		log_warnx("%s is world-executable", path);
849 	}
850 
851 	/*
852 	 * XXX: Should we also check for owner != 0?
853 	 */
854 }
855 
856 struct conf *
857 conf_new_from_file(const char *path)
858 {
859 	struct auth_group *ag;
860 	struct portal_group *pg;
861 	int error;
862 
863 	log_debugx("obtaining configuration from %s", path);
864 
865 	conf = conf_new();
866 
867 	ag = auth_group_new(conf, "default");
868 	assert(ag != NULL);
869 
870 	ag = auth_group_new(conf, "no-authentication");
871 	assert(ag != NULL);
872 	ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
873 
874 	ag = auth_group_new(conf, "no-access");
875 	assert(ag != NULL);
876 	ag->ag_type = AG_TYPE_DENY;
877 
878 	pg = portal_group_new(conf, "default");
879 	assert(pg != NULL);
880 
881 	yyin = fopen(path, "r");
882 	if (yyin == NULL) {
883 		log_warn("unable to open configuration file %s", path);
884 		conf_delete(conf);
885 		return (NULL);
886 	}
887 	check_perms(path);
888 	lineno = 1;
889 	yyrestart(yyin);
890 	error = yyparse();
891 	auth_group = NULL;
892 	portal_group = NULL;
893 	target = NULL;
894 	lun = NULL;
895 	fclose(yyin);
896 	if (error != 0) {
897 		conf_delete(conf);
898 		return (NULL);
899 	}
900 
901 	if (conf->conf_default_ag_defined == false) {
902 		log_debugx("auth-group \"default\" not defined; "
903 		    "going with defaults");
904 		ag = auth_group_find(conf, "default");
905 		assert(ag != NULL);
906 		ag->ag_type = AG_TYPE_DENY;
907 	}
908 
909 	if (conf->conf_default_pg_defined == false) {
910 		log_debugx("portal-group \"default\" not defined; "
911 		    "going with defaults");
912 		pg = portal_group_find(conf, "default");
913 		assert(pg != NULL);
914 		portal_group_add_listen(pg, "0.0.0.0:3260", false);
915 		portal_group_add_listen(pg, "[::]:3260", false);
916 	}
917 
918 	conf->conf_kernel_port_on = true;
919 
920 	error = conf_verify(conf);
921 	if (error != 0) {
922 		conf_delete(conf);
923 		return (NULL);
924 	}
925 
926 	return (conf);
927 }
928