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 | } |