diff --git a/install_roundcube.sh b/install_roundcube.sh index 5c929ae..50156e7 100755 --- a/install_roundcube.sh +++ b/install_roundcube.sh @@ -108,6 +108,62 @@ is_number() { #return $([[ ! -z "${1##*[!0-9]*}" ]]) } +detect_mysql_version () { + + _MYSQLD_VERSION="$(mysqld -V 2>/dev/null)" + + if [[ -z "$_MYSQLD_VERSION" ]]; then + fatal "No installed MySQL server or distribution found!" + elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ percona- ]]; then + MYSQL_CUR_DISTRIBUTION="Percona" + elif [[ "$_MYSQLD_VERSION" =~ MariaDB ]]; then + MYSQL_CUR_DISTRIBUTION="MariaDB" + elif [[ "$_MYSQLD_VERSION" =~ MySQL ]]; then + MYSQL_CUR_DISTRIBUTION="MySQL" + elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ mysql- ]]; then + MYSQL_CUR_DISTRIBUTION="MySQL" + elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ mariadb- ]]; then + MYSQL_CUR_DISTRIBUTION="MariaDB" + else + error "MySQL Instalation found, but cannot determin the distribution!" + + MYSQL_CUR_DISTRIBUTION= + echo "" + echo " Select the installed MySQL distribution." + echo "" + echo " [1] MySQL (the original community edition)" + echo " [2] Percona Server for MySQL" + echo " [3] MariaDB" + echo "" + echononl " Eingabe [1/2/3]: " + + while [ "$MYSQL_CUR_DISTRIBUTION" != "MySQL" -a "$MYSQL_CUR_DISTRIBUTION" != "MariaDB" -a "$MYSQL_CUR_DISTRIBUTION" != "Percona" ];do + read OPTION + case $OPTION in + 1) MYSQL_CUR_DISTRIBUTION="MySQL" + ;; + 2) MYSQL_CUR_DISTRIBUTION="Percona" + ;; + 3) MYSQL_CUR_DISTRIBUTION="MariaDB" + ;; + *) echo "" + echo -e "\tFalsche Eingabe ! [ 1 = MySQL ; 2 = Percona ; 3 = MariaDB ]" + echo "" + echononl " Eingabe:" + ;; + esac + done + fi + + MYSQL_VERSION="$(echo $_MYSQLD_VERSION | grep -o -E "[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?" | head -n 1)" + MYSQL_MAJOR_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f1)" + MYSQL_MINOR_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f2)" + MYSQL_PATCH_LEVEL="$(echo $MYSQL_VERSION | cut -d '.' -f3)" + MYSQL_MAIN_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f1,2)" + +} + + trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters @@ -157,7 +213,7 @@ fi while IFS='' read -r -d '' _conf_file ; do - + WEBSITE_NAME="$(grep -E "^WEBSITE_NAME" "${_conf_file}" 2>/dev/null | cut -d"=" -f2)" #Remove leading / trailling double quotes @@ -208,7 +264,7 @@ read _IN conf_file=${_arr[1]} _OK=true else - echo "" + echo "" echo -e "\tFalsche Eingabe !" echo "" echononl " Eingabe: " @@ -296,14 +352,6 @@ DEFAULT_APACHE_VHOST_DIR="/usr/local/apache2/conf/vhosts" DEFAULT_DB_HOST="localhost" DEFAULT_DB_NAME="roundcubemail" DEFAULT_DB_USER="roundcube" -if [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then - DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf" -elif [[ -f "/etc/mysql/debian.cnf" ]] ; then - DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf" -else - DEFAULT_MYSQL_CREDENTIALS="" -fi -DEFAULT_DEBIAN_MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf" [[ -n "$ROUNDCUBE_VERSION" ]] || fatal "Roundcube Version (ROUNDCUBE_VERSION) not present!" [[ -n "$WEBSITE_NAME" ]] || fatal "Website's name (WEBSITE_NAME) not present!" @@ -322,8 +370,8 @@ HOSTNAME_SHORT=${_tmp_string%%.*} if [[ -z "$IPV4" ]] && [[ -z "$IPV6" ]] ; then fatal "Neither an IPv4 nor an IPv6 address are given.!" else - [[ -n "$IPV4" ]] || warn "IPv4 Address not present!" - [[ -n "$IPV6" ]] || warn "IPv6 Address not present!" + [[ -n "$IPV4" ]] || warn "IPv4 Address not present!" + [[ -n "$IPV6" ]] || warn "IPv6 Address not present!" fi [[ -n "$APACHE_DEBIAN_INSTALLATION" ]] || APACHE_DEBIAN_INSTALLATION=false @@ -355,12 +403,12 @@ if [ -x "$httpd_binary" ];then IS_HTTPD_RUNNING=true fi fi - + [[ -n "$HTTP_USER" ]] || HTTP_USER=$DEFAULT_HTTP_USER [[ -n "$HTTP_GROUP" ]] || HTTP_GROUP=$DEFAULT_HTTP_GROUP [[ -n "$WEBMASTER_EMAIL" ]] || fatal "E-Mail (WEBMASTER_EMAIL) for webmaster not present!" -[[ -n "$WEBSITE_BASEDIR" ]] || WEBSITE_BASEDIR=$DEFAULT_WEBSITE_BASEDIR +[[ -n "$WEBSITE_BASEDIR" ]] || WEBSITE_BASEDIR=$DEFAULT_WEBSITE_BASEDIR if [[ -z "$APACHE_CERT_DIR" ]] ; then if $APACHE_DEBIAN_INSTALLATION ; then @@ -401,16 +449,76 @@ fi [[ -n "$MYSQL_DEBIAN_INSTALLATION" ]] || MYSQL_DEBIAN_INSTALLATION=false -if [[ "$DB_TYPE" = "mysql" ]]; then - if $MYSQL_DEBIAN_INSTALLATION ; then - [[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_DEBIAN_MYSQL_CREDENTIALS" - else - [[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_MYSQL_CREDENTIALS" + +if [ "$DB_TYPE" = "postgres" -o "$DB_TYPE" = "postgresql" -o "$DB_TYPE" = "pgsql" -o "$DB_TYPE" = "psql" ];then + DB_TYPE="pgsql" +fi + + +if [[ "$DB_TYPE" = "mysql" ]] ; then + + if [[ -z ${MYSQL_CREDENTIALS} ]] ; then + + detect_mysql_version + + if [[ "$MYSQL_CUR_DISTRIBUTION" = "MariaDB" ]] && ([[ $MYSQL_MAJOR_VERSION -gt 10 ]] \ + || ( [[ $MYSQL_MAJOR_VERSION -eq 10 ]] && [[ $MYSQL_MINOR_VERSION -gt 3 ]] )) ; then + if [[ -S "/tmp/mysql.sock" ]]; then + MYSQL_CREDENTIALS="-u root -S /tmp/mysql.sock" + elif [[ -S "/run/mysqld/mysqld.sock" ]]; then + MYSQL_CREDENTIALS="-u root -S /run/mysqld/mysqld.sock" + elif [[ -S "/var/run/mysqld/mysqld.sock" ]]; then + MYSQL_CREDENTIALS="-u root -S /var/run/mysqld/mysqld.sock" + else + fatal "Parameter 'MYSQL_CREDENTIALS' cannot be determined automated. + + Use configuration file "$conf_file" to set + parameter manually." + fi + + else + + echononl "\tGet MySQL command.." + mysql_command="$(which mysql)" + if [[ $? -eq 0 ]]; then + echo_ok + else + + if [[ -x "/usr/local/mysql/bin/mysql" ]]; then + mysql_command="/usr/local/mysql/bin/mysql" + echo_ok + else + echo_failed + fatal "$(cat $tmp_log_file)" + fi + fi + + if $(${mysql_command} --login-path=local -e ";" > /dev/null 2>&1) ; then + MYSQL_CREDENTIALS="--login-path=local" + elif [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then + MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf" + elif [[ -f "/etc/mysql/debian.cnf" ]] ; then + MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf" + else + fatal "Parameter 'MYSQL_CREDENTIALS' cannot be determined automated. + + Use configuration file "$conf_file" to set + parameter manually." + fi + fi + + #if $MYSQL_DEBIAN_INSTALLATION ; then + # [[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_DEBIAN_MYSQL_CREDENTIALS" + #else + # [[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_MYSQL_CREDENTIALS" + #fi + fi else [[ "$DB_TYPE" = "pgsql" ]] || fatal "Unknown Database Type '$DB_TYPE' (DB_TYPE)" fi + [[ -n "$SPAM_FOLDER_NAME" ]] || SPAM_FOLDER_NAME=$DEFAULT_SPAM_FOLDER_NAME [[ -n "$SUPPORT_URL" ]] || SUPPORT_URL="http://www.${MAIN_DOMAIN}.$TLD" @@ -604,7 +712,7 @@ _log_dir=${_src_base_dir}/log-roundcube-$_version # - REQUIREMENTS # - ============ -# - +# - # - * An IMAP, HTTP and SMTP server # - * .htaccess support allowing overrides for DirectoryIndex # - * PHP Version 5.4 or greater including: @@ -701,7 +809,7 @@ if $PHP_DEBIAN_INSTALLATION ; then echo_skipped fi done - + else for _version in $php_major_versions ; do @@ -1001,7 +1109,7 @@ if $SKIN_LOGO_PRESENT ; then cp -a "$(realpath "${tmp_dir}/${SKIN_LOGO_DIR}/${SKIN_LOGO_FILE}")" \ "${WEBSITE_BASEDIR}/htdocs/${SKIN_LOGO_DIR}/${SKIN_LOGO_FILE}" >> $log_file 2>&1 fi - + fi if [[ $? -ne 0 ]]; then echo_failed @@ -1168,13 +1276,13 @@ if [[ "$PHP_TYPE" = "fcgid" ]] ; then #!/bin/sh export PHPRC="${WEBSITE_BASEDIR}/conf/" export TMPDIR="${WEBSITE_BASEDIR}/tmp" -# PHP child process management (PHP_FCGI_CHILDREN) should -# always be disabled with mod_fcgid, which will only route one -# request at a time to application processes it has spawned; -# thus, any child processes created by PHP will not be used -# effectively. (Additionally, the PHP child processes may not -# be terminated properly.) By default, and with the environment -# variable setting PHP_FCGI_CHILDREN=0, PHP child process +# PHP child process management (PHP_FCGI_CHILDREN) should +# always be disabled with mod_fcgid, which will only route one +# request at a time to application processes it has spawned; +# thus, any child processes created by PHP will not be used +# effectively. (Additionally, the PHP child processes may not +# be terminated properly.) By default, and with the environment +# variable setting PHP_FCGI_CHILDREN=0, PHP child process # management is disabled. PHP_FCGI_CHILDREN=0 export PHP_FCGI_CHILDREN @@ -1252,7 +1360,7 @@ EOF fi echononl "\tCreate file '${WEBSITE_BASEDIR}/logs/php_errors.log'.." - + if [[ ! -f "${WEBSITE_BASEDIR}/logs/php_errors.log" ]]; then touch ${WEBSITE_BASEDIR}/logs/php_errors.log > $log_file 2>&1 if [[ $? -ne 0 ]]; then @@ -1339,7 +1447,7 @@ EOF _failed=true error "$(cat $log_file)" fi - + if ! $_failed ; then echo_ok fi @@ -1350,11 +1458,11 @@ fi echo -e "\n\n\t\033[37m\033[1mConfigure Apache Webservice\033[m\n" -SSLCertificateChainFile="" +SSLCertificateChainFile="" # - Create SSCertificateChainFile rule for apache vhost entry # - echononl "\tCreate SSCertificateChainFile rule for apache vhost entry" -if [ -n "$CERT_ChainFile" ];then +if [ -n "$CERT_ChainFile" ];then SSLCertificateChainFile="SSLCertificateChainFile ${APACHE_CERT_DIR}/$CERT_ChainFile" echo_ok else @@ -1502,17 +1610,17 @@ EOF # - X-Frame-Options # - - # - The X-Frame-Options header (RFC), or XFO header, protects your visitors - # - against clickjacking attacks. An attacker can load up an iframe on their - # - site and set your site as the source, it's quite easy: + # - The X-Frame-Options header (RFC), or XFO header, protects your visitors + # - against clickjacking attacks. An attacker can load up an iframe on their + # - site and set your site as the source, it's quite easy: # - # - # - - # - Using some crafty CSS they can hide your site in the background and create some - # - genuine looking overlays. When your visitors click on what they think is a harmless - # - link, they're actually clicking on links on your website in the background. That - # - might not seem so bad until we realise that the browser will execute those requests - # - in the context of the user, which could include them being logged in and authenticated + # - Using some crafty CSS they can hide your site in the background and create some + # - genuine looking overlays. When your visitors click on what they think is a harmless + # - link, they're actually clicking on links on your website in the background. That + # - might not seem so bad until we realise that the browser will execute those requests + # - in the context of the user, which could include them being logged in and authenticated # - to your site! # - # - Troy Hunt has a great blog on 'Clickjack attack – the hidden threat right in front : @@ -1520,49 +1628,49 @@ EOF # - # - http://www.troyhunt.com/2013/05/clickjack-attack-hidden-threat-right-in.html # - - # - Valid values include DENY meaning your site can't be framed, SAMEORIGIN which allows - # - you to frame your own site or ALLOW-FROM https://example.com/ which lets you specify + # - Valid values include DENY meaning your site can't be framed, SAMEORIGIN which allows + # - you to frame your own site or ALLOW-FROM https://example.com/ which lets you specify # -sites that are permitted to frame your own site. # - Header always set X-Frame-Options "SAMEORIGIN" # - X-Xss-Protection # - - # - This header is used to configure the built in reflective XSS protection found - # - in Internet Explorer, Chrome and Safari (Webkit). Valid settings for the header - # - are 0, which disables the protection, 1 which enables the protection - # - and 1; mode=block which tells the browser to block the response if it + # - This header is used to configure the built in reflective XSS protection found + # - in Internet Explorer, Chrome and Safari (Webkit). Valid settings for the header + # - are 0, which disables the protection, 1 which enables the protection + # - and 1; mode=block which tells the browser to block the response if it # - detects an attack rather than sanitising the script. # - Header always set X-Xss-Protection "1; mode=block" # - X-Content-Type-Options # - - # - Nice and easy to configure, this header only has one valid value, nosniff. - # - It prevents Google Chrome and Internet Explorer from trying to mime-sniff - # - the content-type of a response away from the one being declared by the server. - # - It reduces exposure to drive-by downloads and the risks of user uploaded content - # - that, with clever naming, could be treated as a different content-type, like + # - Nice and easy to configure, this header only has one valid value, nosniff. + # - It prevents Google Chrome and Internet Explorer from trying to mime-sniff + # - the content-type of a response away from the one being declared by the server. + # - It reduces exposure to drive-by downloads and the risks of user uploaded content + # - that, with clever naming, could be treated as a different content-type, like # - an executable. # - Header always set X-Content-Type-Options "nosniff" # - Content Security Policy # - - # - The CSP header allows you to define a whitelist of approved sources of content - # - for your site. By restricting the assets that a browser can load for your site, - # - like js and css, CSP can act as an effective countermeasure to XSS attacks. I - # - have covered CSP in a lot more detail in my blog Content Security Policy - An - # - Introduction (https://scotthelme.co.uk/content-security-policy-an-introduction/). + # - The CSP header allows you to define a whitelist of approved sources of content + # - for your site. By restricting the assets that a browser can load for your site, + # - like js and css, CSP can act as an effective countermeasure to XSS attacks. I + # - have covered CSP in a lot more detail in my blog Content Security Policy - An + # - Introduction (https://scotthelme.co.uk/content-security-policy-an-introduction/). # - - # - Here is a basic policy to enforce TLS on all assets and prevent + # - Here is a basic policy to enforce TLS on all assets and prevent # - mixed content warnings. # - # - Allow Google Analytics, Google AJAX CDN and Same Origin # - script-src 'self' www.google-analytics.com ajax.googleapis.com; # - # - Emmbedding Google Fonts - # - style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; + # - style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; # - # - Allow YouTube Videos (iframe embedded) # - frame-src 'self' https://www.youtube.com @@ -1572,9 +1680,9 @@ EOF # - Referrer-Policy # - - # - The HTTP referer (originally a misspelling of referrer[1]) is an HTTP header - # - field that identifies the address of the webpage (i.e. the URI or IRI) that - # - linked to the resource being requested. By checking the referrer, the new + # - The HTTP referer (originally a misspelling of referrer[1]) is an HTTP header + # - field that identifies the address of the webpage (i.e. the URI or IRI) that + # - linked to the resource being requested. By checking the referrer, the new # - webpage can see where the request originated. # - Header set Referrer-Policy "strict-origin-when-cross-origin" @@ -1781,7 +1889,7 @@ if ! $database_exists ; then else echo_failed fi - elif [[ "$DB_TYPE" = "pgsql" ]]; then + elif [[ "$DB_TYPE" = "pgsql" ]]; then echo -n " (PostgreSQL).." echo "CREATE ROLE $DB_USER WITH LOGIN NOCREATEDB NOCREATEROLE NOSUPERUSER ENCRYPTED PASSWORD '$DB_PASS'" \ | su - postgres -c "psql" > /dev/null @@ -1832,7 +1940,7 @@ info "Now browse to the intaller site and continue installation.\n$(cat <>$WEBSITE_BASEDIR/roundcubemail-${ROUNDCUBE_VERSION}/config/config.inc.php 2> $log_file // ================================== -// Added after basic installation +// Added after basic installation // ================================== \$config['skin_logo'] = '${SKIN_LOGO}'; @@ -2092,7 +2200,7 @@ cat <>$WEBSITE_BASEDIR/roundcubemail-${ROUNDCUBE_VERSION}/config/config.in // - 'pspell' - requires the PHP Pspell module and aspell installed // - 'enchant' - requires the PHP Enchant module // - 'atd' - install your own After the Deadline server or check with the people at http://www.afterthedeadline.com before using their API -// Since Google shut down their public spell checking service, you need to +// Since Google shut down their public spell checking service, you need to // connect to a Nox Spell Server when using 'googie' here. Therefore specify the 'spellcheck_uri' \$config['spellcheck_engine'] = 'pspell'; @@ -2170,7 +2278,7 @@ if $INCLUDE_ACL_PLUGIN ; then fi echo -e "\tNothing more to do here. Plugin '$_plugin' will be added to array plugins later.." - + fi @@ -2217,7 +2325,7 @@ else fi echo -e "\tNothing more to do here. Plugin '$_plugin' will be added to array plugins later.." - + # - jqueryui # - @@ -2808,12 +2916,12 @@ if $VACATION_PLUGIN ; then echo "$_line" >> $_config_file echo "*/" >> $_config_file echo "\$config['${_key}'] = array(" >> $_config_file - + if [[ "$POSTFIX_DB_TYPE" = "pgsql" ]]; then cat <> $_config_file 2>> $log_file "SELECT - subject AS vacation_subject, - body AS vacation_message, + subject AS vacation_subject, + body AS vacation_message, date(activefrom) AS vacation_start, date(activeuntil) AS vacation_end, CASE WHEN vacation.active = TRUE THEN true ELSE false END AS vacation_enable, @@ -2886,7 +2994,7 @@ EOF echo "$_line" >> $_config_file echo "*/" >> $_config_file echo "\$config['${_key}'] = array(" >> $_config_file - + if [[ "$POSTFIX_DB_TYPE" = "pgsql" ]]; then if $VAC_GUI_FORWARDER ; then @@ -3148,7 +3256,7 @@ EOF else echo_ok fi - fi + fi # - Create postfix trigger function udf_set_active @@ -3247,7 +3355,7 @@ EOF else echo_ok fi - fi + fi # - Create postfix trigger function udf_forwarders_in @@ -3346,7 +3454,7 @@ EOF else echo_ok fi - fi + fi else echononl "\tCreate function 'FORWARDERS_OUT'" @@ -3430,5 +3538,5 @@ else fi echo "" -clean_up 0 +clean_up 0