From: Michael Tremer Date: Fri, 21 Jul 2017 19:15:08 +0000 (+0200) Subject: security-polices: Improve modification of cipher lists X-Git-Tag: 009~128 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d9a6c1832099d4f6c600264583382f594ac9bea6;p=network.git security-polices: Improve modification of cipher lists This now supports setting a cipher list in one command and returns some useful warnings when an intended change could not be performed. Signed-off-by: Michael Tremer --- diff --git a/src/functions/functions.list b/src/functions/functions.list index ff73b04e..e65bbd33 100644 --- a/src/functions/functions.list +++ b/src/functions/functions.list @@ -22,6 +22,13 @@ # Functions for nice handling of lists. # +list_set() { + local list=${1} + shift + + assign "${list}" "$@" +} + list_append() { local list=${1} assert isset list @@ -50,6 +57,28 @@ list_append_one() { fi } +# Appends one or more elements to the list only if they are not on the list, yet +list_append_unique() { + local list=${1} + shift + + assert isset list + + local ret=${EXIT_ERROR} + + local arg + for arg in $@; do + if ! list_match ${arg} ${!list}; then + list_append_one ${list} "${arg}" + ret=${EXIT_OK} + fi + done + + return ${ret} +} + +# Removes all matching items from the list +# Returns OK if at least one match was found and ERROR when not list_remove() { local list=${1} shift @@ -57,14 +86,21 @@ list_remove() { assert isset list assert [ ${list} != "list" ] + local ret=${EXIT_ERROR} + local _list k for k in ${!list}; do - list_match ${k} $@ && continue + if list_match ${k} $@; then + ret=${EXIT_OK} + continue + fi _list="${_list} ${k}" done eval "${list}=\"${_list}\"" + + return ${ret} } list_sort() { @@ -98,6 +134,12 @@ list_match() { return ${EXIT_ERROR} } +list_is_empty() { + local list="${1}" + + [ ! -n "${!list}" ] +} + list_length() { local length=0 diff --git a/src/functions/functions.vpn-security-policies b/src/functions/functions.vpn-security-policies index eb4b9156..fd68264d 100644 --- a/src/functions/functions.vpn-security-policies +++ b/src/functions/functions.vpn-security-policies @@ -461,46 +461,87 @@ vpn_security_policies_cipher(){ # Remove duplicated entries to proceed the list safely CIPHER="$(list_unique ${CIPHER})" + local ciphers_added + local ciphers_removed + local ciphers_set + while [ $# -gt 0 ]; do - case "${1}" in + local arg="${1}" + + case "${arg}" in + +*) + list_append ciphers_added "${arg:1}" + ;; -*) - value=${1#-} - # Check if the cipher is in the list of ciphers and - # check if the list has after removing this cipher at least one valid value - if list_match ${value} ${CIPHER}; then - list_remove CIPHER ${value} - else - # We do not break here because this error does not break the processing of the next maybe valid values. - log ERROR "Can not remove ${value} from the list of Ciphers because ${value} is not in the list." - fi + list_append ciphers_removed "${arg:1}" ;; - +*) - value=${1#+} - # Check if the Ciphers is in the list of supported ciphers. - if ! isoneof value ${!VPN_SUPPORTED_CIPHERS[@]}; then - # We do not break here because this error does not break the processing of the next maybe valid values. - log ERROR "${value} is not a supported cipher and can thats why not added to the list of ciphers." - else - if list_match ${value} ${CIPHER}; then - log WARNING "${value} is already in the list of ciphers of this policy." - else - list_append CIPHER ${value} - fi - fi + [A-Z0-9]*) + list_append ciphers_set "${arg}" + ;; + *) + error "Invalid argument: ${arg}" + return ${EXIT_ERROR} ;; esac shift done - # Check if the list contain at least one valid cipher - if [ $(list_length ${CIPHER}) -ge 1 ]; then - if ! vpn_security_policies_write_config_key ${name} "CIPHER" ${CIPHER}; then - log ERROR "The changes for the vpn security policy ${name} could not be written." - fi + # Check if the user is trying a mixed operation + if ! list_is_empty ciphers_set && (! list_is_empty ciphers_added || ! list_is_empty ciphers_removed); then + error "You cannot reset the cipher list and add or remove ciphers at the same time" + return ${EXIT_ERROR} + fi + + # Set new cipher list + if ! list_is_empty ciphers_set; then + # Check if all ciphers are valid + local cipher + for cipher in ${ciphers_set}; do + if ! vpn_security_policies_cipher_supported ${cipher}; then + error "Unsupported cipher: ${cipher}" + return ${EXIT_ERROR} + fi + done + + list_set CIPHER ${ciphers_set} + + # Perform incremental updates else - log ERROR "After proceding all ciphers the list is empty and thats why no changes are written." + local cipher + + # Perform all removals + for cipher in ${ciphers_removed}; do + if ! list_remove CIPHER ${cipher}; then + warning "${cipher} was not on the list and could not be removed" + fi + done + + for cipher in ${ciphers_added}; do + if vpn_security_policies_cipher_supported ${cipher}; then + if ! list_append_unique CIPHER ${cipher}; then + warning "${cipher} is already on the cipher list" + fi + else + warning "${cipher} is unknown or unsupported and could not be added" + fi + done + fi + + # Check if the list contain at least one valid cipher + if list_is_empty CIPHER; then + error "Cannot save an empty cipher list" return ${EXIT_ERROR} fi + + # Save everything + if ! vpn_security_policies_write_config_key ${name} "CIPHER" ${CIPHER}; then + log ERROR "The changes for the vpn security policy ${name} could not be written." + fi + + cli_headline 1 "Current cipher list for ${name}:" + for cipher in ${CIPHER}; do + cli_print_fmt1 1 "${cipher}" "${VPN_SUPPORTED_CIPHERS[${cipher}]}" + done } # This function parses the parameters for the 'compression' command @@ -791,6 +832,12 @@ vpn_security_policies_destroy() { done } +vpn_security_policies_cipher_supported() { + local cipher=${1} + + list_match ${cipher} ${!VPN_SUPPORTED_CIPHERS[@]} +} + vpn_security_policies_cipher_is_aead() { local cipher=${1}