| File: | lib/libipsecconf/confread.c |
| Warning: | line 1080, column 10 Null pointer passed as an argument to a 'nonnull' parameter |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* Libreswan config file parser (confread.c) | |||
| 2 | * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security | |||
| 3 | * Copyright (C) 2004 Xelerance Corporation | |||
| 4 | * Copyright (C) 2006-2008 Michael Richardson <mcr@xelerance.com> | |||
| 5 | * Copyright (C) 2007 Ken Bantoft <ken@xelerance.com> | |||
| 6 | * Copyright (C) 2006-2012 Paul Wouters <paul@xelerance.com> | |||
| 7 | * Copyright (C) 2010 Michael Smith <msmith@cbnco.com> | |||
| 8 | * Copyright (C) 2010 Tuomo Soini <tis@foobar.fi> | |||
| 9 | * Copyright (C) 2012-2019 Paul Wouters <pwouters@redhat.com> | |||
| 10 | * Copyright (C) 2012 Avesh Agarwal <avagarwa@redhat.com> | |||
| 11 | * Copyright (C) 2012 Antony Antony <antony@phenome.org> | |||
| 12 | * Copyright (C) 2013 Florian Weimer <fweimer@redhat.com> | |||
| 13 | * Copyright (C) 2013 David McCullough <ucdevel@gmail.com> | |||
| 14 | * Copyright (C) 2013-2019 D. Hugh Redelmeier <hugh@mimosa.com> | |||
| 15 | * Copyright (C) 2016 Andrew Cagney <cagney@gnu.org> | |||
| 16 | * Copyright (C) 2017-2018 Vukasin Karadzic <vukasin.karadzic@gmail.com> | |||
| 17 | * Copyright (C) 2017 Mayank Totale <mtotale@gmail.com> | |||
| 18 | * | |||
| 19 | * This program is free software; you can redistribute it and/or modify it | |||
| 20 | * under the terms of the GNU General Public License as published by the | |||
| 21 | * Free Software Foundation; either version 2 of the License, or (at your | |||
| 22 | * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>. | |||
| 23 | * | |||
| 24 | * This program is distributed in the hope that it will be useful, but | |||
| 25 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |||
| 26 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
| 27 | * for more details. | |||
| 28 | */ | |||
| 29 | ||||
| 30 | #include <stdlib.h> | |||
| 31 | #include <stdarg.h> | |||
| 32 | #include <stdio.h> | |||
| 33 | #include <string.h> | |||
| 34 | #include <assert.h> | |||
| 35 | #include <ctype.h> | |||
| 36 | ||||
| 37 | #include "lswalloc.h" | |||
| 38 | #include "ip_address.h" | |||
| 39 | #include "ip_info.h" | |||
| 40 | ||||
| 41 | #include "ipsecconf/confread.h" | |||
| 42 | #include "ipsecconf/starterlog.h" | |||
| 43 | #include "ipsecconf/interfaces.h" | |||
| 44 | ||||
| 45 | #include "ipsecconf/keywords.h" | |||
| 46 | #include "ipsecconf/parser.h" /* includes parser.tab.h generated by bison; requires keywords.h */ | |||
| 47 | ||||
| 48 | #include "whack.h" /* for DEFAULT_CTL_SOCKET */ | |||
| 49 | #include "lswlog.h" | |||
| 50 | #ifdef USE_DNSSEC1 | |||
| 51 | # include <unbound.h> | |||
| 52 | # include <arpa/inet.h> /* for inet_ntop */ | |||
| 53 | # include "dnssec.h" | |||
| 54 | #endif /* USE_DNSSEC */ | |||
| 55 | ||||
| 56 | /** | |||
| 57 | * Set up hardcoded defaults, from data in programs/pluto/constants.h | |||
| 58 | * | |||
| 59 | * @param cfg starter_config struct | |||
| 60 | * @return void | |||
| 61 | */ | |||
| 62 | static void ipsecconf_default_values(struct starter_config *cfg) | |||
| 63 | { | |||
| 64 | static const struct starter_config empty_starter_config; /* zero or null everywhere */ | |||
| 65 | *cfg = empty_starter_config; | |||
| 66 | ||||
| 67 | TAILQ_INIT(&cfg->conns)do { (&cfg->conns)->tqh_first = ((void*)0); (&cfg ->conns)->tqh_last = &(&cfg->conns)->tqh_first ; } while ( 0); | |||
| 68 | ||||
| 69 | /* ==== config setup ==== */ | |||
| 70 | ||||
| 71 | # define SOPT(kbf, v) { cfg->setup.options[kbf] = (v) ; } | |||
| 72 | ||||
| 73 | SOPT(KBF_LOGTIME, TRUE1); | |||
| 74 | SOPT(KBF_LOGAPPEND, TRUE1); | |||
| 75 | SOPT(KBF_LOGIP, TRUE1); | |||
| 76 | SOPT(KBF_AUDIT_LOG, TRUE1); | |||
| 77 | SOPT(KBF_UNIQUEIDS, TRUE1); | |||
| 78 | SOPT(KBF_LISTEN_UDP, TRUE1); | |||
| 79 | SOPT(KBF_LISTEN_TCP, FALSE0); | |||
| 80 | SOPT(KBF_DO_DNSSEC, TRUE1); | |||
| 81 | SOPT(KBF_PERPEERLOG, FALSE0); | |||
| 82 | SOPT(KBF_IKEBUF, IKE_BUF_AUTO0); | |||
| 83 | SOPT(KBF_IKE_ERRQUEUE, TRUE1); | |||
| 84 | SOPT(KBF_NFLOG_ALL, 0); /* disabled per default */ | |||
| 85 | SOPT(KBF_XFRMLIFETIME, XFRM_LIFETIME_DEFAULT30); /* not used by pluto itself */ | |||
| 86 | SOPT(KBF_NHELPERS, -1); /* see also plutomain.c */ | |||
| 87 | ||||
| 88 | SOPT(KBF_KEEPALIVE, 0); /* config setup */ | |||
| 89 | SOPT(KBF_DDOS_IKE_THRESHOLD, DEFAULT_IKE_SA_DDOS_THRESHOLD25000); | |||
| 90 | SOPT(KBF_MAX_HALFOPEN_IKE, DEFAULT_MAXIMUM_HALFOPEN_IKE_SA50000); | |||
| 91 | SOPT(KBF_SHUNTLIFETIME, PLUTO_SHUNT_LIFE_DURATION_DEFAULT(15 * secs_per_minute)); | |||
| 92 | /* Don't inflict BSI requirements on everyone */ | |||
| 93 | SOPT(KBF_SEEDBITS, 0); | |||
| 94 | SOPT(KBF_DROP_OPPO_NULL, FALSE0); | |||
| 95 | ||||
| 96 | #ifdef HAVE_LABELED_IPSEC1 | |||
| 97 | SOPT(KBF_SECCTX, SECCTX); | |||
| 98 | #endif | |||
| 99 | SOPT(KBF_DDOS_MODE, DDOS_AUTO); | |||
| 100 | ||||
| 101 | SOPT(KBF_OCSP_CACHE_SIZE, OCSP_DEFAULT_CACHE_SIZE1000); | |||
| 102 | SOPT(KBF_OCSP_CACHE_MIN, OCSP_DEFAULT_CACHE_MIN_AGE3600); | |||
| 103 | SOPT(KBF_OCSP_CACHE_MAX, OCSP_DEFAULT_CACHE_MAX_AGE24 * 3600); | |||
| 104 | SOPT(KBF_OCSP_METHOD, OCSP_METHOD_GET); | |||
| 105 | SOPT(KBF_OCSP_TIMEOUT, OCSP_DEFAULT_TIMEOUT2); | |||
| 106 | ||||
| 107 | SOPT(KBF_SECCOMP, SECCOMP_DISABLED); /* will be enabled in the future */ | |||
| 108 | ||||
| 109 | # undef SOPT | |||
| 110 | ||||
| 111 | cfg->setup.strings[KSF_PLUTO_DNSSEC_ROOTKEY_FILE] = clone_str(DEFAULT_DNSSEC_ROOTKEY_FILE, "dnssec rootkey file")(("/var/lib/unbound/root.key") == ((void*)0) ? ((void*)0) : clone_bytes (("/var/lib/unbound/root.key"), strlen(("/var/lib/unbound/root.key" )) + 1, ("dnssec rootkey file"))); | |||
| 112 | ||||
| 113 | /* ==== end of config setup ==== */ | |||
| 114 | ||||
| 115 | cfg->ctlsocket = clone_str(DEFAULT_CTL_SOCKET, "default control socket")(("/run/pluto" "/pluto.ctl") == ((void*)0) ? ((void*)0) : clone_bytes (("/run/pluto" "/pluto.ctl"), strlen(("/run/pluto" "/pluto.ctl" )) + 1, ("default control socket"))); | |||
| 116 | ||||
| 117 | /* ==== conn %default ==== */ | |||
| 118 | ||||
| 119 | struct starter_conn *d = &cfg->conn_default; | |||
| 120 | ||||
| 121 | # define DOPT(kbf, v) { d->options[kbf] = (v); } | |||
| 122 | ||||
| 123 | DOPT(KNCF_NAT_KEEPALIVE, TRUE1); /* per conn */ | |||
| 124 | DOPT(KNCF_TYPE, KS_TUNNEL); | |||
| 125 | ||||
| 126 | DOPT(KNCF_INITIAL_CONTACT, FALSE0); | |||
| 127 | DOPT(KNCF_CISCO_UNITY, FALSE0); | |||
| 128 | DOPT(KNCF_NO_ESP_TFC, FALSE0); | |||
| 129 | DOPT(KNCF_VID_STRONGSWAN, FALSE0); | |||
| 130 | DOPT(KNCF_SEND_VENDORID, FALSE0); | |||
| 131 | ||||
| 132 | DOPT(KNCF_REMOTEPEERTYPE, NON_CISCO); | |||
| 133 | ||||
| 134 | DOPT(KNCF_IKEPAD, TRUE1); | |||
| 135 | ||||
| 136 | DOPT(KNCF_IKEV1_NATT, NATT_BOTH); | |||
| 137 | DOPT(KNCF_ENCAPS, yna_auto); | |||
| 138 | ||||
| 139 | DOPT(KNCF_TCP, IKE_TCP_NO); | |||
| 140 | DOPT(KNCF_REMOTE_TCPPORT, NAT_IKE_UDP_PORT4500); | |||
| 141 | ||||
| 142 | /* Network Manager support */ | |||
| 143 | #ifdef HAVE_NM1 | |||
| 144 | DOPT(KNCF_NMCONFIGURED, FALSE0); | |||
| 145 | #endif | |||
| 146 | ||||
| 147 | DOPT(KNCF_XAUTHBY, XAUTHBY_FILE); | |||
| 148 | DOPT(KNCF_XAUTHFAIL, XAUTHFAIL_HARD); | |||
| 149 | ||||
| 150 | DOPT(KNCF_NIC_OFFLOAD, yna_auto); | |||
| 151 | DOPT(KNCF_IKELIFETIME, IKE_SA_LIFETIME_DEFAULTsecs_per_hour); | |||
| 152 | ||||
| 153 | DOPT(KNCF_REPLAY_WINDOW, IPSEC_SA_DEFAULT_REPLAY_WINDOW32); | |||
| 154 | ||||
| 155 | DOPT(KNCF_RETRANSMIT_TIMEOUT, RETRANSMIT_TIMEOUT_DEFAULT60); | |||
| 156 | DOPT(KNCF_RETRANSMIT_INTERVAL_MS, RETRANSMIT_INTERVAL_DEFAULT_MS500); | |||
| 157 | ||||
| 158 | DOPT(KNCF_SALIFETIME, IPSEC_SA_LIFETIME_DEFAULTsecs_per_hour * 8); | |||
| 159 | DOPT(KNCF_REKEYMARGIN, SA_REPLACEMENT_MARGIN_DEFAULT(9 * secs_per_minute)); | |||
| 160 | DOPT(KNCF_REKEYFUZZ, SA_REPLACEMENT_FUZZ_DEFAULT100); | |||
| 161 | ||||
| 162 | DOPT(KNCF_KEYINGTRIES, SA_REPLACEMENT_RETRIES_DEFAULT0); | |||
| 163 | ||||
| 164 | DOPT(KNCF_HOSTADDRFAMILY, AF_UNSPEC0); | |||
| 165 | DOPT(KNCF_CLIENTADDRFAMILY, AF_UNSPEC0); | |||
| 166 | ||||
| 167 | DOPT(KNCF_AUTO, STARTUP_IGNORE); | |||
| 168 | DOPT(KNCF_XFRM_IF_ID, yn_no); | |||
| 169 | ||||
| 170 | # undef DOPT | |||
| 171 | ||||
| 172 | d->policy = | |||
| 173 | POLICY_TUNNEL((lset_t)1 << (POLICY_TUNNEL_IX)) | | |||
| 174 | POLICY_ECDSA((lset_t)1 << (POLICY_ECDSA_IX)) | POLICY_RSASIG((lset_t)1 << (POLICY_RSASIG_IX)) | POLICY_RSASIG_v1_5((lset_t)1 << (POLICY_RSASIG_v1_5_IX)) | /* authby= */ | |||
| 175 | POLICY_ENCRYPT((lset_t)1 << (POLICY_ENCRYPT_IX)) | POLICY_PFS((lset_t)1 << (POLICY_PFS_IX)) | | |||
| 176 | POLICY_IKEV2_ALLOW((lset_t)1 << (POLICY_IKEV2_ALLOW_IX)) | | |||
| 177 | POLICY_IKE_FRAG_ALLOW((lset_t)1 << (POLICY_IKE_FRAG_ALLOW_IX)) | /* ike_frag=yes */ | |||
| 178 | POLICY_ESN_NO((lset_t)1 << (POLICY_ESN_NO_IX)); /* esn=no */ | |||
| 179 | ||||
| 180 | d->sighash_policy = | |||
| 181 | POL_SIGHASH_SHA2_256((lset_t)1 << (POL_SIGHASH_SHA2_256_IX)) | POL_SIGHASH_SHA2_384((lset_t)1 << (POL_SIGHASH_SHA2_384_IX)) | POL_SIGHASH_SHA2_512((lset_t)1 << (POL_SIGHASH_SHA2_512_IX)); | |||
| 182 | ||||
| 183 | d->left.host_family = &ipv4_info; | |||
| 184 | d->left.addr = address_any(&ipv4_info); | |||
| 185 | d->left.nexttype = KH_NOTSET; | |||
| 186 | d->left.nexthop = address_any(&ipv4_info); | |||
| 187 | ||||
| 188 | d->right.host_family = &ipv4_info; | |||
| 189 | d->right.addr = address_any(&ipv4_info); | |||
| 190 | d->right.nexttype = KH_NOTSET; | |||
| 191 | d->right.nexthop = address_any(&ipv4_info); | |||
| 192 | ||||
| 193 | /* default is NOT to look in DNS */ | |||
| 194 | d->left.key_from_DNS_on_demand = FALSE0; | |||
| 195 | d->right.key_from_DNS_on_demand = FALSE0; | |||
| 196 | ||||
| 197 | d->state = STATE_LOADED; | |||
| 198 | ||||
| 199 | d->left.authby = AUTHBY_UNSET; | |||
| 200 | d->right.authby = AUTHBY_UNSET; | |||
| 201 | ||||
| 202 | d->left.updown = clone_str(DEFAULT_UPDOWN, "conn default left updown")(("ipsec _updown") == ((void*)0) ? ((void*)0) : clone_bytes(( "ipsec _updown"), strlen(("ipsec _updown")) + 1, ("conn default left updown" ))); | |||
| 203 | d->right.updown = clone_str(DEFAULT_UPDOWN, "conn default right updown")(("ipsec _updown") == ((void*)0) ? ((void*)0) : clone_bytes(( "ipsec _updown"), strlen(("ipsec _updown")) + 1, ("conn default right updown" ))); | |||
| 204 | /* ==== end of conn %default ==== */ | |||
| 205 | } | |||
| 206 | ||||
| 207 | /* | |||
| 208 | * format error, and append to string of errors | |||
| 209 | * The messages are separated by newline: not perfect. | |||
| 210 | */ | |||
| 211 | void starter_error_append(starter_errors_t *perrl, const char *fmt, ...) | |||
| 212 | { | |||
| 213 | va_list args; | |||
| 214 | char tmp_err[512]; | |||
| 215 | ||||
| 216 | va_start(args, fmt)__builtin_va_start(args, fmt); | |||
| 217 | vsnprintf(tmp_err, sizeof(tmp_err) - 1, fmt, args); | |||
| 218 | va_end(args)__builtin_va_end(args); | |||
| 219 | ||||
| 220 | if (perrl->errors == NULL((void*)0)) { | |||
| 221 | /* first error */ | |||
| 222 | perrl->errors = clone_str(tmp_err, "starter error")((tmp_err) == ((void*)0) ? ((void*)0) : clone_bytes((tmp_err) , strlen((tmp_err)) + 1, ("starter error"))); | |||
| 223 | } else { | |||
| 224 | /* subsequent error: append to previous messages */ | |||
| 225 | size_t ol = strlen(perrl->errors); | |||
| 226 | size_t al = strlen(tmp_err); | |||
| 227 | char *nerr = alloc_bytes(ol + al + 2, "starter errors"); | |||
| 228 | ||||
| 229 | memcpy(nerr, perrl->errors, ol); | |||
| 230 | nerr[ol] = '\n'; | |||
| 231 | memcpy(&nerr[ol + 1], tmp_err, al + 1); | |||
| 232 | pfree(perrl->errors); | |||
| 233 | perrl->errors = nerr; | |||
| 234 | } | |||
| 235 | } | |||
| 236 | ||||
| 237 | #define KW_POLICY_FLAG(val, fl){ if (conn->options_set[val]) conn->policy = (conn-> policy & ~(fl)) | (conn->options[val] ? (fl) : ((lset_t )0)); } { \ | |||
| 238 | if (conn->options_set[val]) \ | |||
| 239 | conn->policy = (conn->policy & ~(fl)) | \ | |||
| 240 | (conn->options[val] ? (fl) : LEMPTY((lset_t)0)); \ | |||
| 241 | } | |||
| 242 | ||||
| 243 | #define KW_POLICY_NEGATIVE_FLAG(val, fl){ if (conn->options_set[val]) { conn->policy = (conn-> policy & ~(fl)) | (!conn->options[val] ? (fl) : ((lset_t )0)); } } { \ | |||
| 244 | if (conn->options_set[val]) { \ | |||
| 245 | conn->policy = (conn->policy & ~(fl)) | \ | |||
| 246 | (!conn->options[val] ? (fl) : LEMPTY((lset_t)0)); \ | |||
| 247 | } \ | |||
| 248 | } | |||
| 249 | ||||
| 250 | /** | |||
| 251 | * Create a NULL-terminated array of tokens from a string of whitespace-separated tokens. | |||
| 252 | * | |||
| 253 | * @param value string to be broken up at blanks, creating strings for list | |||
| 254 | * @param n where to place element count (excluding terminating NULL) | |||
| 255 | * @return tokens_from_string (NULL or pointer to NULL-terminated array of pointers to strings) | |||
| 256 | */ | |||
| 257 | static char **tokens_from_string(const char *value, int *n) | |||
| 258 | { | |||
| 259 | *n = 0; /* in case of early exit */ | |||
| 260 | ||||
| 261 | if (value == NULL((void*)0)) | |||
| 262 | return NULL((void*)0); | |||
| 263 | ||||
| 264 | /* avoid damaging original string */ | |||
| 265 | char *const val = clone_str(value, "tokens_from_string value")((value) == ((void*)0) ? ((void*)0) : clone_bytes((value), strlen ((value)) + 1, ("tokens_from_string value"))); | |||
| 266 | if (val == NULL((void*)0)) | |||
| 267 | return NULL((void*)0); /* cannot happen -- silence a coverity warning */ | |||
| 268 | ||||
| 269 | char *const end = val + strlen(val); | |||
| 270 | ||||
| 271 | /* count number of items in string and terminate each with NUL */ | |||
| 272 | int count = 0; | |||
| 273 | for (char *b = val; b < end; ) { | |||
| 274 | char *e; | |||
| 275 | for (e = b; *e != '\0' && !isblank(*e)((*__ctype_b_loc ())[(int) ((*e))] & (unsigned short int) _ISblank); e++) | |||
| 276 | ; | |||
| 277 | *e = '\0'; | |||
| 278 | if (e != b) | |||
| 279 | count++; | |||
| 280 | b = e + 1; | |||
| 281 | } | |||
| 282 | ||||
| 283 | *n = count; | |||
| 284 | ||||
| 285 | if (count == 0) { | |||
| 286 | pfree(val); | |||
| 287 | return NULL((void*)0); | |||
| 288 | } | |||
| 289 | ||||
| 290 | char **const nlist = (char **)alloc_bytes((count + 1) * sizeof(char *), "tokens_from_string nlist"); | |||
| 291 | ||||
| 292 | count = 0; | |||
| 293 | for (char *b = val; b < end; ) { | |||
| 294 | char *e = b + strlen(b); | |||
| 295 | if (e != b) | |||
| 296 | nlist[count++] = clone_str(b, "tokens_from_string item")((b) == ((void*)0) ? ((void*)0) : clone_bytes((b), strlen((b) ) + 1, ("tokens_from_string item"))); | |||
| 297 | b = e + 1; | |||
| 298 | } | |||
| 299 | nlist[count] = NULL((void*)0); | |||
| 300 | pfree(val); | |||
| 301 | return nlist; | |||
| 302 | } | |||
| 303 | ||||
| 304 | /** | |||
| 305 | * Load a parsed config | |||
| 306 | * | |||
| 307 | * @param cfg starter_config structure | |||
| 308 | * @param cfgp config_parsed (ie: valid) struct | |||
| 309 | * @param perr pointer to store errors in | |||
| 310 | * @return bool TRUE if unsuccessful | |||
| 311 | */ | |||
| 312 | static bool_Bool load_setup(struct starter_config *cfg, | |||
| 313 | const struct config_parsed *cfgp) | |||
| 314 | { | |||
| 315 | bool_Bool err = FALSE0; | |||
| 316 | const struct kw_list *kw; | |||
| 317 | ||||
| 318 | for (kw = cfgp->config_setup; kw != NULL((void*)0); kw = kw->next) { | |||
| 319 | /** | |||
| 320 | * the parser already made sure that only config keywords were used, | |||
| 321 | * but we double check! | |||
| 322 | */ | |||
| 323 | assert(kw->keyword.keydef->validity & kv_config)((void) sizeof ((kw->keyword.keydef->validity & kv_config ) ? 1 : 0), __extension__ ({ if (kw->keyword.keydef->validity & kv_config) ; else __assert_fail ("kw->keyword.keydef->validity & kv_config" , "/home/build/libreswan/lib/libipsecconf/confread.c", 323, __extension__ __PRETTY_FUNCTION__); })); | |||
| 324 | unsigned f = kw->keyword.keydef->field; | |||
| 325 | ||||
| 326 | switch (kw->keyword.keydef->type) { | |||
| 327 | case kt_string: | |||
| 328 | case kt_filename: | |||
| 329 | case kt_dirname: | |||
| 330 | case kt_loose_enum: | |||
| 331 | /* all treated as strings for now */ | |||
| 332 | assert(f < elemsof(cfg->setup.strings))((void) sizeof ((f < (sizeof(cfg->setup.strings) / sizeof (*(cfg->setup.strings)))) ? 1 : 0), __extension__ ({ if (f < (sizeof(cfg->setup.strings) / sizeof(*(cfg->setup .strings)))) ; else __assert_fail ("f < elemsof(cfg->setup.strings)" , "/home/build/libreswan/lib/libipsecconf/confread.c", 332, __extension__ __PRETTY_FUNCTION__); })); | |||
| 333 | pfreeany(cfg->setup.strings[f]){ typeof(cfg->setup.strings[f]) *pp_ = &(cfg->setup .strings[f]); if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ( (void*)0); } }; | |||
| 334 | cfg->setup.strings[f] = | |||
| 335 | clone_str(kw->string, "kt_loose_enum kw->string")((kw->string) == ((void*)0) ? ((void*)0) : clone_bytes((kw ->string), strlen((kw->string)) + 1, ("kt_loose_enum kw->string" ))); | |||
| 336 | cfg->setup.strings_set[f] = TRUE1; | |||
| 337 | break; | |||
| 338 | ||||
| 339 | case kt_list: | |||
| 340 | case kt_lset: | |||
| 341 | case kt_bool: | |||
| 342 | case kt_invertbool: | |||
| 343 | case kt_enum: | |||
| 344 | case kt_number: | |||
| 345 | case kt_time: | |||
| 346 | case kt_percent: | |||
| 347 | /* all treated as a number for now */ | |||
| 348 | assert(f < elemsof(cfg->setup.options))((void) sizeof ((f < (sizeof(cfg->setup.options) / sizeof (*(cfg->setup.options)))) ? 1 : 0), __extension__ ({ if (f < (sizeof(cfg->setup.options) / sizeof(*(cfg->setup .options)))) ; else __assert_fail ("f < elemsof(cfg->setup.options)" , "/home/build/libreswan/lib/libipsecconf/confread.c", 348, __extension__ __PRETTY_FUNCTION__); })); | |||
| 349 | cfg->setup.options[f] = kw->number; | |||
| 350 | cfg->setup.options_set[f] = TRUE1; | |||
| 351 | break; | |||
| 352 | ||||
| 353 | case kt_bitstring: | |||
| 354 | case kt_rsakey: | |||
| 355 | case kt_ipaddr: | |||
| 356 | case kt_subnet: | |||
| 357 | case kt_range: | |||
| 358 | case kt_idtype: | |||
| 359 | err = TRUE1; | |||
| 360 | break; | |||
| 361 | ||||
| 362 | case kt_comment: | |||
| 363 | break; | |||
| 364 | ||||
| 365 | case kt_obsolete: | |||
| 366 | starter_log(LOG_LEVEL_INFO1, | |||
| 367 | "Warning: ignored obsolete keyword '%s'", | |||
| 368 | kw->keyword.keydef->keyname); | |||
| 369 | break; | |||
| 370 | case kt_obsolete_quiet: | |||
| 371 | starter_log(LOG_LEVEL_ERR2, | |||
| 372 | "Warning: ignored obsolete keyword '%s'", | |||
| 373 | kw->keyword.keydef->keyname); | |||
| 374 | break; | |||
| 375 | default: | |||
| 376 | /* NEVER HAPPENS */ | |||
| 377 | break; | |||
| 378 | } | |||
| 379 | } | |||
| 380 | ||||
| 381 | return err; | |||
| 382 | } | |||
| 383 | ||||
| 384 | /** | |||
| 385 | * Validate that yes in fact we are one side of the tunnel | |||
| 386 | * | |||
| 387 | * The function checks that IP addresses are valid, nexthops are | |||
| 388 | * present (if needed) as well as policies, and sets the leftID | |||
| 389 | * from the left= if it isn't set. | |||
| 390 | * | |||
| 391 | * @param conn_st a connection definition | |||
| 392 | * @param end a connection end | |||
| 393 | * @param leftright const char * "left" or "right" | |||
| 394 | * @param perrl pointer to starter_errors_t | |||
| 395 | * @return bool TRUE if failed | |||
| 396 | */ | |||
| 397 | ||||
| 398 | static bool_Bool validate_end(struct starter_conn *conn_st, | |||
| 399 | struct starter_end *end, | |||
| 400 | const char *leftright, | |||
| 401 | starter_errors_t *perrl, | |||
| 402 | struct logger *logger) | |||
| 403 | { | |||
| 404 | err_t er = NULL((void*)0); | |||
| 405 | bool_Bool err = FALSE0; | |||
| 406 | ||||
| 407 | /* | |||
| 408 | * TODO: | |||
| 409 | * The address family default should come in either via | |||
| 410 | * a config setup option, or via gai.conf / RFC3484 | |||
| 411 | * For now, %defaultroute and %any means IPv4 only | |||
| 412 | */ | |||
| 413 | const struct ip_info *hostfam = aftoinfo(conn_st->options[KNCF_HOSTADDRFAMILY]); | |||
| 414 | if (hostfam == NULL((void*)0)) { | |||
| 415 | const char *ips = end->strings[KNCF_IP]; | |||
| 416 | hostfam = &ipv4_info; | |||
| 417 | if (ips != NULL((void*)0) && | |||
| 418 | (strchr(ips, ':') != NULL((void*)0) || | |||
| 419 | streq(ips, "%defaultroute6")(strcmp((ips), ("%defaultroute6")) == 0) || | |||
| 420 | streq(ips, "%any6")(strcmp((ips), ("%any6")) == 0))) { | |||
| 421 | hostfam = &ipv6_info; | |||
| 422 | } | |||
| 423 | } | |||
| 424 | pexpect(hostfam == &ipv4_info || hostfam == &ipv6_info)({ _Bool assertion__ = hostfam == &ipv4_info || hostfam == &ipv6_info; if (!assertion__) { log_pexpect((where_t) { . func = __func__, .basename = "confread.c" , .line = 424}, "%s" , "hostfam == &ipv4_info || hostfam == &ipv6_info"); } assertion__; }); /* i.e., not NULL */ | |||
| 425 | ||||
| 426 | # define ERR_FOUND(...) { starter_error_append(perrl, __VA_ARGS__); err = TRUE1; } | |||
| 427 | ||||
| 428 | if (!end->options_set[KNCF_IP]) | |||
| 429 | conn_st->state = STATE_INCOMPLETE; | |||
| 430 | ||||
| 431 | /* validate the KSCF_IP/KNCF_IP */ | |||
| 432 | end->addrtype = end->options[KNCF_IP]; | |||
| 433 | switch (end->addrtype) { | |||
| 434 | case KH_ANY: | |||
| 435 | end->addr = address_any(hostfam); | |||
| 436 | break; | |||
| 437 | ||||
| 438 | case KH_IFACE: | |||
| 439 | /* generally, this doesn't show up at this stage */ | |||
| 440 | starter_log(LOG_LEVEL_DEBUG3, "starter: %s is KH_IFACE", leftright); | |||
| 441 | break; | |||
| 442 | ||||
| 443 | case KH_IPADDR: | |||
| 444 | assert(end->strings[KSCF_IP] != NULL)((void) sizeof ((end->strings[KSCF_IP] != ((void*)0)) ? 1 : 0), __extension__ ({ if (end->strings[KSCF_IP] != ((void* )0)) ; else __assert_fail ("end->strings[KSCF_IP] != NULL" , "/home/build/libreswan/lib/libipsecconf/confread.c", 444, __extension__ __PRETTY_FUNCTION__); })); | |||
| 445 | ||||
| 446 | if (end->strings[KSCF_IP][0] == '%') { | |||
| 447 | pfree(end->iface); | |||
| 448 | end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface")((end->strings[KSCF_IP] + 1) == ((void*)0) ? ((void*)0) : clone_bytes ((end->strings[KSCF_IP] + 1), strlen((end->strings[KSCF_IP ] + 1)) + 1, ("KH_IPADDR end->iface"))); | |||
| 449 | if (!starter_iface_find(end->iface, hostfam, | |||
| 450 | &end->addr, | |||
| 451 | &end->nexthop)) | |||
| 452 | conn_st->state = STATE_INVALID; | |||
| 453 | /* not numeric, so set the type to the iface type */ | |||
| 454 | end->addrtype = KH_IFACE; | |||
| 455 | break; | |||
| 456 | } | |||
| 457 | ||||
| 458 | er = numeric_to_address(shunk1(end->strings[KNCF_IP]), hostfam, &end->addr); | |||
| 459 | if (er != NULL((void*)0)) { | |||
| 460 | /* not an IP address, so set the type to the string */ | |||
| 461 | end->addrtype = KH_IPHOSTNAME; | |||
| 462 | } else { | |||
| 463 | hostfam = address_type(&end->addr); | |||
| 464 | } | |||
| 465 | ||||
| 466 | if (end->id == NULL((void*)0)) { | |||
| 467 | ipstr_buf b; | |||
| 468 | ||||
| 469 | end->id = clone_str(ipstr(&end->addr, &b), "end if")((ipstr(&end->addr, &b)) == ((void*)0) ? ((void*)0 ) : clone_bytes((ipstr(&end->addr, &b)), strlen((ipstr (&end->addr, &b))) + 1, ("end if"))); | |||
| 470 | } | |||
| 471 | break; | |||
| 472 | ||||
| 473 | case KH_OPPO: | |||
| 474 | conn_st->policy |= POLICY_OPPORTUNISTIC((lset_t)1 << (POLICY_OPPORTUNISTIC_IX)); | |||
| 475 | break; | |||
| 476 | ||||
| 477 | case KH_OPPOGROUP: | |||
| 478 | conn_st->policy |= POLICY_OPPORTUNISTIC((lset_t)1 << (POLICY_OPPORTUNISTIC_IX)) | POLICY_GROUP((lset_t)1 << (POLICY_GROUP_IX)); | |||
| 479 | break; | |||
| 480 | ||||
| 481 | case KH_GROUP: | |||
| 482 | conn_st->policy |= POLICY_GROUP((lset_t)1 << (POLICY_GROUP_IX)); | |||
| 483 | break; | |||
| 484 | ||||
| 485 | case KH_IPHOSTNAME: | |||
| 486 | /* generally, this doesn't show up at this stage */ | |||
| 487 | starter_log(LOG_LEVEL_DEBUG3, | |||
| 488 | "starter: %s is KH_IPHOSTNAME", leftright); | |||
| 489 | break; | |||
| 490 | ||||
| 491 | case KH_DEFAULTROUTE: | |||
| 492 | starter_log(LOG_LEVEL_DEBUG3, | |||
| 493 | "starter: %s is KH_DEFAULTROUTE", leftright); | |||
| 494 | break; | |||
| 495 | ||||
| 496 | case KH_NOTSET: | |||
| 497 | starter_log(LOG_LEVEL_DEBUG3, "starter: %s is KH_NOTSET", leftright); | |||
| 498 | break; | |||
| 499 | } | |||
| 500 | ||||
| 501 | /* now that HOSTFAM has been pined down */ | |||
| 502 | end->host_family = hostfam; | |||
| 503 | ||||
| 504 | if (end->strings_set[KSCF_VTI_IP]) { | |||
| 505 | const char *value = end->strings[KSCF_VTI_IP]; | |||
| 506 | err_t oops = text_cidr_to_subnet(shunk1(value), NULL((void*)0), &end->vti_ip); | |||
| 507 | if (oops != NULL((void*)0)) { | |||
| 508 | ERR_FOUND("bad addr %s%s=%s [%s]", | |||
| 509 | leftright, "vti", value, oops); | |||
| 510 | } | |||
| 511 | /* XXX: check type? */ | |||
| 512 | } | |||
| 513 | ||||
| 514 | /* validate the KSCF_SUBNET */ | |||
| 515 | if (end->strings_set[KSCF_SUBNET]) { | |||
| 516 | char *value = end->strings[KSCF_SUBNET]; | |||
| 517 | ||||
| 518 | if (end->strings_set[KSCF_ADDRESSPOOL]) { | |||
| 519 | ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=", leftright, | |||
| 520 | leftright); | |||
| 521 | } | |||
| 522 | ||||
| 523 | if (startswith(value, "vhost:")(strncmp(((value)), (("vhost:")), (strlen("vhost:"))) == 0) || startswith(value, "vnet:")(strncmp(((value)), (("vnet:")), (strlen("vnet:"))) == 0)) { | |||
| 524 | er = NULL((void*)0); | |||
| 525 | end->virt = clone_str(value, "validate_end item")((value) == ((void*)0) ? ((void*)0) : clone_bytes((value), strlen ((value)) + 1, ("validate_end item"))); | |||
| 526 | } else { | |||
| 527 | end->has_client = TRUE1; | |||
| 528 | er = ttosubnet(value, 0, AF_UNSPEC0, '0', | |||
| 529 | &end->subnet, logger); | |||
| 530 | } | |||
| 531 | if (er != NULL((void*)0)) | |||
| 532 | ERR_FOUND("bad subnet %ssubnet=%s [%s]", leftright, | |||
| 533 | value, er); | |||
| 534 | } | |||
| 535 | ||||
| 536 | /* | |||
| 537 | * validate the KSCF_NEXTHOP; set nexthop address to | |||
| 538 | * something consistent, by default | |||
| 539 | */ | |||
| 540 | end->nexthop = address_any(hostfam); | |||
| 541 | if (end->strings_set[KSCF_NEXTHOP]) { | |||
| 542 | char *value = end->strings[KSCF_NEXTHOP]; | |||
| 543 | ||||
| 544 | if (strcaseeq(value, "%defaultroute")(strcasecmp((value), ("%defaultroute")) == 0)) { | |||
| 545 | end->nexttype = KH_DEFAULTROUTE; | |||
| 546 | } else { | |||
| 547 | if (tnatoaddr(value, strlen(value), AF_UNSPEC0, | |||
| 548 | &end->nexthop) != NULL((void*)0)) { | |||
| 549 | #ifdef USE_DNSSEC1 | |||
| 550 | starter_log(LOG_LEVEL_DEBUG3, | |||
| 551 | "Calling unbound_resolve() for %snexthop value", | |||
| 552 | leftright); | |||
| 553 | if (!unbound_resolve(value, | |||
| 554 | strlen(value), AF_INET2, | |||
| 555 | &end->nexthop, logger) && | |||
| 556 | !unbound_resolve(value, | |||
| 557 | strlen(value), AF_INET610, | |||
| 558 | &end->nexthop, logger)) | |||
| 559 | ERR_FOUND("bad value for %snexthop=%s\n", | |||
| 560 | leftright, value); | |||
| 561 | #else | |||
| 562 | er = ttoaddr(value, 0, AF_UNSPEC0, | |||
| 563 | &end->nexthop); | |||
| 564 | if (er != NULL((void*)0)) | |||
| 565 | ERR_FOUND("bad value for %snexthop=%s [%s]", | |||
| 566 | leftright, value, | |||
| 567 | er); | |||
| 568 | #endif | |||
| 569 | } | |||
| 570 | end->nexttype = KH_IPADDR; | |||
| 571 | } | |||
| 572 | } else { | |||
| 573 | end->nexthop = address_any(hostfam); | |||
| 574 | ||||
| 575 | if (end->addrtype == KH_DEFAULTROUTE) { | |||
| 576 | end->nexttype = KH_DEFAULTROUTE; | |||
| 577 | } | |||
| 578 | } | |||
| 579 | ||||
| 580 | /* validate the KSCF_ID */ | |||
| 581 | if (end->strings_set[KSCF_ID]) { | |||
| 582 | char *value = end->strings[KSCF_ID]; | |||
| 583 | ||||
| 584 | pfreeany(end->id){ typeof(end->id) *pp_ = &(end->id); if (*pp_ != (( void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }; | |||
| 585 | end->id = clone_str(value, "end->id")((value) == ((void*)0) ? ((void*)0) : clone_bytes((value), strlen ((value)) + 1, ("end->id"))); | |||
| 586 | /* fixup old ",," in a ID_DER_ASN1_DN to proper backslash comma */ | |||
| 587 | if ((end->id[0] != '@') && (strstr(end->id, ",,") != NULL((void*)0)) | |||
| 588 | && strstr(end->id, "=") != NULL((void*)0)) | |||
| 589 | { | |||
| 590 | char *cc; | |||
| 591 | while ((cc = strstr(end->id, ",,")) != NULL((void*)0)) { | |||
| 592 | cc[0] = '\\'; | |||
| 593 | } | |||
| 594 | } | |||
| 595 | } | |||
| 596 | ||||
| 597 | if (end->options_set[KSCF_RSAKEY1]) { | |||
| 598 | end->rsakey1_type = end->options[KSCF_RSAKEY1]; | |||
| 599 | end->rsakey2_type = end->options[KSCF_RSAKEY2]; | |||
| 600 | ||||
| 601 | switch (end->options[KSCF_RSAKEY1]) { | |||
| 602 | case PUBKEY_DNSONDEMAND: | |||
| 603 | end->key_from_DNS_on_demand = TRUE1; | |||
| 604 | break; | |||
| 605 | ||||
| 606 | default: | |||
| 607 | end->key_from_DNS_on_demand = FALSE0; | |||
| 608 | /* validate the KSCF_RSAKEY1/RSAKEY2 */ | |||
| 609 | if (end->strings[KSCF_RSAKEY1] != NULL((void*)0)) { | |||
| 610 | char *value = end->strings[KSCF_RSAKEY1]; | |||
| 611 | ||||
| 612 | pfreeany(end->rsakey1){ typeof(end->rsakey1) *pp_ = &(end->rsakey1); if ( *pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }; | |||
| 613 | end->rsakey1 = clone_str(value, "end->rsakey1")((value) == ((void*)0) ? ((void*)0) : clone_bytes((value), strlen ((value)) + 1, ("end->rsakey1"))); | |||
| 614 | } | |||
| 615 | if (end->strings[KSCF_RSAKEY2] != NULL((void*)0)) { | |||
| 616 | char *value = end->strings[KSCF_RSAKEY2]; | |||
| 617 | ||||
| 618 | pfreeany(end->rsakey2){ typeof(end->rsakey2) *pp_ = &(end->rsakey2); if ( *pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }; | |||
| 619 | end->rsakey2 = clone_str(value, "end->rsakey2")((value) == ((void*)0) ? ((void*)0) : clone_bytes((value), strlen ((value)) + 1, ("end->rsakey2"))); | |||
| 620 | } | |||
| 621 | } | |||
| 622 | } | |||
| 623 | ||||
| 624 | /* validate the KSCF_SOURCEIP, if any, and if set, | |||
| 625 | * set the subnet to same value, if not set. | |||
| 626 | */ | |||
| 627 | if (end->strings_set[KSCF_SOURCEIP]) { | |||
| 628 | char *value = end->strings[KSCF_SOURCEIP]; | |||
| 629 | ||||
| 630 | if (tnatoaddr(value, strlen(value), AF_UNSPEC0, | |||
| 631 | &end->sourceip) != NULL((void*)0)) { | |||
| 632 | #ifdef USE_DNSSEC1 | |||
| 633 | starter_log(LOG_LEVEL_DEBUG3, | |||
| 634 | "Calling unbound_resolve() for %ssourceip value", | |||
| 635 | leftright); | |||
| 636 | if (!unbound_resolve(value, | |||
| 637 | strlen(value), AF_INET2, | |||
| 638 | &end->sourceip, logger) && | |||
| 639 | !unbound_resolve(value, | |||
| 640 | strlen(value), AF_INET610, | |||
| 641 | &end->sourceip, logger)) | |||
| 642 | ERR_FOUND("bad value for %ssourceip=%s\n", | |||
| 643 | leftright, value); | |||
| 644 | #else | |||
| 645 | er = ttoaddr(value, 0, AF_UNSPEC0, &end->sourceip); | |||
| 646 | if (er != NULL((void*)0)) | |||
| 647 | ERR_FOUND("bad addr %ssourceip=%s [%s]", | |||
| 648 | leftright, value, er); | |||
| 649 | #endif | |||
| 650 | } else { | |||
| 651 | er = tnatoaddr(value, 0, AF_UNSPEC0, &end->sourceip); | |||
| 652 | if (er != NULL((void*)0)) | |||
| 653 | ERR_FOUND("bad numerical addr %ssourceip=%s [%s]", | |||
| 654 | leftright, value, er); | |||
| 655 | } | |||
| 656 | if (!end->has_client) { | |||
| 657 | er = endtosubnet(&end->sourceip, &end->subnet, HERE(where_t) { .func = __func__, .basename = "confread.c" , .line = 657}); | |||
| 658 | if (er != NULL((void*)0)) { | |||
| 659 | ERR_FOUND("attempt to default %ssubnet from %s failed: %s", | |||
| 660 | leftright, value, er); | |||
| 661 | } | |||
| 662 | end->has_client = TRUE1; | |||
| 663 | } | |||
| 664 | if (end->strings_set[KSCF_INTERFACE_IP]) { | |||
| 665 | ERR_FOUND("can not specify %sinterface-ip=%s and %sssourceip=%s", | |||
| 666 | leftright, | |||
| 667 | end->strings[KSCF_INTERFACE_IP], | |||
| 668 | leftright, | |||
| 669 | end->strings[KSCF_SOURCEIP]); | |||
| 670 | } | |||
| 671 | } | |||
| 672 | ||||
| 673 | /* copy certificate path name */ | |||
| 674 | if (end->strings_set[KSCF_CERT] && end->strings_set[KSCF_CKAID]) { | |||
| 675 | ERR_FOUND("only one of %scert and %sckaid can be specified", | |||
| 676 | leftright, leftright); | |||
| 677 | } | |||
| 678 | if (end->strings_set[KSCF_CERT]) { | |||
| 679 | end->certx = clone_str(end->strings[KSCF_CERT], "KSCF_CERT")((end->strings[KSCF_CERT]) == ((void*)0) ? ((void*)0) : clone_bytes ((end->strings[KSCF_CERT]), strlen((end->strings[KSCF_CERT ])) + 1, ("KSCF_CERT"))); | |||
| 680 | } | |||
| 681 | if (end->strings_set[KSCF_CKAID]) { | |||
| 682 | const char *ckaid = end->strings[KSCF_CKAID]; | |||
| 683 | /* try parsing it */ | |||
| 684 | const char *ugh = ttodata(ckaid, 0, 16, NULL((void*)0), 0, NULL((void*)0)); | |||
| 685 | if (ugh != NULL((void*)0)) { | |||
| 686 | ERR_FOUND("invalid %sckaid: %s", leftright, ugh); | |||
| 687 | } | |||
| 688 | end->ckaid = clone_str(ckaid, "KSCF_CKAID")((ckaid) == ((void*)0) ? ((void*)0) : clone_bytes((ckaid), strlen ((ckaid)) + 1, ("KSCF_CKAID"))); | |||
| 689 | } | |||
| 690 | ||||
| 691 | if (end->strings_set[KSCF_CA]) | |||
| 692 | end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA")((end->strings[KSCF_CA]) == ((void*)0) ? ((void*)0) : clone_bytes ((end->strings[KSCF_CA]), strlen((end->strings[KSCF_CA] )) + 1, ("KSCF_CA"))); | |||
| 693 | ||||
| 694 | if (end->strings_set[KSCF_UPDOWN]) { | |||
| 695 | pfreeany(end->updown){ typeof(end->updown) *pp_ = &(end->updown); if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }; | |||
| 696 | end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN")((end->strings[KSCF_UPDOWN]) == ((void*)0) ? ((void*)0) : clone_bytes ((end->strings[KSCF_UPDOWN]), strlen((end->strings[KSCF_UPDOWN ])) + 1, ("KSCF_UPDOWN"))); | |||
| 697 | } | |||
| 698 | ||||
| 699 | if (end->strings_set[KSCF_PROTOPORT]) { | |||
| 700 | char *value = end->strings[KSCF_PROTOPORT]; | |||
| 701 | err_t ugh = ttoprotoport(value, &end->protoport); | |||
| 702 | if (ugh != NULL((void*)0)) | |||
| 703 | ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value, | |||
| 704 | ugh); | |||
| 705 | } | |||
| 706 | ||||
| 707 | if (end->strings_set[KSCF_ADDRESSPOOL]) { | |||
| 708 | char *addresspool = end->strings[KSCF_ADDRESSPOOL]; | |||
| 709 | ||||
| 710 | if (end->strings_set[KSCF_SUBNET]) | |||
| 711 | ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=", | |||
| 712 | leftright, leftright); | |||
| 713 | starter_log(LOG_LEVEL_DEBUG3, | |||
| 714 | "connection's %saddresspool set to: %s", | |||
| 715 | leftright, end->strings[KSCF_ADDRESSPOOL] ); | |||
| 716 | ||||
| 717 | er = ttorange(addresspool, NULL((void*)0), &end->pool_range, logger); | |||
| 718 | if (er != NULL((void*)0)) | |||
| 719 | ERR_FOUND("bad %saddresspool=%s [%s]", leftright, | |||
| 720 | addresspool, er); | |||
| 721 | ||||
| 722 | if (address_type(&end->pool_range.start) == &ipv6_info && | |||
| 723 | !end->pool_range.is_subnet) { | |||
| 724 | ERR_FOUND("bad IPv6 %saddresspool=%s not subnet", leftright, | |||
| 725 | addresspool); | |||
| 726 | } | |||
| 727 | } | |||
| 728 | ||||
| 729 | if (end->strings_set[KSCF_INTERFACE_IP]) { | |||
| 730 | const char *value = end->strings[KSCF_INTERFACE_IP]; | |||
| 731 | err_t oops = text_cidr_to_subnet(shunk1(value), NULL((void*)0), &end->ifaceip); | |||
| 732 | if (oops != NULL((void*)0)) { | |||
| 733 | ERR_FOUND("bad addr %s%s=%s [%s]", | |||
| 734 | leftright, "interface-ip", value, oops); | |||
| 735 | } | |||
| 736 | if (end->strings_set[KSCF_SOURCEIP]) { | |||
| 737 | ERR_FOUND("can not specify %sinterface-ip=%s and %sssourceip=%s", | |||
| 738 | leftright, | |||
| 739 | end->strings[KSCF_INTERFACE_IP], | |||
| 740 | leftright, | |||
| 741 | end->strings[KSCF_SOURCEIP]); | |||
| 742 | } | |||
| 743 | ||||
| 744 | } | |||
| 745 | ||||
| 746 | if (end->options_set[KNCF_XAUTHSERVER] || | |||
| 747 | end->options_set[KNCF_XAUTHCLIENT]) | |||
| 748 | conn_st->policy |= POLICY_XAUTH((lset_t)1 << (POLICY_XAUTH_IX)); | |||
| 749 | ||||
| 750 | return err; | |||
| 751 | # undef ERR_FOUND | |||
| 752 | } | |||
| 753 | ||||
| 754 | /** | |||
| 755 | * Take keywords from ipsec.conf syntax and load into a conn struct | |||
| 756 | * | |||
| 757 | * @param conn a connection definition | |||
| 758 | * @param sl a section_list | |||
| 759 | * @param assigned_value is set to either k_set, or k_default. | |||
| 760 | * k_default is used when we are loading a conn that should be | |||
| 761 | * considered to be a "default" value, and that replacing this | |||
| 762 | * value is considered acceptable. | |||
| 763 | * @return bool TRUE if unsuccessful | |||
| 764 | */ | |||
| 765 | static bool_Bool translate_conn(struct starter_conn *conn, | |||
| 766 | const struct section_list *sl, | |||
| 767 | enum keyword_set assigned_value, | |||
| 768 | starter_errors_t *perrl) | |||
| 769 | { | |||
| 770 | /* note: not all errors are considered serious */ | |||
| 771 | bool_Bool serious_err = FALSE0; | |||
| 772 | ||||
| 773 | for (const struct kw_list *kw = sl->kw; kw != NULL((void*)0); kw = kw->next) { | |||
| 774 | if ((kw->keyword.keydef->validity & kv_conn) == 0) { | |||
| 775 | /* this isn't valid in a conn! */ | |||
| 776 | char tmp_err[512]; | |||
| 777 | ||||
| 778 | snprintf(tmp_err, sizeof(tmp_err), | |||
| 779 | "keyword '%s' is not valid in a conn (%s)\n", | |||
| 780 | kw->keyword.keydef->keyname, sl->name); | |||
| 781 | starter_log(LOG_LEVEL_INFO1, "%s", tmp_err); | |||
| 782 | starter_error_append(perrl, "%s", tmp_err); | |||
| 783 | continue; | |||
| 784 | } | |||
| 785 | ||||
| 786 | ksf *the_strings; | |||
| 787 | str_set *set_strings; | |||
| 788 | unsigned str_floor, str_roof; | |||
| 789 | ||||
| 790 | knf *the_options; | |||
| 791 | int_set *set_options; | |||
| 792 | unsigned opt_floor, opt_roof; | |||
| 793 | ||||
| 794 | if (kw->keyword.keydef->validity & kv_leftright) { | |||
| 795 | struct starter_end *this = kw->keyword.keyleft ? | |||
| 796 | &conn->left : &conn->right; | |||
| 797 | ||||
| 798 | the_strings = &this->strings; | |||
| 799 | set_strings = &this->strings_set; | |||
| 800 | str_floor = KSCF_last_loose + 1; | |||
| 801 | str_roof = KSCF_last_leftright + 1; | |||
| 802 | ||||
| 803 | the_options = &this->options; | |||
| 804 | set_options = &this->options_set; | |||
| 805 | opt_floor = KSCF_last_loose + 1; | |||
| 806 | opt_roof = KNCF_last_leftright + 1; | |||
| 807 | } else { | |||
| 808 | the_strings = &conn->strings; | |||
| 809 | set_strings = &conn->strings_set; | |||
| 810 | str_floor = KSCF_last_leftright + 1; | |||
| 811 | str_roof = KSCF_ROOF; | |||
| 812 | ||||
| 813 | the_options = &conn->options; | |||
| 814 | set_options = &conn->options_set; | |||
| 815 | opt_floor = KNCF_last_leftright + 1; | |||
| 816 | opt_roof = KNCF_ROOF; | |||
| 817 | } | |||
| 818 | ||||
| 819 | unsigned int field = kw->keyword.keydef->field; | |||
| 820 | ||||
| 821 | assert(kw->keyword.keydef != NULL)((void) sizeof ((kw->keyword.keydef != ((void*)0)) ? 1 : 0 ), __extension__ ({ if (kw->keyword.keydef != ((void*)0)) ; else __assert_fail ("kw->keyword.keydef != NULL", "/home/build/libreswan/lib/libipsecconf/confread.c" , 821, __extension__ __PRETTY_FUNCTION__); })); | |||
| 822 | ||||
| 823 | switch (kw->keyword.keydef->type) { | |||
| 824 | case kt_string: | |||
| 825 | case kt_filename: | |||
| 826 | case kt_dirname: | |||
| 827 | case kt_bitstring: | |||
| 828 | case kt_ipaddr: | |||
| 829 | case kt_range: | |||
| 830 | case kt_subnet: | |||
| 831 | case kt_idtype: | |||
| 832 | /* all treated as strings for now, even loose enums */ | |||
| 833 | assert(field < str_roof)((void) sizeof ((field < str_roof) ? 1 : 0), __extension__ ({ if (field < str_roof) ; else __assert_fail ("field < str_roof" , "/home/build/libreswan/lib/libipsecconf/confread.c", 833, __extension__ __PRETTY_FUNCTION__); })); | |||
| 834 | ||||
| 835 | if ((*set_strings)[field] == k_set) { | |||
| 836 | char tmp_err[512]; | |||
| 837 | ||||
| 838 | snprintf(tmp_err, sizeof(tmp_err), | |||
| 839 | "duplicate key '%s' in conn %s while processing def %s", | |||
| 840 | kw->keyword.keydef->keyname, | |||
| 841 | conn->name, | |||
| 842 | sl->name); | |||
| 843 | ||||
| 844 | starter_log(LOG_LEVEL_INFO1, "%s", tmp_err); | |||
| 845 | starter_error_append(perrl, "%s", tmp_err); | |||
| 846 | ||||
| 847 | /* only fatal if we try to change values */ | |||
| 848 | if (kw->keyword.string == NULL((void*)0) || | |||
| 849 | (*the_strings)[field] == NULL((void*)0) || | |||
| 850 | !streq(kw->keyword.string,(strcmp((kw->keyword.string), ((*the_strings)[field])) == 0 ) | |||
| 851 | (*the_strings)[field])(strcmp((kw->keyword.string), ((*the_strings)[field])) == 0 )) | |||
| 852 | { | |||
| 853 | serious_err = TRUE1; | |||
| 854 | break; | |||
| 855 | } | |||
| 856 | } | |||
| 857 | pfreeany((*the_strings)[field]){ typeof((*the_strings)[field]) *pp_ = &((*the_strings)[field ]); if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }; | |||
| 858 | ||||
| 859 | if (kw->string == NULL((void*)0)) { | |||
| 860 | starter_error_append(perrl, "Invalid %s value", | |||
| 861 | kw->keyword.keydef->keyname); | |||
| 862 | serious_err = TRUE1; | |||
| 863 | break; | |||
| 864 | } | |||
| 865 | ||||
| 866 | (*the_strings)[field] = clone_str(kw->string, "kt_idtype kw->string")((kw->string) == ((void*)0) ? ((void*)0) : clone_bytes((kw ->string), strlen((kw->string)) + 1, ("kt_idtype kw->string" ))); | |||
| 867 | (*set_strings)[field] = assigned_value; | |||
| 868 | break; | |||
| 869 | ||||
| 870 | case kt_appendstring: | |||
| 871 | case kt_appendlist: | |||
| 872 | /* implicitly, this field can have multiple values */ | |||
| 873 | assert(str_floor <= field && field < str_roof)((void) sizeof ((str_floor <= field && field < str_roof ) ? 1 : 0), __extension__ ({ if (str_floor <= field && field < str_roof) ; else __assert_fail ("str_floor <= field && field < str_roof" , "/home/build/libreswan/lib/libipsecconf/confread.c", 873, __extension__ __PRETTY_FUNCTION__); })); | |||
| 874 | if ((*the_strings)[field] == NULL((void*)0)) { | |||
| 875 | (*the_strings)[field] = clone_str(kw->string, "kt_appendlist kw->string")((kw->string) == ((void*)0) ? ((void*)0) : clone_bytes((kw ->string), strlen((kw->string)) + 1, ("kt_appendlist kw->string" ))); | |||
| 876 | } else { | |||
| 877 | char *s = (*the_strings)[field]; | |||
| 878 | size_t old_len = strlen(s); /* excludes '\0' */ | |||
| 879 | size_t new_len = strlen(kw->string); | |||
| 880 | char *n = alloc_bytes(old_len + 1 + new_len + 1, "kt_appendlist"); | |||
| 881 | ||||
| 882 | memcpy(n, s, old_len); | |||
| 883 | n[old_len] = ' '; | |||
| 884 | memcpy(n + old_len + 1, kw->string, new_len + 1); /* includes '\0' */ | |||
| 885 | (*the_strings)[field] = n; | |||
| 886 | pfree(s); | |||
| 887 | } | |||
| 888 | (*set_strings)[field] = TRUE1; | |||
| 889 | break; | |||
| 890 | ||||
| 891 | case kt_rsakey: | |||
| 892 | case kt_loose_enum: | |||
| 893 | assert(field <= KSCF_last_loose)((void) sizeof ((field <= KSCF_last_loose) ? 1 : 0), __extension__ ({ if (field <= KSCF_last_loose) ; else __assert_fail ("field <= KSCF_last_loose" , "/home/build/libreswan/lib/libipsecconf/confread.c", 893, __extension__ __PRETTY_FUNCTION__); })); | |||
| 894 | ||||
| 895 | if ((*set_options)[field] == k_set) { | |||
| 896 | char tmp_err[512]; | |||
| 897 | ||||
| 898 | snprintf(tmp_err, sizeof(tmp_err), | |||
| 899 | "duplicate key '%s' in conn %s while processing def %s", | |||
| 900 | kw->keyword.keydef->keyname, | |||
| 901 | conn->name, | |||
| 902 | sl->name); | |||
| 903 | ||||
| 904 | starter_log(LOG_LEVEL_INFO1, "%s", tmp_err); | |||
| 905 | starter_error_append(perrl, "%s", tmp_err); | |||
| 906 | ||||
| 907 | /* only fatal if we try to change values */ | |||
| 908 | if ((*the_options)[field] != (int)kw->number || | |||
| 909 | !((*the_options)[field] == | |||
| 910 | LOOSE_ENUM_OTHER255 && | |||
| 911 | kw->number == LOOSE_ENUM_OTHER255 && | |||
| 912 | kw->keyword.string != NULL((void*)0) && | |||
| 913 | (*the_strings)[field] != NULL((void*)0) && | |||
| 914 | streq(kw->keyword.string,(strcmp((kw->keyword.string), ((*the_strings)[field])) == 0 ) | |||
| 915 | (*the_strings)[field])(strcmp((kw->keyword.string), ((*the_strings)[field])) == 0 ))) | |||
| 916 | { | |||
| 917 | serious_err = TRUE1; | |||
| 918 | break; | |||
| 919 | } | |||
| 920 | } | |||
| 921 | ||||
| 922 | (*the_options)[field] = kw->number; | |||
| 923 | if (kw->number == LOOSE_ENUM_OTHER255) { | |||
| 924 | assert(kw->keyword.string != NULL)((void) sizeof ((kw->keyword.string != ((void*)0)) ? 1 : 0 ), __extension__ ({ if (kw->keyword.string != ((void*)0)) ; else __assert_fail ("kw->keyword.string != NULL", "/home/build/libreswan/lib/libipsecconf/confread.c" , 924, __extension__ __PRETTY_FUNCTION__); })); | |||
| 925 | pfreeany((*the_strings)[field]){ typeof((*the_strings)[field]) *pp_ = &((*the_strings)[field ]); if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }; | |||
| 926 | (*the_strings)[field] = clone_str(((kw->keyword.string) == ((void*)0) ? ((void*)0) : clone_bytes ((kw->keyword.string), strlen((kw->keyword.string)) + 1 , ("kt_loose_enum kw->keyword.string"))) | |||
| 927 | kw->keyword.string, "kt_loose_enum kw->keyword.string")((kw->keyword.string) == ((void*)0) ? ((void*)0) : clone_bytes ((kw->keyword.string), strlen((kw->keyword.string)) + 1 , ("kt_loose_enum kw->keyword.string"))); | |||
| 928 | } | |||
| 929 | (*set_options)[field] = assigned_value; | |||
| 930 | break; | |||
| 931 | ||||
| 932 | case kt_list: | |||
| 933 | case kt_lset: | |||
| 934 | case kt_bool: | |||
| 935 | case kt_invertbool: | |||
| 936 | case kt_enum: | |||
| 937 | case kt_number: | |||
| 938 | case kt_time: | |||
| 939 | case kt_percent: | |||
| 940 | /* all treated as a number for now */ | |||
| 941 | assert(opt_floor <= field && field < opt_roof)((void) sizeof ((opt_floor <= field && field < opt_roof ) ? 1 : 0), __extension__ ({ if (opt_floor <= field && field < opt_roof) ; else __assert_fail ("opt_floor <= field && field < opt_roof" , "/home/build/libreswan/lib/libipsecconf/confread.c", 941, __extension__ __PRETTY_FUNCTION__); })); | |||
| 942 | ||||
| 943 | if ((*set_options)[field] == k_set) { | |||
| 944 | char tmp_err[512]; | |||
| 945 | ||||
| 946 | snprintf(tmp_err, sizeof(tmp_err), | |||
| 947 | "duplicate key '%s' in conn %s while processing def %s", | |||
| 948 | kw->keyword.keydef->keyname, | |||
| 949 | conn->name, | |||
| 950 | sl->name); | |||
| 951 | starter_log(LOG_LEVEL_INFO1, "%s", tmp_err); | |||
| 952 | starter_error_append(perrl, "%s", tmp_err); | |||
| 953 | /* only fatal if we try to change values */ | |||
| 954 | if ((*the_options)[field] != (int)kw->number) { | |||
| 955 | serious_err = TRUE1; | |||
| 956 | break; | |||
| 957 | } | |||
| 958 | } | |||
| 959 | ||||
| 960 | (*the_options)[field] = kw->number; | |||
| 961 | (*set_options)[field] = assigned_value; | |||
| 962 | break; | |||
| 963 | ||||
| 964 | case kt_comment: | |||
| 965 | break; | |||
| 966 | ||||
| 967 | case kt_obsolete: | |||
| 968 | starter_log(LOG_LEVEL_INFO1, | |||
| 969 | "Warning: obsolete keyword '%s' ignored", | |||
| 970 | kw->keyword.keydef->keyname); | |||
| 971 | break; | |||
| 972 | ||||
| 973 | case kt_obsolete_quiet: | |||
| 974 | starter_log(LOG_LEVEL_ERR2, | |||
| 975 | "Warning: obsolete keyword '%s' ignored", | |||
| 976 | kw->keyword.keydef->keyname); | |||
| 977 | break; | |||
| 978 | } | |||
| 979 | } | |||
| 980 | return serious_err; | |||
| 981 | } | |||
| 982 | ||||
| 983 | static void move_comment_list(struct starter_comments_list *to, | |||
| 984 | struct starter_comments_list *from) | |||
| 985 | { | |||
| 986 | struct starter_comments *sc, *scnext; | |||
| 987 | ||||
| 988 | for (sc = from->tqh_first; | |||
| 989 | sc != NULL((void*)0); | |||
| 990 | sc = scnext) { | |||
| 991 | scnext = sc->link.tqe_next; | |||
| 992 | TAILQ_REMOVE(from, sc, link)do { if (((sc)->link.tqe_next) != ((void*)0)) (sc)->link .tqe_next->link.tqe_prev = (sc)->link.tqe_prev; else (from )->tqh_last = (sc)->link.tqe_prev; *(sc)->link.tqe_prev = (sc)->link.tqe_next; } while ( 0); | |||
| 993 | TAILQ_INSERT_TAIL(to, sc, link)do { (sc)->link.tqe_next = ((void*)0); (sc)->link.tqe_prev = (to)->tqh_last; *(to)->tqh_last = (sc); (to)->tqh_last = &(sc)->link.tqe_next; } while ( 0); | |||
| 994 | } | |||
| 995 | } | |||
| 996 | ||||
| 997 | static bool_Bool load_conn(struct starter_conn *conn, | |||
| 998 | const struct config_parsed *cfgp, | |||
| 999 | struct section_list *sl, | |||
| 1000 | bool_Bool alsoprocessing, | |||
| 1001 | bool_Bool defaultconn, | |||
| 1002 | starter_errors_t *perrl, | |||
| 1003 | struct logger *logger) | |||
| 1004 | { | |||
| 1005 | bool_Bool err; | |||
| 1006 | ||||
| 1007 | /* turn all of the keyword/value pairs into options/strings in left/right */ | |||
| 1008 | err = translate_conn(conn, sl, | |||
| 1009 | defaultconn ? k_default : k_set, | |||
| ||||
| 1010 | perrl); | |||
| 1011 | ||||
| 1012 | move_comment_list(&conn->comments, &sl->comments); | |||
| 1013 | ||||
| 1014 | if (err) | |||
| 1015 | return err; | |||
| 1016 | ||||
| 1017 | if (conn->strings[KSCF_ALSO] != NULL((void*)0) && | |||
| 1018 | !alsoprocessing) { | |||
| 1019 | starter_log(LOG_LEVEL_INFO1, | |||
| 1020 | "also= is not valid in section '%s'", | |||
| 1021 | sl->name); | |||
| 1022 | starter_error_append(perrl, "also= is not valid in section '%s'", | |||
| 1023 | sl->name); | |||
| 1024 | return TRUE1; /* error */ | |||
| 1025 | } | |||
| 1026 | ||||
| 1027 | /* | |||
| 1028 | * Process the also list | |||
| 1029 | * | |||
| 1030 | * Note: conn->alsos will be NULL until we finish | |||
| 1031 | * and the appropriate list will be in local variable alsos. | |||
| 1032 | */ | |||
| 1033 | ||||
| 1034 | /* free any residual alsos list */ | |||
| 1035 | if (conn->alsos != NULL((void*)0)) { | |||
| 1036 | for (char **s = conn->alsos; *s != NULL((void*)0); s++) | |||
| 1037 | pfreeany(*s){ typeof(*s) *pp_ = &(*s); if (*pp_ != ((void*)0)) { pfree (*pp_); *pp_ = ((void*)0); } }; | |||
| 1038 | pfree(conn->alsos); | |||
| 1039 | conn->alsos = NULL((void*)0); | |||
| 1040 | } | |||
| 1041 | ||||
| 1042 | int alsosize; | |||
| 1043 | char **alsos = tokens_from_string(conn->strings[KSCF_ALSO], &alsosize); | |||
| 1044 | ||||
| 1045 | if (alsoprocessing && alsos != NULL((void*)0)) { | |||
| 1046 | /* reset all of the "beenhere" flags */ | |||
| 1047 | for (struct section_list *s = cfgp->sections.tqh_first; s != NULL((void*)0); | |||
| 1048 | s = s->link.tqe_next) | |||
| 1049 | s->beenhere = FALSE0; | |||
| 1050 | sl->beenhere = TRUE1; | |||
| 1051 | ||||
| 1052 | for (int alsoplace = 0; alsoplace < alsosize; alsoplace++) { | |||
| 1053 | /* | |||
| 1054 | * Check for too many alsos. | |||
| 1055 | * Inside the loop because of indirect alsos. | |||
| 1056 | */ | |||
| 1057 | if (alsosize >= ALSO_LIMIT32) { | |||
| 1058 | starter_log(LOG_LEVEL_INFO1, | |||
| 1059 | "while loading conn '%s', too many also= used at section %s. Limit is %d", | |||
| 1060 | conn->name, | |||
| 1061 | alsos[alsosize], | |||
| 1062 | ALSO_LIMIT32); | |||
| 1063 | starter_error_append(perrl, "while loading conn '%s', too many also= used at section %s. Limit is %d", | |||
| 1064 | conn->name, | |||
| 1065 | alsos[alsosize], | |||
| 1066 | ALSO_LIMIT32); | |||
| 1067 | return TRUE1; /* error */ | |||
| 1068 | } | |||
| 1069 | ||||
| 1070 | /* | |||
| 1071 | * for each also= listed, go find this section's keyword list, and | |||
| 1072 | * load it as well. This may extend the also= list (and the end), | |||
| 1073 | * which we handle by zeroing the also list, and adding to it after | |||
| 1074 | * checking for duplicates. | |||
| 1075 | */ | |||
| 1076 | struct section_list *addin; | |||
| 1077 | ||||
| 1078 | for (addin = cfgp->sections.tqh_first; | |||
| 1079 | addin != NULL((void*)0) && | |||
| 1080 | !streq(alsos[alsoplace], addin->name)(strcmp((alsos[alsoplace]), (addin->name)) == 0); | |||
| ||||
| 1081 | addin = addin->link.tqe_next) | |||
| 1082 | ; | |||
| 1083 | ||||
| 1084 | if (addin == NULL((void*)0)) { | |||
| 1085 | starter_log(LOG_LEVEL_ERR2, | |||
| 1086 | "cannot find conn '%s' needed by conn '%s'", | |||
| 1087 | alsos[alsoplace], conn->name); | |||
| 1088 | starter_error_append(perrl, "cannot find conn '%s' needed by conn '%s'", | |||
| 1089 | alsos[alsoplace], conn->name); | |||
| 1090 | err = TRUE1; | |||
| 1091 | continue; /* allowing further error detection */ | |||
| 1092 | } | |||
| 1093 | ||||
| 1094 | if (addin->beenhere) | |||
| 1095 | continue; /* already handled */ | |||
| 1096 | ||||
| 1097 | starter_log(LOG_LEVEL_DEBUG3, | |||
| 1098 | "\twhile loading conn '%s' also including '%s'", | |||
| 1099 | conn->name, alsos[alsoplace]); | |||
| 1100 | ||||
| 1101 | conn->strings_set[KSCF_ALSO] = FALSE0; | |||
| 1102 | pfreeany(conn->strings[KSCF_ALSO]){ typeof(conn->strings[KSCF_ALSO]) *pp_ = &(conn->strings [KSCF_ALSO]); if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ( (void*)0); } }; | |||
| 1103 | conn->strings[KSCF_ALSO] = NULL((void*)0); | |||
| 1104 | addin->beenhere = TRUE1; | |||
| 1105 | ||||
| 1106 | /* translate things, but do not replace earlier settings! */ | |||
| 1107 | err |= translate_conn(conn, addin, k_set, perrl); | |||
| 1108 | ||||
| 1109 | if (conn->strings[KSCF_ALSO] != NULL((void*)0)) { | |||
| 1110 | /* add this guy's alsos too */ | |||
| 1111 | int newalsosize; | |||
| 1112 | char **newalsos = tokens_from_string( | |||
| 1113 | conn->strings[KSCF_ALSO], &newalsosize); | |||
| 1114 | ||||
| 1115 | if (newalsos != NULL((void*)0)) { | |||
| 1116 | /* | |||
| 1117 | * Append newalsos onto alsos. | |||
| 1118 | * Requires a re-allocation. | |||
| 1119 | * Copying is shallow: the lists | |||
| 1120 | * are copied and freed but | |||
| 1121 | * the underlying strings are unchanged. | |||
| 1122 | */ | |||
| 1123 | char **ra = alloc_bytes((alsosize + | |||
| 1124 | newalsosize + 1) * | |||
| 1125 | sizeof(char *), | |||
| 1126 | "conn->alsos"); | |||
| 1127 | memcpy(ra, alsos, alsosize * sizeof(char *)); | |||
| 1128 | pfree(alsos); | |||
| 1129 | alsos = ra; | |||
| 1130 | ||||
| 1131 | memcpy(ra + alsosize, newalsos, | |||
| 1132 | (newalsosize + 1) * sizeof(char *)); | |||
| 1133 | pfree(newalsos); | |||
| 1134 | ||||
| 1135 | alsosize += newalsosize; | |||
| 1136 | } | |||
| 1137 | } | |||
| 1138 | } | |||
| 1139 | } | |||
| 1140 | ||||
| 1141 | /* | |||
| 1142 | * Migrate alsos back to conn->alsos. | |||
| 1143 | * Note that this is the transitive closure. | |||
| 1144 | */ | |||
| 1145 | conn->alsos = alsos; | |||
| 1146 | ||||
| 1147 | if (conn->options_set[KNCF_TYPE]) { | |||
| 1148 | switch ((enum keyword_satype)conn->options[KNCF_TYPE]) { | |||
| 1149 | case KS_TUNNEL: | |||
| 1150 | conn->policy &= ~POLICY_SHUNT_MASK(((lset_t)1 << (POLICY_SHUNT1_IX)) - ((lset_t)1 << (POLICY_SHUNT0_IX)) + ((lset_t)1 << (POLICY_SHUNT1_IX) )); | |||
| 1151 | conn->policy |= POLICY_TUNNEL((lset_t)1 << (POLICY_TUNNEL_IX)) | POLICY_SHUNT_TRAP(0 * ((lset_t)1 << (POLICY_SHUNT0_IX))); | |||
| 1152 | break; | |||
| 1153 | ||||
| 1154 | case KS_TRANSPORT: | |||
| 1155 | conn->policy &= ~POLICY_TUNNEL((lset_t)1 << (POLICY_TUNNEL_IX)) & ~POLICY_SHUNT_MASK(((lset_t)1 << (POLICY_SHUNT1_IX)) - ((lset_t)1 << (POLICY_SHUNT0_IX)) + ((lset_t)1 << (POLICY_SHUNT1_IX) )); | |||
| 1156 | conn->policy |= POLICY_SHUNT_TRAP(0 * ((lset_t)1 << (POLICY_SHUNT0_IX))); | |||
| 1157 | break; | |||
| 1158 | ||||
| 1159 | case KS_PASSTHROUGH: | |||
| 1160 | conn->policy &= | |||
| 1161 | ~(POLICY_ENCRYPT((lset_t)1 << (POLICY_ENCRYPT_IX)) | POLICY_AUTHENTICATE((lset_t)1 << (POLICY_AUTHENTICATE_IX)) | | |||
| 1162 | POLICY_TUNNEL((lset_t)1 << (POLICY_TUNNEL_IX)) | POLICY_RSASIG((lset_t)1 << (POLICY_RSASIG_IX)) | | |||
| 1163 | POLICY_SHUNT_MASK(((lset_t)1 << (POLICY_SHUNT1_IX)) - ((lset_t)1 << (POLICY_SHUNT0_IX)) + ((lset_t)1 << (POLICY_SHUNT1_IX) ))); | |||
| 1164 | conn->policy |= POLICY_SHUNT_PASS(1 * ((lset_t)1 << (POLICY_SHUNT0_IX))); | |||
| 1165 | break; | |||
| 1166 | ||||
| 1167 | case KS_DROP: | |||
| 1168 | conn->policy &= | |||
| 1169 | ~(POLICY_ENCRYPT((lset_t)1 << (POLICY_ENCRYPT_IX)) | POLICY_AUTHENTICATE((lset_t)1 << (POLICY_AUTHENTICATE_IX)) | | |||
| 1170 | POLICY_TUNNEL((lset_t)1 << (POLICY_TUNNEL_IX)) | POLICY_RSASIG((lset_t)1 << (POLICY_RSASIG_IX)) | | |||
| 1171 | POLICY_SHUNT_MASK(((lset_t)1 << (POLICY_SHUNT1_IX)) - ((lset_t)1 << (POLICY_SHUNT0_IX)) + ((lset_t)1 << (POLICY_SHUNT1_IX) ))); | |||
| 1172 | conn->policy |= POLICY_SHUNT_DROP(2 * ((lset_t)1 << (POLICY_SHUNT0_IX))); | |||
| 1173 | break; | |||
| 1174 | ||||
| 1175 | case KS_REJECT: | |||
| 1176 | conn->policy &= | |||
| 1177 | ~(POLICY_ENCRYPT((lset_t)1 << (POLICY_ENCRYPT_IX)) | POLICY_AUTHENTICATE((lset_t)1 << (POLICY_AUTHENTICATE_IX)) | | |||
| 1178 | POLICY_TUNNEL((lset_t)1 << (POLICY_TUNNEL_IX)) | POLICY_RSASIG((lset_t)1 << (POLICY_RSASIG_IX)) | | |||
| 1179 | POLICY_SHUNT_MASK(((lset_t)1 << (POLICY_SHUNT1_IX)) - ((lset_t)1 << (POLICY_SHUNT0_IX)) + ((lset_t)1 << (POLICY_SHUNT1_IX) ))); | |||
| 1180 | conn->policy |= POLICY_SHUNT_REJECT(3 * ((lset_t)1 << (POLICY_SHUNT0_IX))); | |||
| 1181 | break; | |||
| 1182 | } | |||
| 1183 | } | |||
| 1184 | ||||
| 1185 | if (conn->options_set[KNCF_FAILURESHUNT]) { | |||
| 1186 | conn->policy &= ~POLICY_FAIL_MASK(((lset_t)1 << (POLICY_FAIL1_IX)) - ((lset_t)1 << (POLICY_FAIL0_IX)) + ((lset_t)1 << (POLICY_FAIL1_IX))); | |||
| 1187 | switch (conn->options[KNCF_FAILURESHUNT]) { | |||
| 1188 | case KFS_FAIL_NONE: | |||
| 1189 | conn->policy |= POLICY_FAIL_NONE(0 * ((lset_t)1 << (POLICY_FAIL0_IX))); | |||
| 1190 | break; | |||
| 1191 | case KFS_FAIL_PASS: | |||
| 1192 | conn->policy |= POLICY_FAIL_PASS(1 * ((lset_t)1 << (POLICY_FAIL0_IX))); | |||
| 1193 | break; | |||
| 1194 | case KFS_FAIL_DROP: | |||
| 1195 | conn->policy |= POLICY_FAIL_DROP(2 * ((lset_t)1 << (POLICY_FAIL0_IX))); | |||
| 1196 | break; | |||
| 1197 | case KFS_FAIL_REJECT: | |||
| 1198 | conn->policy |= POLICY_FAIL_REJECT(3 * ((lset_t)1 << (POLICY_FAIL0_IX))); | |||
| 1199 | break; | |||
| 1200 | } | |||
| 1201 | } | |||
| 1202 | ||||
| 1203 | if (conn->options_set[KNCF_NEGOTIATIONSHUNT]) { | |||
| 1204 | switch (conn->options[KNCF_NEGOTIATIONSHUNT]) { | |||
| 1205 | case KNS_FAIL_PASS: | |||
| 1206 | conn->policy |= POLICY_NEGO_PASS((lset_t)1 << (POLICY_NEGO_PASS_IX)); | |||
| 1207 | break; | |||
| 1208 | case KNS_FAIL_DROP: | |||
| 1209 | conn->policy &= ~POLICY_NEGO_PASS((lset_t)1 << (POLICY_NEGO_PASS_IX)); | |||
| 1210 | break; | |||
| 1211 | } | |||
| 1212 | } | |||
| 1213 | ||||
| 1214 | KW_POLICY_FLAG(KNCF_COMPRESS, POLICY_COMPRESS){ if (conn->options_set[KNCF_COMPRESS]) conn->policy = ( conn->policy & ~(((lset_t)1 << (POLICY_COMPRESS_IX )))) | (conn->options[KNCF_COMPRESS] ? (((lset_t)1 << (POLICY_COMPRESS_IX))) : ((lset_t)0)); }; | |||
| 1215 | KW_POLICY_FLAG(KNCF_PFS, POLICY_PFS){ if (conn->options_set[KNCF_PFS]) conn->policy = (conn ->policy & ~(((lset_t)1 << (POLICY_PFS_IX)))) | ( conn->options[KNCF_PFS] ? (((lset_t)1 << (POLICY_PFS_IX ))) : ((lset_t)0)); }; | |||
| 1216 | ||||
| 1217 | /* reset authby= flags */ | |||
| 1218 | if (conn->strings_set[KSCF_AUTHBY]) { | |||
| 1219 | ||||
| 1220 | conn->policy &= ~POLICY_ID_AUTH_MASK(((lset_t)1 << (POLICY_AUTH_NULL_IX)) - ((lset_t)1 << (POLICY_PSK_IX)) + ((lset_t)1 << (POLICY_AUTH_NULL_IX) )); | |||
| 1221 | conn->sighash_policy = LEMPTY((lset_t)0); | |||
| 1222 | } | |||
| 1223 | ||||
| 1224 | KW_POLICY_NEGATIVE_FLAG(KNCF_IKEPAD, POLICY_NO_IKEPAD){ if (conn->options_set[KNCF_IKEPAD]) { conn->policy = ( conn->policy & ~(((lset_t)1 << (POLICY_NO_IKEPAD_IX )))) | (!conn->options[KNCF_IKEPAD] ? (((lset_t)1 << (POLICY_NO_IKEPAD_IX))) : ((lset_t)0)); } }; | |||
| 1225 | ||||
| 1226 | KW_POLICY_NEGATIVE_FLAG(KNCF_REKEY, POLICY_DONT_REKEY){ if (conn->options_set[KNCF_REKEY]) { conn->policy = ( conn->policy & ~(((lset_t)1 << (POLICY_DONT_REKEY_IX )))) | (!conn->options[KNCF_REKEY] ? (((lset_t)1 << ( POLICY_DONT_REKEY_IX))) : ((lset_t)0)); } }; | |||
| 1227 | KW_POLICY_FLAG(KNCF_REAUTH, POLICY_REAUTH){ if (conn->options_set[KNCF_REAUTH]) conn->policy = (conn ->policy & ~(((lset_t)1 << (POLICY_REAUTH_IX)))) | (conn->options[KNCF_REAUTH] ? (((lset_t)1 << (POLICY_REAUTH_IX ))) : ((lset_t)0)); }; | |||
| 1228 | ||||
| 1229 | KW_POLICY_FLAG(KNCF_AGGRMODE, POLICY_AGGRESSIVE){ if (conn->options_set[KNCF_AGGRMODE]) conn->policy = ( conn->policy & ~(((lset_t)1 << (POLICY_AGGRESSIVE_IX )))) | (conn->options[KNCF_AGGRMODE] ? (((lset_t)1 << (POLICY_AGGRESSIVE_IX))) : ((lset_t)0)); }; | |||
| 1230 | ||||
| 1231 | KW_POLICY_FLAG(KNCF_MODECONFIGPULL, POLICY_MODECFG_PULL){ if (conn->options_set[KNCF_MODECONFIGPULL]) conn->policy = (conn->policy & ~(((lset_t)1 << (POLICY_MODECFG_PULL_IX )))) | (conn->options[KNCF_MODECONFIGPULL] ? (((lset_t)1 << (POLICY_MODECFG_PULL_IX))) : ((lset_t)0)); }; | |||
| 1232 | ||||
| 1233 | KW_POLICY_FLAG(KNCF_OVERLAPIP, POLICY_OVERLAPIP){ if (conn->options_set[KNCF_OVERLAPIP]) conn->policy = (conn->policy & ~(((lset_t)1 << (POLICY_OVERLAPIP_IX )))) | (conn->options[KNCF_OVERLAPIP] ? (((lset_t)1 << (POLICY_OVERLAPIP_IX))) : ((lset_t)0)); }; | |||
| 1234 | ||||
| 1235 | KW_POLICY_FLAG(KNCF_IKEv2_ALLOW_NARROWING,{ if (conn->options_set[KNCF_IKEv2_ALLOW_NARROWING]) conn-> policy = (conn->policy & ~(((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX )))) | (conn->options[KNCF_IKEv2_ALLOW_NARROWING] ? (((lset_t )1 << (POLICY_IKEV2_ALLOW_NARROWING_IX))) : ((lset_t)0) ); } | |||
| 1236 | POLICY_IKEV2_ALLOW_NARROWING){ if (conn->options_set[KNCF_IKEv2_ALLOW_NARROWING]) conn-> policy = (conn->policy & ~(((lset_t)1 << (POLICY_IKEV2_ALLOW_NARROWING_IX )))) | (conn->options[KNCF_IKEv2_ALLOW_NARROWING] ? (((lset_t )1 << (POLICY_IKEV2_ALLOW_NARROWING_IX))) : ((lset_t)0) ); }; | |||
| 1237 | ||||
| 1238 | KW_POLICY_FLAG(KNCF_MOBIKE, POLICY_MOBIKE){ if (conn->options_set[KNCF_MOBIKE]) conn->policy = (conn ->policy & ~(((lset_t)1 << (POLICY_MOBIKE_IX)))) | (conn->options[KNCF_MOBIKE] ? (((lset_t)1 << (POLICY_MOBIKE_IX ))) : ((lset_t)0)); }; | |||
| 1239 | ||||
| 1240 | KW_POLICY_FLAG(KNCF_IKEv2_PAM_AUTHORIZE,{ if (conn->options_set[KNCF_IKEv2_PAM_AUTHORIZE]) conn-> policy = (conn->policy & ~(((lset_t)1 << (POLICY_IKEV2_PAM_AUTHORIZE_IX )))) | (conn->options[KNCF_IKEv2_PAM_AUTHORIZE] ? (((lset_t )1 << (POLICY_IKEV2_PAM_AUTHORIZE_IX))) : ((lset_t)0)); } | |||
| 1241 | POLICY_IKEV2_PAM_AUTHORIZE){ if (conn->options_set[KNCF_IKEv2_PAM_AUTHORIZE]) conn-> policy = (conn->policy & ~(((lset_t)1 << (POLICY_IKEV2_PAM_AUTHORIZE_IX )))) | (conn->options[KNCF_IKEv2_PAM_AUTHORIZE] ? (((lset_t )1 << (POLICY_IKEV2_PAM_AUTHORIZE_IX))) : ((lset_t)0)); }; | |||
| 1242 | ||||
| 1243 | KW_POLICY_FLAG(KNCF_DECAP_DSCP, POLICY_DECAP_DSCP){ if (conn->options_set[KNCF_DECAP_DSCP]) conn->policy = (conn->policy & ~(((lset_t)1 << (POLICY_DECAP_DSCP_IX )))) | (conn->options[KNCF_DECAP_DSCP] ? (((lset_t)1 << (POLICY_DECAP_DSCP_IX))) : ((lset_t)0)); }; | |||
| 1244 | KW_POLICY_FLAG(KNCF_NOPMTUDISC, POLICY_NOPMTUDISC){ if (conn->options_set[KNCF_NOPMTUDISC]) conn->policy = (conn->policy & ~(((lset_t)1 << (POLICY_NOPMTUDISC_IX )))) | (conn->options[KNCF_NOPMTUDISC] ? (((lset_t)1 << (POLICY_NOPMTUDISC_IX))) : ((lset_t)0)); }; | |||
| 1245 | KW_POLICY_FLAG(KNCF_MSDH_DOWNGRADE, POLICY_MSDH_DOWNGRADE){ if (conn->options_set[KNCF_MSDH_DOWNGRADE]) conn->policy = (conn->policy & ~(((lset_t)1 << (POLICY_MSDH_DOWNGRADE_IX )))) | (conn->options[KNCF_MSDH_DOWNGRADE] ? (((lset_t)1 << (POLICY_MSDH_DOWNGRADE_IX))) : ((lset_t)0)); }; | |||
| 1246 | KW_POLICY_FLAG(KNCF_DNS_MATCH_ID, POLICY_DNS_MATCH_ID){ if (conn->options_set[KNCF_DNS_MATCH_ID]) conn->policy = (conn->policy & ~(((lset_t)1 << (POLICY_DNS_MATCH_ID_IX )))) | (conn->options[KNCF_DNS_MATCH_ID] ? (((lset_t)1 << (POLICY_DNS_MATCH_ID_IX))) : ((lset_t)0)); }; | |||
| 1247 | KW_POLICY_FLAG(KNCF_SHA2_TRUNCBUG, POLICY_SHA2_TRUNCBUG){ if (conn->options_set[KNCF_SHA2_TRUNCBUG]) conn->policy = (conn->policy & ~(((lset_t)1 << (POLICY_SHA2_TRUNCBUG_IX )))) | (conn->options[KNCF_SHA2_TRUNCBUG] ? (((lset_t)1 << (POLICY_SHA2_TRUNCBUG_IX))) : ((lset_t)0)); }; | |||
| 1248 | ||||
| 1249 | if (conn->options_set[KNCF_SAN_ON_CERT]) { | |||
| 1250 | if (!conn->options[KNCF_SAN_ON_CERT]) | |||
| 1251 | conn->policy |= POLICY_ALLOW_NO_SAN((lset_t)1 << (POLICY_ALLOW_NO_SAN_IX)); | |||
| 1252 | } | |||
| 1253 | ||||
| 1254 | /* ??? sometimes (when? why?) the member is already set */ | |||
| 1255 | ||||
| 1256 | # define str_to_conn(member, kscf) { \ | |||
| 1257 | if (conn->strings_set[kscf]) { \ | |||
| 1258 | pfreeany(conn->member){ typeof(conn->member) *pp_ = &(conn->member); if ( *pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }; \ | |||
| 1259 | conn->member = clone_str(conn->strings[kscf], #kscf)((conn->strings[kscf]) == ((void*)0) ? ((void*)0) : clone_bytes ((conn->strings[kscf]), strlen((conn->strings[kscf])) + 1, (#kscf))); \ | |||
| 1260 | } \ | |||
| 1261 | } | |||
| 1262 | ||||
| 1263 | str_to_conn(connalias, KSCF_CONNALIAS); | |||
| 1264 | ||||
| 1265 | str_to_conn(ike_crypto, KSCF_IKE); | |||
| 1266 | str_to_conn(esp, KSCF_ESP); | |||
| 1267 | ||||
| 1268 | str_to_conn(modecfg_dns, KSCF_MODECFGDNS); | |||
| 1269 | str_to_conn(modecfg_domains, KSCF_MODECFGDOMAINS); | |||
| 1270 | str_to_conn(modecfg_banner, KSCF_MODECFGBANNER); | |||
| 1271 | ||||
| 1272 | #ifdef HAVE_LABELED_IPSEC1 | |||
| 1273 | str_to_conn(policy_label, KSCF_POLICY_LABEL); | |||
| 1274 | if (conn->policy_label != NULL((void*)0)) | |||
| 1275 | starter_log(LOG_LEVEL_DEBUG3, "connection's policy label: %s", | |||
| 1276 | conn->policy_label); | |||
| 1277 | #endif | |||
| 1278 | ||||
| 1279 | str_to_conn(conn_mark_both, KSCF_CONN_MARK_BOTH); | |||
| 1280 | str_to_conn(conn_mark_in, KSCF_CONN_MARK_IN); | |||
| 1281 | str_to_conn(conn_mark_out, KSCF_CONN_MARK_OUT); | |||
| 1282 | str_to_conn(vti_iface, KSCF_VTI_IFACE); | |||
| 1283 | ||||
| 1284 | str_to_conn(redirect_to, KSCF_REDIRECT_TO); | |||
| 1285 | str_to_conn(accept_redirect_to, KSCF_ACCEPT_REDIRECT_TO); | |||
| 1286 | ||||
| 1287 | # undef str_to_conn | |||
| 1288 | ||||
| 1289 | if (conn->options_set[KNCF_PHASE2]) { | |||
| 1290 | conn->policy &= ~(POLICY_AUTHENTICATE((lset_t)1 << (POLICY_AUTHENTICATE_IX)) | POLICY_ENCRYPT((lset_t)1 << (POLICY_ENCRYPT_IX))); | |||
| 1291 | conn->policy |= conn->options[KNCF_PHASE2]; | |||
| 1292 | } | |||
| 1293 | ||||
| 1294 | /* | |||
| 1295 | * This option has really been turned into a boolean, but | |||
| 1296 | * we need the keywords for backwards compatibility for now | |||
| 1297 | */ | |||
| 1298 | if (conn->options_set[KNCF_IKEv2]) { | |||
| 1299 | ||||
| 1300 | switch (conn->options[KNCF_IKEv2]) { | |||
| 1301 | case fo_never: | |||
| 1302 | case fo_permit: | |||
| 1303 | conn->policy |= POLICY_IKEV1_ALLOW((lset_t)1 << (POLICY_IKEV1_ALLOW_IX)); | |||
| 1304 | /* clear any inherited default */ | |||
| 1305 | conn->policy &= ~POLICY_IKEV2_ALLOW((lset_t)1 << (POLICY_IKEV2_ALLOW_IX)); | |||
| 1306 | break; | |||
| 1307 | ||||
| 1308 | case fo_propose: | |||
| 1309 | case fo_insist: | |||
| 1310 | conn->policy |= POLICY_IKEV2_ALLOW((lset_t)1 << (POLICY_IKEV2_ALLOW_IX)); | |||
| 1311 | /* clear any inherited default */ | |||
| 1312 | conn->policy &= ~POLICY_IKEV1_ALLOW((lset_t)1 << (POLICY_IKEV1_ALLOW_IX)); | |||
| 1313 | break; | |||
| 1314 | } | |||
| 1315 | } | |||
| 1316 | ||||
| 1317 | if (conn->options_set[KNCF_SEND_REDIRECT]) { | |||
| 1318 | if (!LIN(POLICY_IKEV1_ALLOW, conn->policy)(((((lset_t)1 << (POLICY_IKEV1_ALLOW_IX))) & (conn-> policy)) == (((lset_t)1 << (POLICY_IKEV1_ALLOW_IX))))) { | |||
| 1319 | switch (conn->options[KNCF_SEND_REDIRECT]) { | |||
| 1320 | case yna_yes: | |||
| 1321 | conn->policy |= POLICY_SEND_REDIRECT_ALWAYS((lset_t)1 << (POLICY_SEND_REDIRECT_ALWAYS_IX)); | |||
| 1322 | if (conn->redirect_to == NULL((void*)0)) { | |||
| 1323 | starter_log(LOG_LEVEL_INFO1, | |||
| 1324 | "redirect-to is not specified, although send-redirect is set to yes"); | |||
| 1325 | } | |||
| 1326 | break; | |||
| 1327 | ||||
| 1328 | case yna_no: | |||
| 1329 | conn->policy |= POLICY_SEND_REDIRECT_NEVER((lset_t)1 << (POLICY_SEND_REDIRECT_NEVER_IX)); | |||
| 1330 | break; | |||
| 1331 | ||||
| 1332 | case yna_auto: | |||
| 1333 | break; | |||
| 1334 | } | |||
| 1335 | } | |||
| 1336 | } | |||
| 1337 | ||||
| 1338 | if (conn->options_set[KNCF_ACCEPT_REDIRECT]) { | |||
| 1339 | if (!LIN(POLICY_IKEV1_ALLOW, conn->policy)(((((lset_t)1 << (POLICY_IKEV1_ALLOW_IX))) & (conn-> policy)) == (((lset_t)1 << (POLICY_IKEV1_ALLOW_IX))))) { | |||
| 1340 | switch (conn->options[KNCF_ACCEPT_REDIRECT]) { | |||
| 1341 | case yna_yes: | |||
| 1342 | conn->policy |= POLICY_ACCEPT_REDIRECT_YES((lset_t)1 << (POLICY_ACCEPT_REDIRECT_YES_IX)); | |||
| 1343 | break; | |||
| 1344 | ||||
| 1345 | /* default policy is no, so there is no POLICY_ACCEPT_REDIRECT_YES | |||
| 1346 | * in policy. | |||
| 1347 | * | |||
| 1348 | * technically the values for this option are yes/no, | |||
| 1349 | * although we use yna option set (we do not want to | |||
| 1350 | * make new yes-no enum) | |||
| 1351 | */ | |||
| 1352 | case yna_auto: | |||
| 1353 | case yna_no: | |||
| 1354 | break; | |||
| 1355 | } | |||
| 1356 | } | |||
| 1357 | } | |||
| 1358 | ||||
| 1359 | if (conn->options_set[KNCF_PPK]) { | |||
| 1360 | lset_t ppk = LEMPTY((lset_t)0); | |||
| 1361 | ||||
| 1362 | if (!(conn->policy & POLICY_IKEV1_ALLOW((lset_t)1 << (POLICY_IKEV1_ALLOW_IX)))) { | |||
| 1363 | switch (conn->options[KNCF_PPK]) { | |||
| 1364 | case fo_propose: | |||
| 1365 | ppk = POLICY_PPK_ALLOW((lset_t)1 << (POLICY_PPK_ALLOW_IX)); | |||
| 1366 | break; | |||
| 1367 | ||||
| 1368 | case fo_permit: | |||
| 1369 | ppk = POLICY_PPK_ALLOW((lset_t)1 << (POLICY_PPK_ALLOW_IX)); | |||
| 1370 | break; | |||
| 1371 | ||||
| 1372 | case fo_insist: | |||
| 1373 | ppk = POLICY_PPK_ALLOW((lset_t)1 << (POLICY_PPK_ALLOW_IX)) | POLICY_PPK_INSIST((lset_t)1 << (POLICY_PPK_INSIST_IX)); | |||
| 1374 | break; | |||
| 1375 | ||||
| 1376 | case fo_never: | |||
| 1377 | break; | |||
| 1378 | } | |||
| 1379 | } | |||
| 1380 | conn->policy = conn->policy | ppk; | |||
| 1381 | } | |||
| 1382 | ||||
| 1383 | if (conn->options_set[KNCF_ESN]) { | |||
| 1384 | conn->policy &= ~(POLICY_ESN_NO((lset_t)1 << (POLICY_ESN_NO_IX)) | POLICY_ESN_YES((lset_t)1 << (POLICY_ESN_YES_IX))); | |||
| 1385 | ||||
| 1386 | switch (conn->options[KNCF_ESN]) { | |||
| 1387 | case ESN_YES: | |||
| 1388 | conn->policy |= POLICY_ESN_YES((lset_t)1 << (POLICY_ESN_YES_IX)); | |||
| 1389 | break; | |||
| 1390 | ||||
| 1391 | case ESN_NO: | |||
| 1392 | /* this is the default for now */ | |||
| 1393 | conn->policy |= POLICY_ESN_NO((lset_t)1 << (POLICY_ESN_NO_IX)); | |||
| 1394 | break; | |||
| 1395 | ||||
| 1396 | case ESN_EITHER: | |||
| 1397 | conn->policy |= POLICY_ESN_NO((lset_t)1 << (POLICY_ESN_NO_IX)) | POLICY_ESN_YES((lset_t)1 << (POLICY_ESN_YES_IX)); | |||
| 1398 | break; | |||
| 1399 | } | |||
| 1400 | } | |||
| 1401 | ||||
| 1402 | if (conn->options_set[KNCF_IKE_FRAG]) { | |||
| 1403 | conn->policy &= ~(POLICY_IKE_FRAG_ALLOW((lset_t)1 << (POLICY_IKE_FRAG_ALLOW_IX)) | POLICY_IKE_FRAG_FORCE((lset_t)1 << (POLICY_IKE_FRAG_FORCE_IX))); | |||
| 1404 | ||||
| 1405 | switch (conn->options[KNCF_IKE_FRAG]) { | |||
| 1406 | case ynf_no: | |||
| 1407 | break; | |||
| 1408 | ||||
| 1409 | case ynf_yes: | |||
| 1410 | /* this is the default */ | |||
| 1411 | conn->policy |= POLICY_IKE_FRAG_ALLOW((lset_t)1 << (POLICY_IKE_FRAG_ALLOW_IX)); | |||
| 1412 | break; | |||
| 1413 | ||||
| 1414 | case ynf_force: | |||
| 1415 | conn->policy |= POLICY_IKE_FRAG_ALLOW((lset_t)1 << (POLICY_IKE_FRAG_ALLOW_IX)) | | |||
| 1416 | POLICY_IKE_FRAG_FORCE((lset_t)1 << (POLICY_IKE_FRAG_FORCE_IX)); | |||
| 1417 | break; | |||
| 1418 | } | |||
| 1419 | } | |||
| 1420 | ||||
| 1421 | /* read in the authby string and translate to policy bits | |||
| 1422 | * this is the symmetric (left+right) version | |||
| 1423 | * there is also leftauthby/rightauthby version stored in 'end' | |||
| 1424 | * | |||
| 1425 | * authby=secret|rsasig|null|never|rsa-HASH | |||
| 1426 | * | |||
| 1427 | * using authby=rsasig results in legacy POLICY_RSASIG_v1_5 and RSA_PSS | |||
| 1428 | * | |||
| 1429 | * HASH needs to use full syntax - eg sha2_256 and not sha256, to avoid | |||
| 1430 | * confusion with sha3_256 | |||
| 1431 | */ | |||
| 1432 | if (conn->strings_set[KSCF_AUTHBY]) { | |||
| 1433 | char *val = strtok(conn->strings[KSCF_AUTHBY], ", "); | |||
| 1434 | ||||
| 1435 | conn->sighash_policy = LEMPTY((lset_t)0); | |||
| 1436 | conn->policy &= ~POLICY_ID_AUTH_MASK(((lset_t)1 << (POLICY_AUTH_NULL_IX)) - ((lset_t)1 << (POLICY_PSK_IX)) + ((lset_t)1 << (POLICY_AUTH_NULL_IX) )); | |||
| 1437 | conn->policy &= ~POLICY_RSASIG_v1_5((lset_t)1 << (POLICY_RSASIG_v1_5_IX)); | |||
| 1438 | ||||
| 1439 | while (val != NULL((void*)0)) { | |||
| 1440 | /* Supported for IKEv1 and IKEv2 */ | |||
| 1441 | if (streq(val, "secret")(strcmp((val), ("secret")) == 0)) { | |||
| 1442 | conn->policy |= POLICY_PSK((lset_t)1 << (POLICY_PSK_IX)); | |||
| 1443 | } else if (streq(val, "rsasig")(strcmp((val), ("rsasig")) == 0) || streq(val, "rsa")(strcmp((val), ("rsa")) == 0)) { | |||
| 1444 | conn->policy |= POLICY_RSASIG((lset_t)1 << (POLICY_RSASIG_IX)); | |||
| 1445 | conn->policy |= POLICY_RSASIG_v1_5((lset_t)1 << (POLICY_RSASIG_v1_5_IX)); | |||
| 1446 | conn->sighash_policy |= POL_SIGHASH_SHA2_256((lset_t)1 << (POL_SIGHASH_SHA2_256_IX)); | |||
| 1447 | conn->sighash_policy |= POL_SIGHASH_SHA2_384((lset_t)1 << (POL_SIGHASH_SHA2_384_IX)); | |||
| 1448 | conn->sighash_policy |= POL_SIGHASH_SHA2_512((lset_t)1 << (POL_SIGHASH_SHA2_512_IX)); | |||
| 1449 | } else if (streq(val, "never")(strcmp((val), ("never")) == 0)) { | |||
| 1450 | conn->policy |= POLICY_AUTH_NEVER((lset_t)1 << (POLICY_AUTH_NEVER_IX)); | |||
| 1451 | /* everything else is only supported for IKEv2 */ | |||
| 1452 | } else if (conn->policy & POLICY_IKEV1_ALLOW((lset_t)1 << (POLICY_IKEV1_ALLOW_IX))) { | |||
| 1453 | starter_error_append(perrl, "ikev1 connection must use authby= of rsasig, secret or never"); | |||
| 1454 | return TRUE1; | |||
| 1455 | } else if (streq(val, "null")(strcmp((val), ("null")) == 0)) { | |||
| 1456 | conn->policy |= POLICY_AUTH_NULL((lset_t)1 << (POLICY_AUTH_NULL_IX)); | |||
| 1457 | } else if (streq(val, "rsa-sha1")(strcmp((val), ("rsa-sha1")) == 0)) { | |||
| 1458 | conn->policy |= POLICY_RSASIG((lset_t)1 << (POLICY_RSASIG_IX)); | |||
| 1459 | conn->policy |= POLICY_RSASIG_v1_5((lset_t)1 << (POLICY_RSASIG_v1_5_IX)); | |||
| 1460 | } else if (streq(val, "rsa-sha2")(strcmp((val), ("rsa-sha2")) == 0)) { | |||
| 1461 | conn->policy |= POLICY_RSASIG((lset_t)1 << (POLICY_RSASIG_IX)); | |||
| 1462 | conn->sighash_policy |= POL_SIGHASH_SHA2_256((lset_t)1 << (POL_SIGHASH_SHA2_256_IX)); | |||
| 1463 | conn->sighash_policy |= POL_SIGHASH_SHA2_384((lset_t)1 << (POL_SIGHASH_SHA2_384_IX)); | |||
| 1464 | conn->sighash_policy |= POL_SIGHASH_SHA2_512((lset_t)1 << (POL_SIGHASH_SHA2_512_IX)); | |||
| 1465 | } else if (streq(val, "rsa-sha2_256")(strcmp((val), ("rsa-sha2_256")) == 0)) { | |||
| 1466 | conn->sighash_policy |= POL_SIGHASH_SHA2_256((lset_t)1 << (POL_SIGHASH_SHA2_256_IX)); | |||
| 1467 | } else if (streq(val, "rsa-sha2_384")(strcmp((val), ("rsa-sha2_384")) == 0)) { | |||
| 1468 | conn->policy |= POLICY_RSASIG((lset_t)1 << (POLICY_RSASIG_IX)); | |||
| 1469 | conn->sighash_policy |= POL_SIGHASH_SHA2_384((lset_t)1 << (POL_SIGHASH_SHA2_384_IX)); | |||
| 1470 | } else if (streq(val, "rsa-sha2_512")(strcmp((val), ("rsa-sha2_512")) == 0)) { | |||
| 1471 | conn->policy |= POLICY_RSASIG((lset_t)1 << (POLICY_RSASIG_IX)); | |||
| 1472 | conn->sighash_policy |= POL_SIGHASH_SHA2_512((lset_t)1 << (POL_SIGHASH_SHA2_512_IX)); | |||
| 1473 | } else if (streq(val, "ecdsa")(strcmp((val), ("ecdsa")) == 0) || streq(val, "ecdsa-sha2")(strcmp((val), ("ecdsa-sha2")) == 0)) { | |||
| 1474 | conn->policy |= POLICY_ECDSA((lset_t)1 << (POLICY_ECDSA_IX)); | |||
| 1475 | conn->sighash_policy |= POL_SIGHASH_SHA2_256((lset_t)1 << (POL_SIGHASH_SHA2_256_IX)); | |||
| 1476 | conn->sighash_policy |= POL_SIGHASH_SHA2_384((lset_t)1 << (POL_SIGHASH_SHA2_384_IX)); | |||
| 1477 | conn->sighash_policy |= POL_SIGHASH_SHA2_512((lset_t)1 << (POL_SIGHASH_SHA2_512_IX)); | |||
| 1478 | } else if (streq(val, "ecdsa-sha2_256")(strcmp((val), ("ecdsa-sha2_256")) == 0)) { | |||
| 1479 | conn->policy |= POLICY_ECDSA((lset_t)1 << (POLICY_ECDSA_IX)); | |||
| 1480 | conn->sighash_policy |= POL_SIGHASH_SHA2_256((lset_t)1 << (POL_SIGHASH_SHA2_256_IX)); | |||
| 1481 | } else if (streq(val, "ecdsa-sha2_384")(strcmp((val), ("ecdsa-sha2_384")) == 0)) { | |||
| 1482 | conn->policy |= POLICY_ECDSA((lset_t)1 << (POLICY_ECDSA_IX)); | |||
| 1483 | conn->sighash_policy |= POL_SIGHASH_SHA2_384((lset_t)1 << (POL_SIGHASH_SHA2_384_IX)); | |||
| 1484 | } else if (streq(val, "ecdsa-sha2_512")(strcmp((val), ("ecdsa-sha2_512")) == 0)) { | |||
| 1485 | conn->policy |= POLICY_ECDSA((lset_t)1 << (POLICY_ECDSA_IX)); | |||
| 1486 | conn->sighash_policy |= POL_SIGHASH_SHA2_512((lset_t)1 << (POL_SIGHASH_SHA2_512_IX)); | |||
| 1487 | } else if (streq(val, "ecdsa-sha1")(strcmp((val), ("ecdsa-sha1")) == 0)) { | |||
| 1488 | starter_error_append(perrl, "authby=ecdsa cannot use sha1, only sha2"); | |||
| 1489 | return TRUE1; | |||
| 1490 | } else { | |||
| 1491 | starter_error_append(perrl, "connection authby= value is unknown"); | |||
| 1492 | return TRUE1; | |||
| 1493 | } | |||
| 1494 | val = strtok(NULL((void*)0), ", "); | |||
| 1495 | } | |||
| 1496 | } | |||
| 1497 | ||||
| 1498 | /* | |||
| 1499 | * some options are set as part of our default, but | |||
| 1500 | * some make no sense for shunts, so remove those again | |||
| 1501 | */ | |||
| 1502 | if (NEVER_NEGOTIATE(conn->policy)(((((conn->policy)) & (((lset_t)1 << (POLICY_ENCRYPT_IX )) | ((lset_t)1 << (POLICY_AUTHENTICATE_IX)))) == ((lset_t )0)))) { | |||
| 1503 | /* remove IPsec related options */ | |||
| 1504 | conn->policy &= ~(POLICY_PFS((lset_t)1 << (POLICY_PFS_IX)) | POLICY_COMPRESS((lset_t)1 << (POLICY_COMPRESS_IX)) | POLICY_ESN_NO((lset_t)1 << (POLICY_ESN_NO_IX)) | | |||
| 1505 | POLICY_ESN_YES((lset_t)1 << (POLICY_ESN_YES_IX)) | POLICY_DECAP_DSCP((lset_t)1 << (POLICY_DECAP_DSCP_IX)) | | |||
| 1506 | POLICY_NOPMTUDISC((lset_t)1 << (POLICY_NOPMTUDISC_IX))) & | |||
| 1507 | /* remove IKE related options */ | |||
| 1508 | ~(POLICY_IKEV1_ALLOW((lset_t)1 << (POLICY_IKEV1_ALLOW_IX)) | POLICY_IKEV2_ALLOW((lset_t)1 << (POLICY_IKEV2_ALLOW_IX)) | | |||
| 1509 | POLICY_IKE_FRAG_ALLOW((lset_t)1 << (POLICY_IKE_FRAG_ALLOW_IX)) | POLICY_IKE_FRAG_FORCE((lset_t)1 << (POLICY_IKE_FRAG_FORCE_IX))); | |||
| 1510 | } | |||
| 1511 | ||||
| 1512 | err |= validate_end(conn, &conn->left, "left", perrl, logger); | |||
| 1513 | err |= validate_end(conn, &conn->right, "right", perrl, logger); | |||
| 1514 | ||||
| 1515 | /* | |||
| 1516 | * TODO: | |||
| 1517 | * verify both ends are using the same inet family, if one end | |||
| 1518 | * is "%any" or "%defaultroute", then perhaps adjust it. | |||
| 1519 | * ensource this for left,leftnexthop,right,rightnexthop | |||
| 1520 | */ | |||
| 1521 | ||||
| 1522 | if (conn->options_set[KNCF_AUTO]) | |||
| 1523 | conn->desired_state = conn->options[KNCF_AUTO]; | |||
| 1524 | ||||
| 1525 | return err; | |||
| 1526 | } | |||
| 1527 | ||||
| 1528 | static void copy_conn_default(struct starter_conn *conn, | |||
| 1529 | const struct starter_conn *def) | |||
| 1530 | { | |||
| 1531 | /* structure copy to start */ | |||
| 1532 | *conn = *def; | |||
| 1533 | ||||
| 1534 | /* unlink it */ | |||
| 1535 | conn->link.tqe_next = NULL((void*)0); | |||
| 1536 | conn->link.tqe_prev = NULL((void*)0); | |||
| 1537 | ||||
| 1538 | /* Unshare all strings */ | |||
| 1539 | ||||
| 1540 | /* | |||
| 1541 | * Note: string fields in struct starter_end and struct starter_conn | |||
| 1542 | * should correspond to STR_FIELD calls in copy_conn_default() and confread_free_conn. | |||
| 1543 | */ | |||
| 1544 | ||||
| 1545 | assert(conn->connalias == NULL)((void) sizeof ((conn->connalias == ((void*)0)) ? 1 : 0), __extension__ ({ if (conn->connalias == ((void*)0)) ; else __assert_fail ("conn->connalias == NULL", "/home/build/libreswan/lib/libipsecconf/confread.c" , 1545, __extension__ __PRETTY_FUNCTION__); })); | |||
| 1546 | ||||
| 1547 | # define STR_FIELD(f) { conn->f = clone_str(conn->f, #f)((conn->f) == ((void*)0) ? ((void*)0) : clone_bytes((conn-> f), strlen((conn->f)) + 1, (#f))); } | |||
| 1548 | ||||
| 1549 | STR_FIELD(name); | |||
| 1550 | STR_FIELD(connalias); | |||
| 1551 | ||||
| 1552 | STR_FIELD(ike_crypto); | |||
| 1553 | STR_FIELD(esp); | |||
| 1554 | ||||
| 1555 | STR_FIELD(modecfg_dns); | |||
| 1556 | STR_FIELD(modecfg_domains); | |||
| 1557 | STR_FIELD(modecfg_banner); | |||
| 1558 | STR_FIELD(conn_mark_both); | |||
| 1559 | STR_FIELD(conn_mark_in); | |||
| 1560 | STR_FIELD(conn_mark_out); | |||
| 1561 | STR_FIELD(policy_label); | |||
| 1562 | STR_FIELD(conn_mark_both); | |||
| 1563 | STR_FIELD(conn_mark_in); | |||
| 1564 | STR_FIELD(conn_mark_out); | |||
| 1565 | STR_FIELD(vti_iface); | |||
| 1566 | STR_FIELD(redirect_to); | |||
| 1567 | STR_FIELD(accept_redirect_to); | |||
| 1568 | ||||
| 1569 | for (unsigned i = 0; i < elemsof(conn->strings)(sizeof(conn->strings) / sizeof(*(conn->strings))); i++) | |||
| 1570 | STR_FIELD(strings[i]); | |||
| 1571 | ||||
| 1572 | /* handle starter_end strings */ | |||
| 1573 | ||||
| 1574 | # define STR_FIELD_END(f) { STR_FIELD(left.f); STR_FIELD(right.f); } | |||
| 1575 | ||||
| 1576 | STR_FIELD_END(iface); | |||
| 1577 | STR_FIELD_END(id); | |||
| 1578 | STR_FIELD_END(rsakey1); | |||
| 1579 | STR_FIELD_END(rsakey2); | |||
| 1580 | STR_FIELD_END(virt); | |||
| 1581 | STR_FIELD_END(certx); | |||
| 1582 | STR_FIELD_END(ckaid); | |||
| 1583 | STR_FIELD_END(ca); | |||
| 1584 | STR_FIELD_END(updown); | |||
| 1585 | ||||
| 1586 | for (unsigned i = 0; i < elemsof(conn->left.strings)(sizeof(conn->left.strings) / sizeof(*(conn->left.strings ))); i++) | |||
| 1587 | STR_FIELD_END(strings[i]); | |||
| 1588 | ||||
| 1589 | # undef STR_FIELD_END | |||
| 1590 | ||||
| 1591 | # undef STR_FIELD | |||
| 1592 | } | |||
| 1593 | ||||
| 1594 | static struct starter_conn *alloc_add_conn(struct starter_config *cfg, const char *name) | |||
| 1595 | { | |||
| 1596 | struct starter_conn *conn = alloc_thing(struct starter_conn, "add_conn starter_conn")((struct starter_conn*) alloc_bytes(sizeof(struct starter_conn ), ("add_conn starter_conn"))); | |||
| 1597 | ||||
| 1598 | copy_conn_default(conn, &cfg->conn_default); | |||
| 1599 | assert(conn->name == NULL)((void) sizeof ((conn->name == ((void*)0)) ? 1 : 0), __extension__ ({ if (conn->name == ((void*)0)) ; else __assert_fail ("conn->name == NULL" , "/home/build/libreswan/lib/libipsecconf/confread.c", 1599, __extension__ __PRETTY_FUNCTION__); })); | |||
| 1600 | conn->name = clone_str(name, "add conn name")((name) == ((void*)0) ? ((void*)0) : clone_bytes((name), strlen ((name)) + 1, ("add conn name"))); | |||
| 1601 | conn->desired_state = STARTUP_IGNORE; | |||
| 1602 | conn->state = STATE_FAILED; | |||
| 1603 | ||||
| 1604 | TAILQ_INIT(&conn->comments)do { (&conn->comments)->tqh_first = ((void*)0); (& conn->comments)->tqh_last = &(&conn->comments )->tqh_first; } while ( 0); | |||
| 1605 | ||||
| 1606 | TAILQ_INSERT_TAIL(&cfg->conns, conn, link)do { (conn)->link.tqe_next = ((void*)0); (conn)->link.tqe_prev = (&cfg->conns)->tqh_last; *(&cfg->conns)-> tqh_last = (conn); (&cfg->conns)->tqh_last = &( conn)->link.tqe_next; } while ( 0); | |||
| 1607 | return conn; | |||
| 1608 | } | |||
| 1609 | ||||
| 1610 | static bool_Bool init_load_conn(struct starter_config *cfg, | |||
| 1611 | const struct config_parsed *cfgp, | |||
| 1612 | struct section_list *sconn, | |||
| 1613 | bool_Bool defaultconn, | |||
| 1614 | starter_errors_t *perrl, | |||
| 1615 | struct logger *logger) | |||
| 1616 | { | |||
| 1617 | starter_log(LOG_LEVEL_DEBUG3, "Loading conn %s", sconn->name); | |||
| 1618 | ||||
| 1619 | struct starter_conn *conn = alloc_add_conn(cfg, sconn->name); | |||
| 1620 | ||||
| 1621 | bool_Bool connerr = load_conn(conn, cfgp, sconn, TRUE1, | |||
| 1622 | defaultconn, perrl, logger); | |||
| 1623 | ||||
| 1624 | if (connerr) { | |||
| 1625 | starter_log(LOG_LEVEL_INFO1, "while loading '%s': %s", | |||
| 1626 | sconn->name, perrl->errors); | |||
| 1627 | /* ??? should caller not log perrl? */ | |||
| 1628 | } else { | |||
| 1629 | conn->state = STATE_LOADED; | |||
| 1630 | } | |||
| 1631 | return connerr; | |||
| 1632 | } | |||
| 1633 | ||||
| 1634 | struct starter_config *confread_load(const char *file, | |||
| 1635 | starter_errors_t *perrl, | |||
| 1636 | const char *ctlsocket, | |||
| 1637 | bool_Bool setuponly, | |||
| 1638 | struct logger *logger) | |||
| 1639 | { | |||
| 1640 | bool_Bool err = FALSE0; | |||
| 1641 | ||||
| 1642 | /** | |||
| 1643 | * Load file | |||
| 1644 | */ | |||
| 1645 | struct config_parsed *cfgp = parser_load_conf(file, perrl); | |||
| 1646 | ||||
| 1647 | if (cfgp == NULL((void*)0)) | |||
| 1648 | return NULL((void*)0); | |||
| 1649 | ||||
| 1650 | struct starter_config *cfg = alloc_thing(struct starter_config, "starter_config cfg")((struct starter_config*) alloc_bytes(sizeof(struct starter_config ), ("starter_config cfg"))); | |||
| 1651 | ||||
| 1652 | /** | |||
| 1653 | * Set default values | |||
| 1654 | */ | |||
| 1655 | ipsecconf_default_values(cfg); | |||
| 1656 | ||||
| 1657 | if (ctlsocket != NULL((void*)0)) { | |||
| 1658 | pfree(cfg->ctlsocket); | |||
| 1659 | cfg->ctlsocket = clone_str(ctlsocket, "default ctlsocket")((ctlsocket) == ((void*)0) ? ((void*)0) : clone_bytes((ctlsocket ), strlen((ctlsocket)) + 1, ("default ctlsocket"))); | |||
| 1660 | } | |||
| 1661 | ||||
| 1662 | /** | |||
| 1663 | * Load setup | |||
| 1664 | */ | |||
| 1665 | err |= load_setup(cfg, cfgp); | |||
| 1666 | ||||
| 1667 | if (err) { | |||
| 1668 | parser_free_conf(cfgp); | |||
| 1669 | confread_free(cfg); | |||
| 1670 | return NULL((void*)0); | |||
| 1671 | } | |||
| 1672 | ||||
| 1673 | if (!setuponly) { | |||
| 1674 | #ifdef USE_DNSSEC1 | |||
| 1675 | unbound_sync_init(cfg->setup.options[KBF_DO_DNSSEC], | |||
| 1676 | cfg->setup.strings[KSF_PLUTO_DNSSEC_ROOTKEY_FILE], | |||
| 1677 | cfg->setup.strings[KSF_PLUTO_DNSSEC_ANCHORS], | |||
| 1678 | logger); | |||
| 1679 | #endif | |||
| 1680 | ||||
| 1681 | /* | |||
| 1682 | * Load %default conn | |||
| 1683 | * ??? is it correct to accept multiple %default conns? | |||
| 1684 | */ | |||
| 1685 | for (struct section_list *sconn = cfgp->sections.tqh_first; (!err) && sconn != NULL((void*)0); | |||
| 1686 | sconn = sconn->link.tqe_next) { | |||
| 1687 | if (streq(sconn->name, "%default")(strcmp((sconn->name), ("%default")) == 0)) { | |||
| 1688 | starter_log(LOG_LEVEL_DEBUG3, | |||
| 1689 | "Loading default conn"); | |||
| 1690 | err |= load_conn(&cfg->conn_default, | |||
| 1691 | cfgp, sconn, false0, | |||
| 1692 | true1/*default conn*/, | |||
| 1693 | perrl, logger); | |||
| 1694 | } | |||
| 1695 | } | |||
| 1696 | ||||
| 1697 | /* | |||
| 1698 | * Load other conns | |||
| 1699 | */ | |||
| 1700 | for (struct section_list *sconn = cfgp->sections.tqh_first; sconn != NULL((void*)0); | |||
| 1701 | sconn = sconn->link.tqe_next) { | |||
| 1702 | if (!streq(sconn->name, "%default")(strcmp((sconn->name), ("%default")) == 0)) | |||
| 1703 | err |= init_load_conn(cfg, cfgp, sconn, | |||
| 1704 | false0/*default conn*/, | |||
| 1705 | perrl, logger); | |||
| 1706 | } | |||
| 1707 | } | |||
| 1708 | ||||
| 1709 | parser_free_conf(cfgp); | |||
| 1710 | #ifdef USE_DNSSEC1 | |||
| 1711 | unbound_ctx_free(); | |||
| 1712 | #endif | |||
| 1713 | return cfg; | |||
| 1714 | } | |||
| 1715 | ||||
| 1716 | static void confread_free_conn(struct starter_conn *conn) | |||
| 1717 | { | |||
| 1718 | /* Free all strings */ | |||
| 1719 | ||||
| 1720 | /* | |||
| 1721 | * Note: string fields in struct starter_end and struct starter_conn | |||
| 1722 | * should correspond to STR_FIELD calls in copy_conn_default() and confread_free_conn. | |||
| 1723 | */ | |||
| 1724 | ||||
| 1725 | # define STR_FIELD(f) { pfreeany(conn->f){ typeof(conn->f) *pp_ = &(conn->f); if (*pp_ != (( void*)0)) { pfree(*pp_); *pp_ = ((void*)0); } }; } | |||
| 1726 | ||||
| 1727 | STR_FIELD(name); | |||
| 1728 | STR_FIELD(connalias); | |||
| 1729 | ||||
| 1730 | STR_FIELD(ike_crypto); | |||
| 1731 | STR_FIELD(esp); | |||
| 1732 | ||||
| 1733 | STR_FIELD(modecfg_dns); | |||
| 1734 | STR_FIELD(modecfg_domains); | |||
| 1735 | STR_FIELD(modecfg_banner); | |||
| 1736 | STR_FIELD(conn_mark_both); | |||
| 1737 | STR_FIELD(conn_mark_in); | |||
| 1738 | STR_FIELD(conn_mark_out); | |||
| 1739 | STR_FIELD(policy_label); | |||
| 1740 | STR_FIELD(conn_mark_both); | |||
| 1741 | STR_FIELD(conn_mark_in); | |||
| 1742 | STR_FIELD(conn_mark_out); | |||
| 1743 | STR_FIELD(vti_iface); | |||
| 1744 | STR_FIELD(redirect_to); | |||
| 1745 | STR_FIELD(accept_redirect_to); | |||
| 1746 | ||||
| 1747 | for (unsigned i = 0; i < elemsof(conn->strings)(sizeof(conn->strings) / sizeof(*(conn->strings))); i++) | |||
| 1748 | STR_FIELD(strings[i]); | |||
| 1749 | ||||
| 1750 | /* handle starter_end strings */ | |||
| 1751 | ||||
| 1752 | # define STR_FIELD_END(f) { STR_FIELD(left.f); STR_FIELD(right.f); } | |||
| 1753 | ||||
| 1754 | STR_FIELD_END(iface); | |||
| 1755 | STR_FIELD_END(id); | |||
| 1756 | STR_FIELD_END(rsakey1); | |||
| 1757 | STR_FIELD_END(rsakey2); | |||
| 1758 | STR_FIELD_END(virt); | |||
| 1759 | STR_FIELD_END(certx); | |||
| 1760 | STR_FIELD_END(ckaid); | |||
| 1761 | STR_FIELD_END(ca); | |||
| 1762 | STR_FIELD_END(updown); | |||
| 1763 | ||||
| 1764 | for (unsigned i = 0; i < elemsof(conn->left.strings)(sizeof(conn->left.strings) / sizeof(*(conn->left.strings ))); i++) | |||
| 1765 | STR_FIELD_END(strings[i]); | |||
| 1766 | ||||
| 1767 | # undef STR_FIELD_END | |||
| 1768 | ||||
| 1769 | # undef STR_FIELD | |||
| 1770 | } | |||
| 1771 | ||||
| 1772 | void confread_free(struct starter_config *cfg) | |||
| 1773 | { | |||
| 1774 | pfree(cfg->ctlsocket); | |||
| 1775 | ||||
| 1776 | for (unsigned i = 0; i < elemsof(cfg->setup.strings)(sizeof(cfg->setup.strings) / sizeof(*(cfg->setup.strings ))); i++) | |||
| 1777 | pfreeany(cfg->setup.strings[i]){ typeof(cfg->setup.strings[i]) *pp_ = &(cfg->setup .strings[i]); if (*pp_ != ((void*)0)) { pfree(*pp_); *pp_ = ( (void*)0); } }; | |||
| 1778 | ||||
| 1779 | confread_free_conn(&cfg->conn_default); | |||
| 1780 | ||||
| 1781 | for (struct starter_conn *conn = cfg->conns.tqh_first; conn != NULL((void*)0); ) { | |||
| 1782 | struct starter_conn *c = conn; | |||
| 1783 | ||||
| 1784 | conn = conn->link.tqe_next; | |||
| 1785 | confread_free_conn(c); | |||
| 1786 | pfree(c); | |||
| 1787 | } | |||
| 1788 | pfree(cfg); | |||
| 1789 | } |