]> git.ipfire.org Git - people/stevee/network.git/blame - src/functions/functions.vpn-security-policies
copy: Do not empty $dst when source file cannot be read
[people/stevee/network.git] / src / functions / functions.vpn-security-policies
CommitLineData
3eae7bed
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
22VPN_SECURITY_POLICIES_CONFIG_SETTINGS="CIPHER COMPRESSION GROUP_TYPE INTEGRITY KEY_EXCHANGE LIFETIME PFS"
23VPN_SECURITY_POLICIES_READONLY="system"
24
25VPN_SUPPORTED_CIPHERS="AES192 AES256 AES512"
26VPN_SUPPORTED_INTEGRITY="SHA512 SHA256 SHA128"
27VPN_SUPPORTED_GROUP_TYPES="MODP8192 MODP4096"
28
6740c9c5
MT
29# This functions checks if a policy is readonly
30# returns true when yes and false when no
3eae7bed 31vpn_security_policies_check_readonly() {
3eae7bed
JS
32 if isoneof name ${VPN_SECURITY_POLICIES_READONLY}; then
33 return ${EXIT_TRUE}
34 else
35 return ${EXIT_FALSE}
36 fi
37}
38
6740c9c5 39# This function writes all values to a via ${name} specificated vpn security policy configuration file
3eae7bed 40vpn_security_policies_write_config() {
3eae7bed
JS
41 assert [ $# -ge 1 ]
42
43 local name="${1}"
44
6740c9c5 45 if ! vpn_security_policy_exists "${name}"; then
3eae7bed
JS
46 log ERROR "No such vpn security policy: ${name}"
47 return ${EXIT_ERROR}
48 fi
49
6740c9c5 50 if vpn_security_policies_check_readonly "${name}"; then
3eae7bed
JS
51 log ERROR "The ${name} vpn security policy cannot be changed."
52 return ${EXIT_ERROR}
53 fi
54
6740c9c5 55 local path="$(vpn_security_policies_path "${name}")"
3eae7bed
JS
56 if [ ! -w ${path} ]; then
57 log ERROR "${path} is not writeable"
58 return ${EXIT_ERROR}
59 fi
60
61 if ! settings_write "${path}" ${VPN_SECURITY_POLICIES_CONFIG_SETTINGS}; then
62 log ERROR "Could not write configuration settings for vpn security policy ${name}"
63 return ${EXIT_ERROR}
64 fi
65
66 # TODO everytime we successfully write a config we should call some trigger to take the changes into effect
67}
68
6740c9c5 69# This funtion writes the value for one key to a via ${name} specificated vpn security policy configuration file
3eae7bed 70vpn_security_policies_write_config_key() {
3eae7bed 71 assert [ $# -ge 3 ]
6740c9c5 72
3eae7bed
JS
73 local name=${1}
74 local key=${2}
75 shift 2
6740c9c5 76
3eae7bed
JS
77 local value="$@"
78
6740c9c5 79 if ! vpn_security_policy_exists "${name}"; then
3eae7bed
JS
80 log ERROR "No such vpn security policy: ${name}"
81 return ${EXIT_ERROR}
82 fi
83
84 log DEBUG "Set '${key}' to new value '${value}' in vpn security policy ${name}"
85
86 local ${VPN_SECURITY_POLICIES_CONFIG_SETTINGS}
87
88 # Read the config settings
6740c9c5 89 if ! vpn_security_policies_read_config "${name}"; then
3eae7bed
JS
90 return ${EXIT_ERROR}
91 fi
92
93 # Set the key to a new value
94 assign "${key}" "${value}"
95
6740c9c5 96 if ! vpn_security_policies_write_config "${name}"; then
3eae7bed
JS
97 return ${EXIT_ERROR}
98 fi
99
100 return ${EXIT_TRUE}
3eae7bed
JS
101}
102
6740c9c5 103# Reads one or more keys out of a settings file or all if no key is provided.
3eae7bed 104vpn_security_policies_read_config() {
3eae7bed
JS
105 assert [ $# -ge 1 ]
106
107 local name="${1}"
108 shift 1
109
6740c9c5 110 if ! vpn_security_policy_exists "${name}"; then
3eae7bed
JS
111 log ERROR "No such vpn security policy: ${name}"
112 return ${EXIT_ERROR}
113 fi
114
115
116 local args
117 if [ $# -eq 0 ] && [ -n "${VPN_SECURITY_POLICIES_CONFIG_SETTINGS}" ]; then
118 list_append args ${VPN_SECURITY_POLICIES_CONFIG_SETTINGS}
119 else
120 list_append args $@
121 fi
122
123 local path="$(vpn_security_policies_path ${name})"
124
125 if ! settings_read "${path}" ${args}; then
126 log ERROR "Could not read settings for vpn security policy ${name}"
127 return ${EXIT_ERROR}
128 fi
129}
130
6740c9c5 131# Returns the path to a the configuration fora given name
3eae7bed 132vpn_security_policies_path() {
3eae7bed 133 assert [ $# -eq 1 ]
6740c9c5 134
3eae7bed
JS
135 local name=${1}
136
6740c9c5 137 if vpn_security_policies_check_readonly "${name}"; then
3eae7bed
JS
138 echo "${NETWORK_SHARE_DIR}/vpn/security-policies/${name}"
139 else
140 echo "${NETWORK_CONFIG_DIR}/vpn/security-policies/${name}"
141 fi
142}
143
6740c9c5 144# Print the content of a vpn security policy configuration file in a nice way
3eae7bed 145vpn_security_policies_show() {
3eae7bed 146 assert [ $# -eq 1 ]
6740c9c5 147
3eae7bed
JS
148 local name=${1}
149
150 local ${VPN_SECURITY_POLICIES_CONFIG_SETTINGS}
3eae7bed
JS
151 if ! vpn_security_policies_read_config ${name}; then
152 return ${EXIT_ERROR}
153 fi
154
155 cli_print_fmt1 0 "Security Policy: ${name}"
156 cli_space
157
158 # This could be done in a loop but a loop is much more complicated
159 # because we print 'Group Types' but the variable is named 'GROUP_TYPES'
160 cli_print_fmt1 1 "Ciphers:"
161 cli_print_fmt1 2 "${CIPHER}"
162 cli_space
6740c9c5 163
3eae7bed
JS
164 cli_print_fmt1 1 "Integrity:"
165 cli_print_fmt1 2 "${INTEGRITY}"
166 cli_space
6740c9c5 167
3eae7bed
JS
168 cli_print_fmt1 1 "Group Types:"
169 cli_print_fmt1 2 "${GROUP_TYPE}"
170 cli_space
171
172 cli_print_fmt1 1 "Key Exchange:" "${KEY_EXCHANGE}"
6740c9c5
MT
173
174 # Key Lifetime
3eae7bed
JS
175 if isinteger LIFETIME && [ ${LIFETIME} -gt 0 ]; then
176 cli_print_fmt1 1 "Key Lifetime:" "$(format_time ${LIFETIME})"
177 else
178 log ERROR "The value for Key Lifetime is not a valid integer greater zero."
179 fi
6740c9c5
MT
180
181 # PFS
3eae7bed
JS
182 if enabled PFS; then
183 cli_print_fmt1 1 "Perfect Forward Secrecy:" "enabled"
184 else
185 cli_print_fmt1 1 "Perfect Forward Secrecy:" "disabled"
186 fi
187 cli_space
6740c9c5
MT
188
189 # Compression
3eae7bed
JS
190 if enabled COMPRESSION; then
191 cli_print_fmt1 1 "Compression:" "enabled"
192 else
193 cli_print_fmt1 1 "Compression:" "disabled"
194 fi
195 cli_space
196}
197
6740c9c5
MT
198# This function checks if a vpn security policy exists
199# Returns True when yes and false when not
3eae7bed 200vpn_security_policy_exists() {
3eae7bed 201 assert [ $# -eq 1 ]
6740c9c5 202
3eae7bed
JS
203 local name=${1}
204
6740c9c5
MT
205 local path=$(vpn_security_policies_path "${name}")
206
207 [ -f ${path} ] && return ${EXIT_TRUE} || return ${EXIT_FALSE}
3eae7bed
JS
208}
209
210
6740c9c5 211# This function parses the parameters for the 'cipher' command
3eae7bed 212vpn_security_policies_cipher(){
3eae7bed
JS
213 local name=${1}
214 shift
215
216 if [ $# -eq 0 ]; then
217 log ERROR "You must pass at least one value after cipher"
218 return ${EXIT_ERROR}
219 fi
220
221 local CIPHER
3eae7bed
JS
222 if ! vpn_security_policies_read_config ${name} "CIPHER"; then
223 return ${EXIT_ERROR}
224 fi
225
226 # Remove duplicated entries to proceed the list safely
227 CIPHER="$(list_unique ${CIPHER})"
228
229 while [ $# -gt 0 ]; do
230 case "${1}" in
231 -*)
232 value=${1#-}
233 # Check if the cipher is in the list of ciphers and
234 # check if the list has after removing this cipher at least one valid value
235 if list_match ${value} ${CIPHER}; then
236 list_remove CIPHER ${value}
237 else
238 # We do not break here because this error does not break the processing of the next maybe valid values.
239 log ERROR "Can not remove ${value} from the list of Ciphers because ${value} is not in the list."
240 fi
241 ;;
242 +*)
243 value=${1#+}
244 # Check if the Ciphers is in the list of supported ciphers.
245 if ! isoneof value ${VPN_SUPPORTED_CIPHERS}; then
246 # We do not break here because this error does not break the processing of the next maybe valid values.
247 log ERROR "${value} is not a supported cipher and can thats why not added to the list of ciphers."
248 else
249 if list_match ${value} ${CIPHER}; then
250 log WARNING "${value} is already in the list of ciphers of this policy."
251 else
252 list_append CIPHER ${value}
253 fi
254 fi
255 ;;
256 esac
257 shift
258 done
259
260 # Check if the list contain at least one valid cipher
261 if [ $(list_length ${CIPHER}) -ge 1 ]; then
262 if ! vpn_security_policies_write_config_key ${name} "CIPHER" ${CIPHER}; then
263 log ERROR "The changes for the vpn security policy ${name} could not be written."
264 fi
265 else
266 log ERROR "After proceding all ciphers the list is empty and thats why no changes are written."
267 return ${EXIT_ERROR}
268 fi
269}
270
6740c9c5 271# This function parses the parameters for the 'compression' command
3eae7bed 272vpn_security_policies_compression(){
3eae7bed
JS
273 local name=${1}
274 local value=${2}
275
276 # Check if we get only one argument after compression <name>
277 if [ ! $# -eq 2 ]; then
278 log ERROR "The number of arguments do not match. Only one argument after compression is allowed."
279 return ${EXIT_ERROR}
280 fi
281
282 if ! isbool value; then
283 # We suggest only two values to avoid overburding the user.
284 log ERROR "Invalid Argument ${value}"
285 return ${EXIT_ERROR}
286 fi
287
288 vpn_security_policies_write_config_key "${name}" "COMPRESSION" "${value}"
289}
290
6740c9c5 291# This function parses the parameters for the 'group-type' command
3eae7bed 292vpn_security_policies_group_type(){
3eae7bed
JS
293 local name=${1}
294 shift
295
296 if [ $# -eq 0 ]; then
297 log ERROR "You must pass at least one value after group-type"
298 return ${EXIT_ERROR}
299 fi
300
301 local GROUP_TYPE
3eae7bed
JS
302 if ! vpn_security_policies_read_config ${name} "GROUP_TYPE"; then
303 return ${EXIT_ERROR}
304 fi
305
306 # Remove duplicated entries to proceed the list safely
307 GROUP_TYPE="$(list_unique ${GROUP_TYPE})"
308
309 while [ $# -gt 0 ]; do
310 case "${1}" in
311 -*)
312 value=${1#-}
313 # Check if the group type is in the list of group types and
314 # check if the list has after removing this group type at leatst one valid value
315 if list_match ${value} ${GROUP_TYPE}; then
316 list_remove GROUP_TYPE ${value}
317 else
318 # We do not break here because this error does not break the processing of the next maybe valid values.
319 log ERROR "Can not remove ${value} from the list of group types because ${value} is not in the list."
320 fi
321 ;;
322 +*)
323 value=${1#+}
324 # Check if the group type is in the list of supported group types.
325 if ! isoneof value ${VPN_SUPPORTED_GROUP_TYPES}; then
326 # We do not break here because the processing of other maybe valid values are indepent from this error.
327 log ERROR "${value} is not a supported group type and can thats why not added to the list of group types."
328 else
329 if list_match ${value} ${GROUP_TYPE}; then
330 log WARNING "${value} is already in the list of group-types of this policy."
331 else
332 list_append GROUP_TYPE ${value}
333 fi
334 fi
335 ;;
336 esac
337 shift
338 done
339
340 # Check if the list contain at least one valid group-type
341 if [ $(list_length ${GROUP_TYPE}) -ge 1 ]; then
342 if ! vpn_security_policies_write_config_key ${name} "GROUP_TYPE" ${GROUP_TYPE}; then
343 log ERROR "The changes for the vpn security policy ${name} could not be written."
344 fi
345 else
346 log ERROR "After proceding all group types the list is empty and thats why no changes are written."
347 return ${EXIT_ERROR}
348 fi
349}
6740c9c5
MT
350
351# This function parses the parameters for the 'integrity' command
3eae7bed 352vpn_security_policies_integrity(){
3eae7bed
JS
353 local name=${1}
354 shift
355
356 if [ $# -eq 0 ]; then
357 log ERROR "You must pass at least one value after integrity."
358 return ${EXIT_ERROR}
359 fi
360
361 local INTEGRITY
3eae7bed
JS
362 if ! vpn_security_policies_read_config ${name} "INTEGRITY"; then
363 return ${EXIT_ERROR}
364 fi
365
366 # Remove duplicated entries to proceed the list safely
367 INTEGRITY="$(list_unique ${INTEGRITY})"
368
369 while [ $# -gt 0 ]; do
370 case "${1}" in
371 -*)
372 value=${1#-}
373 # Check if the integrity hash is in the list of integrity hashes and
374 # check if the list has after removing this integrity hash at least one valid value
375 if list_match ${value} ${INTEGRITY}; then
376 list_remove INTEGRITY ${value}
377 else
378 # We do not break here because the processing of other maybe valid values are indepent from this error.
379 log ERROR "Can not remove ${value} from the list of integrity hashes because ${value} is not in the list."
380 fi
381 ;;
382 +*)
383 value=${1#+}
384 # Check if the Ciphers is in the list of supported integrity hashes.
385 if ! isoneof value ${VPN_SUPPORTED_INTEGRITY}; then
386 # We do not break here because the processing of other maybe valid values are indepent from this error.
387 log ERROR "${value} is not a supported integrity hash and can thats why not added to the list of integrity hashes."
388 else
389 if list_match ${value} ${INTEGRITY}; then
390 log WARNING "${value} is already in the list of integrety hashes of this policy."
391 else
392 list_append INTEGRITY ${value}
393 fi
394 fi
395 ;;
396 esac
397 shift
398 done
399
400 # Check if the list contain at least one valid group-type
401 if [ $(list_length ${INTEGRITY}) -ge 1 ]; then
402 if ! vpn_security_policies_write_config_key ${name} "INTEGRITY" ${INTEGRITY}; then
403 log ERROR "The changes for the vpn security policy ${name} could not be written."
404 fi
405 else
406 log ERROR "After proceding all integrity hashes the list is empty and thats why no changes are written."
407 return ${EXIT_ERROR}
408 fi
3eae7bed
JS
409}
410
6740c9c5 411# This function parses the parameters for the 'key-exchange' command
3eae7bed 412vpn_security_policies_key_exchange() {
3eae7bed
JS
413 local name=${1}
414 local value=${2}
6740c9c5 415
3eae7bed
JS
416 # Check if we get only one argument after key-exchange <name>
417 if [ ! $# -eq 2 ]; then
418 log ERROR "The number of arguments do not match. Only argument after key-exchange is allowed."
419 return ${EXIT_ERROR}
420 fi
421
3eae7bed
JS
422 if ! isoneof value "ikev1" "ikev2" "IKEV1" "IKEV2"; then
423 log ERROR "Invalid Argument ${value}"
424 return ${EXIT_ERROR}
425 fi
426
427 vpn_security_policies_write_config_key "${name}" "KEY_EXCHANGE" "${value,,}"
428}
429
6740c9c5 430# This function parses the parameters for the 'lifetime' command.
3eae7bed 431vpn_security_policies_lifetime(){
3eae7bed
JS
432 local name=${1}
433 shift
6740c9c5 434
3eae7bed
JS
435 local value=$@
436
437 # Check if we get only one argument after lifetime <name>
438 if [ ! $# -ge 1 ]; then
439 log ERROR "The number of arguments do not match you must provide at least one integer value or a valid time with the format <hours>h <minutes>m <seconds>s"
440 return ${EXIT_ERROR}
441 fi
442
443 if ! isinteger value; then
444 value=$(parse_time $@)
445 if [ ! $? -eq 0 ]; then
446 log ERROR "Parsing the passed time was not sucessful please check the passed values."
447 return ${EXIT_ERROR}
448 fi
449 fi
450
451 if [ ${value} -le 0 ]; then
452 log ERROR "The passed time value must be in the sum greater zero seconds."
453 return ${EXIT_ERROR}
454 fi
455
456 vpn_security_policies_write_config_key "${name}" "LIFETIME" "${value}"
457}
458
6740c9c5 459# This function parses the parameters for the 'pfs' command
3eae7bed 460vpn_security_policies_pfs(){
3eae7bed
JS
461 local name=${1}
462 local value=${2}
463
464 # Check if we get only one argument after pfs <name>
465 if [ ! $# -eq 2 ]; then
466 log ERROR "The number of arguments do not match. Only argument after pfs is allowed."
467 return ${EXIT_ERROR}
468 fi
469
470 if [ ! $# -eq 2 ] || ! isbool value; then
471 # We suggest only two values to avoid overburding the user.
472 log ERROR "Invalid Argument ${value}"
473 return ${EXIT_ERROR}
474 fi
475
476 vpn_security_policies_write_config_key "${name}" "PFS" "${value}"
477}
478
6740c9c5
MT
479# This function checks if a vpn security policy name is valid
480# Allowed are only A-Za-z0-9
3eae7bed 481vpn_security_policies_check_name() {
3eae7bed 482 assert [ $# -eq 1 ]
6740c9c5 483
3eae7bed 484 local name=${1}
6740c9c5 485
3eae7bed
JS
486 [[ ${name} =~ [^[:alnum:]$] ]]
487}
488
6740c9c5 489# Function that creates based on the paramters one ore more new vpn security policies
3eae7bed 490vpn_security_policies_new() {
58aa0edf
MT
491 if [ $# -gt 1 ]; then
492 error "Too many arguments"
3eae7bed
JS
493 return ${EXIT_ERROR}
494 fi
495
58aa0edf
MT
496 local name="${1}"
497 if ! isset name; then
498 error "Please provide a name"
499 return ${EXIT_ERROR}
500 fi
3eae7bed 501
58aa0edf
MT
502 # Check for duplicates
503 if vpn_security_policy_exists "${name}"; then
504 error "The VPN security policy with name ${name} already exists"
505 return ${EXIT_ERROR}
506 fi
3eae7bed 507
58aa0edf
MT
508 # Check if name is valid
509 if vpn_security_policies_check_name "${name}"; then
510 error "'${name}' contains illegal characters"
511 return ${EXIT_ERROR}
512 fi
3eae7bed 513
58aa0edf
MT
514 # Check if we have a read-only policy with the same name
515 if vpn_security_policies_check_readonly "${name}"; then
516 error "The VPN security policy ${name} is read-only"
517 return ${EXIT_ERROR}
518 fi
519
520 log DEBUG "Creating VPN Security Policy ${name}"
521
522 if copy "$(vpn_security_policies_path "system")" "$(vpn_security_policies_path ${name})"; then
523 log INFO "VPN Security Policy ${name} successfully created"
524 else
525 log ERROR "Could not create VPN Security Policy ${name}"
526 return ${EXIT_ERROR}
527 fi
3eae7bed
JS
528}
529
6740c9c5 530# Function that deletes based on the passed parameters one ore more vpn security policies
3eae7bed 531vpn_security_policies_destroy() {
3eae7bed
JS
532 local name
533 for name in $@; do
534 if ! vpn_security_policy_exists ${name}; then
535 log ERROR "The vpn security policy ${name} does not exist."
536 continue
537 fi
538
539 if vpn_security_policies_check_readonly ${name}; then
540 log ERROR "The vpn security policy ${name} cannot be deleted."
541 continue
542 fi
543
544 log DEBUG "Deleting vpn security policy ${name}"
545 settings_remove $(vpn_security_policies_path ${name})
546 done
547}