File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / starter / confread.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:43 2020 UTC (4 years, 4 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    1: /*
    2:  * Copyright (C) 2014 Tobias Brunner
    3:  * HSR Hochschule fuer Technik Rapperswil
    4:  *
    5:  * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
    6:  *
    7:  * This program is free software; you can redistribute it and/or modify it
    8:  * under the terms of the GNU General Public License as published by the
    9:  * Free Software Foundation; either version 2 of the License, or (at your
   10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
   11:  *
   12:  * This program is distributed in the hope that it will be useful, but
   13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   15:  * for more details.
   16:  */
   17: 
   18: #include <sys/types.h>
   19: #include <sys/stat.h>
   20: #include <unistd.h>
   21: #include <stddef.h>
   22: #include <stdlib.h>
   23: #include <string.h>
   24: #include <assert.h>
   25: #include <netdb.h>
   26: 
   27: #include <library.h>
   28: #include <utils/debug.h>
   29: 
   30: #include "keywords.h"
   31: #include "confread.h"
   32: #include "args.h"
   33: #include "files.h"
   34: #include "parser/conf_parser.h"
   35: 
   36: #define IKE_LIFETIME_DEFAULT         10800 /* 3 hours */
   37: #define IPSEC_LIFETIME_DEFAULT        3600 /* 1 hour */
   38: #define SA_REPLACEMENT_MARGIN_DEFAULT  540 /* 9 minutes */
   39: #define SA_REPLACEMENT_FUZZ_DEFAULT    100 /* 100% of margin */
   40: #define SA_REPLACEMENT_RETRIES_DEFAULT   3
   41: #define SA_REPLAY_WINDOW_DEFAULT        -1 /* use charon.replay_window */
   42: 
   43: static const char firewall_defaults[] = IPSEC_SCRIPT " _updown iptables";
   44: 
   45: /**
   46:  * Process deprecated keywords
   47:  */
   48: static bool is_deprecated(kw_token_t token, char *name, char *conn)
   49: {
   50: 	switch (token)
   51: 	{
   52: 		case KW_SETUP_DEPRECATED:
   53: 		case KW_PKCS11_DEPRECATED:
   54: 			DBG1(DBG_APP, "# deprecated keyword '%s' in config setup", name);
   55: 			break;
   56: 		case KW_CONN_DEPRECATED:
   57: 		case KW_END_DEPRECATED:
   58: 		case KW_PFS_DEPRECATED:
   59: 			DBG1(DBG_APP, "# deprecated keyword '%s' in conn '%s'", name, conn);
   60: 			break;
   61: 		case KW_CA_DEPRECATED:
   62: 			DBG1(DBG_APP, "# deprecated keyword '%s' in ca '%s'", name, conn);
   63: 			break;
   64: 		default:
   65: 			return FALSE;
   66: 	}
   67: 	/* additional messages for some */
   68: 	switch (token)
   69: 	{
   70: 		case KW_PKCS11_DEPRECATED:
   71: 			DBG1(DBG_APP, "  use the 'pkcs11' plugin instead");
   72: 			break;
   73: 		case KW_PFS_DEPRECATED:
   74: 			DBG1(DBG_APP, "  PFS is enabled by specifying a DH group in the "
   75: 				 "'esp' cipher suite");
   76: 			break;
   77: 		default:
   78: 			break;
   79: 	}
   80: 	return TRUE;
   81: }
   82: 
   83: /*
   84:  * parse config setup section
   85:  */
   86: static void load_setup(starter_config_t *cfg, conf_parser_t *parser)
   87: {
   88: 	enumerator_t *enumerator;
   89: 	dictionary_t *dict;
   90: 	const kw_entry_t *entry;
   91: 	char *key, *value;
   92: 
   93: 	DBG2(DBG_APP, "Loading config setup");
   94: 	dict = parser->get_section(parser, CONF_PARSER_CONFIG_SETUP, NULL);
   95: 	if (!dict)
   96: 	{
   97: 		return;
   98: 	}
   99: 	enumerator = dict->create_enumerator(dict);
  100: 	while (enumerator->enumerate(enumerator, &key, &value))
  101: 	{
  102: 		bool assigned = FALSE;
  103: 
  104: 		entry = in_word_set(key, strlen(key));
  105: 		if (!entry)
  106: 		{
  107: 			DBG1(DBG_APP, "# unknown keyword '%s'", key);
  108: 			cfg->non_fatal_err++;
  109: 			continue;
  110: 		}
  111: 		if ((int)entry->token < KW_SETUP_FIRST || entry->token > KW_SETUP_LAST)
  112: 		{
  113: 			DBG1(DBG_APP, "# unsupported keyword '%s' in config setup", key);
  114: 			cfg->err++;
  115: 			continue;
  116: 		}
  117: 		if (is_deprecated(entry->token, key, ""))
  118: 		{
  119: 			cfg->non_fatal_err++;
  120: 			continue;
  121: 		}
  122: 		if (!assign_arg(entry->token, KW_SETUP_FIRST, key, value, cfg,
  123: 						&assigned))
  124: 		{
  125: 			DBG1(DBG_APP, "  bad argument value in config setup");
  126: 			cfg->err++;
  127: 		}
  128: 	}
  129: 	enumerator->destroy(enumerator);
  130: 	dict->destroy(dict);
  131: }
  132: 
  133: /*
  134:  * parse a ca section
  135:  */
  136: static void load_ca(starter_ca_t *ca, starter_config_t *cfg,
  137: 					conf_parser_t *parser)
  138: {
  139: 	enumerator_t *enumerator;
  140: 	dictionary_t *dict;
  141: 	const kw_entry_t *entry;
  142: 	kw_token_t token;
  143: 	char *key, *value;
  144: 
  145: 	DBG2(DBG_APP, "Loading ca '%s'", ca->name);
  146: 	dict = parser->get_section(parser, CONF_PARSER_CA, ca->name);
  147: 	if (!dict)
  148: 	{
  149: 		return;
  150: 	}
  151: 	enumerator = dict->create_enumerator(dict);
  152: 	while (enumerator->enumerate(enumerator, &key, &value))
  153: 	{
  154: 		bool assigned = FALSE;
  155: 
  156: 		entry = in_word_set(key, strlen(key));
  157: 		if (!entry)
  158: 		{
  159: 			DBG1(DBG_APP, "# unknown keyword '%s'", key);
  160: 			cfg->non_fatal_err++;
  161: 			continue;
  162: 		}
  163: 		token = entry->token;
  164: 		if (token == KW_AUTO)
  165: 		{
  166: 			token = KW_CA_SETUP;
  167: 		}
  168: 		if (token < KW_CA_FIRST || token > KW_CA_LAST)
  169: 		{
  170: 			DBG1(DBG_APP, "# unsupported keyword '%s' in ca '%s'",
  171: 				 key, ca->name);
  172: 			cfg->err++;
  173: 			continue;
  174: 		}
  175: 		if (is_deprecated(token, key, ca->name))
  176: 		{
  177: 			cfg->non_fatal_err++;
  178: 			continue;
  179: 		}
  180: 		if (!assign_arg(token, KW_CA_FIRST, key, value, ca, &assigned))
  181: 		{
  182: 			DBG1(DBG_APP, "  bad argument value in ca '%s'", ca->name);
  183: 			cfg->err++;
  184: 		}
  185: 	}
  186: 	enumerator->destroy(enumerator);
  187: 	dict->destroy(dict);
  188: 
  189: 	/* treat 'route' and 'start' as 'add' */
  190: 	if (ca->startup != STARTUP_NO)
  191: 	{
  192: 		ca->startup = STARTUP_ADD;
  193: 	}
  194: }
  195: 
  196: /*
  197:  * set some default values
  198:  */
  199: static void conn_defaults(starter_conn_t *conn)
  200: {
  201: 	conn->startup = STARTUP_NO;
  202: 	conn->state   = STATE_IGNORE;
  203: 	conn->mode    = MODE_TUNNEL;
  204: 	conn->options = SA_OPTION_MOBIKE;
  205: 
  206: 	/* esp defaults are set after parsing the conn section */
  207: 	conn->sa_ike_life_seconds   = IKE_LIFETIME_DEFAULT;
  208: 	conn->sa_ipsec_life_seconds = IPSEC_LIFETIME_DEFAULT;
  209: 	conn->sa_rekey_margin       = SA_REPLACEMENT_MARGIN_DEFAULT;
  210: 	conn->sa_rekey_fuzz         = SA_REPLACEMENT_FUZZ_DEFAULT;
  211: 	conn->sa_keying_tries       = SA_REPLACEMENT_RETRIES_DEFAULT;
  212: 	conn->install_policy        = TRUE;
  213: 	conn->dpd_delay             =  30; /* seconds */
  214: 	conn->dpd_timeout           = 150; /* seconds */
  215: 	conn->replay_window         = SA_REPLAY_WINDOW_DEFAULT;
  216: 	conn->fragmentation         = FRAGMENTATION_YES;
  217: 
  218: 	conn->left.sendcert = CERT_SEND_IF_ASKED;
  219: 	conn->right.sendcert = CERT_SEND_IF_ASKED;
  220: 
  221: 	conn->left.ikeport = 500;
  222: 	conn->right.ikeport = 500;
  223: 
  224: 	conn->left.to_port = 0xffff;
  225: 	conn->right.to_port = 0xffff;
  226: }
  227: 
  228: /*
  229:  * parse left|right specific options
  230:  */
  231: static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
  232: 				   char *key, char *value, starter_config_t *cfg)
  233: {
  234: 	bool assigned = FALSE;
  235: 
  236: 	if (is_deprecated(token, key, conn->name))
  237: 	{
  238: 		cfg->non_fatal_err++;
  239: 		return;
  240: 	}
  241: 
  242: 	if (!assign_arg(token, KW_END_FIRST, key, value, end, &assigned))
  243: 	{
  244: 		goto err;
  245: 	}
  246: 
  247: 	/* post processing of some keywords that were assigned automatically */
  248: 	switch (token)
  249: 	{
  250: 		case KW_HOST:
  251: 			if (value && strlen(value) > 0 && value[0] == '%')
  252: 			{
  253: 				if (streq(value, "%defaultroute"))
  254: 				{
  255: 					value = "%any";
  256: 				}
  257: 				if (!streq(value, "%any") && !streq(value, "%any4") &&
  258: 					!streq(value, "%any6"))
  259: 				{	/* allow_any prefix */
  260: 					end->allow_any = TRUE;
  261: 					value++;
  262: 				}
  263: 			}
  264: 			free(end->host);
  265: 			end->host = strdupnull(value);
  266: 			break;
  267: 		case KW_SOURCEIP:
  268: 			conn->mode = MODE_TUNNEL;
  269: 			conn->proxy_mode = FALSE;
  270: 			break;
  271: 		case KW_SENDCERT:
  272: 			if (end->sendcert == CERT_YES_SEND)
  273: 			{
  274: 				end->sendcert = CERT_ALWAYS_SEND;
  275: 			}
  276: 			else if (end->sendcert == CERT_NO_SEND)
  277: 			{
  278: 				end->sendcert = CERT_NEVER_SEND;
  279: 			}
  280: 			break;
  281: 		default:
  282: 			break;
  283: 	}
  284: 
  285: 	if (assigned)
  286: 	{
  287: 		return;
  288: 	}
  289: 
  290: 	/* individual processing of keywords that were not assigned automatically */
  291: 	switch (token)
  292: 	{
  293: 		case KW_PROTOPORT:
  294: 		{
  295: 			struct protoent *proto;
  296: 			struct servent *svc;
  297: 			char *sep, *port = "", *endptr;
  298: 			long int p;
  299: 
  300: 			sep = strchr(value, '/');
  301: 			if (sep)
  302: 			{	/* protocol/port */
  303: 				*sep = '\0';
  304: 				port = sep + 1;
  305: 			}
  306: 
  307: 			if (streq(value, "%any"))
  308: 			{
  309: 				end->protocol = 0;
  310: 			}
  311: 			else
  312: 			{
  313: 				proto = getprotobyname(value);
  314: 				if (proto)
  315: 				{
  316: 					end->protocol = proto->p_proto;
  317: 				}
  318: 				else
  319: 				{
  320: 					p = strtol(value, &endptr, 0);
  321: 					if ((*value && *endptr) || p < 0 || p > 0xff)
  322: 					{
  323: 						DBG1(DBG_APP, "# bad protocol: %s=%s", key, value);
  324: 						goto err;
  325: 					}
  326: 					end->protocol = (uint8_t)p;
  327: 				}
  328: 			}
  329: 			if (streq(port, "%any"))
  330: 			{
  331: 				end->from_port = 0;
  332: 				end->to_port = 0xffff;
  333: 			}
  334: 			else if (streq(port, "%opaque"))
  335: 			{
  336: 				end->from_port = 0xffff;
  337: 				end->to_port = 0;
  338: 			}
  339: 			else if (*port)
  340: 			{
  341: 				svc = getservbyname(port, NULL);
  342: 				if (svc)
  343: 				{
  344: 					end->from_port = end->to_port = ntohs(svc->s_port);
  345: 				}
  346: 				else
  347: 				{
  348: 					p = strtol(port, &endptr, 0);
  349: 					if (p < 0 || p > 0xffff)
  350: 					{
  351: 						DBG1(DBG_APP, "# bad port: %s=%s", key, port);
  352: 						goto err;
  353: 					}
  354: 					end->from_port = p;
  355: 					if (*endptr == '-')
  356: 					{
  357: 						port = endptr + 1;
  358: 						p = strtol(port, &endptr, 0);
  359: 						if (p < 0 || p > 0xffff)
  360: 						{
  361: 							DBG1(DBG_APP, "# bad port: %s=%s", key, port);
  362: 							goto err;
  363: 						}
  364: 					}
  365: 					end->to_port = p;
  366: 					if (*endptr)
  367: 					{
  368: 						DBG1(DBG_APP, "# bad port: %s=%s", key, port);
  369: 						goto err;
  370: 					}
  371: 				}
  372: 			}
  373: 			if (sep)
  374: 			{	/* restore the original text in case also= is used */
  375: 				*sep = '/';
  376: 			}
  377: 			break;
  378: 		}
  379: 		default:
  380: 			break;
  381: 	}
  382: 	return;
  383: 
  384: err:
  385: 	DBG1(DBG_APP, "  bad argument value in conn '%s'", conn->name);
  386: 	cfg->err++;
  387: }
  388: 
  389: /*
  390:  * macro to handle simple flags
  391:  */
  392: #define KW_SA_OPTION_FLAG(sy, sn, fl) \
  393: 		if (streq(value, sy)) { conn->options |= fl; } \
  394: 		else if (streq(value, sn)) { conn->options &= ~fl; } \
  395: 		else { DBG1(DBG_APP, "# bad option value: %s=%s", key, value); cfg->err++; }
  396: 
  397: /*
  398:  * parse settings not handled by the simple argument parser
  399:  */
  400: static void handle_keyword(kw_token_t token, starter_conn_t *conn, char *key,
  401: 						   char *value, starter_config_t *cfg)
  402: {
  403: 	if ((token == KW_ESP && conn->ah) || (token == KW_AH && conn->esp))
  404: 	{
  405: 		DBG1(DBG_APP, "# can't have both 'ah' and 'esp' options");
  406: 		cfg->err++;
  407: 		return;
  408: 	}
  409: 	switch (token)
  410: 	{
  411: 		case KW_TYPE:
  412: 		{
  413: 			conn->mode = MODE_TRANSPORT;
  414: 			conn->proxy_mode = FALSE;
  415: 			if (streq(value, "tunnel"))
  416: 			{
  417: 				conn->mode = MODE_TUNNEL;
  418: 			}
  419: 			else if (streq(value, "beet"))
  420: 			{
  421: 				conn->mode = MODE_BEET;
  422: 			}
  423: 			else if (streq(value, "transport_proxy"))
  424: 			{
  425: 				conn->mode = MODE_TRANSPORT;
  426: 				conn->proxy_mode = TRUE;
  427: 			}
  428: 			else if (streq(value, "passthrough") || streq(value, "pass"))
  429: 			{
  430: 				conn->mode = MODE_PASS;
  431: 			}
  432: 			else if (streq(value, "drop") || streq(value, "reject"))
  433: 			{
  434: 				conn->mode = MODE_DROP;
  435: 			}
  436: 			else if (!streq(value, "transport"))
  437: 			{
  438: 				DBG1(DBG_APP, "# bad policy value: %s=%s", key, value);
  439: 				cfg->err++;
  440: 			}
  441: 			break;
  442: 		}
  443: 		case KW_COMPRESS:
  444: 			KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_COMPRESS)
  445: 			break;
  446: 		case KW_MARK:
  447: 			if (!mark_from_string(value, MARK_OP_UNIQUE, &conn->mark_in))
  448: 			{
  449: 				cfg->err++;
  450: 				break;
  451: 			}
  452: 			conn->mark_out = conn->mark_in;
  453: 			break;
  454: 		case KW_MARK_IN:
  455: 			if (!mark_from_string(value, MARK_OP_UNIQUE, &conn->mark_in))
  456: 			{
  457: 				cfg->err++;
  458: 			}
  459: 			break;
  460: 		case KW_MARK_OUT:
  461: 			if (!mark_from_string(value, MARK_OP_UNIQUE, &conn->mark_out))
  462: 			{
  463: 				cfg->err++;
  464: 			}
  465: 			break;
  466: 		case KW_TFC:
  467: 			if (streq(value, "%mtu"))
  468: 			{
  469: 				conn->tfc = -1;
  470: 			}
  471: 			else
  472: 			{
  473: 				char *endptr;
  474: 
  475: 				conn->tfc = strtoul(value, &endptr, 10);
  476: 				if (*endptr != '\0')
  477: 				{
  478: 					DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
  479: 					cfg->err++;
  480: 				}
  481: 			}
  482: 			break;
  483: 		case KW_KEYINGTRIES:
  484: 			if (streq(value, "%forever"))
  485: 			{
  486: 				conn->sa_keying_tries = 0;
  487: 			}
  488: 			else
  489: 			{
  490: 				char *endptr;
  491: 
  492: 				conn->sa_keying_tries = strtoul(value, &endptr, 10);
  493: 				if (*endptr != '\0')
  494: 				{
  495: 					DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
  496: 					cfg->err++;
  497: 				}
  498: 			}
  499: 			break;
  500: 		case KW_REKEY:
  501: 			KW_SA_OPTION_FLAG("no", "yes", SA_OPTION_DONT_REKEY)
  502: 			break;
  503: 		case KW_REAUTH:
  504: 			KW_SA_OPTION_FLAG("no", "yes", SA_OPTION_DONT_REAUTH)
  505: 			break;
  506: 		case KW_MOBIKE:
  507: 			KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_MOBIKE)
  508: 			break;
  509: 		case KW_FORCEENCAPS:
  510: 			KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_FORCE_ENCAP)
  511: 			break;
  512: 		case KW_MODECONFIG:
  513: 			KW_SA_OPTION_FLAG("push", "pull", SA_OPTION_MODECFG_PUSH)
  514: 			break;
  515: 		case KW_XAUTH:
  516: 			KW_SA_OPTION_FLAG("server", "client", SA_OPTION_XAUTH_SERVER)
  517: 			break;
  518: 		default:
  519: 			break;
  520: 	}
  521: }
  522: 
  523: /*
  524:  * handles left|rightfirewall and left|rightupdown parameters
  525:  */
  526: static void handle_firewall(const char *label, starter_end_t *end,
  527: 							starter_config_t *cfg)
  528: {
  529: 	if (end->firewall)
  530: 	{
  531: 		if (end->updown != NULL)
  532: 		{
  533: 			DBG1(DBG_APP, "# cannot have both %sfirewall and %supdown", label,
  534: 				 label);
  535: 			cfg->err++;
  536: 		}
  537: 		else
  538: 		{
  539: 			end->updown = strdupnull(firewall_defaults);
  540: 			end->firewall = FALSE;
  541: 		}
  542: 	}
  543: }
  544: 
  545: /*
  546:  * parse a conn section
  547:  */
  548: static void load_conn(starter_conn_t *conn, starter_config_t *cfg,
  549: 					  conf_parser_t *parser)
  550: {
  551: 	enumerator_t *enumerator;
  552: 	dictionary_t *dict;
  553: 	const kw_entry_t *entry;
  554: 	kw_token_t token;
  555: 	char *key, *value;
  556: 
  557: 	DBG2(DBG_APP, "Loading conn '%s'", conn->name);
  558: 	dict = parser->get_section(parser, CONF_PARSER_CONN, conn->name);
  559: 	if (!dict)
  560: 	{
  561: 		return;
  562: 	}
  563: 	enumerator = dict->create_enumerator(dict);
  564: 	while (enumerator->enumerate(enumerator, &key, &value))
  565: 	{
  566: 		bool assigned = FALSE;
  567: 
  568: 		entry = in_word_set(key, strlen(key));
  569: 		if (!entry)
  570: 		{
  571: 			DBG1(DBG_APP, "# unknown keyword '%s'", key);
  572: 			cfg->non_fatal_err++;
  573: 			continue;
  574: 		}
  575: 		token = entry->token;
  576: 		if (token >= KW_LEFT_FIRST && token <= KW_LEFT_LAST)
  577: 		{
  578: 			kw_end(conn, &conn->left, token - KW_LEFT_FIRST + KW_END_FIRST,
  579: 				   key, value, cfg);
  580: 			continue;
  581: 		}
  582: 		else if (token >= KW_RIGHT_FIRST && token <= KW_RIGHT_LAST)
  583: 		{
  584: 			kw_end(conn, &conn->right, token - KW_RIGHT_FIRST + KW_END_FIRST,
  585: 				   key, value, cfg);
  586: 			continue;
  587: 		}
  588: 		if (token == KW_AUTO)
  589: 		{
  590: 			token = KW_CONN_SETUP;
  591: 		}
  592: 		if (token < KW_CONN_FIRST || token > KW_CONN_LAST)
  593: 		{
  594: 			DBG1(DBG_APP, "# unsupported keyword '%s' in conn '%s'",
  595: 				 key, conn->name);
  596: 			cfg->err++;
  597: 			continue;
  598: 		}
  599: 		if (is_deprecated(token, key, conn->name))
  600: 		{
  601: 			cfg->non_fatal_err++;
  602: 			continue;
  603: 		}
  604: 		if (!assign_arg(token, KW_CONN_FIRST, key, value, conn,
  605: 						&assigned))
  606: 		{
  607: 			DBG1(DBG_APP, "  bad argument value in conn '%s'", conn->name);
  608: 			cfg->err++;
  609: 			continue;
  610: 		}
  611: 		if (!assigned)
  612: 		{
  613: 			handle_keyword(token, conn, key, value, cfg);
  614: 		}
  615: 	}
  616: 	enumerator->destroy(enumerator);
  617: 	dict->destroy(dict);
  618: 
  619: 	handle_firewall("left", &conn->left, cfg);
  620: 	handle_firewall("right", &conn->right, cfg);
  621: }
  622: 
  623: /*
  624:  * free the memory used by a starter_ca_t object
  625:  */
  626: static void confread_free_ca(starter_ca_t *ca)
  627: {
  628: 	free_args(KW_CA_NAME, KW_CA_LAST, (char *)ca);
  629: 	free(ca);
  630: }
  631: 
  632: /*
  633:  * free the memory used by a starter_conn_t object
  634:  */
  635: static void confread_free_conn(starter_conn_t *conn)
  636: {
  637: 	free_args(KW_END_FIRST, KW_END_LAST,  (char *)&conn->left);
  638: 	free_args(KW_END_FIRST, KW_END_LAST,  (char *)&conn->right);
  639: 	free_args(KW_CONN_NAME, KW_CONN_LAST, (char *)conn);
  640: 	free(conn);
  641: }
  642: 
  643: /*
  644:  * free the memory used by a starter_config_t object
  645:  */
  646: void confread_free(starter_config_t *cfg)
  647: {
  648: 	starter_conn_t *conn = cfg->conn_first;
  649: 	starter_ca_t   *ca   = cfg->ca_first;
  650: 
  651: 	free_args(KW_SETUP_FIRST, KW_SETUP_LAST, (char *)cfg);
  652: 
  653: 	while (conn != NULL)
  654: 	{
  655: 		starter_conn_t *conn_aux = conn;
  656: 
  657: 		conn = conn->next;
  658: 		confread_free_conn(conn_aux);
  659: 	}
  660: 
  661: 	while (ca != NULL)
  662: 	{
  663: 		starter_ca_t *ca_aux = ca;
  664: 
  665: 		ca = ca->next;
  666: 		confread_free_ca(ca_aux);
  667: 	}
  668: 
  669: 	free(cfg);
  670: }
  671: 
  672: /*
  673:  * load and parse an IPsec configuration file
  674:  */
  675: starter_config_t* confread_load(const char *file)
  676: {
  677: 	conf_parser_t *parser;
  678: 	starter_config_t *cfg = NULL;
  679: 	enumerator_t *enumerator;
  680: 	u_int total_err;
  681: 	char *name;
  682: 
  683: 	parser = conf_parser_create(file);
  684: 	if (!parser->parse(parser))
  685: 	{
  686: 		parser->destroy(parser);
  687: 		return NULL;
  688: 	}
  689: 
  690: 	INIT(cfg,
  691: 		.setup = {
  692: 			.uniqueids = TRUE,
  693: 		}
  694: 	);
  695: 
  696: 	/* load config setup section */
  697: 	load_setup(cfg, parser);
  698: 
  699: 	/* load ca sections */
  700: 	enumerator = parser->get_sections(parser, CONF_PARSER_CA);
  701: 	while (enumerator->enumerate(enumerator, &name))
  702: 	{
  703: 		u_int previous_err = cfg->err;
  704: 		starter_ca_t *ca;
  705: 
  706: 		INIT(ca,
  707: 			.name = strdup(name),
  708: 		);
  709: 		load_ca(ca, cfg, parser);
  710: 
  711: 		if (cfg->err > previous_err)
  712: 		{
  713: 			total_err = cfg->err - previous_err;
  714: 			DBG1(DBG_APP, "# ignored ca '%s' due to %d parsing error%s", name,
  715: 				 total_err, (total_err > 1) ? "s" : "");
  716: 			confread_free_ca(ca);
  717: 			cfg->non_fatal_err += cfg->err - previous_err;
  718: 			cfg->err = previous_err;
  719: 		}
  720: 		else
  721: 		{
  722: 			if (cfg->ca_last)
  723: 			{
  724: 				cfg->ca_last->next = ca;
  725: 			}
  726: 			cfg->ca_last = ca;
  727: 			if (!cfg->ca_first)
  728: 			{
  729: 				cfg->ca_first = ca;
  730: 			}
  731: 			if (ca->startup != STARTUP_NO)
  732: 			{
  733: 				ca->state = STATE_TO_ADD;
  734: 			}
  735: 		}
  736: 	}
  737: 	enumerator->destroy(enumerator);
  738: 
  739: 	/* load conn sections */
  740: 	enumerator = parser->get_sections(parser, CONF_PARSER_CONN);
  741: 	while (enumerator->enumerate(enumerator, &name))
  742: 	{
  743: 		u_int previous_err = cfg->err;
  744: 		starter_conn_t *conn;
  745: 
  746: 		INIT(conn,
  747: 			.name = strdup(name),
  748: 		);
  749: 		conn_defaults(conn);
  750: 		load_conn(conn, cfg, parser);
  751: 
  752: 		if (cfg->err > previous_err)
  753: 		{
  754: 			total_err = cfg->err - previous_err;
  755: 			DBG1(DBG_APP, "# ignored conn '%s' due to %d parsing error%s", name,
  756: 				 total_err, (total_err > 1) ? "s" : "");
  757: 			confread_free_conn(conn);
  758: 			cfg->non_fatal_err += cfg->err - previous_err;
  759: 			cfg->err = previous_err;
  760: 		}
  761: 		else
  762: 		{
  763: 			if (cfg->conn_last)
  764: 			{
  765: 				cfg->conn_last->next = conn;
  766: 			}
  767: 			cfg->conn_last = conn;
  768: 			if (!cfg->conn_first)
  769: 			{
  770: 				cfg->conn_first = conn;
  771: 			}
  772: 			if (conn->startup != STARTUP_NO)
  773: 			{
  774: 				conn->state = STATE_TO_ADD;
  775: 			}
  776: 		}
  777: 	}
  778: 	enumerator->destroy(enumerator);
  779: 
  780: 	parser->destroy(parser);
  781: 
  782: 	total_err = cfg->err + cfg->non_fatal_err;
  783: 	if (total_err > 0)
  784: 	{
  785: 		DBG1(DBG_APP, "### %d parsing error%s (%d fatal) ###",
  786: 			 total_err, (total_err > 1)?"s":"", cfg->err);
  787: 	}
  788: 	return cfg;
  789: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>