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
="${NETWORK_IPSEC_CONNS_DIR}/${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
="${NETWORK_IPSEC_CONNS_DIR}/${connection}/settings"
165 if ! settings_read
"${path}" ${args}; then
166 log ERROR
"Could not read settings for VPN IPsec connection ${connection}"
171 # This function checks if a vpn ipsec connection exists
172 # Returns True when yes and false when not
173 ipsec_connection_exists
() {
176 local connection
=${1}
178 local path
="${NETWORK_IPSEC_CONNS_DIR}/${connection}"
180 [ -d "${path}" ] && return ${EXIT_TRUE} || return ${EXIT_FALSE}
183 # Reloads the connection after config changes
188 # Handle the cli after authentification
189 ipsec_connection_authentication() {
190 if [ ! $# -gt 1 ]; then
191 log ERROR "Not enough arguments
"
195 local connection=${1}
201 ipsec_connection_authentication_mode "${connection}" $@
204 ipsec_connection_authentication_psk "${connection}" $@
207 log ERROR "Unrecognized argument
: ${cmd}"
213 # Set the authentification mode
214 ipsec_connection_authentication_mode() {
215 if [ ! $# -eq 2 ]; then
216 log ERROR "Not enough arguments
"
219 local connection=${1}
222 if ! isoneof mode ${IPSEC_VALID_AUTH_MODES}; then
223 log ERROR "Auth mode
'${mode}' is invalid
"
227 if ! ipsec_connection_write_config_key "${connection}" "AUTH_MODE
" ${mode,,}; then
228 log ERROR "Could not
write configuration settings
"
234 ipsec_connection_authentication_psk() {
235 if [ ! $# -eq 2]; then
236 log ERROR "Not enough arguments
"
239 local connection=${1}
242 # TODO Check if psk is valid
244 if ! ipsec_connection_write_config_key "${connection}" "PSK
" ${psk}; then
245 log ERROR "Could not
write configuration settings
"
252 # Handle the cli after local
253 ipsec_connection_local() {
254 if [ ! $# -ge 2 ]; then
255 log ERROR "Not enough arguments
"
259 local connection=${1}
265 ipsec_connection_id "${connection}" "LOCAL
" $@
268 ipsec_connection_prefix "${connection}" "LOCAL
" $@
271 log ERROR "Unrecognized argument
: ${cmd}"
279 # Set the connection mode
280 ipsec_connection_mode() {
281 if [ ! $# -eq 2]; then
282 log ERROR "Not enough arguments
"
285 local connection=${1}
288 if ! isoneof mode ${IPSEC_VALID_MODES}; then
289 log ERROR "Mode
'${mode}' is invalid
"
293 if ! ipsec_connection_write_config_key "${connection}" "MODE
" ${mode}; then
294 log ERROR "Could not
write configuration settings
"
301 # Set the peer to connect to
302 ipsec_connection_peer() {
303 if [ ! $# -eq 2 ]; then
304 log ERROR "Not enough arguments
"
307 local connection=${1}
310 if ! ipsec_connection_check_peer ${peer}; then
311 log ERROR "Peer
'${peer}' is invalid
"
315 if ! ipsec_connection_write_config_key "${connection}" "PEER
" ${peer}; then
316 log ERROR "Could not
write configuration settings
"
323 #Set the local or remote id
324 ipsec_connection_id() {
325 if [ ! $# -eq 3 ]; then
326 log ERROR "Not enough arguments
"
329 local connection=${1}
333 if ! ipsec_connection_check_id ${id}; then
334 log ERROR "Id
'${id}' is invalid
"
338 if ! ipsec_connection_write_config_key "${connection}" "${type}_ID" ${id}; then
339 log ERROR
"Could not write configuration settings"
346 # Set the local or remote prefix
347 ipsec_connection_prefix
() {
348 if [ ! $# -ge 3 ]; then
349 log ERROR
"Not enough arguments"
352 local connection
=${1}
356 local _prefix
="${type}_PREFIX"
358 if ! ipsec_connection_read_config
"${connection}" "${_prefix}"; then
362 # Remove duplicated entries to proceed the list safely
363 assign
"${_prefix}" "$(list_unique ${!_prefix} )"
366 local prefixes_removed
369 while [ $# -gt 0 ]; do
374 list_append prefixes_added
"${arg:1}"
377 list_append prefixes_removed
"${arg:1}"
380 list_append prefixes_set
"${arg}"
383 error
"Invalid argument: ${arg}"
390 # Check if the user is trying a mixed operation
391 if ! list_is_empty prefixes_set
&& (! list_is_empty prefixes_added ||
! list_is_empty prefixes_removed
); then
392 error
"You cannot reset the prefix list and add or remove prefixes at the same time"
396 # Set new prefix list
397 if ! list_is_empty prefixes_set
; then
398 # Check if all prefixes are valid
400 for prefix
in ${prefixes_set}; do
401 if ! ip_net_is_valid
${prefix}; then
402 error
"Unsupported prefix: ${prefix}"
407 assign
"${_prefix}" "${prefixes_set}"
409 # Perform incremental updates
413 # Perform all removals
414 for prefix
in ${prefixes_removed}; do
415 if ! list_remove
"${_prefix}" ${prefix}; then
416 warning
"${prefix} was not on the list and could not be removed"
421 for prefix
in ${prefixes_added}; do
422 if ip_net_is_valid
${prefix}; then
423 if ! list_append_unique
"${_prefix}" ${prefix}; then
424 warning
"${prefix} is already on the prefix list"
427 warning
"${prefix} is not a valiv IP net and could not be added"
432 # Check if the list contain at least one valid prefix
433 if list_is_empty
${_prefix}; then
434 error
"Cannot save an empty prefix list"
439 if ! ipsec_connection_write_config_key
"${connection}" "${_prefix}" ${!_prefix}; then
440 log ERROR "Could not
write configuration settings
"
446 # Handle the cli after remote
447 ipsec_connection_remote() {
448 if [ ! $# -ge 2 ]; then
449 log ERROR "Not enough arguments
"
453 local connection=${1}
459 ipsec_connection_id "${connection}" "REMOTE
" $@
463 ipsec_connection_prefix "${connection}" "REMOTE
" $@
466 log ERROR "Unrecognized argument
: ${cmd}"
474 # Set the inactivity timeout
475 ipsec_connection_inactivity_timeout() {
476 if [ ! $# -ge 2 ]; then
477 log ERROR "Not enough arguments
"
481 local connection=${1}
485 if ! isinteger value; then
486 value=$(parse_time $@)
487 if [ ! $? -eq 0 ]; then
488 log ERROR "Parsing the passed
time was not sucessful please check the passed values.
"
493 if [ ${value} -le 0 ]; then
494 log ERROR "The passed
time value must be
in the
sum greater zero seconds.
"
498 if ! ipsec_connection_write_config_key "${connection}" "INACTIVITY_TIMEOUT
" ${value}; then
499 log ERROR "Could not
write configuration settings
"
507 # Set the security policy to use
508 ipsec_connection_security_policy() {
509 if [ ! $# -eq 2 ]; then
510 log ERROR "Not enough arguments
"
513 local connection=${1}
514 local security_policy=${2}
516 if ! vpn_security_policy_exists ${security_policy}; then
517 log ERROR "No such vpn security policy
'${security_policy}'"
521 if ! ipsec_connection_write_config_key "${connection}" "SECURITY_POLICY
" ${security_policy}; then
522 log ERROR "Could not
write configuration settings
"
527 # Check if a id is valid
528 ipsec_connection_check_id() {
532 if [[ ${id} =~ ^@[[:alnum:]]+$ ]] || ip_is_valid ${id}; then
539 # Checks if a peer is valid
540 ipsec_connection_check_peer() {
544 # TODO Accept also FQDNs
545 if ip_is_valid ${peer}; then
552 # This function checks if a VPN IPsec connection name is valid
553 # Allowed are only A-Za-z0-9
554 ipsec_connection_check_name() {
557 local connection=${1}
559 [[ "${connection}" =~ [^[:alnum:]$] ]]
562 # Function that creates one VPN IPsec connection
563 ipsec_connection_new() {
564 if [ $# -gt 1 ]; then
565 error "Too many arguments
"
569 local connection="${1}"
570 if ! isset connection; then
571 error "Please provide a connection name
"
575 # Check for duplicates
576 if ipsec_connection_exists "${connection}"; then
577 error "The VPN IPsec connection
${connection} already exists
"
581 # Check if the name of the connection is valid
582 if ipsec_connection_check_name "${connection}"; then
583 error "'${connection}' contains illegal characters
"
587 log DEBUG "Creating VPN IPsec connection
${connection}"
589 if ! mkdir -p "${NETWORK_IPSEC_CONNS_DIR}/${connection}"; then
590 log ERROR "Could not create config directory
for ${connection}"
594 local ${IPSEC_CONNECTION_CONFIG_SETTINGS}
596 MODE=${IPSEC_DEFAULT_MODE}
597 AUTH_MODE=${IPSEC_DEFAULT_AUTH_MODE}
598 INACTIVITY_TIMEOUT=${IPSEC_DEFAULT_INACTIVITY_TIMEOUT}
599 SECURITY_POLICY=${IPSEC_DEFAULT_SECURITY_POLICY}
601 if ! ipsec_connection_write_config "${connection}"; then
602 log ERROR "Could not
write new config
file"
607 # Function that deletes based on the passed parameters one ore more vpn security policies
608 ipsec_connection_destroy() {
610 for connection in $@; do
611 if ! ipsec_connection_exists "${connection}"; then
612 log ERROR "The VPN IPsec connection
${connection} does not exist.
"
616 log DEBUG "Deleting VPN IPsec connection
${connection}"
617 if ! rm -rf "${NETWORK_IPSEC_CONNS_DIR}/${connection}"; then
618 log ERROR "Deleting the VPN IPsec connection
${connection} was not sucessful
"