]>
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 | |
246 | } | |
247 | ||
248 | ipsec_pool_set_type() { | |
249 | local pool=${1} | |
250 | local ip=${2} | |
251 | assert isset pool | |
252 | assert isset ip | |
253 | ||
254 | local type=$(ip_detect_protocol ${ip}) | |
255 | ||
256 | if ! isset type; then | |
257 | error "Cannot detect IP protocol of ${ip}" | |
258 | return ${EXIT_ERROR} | |
259 | else | |
260 | log DEBUG "IP protocol of ${ip} is ${type}" | |
261 | if ! ipsec_pool_write_config_key "${pool}" "TYPE" ${type}; then | |
262 | log ERROR "Could not write configuration settings" | |
263 | return ${EXIT_ERROR} | |
264 | fi | |
265 | fi | |
266 | } | |
267 | ||
268 | ipsec_pool_network() { | |
269 | if [ ! $# -eq 2 ]; then | |
270 | log ERROR "Not enough arguments" | |
271 | return ${EXIT_ERROR} | |
272 | fi | |
273 | local pool=${1} | |
274 | local network=${2} | |
275 | ||
276 | local TYPE | |
277 | if ! ipsec_pool_read_config ${pool} "TYPE"; then | |
278 | error "Failed to read configuration settings for pool '${pool}'" | |
279 | return ${EXIT_ERROR} | |
280 | fi | |
281 | ||
282 | if ! isset TYPE; then | |
283 | if ! ip_net_is_valid ${network}; then | |
284 | log ERROR "Network '${network}' is invalid" | |
285 | return ${EXIT_ERROR} | |
286 | fi | |
287 | ||
288 | if ! ipsec_pool_set_type ${pool} ${network}; then | |
289 | log ERROR "Could not set type for IPsec pool ${pool}" | |
290 | return ${EXIT_ERROR} | |
291 | fi | |
292 | else | |
293 | if ! ${TYPE}_net_is_valid ${network}; then | |
294 | log ERROR "Network '${network}' is invalid" | |
295 | return ${EXIT_ERROR} | |
296 | fi | |
297 | fi | |
298 | ||
299 | if ! ipsec_pool_write_config_key "${pool}" "NETWORK" ${network}; then | |
300 | log ERROR "Could not write configuration settings" | |
301 | return ${EXIT_ERROR} | |
302 | fi | |
303 | } | |
304 | ||
305 | ipsec_pool_dns_server() { | |
306 | if [ ! $# -eq 2 ]; then | |
307 | log ERROR "Not enough arguments" | |
308 | return ${EXIT_ERROR} | |
309 | fi | |
310 | local pool=${1} | |
311 | local dns_server=${2} | |
312 | ||
313 | local TYPE | |
314 | if ! ipsec_pool_read_config ${pool} "TYPE"; then | |
315 | error "Failed to read configuration settings for pool '${pool}'" | |
316 | return ${EXIT_ERROR} | |
317 | fi | |
318 | ||
319 | if ! isset TYPE; then | |
320 | if ! ip_is_valid ${dns_server}; then | |
321 | log ERROR "DNS server '${dns_server}' is invalid" | |
322 | return ${EXIT_ERROR} | |
323 | fi | |
324 | ||
325 | if ! ipsec_pool_set_type ${pool} ${dns_server}; then | |
326 | log ERROR "Could not set type for IPsec pool ${pool}" | |
327 | return ${EXIT_ERROR} | |
328 | fi | |
329 | else | |
330 | if ! ${TYPE}_is_valid ${dns_server}; then | |
331 | log ERROR "DNS server '${dns_server}' is invalid" | |
332 | return ${EXIT_ERROR} | |
333 | fi | |
334 | fi | |
335 | ||
336 | if ! ipsec_pool_write_config_key "${pool}" "DNS_SERVER" ${dns_server}; then | |
337 | log ERROR "Could not write configuration settings" | |
338 | return ${EXIT_ERROR} | |
339 | fi | |
340 | } | |
341 | ||
342 | ipsec_pool_check_config() { | |
343 | local pool=${1} | |
344 | assert isset pool | |
345 | ||
346 | local ${IPSEC_POOL_CONFIG_SETTINGS} | |
347 | if ! ipsec_pool_read_config "${pool}"; then | |
348 | log ERROR "Could not read configuration settings" | |
349 | return ${EXIT_ERROR} | |
350 | fi | |
351 | ||
352 | if ! isset NETWORK; then | |
353 | log ERROR "Network for IPSec pool ${pool} is not set" | |
354 | return ${EXIT_ERROR} | |
355 | fi | |
356 | ||
357 | if ! isset TYPE; then | |
358 | TYPE=$(ip_detect_protocol ${NETWORK}) | |
359 | log DEBUG "IP protocol of ${NETWORK} is ${TYPE}" | |
360 | if ! isset TYPE; then | |
361 | error "Cannot detect IP protocol of ${NETWORK}" | |
362 | return ${EXIT_ERROR} | |
363 | else | |
364 | if ! ipsec_pool_write_config_key "${pool}" "TYPE" ${TYPE}; then | |
365 | log ERROR "Could not write configuration settings" | |
366 | return ${EXIT_ERROR} | |
367 | fi | |
368 | fi | |
369 | else | |
370 | if ! ${TYPE}_net_is_valid ${NETWORK}; then | |
371 | log ERROR "NETWORK '${NETWORK}' is invalid" | |
372 | return ${EXIT_ERROR} | |
373 | fi | |
374 | ||
375 | if isset DNS_SERVER && ! ${TYPE}_is_valid ${DNS_SERVER}; then | |
376 | log ERROR "DNS server '${DNS_SERVER}' is invalid" | |
377 | return ${EXIT_ERROR} | |
378 | fi | |
379 | fi | |
380 | ||
381 | return ${EXIT_OK} | |
382 | } | |
383 | ||
384 | ipsec_pool_reload() { | |
385 | local pool=${1} | |
386 | ||
387 | if ! ipsec_pool_to_strongswan ${pool}; then | |
388 | log ERROR "Could not generate strongswan config for ${pool}" | |
389 | return ${EXIT_ERROR} | |
390 | fi | |
391 | ||
392 | ipsec_strongswan_load | |
393 | } | |
394 | ||
395 | ipsec_pool_to_strongswan() { | |
396 | local pool=${1} | |
397 | ||
398 | log DEBUG "Generating IPsec pool config for ${pool}" | |
399 | ||
400 | local ${IPSEC_POOL_CONFIG_SETTINGS} | |
401 | if ! ipsec_pool_read_config "${pool}"; then | |
402 | return ${EXIT_ERROR} | |
403 | fi | |
404 | ||
405 | if isset NETWORK && ! ipsec_pool_check_config "${pool}"; then | |
406 | log ERROR "Configuration of ${pool} seems to be invalid" | |
407 | return ${EXIT_ERROR} | |
408 | fi | |
409 | ||
410 | local path="${NETWORK_IPSEC_SWANCTL_POOLS_DIR}/${pool}.conf" | |
411 | ||
412 | ( | |
413 | config_header "strongSwan pool configuration" | |
414 | ||
415 | if isset NETWORK; then | |
416 | print_indent 0 "pools {" | |
417 | ||
418 | print_indent 1 "${pool} {" | |
419 | print_indent 2 "addrs = ${NETWORK}" | |
420 | ||
421 | if isset DNS_SERVER; then | |
422 | print_indent 2 "dns = ${DNS_SERVER}" | |
423 | fi | |
424 | ||
425 | print_indent 1 "}" | |
426 | print_indent 0 "}" | |
427 | fi | |
428 | ) > ${path} | |
429 | } | |
ecac9e2b JS |
430 | |
431 | # List all IPsec pools | |
432 | ipsec_list_pools() { | |
433 | local pool | |
434 | for pool in ${NETWORK_IPSEC_POOLS_DIR}/*; do | |
435 | [ -d "${pool}" ] || continue | |
436 | basename "${pool}" | |
437 | done | |
438 | } |