]> git.ipfire.org Git - people/stevee/network.git/blob - src/functions/functions.ipsec
ipsec: add type
[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 # Pools
1330 if isset POOLS; then
1331 print_indent 2 "# Pools"
1332 print_indent 2 "pools = $(list_join POOLS ", ")"
1333 print
1334 fi
1335
1336 # Local
1337 print_indent 2 "local {"
1338
1339 # Local ID
1340 if isset LOCAL_ID; then
1341 print_indent 3 "id = ${LOCAL_ID}"
1342 fi
1343
1344 # Authentication
1345 case "${AUTH_MODE}" in
1346 PSK)
1347 print_indent 3 "auth = psk"
1348 ;;
1349 esac
1350
1351 print_indent 2 "}"
1352 print
1353
1354 # Remote
1355 print_indent 2 "remote {"
1356
1357 # Remote ID
1358 if isset REMOTE_ID; then
1359 print_indent 3 "id = ${REMOTE_ID}"
1360 fi
1361
1362 # Authentication
1363 case "${AUTH_MODE}" in
1364 PSK)
1365 print_indent 3 "auth = psk"
1366 ;;
1367 esac
1368
1369 print_indent 2 "}"
1370 print
1371
1372 # Children
1373
1374 print_indent 2 "children {"
1375 print_indent 3 "${connection} {"
1376
1377 print_indent 4 "# ESP Proposals"
1378 print_indent 4 "esp_proposals = $(vpn_security_policies_make_esp_proposal ${SECURITY_POLICY})"
1379 print
1380
1381 # Traffic Selectors
1382
1383 case "${MODE}" in
1384 gre-*)
1385 print_indent 4 "local_ts = dynamic[gre]"
1386 print_indent 4 "remote_ts = dynamic[gre]"
1387 ;;
1388 *)
1389 # Local Prefixes
1390 if isset LOCAL_PREFIX; then
1391 print_indent 4 "local_ts = $(list_join LOCAL_PREFIX ,)"
1392 else
1393 print_indent 4 "local_ts = dynamic"
1394 fi
1395
1396 # Remote Prefixes
1397 if isset REMOTE_PREFIX; then
1398 print_indent 4 "remote_ts = $(list_join REMOTE_PREFIX ,)"
1399 else
1400 print_indent 4 "remote_ts = dynamic"
1401 fi
1402 ;;
1403 esac
1404 print
1405
1406 # Netfilter Marks
1407 case "${MODE}" in
1408 vti)
1409 print_indent 4 "# Netfilter Marks"
1410 print_indent 4 "mark_in = %unique"
1411 print_indent 4 "mark_out = %unique"
1412 print
1413 ;;
1414 esac
1415
1416 # Dead Peer Detection
1417 if enabled dpd; then
1418 print_indent 4 "# Dead Peer Detection"
1419 print_indent 4 "dpd_action = ${DPD_ACTION}"
1420 print
1421 fi
1422
1423 # Rekeying
1424 if isset LIFETIME; then
1425 print_indent 4 "# Rekey Time"
1426 print_indent 4 "rekey_time = ${LIFETIME}"
1427 print
1428 fi
1429
1430 # Updown Script
1431 print_indent 4 "updown = ${NETWORK_HELPERS_DIR}/ipsec-updown"
1432 print
1433
1434 # Mode
1435 print_indent 4 "# Mode"
1436 case "${MODE}" in
1437 gre-transport)
1438 print_indent 4 "mode = transport"
1439 ;;
1440 tunnel|vti|*)
1441 print_indent 4 "mode = tunnel"
1442 ;;
1443 esac
1444 print
1445
1446 # Compression
1447 print_indent 4 "# Compression"
1448 if enabled COMPRESSION; then
1449 print_indent 4 "ipcomp = yes"
1450 else
1451 print_indent 4 "ipcomp = no"
1452 fi
1453 print
1454
1455 # Inactivity Timeout
1456 if isset INACTIVITY_TIMEOUT; then
1457 print_indent 4 "# Inactivity Timeout"
1458 print_indent 4 "inactivity = ${INACTIVITY_TIMEOUT}"
1459 print
1460 fi
1461
1462 # Start Action
1463 print_indent 4 "# Start Action"
1464 case "${START_ACTION}" in
1465 on-demand)
1466 print_indent 4 "start_action = trap"
1467 print_indent 4 "close_action = trap"
1468 ;;
1469 wait)
1470 print_indent 4 "start_action = none"
1471 print_indent 4 "close_action = none"
1472 ;;
1473 always-on|*)
1474 print_indent 4 "start_action = start"
1475 print_indent 4 "close_action = start"
1476 ;;
1477 esac
1478 print
1479
1480 print_indent 3 "}"
1481 print_indent 2 "}"
1482 print
1483
1484 print_indent 1 "}"
1485 print_indent 0 "}"
1486 print
1487 }
1488
1489 _ipsec_connection_to_strongswan_secrets() {
1490 local connection="${1}"
1491
1492 print_indent 0 "secrets {"
1493
1494 case "${AUTH_MODE}" in
1495 PSK)
1496 print_indent 1 "ike {"
1497
1498 # Secret
1499 print_indent 2 "secret = ${PSK}"
1500
1501 # ID
1502 if isset REMOTE_ID; then
1503 print_indent 2 "id = ${REMOTE_ID}"
1504 fi
1505
1506 print_indent 1 "}"
1507 ;;
1508 esac
1509
1510 print_indent 0 "}"
1511 }
1512
1513 # This function writes all values to a via ${pool} specificated VPN IPsec pool configuration file
1514 ipsec_pool_write_config() {
1515 assert [ $# -ge 1 ]
1516
1517 local pool="${1}"
1518
1519 if ! ipsec_pool_exists "${pool}"; then
1520 log ERROR "No such VPN IPsec pool: ${pool}"
1521 return ${EXIT_ERROR}
1522 fi
1523
1524 local path="${NETWORK_IPSEC_POOLS_DIR}/${pool}/settings"
1525
1526 if ! settings_write "${path}" ${IPSEC_POOL_CONFIG_SETTINGS}; then
1527 log ERROR "Could not write configuration settings for VPN IPsec pool ${pool}"
1528 return ${EXIT_ERROR}
1529 fi
1530
1531 if ! ipsec_pool_reload ${pool}; then
1532 log WARNING "Could not reload IPsec pool ${pool}"
1533 fi
1534
1535 # When we get here the writing of the config file was successful
1536 return ${EXIT_OK}
1537 }
1538
1539 # This funtion writes the value for one key to a via ${connection} specificated
1540 # VPN IPsec pool configuration file
1541 ipsec_pool_write_config_key() {
1542 assert [ $# -ge 3 ]
1543
1544 local pool=${1}
1545 local key=${2}
1546 shift 2
1547
1548 local value="$@"
1549
1550 if ! ipsec_pool_exists "${pool}"; then
1551 log ERROR "No such VPN IPsec pool: ${pool}"
1552 return ${EXIT_ERROR}
1553 fi
1554
1555 log DEBUG "Set '${key}' to new value '${value}' in VPN IPsec pool '${pool}'"
1556
1557 local ${IPSEC_POOL_CONFIG_SETTINGS}
1558
1559 # Read the config settings
1560 if ! ipsec_pool_read_config "${pool}"; then
1561 return ${EXIT_ERROR}
1562 fi
1563
1564 # Set the key to a new value
1565 assign "${key}" "${value}"
1566
1567 if ! ipsec_pool_write_config "${pool}"; then
1568 return ${EXIT_ERROR}
1569 fi
1570
1571 return ${EXIT_TRUE}
1572 }
1573
1574 # Reads one or more keys out of a settings file or all if no key is provided.
1575 ipsec_pool_read_config() {
1576 assert [ $# -ge 1 ]
1577
1578 local pool="${1}"
1579 shift 1
1580
1581 if ! ipsec_pool_exists "${pool}"; then
1582 log ERROR "No such VPN IPsec pool : ${pool}"
1583 return ${EXIT_ERROR}
1584 fi
1585
1586 local args
1587 if [ $# -eq 0 ] && [ -n "${IPSEC_POOL_CONFIG_SETTINGS}" ]; then
1588 list_append args ${IPSEC_POOL_CONFIG_SETTINGS}
1589 else
1590 list_append args $@
1591 fi
1592
1593 local path="${NETWORK_IPSEC_POOLS_DIR}/${pool}/settings"
1594
1595 if ! settings_read "${path}" ${args}; then
1596 log ERROR "Could not read settings for VPN IPsec pool ${pool}"
1597 return ${EXIT_ERROR}
1598 fi
1599 }
1600
1601 # This function checks if a vpn IPsec pool exists
1602 # Returns True when yes and false when not
1603 ipsec_pool_exists() {
1604 assert [ $# -eq 1 ]
1605
1606 local pool=${1}
1607
1608 local path="${NETWORK_IPSEC_POOLS_DIR}/${pool}"
1609
1610 [ -d "${path}" ] && return ${EXIT_TRUE} || return ${EXIT_FALSE}
1611 }
1612
1613 # This function checks if a VPN IPsec pool name is valid
1614 # Allowed are only A-Za-z0-9
1615 ipsec_pool_check_name() {
1616 assert [ $# -eq 1 ]
1617
1618 local pool=${1}
1619
1620 # These are special words in strongswan
1621 if isoneof pool dhcp radius; then
1622 return ${EXIT_ERROR}
1623 fi
1624
1625 [[ "${pool}" =~ [^[:alnum:]$] ]]
1626 }
1627
1628 ipsec_pool_new() {
1629 if [ $# -gt 1 ]; then
1630 error "Too many arguments"
1631 return ${EXIT_ERROR}
1632 fi
1633
1634 local pool="${1}"
1635 if ! isset pool; then
1636 error "Please provide a pool name"
1637 return ${EXIT_ERROR}
1638 fi
1639
1640 # Check for duplicates
1641 if ipsec_pool_exists "${pool}"; then
1642 error "The VPN IPsec pool ${pool} already exists"
1643 return ${EXIT_ERROR}
1644 fi
1645
1646 # Check if the name of the connection is valid
1647 if ipsec_pool_check_name "${pool}"; then
1648 error "'${pool}' contains illegal characters"
1649 return ${EXIT_ERROR}
1650 fi
1651
1652 log DEBUG "Creating VPN IPsec pool ${pool}"
1653
1654 if ! mkdir -p "${NETWORK_IPSEC_POOLS_DIR}/${pool}"; then
1655 log ERROR "Could not create config directory for ${pool}"
1656 return ${EXIT_ERROR}
1657 fi
1658
1659 local ${IPSEC_POOL_CONFIG_SETTINGS}
1660
1661 if ! ipsec_pool_write_config "${pool}"; then
1662 log ERROR "Could not write new config file"
1663 return ${EXIT_ERROR}
1664 fi
1665 }
1666
1667 # Function that deletes based on the passed parameters
1668 # one ore more vpn ipsec pools
1669 ipsec_pool_destroy() {
1670 local pool
1671 for pool in $@; do
1672 if ! ipsec_pool_exists "${pool}"; then
1673 log ERROR "The VPN IPsec pool ${pool} does not exist."
1674 continue
1675 fi
1676
1677 log DEBUG "Deleting VPN IPsec pool ${pool}"
1678
1679 if ! rm -rf "${NETWORK_IPSEC_POOLS_DIR}/${pool}"; then
1680 log ERROR "Deleting the VPN IPsec pool ${pool} was not sucessful"
1681 return ${EXIT_ERROR}
1682 fi
1683 done
1684 }
1685
1686 ipsec_pool_set_type() {
1687 local pool=${1}
1688 local ip=${2}
1689 assert isset pool
1690 assert isset ip
1691
1692 local type=$(ip_detect_protocol ${ip})
1693
1694 if ! isset type; then
1695 error "Cannot detect IP protocol of ${ip}"
1696 return ${EXIT_ERROR}
1697 else
1698 log DEBUG "IP protocol of ${ip} is ${type}"
1699 if ! ipsec_pool_write_config_key "${pool}" "TYPE" ${type}; then
1700 log ERROR "Could not write configuration settings"
1701 return ${EXIT_ERROR}
1702 fi
1703 fi
1704 }
1705
1706 ipsec_pool_network() {
1707 if [ ! $# -eq 2 ]; then
1708 log ERROR "Not enough arguments"
1709 return ${EXIT_ERROR}
1710 fi
1711 local pool=${1}
1712 local network=${2}
1713
1714 local TYPE
1715 if ! ipsec_pool_read_config ${pool} "TYPE"; then
1716 error "Failed to read configuration settings for pool '${pool}'"
1717 return ${EXIT_ERROR}
1718 fi
1719
1720 if ! isset TYPE; then
1721 if ! ip_net_is_valid ${network}; then
1722 log ERROR "Network '${network}' is invalid"
1723 return ${EXIT_ERROR}
1724 fi
1725
1726 if ! ipsec_pool_set_type ${pool} ${network}; then
1727 log ERROR "Could not set type for IPsec pool ${pool}"
1728 return ${EXIT_ERROR}
1729 fi
1730 else
1731 if ! ${TYPE}_net_is_valid ${network}; then
1732 log ERROR "Network '${network}' is invalid"
1733 return ${EXIT_ERROR}
1734 fi
1735 fi
1736
1737 if ! ipsec_pool_write_config_key "${pool}" "NETWORK" ${network}; then
1738 log ERROR "Could not write configuration settings"
1739 return ${EXIT_ERROR}
1740 fi
1741 }
1742
1743 ipsec_pool_dns_server() {
1744 if [ ! $# -eq 2 ]; then
1745 log ERROR "Not enough arguments"
1746 return ${EXIT_ERROR}
1747 fi
1748 local pool=${1}
1749 local dns_server=${2}
1750
1751 local TYPE
1752 if ! ipsec_pool_read_config ${pool} "TYPE"; then
1753 error "Failed to read configuration settings for pool '${pool}'"
1754 return ${EXIT_ERROR}
1755 fi
1756
1757 if ! isset TYPE; then
1758 if ! ip_is_valid ${dns_server}; then
1759 log ERROR "DNS server '${dns_server}' is invalid"
1760 return ${EXIT_ERROR}
1761 fi
1762
1763 if ! ipsec_pool_set_type ${pool} ${dns_server}; then
1764 log ERROR "Could not set type for IPsec pool ${pool}"
1765 return ${EXIT_ERROR}
1766 fi
1767 else
1768 if ! ${TYPE}_is_valid ${dns_server}; then
1769 log ERROR "DNS server '${dns_server}' is invalid"
1770 return ${EXIT_ERROR}
1771 fi
1772 fi
1773
1774 if ! ipsec_pool_write_config_key "${pool}" "DNS_SERVER" ${dns_server}; then
1775 log ERROR "Could not write configuration settings"
1776 return ${EXIT_ERROR}
1777 fi
1778 }
1779
1780 ipsec_pool_check_config() {
1781 local pool=${1}
1782 assert isset pool
1783
1784 local ${IPSEC_POOL_CONFIG_SETTINGS}
1785 if ! ipsec_pool_read_config "${pool}"; then
1786 log ERROR "Could not read configuration settings"
1787 return ${EXIT_ERROR}
1788 fi
1789
1790 if ! isset NETWORK; then
1791 log ERROR "Network for IPSec pool ${pool} is not set"
1792 return ${EXIT_ERROR}
1793 fi
1794
1795 if ! isset TYPE; then
1796 TYPE=$(ip_detect_protocol ${NETWORK})
1797 log DEBUG "IP protocol of ${NETWORK} is ${TYPE}"
1798 if ! isset TYPE; then
1799 error "Cannot detect IP protocol of ${NETWORK}"
1800 return ${EXIT_ERROR}
1801 else
1802 if ! ipsec_pool_write_config_key "${pool}" "TYPE" ${TYPE}; then
1803 log ERROR "Could not write configuration settings"
1804 return ${EXIT_ERROR}
1805 fi
1806 fi
1807 else
1808 if ! ${TYPE}_net_is_valid ${NETWORK}; then
1809 log ERROR "NETWORK '${NETWORK}' is invalid"
1810 return ${EXIT_ERROR}
1811 fi
1812
1813 if isset DNS_SERVER && ! ${TYPE}_is_valid ${DNS_SERVER}; then
1814 log ERROR "DNS server '${DNS_SERVER}' is invalid"
1815 return ${EXIT_ERROR}
1816 fi
1817 fi
1818
1819 return ${EXIT_OK}
1820 }
1821
1822 ipsec_pool_reload() {
1823 local pool=${1}
1824
1825 if ! ipsec_pool_to_strongswan ${pool}; then
1826 log ERROR "Could not generate strongswan config for ${pool}"
1827 return ${EXIT_ERROR}
1828 fi
1829
1830 ipsec_strongswan_load
1831 }
1832
1833 ipsec_pool_to_strongswan() {
1834 local pool=${1}
1835
1836 log DEBUG "Generating IPsec pool config for ${pool}"
1837
1838 local ${IPSEC_POOL_CONFIG_SETTINGS}
1839 if ! ipsec_pool_read_config "${pool}"; then
1840 return ${EXIT_ERROR}
1841 fi
1842
1843 if isset NETWORK && ! ipsec_pool_check_config "${pool}"; then
1844 log ERROR "Configuration of ${pool} seems to be invalid"
1845 return ${EXIT_ERROR}
1846 fi
1847
1848 local path="${NETWORK_IPSEC_SWANCTL_POOLS_DIR}/${pool}.conf"
1849
1850 (
1851 config_header "strongSwan pool configuration"
1852
1853 if isset NETWORK; then
1854 print_indent 0 "pools {"
1855
1856 print_indent 1 "${pool} {"
1857 print_indent 2 "addrs = ${NETWORK}"
1858
1859 if isset DNS_SERVER; then
1860 print_indent 2 "dns = ${DNS_SERVER}"
1861 fi
1862
1863 print_indent 1 "}"
1864 print_indent 0 "}"
1865 fi
1866 ) > ${path}
1867 }