#! /bin/bash # @(#)(CAcert) $Id$ # mkchrootenv - create chroot environment for CAcert webdb application # Note: think about redesigning this script by using "dpkg --root=${ROOT}" # to build up the restricted chroot environment # define top of chroot environment #ROOT=/home/cacert ROOT=/home/cacert2 # define location of specific files SPEC=/root/chroot/spec # define location of preserved certificate files SSL_CACERT=/etc/ssl/cacert # define location of old chroot environment #OLD_ROOT= OLD_ROOT=/home/cacert #USE=copy USE=move # define how to deal with PHP short open tags (On or Off) PHP_SHORT_OPEN_TAGS=On # define apache virtual server settings depending on hostname case `hostname` in webdb) IP_NORMAL=213.154.225.245 IP_SECURE=213.154.225.246 IP_TVERIFY=213.154.225.247 IPV6_NORMAL=2001:7b8:3:9c::245 IPV6_SECURE=2001:7b8:3:9c::246 IPV6_TVERIFY=2001:7b8:3:9c::247 NAME_NORMAL=www.cacert.org ALIAS_NORMAL="cacert.org *.cacert.org cacert.com *.cacert.com cacert.net *.cacert.net" NAME_SECURE=secure.cacert.org ALIAS_SECURE=${NAME_SECURE} COMMENT="##" ERROR_REPORTING="E_ALL & ~E_NOTICE" CRT_NORMAL=/etc/ssl/certs/cacert.crt KEY_NORMAL=/etc/ssl/private/cacert.pem CRT_SECURE=/etc/ssl/certs/cacert.crt KEY_SECURE=/etc/ssl/private/cacert.pem CRT_CHAIN="/www/www/certs/class3_X0E.crt /www/www/certs/root_X0F.crt" ;; test) IP_NORMAL='*' IP_SECURE='*' NAME_NORMAL=test.cacert.org ALIAS_NORMAL="www.test.cacert.org" NAME_SECURE=secure.test.cacert.org ALIAS_SECURE="secure.test.cacert.org" COMMENT="" ERROR_REPORTING="E_ALL" CRT_NORMAL=/etc/ssl/certs/test_cacert_org.crt KEY_NORMAL=/etc/ssl/private/test_cacert_org.pem CRT_SECURE=/etc/ssl/certs/secure_test_cacert_org.crt KEY_SECURE=/etc/ssl/private/secure_test_cacert_org.pem CRT_CHAIN="/etc/ssl/cacert.crt" # CAcert Test Root ;; test2) IP_NORMAL='*' IP_SECURE='*' NAME_NORMAL=test2.cacert.org ALIAS_NORMAL="www.test2.cacert.org" NAME_SECURE=secure.test2.cacert.org ALIAS_SECURE="secure.test2.cacert.org" COMMENT="" ERROR_REPORTING="E_ALL" CRT_NORMAL=/etc/ssl/certs/test2_cacert_org.crt KEY_NORMAL=/etc/ssl/private/test2_cacert_org.pem CRT_SECURE=/etc/ssl/certs/secure_test2_cacert_org.crt KEY_SECURE=/etc/ssl/private/secure_test2_cacert_org.pem CRT_CHAIN="/etc/ssl/cacert.crt" # CAcert Test Root ;; test3.cacert.org) IP_NORMAL='*' IP_SECURE='*' NAME_NORMAL=test3.cacert.org ALIAS_NORMAL="www.test3.cacert.org" NAME_SECURE=secure.test3.cacert.org ALIAS_SECURE="secure.test2.cacert.org" COMMENT="" ERROR_REPORTING="E_ALL" CRT_NORMAL=/etc/ssl/certs/test3_cacert_org.crt KEY_NORMAL=/etc/ssl/private/test3_cacert_org.pem CRT_SECURE=/etc/ssl/certs/secure_test3_cacert_org.crt KEY_SECURE=/etc/ssl/private/secure_test3_cacert_org.pem CRT_CHAIN="/etc/ssl/cacert.crt" # CAcert Test Root ;; *) echo Please add parameters for `hostname` to $0 script 1>&2 exit 1 ;; esac FULL_NORMAL=/etc/ssl/certs/normal.crt FULL_SECURE=/etc/ssl/certs/secure.crt FULL_CHAIN=/etc/ssl/certs/combined.crt function mk_cacert_apache_certs() { >${ROOT}${FULL_CHAIN} for chain in ${CRT_CHAIN} do cat ${ROOT}${chain} >>${ROOT}${FULL_CHAIN} done cat ${ROOT}${CRT_NORMAL} ${ROOT}${FULL_CHAIN} >${ROOT}${FULL_NORMAL} cat ${ROOT}${CRT_SECURE} ${ROOT}${FULL_CHAIN} >${ROOT}${FULL_SECURE} } function mk_cacert_sitefile() { if [ "${IPV6_NORMAL}" != "" ] then VHOST1="${IP_NORMAL}:80 [${IPV6_NORMAL}]:80" VHOST2="${IP_NORMAL}:443 [${IPV6_NORMAL}]:443" else VHOST1="${IP_NORMAL}:80" VHOST2="${IP_NORMAL}:443" fi if [ "${IPV6_SECURE}" != "" ] then VHOST3="${IP_SECURE}:443 [${IPV6_SECURE}]:443" else VHOST3="${IP_SECURE}:443" fi if [ "${IPV6_TVERIFY}" != "" ] then VHOST4="${IP_TVERIFY}:443 [${IPV6_TVERIFY}]:443" else VHOST4="${IP_TVERIFY}:443" fi cat < ServerName ${NAME_NORMAL} ServerAlias ${ALIAS_NORMAL} DocumentRoot /www/www ScriptAlias /cgi-bin/ /www/cgi-bin/ Redirect permanent /revoke.crl http://crl.cacert.org/revoke.crl Redirect permanent /class3-revoke.crl http://crl.cacert.org/class3-revoke.crl RewriteEngine On RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) RewriteRule .* - [F] AddDefaultCharset utf-8 ServerName ${NAME_NORMAL} ${COMMENT}ServerAlias ${ALIAS_NORMAL} DocumentRoot /www/www SSLEngine on ${COMMENT}SSLStrictSNIVHostCheck on SSLProtocol all -SSLv2 -SSLv3 SSLHonorCipherOrder on SSLCipherSuite kEECDH:kEDH:AESGCM:ALL:!3DES!RC4:!LOW:!EXP:!MD5:!aNULL:!eNULL SSLCertificateFile ${FULL_NORMAL} SSLCertificateKeyFile ${KEY_NORMAL} SSLCACertificateFile ${FULL_CHAIN} Header always set Strict-Transport-Security "max-age=31536000" ScriptAlias /cgi-bin/ /www/cgi-bin/ Redirect permanent /revoke.crl http://crl.cacert.org/revoke.crl Redirect permanent /class3-revoke.crl http://crl.cacert.org/class3-revoke.crl RewriteEngine On RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) RewriteRule .* - [F] AddDefaultCharset utf-8 ServerName ${NAME_SECURE} ${COMMENT}ServerAlias ${ALIAS_SECURE} DocumentRoot /www/www SSLEngine on ${COMMENT}SSLStrictSNIVHostCheck on SSLProtocol all -SSLv2 -SSLv3 SSLHonorCipherOrder on SSLCipherSuite kEECDH:kEDH:AESGCM:ALL:!3DES!RC4:!LOW:!EXP:!MD5:!aNULL:!eNULL SSLCertificateFile ${FULL_SECURE} SSLCertificateKeyFile ${KEY_SECURE} SSLVerifyClient require SSLVerifyDepth 2 SSLCACertificateFile ${FULL_CHAIN} #SSLCARevocationFile /etc/ssl/crls/cacert-combined.crl #SSLOCSPEnable on #SSLOCSPDefaultResponder http://ocsp.cacert.org/ SSLOptions +StdEnvVars Header always set Strict-Transport-Security "max-age=31536000" Redirect permanent /revoke.crl http://crl.cacert.org/revoke.crl Redirect permanent /class3-revoke.crl http://crl.cacert.org/class3-revoke.crl RewriteEngine On RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) RewriteRule .* - [F] AddDefaultCharset utf-8 ! if [ "${IP_TVERIFY}" != "" ] then cat < ServerName ${NAME_SECURE} DocumentRoot /www/tverify SSLEngine on ##LATER##SSLStrictSNIVHostCheck on SSLProtocol all -SSLv2 -SSLv3 SSLHonorCipherOrder on SSLCipherSuite kEECDH:kEDH:AESGCM:ALL:!3DES!RC4:!LOW:!EXP:!MD5:!aNULL:!eNULL SSLCertificateFile ${FULL_SECURE} SSLCertificateKeyFile ${KEY_SECURE} ##OFF on Nov 18, 2009 -- see below##SSLVerifyClient require ##OFF on Nov 18, 2009 -- see below##SSLVerifyDepth 2 SSLCACertificateFile /etc/ssl/thawte.crt SSLOptions +StdEnvVars # tverify out of service on Nov 18, 2009: redirect to appropriate wiki page RedirectMatch .* https://wiki.cacert.org/Tverify RewriteEngine On RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) RewriteRule .* - [F] ! fi } umask 022 unset LANGUAGE LC_ALL LANG ######################## # 0. check prerequisites fatal() { echo "$0: $*" 1>&2 exit 1 } test ! -e ${ROOT} || fatal "${ROOT} already exists, please remove it first" test -d ${SPEC} || fatal "${SPEC} not found or not a directory" if [ -n "${OLD_ROOT}" -a -d "${OLD_ROOT}" ] then USE_WWW=${OLD_ROOT}/www/ USE_CERTS=${OLD_ROOT}/etc/ssl/ if [ -n "${USE}" -a "${USE}" = "move" ] then USE_CMD="mv" else USE_CMD="cp -a" fi fi ARCH=`file /bin/date | awk -F',' '{ print $2 }' | sed -e 's/.* //'` case ${ARCH} in i686|80386) LIBDIR=lib ALTLIB= ARCHDIR=i386-linux-gnu ;; x86_64|x86-64) LIBDIR=lib ALTLIB=lib64 ARCHDIR=x86_64-linux-gnu ;; *) fatal "${ARCH} architecture is currently not supported" ;; esac GCONVLIB=`dpkg -L libc6 | grep gconv | head -1` SSLENGINES=`dpkg -L libssl1.0.0 | grep engines | head -1` cat <${LDD_TMP}.list for binary in \ bash \ cat \ cut \ c_rehash \ dash \ dig \ dirname \ echo \ egrep \ env \ expr \ false \ file \ find \ gettext \ gettextize \ gettext.sh \ gpg \ gpgsplit \ gpgv \ gpg-zip \ grep \ gzip \ id \ install \ ls \ less \ ln \ locale \ localedef \ lspgpot \ mkdir \ mktemp \ msgattrib \ msgcat \ msgcmp \ msgcomm \ msgconv \ msgen \ msgexec \ msgfilter \ msgfmt \ msggrep \ msginit \ msgmerge \ msgunfmt \ msguniq \ openssl \ perl \ php \ php7.0 \ ps \ readlink \ recode \ rm \ sed \ sh \ sort \ stat \ touch \ tr \ wc \ whois \ xgettext do if [ -f /bin/${binary} ] then cp -a /bin/${binary} bin elif [ -f /usr/bin/${binary} ] then cp -a /usr/bin/${binary} bin else echo "$0: cannot find ${binary} in /bin or /usr/bin" 1>&2 fi echo bin/${binary} >>${LDD_TMP}.list done for binary in \ apache2 \ apache2ctl \ a2disconf \ a2dismod \ a2dissite \ a2enconf \ a2enmod \ a2ensite \ phpdismod \ phpenmod \ phpquery \ locale-gen \ update-locale \ validlocale do cp -a /usr/sbin/${binary} usr/sbin echo usr/sbin/${binary} >>${LDD_TMP}.list done for device in null random tty urandom do cp -a /dev/${device} dev done cp -a /etc/alternatives/php etc/alternatives cp -a /etc/default/locale etc/default ln -s /usr/share/dict/american-english-large etc/dictionaries-common/words ln -s ../usr/share/zoneinfo/Europe/Amsterdam etc/localtime for etc in ld.so.conf ld.so.conf.d resolv.conf services do cp -a /etc/${etc} etc done sed 's/x-x509-ca-cert.*crt$/& der/' /etc/mime.types >etc/mime.types egrep '^root|^www-data|^nogroup' /etc/group >etc/group egrep '^root|^www-data|^nogroup' /etc/gshadow >etc/gshadow egrep '^root|^www-data|^nobody' /etc/passwd >etc/passwd egrep '^www-data|^nobody' /etc/shadow >etc/shadow cp /etc/hosts etc/hosts cp /etc/locale.alias etc/locale.alias sed -e 's/^# //' etc/locale.gen for specific in group gshadow passwd shadow hosts locale.alias locale.gen do chown --reference /etc/${specific} etc/${specific} chmod --reference /etc/${specific} etc/${specific} done cat >etc/fstab <<\! # /etc/fstab: static file system information. # # proc /proc proc defaults 0 0 ! echo "cacert.org" >etc/mailname echo "none /proc proc rw 0 0" >etc/mtab (echo "passwd: files"; echo "shadow: files"; echo "group: files"; echo "hosts: files dns") >etc/nsswitch.conf echo ".eu whois.eu" >etc/whois.conf for binary in \ ldconfig do cp -a /sbin/${binary} sbin done for lib in \ apache2 gettext php do cp -a /usr/lib/${lib} usr/lib done for lib in \ perl do cp -a /usr/lib/${ARCHDIR}/${lib} usr/lib/${ARCHDIR} done >usr/lib/ssl/openssl.cnf cp -a ${GCONVLIB} .`dirname ${GCONVLIB}` rm -f .${GCONVLIB}/gconv-modules.cache cp -a ${SSLENGINES} .`dirname ${SSLENGINES}` for module in \ usr/lib/apache2/modules/*.so \ usr/lib/php/20*/*.so do echo ${module} >>${LDD_TMP}.list done for dir in \ aclocal apache2 dict file gettext gnupg i18n perl php7.0-common do cp -a /usr/share/${dir} usr/share done cp -a /usr/share/locale/locale.alias usr/share/locale find /usr/share/locale \( -name gnupg.mo -o -name libc.mo \) -print |\ sed -e 's/^\///' |\ while read file do mkdir -p `dirname ${file}` cp -a /${file} ${file} done cp -a ${SPEC}/dict/american-english-large usr/share/dict for zone in \ usr/share/zoneinfo/Europe/Amsterdam \ usr/share/zoneinfo/Europe/Berlin \ usr/share/zoneinfo/UTC \ usr/share/zoneinfo/zone.tab do cp -a /${zone} ${zone} done for addon in fpdf html2fpdf tcpdf tcpdf_php4 ufpdf do tar -xzp -C usr/share -f ${SPEC}/distro/${addon}.tar.gz chmod -R og-w usr/share/${addon} done # patch below is needed to keep ufpdf working with PHP 5.3 or later patch usr/share/ufpdf/fpdf.php <<\! --- fpdf.php.org 2005-08-21 03:41:19.000000000 +0200 +++ fpdf.php 2013-03-03 17:57:41.963434512 +0100 @@ -993,7 +993,7 @@ function Output($name='',$dest='') { //Output PDF to some destination - global $HTTP_SERVER_VARS; + global $_SERVER; //Finish document if necessary if($this->state<3) @@ -1016,7 +1016,7 @@ { case 'I': //Send to standard output - if(isset($HTTP_SERVER_VARS['SERVER_NAME'])) + if(isset($_SERVER['SERVER_NAME'])) { //We send to a browser Header('Content-Type: application/pdf'); @@ -1029,7 +1029,7 @@ break; case 'D': //Download file - if(isset($HTTP_SERVER_VARS['HTTP_USER_AGENT']) and strpos($HTTP_SERVER_VARS['HTTP_USER_AGENT'],'MSIE')) + if(isset($_SERVER['HTTP_USER_AGENT']) and strpos($_SERVER['HTTP_USER_AGENT'],'MSIE')) Header('Content-Type: application/force-download'); else Header('Content-Type: application/octet-stream'); @@ -1608,7 +1608,7 @@ } //Handle special IE contype request -if(isset($HTTP_SERVER_VARS['HTTP_USER_AGENT']) and $HTTP_SERVER_VARS['HTTP_USER_AGENT']=='contype') +if(isset($_SERVER['HTTP_USER_AGENT']) and $_SERVER['HTTP_USER_AGENT']=='contype') { Header('Content-Type: application/pdf'); exit; ! # patch below is needed because magic_quotes_runtime has been deprecated in PHP 5.3 and later grep -v magic_quotes_runtime usr/share/ufpdf/fpdf.php >/tmp/fpdf.$$ cp /tmp/fpdf.$$ usr/share/ufpdf/fpdf.php rm /tmp/fpdf.$$ >${LDD_TMP}.out for bin in `cat ${LDD_TMP}.list` do ldd ${bin} >>${LDD_TMP}.out done LIBS=`grep "=> /" ${LDD_TMP}.out | sed -e 's/.*=> //' -e 's/ .*//' | sort -u` for lib in ${LIBS} /lib*/ld-linux* \ /lib/*-linux-gnu/libnss_files.so.2 \ /lib/*-linux-gnu/libnss_dns.so.2 \ /lib/*-linux-gnu/libgcc_s.so.1 do mkdir -p `dirname .${lib}` cp -a ${lib} .${lib} if [ -L ${lib} ] then rlib=`ls -l ${lib} | sed 's/.* //'` case ${rlib} in /*) cp -a ${rlib} .${rlib} ;; *) cp -a `dirname ${lib}`/${rlib} .`dirname ${lib}`/${rlib} ;; esac fi done ############################# # 3. perform additional setup chroot ${ROOT} /sbin/ldconfig -v chroot ${ROOT} /usr/sbin/locale-gen chroot ${ROOT} /usr/sbin/update-locale ############################# # 4. setup for apache2 / php7.0 cp -a /etc/apache2 etc cat >etc/apache2/conf-available/cacert.conf <<\! # customized settings for CAcert webserver MaxRequestsPerChild 100 ServerAdmin support@cacert.org ServerName cacert.org Header always set X-Frame-Options "DENY" Header always set X-XSS-Protection "1; mode=block" Header always set X-Content-Type-Options "nosniff" DocumentRoot /www/www Options -Indexes +Includes +FollowSymLinks AllowOverride None Options -Indexes +Includes +FollowSymLinks AllowOverride All Require all granted Options +Indexes +Includes +FollowSymLinks +MultiViews AllowOverride None Options -Indexes +Includes +FollowSymLinks AllowOverride All Require all granted UseCanonicalName off HostnameLookups on LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" mod_gzip: %{mod_gzip_compression_ratio}npct. %T %v" full CustomLog /var/log/apache2/access.log full ServerSignature off AddDefaultCharset on # OCSP Stapling, only in httpd 2.3.3 and later SSLUseStapling on SSLStaplingResponderTimeout 5 SSLStaplingReturnResponderErrors off SSLStaplingCache shmcb:${APACHE_RUN_DIR}/ocsp(1280000) SSLStaplingFakeTryLater off SSLStaplingStandardCacheTimeout 86400 ! mk_cacert_sitefile >etc/apache2/sites-available/cacert.conf cp -a /etc/php etc cat >etc/php/7.0/mods-available/cacert.ini <${FILE} if cmp -s ${FILE} ${FILE}.org then mv ${FILE}.org ${FILE} else chmod --reference=${FILE}.org ${FILE} touch --reference=${FILE}.org ${FILE} echo "$0: updated ${FILE}" fi } case ${PHP_SHORT_OPEN_TAGS} in On) echo "Leaving PHP short open tags in CAcert application as is" ;; Off) echo "Fixing PHP short open tags in CAcert application" for f in `find www -name '*.php' -print` do fix_php_short_open_tags $f done # generate patch file with php short open tag updates (cd www; find . -name '*.php.org' -print |\ while read file do dir=`dirname $file`; base=`basename $file .org` diff -u ${dir}/${base}.org ${dir}/${base} rm -f ${dir}/${base}.org done >php-short-open-tags.patch ) ;; esac ################################################## # 7. generate certificates (for test systems only) HOST=`hostname -f` if [ -z "${USE_CERTS}" -a ! -f ${SSL_CACERT}/${HOST}.crt ] then # generate certificates from scratch mkdir -p ${SSL_CACERT} cd ${SSL_CACERT} mkdir demoCA demoCA/certs demoCA/crl demoCA/newcerts demoCA/private >demoCA/index.txt echo 01 >demoCA/crlnumber openssl req -new \ -keyout demoCA/private/cakey.pem \ -out demoCA/careq.pem <${HOST}.key chmod 600 ${HOST}.key /usr/bin/openssl req -new -key ${HOST}.key >${HOST}.csr <