Annotation of embedaddon/strongswan/src/starter/confread.c, revision 1.1

1.1     ! misho       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>