Annotation of embedaddon/strongswan/src/starter/confread.c, revision 1.1.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>