From 21a0ce71f067adc8f0b52557bac5ea641bb13ade Mon Sep 17 00:00:00 2001 From: Andrew Stevenson Date: Sun, 24 Jul 2022 00:13:59 +0000 Subject: [PATCH] Make parsing on jail.conf more robust jail.conf has a few tricky things about it's format (such as supporting variable expansion) so it is easiest to get jail to do the parsing for us. The changes to get required changes to set as well as we no longer are calling grep so that became a single awk script as well. --- usr/local/share/bastille/config.sh | 87 ++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/usr/local/share/bastille/config.sh b/usr/local/share/bastille/config.sh index abc920d51..525f11c4c 100644 --- a/usr/local/share/bastille/config.sh +++ b/usr/local/share/bastille/config.sh @@ -35,6 +35,15 @@ usage() { error_exit "Usage: bastille config TARGET get|set propertyName [newValue]" } +# we need jail(8) to parse the config file so it can expand variables etc +print_jail_conf() { + + # we need to pass a literal \n to jail to get each parameter on its own + # line + jail -f "$1" -e ' +' +} + # Handle special-case commands first. case "$1" in help|-h|--help) @@ -71,23 +80,30 @@ for _jail in ${JAILS}; do continue fi - ESCAPED_PROPERTY=$(echo "${PROPERTY}" | sed 's/\./\\\./g') - MATCH_LINE=$(grep "^[[:blank:]]*${ESCAPED_PROPERTY}[[:blank:]=;]" "${FILE}" 2>/dev/null) - MATCH_FOUND=$? - if [ "${ACTION}" = 'get' ]; then - if [ "${MATCH_FOUND}" -ne 0 ]; then - warn "not set" - elif ! echo "${MATCH_LINE}" | grep '=' > /dev/null 2>&1; then - echo "enabled" - else - VALUE=$(echo "${MATCH_LINE}" | sed -E 's/.+= *(.+) *;$/\1/' 2>/dev/null) - if [ $? -ne 0 ]; then - error_notify "Failed to get value." - else - echo "${VALUE}" - fi - fi + print_jail_conf "${FILE}" | awk -F= -v property="${PROPERTY}" ' + $1 == property { + # note that we have found the property + found = 1; + # check if there is a value for this property + if (NF == 2) { + # remove any quotes surrounding the string + sub(/^"/, "", $2); + sub(/"$/, "", $2); + print $2; + } else { + # no value, just the property name + print "enabled" + } + exit 0; + } + END { + # if we have not found anything we need to print a special + # string + if (! found) { + print("not set") + } + }' else # Setting the value. -- cwells if [ -n "${VALUE}" ]; then VALUE=$(echo "${VALUE}" | sed 's/\//\\\//g') @@ -99,11 +115,40 @@ for _jail in ${JAILS}; do LINE=" ${PROPERTY};" fi - if [ "${MATCH_FOUND}" -ne 0 ]; then # No match, so insert the property at the end. -- cwells - echo "$(awk -v line="${LINE}" '$0 == "}" { print line; } 1 { print $0; }' "${FILE}")" > "${FILE}" - else # Replace the existing value. -- cwells - sed -i '' -E "s/ *${ESCAPED_PROPERTY}[ =;].*/${LINE}/" "${FILE}" - fi + # add the value to the config file, replacing any existing value or, if + # there is none, at the end + # + # awk doesn't have "inplace" editing so we use a temp file + _tmpfile=$(mktemp) || error_exit "unable to set because mktemp failed" + cp "${FILE}" "${_tmpfile}" && \ + awk -F= -v line="${LINE}" -v property="${PROPERTY}" ' + BEGIN { + # build RE as string as we can not expand vars in RE literals + prop_re = "^[[:space:]]*" property "[[:space:]]*$"; + } + $1 ~ prop_re && !found { + # we already have an entry in the config for this property so + # we need to substitute our line here rather than keep the + # existing line + print(line); + # note we have already found the property + found = 1; + # move onto the next line + next; + } + $1 == "}" { + # reached the end of the stanza so if we have not already + # added our line we need to do so now + if (! found) { + print(line); + } + } + { + # print each uninteresting line unchanged + print; + } + ' "${_tmpfile}" > "${FILE}" + rm "${_tmpfile}" fi done