]>
Commit | Line | Data |
---|---|---|
4e78b7ad JS |
1 | #!/bin/bash |
2 | ############################################################################### | |
3 | # # | |
4 | # IPFire.org - A linux based firewall # | |
5 | # Copyright (C) 2017 IPFire Network Development Team # | |
6 | # # | |
7 | # This program is free software: you can redistribute it and/or modify # | |
8 | # it under the terms of the GNU General Public License as published by # | |
9 | # the Free Software Foundation, either version 3 of the License, or # | |
10 | # (at your option) any later version. # | |
11 | # # | |
12 | # This program is distributed in the hope that it will be useful, # | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
15 | # GNU General Public License for more details. # | |
16 | # # | |
17 | # You should have received a copy of the GNU General Public License # | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
19 | # # | |
20 | ############################################################################### | |
21 | ||
22 | IPSEC_POOL_CONFIG_SETTINGS="\ | |
23 | DNS_SERVER \ | |
24 | NETWORK \ | |
25 | TYPE" | |
26 | ||
27 | cli_ipsec_pool() { | |
28 | if ipsec_pool_exists ${1}; then | |
29 | local pool=${1} | |
30 | local key=${2} | |
31 | key=${key//-/_} | |
32 | shift 2 | |
33 | ||
34 | case "${key}" in | |
35 | dns_server|network) | |
36 | ipsec_pool_${key} ${pool} "$@" | |
37 | ;; | |
38 | show) | |
39 | cli_ipsec_pool_show "${pool}" | |
40 | exit $? | |
41 | ;; | |
42 | *) | |
43 | error "Unrecognized argument: ${key}" | |
44 | exit ${EXIT_ERROR} | |
45 | ;; | |
46 | esac | |
47 | else | |
48 | local action=${1} | |
49 | shift | |
50 | ||
51 | case "${action}" in | |
52 | new) | |
53 | ipsec_pool_new "$@" | |
54 | ;; | |
55 | destroy) | |
56 | ipsec_pool_destroy "$@" | |
57 | ;; | |
58 | ""|*) | |
59 | if [ -n "${action}" ]; then | |
60 | error "Unrecognized argument: '${action}'" | |
61 | fi | |
62 | exit ${EXIT_ERROR} | |
63 | ;; | |
64 | esac | |
65 | fi | |
66 | } | |
67 | ||
68 | # This function writes all values to a via ${pool} specificated VPN IPsec pool configuration file | |
69 | ipsec_pool_write_config() { | |
70 | assert [ $# -ge 1 ] | |
71 | ||
72 | local pool="${1}" | |
73 | ||
74 | if ! ipsec_pool_exists "${pool}"; then | |
75 | log ERROR "No such VPN IPsec pool: ${pool}" | |
76 | return ${EXIT_ERROR} | |
77 | fi | |
78 | ||
79 | local path="${NETWORK_IPSEC_POOLS_DIR}/${pool}/settings" | |
80 | ||
81 | if ! settings_write "${path}" ${IPSEC_POOL_CONFIG_SETTINGS}; then | |
82 | log ERROR "Could not write configuration settings for VPN IPsec pool ${pool}" | |
83 | return ${EXIT_ERROR} | |
84 | fi | |
85 | ||
86 | if ! ipsec_pool_reload ${pool}; then | |
87 | log WARNING "Could not reload IPsec pool ${pool}" | |
88 | fi | |
89 | ||
90 | # When we get here the writing of the config file was successful | |
91 | return ${EXIT_OK} | |
92 | } | |
93 | ||
94 | # This funtion writes the value for one key to a via ${connection} specificated | |
95 | # VPN IPsec pool configuration file | |
96 | ipsec_pool_write_config_key() { | |
97 | assert [ $# -ge 3 ] | |
98 | ||
99 | local pool=${1} | |
100 | local key=${2} | |
101 | shift 2 | |
102 | ||
103 | local value="$@" | |
104 | ||
105 | if ! ipsec_pool_exists "${pool}"; then | |
106 | log ERROR "No such VPN IPsec pool: ${pool}" | |
107 | return ${EXIT_ERROR} | |
108 | fi | |
109 | ||
110 | log DEBUG "Set '${key}' to new value '${value}' in VPN IPsec pool '${pool}'" | |
111 | ||
112 | local ${IPSEC_POOL_CONFIG_SETTINGS} | |
113 | ||
114 | # Read the config settings | |
115 | if ! ipsec_pool_read_config "${pool}"; then | |
116 | return ${EXIT_ERROR} | |
117 | fi | |
118 | ||
119 | # Set the key to a new value | |
120 | assign "${key}" "${value}" | |
121 | ||
122 | if ! ipsec_pool_write_config "${pool}"; then | |
123 | return ${EXIT_ERROR} | |
124 | fi | |
125 | ||
126 | return ${EXIT_TRUE} | |
127 | } | |
128 | ||
129 | # Reads one or more keys out of a settings file or all if no key is provided. | |
130 | ipsec_pool_read_config() { | |
131 | assert [ $# -ge 1 ] | |
132 | ||
133 | local pool="${1}" | |
134 | shift 1 | |
135 | ||
136 | if ! ipsec_pool_exists "${pool}"; then | |
137 | log ERROR "No such VPN IPsec pool : ${pool}" | |
138 | return ${EXIT_ERROR} | |
139 | fi | |
140 | ||
141 | local args | |
142 | if [ $# -eq 0 ] && [ -n "${IPSEC_POOL_CONFIG_SETTINGS}" ]; then | |
143 | list_append args ${IPSEC_POOL_CONFIG_SETTINGS} | |
144 | else | |
145 | list_append args $@ | |
146 | fi | |
147 | ||
148 | local path="${NETWORK_IPSEC_POOLS_DIR}/${pool}/settings" | |
149 | ||
150 | if ! settings_read "${path}" ${args}; then | |
151 | log ERROR "Could not read settings for VPN IPsec pool ${pool}" | |
152 | return ${EXIT_ERROR} | |
153 | fi | |
154 | } | |
155 | ||
156 | # This function checks if a vpn IPsec pool exists | |
157 | # Returns True when yes and false when not | |
158 | ipsec_pool_exists() { | |
159 | assert [ $# -eq 1 ] | |
160 | ||
161 | local pool=${1} | |
162 | ||
163 | local path="${NETWORK_IPSEC_POOLS_DIR}/${pool}" | |
164 | ||
165 | [ -d "${path}" ] && return ${EXIT_TRUE} || return ${EXIT_FALSE} | |
166 | } | |
167 | ||
168 | # This function checks if a VPN IPsec pool name is valid | |
169 | # Allowed are only A-Za-z0-9 | |
170 | ipsec_pool_check_name() { | |
171 | assert [ $# -eq 1 ] | |
172 | ||
173 | local pool=${1} | |
174 | ||
175 | # These are special words in strongswan | |
176 | if isoneof pool dhcp radius; then | |
177 | return ${EXIT_ERROR} | |
178 | fi | |
179 | ||
180 | [[ "${pool}" =~ [^[:alnum:]$] ]] | |
181 | } | |
182 | ||
183 | ipsec_pool_new() { | |
184 | if [ $# -gt 1 ]; then | |
185 | error "Too many arguments" | |
186 | return ${EXIT_ERROR} | |
187 | fi | |
188 | ||
189 | local pool="${1}" | |
190 | if ! isset pool; then | |
191 | error "Please provide a pool name" | |
192 | return ${EXIT_ERROR} | |
193 | fi | |
194 | ||
195 | # Check for duplicates | |
196 | if ipsec_pool_exists "${pool}"; then | |
197 | error "The VPN IPsec pool ${pool} already exists" | |
198 | return ${EXIT_ERROR} | |
199 | fi | |
200 | ||
201 | # Check if the name of the connection is valid | |
202 | if ipsec_pool_check_name "${pool}"; then | |
203 | error "'${pool}' contains illegal characters" | |
204 | return ${EXIT_ERROR} | |
205 | fi | |
206 | ||
207 | log DEBUG "Creating VPN IPsec pool ${pool}" | |
208 | ||
209 | if ! mkdir -p "${NETWORK_IPSEC_POOLS_DIR}/${pool}"; then | |
210 | log ERROR "Could not create config directory for ${pool}" | |
211 | return ${EXIT_ERROR} | |
212 | fi | |
213 | ||
214 | local ${IPSEC_POOL_CONFIG_SETTINGS} | |
215 | ||
216 | if ! ipsec_pool_write_config "${pool}"; then | |
217 | log ERROR "Could not write new config file" | |
218 | return ${EXIT_ERROR} | |
219 | fi | |
220 | } | |
221 | ||
222 | # Function that deletes based on the passed parameters | |
223 | # one ore more vpn ipsec pools | |
224 | ipsec_pool_destroy() { | |
225 | local pool | |
226 | for pool in $@; do | |
227 | if ! ipsec_pool_exists "${pool}"; then | |
228 | log ERROR "The VPN IPsec pool ${pool} does not exist." | |
229 | continue | |
230 | fi | |
231 | ||
ca0527dd JS |
232 | if [ -f "${NETWORK_IPSEC_SWANCTL_POOLS_DIR}/${pool}.conf" ]; then |
233 | if ! file_delete "${NETWORK_IPSEC_SWANCTL_POOLS_DIR}/${pool}.conf"; then | |
234 | # We going on here to delete at least the configuration directory | |
235 | log ERROR "Could not delete ${NETWORK_IPSEC_SWANCTL_POOLS_DIR}/${pool}.conf" | |
236 | fi | |
237 | fi | |
238 | ||
4e78b7ad JS |
239 | log DEBUG "Deleting VPN IPsec pool ${pool}" |
240 | ||
241 | if ! rm -rf "${NETWORK_IPSEC_POOLS_DIR}/${pool}"; then | |
242 | log ERROR "Deleting the VPN IPsec pool ${pool} was not sucessful" | |
243 | return ${EXIT_ERROR} | |
244 | fi | |
245 | done | |
f5135fb7 JS |
246 | |
247 | ipsec_strongswan_load_pools | |
4e78b7ad JS |
248 | } |
249 | ||
250 | ipsec_pool_set_type() { | |
251 | local pool=${1} | |
252 | local ip=${2} | |
253 | assert isset pool | |
254 | assert isset ip | |
255 | ||
256 | local type=$(ip_detect_protocol ${ip}) | |
257 | ||
258 | if ! isset type; then | |
259 | error "Cannot detect IP protocol of ${ip}" | |
260 | return ${EXIT_ERROR} | |
261 | else | |
262 | log DEBUG "IP protocol of ${ip} is ${type}" | |
263 | if ! ipsec_pool_write_config_key "${pool}" "TYPE" ${type}; then | |
264 | log ERROR "Could not write configuration settings" | |
265 | return ${EXIT_ERROR} | |
266 | fi | |
267 | fi | |
268 | } | |
269 | ||
270 | ipsec_pool_network() { | |
271 | if [ ! $# -eq 2 ]; then | |
272 | log ERROR "Not enough arguments" | |
273 | return ${EXIT_ERROR} | |
274 | fi | |
275 | local pool=${1} | |
276 | local network=${2} | |
277 | ||
278 | local TYPE | |
279 | if ! ipsec_pool_read_config ${pool} "TYPE"; then | |
280 | error "Failed to read configuration settings for pool '${pool}'" | |
281 | return ${EXIT_ERROR} | |
282 | fi | |
283 | ||
284 | if ! isset TYPE; then | |
285 | if ! ip_net_is_valid ${network}; then | |
286 | log ERROR "Network '${network}' is invalid" | |
287 | return ${EXIT_ERROR} | |
288 | fi | |
289 | ||
290 | if ! ipsec_pool_set_type ${pool} ${network}; then | |
291 | log ERROR "Could not set type for IPsec pool ${pool}" | |
292 | return ${EXIT_ERROR} | |
293 | fi | |
294 | else | |
295 | if ! ${TYPE}_net_is_valid ${network}; then | |
296 | log ERROR "Network '${network}' is invalid" | |
297 | return ${EXIT_ERROR} | |
298 | fi | |
299 | fi | |
300 | ||
301 | if ! ipsec_pool_write_config_key "${pool}" "NETWORK" ${network}; then | |
302 | log ERROR "Could not write configuration settings" | |
303 | return ${EXIT_ERROR} | |
304 | fi | |
305 | } | |
306 | ||
307 | ipsec_pool_dns_server() { | |
308 | if [ ! $# -eq 2 ]; then | |
309 | log ERROR "Not enough arguments" | |
310 | return ${EXIT_ERROR} | |
311 | fi | |
312 | local pool=${1} | |
313 | local dns_server=${2} | |
314 | ||
315 | local TYPE | |
316 | if ! ipsec_pool_read_config ${pool} "TYPE"; then | |
317 | error "Failed to read configuration settings for pool '${pool}'" | |
318 | return ${EXIT_ERROR} | |
319 | fi | |
320 | ||
321 | if ! isset TYPE; then | |
322 | if ! ip_is_valid ${dns_server}; then | |
323 | log ERROR "DNS server '${dns_server}' is invalid" | |
324 | return ${EXIT_ERROR} | |
325 | fi | |
326 | ||
327 | if ! ipsec_pool_set_type ${pool} ${dns_server}; then | |
328 | log ERROR "Could not set type for IPsec pool ${pool}" | |
329 | return ${EXIT_ERROR} | |
330 | fi | |
331 | else | |
332 | if ! ${TYPE}_is_valid ${dns_server}; then | |
333 | log ERROR "DNS server '${dns_server}' is invalid" | |
334 | return ${EXIT_ERROR} | |
335 | fi | |
336 | fi | |
337 | ||
338 | if ! ipsec_pool_write_config_key "${pool}" "DNS_SERVER" ${dns_server}; then | |
339 | log ERROR "Could not write configuration settings" | |
340 | return ${EXIT_ERROR} | |
341 | fi | |
342 | } | |
343 | ||
344 | ipsec_pool_check_config() { | |
345 | local pool=${1} | |
346 | assert isset pool | |
347 | ||
348 | local ${IPSEC_POOL_CONFIG_SETTINGS} | |
349 | if ! ipsec_pool_read_config "${pool}"; then | |
350 | log ERROR "Could not read configuration settings" | |
351 | return ${EXIT_ERROR} | |
352 | fi | |
353 | ||
354 | if ! isset NETWORK; then | |
355 | log ERROR "Network for IPSec pool ${pool} is not set" | |
356 | return ${EXIT_ERROR} | |
357 | fi | |
358 | ||
359 | if ! isset TYPE; then | |
360 | TYPE=$(ip_detect_protocol ${NETWORK}) | |
361 | log DEBUG "IP protocol of ${NETWORK} is ${TYPE}" | |
362 | if ! isset TYPE; then | |
363 | error "Cannot detect IP protocol of ${NETWORK}" | |
364 | return ${EXIT_ERROR} | |
365 | else | |
366 | if ! ipsec_pool_write_config_key "${pool}" "TYPE" ${TYPE}; then | |
367 | log ERROR "Could not write configuration settings" | |
368 | return ${EXIT_ERROR} | |
369 | fi | |
370 | fi | |
371 | else | |
372 | if ! ${TYPE}_net_is_valid ${NETWORK}; then | |
373 | log ERROR "NETWORK '${NETWORK}' is invalid" | |
374 | return ${EXIT_ERROR} | |
375 | fi | |
376 | ||
377 | if isset DNS_SERVER && ! ${TYPE}_is_valid ${DNS_SERVER}; then | |
378 | log ERROR "DNS server '${DNS_SERVER}' is invalid" | |
379 | return ${EXIT_ERROR} | |
380 | fi | |
381 | fi | |
382 | ||
383 | return ${EXIT_OK} | |
384 | } | |
385 | ||
386 | ipsec_pool_reload() { | |
387 | local pool=${1} | |
388 | ||
389 | if ! ipsec_pool_to_strongswan ${pool}; then | |
390 | log ERROR "Could not generate strongswan config for ${pool}" | |
391 | return ${EXIT_ERROR} | |
392 | fi | |
393 | ||
394 | ipsec_strongswan_load | |
395 | } | |
396 | ||
397 | ipsec_pool_to_strongswan() { | |
398 | local pool=${1} | |
399 | ||
400 | log DEBUG "Generating IPsec pool config for ${pool}" | |
401 | ||
402 | local ${IPSEC_POOL_CONFIG_SETTINGS} | |
403 | if ! ipsec_pool_read_config "${pool}"; then | |
404 | return ${EXIT_ERROR} | |
405 | fi | |
406 | ||
407 | if isset NETWORK && ! ipsec_pool_check_config "${pool}"; then | |
408 | log ERROR "Configuration of ${pool} seems to be invalid" | |
409 | return ${EXIT_ERROR} | |
410 | fi | |
411 | ||
412 | local path="${NETWORK_IPSEC_SWANCTL_POOLS_DIR}/${pool}.conf" | |
413 | ||
414 | ( | |
415 | config_header "strongSwan pool configuration" | |
416 | ||
417 | if isset NETWORK; then | |
418 | print_indent 0 "pools {" | |
419 | ||
420 | print_indent 1 "${pool} {" | |
421 | print_indent 2 "addrs = ${NETWORK}" | |
422 | ||
423 | if isset DNS_SERVER; then | |
424 | print_indent 2 "dns = ${DNS_SERVER}" | |
425 | fi | |
426 | ||
427 | print_indent 1 "}" | |
428 | print_indent 0 "}" | |
429 | fi | |
430 | ) > ${path} | |
431 | } | |
ecac9e2b JS |
432 | |
433 | # List all IPsec pools | |
434 | ipsec_list_pools() { | |
435 | local pool | |
436 | for pool in ${NETWORK_IPSEC_POOLS_DIR}/*; do | |
437 | [ -d "${pool}" ] || continue | |
438 | basename "${pool}" | |
439 | done | |
440 | } | |
f5135fb7 JS |
441 | |
442 | # Reload all strongswan pools | |
443 | ipsec_strongswan_load_pools() { | |
444 | # Do nothing if strongswan is not running | |
445 | if ! service_is_active "strongswan"; then | |
446 | return ${EXIT_OK} | |
447 | fi | |
448 | ||
449 | if ! cmd swanctl --load-pools; then | |
450 | log ERROR "Could not reload strongswan pools" | |
451 | return ${EXIT_ERROR} | |
452 | fi | |
453 | } |