2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2017 IPFire Network Development Team #
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. #
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. #
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/>. #
20 ###############################################################################
22 IPSEC_CONNECTION_CONFIG_SETTINGS
="AUTH_MODE INACTIVITY_TIMEOUT LOCAL_ID LOCAL_PREFIX"
23 IPSEC_CONNECTION_CONFIG_SETTINGS
="${IPSEC_CONNECTION_CONFIG_SETTINGS} MODE PEER PSK"
24 IPSEC_CONNECTION_CONFIG_SETTINGS
="${IPSEC_CONNECTION_CONFIG_SETTINGS} REMOTE_ID REMOTE_PREFIX"
25 IPSEC_CONNECTION_CONFIG_SETTINGS
="${IPSEC_CONNECTION_CONFIG_SETTINGS} SECURITY_POLICY"
28 IPSEC_DEFAULT_MODE
="tunnel"
29 IPSEC_DEFAULT_AUTH_MODE
="psk"
30 IPSEC_DEFAULT_INACTIVITY_TIMEOUT
="0"
31 IPSEC_DEFAULT_SECURITY_POLICY
="system"
33 IPSEC_VALID_MODES
="gre-transport tunnel vti"
34 IPSEC_VALID_AUTH_MODES
="PSK psk"
42 cli_ipsec_connection $@
45 error
"Unrecognized argument: ${action}"
51 cli_ipsec_connection
() {
52 if ipsec_connection_exists
${1}; then
59 authentication|inactivity-timout|
local|mode|peer|remote|security-policy
)
60 ipsec_connection_
${key} ${connection} $@
63 error
"Unrecognized argument: ${key}"
73 ipsec_connection_new $@
76 ipsec_connection_destroy $@
79 if [ -n "${action}" ]; then
80 error
"Unrecognized argument: '${action}'"
88 # This function writes all values to a via ${connection} specificated VPN IPsec configuration file
89 ipsec_connection_write_config
() {
92 local connection
="${1}"
94 if ! ipsec_connection_exists
"${connection}"; then
95 log ERROR
"No such VPN IPsec connection: ${connection}"
99 local path
="$(ipsec_connection_path "${connection}")/settings"
101 if ! settings_write
"${path}" ${IPSEC_CONNECTION_CONFIG_SETTINGS}; then
102 log ERROR
"Could not write configuration settings for VPN IPsec connection ${connection}"
106 ipsec_reload
${connection}
109 # This funtion writes the value for one key to a via ${connection} specificated VPN IPsec connection configuration file
110 ipsec_connection_write_config_key
() {
113 local connection
=${1}
119 if ! ipsec_connection_exists
"${connection}"; then
120 log ERROR
"No such VPN ipsec connection: ${connection}"
124 log DEBUG
"Set '${key}' to new value '${value}' in VPN ipsec connection '${connection}'"
126 local ${IPSEC_CONNECTION_CONFIG_SETTINGS}
128 # Read the config settings
129 if ! ipsec_connection_read_config
"${connection}"; then
133 # Set the key to a new value
134 assign
"${key}" "${value}"
136 if ! ipsec_connection_write_config
"${connection}"; then
143 # Reads one or more keys out of a settings file or all if no key is provided.
144 ipsec_connection_read_config
() {
147 local connection
="${1}"
150 if ! ipsec_connection_exists
"${connection}"; then
151 log ERROR
"No such VPN IPsec connection : ${connection}"
157 if [ $# -eq 0 ] && [ -n "${IPSEC_CONNECTION_CONFIG_SETTINGS}" ]; then
158 list_append args
${IPSEC_CONNECTION_CONFIG_SETTINGS}
163 local path
="$(ipsec_connection_path "${connection}")/settings"
165 if ! settings_read
"${path}" ${args}; then
166 log ERROR
"Could not read settings for VPN IPsec connection ${connection}"
171 # Returns the path to a the directory for given connection
172 ipsec_connection_path
() {
175 local connection
=${1}
177 echo "${NETWORK_CONFIG_DIR}/vpn/ipsec/connection/${connection}"
180 # This function checks if a vpn ipsec connection exists
181 # Returns True when yes and false when not
182 ipsec_connection_exists
() {
185 local connection
=${1}
187 local path
=$
(ipsec_connection_path
"${connection}")
189 [ -d "${path}" ] && return ${EXIT_TRUE} || return ${EXIT_FALSE}
192 # Reloads the connection after config changes
197 # Handle the cli after authentification
198 ipsec_connection_authentication() {
199 if [ ! $# -gt 1 ]; then
200 log ERROR "Not enough arguments
"
204 local connection=${1}
210 ipsec_connection_authentication_mode "${connection}" $@
213 ipsec_connection_authentication_psk "${connection}" $@
216 log ERROR "Unrecognized argument
: ${cmd}"
222 # Set the authentification mode
223 ipsec_connection_authentication_mode() {
224 if [ ! $# -eq 2 ]; then
225 log ERROR "Not enough arguments
"
228 local connection=${1}
231 if ! isoneof mode ${IPSEC_VALID_AUTH_MODES}; then
232 log ERROR "Auth mode
'${mode}' is invalid
"
236 if ! ipsec_connection_write_config_key "${connection}" "AUTH_MODE
" ${mode,,}; then
237 log ERROR "Could not
write configuration settings
"
243 ipsec_connection_authentication_psk() {
244 if [ ! $# -eq 2]; then
245 log ERROR "Not enough arguments
"
248 local connection=${1}
251 # TODO Check if psk is valid
253 if ! ipsec_connection_write_config_key "${connection}" "PSK
" ${psk}; then
254 log ERROR "Could not
write configuration settings
"
261 # Handle the cli after local
262 ipsec_connection_local() {
263 if [ ! $# -ge 2 ]; then
264 log ERROR "Not enough arguments
"
268 local connection=${1}
274 ipsec_connection_id "${connection}" "LOCAL
" $@
277 ipsec_connection_prefix "${connection}" "LOCAL
" $@
280 log ERROR "Unrecognized argument
: ${cmd}"
288 # Set the connection mode
289 ipsec_connection_mode() {
290 if [ ! $# -eq 2]; then
291 log ERROR "Not enough arguments
"
294 local connection=${1}
297 if ! isoneof mode ${IPSEC_VALID_MODES}; then
298 log ERROR "Mode
'${mode}' is invalid
"
302 if ! ipsec_connection_write_config_key "${connection}" "MODE
" ${mode}; then
303 log ERROR "Could not
write configuration settings
"
310 # Set the peer to connect to
311 ipsec_connection_peer() {
312 if [ ! $# -eq 2]; then
313 log ERROR "Not enough arguments
"
316 local connection=${1}
319 if ! ipsec_connection_check_peer ${peer}; then
320 log ERROR "Peer
'${peer}' is invalid
"
324 if ! ipsec_connection_write_config_key "${connection}" "PEER
" ${peer}; then
325 log ERROR "Could not
write configuration settings
"
332 #Set the local or remote id
333 ipsec_connection_id() {
334 if [ ! $# -eq 3 ]; then
335 log ERROR "Not enough arguments
"
338 local connection=${1}
342 if ! ipsec_connection_check_id ${id}; then
343 log ERROR "Id
'${id}' is invalid
"
347 if ! ipsec_connection_write_config_key "${connection}" "${type}_ID" ${id}; then
348 log ERROR
"Could not write configuration settings"
355 # Set the local or remote prefix
356 ipsec_connection_prefix
() {
357 if [ ! $# -ge 3 ]; then
358 log ERROR
"Not enough arguments"
361 local connection
=${1}
365 local _prefix
="${type}_PREFIX"
367 if ! ipsec_connection_read_config
"${connection}" "${_prefix}"; then
371 # Remove duplicated entries to proceed the list safely
372 assign
"${_prefix}" "$(list_unique ${!_prefix} )"
375 local prefixes_removed
378 while [ $# -gt 0 ]; do
383 list_append prefixes_added
"${arg:1}"
386 list_append prefixes_removed
"${arg:1}"
389 list_append prefixes_set
"${arg}"
392 error
"Invalid argument: ${arg}"
399 # Check if the user is trying a mixed operation
400 if ! list_is_empty prefixes_set
&& (! list_is_empty prefixes_added ||
! list_is_empty prefixes_removed
); then
401 error
"You cannot reset the prefix list and add or remove prefixes at the same time"
405 # Set new prefix list
406 if ! list_is_empty prefixes_set
; then
407 # Check if all prefixes are valid
409 for prefix
in ${prefixes_set}; do
410 if ! ip_net_is_valid
${prefix}; then
411 error
"Unsupported prefix: ${prefix}"
416 assign
"${_prefix}" "${prefixes_set}"
418 # Perform incremental updates
422 # Perform all removals
423 for prefix
in ${prefixes_removed}; do
424 if ! list_remove
"${_prefix}" ${prefix}; then
425 warning
"${prefix} was not on the list and could not be removed"
430 for prefix
in ${prefixes_added}; do
431 if ip_net_is_valid
${prefix}; then
432 if ! list_append_unique
"${_prefix}" ${prefix}; then
433 warning
"${prefix} is already on the prefix list"
436 warning
"${prefix} is not a valiv IP net and could not be added"
441 # Check if the list contain at least one valid prefix
442 if list_is_empty
${_prefix}; then
443 error
"Cannot save an empty prefix list"
448 if ! ipsec_connection_write_config_key
"${connection}" "${_prefix}" ${!_prefix}; then
449 log ERROR "Could not
write configuration settings
"
455 # Handle the cli after remote
456 ipsec_connection_remote() {
457 if [ ! $# -ge 2 ]; then
458 log ERROR "Not enough arguments
"
462 local connection=${1}
468 ipsec_connection_id "${connection}" "REMOTE
" $@
472 ipsec_connection_prefix "${connection}" "REMOTE
" $@
475 log ERROR "Unrecognized argument
: ${cmd}"
483 # Set the inactivity timeout
484 ipsec_connection_inactivity_timeout() {
485 if [ ! $# -ge 2 ]; then
486 log ERROR "Not enough arguments
"
490 local connection=${1}
494 if ! isinteger value; then
495 value=$(parse_time $@)
496 if [ ! $? -eq 0 ]; then
497 log ERROR "Parsing the passed
time was not sucessful please check the passed values.
"
502 if [ ${value} -le 0 ]; then
503 log ERROR "The passed
time value must be
in the
sum greater zero seconds.
"
507 if ! ipsec_connection_write_config_key "${connection}" "INACTIVITY_TIMEOUT
" ${value}; then
508 log ERROR "Could not
write configuration settings
"
516 # Set the security policy to use
517 ipsec_connection_security_policy() {
518 if [ ! $# -eq 2 ]; then
519 log ERROR "Not enough arguments
"
522 local connection=${1}
523 local security_policy=${2}
525 if ! vpn_security_policy_exists ${security_policy}; then
526 log ERROR "No such vpn security policy
'${security_policy}'"
530 if ! ipsec_connection_write_config_key "${connection}" "SECURITY_POLICY
" ${security_policy}; then
531 log ERROR "Could not
write configuration settings
"
536 # Check if a id is valid
537 ipsec_connection_check_id() {
541 if [[ ${id} =~ ^@[[:alnum:]]+$ ]] || ip_is_valid ${id}; then
548 # Checks if a peer is valid
549 ipsec_connection_check_peer() {
553 # TODO Accept also FQDNs
554 if ip_is_valid ${peer}; then
561 # This function checks if a VPN IPsec connection name is valid
562 # Allowed are only A-Za-z0-9
563 ipsec_connection_check_name() {
566 local connection=${1}
568 [[ "${connection}" =~ [^[:alnum:]$] ]]
571 # Function that creates one VPN IPsec connection
572 ipsec_connection_new() {
573 if [ $# -gt 1 ]; then
574 error "Too many arguments
"
578 local connection="${1}"
579 if ! isset connection; then
580 error "Please provide a connection name
"
584 # Check for duplicates
585 if ipsec_connection_exists "${connection}"; then
586 error "The VPN IPsec connection
${connection} already exists
"
590 # Check if the name of the connection is valid
591 if ipsec_connection_check_name "${connection}"; then
592 error "'${connection}' contains illegal characters
"
596 log DEBUG "Creating VPN IPsec connection
${connection}"
598 if ! mkdir -p $(ipsec_connection_path "${connection}"); then
599 log ERROR "Could not create config directory
for ${connection}"
603 local ${IPSEC_CONNECTION_CONFIG_SETTINGS}
605 MODE=${IPSEC_DEFAULT_MODE}
606 AUTH_MODE=${IPSEC_DEFAULT_AUTH_MODE}
607 INACTIVITY_TIMEOUT=${IPSEC_DEFAULT_INACTIVITY_TIMEOUT}
608 SECURITY_POLICY=${IPSEC_DEFAULT_SECURITY_POLICY}
610 if ! ipsec_connection_write_config "${connection}"; then
611 log ERROR "Could not
write new config
file"
616 # Function that deletes based on the passed parameters one ore more vpn security policies
617 ipsec_connection_destroy() {
619 for connection in $@; do
620 if ! ipsec_connection_exists "${connection}"; then
621 log ERROR "The VPN IPsec connection
${connection} does not exist.
"
625 log DEBUG "Deleting VPN IPsec connection
${connection}"
626 if ! rm -rf $(ipsec_connection_path "${connection}"); then
627 log ERROR "Deleting the VPN IPsec connection
${connection} was not sucessful
"