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