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