#!/bin/bash # Copyright (C) 2023 Pädagogisches Landesinstitut Rheinland-Pfalz # Copyright (C) 2023 Mike Gabriel # Copyright (C) 2023 Daniel Teichmann # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the # Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. set -e . /usr/share/debconf/confmodule || exit 255 common_file="/usr/share/debian-edu-router/debian-edu-router.common" # Load common functions, variables and stuff. if [ -s "$common_file" ]; then source "$common_file" else echo "Could not load common file at "$common_file"." exit 0; fi # prepare debconf export DC_PRIO_LOW="medium" export DC_PRIO_HIGH="high" db_version 2.0 db_capb backup escape if [ -e /etc/debian-edu/router.conf ]; then source /etc/debian-edu/router.conf fi PRODUCTNAME="${PRODUCTNAME:-"Debian Edu Router"}" PRODUCTNAME_PLUGIN_SUFFIX="${PRODUCTNAME_PLUGIN_SUFFIX:-"Plugin"}" PRODUCTNAME_PLUGIN="${PRODUCTNAME_PLUGIN:-"${PRODUCTNAME} ${PRODUCTNAME_PLUGIN_SUFFIX}: Content filter"}" PACKAGE_NAME="debian-edu-router-plugin.content-filter" db_title "${PRODUCTNAME_PLUGIN}" # If we don't run this script for the first time, make sure we know what IP # proto versions are enabled for non-network configuration steps, what internal # networks are enabled and what internal networks have static IP address set. # # This is really important for cases where the sysadmin chooses to skip network # settings. We can't populate the IPV4 and IPV6 variables from within the while # loop, so let's preset these values in case networking set up gets skipped. # # Sets IPV4 and IPV6 bool variables. parse_ip_versions if [ "${CONFIGURE_ONLY}" = "NOT_IMPLEMENTED" ]; then STATE=21 QCOUNT=21 elif [ "${CONFIGURE_ONLY}" = "ONOFF" ]; then STATE=0 QCOUNT=0 elif [ "${CONFIGURE_ONLY}" = "FORCE_REWRITE_SSL_MITM_CA" ]; then STATE=10 QCOUNT=16 elif [ "${SKIP_DEBCONF_QUESTIONS_CONFIG}" = "1" ]; then STATE=999 QCOUNT=999 else STATE=0 QCOUNT=20 fi # Define a starting point that cannot be skipped by going back BACKSTOP=${STATE} debug_log "Picked up the following debconf-question state-machine settings for ${PACKAGE_NAME}.config:" debug_log " - SKIP_DEBCONF_QUESTIONS_CONFIG='${SKIP_DEBCONF_QUESTIONS_CONFIG}'." debug_log " - CONFIGURE_ONLY= '${CONFIGURE_ONLY}'." debug_log " - STATE= '${STATE}'." debug_log " - QCOUNT= '${QCOUNT}'." debug_log " - BACKSTOP= '${BACKSTOP}'." debug_log " - Script arguments= '${0} $@'." # Failure counters: Some question don't allow empty input or similar. # We can't re-ask questions endlessly, but need to bail out at some point. FCOUNTER=0 # default behaviour should be that steps go UP rather than down. # we have this variable to track in which direction we are currently going # for example if the user wants to backup a step at step 17 # and step 16 should be skipped (for whatever reason) then we should move on # to step *15* instead of step 17! STATE_DIRECTION=1 # setup milestones # when configuring a new milestone, please test if backing up from that # milestone does work as expected! ONOFF_QUESTION=0 FIRST_QUESTION=1 db_get debian-edu-router-config/net-int-supportednetworks || true supported_internal_networks="${RET}" function statemachine() { while [ ${STATE} -gt -1 ] && [ ${STATE} -le ${QCOUNT} ] && [ ${STATE} -ge ${BACKSTOP} ]; do debug_log "We are currently at step ${cyan}$STATE${normal}." # ask questions case "${STATE}" in # PLUGIN ENABLED? 0) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/content-filter-enabled || true ;; # DNS ALIAS 1) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/dns-alias || true ;; # DNS SERVERS 2) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/dns-servers || true ;; # ENABLE SQUID FOR NETWORKS 3) choices="${supported_internal_networks}" db_subst debian-edu-router-plugin.content-filter/service-httpproxy-networks-enabled choices "${choices}" db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-httpproxy-networks-enabled || true ;; # PROXY PORT EXPOSED TO CLIENTS 4) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/proxy-port-exposed-to-clients || true ;; # TRANSPARENT PROXY MODE: ENABLED? 5) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-httpproxy-transparent-mode-enabled || true ;; # APACHE2 HTTP PORT 6) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/apache2-http-port || true ;; # APACHE2 HTTPS PORT 7) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/apache2-https-port || true ;; # USE PARENT PROXY 8) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/parent-proxy || true ;; # ENABLE SQUID'S SSL BUMPING FEATURE? 9) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-httpproxy-enable-sslbumping || true ;; # SELECT NETWORKS WITH SSL BUMPING ENABLED 10) db_get debian-edu-router-plugin.content-filter/service-httpproxy-networks-enabled || true choices="${RET}" db_subst debian-edu-router-plugin.content-filter/service-httpproxy-networks-with-sslbumping choices "${choices}" db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-httpproxy-networks-with-sslbumping || true ;; # CA SETUP FOR SSL MITM 11) if [ ! -s "$SSL_MITM_CA_CONFIG_PATH" ]; then db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-org || true fi ;; 12) if [ ! -s "$SSL_MITM_CA_CONFIG_PATH" ]; then db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-ou || true fi ;; 13) if [ ! -s "$SSL_MITM_CA_CONFIG_PATH" ]; then db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-province || true fi ;; 14) if [ ! -s "$SSL_MITM_CA_CONFIG_PATH" ]; then db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-city || true fi ;; 15) if [ ! -s "$SSL_MITM_CA_CONFIG_PATH" ]; then db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-country || true fi ;; 16) if [ ! -s "$SSL_MITM_CA_CONFIG_PATH" ]; then db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-cn || true fi ;; 17) if [ ! -s "$SSL_MITM_CA_CONFIG_PATH" ]; then db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-email || true fi ;; # E2GUARDIAN'S CONTENT ANALYSIS 18) # SSL MITM only makes sense in combination with Squid SSL bumping db_get debian-edu-router-plugin.content-filter/service-httpproxy-networks-with-sslbumping || true ssl_bumping_networks="${RET}" db_subst debian-edu-router-plugin.content-filter/service-contentfilter-networks-enabled choices "${ssl_bumping_networks}" db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-contentfilter-networks-enabled || true ;; # SQUID+E2GUARDIAN: AUTOREFRESH BLACKLISTS 19) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-contentfilter-autorefresh-blacklist || true ;; # SQUID: Auto-regenerate Proxy*Site.* IPs? 20) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/service-contentfilter-autoregenerate-ips || true ;; # not implemented yet... 21) db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/not-implemented-yet || true ;; # Used for skipping/aborting questions entirely. 999) ;; *) echo "Unknown state ${STATE}!"; exit 255 ;; esac if db_go || [ "$BYPASS_DB_GO" == true ]; then # evaluate answers case "${STATE}" in # PLUGIN ENABLED? 0) db_get debian-edu-router-plugin.content-filter/content-filter-enabled || true if [ "${RET}" = "false" ]; then STATE=999 continue fi ;; # DNS ALIAS 1) db_get debian-edu-router-plugin.content-filter/dns-alias || true dns_alias="${RET}" ;; # DNS SERVERS 2) db_get debian-edu-router-plugin.content-filter/dns-servers || true contentfilter_dns_servers="$(echo ${RET} | sed -E -e "s/,/ /g" -e "s/\s+/ /g")" # Force non-empty answer. if [ -z "${contentfilter_dns_servers}" ]; then # db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/dns-servers-required || true # if ! db_go; then # debug_log "Ignoring backup/db_go-failure..." # fi warning_log "An external nameserver must be specified to resolve client hostnames coming from LDAP!" FCOUNTER=$((${FCOUNTER}+1)) bailout_on_too_many_failures debian-edu-router-plugin.content-filter/dns-servers ${FCOUNTER} 5 continue fi invalid_nameserver=false # FIXME: Actually test DNS via e.g. 'dig'? # Check for invalid DNS entries. for dns_addr in ${contentfilter_dns_servers}; do if [ "$IPV4" == true ] && is_address_v4 "${dns_addr}"; then # Alright, address looks good. Check next one. debug_log "IPv4 nameserver address '$dns_addr' could be verified." continue elif [ "$IPV6" == true ] && is_address_v6 "${dns_addr}"; then # Alright, address looks good. Check next one. debug_log "IPv6 nameserver address '$dns_addr' could be verified." continue fi warning_log "Nameserver address '$dns_addr' is *not* valid!" db_input ${DC_PRIO_HIGH} debian-edu-router-config/net-syntax-invalid-nameserver || true if ! db_go; then debug_log "Ignoring backup/db_go-failure..." fi invalid_nameserver=true FCOUNTER=$((${FCOUNTER}+1)) bailout_on_too_many_failures debian-edu-router-plugin.content-filter/dns-servers ${FCOUNTER} 5 break done # Let the user retry if invalid entry was found. if [ "${invalid_nameserver}" == true ]; then continue fi FCOUNTER=0 ;; # SQUIDs WEBSITE FILTERING VIA ACLs 3) # Skip all other questions if no networks are selected. # Not selecting any networks basically means: disabled # content filtering / HTTP caching db_get debian-edu-router-plugin.content-filter/service-httpproxy-networks-enabled || true httpproxy_networks_enabled="${RET}" if [ "${httpproxy_networks_enabled}" = "" ]; then STATE=999 continue fi ;; # PROXY PORT EXPOSED TO CLIENTS 4) # FIXME: sanity check that this is a number between 1025 and 49999 (or so) ;; # TRANSPARENT PROXY MODE: ENABLED? 5) db_get debian-edu-router-plugin.content-filter/service-httpproxy-transparent-mode-enabled || true transparent_proxy_mode_enabled="${RET}" ;; # APACHE2 HTTP PORT 6) # FIXME: sanity check that this is a number between 1025 and 49999 (or so) db_get debian-edu-router-plugin.content-filter/apache2-http-port || true apache2_http_port="${RET}" if [[ -z "${apache2_http_port}" ]]; then db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/cannot-be-empty || true if ! db_go; then debug_log "Ignoring backup/db_go-failure..." fi FCOUNTER=$((${FCOUNTER}+1)) bailout_on_too_many_failures debian-edu-router-plugin.content-filter/apache2-http-port ${FCOUNTER} 5 continue fi FCOUNTER=0 ;; # APACHE2 HTTPS PORT 7) # FIXME: sanity check that this is a number between 1025 and 49999 (or so) ;; # USE PARENT PROXY 8) # FIXME: sanity checks that the parent proxy is in format ':' ;; # ENABLE SQUID'S SSL BUMPING FEATURE? 9) db_get debian-edu-router-plugin.content-filter/service-httpproxy-enable-sslbumping || true httpproxy_sslbumping_enabled="${RET}" if [ "${httpproxy_sslbumping_enabled}" = "false" ]; then STATE=999 continue fi ;; # SELECT NETWORKS WITH SSL BUMPING ENABLED 10) db_get debian-edu-router-plugin.content-filter/service-httpproxy-networks-with-sslbumping || true httpproxy_networks_sslbumping="${RET}" if [ "${httpproxy_networks_sslbumping}" = "" ]; then continue fi ;; # CA SETUP FOR SSL MITM 11) # FIXME: sanity checks for CA_ORG ;; 12) # FIXME: sanity checks for CA_OU ;; 13) # FIXME: sanity checks for CA_PROVINCE ;; 14) # FIXME: sanity checks for CA_CITY ;; 15) # FIXME: sanity checks for CA_COUNTRY ;; 16) # FIXME: sanity checks for CA_CN ;; 17) # FIXME: sanity checks for CA_EMAIL # Assume all PKI / CA debconf options have been answered. # Create empty openssl.d-e-r_sslmitm-ca.cnf file to avoid # that the debconf questions get re-asked (e.g. during triggers). if [ ! -s "$SSL_MITM_CA_CONFIG_PATH" ]; then mkdir -p /etc/debian-edu-router/ssl/ # Create empty .cnf file, this triggers population of the file in our # .postinst script. touch "$SSL_MITM_CA_CONFIG_PATH" fi ;; # E2GUARDIAN'S CONTENT ANALYSIS 18) # Nothing to do here... ;; # SQUID: AUTOREFRESH BLACKLISTS 19) db_get debian-edu-router-plugin.content-filter/service-contentfilter-autorefresh-blacklist || true autorefresh_blacklist="${RET}" ;; # SQUID: Auto-regenerate Proxy*Site.* IPs? 20) db_get debian-edu-router-plugin.content-filter/service-contentfilter-autoregenerate-ips || true autorefresh_blacklist="${RET}" ;; # not implemented yet... 21) ;; # Used for skipping/aborting questions entirely. 999) ;; esac # last question was ok, so go up. # except if we just simulated that step... if [ "$BYPASS_DB_GO" == true ]; then STATE_DIRECTION=1 STATE=$ORIGIN_STATE else STATE_DIRECTION=1 STATE=$(($STATE + $STATE_DIRECTION)) fi # reset. BYPASS_DB_GO=false else # last question was not ok (user wants to backup), so go *DOWN* a step. # and if the next step should be skipped, go down another step. # and if that step should also be skipped, go down another step. # and so on and so on... STATE_DIRECTION=-1 STATE=$(($STATE + $STATE_DIRECTION)) debug_log "Backing up to step ${cyan}${STATE}${green}..." fi done if [ $STATE -lt $BACKSTOP ]; then # user went backwards from beyond BACKSTOP/entry point, abort package configuration. debug_log "User tried to backup beyond BACKSTOP/entry point... Exiting." exit 10 fi } function main() { SSL_MITM_CA_CONFIG_PATH="/etc/debian-edu-router/ssl/openssl.d-e-r_sslmitm-ca.cnf" if [ "${CONFIGURE_ONLY}" = "FORCE_REWRITE_SSL_MITM_CA" ]; then db_set debian-edu-router-plugin.content-filter/warning-ssl-mitm-ca-cert-rewrite false db_fset debian-edu-router-plugin.content-filter/warning-ssl-mitm-ca-cert-rewrite seen false db_input ${DC_PRIO_HIGH} debian-edu-router-plugin.content-filter/warning-ssl-mitm-ca-cert-rewrite # If user agreed, go on. if db_go; then db_get debian-edu-router-plugin.content-filter/warning-ssl-mitm-ca-cert-rewrite if [ "${RET}" = "true" ]; then rm "$SSL_MITM_CA_CONFIG_PATH" || true notice_log "User started recreation of SSL CA certificate!" else notice_log "User aborted recreation of SSL CA certificate." STATE=999 fi fi fi # Enforce SSL-MitM CA re-creation if the .cnf file has been removed. # (We use the removal of the .cnf file as a signal for recreating the PKI). if ! [ -s "$SSL_MITM_CA_CONFIG_PATH" ]; then db_fset debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-org seen false db_fset debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-ou seen false db_fset debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-province seen false db_fset debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-city seen false db_fset debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-country seen false db_fset debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-cn seen false db_fset debian-edu-router-plugin.content-filter/service-httpproxy-sslbumping-ca-email seen false fi statemachine } if [[ "$1" == "configure" ]] && [[ -n "$2" ]]; then main elif [[ "$1" == "configure" ]] && [[ "$2" == "debian-edu-router-reconfigured" ]]; then debug_log "config script was called via dpkg-trigger, specifically 'debian-edu-router-reconfigured' trigger." main elif [[ "$1" == "reconfigure" ]]; then debug_log "config script was called via dpkg-reconfigure." main else debug_log "config script was probably called to preconfigure package, skipping..." exit 0 fi # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. debug_log "Finished .config stage of ${PACKAGE_NAME}." exit 0