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