]> git.ipfire.org Git - people/stevee/network.git/blob - src/functions/functions.ipsec
72838363ef69549cdc8d847983590c541b0906f3
[people/stevee/network.git] / src / functions / functions.ipsec
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_CONNECTION_CONFIG_SETTINGS="\
23 AUTH_MODE \
24 DPD_ACTION \
25 DPD_DELAY \
26 DPD_TIMEOUT \
27 INACTIVITY_TIMEOUT \
28 LOCAL_ADDRESS \
29 LOCAL_ID \
30 LOCAL_PREFIX \
31 MODE \
32 PEER \
33 POOLS \
34 PSK \
35 REMOTE_ID \
36 REMOTE_PREFIX \
37 SECURITY_POLICY \
38 START_ACTION \
39 TYPE \
40 ENABLED"
41
42 IPSEC_POOL_CONFIG_SETTINGS="\
43 DNS_SERVER \
44 NETWORK \
45 TYPE"
46
47 # Default values
48 IPSEC_DEFAULT_AUTH_MODE="PSK"
49 IPSEC_DEFAULT_DPD_ACTION="restart"
50 IPSEC_DEFAULT_DPD_DELAY="30"
51 IPSEC_DEFAULT_DPD_TIMEOUT="120"
52 IPSEC_DEFAULT_ENABLED="true"
53 IPSEC_DEFAULT_INACTIVITY_TIMEOUT="0"
54 IPSEC_DEFAULT_MODE="tunnel"
55 IPSEC_DEFAULT_SECURITY_POLICY="system"
56 IPSEC_DEFAULT_START_ACTION="on-demand"
57 IPSEC_DEFAULT_TYPE="net-to-net"
58
59 IPSEC_VALID_MODES="gre-transport tunnel vti"
60 IPSEC_VALID_AUTH_MODES="PSK"
61
62 cli_ipsec() {
63 local action=${1}
64 shift 1
65
66 case "${action}" in
67 connection)
68 cli_ipsec_connection $@
69 ;;
70 pool)
71 cli_ipsec_pool $@
72 ;;
73 *)
74 error "Unrecognized argument: ${action}"
75 exit ${EXIT_ERROR}
76 ;;
77 esac
78 }
79
80 cli_ipsec_connection() {
81 if ipsec_connection_exists ${1}; then
82 local connection=${1}
83 local key=${2}
84 key=${key//-/_}
85 shift 2
86
87 case "${key}" in
88 authentication|down|disable|dpd|enable|inactivity_timeout|local|mode|peer|pool|remote|security_policy|start_action|up)
89 ipsec_connection_${key} ${connection} $@
90 ;;
91 show)
92 cli_ipsec_connection_show "${connection}"
93 exit $?
94 ;;
95 *)
96 error "Unrecognized argument: ${key}"
97 exit ${EXIT_ERROR}
98 ;;
99 esac
100 else
101 local action=${1}
102 shift
103
104 case "${action}" in
105 new)
106 ipsec_connection_new $@
107 ;;
108 destroy)
109 cli_ipsec_connection_destroy $@
110 ;;
111 ""|*)
112 if [ -n "${action}" ]; then
113 error "Unrecognized argument: '${action}'"
114 fi
115 exit ${EXIT_ERROR}
116 ;;
117 esac
118 fi
119 }
120
121 cli_ipsec_pool() {
122 if ipsec_pool_exists ${1}; then
123 local pool=${1}
124 local key=${2}
125 key=${key//-/_}
126 shift 2
127
128 case "${key}" in
129 dns_server|network)
130 ipsec_pool_${key} ${pool} $@
131 ;;
132 show)
133 cli_ipsec_pool_show "${pool}"
134 exit $?
135 ;;
136 *)
137 error "Unrecognized argument: ${key}"
138 exit ${EXIT_ERROR}
139 ;;
140 esac
141 else
142 local action=${1}
143 shift
144
145 case "${action}" in
146 new)
147 ipsec_pool_new $@
148 ;;
149 destroy)
150 ipsec_pool_destroy $@
151 ;;
152 ""|*)
153 if [ -n "${action}" ]; then
154 error "Unrecognized argument: '${action}'"
155 fi
156 exit ${EXIT_ERROR}
157 ;;
158 esac
159 fi
160 }
161
162 cli_ipsec_connection_destroy() {
163 local connection="${1}"
164
165 if ! ipsec_connection_destroy "${connection}"; then
166 return ${EXIT_ERROR}
167 fi
168
169 # Inform strongswan about the changes
170 ipsec_strongswan_load
171
172 # Configure strongswan autostart
173 ipsec_strongswan_autostart
174 }
175
176 cli_ipsec_connection_show() {
177 local connection="${1}"
178
179 # Read the config settings
180 local ${IPSEC_CONNECTION_CONFIG_SETTINGS}
181 if ! ipsec_connection_read_config "${connection}"; then
182 error "Could not read the connection configuration"
183 return ${EXIT_ERROR}
184 fi
185
186 cli_headline 0 "IPsec VPN Connection: ${connection}"
187 cli_space
188
189 # Peer
190 if isset PEER; then
191 cli_print_fmt1 1 "Peer" "${PEER}"
192 fi
193
194 # Security Policy
195 cli_print_fmt1 1 "Security Policy" "${SECURITY_POLICY-${IPSEC_DEFAULT_SECURITY_POLICY}}"
196 cli_space
197
198 cli_headline 2 "Authentication"
199 case "${AUTH_MODE^^}" in
200 PSK)
201 cli_print_fmt1 2 "Mode" "Pre-Shared-Key"
202
203 if isset PSK; then
204 cli_print_fmt1 2 "Pre-Shared-Key" "****"
205 else
206 cli_print_fmt1 2 "Pre-Shared-Key" "- is not set -"
207 fi
208 ;;
209 X509)
210 : # TODO
211 ;;
212 esac
213 cli_space
214
215 local i
216 for i in LOCAL REMOTE; do
217 case "${i}" in
218 LOCAL)
219 cli_headline 2 "Local"
220 ;;
221 REMOTE)
222 cli_headline 2 "Remote"
223 ;;
224 esac
225
226 local id_var="${i}_ID"
227 if [ -n "${!id_var}" ]; then
228 cli_print_fmt1 2 "ID" "${!id_var}"
229 fi
230
231 local prefix_var="${i}_PREFIX"
232 if isset ${prefix_var}; then
233 cli_headline 3 "Prefix(es)"
234
235 local prefix
236 for prefix in ${!prefix_var}; do
237 cli_print_fmt1 3 "${prefix}"
238 done
239 fi
240
241 cli_space
242 done
243
244 cli_headline 2 "Misc."
245
246 case "${MODE}" in
247 gre-transport)
248 cli_print_fmt1 2 "Transport Mode" "GRE Transport"
249 ;;
250 tunnel)
251 cli_print_fmt1 2 "Transport Mode" "Tunnel"
252 ;;
253 vti)
254 cli_print_fmt1 2 "Transport Mode" "Virtual Tunnel Interface"
255 ;;
256 *)
257 cli_print_fmt1 2 "Transport Mode" "- Unknown -"
258 ;;
259 esac
260
261 # Inactivity timeout
262 if isset INACTIVITY_TIMEOUT && [ ${INACTIVITY_TIMEOUT} -gt 0 ]; then
263 cli_print_fmt1 2 "Inactivity Timeout" "$(format_time ${INACTIVITY_TIMEOUT})"
264 fi
265 cli_space
266
267 return ${EXIT_OK}
268 }
269
270 ipsec_connection_disable() {
271 local connection=${1}
272
273 if ! ipsec_connection_write_config_key "${connection}" "ENABLED" "false"; then
274 log ERROR "Could not write configuration settings"
275 return ${EXIT_ERROR}
276 fi
277
278 # Configure strongswan autostart
279 ipsec_strongswan_autostart
280 }
281
282 ipsec_connection_enable() {
283 local connection=${1}
284
285 if ! ipsec_connection_write_config_key "${connection}" "ENABLED" "true"; then
286 log ERROR "Could not write configuration settings"
287 return ${EXIT_ERROR}
288 fi
289
290 # Configure strongswan autostart
291 ipsec_strongswan_autostart
292 }
293
294 # This function writes all values to a via ${connection} specificated VPN IPsec configuration file
295 ipsec_connection_write_config() {
296 assert [ $# -ge 1 ]
297
298 local connection="${1}"
299
300 if ! ipsec_connection_exists "${connection}"; then
301 log ERROR "No such VPN IPsec connection: ${connection}"
302 return ${EXIT_ERROR}
303 fi
304
305 local path="${NETWORK_IPSEC_CONNS_DIR}/${connection}/settings"
306
307 if ! settings_write "${path}" ${IPSEC_CONNECTION_CONFIG_SETTINGS}; then
308 log ERROR "Could not write configuration settings for VPN IPsec connection ${connection}"
309 return ${EXIT_ERROR}
310 fi
311
312 ipsec_reload ${connection}
313 }
314
315 # This funtion writes the value for one key to a via ${connection} specificated VPN IPsec connection configuration file
316 ipsec_connection_write_config_key() {
317 assert [ $# -ge 3 ]
318
319 local connection=${1}
320 local key=${2}
321 shift 2
322
323 local value="$@"
324
325 if ! ipsec_connection_exists "${connection}"; then
326 log ERROR "No such VPN ipsec connection: ${connection}"
327 return ${EXIT_ERROR}
328 fi
329
330 log DEBUG "Set '${key}' to new value '${value}' in VPN ipsec connection '${connection}'"
331
332 local ${IPSEC_CONNECTION_CONFIG_SETTINGS}
333
334 # Read the config settings
335 if ! ipsec_connection_read_config "${connection}"; then
336 return ${EXIT_ERROR}
337 fi
338
339 # Set the key to a new value
340 assign "${key}" "${value}"
341
342 if ! ipsec_connection_write_config "${connection}"; then
343 return ${EXIT_ERROR}
344 fi
345
346 return ${EXIT_TRUE}
347 }
348
349 # Reads one or more keys out of a settings file or all if no key is provided.
350 ipsec_connection_read_config() {
351 assert [ $# -ge 1 ]
352
353 local connection="${1}"
354 shift 1
355
356 if ! ipsec_connection_exists "${connection}"; then
357 log ERROR "No such VPN IPsec connection : ${connection}"
358 return ${EXIT_ERROR}
359 fi
360
361
362 local args
363 if [ $# -eq 0 ] && [ -n "${IPSEC_CONNECTION_CONFIG_SETTINGS}" ]; then
364 list_append args ${IPSEC_CONNECTION_CONFIG_SETTINGS}
365 else
366 list_append args $@
367 fi
368
369 local path="${NETWORK_IPSEC_CONNS_DIR}/${connection}/settings"
370
371 if ! settings_read "${path}" ${args}; then
372 log ERROR "Could not read settings for VPN IPsec connection ${connection}"
373 return ${EXIT_ERROR}
374 fi
375 }
376
377 # This function checks if a vpn ipsec connection exists
378 # Returns True when yes and false when not
379 ipsec_connection_exists() {
380 assert [ $# -eq 1 ]
381
382 local connection=${1}
383
384 local path="${NETWORK_IPSEC_CONNS_DIR}/${connection}"
385
386 [ -d "${path}" ] && return ${EXIT_TRUE} || return ${EXIT_FALSE}
387 }
388
389 # Determines if strongswan should be automatically started
390 # when the system boots up.
391 ipsec_strongswan_autostart() {
392 local autostart_needed="false"
393
394 local connection
395 for connection in $(ipsec_list_connections); do
396 local ENABLED
397
398 if ! ipsec_connection_read_config "${connection}" "ENABLED"; then
399 log WARNING "Could not read configuation"
400 continue
401 fi
402
403 if enabled ENABLED; then
404 autostart_needed="true"
405 break
406 fi
407 done
408
409 # Start strongswan when we need it and when it is not yet enabled
410 if ${autostart_needed}; then
411 if ! service_is_enabled "strongswan"; then
412 service_enable "strongswan"
413 fi
414
415 if ! service_is_active "strongswan"; then
416 service_start "strongswan"
417 fi
418
419 # Disable strongswan when we do not need it but it is enabled
420 elif ! ${autostart_needed}; then
421 if service_is_enabled "strongswan"; then
422 service_disable "strongswan"
423 fi
424
425 if service_is_active "strongswan"; then
426 service_stop "strongswan"
427 fi
428 fi
429 }
430
431 ipsec_strongswan_load() {
432 # Do nothing if strongswan is not running
433 if ! service_is_active "strongswan"; then
434 return ${EXIT_OK}
435 fi
436
437 if ! cmd swanctl --load-all; then
438 log ERROR "Could not reload strongswan config"
439 return ${EXIT_ERROR}
440 fi
441 }
442
443 # Reloads the connection after config changes
444 ipsec_reload() {
445 local connection=${1}
446
447 local ENABLED
448
449 if ! ipsec_connection_read_config "${connection}" "ENABLED"; then
450 log ERROR "Could not read configuration for IPsec connection ${connection}"
451 return ${EXIT_ERROR}
452 fi
453
454 if enabled ENABLED; then
455 if ! ipsec_connection_to_strongswan ${connection}; then
456 log ERROR "Could not generate strongswan config for ${connnection}"
457 return ${EXIT_ERROR}
458 fi
459 else
460 log DEBUG "Deleting strongswan config ${NETWORK_IPSEC_SWANCTL_CONNECTIONS_DIR}/${connection}.conf"
461 unlink "${NETWORK_IPSEC_SWANCTL_CONNECTIONS_DIR}/${connection}.conf"
462 fi
463
464 ipsec_strongswan_load
465 }
466
467 # Handle the cli after authentification
468 ipsec_connection_authentication() {
469 if [ ! $# -gt 1 ]; then
470 log ERROR "Not enough arguments"
471 return ${EXIT_ERROR}
472 fi
473
474 local connection=${1}
475 local cmd=${2}
476 shift 2
477
478 case ${cmd} in
479 mode)
480 ipsec_connection_authentication_mode "${connection}" $@
481 ;;
482 pre-shared-key)
483 ipsec_connection_authentication_psk "${connection}" $@
484 ;;
485 *)
486 log ERROR "Unrecognized argument: ${cmd}"
487 return ${EXIT_ERROR}
488 ;;
489 esac
490 }
491
492 # Set the authentification mode
493 ipsec_connection_authentication_mode() {
494 if [ ! $# -eq 2 ]; then
495 log ERROR "Not enough arguments"
496 return ${EXIT_ERROR}
497 fi
498 local connection=${1}
499 local mode=${2}
500
501 if ! isoneof mode ${IPSEC_VALID_AUTH_MODES}; then
502 log ERROR "Auth mode '${mode}' is invalid"
503 return ${EXIT_ERROR}
504 fi
505
506 if ! ipsec_connection_write_config_key "${connection}" "AUTH_MODE" ${mode^^}; then
507 log ERROR "Could not write configuration settings"
508 return ${EXIT_ERROR}
509 fi
510 }
511
512 # Set the psk
513 ipsec_connection_authentication_psk() {
514 if [ ! $# -eq 2 ]; then
515 log ERROR "Not enough arguments"
516 return ${EXIT_ERROR}
517 fi
518
519 local connection=${1}
520 local psk=${2}
521
522 local length=${#psk}
523
524 if [ ${length} -lt 4 ]; then
525 error "The PSK must be longer than four characters"
526 return ${EXIT_ERROR}
527 fi
528
529 if [ ${length} -gt 128 ]; then
530 error "The PSK cannot be longer than 128 characters"
531 return ${EXIT_ERROR}
532 fi
533
534 if ! ipsec_connection_write_config_key "${connection}" "PSK" "${psk}"; then
535 log ERROR "Could not write configuration settings"
536 return ${EXIT_ERROR}
537 fi
538
539 return ${EXIT_OK}
540 }
541
542 ipsec_connection_up() {
543 local connection="${1}"
544
545 if ! ipsec_connection_exists "${connection}"; then
546 error "No such VPN IPsec connection: ${connection}"
547 return ${EXIT_ERROR}
548 fi
549
550 cmd swanctl --initiate --child "${connection}"
551 }
552
553 ipsec_connection_down() {
554 local connection="${1}"
555
556 if ! ipsec_connection_exists "${connection}"; then
557 error "No such VPN IPsec connection: ${connection}"
558 return ${EXIT_ERROR}
559 fi
560
561 cmd swanctl --terminate --ike "${connection}"
562 }
563
564 # Handle the cli after authentification
565 ipsec_connection_dpd() {
566 if [ ! $# -gt 1 ]; then
567 log ERROR "Not enough arguments"
568 return ${EXIT_ERROR}
569 fi
570
571 local connection=${1}
572 local cmd=${2}
573 shift 2
574
575 case ${cmd} in
576 action)
577 ipsec_connection_dpd_action "${connection}" $@
578 ;;
579 delay)
580 ipsec_connection_dpd_delay "${connection}" $@
581 ;;
582 timeout)
583 ipsec_connection_dpd_timeout "${connection}" $@
584 ;;
585 *)
586 log ERROR "Unrecognized argument: ${cmd}"
587 return ${EXIT_ERROR}
588 ;;
589 esac
590 }
591
592 # Set the default dpd action
593 ipsec_connection_dpd_action() {
594 if [ ! $# -eq 2 ]; then
595 log ERROR "Not enough arguments"
596 return ${EXIT_ERROR}
597 fi
598 local connection=${1}
599 local action=${2}
600
601 if ! isoneof action "restart" "clear"; then
602 log ERROR "dpd action '${action}' is invalid"
603 return ${EXIT_ERROR}
604 fi
605
606 if ! ipsec_connection_write_config_key "${connection}" "DPD_ACTION" ${action}; then
607 log ERROR "Could not write configuration settings"
608 return ${EXIT_ERROR}
609 fi
610 }
611
612 # Set the dpd delay
613 ipsec_connection_dpd_delay() {
614 if [ ! $# -ge 2 ]; then
615 log ERROR "Not enough arguments"
616 return ${EXIT_ERROR}
617 fi
618
619 local connection=${1}
620 shift 1
621 local value=$@
622
623 if ! isinteger value; then
624 value=$(parse_time $@)
625 if [ ! $? -eq 0 ]; then
626 log ERROR "Parsing the passed time was not sucessful please check the passed values."
627 return ${EXIT_ERROR}
628 fi
629 fi
630
631 if [ ${value} -lt 0 ]; then
632 log ERROR "The passed time value must be in the sum greater or equal zero seconds."
633 return ${EXIT_ERROR}
634 fi
635
636 if ! ipsec_connection_write_config_key "${connection}" "DPD_DELAY" ${value}; then
637 log ERROR "Could not write configuration settings"
638 return ${EXIT_ERROR}
639 fi
640
641 return ${EXIT_OK}
642 }
643
644 # Set the dpd timeout
645 ipsec_connection_dpd_timeout() {
646 if [ ! $# -ge 2 ]; then
647 log ERROR "Not enough arguments"
648 return ${EXIT_ERROR}
649 fi
650
651 local connection=${1}
652 shift 1
653 local value=$@
654
655 if ! isinteger value; then
656 value=$(parse_time $@)
657 if [ ! $? -eq 0 ]; then
658 log ERROR "Parsing the passed time was not sucessful please check the passed values."
659 return ${EXIT_ERROR}
660 fi
661 fi
662
663 if [ ${value} -le 0 ]; then
664 log ERROR "The passed time value must be in the sum greater or equal zero seconds."
665 return ${EXIT_ERROR}
666 fi
667
668 if ! ipsec_connection_write_config_key "${connection}" "DPD_TIMEOUT" ${value}; then
669 log ERROR "Could not write configuration settings"
670 return ${EXIT_ERROR}
671 fi
672
673 return ${EXIT_OK}
674 }
675
676 # Handle the cli after local
677 ipsec_connection_local() {
678 if [ ! $# -ge 2 ]; then
679 log ERROR "Not enough arguments"
680 return ${EXIT_ERROR}
681 fi
682
683 local connection=${1}
684 local cmd=${2}
685 shift 2
686
687 case ${cmd} in
688 address)
689 ipsec_connection_local_address "${connection}" $@
690 ;;
691 id)
692 ipsec_connection_id "${connection}" "LOCAL" $@
693 ;;
694 prefix)
695 ipsec_connection_prefix "${connection}" "LOCAL" $@
696 ;;
697 *)
698 log ERROR "Unrecognized argument: ${cmd}"
699 return ${EXIT_ERROR}
700 ;;
701 esac
702
703 return ${EXIT_OK}
704 }
705
706 # Set the connection mode
707 ipsec_connection_mode() {
708 if [ ! $# -eq 2 ]; then
709 log ERROR "Not enough arguments"
710 return ${EXIT_ERROR}
711 fi
712 local connection=${1}
713 local mode=${2}
714
715 if ! isoneof mode ${IPSEC_VALID_MODES}; then
716 log ERROR "Mode '${mode}' is invalid"
717 return ${EXIT_ERROR}
718 fi
719
720 if ! ipsec_connection_write_config_key "${connection}" "MODE" ${mode}; then
721 log ERROR "Could not write configuration settings"
722 return ${EXIT_ERROR}
723 fi
724
725 return ${EXIT_OK}
726 }
727
728 # Set the local address
729 ipsec_connection_local_address() {
730 if [ ! $# -eq 2 ]; then
731 log ERROR "Not enough arguments"
732 return ${EXIT_ERROR}
733 fi
734 local connection=${1}
735 local local_address=${2}
736
737 if ! ipsec_connection_check_peer ${local_address}; then
738 log ERROR "Local address '${local_address}' is invalid"
739 return ${EXIT_ERROR}
740 fi
741
742 if ! ipsec_connection_write_config_key "${connection}" "LOCAL_ADDRESS" ${local_address}; then
743 log ERROR "Could not write configuration settings"
744 return ${EXIT_ERROR}
745 fi
746
747 return ${EXIT_OK}
748 }
749
750 # Set the peer to connect to
751 ipsec_connection_peer() {
752 if [ ! $# -eq 2 ]; then
753 log ERROR "Not enough arguments"
754 return ${EXIT_ERROR}
755 fi
756 local connection=${1}
757 local peer=${2}
758
759 if ! ipsec_connection_check_peer ${peer}; then
760 log ERROR "Peer '${peer}' is invalid"
761 return ${EXIT_ERROR}
762 fi
763
764 if ! ipsec_connection_write_config_key "${connection}" "PEER" ${peer}; then
765 log ERROR "Could not write configuration settings"
766 return ${EXIT_ERROR}
767 fi
768
769 return ${EXIT_OK}
770 }
771
772 #Set the local or remote id
773 ipsec_connection_id() {
774 if [ ! $# -eq 3 ]; then
775 log ERROR "Not enough arguments"
776 return ${EXIT_ERROR}
777 fi
778 local connection=${1}
779 local type=${2}
780 local id=${3}
781
782 if ! ipsec_connection_check_id ${id}; then
783 log ERROR "Id '${id}' is invalid"
784 return ${EXIT_ERROR}
785 fi
786
787 if ! ipsec_connection_write_config_key "${connection}" "${type}_ID" ${id}; then
788 log ERROR "Could not write configuration settings"
789 return ${EXIT_ERROR}
790 fi
791
792 return ${EXIT_OK}
793 }
794
795 # Set the local or remote prefix
796 ipsec_connection_prefix() {
797 if [ ! $# -ge 3 ]; then
798 log ERROR "Not enough arguments"
799 return ${EXIT_ERROR}
800 fi
801 local connection=${1}
802 local type=${2}
803 shift 2
804
805 local _prefix="${type}_PREFIX"
806 local "${_prefix}"
807 if ! ipsec_connection_read_config "${connection}" "${_prefix}"; then
808 return ${EXIT_ERROR}
809 fi
810
811 # Remove duplicated entries to proceed the list safely
812 assign "${_prefix}" "$(list_unique ${!_prefix} )"
813
814 local prefixes_added
815 local prefixes_removed
816 local prefixes_set
817
818 while [ $# -gt 0 ]; do
819 local arg="${1}"
820
821 case "${arg}" in
822 +*)
823 list_append prefixes_added "${arg:1}"
824 ;;
825 -*)
826 list_append prefixes_removed "${arg:1}"
827 ;;
828 [A-Fa-f0-9]*)
829 list_append prefixes_set "${arg}"
830 ;;
831 *)
832 error "Invalid argument: ${arg}"
833 return ${EXIT_ERROR}
834 ;;
835 esac
836 shift
837 done
838
839 # Check if the user is trying a mixed operation
840 if ! list_is_empty prefixes_set && (! list_is_empty prefixes_added || ! list_is_empty prefixes_removed); then
841 error "You cannot reset the prefix list and add or remove prefixes at the same time"
842 return ${EXIT_ERROR}
843 fi
844
845 # Set new prefix list
846 if ! list_is_empty prefixes_set; then
847 # Check if all prefixes are valid
848 local prefix
849 for prefix in ${prefixes_set}; do
850 if ! ip_net_is_valid ${prefix}; then
851 error "Unsupported prefix: ${prefix}"
852 return ${EXIT_ERROR}
853 fi
854 done
855
856 assign "${_prefix}" "${prefixes_set}"
857
858 # Perform incremental updates
859 else
860 local prefix
861
862 # Perform all removals
863 for prefix in ${prefixes_removed}; do
864 if ! list_remove "${_prefix}" ${prefix}; then
865 warning "${prefix} was not on the list and could not be removed"
866 fi
867 done
868
869
870 for prefix in ${prefixes_added}; do
871 if ip_net_is_valid ${prefix}; then
872 if ! list_append_unique "${_prefix}" ${prefix}; then
873 warning "${prefix} is already on the prefix list"
874 fi
875 else
876 warning "${prefix} is not a valid IP network and could not be added"
877 fi
878 done
879 fi
880
881 # Check if the list contain at least one valid prefix
882 if list_is_empty ${_prefix}; then
883 error "Cannot save an empty prefix list"
884 return ${EXIT_ERROR}
885 fi
886
887 # Save everything
888 if ! ipsec_connection_write_config_key "${connection}" "${_prefix}" ${!_prefix}; then
889 log ERROR "Could not write configuration settings"
890 fi
891
892 return ${EXIT_OK}
893 }
894
895 # Set the pools to use
896 ipsec_connection_pool() {
897 if [ ! $# -ge 2 ]; then
898 log ERROR "Not enough arguments"
899 return ${EXIT_ERROR}
900 fi
901 local connection=${1}
902 shift
903
904 local POOLS
905 if ! ipsec_connection_read_config "${connection}" "POOLS"; then
906 return ${EXIT_ERROR}
907 fi
908
909 # Remove duplicated entries to proceed the list safely
910 assign "POOLS" "$(list_unique ${POOLS})"
911
912 local pools_added
913 local pools_removed
914 local pools_set
915
916 while [ $# -gt 0 ]; do
917 local arg="${1}"
918
919 case "${arg}" in
920 +*)
921 list_append pools_added "${arg:1}"
922 ;;
923 -*)
924 list_append pools_removed "${arg:1}"
925 ;;
926 [A-Za-z0-9]*)
927 list_append pools_set "${arg}"
928 ;;
929 *)
930 error "Invalid argument: ${arg}"
931 return ${EXIT_ERROR}
932 ;;
933 esac
934 shift
935 done
936
937 # Check if the user is trying a mixed operation
938 if ! list_is_empty pools_set && (! list_is_empty pools_added || ! list_is_empty pools_removed); then
939 error "You cannot reset the pools list and add or remove pools at the same time"
940 return ${EXIT_ERROR}
941 fi
942
943 # Set new pools list
944 if ! list_is_empty pools_set; then
945 # Check if all pools are valid
946 local pool
947 for pool in ${pools_set}; do
948 if ! ipsec_pool_exists ${pool} || ! ipsec_pool_check_config ${pool}; then
949 error "Pool ${pool} is not valid"
950 return ${EXIT_ERROR}
951 fi
952 done
953
954 assign "POOLS" "${pools_set}"
955
956 # Perform incremental updates
957 else
958 local pool
959
960 # Perform all removals
961 for pool in ${pools_removed}; do
962 if ! list_remove "POOLS" ${pool}; then
963 warning "${pool} was not on the list and could not be removed"
964 fi
965 done
966
967
968 for pool in ${pools_added}; do
969 if ipsec_pool_exists ${pool} && ipsec_pool_check_config ${pool}; then
970 if ! list_append_unique "POOLS" ${pool}; then
971 warning "${pool} is already on the prefix list"
972 fi
973 else
974 warning "${pool} is not a valid pool"
975 fi
976 done
977 fi
978
979 # Check if the list contain at least one valid pool
980 if list_is_empty POOLS; then
981 error "Cannot save an empty pool list"
982 return ${EXIT_ERROR}
983 fi
984
985 # Save everything
986 if ! ipsec_connection_write_config_key "${connection}" "POOLS" ${POOLS}; then
987 log ERROR "Could not write configuration settings"
988 fi
989
990 return ${EXIT_OK}
991 }
992
993 # Handle the cli after remote
994 ipsec_connection_remote() {
995 if [ ! $# -ge 2 ]; then
996 log ERROR "Not enough arguments"
997 return ${EXIT_ERROR}
998 fi
999
1000 local connection=${1}
1001 local cmd=${2}
1002 shift 2
1003
1004 case ${cmd} in
1005 id)
1006 ipsec_connection_id "${connection}" "REMOTE" $@
1007 ;;
1008
1009 prefix)
1010 ipsec_connection_prefix "${connection}" "REMOTE" $@
1011 ;;
1012 *)
1013 log ERROR "Unrecognized argument: ${cmd}"
1014 return ${EXIT_ERROR}
1015 ;;
1016 esac
1017
1018 return ${EXIT_OK}
1019 }
1020
1021 # Set the inactivity timeout
1022 ipsec_connection_inactivity_timeout() {
1023 if [ ! $# -ge 2 ]; then
1024 log ERROR "Not enough arguments"
1025 return ${EXIT_ERROR}
1026 fi
1027
1028 local connection=${1}
1029 shift 1
1030 local value=$@
1031
1032 if ! isinteger value; then
1033 value=$(parse_time $@)
1034 if [ ! $? -eq 0 ]; then
1035 log ERROR "Parsing the passed time was not sucessful please check the passed values."
1036 return ${EXIT_ERROR}
1037 fi
1038 fi
1039
1040 if [ ${value} -le 0 ]; then
1041 log ERROR "The passed time value must be in the sum greater zero seconds."
1042 return ${EXIT_ERROR}
1043 fi
1044
1045 if ! ipsec_connection_write_config_key "${connection}" "INACTIVITY_TIMEOUT" ${value}; then
1046 log ERROR "Could not write configuration settings"
1047 return ${EXIT_ERROR}
1048 fi
1049
1050 return ${EXIT_OK}
1051 }
1052
1053 # Set the default start action
1054 ipsec_connection_start_action() {
1055 if [ ! $# -eq 2 ]; then
1056 log ERROR "Not enough arguments"
1057 return ${EXIT_ERROR}
1058 fi
1059 local connection=${1}
1060 local action=${2}
1061
1062 if ! isoneof action "on-demand" "always-on"; then
1063 log ERROR "Start action '${action}' is invalid"
1064 return ${EXIT_ERROR}
1065 fi
1066
1067 if ! ipsec_connection_write_config_key "${connection}" "START_ACTION" ${action}; then
1068 log ERROR "Could not write configuration settings"
1069 return ${EXIT_ERROR}
1070 fi
1071 }
1072
1073 # Set the security policy to use
1074 ipsec_connection_security_policy() {
1075 if [ ! $# -eq 2 ]; then
1076 log ERROR "Not enough arguments"
1077 return ${EXIT_ERROR}
1078 fi
1079 local connection=${1}
1080 local security_policy=${2}
1081
1082 if ! vpn_security_policy_exists ${security_policy}; then
1083 log ERROR "No such vpn security policy '${security_policy}'"
1084 return ${EXIT_ERROR}
1085 fi
1086
1087 if ! ipsec_connection_write_config_key "${connection}" "SECURITY_POLICY" ${security_policy}; then
1088 log ERROR "Could not write configuration settings"
1089 return ${EXIT_ERROR}
1090 fi
1091 }
1092
1093 # Check if a id is valid
1094 ipsec_connection_check_id() {
1095 assert [ $# -eq 1 ]
1096 local id=${1}
1097
1098 if [[ ${id} =~ ^@[[:alnum:]]+$ ]] || ip_is_valid ${id}; then
1099 return ${EXIT_TRUE}
1100 else
1101 return ${EXIT_FALSE}
1102 fi
1103 }
1104
1105 # Checks if a peer is valid
1106 ipsec_connection_check_peer() {
1107 assert [ $# -eq 1 ]
1108 local peer=${1}
1109
1110 # TODO Accept also FQDNs
1111 if ip_is_valid ${peer}; then
1112 return ${EXIT_TRUE}
1113 else
1114 return ${EXIT_FALSE}
1115 fi
1116 }
1117
1118 # This function checks if a VPN IPsec connection name is valid
1119 # Allowed are only A-Za-z0-9
1120 ipsec_connection_check_name() {
1121 assert [ $# -eq 1 ]
1122
1123 local connection=${1}
1124
1125 [[ "${connection}" =~ [^[:alnum:]$] ]]
1126 }
1127
1128 # Function that creates one VPN IPsec connection
1129 ipsec_connection_new() {
1130 if [ $# -gt 2 ]; then
1131 error "Too many arguments"
1132 return ${EXIT_ERROR}
1133 fi
1134
1135 local connection="${1}"
1136 local type="${2}"
1137
1138 if ! isset connection; then
1139 error "Please provide a connection name"
1140 return ${EXIT_ERROR}
1141 fi
1142
1143 # Check for duplicates
1144 if ipsec_connection_exists "${connection}"; then
1145 error "The VPN IPsec connection ${connection} already exists"
1146 return ${EXIT_ERROR}
1147 fi
1148
1149 # Check if the name of the connection is valid
1150 if ipsec_connection_check_name "${connection}"; then
1151 error "'${connection}' contains illegal characters"
1152 return ${EXIT_ERROR}
1153 fi
1154
1155 # Set TYPE to default if not set by the user
1156 if ! isset type; then
1157 type="${IPSEC_DEFAULT_TYPE}"
1158 fi
1159
1160 if ! isoneof "type" "net-to-net" "host-to-net"; then
1161 error "Type is invalid"
1162 return ${EXIT_ERROR}
1163 fi
1164
1165 log DEBUG "Creating VPN IPsec connection ${connection}"
1166
1167 if ! mkdir -p "${NETWORK_IPSEC_CONNS_DIR}/${connection}"; then
1168 log ERROR "Could not create config directory for ${connection}"
1169 return ${EXIT_ERROR}
1170 fi
1171
1172 local ${IPSEC_CONNECTION_CONFIG_SETTINGS}
1173
1174 AUTH_MODE=${IPSEC_DEFAULT_AUTH_MODE}
1175 DPD_ACTION=${IPSEC_DEFAULT_DPD_ACTION}
1176 DPD_DELAY=${IPSEC_DEFAULT_DPD_DELAY}
1177 DPD_TIMEOUT=${IPSEC_DEFAULT_DPD_TIMEOUT}
1178 ENABLED=${IPSEC_DEFAULT_ENABLED}
1179 MODE=${IPSEC_DEFAULT_MODE}
1180 START_ACTION=${IPSEC_DEFAULT_START_ACTION}
1181 TYPE="${type}"
1182
1183 INACTIVITY_TIMEOUT=${IPSEC_DEFAULT_INACTIVITY_TIMEOUT}
1184 SECURITY_POLICY=${IPSEC_DEFAULT_SECURITY_POLICY}
1185
1186 if ! ipsec_connection_write_config "${connection}"; then
1187 log ERROR "Could not write new config file"
1188 return ${EXIT_ERROR}
1189 fi
1190
1191 # Configure strongswan autostart
1192 ipsec_strongswan_autostart
1193 }
1194
1195 # Function that deletes based on the passed parameters one ore more vpn security policies
1196 ipsec_connection_destroy() {
1197 local connection
1198 for connection in $@; do
1199 if ! ipsec_connection_exists "${connection}"; then
1200 log ERROR "The VPN IPsec connection ${connection} does not exist."
1201 continue
1202 fi
1203
1204 log DEBUG "Deleting VPN IPsec connection ${connection}"
1205
1206 # Delete strongswan configuration file
1207 file_delete "${NETWORK_IPSEC_SWANCTL_CONNECTIONS_DIR}/${connection}.conf"
1208
1209 if ! rm -rf "${NETWORK_IPSEC_CONNS_DIR}/${connection}"; then
1210 log ERROR "Deleting the VPN IPsec connection ${connection} was not sucessful"
1211 return ${EXIT_ERROR}
1212 fi
1213
1214 done
1215 }
1216
1217 # List all ipsec connections
1218 ipsec_list_connections() {
1219 local connection
1220 for connection in ${NETWORK_IPSEC_CONNS_DIR}/*; do
1221 [ -d ${connection} ] || continue
1222 basename ${connection}
1223 done
1224 }
1225
1226 ipsec_connection_to_strongswan() {
1227 local connection="${1}"
1228 log DEBUG "Generating IPsec configuration for ${connection}"
1229
1230 # Read the config settings
1231 local ${IPSEC_CONNECTION_CONFIG_SETTINGS}
1232 if ! ipsec_connection_read_config "${connection}"; then
1233 error "Could not read the connection ${connection}"
1234 return ${EXIT_ERROR}
1235 fi
1236
1237 local path="${NETWORK_IPSEC_SWANCTL_CONNECTIONS_DIR}/${connection}.conf"
1238
1239 (
1240 # Write the connection section
1241 _ipsec_connection_to_strongswan_connection "${connection}"
1242
1243 # Write the secrets section
1244 _ipsec_connection_to_strongswan_secrets "${connection}"
1245
1246 ) > ${path}
1247 }
1248
1249 _ipsec_connection_to_strongswan_connection() {
1250 local connection="${1}"
1251
1252 # Read the security policy
1253 local ${VPN_SECURITY_POLICIES_CONFIG_SETTINGS}
1254 if ! vpn_security_policies_read_config "${SECURITY_POLICY}"; then
1255 return ${EXIT_ERROR}
1256 fi
1257
1258 # Is DPD enabled?
1259 local dpd="false"
1260 if isset DPD_DELAY && isinteger DPD_DELAY && [ ${DPD_DELAY} -gt 0 ]; then
1261 dpd="true"
1262 fi
1263
1264 # Write configuration header
1265 config_header "strongSwan configuration for ${connection}"
1266
1267 print_indent 0 "connections {"
1268 print_indent 1 "${connection} {"
1269
1270 # IKE Version
1271 print_indent 2 "# IKE Version"
1272 case "${KEY_EXCHANGE^^}" in
1273 IKEV1)
1274 print_indent 2 "version = 1"
1275 ;;
1276
1277 # Fall back to IKEv2 for any random values
1278 IKEV2|*)
1279 print_indent 2 "version = 2"
1280 ;;
1281 esac
1282 print # empty line
1283
1284 # Always only keep one connection open at a time
1285 print_indent 2 "# Unique IDs"
1286 print_indent 2 "unique = replace"
1287 print
1288
1289 # Local Address
1290 print_indent 2 "# Local Address"
1291 if isset LOCAL_ADDRESS; then
1292 print_indent 2 "local_addrs = ${LOCAL_ADDRESS}"
1293 else
1294 print_indent 2 "local_addrs = %any"
1295 fi
1296 print
1297
1298 # Remote Address
1299 print_indent 2 "# Remote Address"
1300 if isset PEER; then
1301 print_indent 2 "remote_addrs = ${PEER}"
1302 else
1303 print_indent 2 "remote_addrs = %any"
1304 fi
1305 print
1306
1307 # IKE Proposals
1308 print_indent 2 "# IKE Proposals"
1309 print_indent 2 "proposals = $(vpn_security_policies_make_ike_proposal ${SECURITY_POLICY})"
1310 print
1311
1312 # DPD Settings
1313 if enabled dpd; then
1314 print_indent 2 "# Dead Peer Detection"
1315 print_indent 2 "dpd_delay = ${DPD_DELAY}"
1316
1317 if isset DPD_TIMEOUT; then
1318 print_indent 2 "dpd_timeout = ${DPD_TIMEOUT}"
1319 fi
1320
1321 print
1322 fi
1323
1324 # Fragmentation
1325 print_indent 2 "# Fragmentation"
1326 print_indent 2 "fragmentation = yes"
1327 print
1328
1329
1330 # Host-to-Net specific settings
1331 case "${TYPE}" in
1332 host-to-net)
1333 # Pools
1334 if isset POOLS; then
1335 print_indent 2 "# Pools"
1336 print_indent 2 "pools = $(list_join POOLS ", ")"
1337 print
1338 fi
1339 ;;
1340 esac
1341
1342 # Local
1343 print_indent 2 "local {"
1344
1345 # Local ID
1346 if isset LOCAL_ID; then
1347 print_indent 3 "id = ${LOCAL_ID}"
1348 fi
1349
1350 # Authentication
1351 case "${AUTH_MODE}" in
1352 PSK)
1353 print_indent 3 "auth = psk"
1354 ;;
1355 esac
1356
1357 print_indent 2 "}"
1358 print
1359
1360 # Remote
1361 print_indent 2 "remote {"
1362
1363 # Remote ID
1364 if isset REMOTE_ID; then
1365 print_indent 3 "id = ${REMOTE_ID}"
1366 fi
1367
1368 # Authentication
1369 case "${AUTH_MODE}" in
1370 PSK)
1371 print_indent 3 "auth = psk"
1372 ;;
1373 esac
1374
1375 print_indent 2 "}"
1376 print
1377
1378 # Children
1379
1380 print_indent 2 "children {"
1381 print_indent 3 "${connection} {"
1382
1383 print_indent 4 "# ESP Proposals"
1384 print_indent 4 "esp_proposals = $(vpn_security_policies_make_esp_proposal ${SECURITY_POLICY})"
1385 print
1386
1387 # Traffic Selectors
1388
1389 case "${MODE}" in
1390 gre-*)
1391 print_indent 4 "local_ts = dynamic[gre]"
1392 print_indent 4 "remote_ts = dynamic[gre]"
1393 ;;
1394 *)
1395 # Local Prefixes
1396 if isset LOCAL_PREFIX; then
1397 print_indent 4 "local_ts = $(list_join LOCAL_PREFIX ,)"
1398 else
1399 print_indent 4 "local_ts = dynamic"
1400 fi
1401
1402 # Remote Prefixes
1403 if isset REMOTE_PREFIX; then
1404 print_indent 4 "remote_ts = $(list_join REMOTE_PREFIX ,)"
1405 else
1406 print_indent 4 "remote_ts = dynamic"
1407 fi
1408 ;;
1409 esac
1410 print
1411
1412 # Netfilter Marks
1413 case "${MODE}" in
1414 vti)
1415 print_indent 4 "# Netfilter Marks"
1416 print_indent 4 "mark_in = %unique"
1417 print_indent 4 "mark_out = %unique"
1418 print
1419 ;;
1420 esac
1421
1422 # Dead Peer Detection
1423 if enabled dpd; then
1424 print_indent 4 "# Dead Peer Detection"
1425 print_indent 4 "dpd_action = ${DPD_ACTION}"
1426 print
1427 fi
1428
1429 # Rekeying
1430 if isset LIFETIME; then
1431 print_indent 4 "# Rekey Time"
1432 print_indent 4 "rekey_time = ${LIFETIME}"
1433 print
1434 fi
1435
1436 # Updown Script
1437 print_indent 4 "updown = ${NETWORK_HELPERS_DIR}/ipsec-updown"
1438 print
1439
1440 # Mode
1441 print_indent 4 "# Mode"
1442 case "${MODE}" in
1443 gre-transport)
1444 print_indent 4 "mode = transport"
1445 ;;
1446 tunnel|vti|*)
1447 print_indent 4 "mode = tunnel"
1448 ;;
1449 esac
1450 print
1451
1452 # Compression
1453 print_indent 4 "# Compression"
1454 if enabled COMPRESSION; then
1455 print_indent 4 "ipcomp = yes"
1456 else
1457 print_indent 4 "ipcomp = no"
1458 fi
1459 print
1460
1461 # Inactivity Timeout
1462 if isset INACTIVITY_TIMEOUT; then
1463 print_indent 4 "# Inactivity Timeout"
1464 print_indent 4 "inactivity = ${INACTIVITY_TIMEOUT}"
1465 print
1466 fi
1467
1468 # Net-to-Net specific settings
1469 case "${TYPE}" in
1470 net-to-net)
1471 # Start Action
1472 print_indent 4 "# Start Action"
1473 case "${START_ACTION}" in
1474 on-demand)
1475 print_indent 4 "start_action = trap"
1476 print_indent 4 "close_action = trap"
1477 ;;
1478 wait)
1479 print_indent 4 "start_action = none"
1480 print_indent 4 "close_action = none"
1481 ;;
1482 always-on|*)
1483 print_indent 4 "start_action = start"
1484 print_indent 4 "close_action = start"
1485 ;;
1486 esac
1487 print
1488 ;;
1489 esac
1490
1491 print_indent 3 "}"
1492 print_indent 2 "}"
1493 print
1494
1495 print_indent 1 "}"
1496 print_indent 0 "}"
1497 print
1498 }
1499
1500 _ipsec_connection_to_strongswan_secrets() {
1501 local connection="${1}"
1502
1503 print_indent 0 "secrets {"
1504
1505 case "${AUTH_MODE}" in
1506 PSK)
1507 print_indent 1 "ike {"
1508
1509 # Secret
1510 print_indent 2 "secret = ${PSK}"
1511
1512 # ID
1513 if isset REMOTE_ID; then
1514 print_indent 2 "id = ${REMOTE_ID}"
1515 fi
1516
1517 print_indent 1 "}"
1518 ;;
1519 esac
1520
1521 print_indent 0 "}"
1522 }
1523
1524 # This function writes all values to a via ${pool} specificated VPN IPsec pool configuration file
1525 ipsec_pool_write_config() {
1526 assert [ $# -ge 1 ]
1527
1528 local pool="${1}"
1529
1530 if ! ipsec_pool_exists "${pool}"; then
1531 log ERROR "No such VPN IPsec pool: ${pool}"
1532 return ${EXIT_ERROR}
1533 fi
1534
1535 local path="${NETWORK_IPSEC_POOLS_DIR}/${pool}/settings"
1536
1537 if ! settings_write "${path}" ${IPSEC_POOL_CONFIG_SETTINGS}; then
1538 log ERROR "Could not write configuration settings for VPN IPsec pool ${pool}"
1539 return ${EXIT_ERROR}
1540 fi
1541
1542 if ! ipsec_pool_reload ${pool}; then
1543 log WARNING "Could not reload IPsec pool ${pool}"
1544 fi
1545
1546 # When we get here the writing of the config file was successful
1547 return ${EXIT_OK}
1548 }
1549
1550 # This funtion writes the value for one key to a via ${connection} specificated
1551 # VPN IPsec pool configuration file
1552 ipsec_pool_write_config_key() {
1553 assert [ $# -ge 3 ]
1554
1555 local pool=${1}
1556 local key=${2}
1557 shift 2
1558
1559 local value="$@"
1560
1561 if ! ipsec_pool_exists "${pool}"; then
1562 log ERROR "No such VPN IPsec pool: ${pool}"
1563 return ${EXIT_ERROR}
1564 fi
1565
1566 log DEBUG "Set '${key}' to new value '${value}' in VPN IPsec pool '${pool}'"
1567
1568 local ${IPSEC_POOL_CONFIG_SETTINGS}
1569
1570 # Read the config settings
1571 if ! ipsec_pool_read_config "${pool}"; then
1572 return ${EXIT_ERROR}
1573 fi
1574
1575 # Set the key to a new value
1576 assign "${key}" "${value}"
1577
1578 if ! ipsec_pool_write_config "${pool}"; then
1579 return ${EXIT_ERROR}
1580 fi
1581
1582 return ${EXIT_TRUE}
1583 }
1584
1585 # Reads one or more keys out of a settings file or all if no key is provided.
1586 ipsec_pool_read_config() {
1587 assert [ $# -ge 1 ]
1588
1589 local pool="${1}"
1590 shift 1
1591
1592 if ! ipsec_pool_exists "${pool}"; then
1593 log ERROR "No such VPN IPsec pool : ${pool}"
1594 return ${EXIT_ERROR}
1595 fi
1596
1597 local args
1598 if [ $# -eq 0 ] && [ -n "${IPSEC_POOL_CONFIG_SETTINGS}" ]; then
1599 list_append args ${IPSEC_POOL_CONFIG_SETTINGS}
1600 else
1601 list_append args $@
1602 fi
1603
1604 local path="${NETWORK_IPSEC_POOLS_DIR}/${pool}/settings"
1605
1606 if ! settings_read "${path}" ${args}; then
1607 log ERROR "Could not read settings for VPN IPsec pool ${pool}"
1608 return ${EXIT_ERROR}
1609 fi
1610 }
1611
1612 # This function checks if a vpn IPsec pool exists
1613 # Returns True when yes and false when not
1614 ipsec_pool_exists() {
1615 assert [ $# -eq 1 ]
1616
1617 local pool=${1}
1618
1619 local path="${NETWORK_IPSEC_POOLS_DIR}/${pool}"
1620
1621 [ -d "${path}" ] && return ${EXIT_TRUE} || return ${EXIT_FALSE}
1622 }
1623
1624 # This function checks if a VPN IPsec pool name is valid
1625 # Allowed are only A-Za-z0-9
1626 ipsec_pool_check_name() {
1627 assert [ $# -eq 1 ]
1628
1629 local pool=${1}
1630
1631 # These are special words in strongswan
1632 if isoneof pool dhcp radius; then
1633 return ${EXIT_ERROR}
1634 fi
1635
1636 [[ "${pool}" =~ [^[:alnum:]$] ]]
1637 }
1638
1639 ipsec_pool_new() {
1640 if [ $# -gt 1 ]; then
1641 error "Too many arguments"
1642 return ${EXIT_ERROR}
1643 fi
1644
1645 local pool="${1}"
1646 if ! isset pool; then
1647 error "Please provide a pool name"
1648 return ${EXIT_ERROR}
1649 fi
1650
1651 # Check for duplicates
1652 if ipsec_pool_exists "${pool}"; then
1653 error "The VPN IPsec pool ${pool} already exists"
1654 return ${EXIT_ERROR}
1655 fi
1656
1657 # Check if the name of the connection is valid
1658 if ipsec_pool_check_name "${pool}"; then
1659 error "'${pool}' contains illegal characters"
1660 return ${EXIT_ERROR}
1661 fi
1662
1663 log DEBUG "Creating VPN IPsec pool ${pool}"
1664
1665 if ! mkdir -p "${NETWORK_IPSEC_POOLS_DIR}/${pool}"; then
1666 log ERROR "Could not create config directory for ${pool}"
1667 return ${EXIT_ERROR}
1668 fi
1669
1670 local ${IPSEC_POOL_CONFIG_SETTINGS}
1671
1672 if ! ipsec_pool_write_config "${pool}"; then
1673 log ERROR "Could not write new config file"
1674 return ${EXIT_ERROR}
1675 fi
1676 }
1677
1678 # Function that deletes based on the passed parameters
1679 # one ore more vpn ipsec pools
1680 ipsec_pool_destroy() {
1681 local pool
1682 for pool in $@; do
1683 if ! ipsec_pool_exists "${pool}"; then
1684 log ERROR "The VPN IPsec pool ${pool} does not exist."
1685 continue
1686 fi
1687
1688 log DEBUG "Deleting VPN IPsec pool ${pool}"
1689
1690 if ! rm -rf "${NETWORK_IPSEC_POOLS_DIR}/${pool}"; then
1691 log ERROR "Deleting the VPN IPsec pool ${pool} was not sucessful"
1692 return ${EXIT_ERROR}
1693 fi
1694 done
1695 }
1696
1697 ipsec_pool_set_type() {
1698 local pool=${1}
1699 local ip=${2}
1700 assert isset pool
1701 assert isset ip
1702
1703 local type=$(ip_detect_protocol ${ip})
1704
1705 if ! isset type; then
1706 error "Cannot detect IP protocol of ${ip}"
1707 return ${EXIT_ERROR}
1708 else
1709 log DEBUG "IP protocol of ${ip} is ${type}"
1710 if ! ipsec_pool_write_config_key "${pool}" "TYPE" ${type}; then
1711 log ERROR "Could not write configuration settings"
1712 return ${EXIT_ERROR}
1713 fi
1714 fi
1715 }
1716
1717 ipsec_pool_network() {
1718 if [ ! $# -eq 2 ]; then
1719 log ERROR "Not enough arguments"
1720 return ${EXIT_ERROR}
1721 fi
1722 local pool=${1}
1723 local network=${2}
1724
1725 local TYPE
1726 if ! ipsec_pool_read_config ${pool} "TYPE"; then
1727 error "Failed to read configuration settings for pool '${pool}'"
1728 return ${EXIT_ERROR}
1729 fi
1730
1731 if ! isset TYPE; then
1732 if ! ip_net_is_valid ${network}; then
1733 log ERROR "Network '${network}' is invalid"
1734 return ${EXIT_ERROR}
1735 fi
1736
1737 if ! ipsec_pool_set_type ${pool} ${network}; then
1738 log ERROR "Could not set type for IPsec pool ${pool}"
1739 return ${EXIT_ERROR}
1740 fi
1741 else
1742 if ! ${TYPE}_net_is_valid ${network}; then
1743 log ERROR "Network '${network}' is invalid"
1744 return ${EXIT_ERROR}
1745 fi
1746 fi
1747
1748 if ! ipsec_pool_write_config_key "${pool}" "NETWORK" ${network}; then
1749 log ERROR "Could not write configuration settings"
1750 return ${EXIT_ERROR}
1751 fi
1752 }
1753
1754 ipsec_pool_dns_server() {
1755 if [ ! $# -eq 2 ]; then
1756 log ERROR "Not enough arguments"
1757 return ${EXIT_ERROR}
1758 fi
1759 local pool=${1}
1760 local dns_server=${2}
1761
1762 local TYPE
1763 if ! ipsec_pool_read_config ${pool} "TYPE"; then
1764 error "Failed to read configuration settings for pool '${pool}'"
1765 return ${EXIT_ERROR}
1766 fi
1767
1768 if ! isset TYPE; then
1769 if ! ip_is_valid ${dns_server}; then
1770 log ERROR "DNS server '${dns_server}' is invalid"
1771 return ${EXIT_ERROR}
1772 fi
1773
1774 if ! ipsec_pool_set_type ${pool} ${dns_server}; then
1775 log ERROR "Could not set type for IPsec pool ${pool}"
1776 return ${EXIT_ERROR}
1777 fi
1778 else
1779 if ! ${TYPE}_is_valid ${dns_server}; then
1780 log ERROR "DNS server '${dns_server}' is invalid"
1781 return ${EXIT_ERROR}
1782 fi
1783 fi
1784
1785 if ! ipsec_pool_write_config_key "${pool}" "DNS_SERVER" ${dns_server}; then
1786 log ERROR "Could not write configuration settings"
1787 return ${EXIT_ERROR}
1788 fi
1789 }
1790
1791 ipsec_pool_check_config() {
1792 local pool=${1}
1793 assert isset pool
1794
1795 local ${IPSEC_POOL_CONFIG_SETTINGS}
1796 if ! ipsec_pool_read_config "${pool}"; then
1797 log ERROR "Could not read configuration settings"
1798 return ${EXIT_ERROR}
1799 fi
1800
1801 if ! isset NETWORK; then
1802 log ERROR "Network for IPSec pool ${pool} is not set"
1803 return ${EXIT_ERROR}
1804 fi
1805
1806 if ! isset TYPE; then
1807 TYPE=$(ip_detect_protocol ${NETWORK})
1808 log DEBUG "IP protocol of ${NETWORK} is ${TYPE}"
1809 if ! isset TYPE; then
1810 error "Cannot detect IP protocol of ${NETWORK}"
1811 return ${EXIT_ERROR}
1812 else
1813 if ! ipsec_pool_write_config_key "${pool}" "TYPE" ${TYPE}; then
1814 log ERROR "Could not write configuration settings"
1815 return ${EXIT_ERROR}
1816 fi
1817 fi
1818 else
1819 if ! ${TYPE}_net_is_valid ${NETWORK}; then
1820 log ERROR "NETWORK '${NETWORK}' is invalid"
1821 return ${EXIT_ERROR}
1822 fi
1823
1824 if isset DNS_SERVER && ! ${TYPE}_is_valid ${DNS_SERVER}; then
1825 log ERROR "DNS server '${DNS_SERVER}' is invalid"
1826 return ${EXIT_ERROR}
1827 fi
1828 fi
1829
1830 return ${EXIT_OK}
1831 }
1832
1833 ipsec_pool_reload() {
1834 local pool=${1}
1835
1836 if ! ipsec_pool_to_strongswan ${pool}; then
1837 log ERROR "Could not generate strongswan config for ${pool}"
1838 return ${EXIT_ERROR}
1839 fi
1840
1841 ipsec_strongswan_load
1842 }
1843
1844 ipsec_pool_to_strongswan() {
1845 local pool=${1}
1846
1847 log DEBUG "Generating IPsec pool config for ${pool}"
1848
1849 local ${IPSEC_POOL_CONFIG_SETTINGS}
1850 if ! ipsec_pool_read_config "${pool}"; then
1851 return ${EXIT_ERROR}
1852 fi
1853
1854 if isset NETWORK && ! ipsec_pool_check_config "${pool}"; then
1855 log ERROR "Configuration of ${pool} seems to be invalid"
1856 return ${EXIT_ERROR}
1857 fi
1858
1859 local path="${NETWORK_IPSEC_SWANCTL_POOLS_DIR}/${pool}.conf"
1860
1861 (
1862 config_header "strongSwan pool configuration"
1863
1864 if isset NETWORK; then
1865 print_indent 0 "pools {"
1866
1867 print_indent 1 "${pool} {"
1868 print_indent 2 "addrs = ${NETWORK}"
1869
1870 if isset DNS_SERVER; then
1871 print_indent 2 "dns = ${DNS_SERVER}"
1872 fi
1873
1874 print_indent 1 "}"
1875 print_indent 0 "}"
1876 fi
1877 ) > ${path}
1878 }