From 7b73d1db5f0f4d2fcb4ba0957d6ac69954cfe35d Mon Sep 17 00:00:00 2001 From: nachoparker Date: Fri, 22 Oct 2021 18:02:49 -0600 Subject: add nc-encrypt Signed-off-by: nachoparker --- bin/ncp-provisioning.sh | 8 ++ bin/ncp/CONFIG/nc-datadir.sh | 1 + bin/ncp/SECURITY/nc-encrypt.sh | 107 +++++++++++++++ bin/nextcloud-domain.sh | 6 + build/docker/docker-compose.yml | 6 + build/docker/nextcloud/020nextcloud | 8 ++ changelog.md | 10 +- etc/library.sh | 25 +++- etc/ncp-config.d/nc-encrypt.cfg | 22 +++ ncp-web/activate/index.php | 30 +++-- ncp-web/decrypt/CSS.css | 259 ++++++++++++++++++++++++++++++++++++ ncp-web/decrypt/JS.js | 81 +++++++++++ ncp-web/decrypt/index.php | 92 +++++++++++++ ncp-web/img/toggle-white.svg | 56 ++++++++ ncp-web/index.php | 57 ++++---- 15 files changed, 731 insertions(+), 37 deletions(-) create mode 100644 bin/ncp/SECURITY/nc-encrypt.sh create mode 100644 etc/ncp-config.d/nc-encrypt.cfg create mode 100644 ncp-web/decrypt/CSS.css create mode 100644 ncp-web/decrypt/JS.js create mode 100644 ncp-web/decrypt/index.php create mode 100644 ncp-web/img/toggle-white.svg diff --git a/bin/ncp-provisioning.sh b/bin/ncp-provisioning.sh index cda1c70c..68b12df1 100644 --- a/bin/ncp-provisioning.sh +++ b/bin/ncp-provisioning.sh @@ -64,4 +64,12 @@ BKP="$( ls -1t /var/www/nextcloud-bkp_*.tar.gz 2>/dev/null | head -1 )" ncp-restore "$BKP_NEW" && rm "$BKP_NEW" } +## Check for encrypted data and ask for password +if needs_decrypt; then + echo "Detected encrypted instance" + a2dissite ncp nextcloud + a2ensite ncp-activation + apache2ctl -k graceful +fi + exit 0 diff --git a/bin/ncp/CONFIG/nc-datadir.sh b/bin/ncp/CONFIG/nc-datadir.sh index f99fdcfd..6948518a 100644 --- a/bin/ncp/CONFIG/nc-datadir.sh +++ b/bin/ncp/CONFIG/nc-datadir.sh @@ -100,6 +100,7 @@ configure() # datadir ncc config:system:set datadirectory --value="$DATADIR" ncc config:system:set logfile --value="$DATADIR/nextcloud.log" + set_ncpcfg datadir "${datadir}" restore_maintenance_mode } diff --git a/bin/ncp/SECURITY/nc-encrypt.sh b/bin/ncp/SECURITY/nc-encrypt.sh new file mode 100644 index 00000000..33f8dea3 --- /dev/null +++ b/bin/ncp/SECURITY/nc-encrypt.sh @@ -0,0 +1,107 @@ +#!/bin/bash + +# Data at rest encryption for NextCloudPi +# +# Copyleft 2021 by Ignacio Nunez Hernanz +# GPL licensed (see end of file) * Use at your own risk! +# +# More at: nextcloudpi.com +# + +is_active() +{ + mount | grep ncdata_enc | grep -q gocryptfs +} + +install() +{ + apt_install gocryptfs +} + +configure() +{ +( + set -eu -o pipefail + local datadir parentdir encdir tmpdir + datadir="$(get_ncpcfg datadir)" + [[ "${datadir}" == "null" ]] && datadir=/var/www/nextcloud/data + parentdir="$(dirname "${datadir}")" + encdir="${parentdir}/ncdata_enc" + tmpdir="$(mktemp -u -p "${parentdir}" -t nc-data-crypt.XXXXXX))" + + [[ "${ACTIVE}" != "yes" ]] && { + if ! is_active; then + echo "Data not currently encrypted" + return 0 + fi + save_maintenance_mode + trap restore_maintenance_mode EXIT + echo "Decrypting data..." + mkdir "${tmpdir}" + chown www-data: "${tmpdir}" + pkill tail # prevents from umounting in docker + mv "${datadir}"/* "${datadir}"/.[!.]* "${tmpdir}" + fusermount -u "${datadir}" + rmdir "${datadir}" + mv "${tmpdir}" "${datadir}" + rm "${encdir}"/gocryptfs.* + rmdir "${encdir}" + echo "Data no longer encrypted" + return + } + + if is_active; then + echo "Encrypted data already in use" + return + fi + + # Just mount already encrypted data + if [[ -f "${encdir}"/gocryptfs.conf ]]; then + echo "${PASSWORD}" | gocryptfs -allow_other -q "${encdir}" "${datadir}" 2>&1 | sed /^Switch/d + + # switch to the regular virtual hosts after we decrypt, so we can access NC and ncp-web + a2ensite ncp nextcloud + a2dissite ncp-activation + apache2ctl -k graceful + + echo "Encrypted data now accessible" + return + fi + mkdir -p "${encdir}" + echo "${PASSWORD}" | gocryptfs -init -q "${encdir}" + save_maintenance_mode + trap restore_maintenance_mode EXIT + + mv "${datadir}" "${tmpdir}" + + mkdir "${datadir}" + echo "${PASSWORD}" | gocryptfs -allow_other -q "${encdir}" "${datadir}" 2>&1 | sed /^Switch/d + + echo "Encrypting data..." + mv "${tmpdir}"/* "${tmpdir}"/.[!.]* "${datadir}" + chown -R www-data: "${datadir}" + rmdir "${tmpdir}" + + set_ncpcfg datadir "${datadir}" + + echo "Data is now encrypted" +) +} + +# License +# +# This script 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 script 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 script; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, +# Boston, MA 02111-1307 USA + diff --git a/bin/nextcloud-domain.sh b/bin/nextcloud-domain.sh index 8d511160..ff50c1b5 100644 --- a/bin/nextcloud-domain.sh +++ b/bin/nextcloud-domain.sh @@ -2,6 +2,12 @@ source /usr/local/etc/library.sh +# wait until user decrypts the instance first +while :; do + needs_decrypt || break + sleep 1 +done + # wicd service finishes before completing DHCP while :; do local_ip="$(get_ip)" diff --git a/build/docker/docker-compose.yml b/build/docker/docker-compose.yml index 8e1f5e19..e1c94452 100644 --- a/build/docker/docker-compose.yml +++ b/build/docker/docker-compose.yml @@ -10,6 +10,12 @@ services: volumes: - ncdata:/data - /etc/localtime:/etc/localtime:ro + # for nc-encrypt + devices: + - /dev/fuse:/dev/fuse + # for nc-encrypt # NOTE: take a look at this https://github.com/docker/for-linux/issues/321#issuecomment-677744121 + cap_add: + - SYS_ADMIN container_name: nextcloudpi volumes: diff --git a/build/docker/nextcloud/020nextcloud b/build/docker/nextcloud/020nextcloud index 4826e035..257818ef 100755 --- a/build/docker/nextcloud/020nextcloud +++ b/build/docker/nextcloud/020nextcloud @@ -58,6 +58,14 @@ bash /usr/local/bin/ncp-provisioning.sh echo "Starting notify_push daemon" start_notify_push +if needs_decrypt; then + echo "Waiting for user to decrypt instance" + while :; do + sleep 1 + needs_decrypt || break + done +fi + echo "Configuring Domain" # Trusted Domain (local/public IP) bash /usr/local/bin/nextcloud-domain.sh diff --git a/changelog.md b/changelog.md index a230b03d..e559f3ab 100644 --- a/changelog.md +++ b/changelog.md @@ -1,7 +1,13 @@ -[v1.42.3](https://github.com/nextcloud/nextcloudpi/commit/2d804cb) (2021-10-25) nextcloud-domain: fix variable collision +[v1.43.0](https://github.com/nextcloud/nextcloudpi/commit/9bad41c) (2021-10-22) add nc-encrypt -[v1.42.2](https://github.com/nextcloud/nextcloudpi/commit/9ff21bb) (2021-10-23) nc-backup-auto: ncc path +[v1.42.5](https://github.com/nextcloud/nextcloudpi/commit/f0abbbc) (2021-10-27) letsencrypt: sync ncp and nc cert paths + +[v1.42.4 ](https://github.com/nextcloud/nextcloudpi/commit/f7e28c2) (2021-10-27) small trusted domains refactor + +[v1.42.3 ](https://github.com/nextcloud/nextcloudpi/commit/b1e7323) (2021-10-25) nextcloud-domain: fix variable collision + +[v1.42.2 ](https://github.com/nextcloud/nextcloudpi/commit/9ff21bb) (2021-10-23) nc-backup-auto: ncc path [v1.42.1 ](https://github.com/nextcloud/nextcloudpi/commit/e11ce59) (2021-10-22) ncp-web: fix log download bug diff --git a/etc/library.sh b/etc/library.sh index 63858c35..be674f34 100644 --- a/etc/library.sh +++ b/etc/library.sh @@ -32,7 +32,7 @@ command -v jq &>/dev/null || { PHPVER=$( jq -r .php_version < "$NCPCFG") RELEASE=$( jq -r .release < "$NCPCFG") } -command -v ncc &>/dev/null && NCVER="$(ncc status | grep "version:" | awk '{ print $3 }')" +command -v ncc &>/dev/null && NCVER="$(ncc status 2>/dev/null | grep "version:" | awk '{ print $3 }')" function configure_app() { @@ -481,6 +481,29 @@ function restore_maintenance_mode() fi } +function needs_decrypt() +{ + local active + active="$(find_app_param nc-encrypt ACTIVE)" + (! is_active_app nc-encrypt) && [[ "${active}" == "yes" ]] +} + +function set_ncpcfg() +{ + local name="${1}" + local value="${2}" + local cfg + cfg="$(jq '.' "${NCPCFG}")" + cfg="$(jq ".${name} = \"${value}\"" <<<"${cfg}")" + echo "$cfg" > "${NCPCFG}" +} + +function get_ncpcfg() +{ + local name="${1}" + jq -r ".${name}" < "${NCPCFG}" +} + # License # # This script is free software; you can redistribute it and/or modify it diff --git a/etc/ncp-config.d/nc-encrypt.cfg b/etc/ncp-config.d/nc-encrypt.cfg new file mode 100644 index 00000000..a86e7655 --- /dev/null +++ b/etc/ncp-config.d/nc-encrypt.cfg @@ -0,0 +1,22 @@ +{ + "id": "nc-encrypt", + "name": "Nc-encrypt", + "title": "nc-encrypt", + "description": "Data at rest encryption for NCP", + "info": "The encryption password will be needed after every reboot.\nThis will increase CPU usage.", + "infotitle": "", + "params": [ + { + "id": "ACTIVE", + "name": "Active", + "value": "no", + "type": "bool" + }, + { + "id": "PASSWORD", + "name": "Password", + "value": "ownyourbits", + "type": "password" + } + ] +} diff --git a/ncp-web/activate/index.php b/ncp-web/activate/index.php index 5c94a1a3..b983b8d7 100644 --- a/ncp-web/activate/index.php +++ b/ncp-web/activate/index.php @@ -1,11 +1,25 @@ @@ -63,7 +77,7 @@ HTML; + * GPL licensed (see end of file) * Use at your own risk! + * + * More at https://ownyourbits.com/2017/02/13/nextcloud-ready-raspberry-pi-image/ +*/ + + +html,body { + height:100% +} +article,aside,dialog,figure,footer,header,hgroup,nav,section { + display:block +} +body { + text-align: center; + line-height:1.5 +} +a { + border:0; + color:#fff; + text-decoration:none; + cursor:pointer +} +a * { + cursor:pointer +} +select,.button span,label { + cursor:pointer +} +body { + background-image: url(../img/background.png); + background-color:#0082c9; + font-weight:400; + line-height:1.6em; + font-family:'Open Sans', Frutiger, Calibri, 'Myriad Pro', Myriad, sans-serif; + color:#fff; + height:auto +} +#nojavascript { + position:fixed; + top:0; + bottom:0; + height:100%; + width:100%; + z-index:9000; + text-align:center; + background-color:rgba(0, 0, 0, 0.5); + color:#fff; + line-height:125%; + font-size:24px +} +#nojavascript div { + display:block; + position:relative; + width:50%; + top:35%; + margin:0px auto +} +#nojavascript a { + color:#fff; + border-bottom:2px dotted #fff +} +#nojavascript a:hover,#nojavascript a:focus { + color:#dbdbdb +} +::-webkit-scrollbar { + width:5px +} +::-webkit-scrollbar-track-piece { + background-color:transparent +} +::-webkit-scrollbar-thumb { + background:#dbdbdb; + border-radius:3px +} +select,button,input,textarea { + width: 3em; + min-height:32px; + box-sizing:border-box; + text-align: center; +} +select,button,.button,input:not([type='range']),textarea,#quota,.pager li a { + margin:3px 3px 3px 0; + padding:7px 6px; + font-size:13px; + background-color:#fff; + color:#545454; + border:1px solid #dbdbdb; + outline:none; + border-radius:3px; +} +select:not(:disabled):not(.primary),button:not(:disabled):not(.primary),.button:not(:disabled):not(.primary),input:not([type='range']):not(:disabled):not(.primary),textarea:not(:disabled):not(.primary),#quota:not(:disabled):not(.primary),.pager li a:not(:disabled):not(.primary) { +} +select:not(:disabled):not(.primary):not(#quota):hover,button:not(:disabled):not(.primary):not(#quota):hover,.button:not(:disabled):not(.primary):not(#quota):hover,input:not([type='range']):not(:disabled):not(.primary):not(#quota):hover,textarea:not(:disabled):not(.primary):not(#quota):hover,#quota:not(:disabled):not(.primary):not(#quota):hover,.pager li a:not(:disabled):not(.primary):not(#quota):hover,select:not(:disabled):not(.primary):focus,button:not(:disabled):not(.primary):focus,.button:not(:disabled):not(.primary):focus,input:not([type='range']):not(:disabled):not(.primary):focus,textarea:not(:disabled):not(.primary):focus,#quota:not(:disabled):not(.primary):focus,.pager li a:not(:disabled):not(.primary):focus,select:not(:disabled):not(.primary).active,button:not(:disabled):not(.primary).active,.button:not(:disabled):not(.primary).active,input:not([type='range']):not(:disabled):not(.primary).active,textarea:not(:disabled):not(.primary).active,#quota:not(:disabled):not(.primary).active,.pager li a:not(:disabled):not(.primary).active { + border-color:#0082c9; + outline:none +} +select:not(:disabled):not(.primary):active,button:not(:disabled):not(.primary):active,.button:not(:disabled):not(.primary):active,input:not([type='range']):not(:disabled):not(.primary):active,textarea:not(:disabled):not(.primary):active,#quota:not(:disabled):not(.primary):active,.pager li a:not(:disabled):not(.primary):active { + outline:none; + background-color:#fff +} +select:disabled,button:disabled,.button:disabled,input:not([type='range']):disabled,textarea:disabled,#quota:disabled,.pager li a:disabled { + background-color:#ebebeb; + color:rgba(0, 0, 0, 0.4); + cursor:default; + opacity:0.5 +} +select.primary,button.primary,.button.primary,input:not([type='range']).primary,textarea.primary,#quota.primary,.pager li a.primary { + border:1px solid #0082c9; + background-color:rgba(0, 130, 201, .7); + color:#fff; + cursor:pointer +} +select.primary:not(:disabled):hover,button.primary:not(:disabled):hover,.button.primary:not(:disabled):hover,input:not([type='range']).primary:not(:disabled):hover,textarea.primary:not(:disabled):hover,#quota.primary:not(:disabled):hover,.pager li a.primary:not(:disabled):hover,select.primary:not(:disabled):focus,button.primary:not(:disabled):focus,.button.primary:not(:disabled):focus,input:not([type='range']).primary:not(:disabled):focus,textarea.primary:not(:disabled):focus,#quota.primary:not(:disabled):focus,.pager li a.primary:not(:disabled):focus { + background-color:rgba(0, 130, 201, .85) +} +select.primary:not(:disabled):active,button.primary:not(:disabled):active,.button.primary:not(:disabled):active,input:not([type='range']).primary:not(:disabled):active,textarea.primary:not(:disabled):active,#quota.primary:not(:disabled):active,.pager li a.primary:not(:disabled):active { + background-color:rgba(0, 130, 201, .7) +} +select.primary:disabled,button.primary:disabled,.button.primary:disabled,input:not([type='range']).primary:disabled,textarea.primary:disabled,#quota.primary:disabled,.pager li a.primary:disabled { + background-color:rgba(0, 130, 201, .7); + color:#bababa +} +input { +} +input:not([type='radio']):not([type='checkbox']):not([type='range']):not([type='submit']):not([type='button']):not([type='reset']):not([type='color']):not([type='file']):not([type='image']) { + -webkit-appearance:textfield; + -moz-appearance:textfield +} +select,button,.button,input[type='button'],input[type='submit'],input[type='reset'] { + padding:6px 12px; + width:auto; + min-height:34px; + cursor:pointer; + box-sizing:border-box; + background-color:#f7f7f7 +} +button,.button,input[type='button'],input[type='submit'],input[type='reset'] { + font-weight:bold; +} +button::-moz-focus-inner,.button::-moz-focus-inner,input[type='button']::-moz-focus-inner,input[type='submit']::-moz-focus-inner,input[type='reset']::-moz-focus-inner { + border:0 +} +button,.button { +} +button > span[class^='icon-'],.button > span[class^='icon-'],button > span[class*=' icon-'],.button > span[class*=' icon-'] { + display:inline-block; + vertical-align:text-bottom; + opacity:0.5 +} +textarea { + color:#545454; + cursor:text; + font-family:inherit; + height:auto +} +textarea:not(:disabled):active,textarea:not(:disabled):hover,textarea:not(:disabled):focus { + border-color:#dbdbdb !important; + background-color:#fff !important +} +select { + -webkit-appearance:none; + -moz-appearance:none; + appearance:none; + background:url('../../../core/css/../img/actions/triangle-s.svg') no-repeat right 4px center; + background-color:inherit; + outline:0; + padding-right:24px !important +} +button img,.button img { + cursor:pointer +} +input[type='checkbox'].radio,input[type='radio'].radio,input[type='checkbox'].checkbox,input[type='radio'].checkbox { + position:absolute; + left:-10000px; + top:auto; + width:1px; + height:1px; + overflow:hidden +} +#header { + color: white; +} +h2 { + font-size:20px; + font-weight:300; + margin-bottom:12px; + line-height:140% +} +h3 { + font-size:15px; + font-weight:300; + margin:12px 0 +} +em { + font-style:normal; + -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=50)'; + opacity:0.5 +} +dl { + padding:12px 0 +} +dt,dd { + display:inline-block; + padding:12px; + padding-left:0 +} +dt { + width:130px; + white-space:nowrap; + text-align:right +} +kbd { + padding:4px 10px; + border:1px solid #ccc; + box-shadow:0 1px 0 rgba(0, 0, 0, .2); + border-radius:3px; + display:inline-block; + white-space:nowrap +} + +hr { border: solid 1px white; } + +#ncp-logo { margin-top: 24px; } + +#loading-gif { display: none; } + +#ncp-pwd,#nc-pwd{ width:30em; } + +img { vertical-align: middle; } + +.info { + text-shadow: 0 0 2px rgba(0, 0, 0, .4); + font-size: 80%; +} + +.info a { + font-weight: 600; +} + +.table-wrapper { + width: 80%; + max-width: 450px; + margin-left: auto; + margin-right: auto; +} + +.table-wrapper table { + width: 100%; + max-width: 450px; + margin: 0 auto; +} + +.table-wrapper input[type='text'], .table-wrapper input[type='password'] { + width: 90%; +} diff --git a/ncp-web/decrypt/JS.js b/ncp-web/decrypt/JS.js new file mode 100644 index 00000000..91d6149c --- /dev/null +++ b/ncp-web/decrypt/JS.js @@ -0,0 +1,81 @@ +/// +// NextCloudPi Web Panel javascript library +// +// Copyleft 2017 by Ignacio Nunez Hernanz +// GPL licensed (see end of file) * Use at your own risk! +// +// More at https://ownyourbits.com/2017/02/13/nextcloud-ready-raspberry-pi-image/ +/// + +var MINI = require('minified'); +var $ = MINI.$, $$ = MINI.$$, EE = MINI.EE; + +function errorMsg() +{ + $('#error-box').fill("Something went wrong. Try refreshing the page"); +} + +function decrypt_ok_cb(result) +{ + var ret = $.parseJSON(result); + $('#loading-gif').hide(); + if ( ret.token ) + $('#csrf-token').set( { value: ret.token } ); + if ( ret.ret == '0' ) { + $('#error-box').fill("OK"); + var url = window.location.protocol + '//' + window.location.hostname; + window.location.replace( url ); + } else { + $('#error-box').fill("Password error"); + $('#decrypt-btn').show(); + } +} + +function decrypt() +{ + // request + $.request('post', '../ncp-launcher.php', { action: 'launch', + ref : 'nc-encrypt', + config: '{ "ACTIVE": "yes", "PASSWORD":"' + $('#encryption-pass').get('.value') + '" }', + csrf_token: $('#csrf-token').get('.value') } + ).then(decrypt_ok_cb).error(errorMsg); +} + +// Show password button +$( '.pwd-btn' ).on('click', function(e) + { + var input = this.trav('previousSibling', 1); + if ( input.get('.type') == 'password' ) + input.set('.type', 'text'); + else if ( input.get('.type') == 'text' ) + input.set('.type', 'password'); + }); + +$(function() +{ + $('#decrypt-btn').on('click', function(e) + { + $('#decrypt-btn').hide(); + $('#loading-gif').set( { $display: 'inline' } ); + decrypt(); + } ); + + $$('#encryption-pass').focus(); +} ); + +// License +// +// This script 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 script 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 script; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA diff --git a/ncp-web/decrypt/index.php b/ncp-web/decrypt/index.php new file mode 100644 index 00000000..795b1287 --- /dev/null +++ b/ncp-web/decrypt/index.php @@ -0,0 +1,92 @@ + + + + + + + Unlock NextCloudPi + + + + + + + + + + +
+
+
+ +
+
+
+ + '; + ?> + + + + diff --git a/ncp-web/img/toggle-white.svg b/ncp-web/img/toggle-white.svg new file mode 100644 index 00000000..dbfee9a5 --- /dev/null +++ b/ncp-web/img/toggle-white.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/ncp-web/index.php b/ncp-web/index.php index 361f4210..21ce5475 100644 --- a/ncp-web/index.php +++ b/ncp-web/index.php @@ -8,15 +8,45 @@ More at https://ownyourbits.com/2017/02/13/nextcloud-ready-raspberry-pi-image/ **/ +ob_start(); + +// check for encrypted data to present unlock dialog +exec("bash -c 'source /usr/local/etc/library.sh; needs_decrypt'", $output, $ret); +if ($ret == 0) { + header("Location: decrypt"); + exit(); +} // redirect to activation first time -ob_start(); exec("a2query -s ncp-activation", $output, $ret); if ($ret == 0) { header("Location: activate"); exit(); } +ini_set('session.cookie_httponly', 1); +if (isset($_SERVER['HTTPS'])) + ini_set('session.cookie_secure', 1); +session_start(); + +include('elements.php'); +$modules_path = '/usr/local/etc/ncp-config.d/'; +$l10nDir = "l10n"; + +// security headers +header("Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; object-src 'self';"); +header("X-XSS-Protection: 1; mode=block"); +header("X-Content-Type-Options: nosniff"); +header("X-Robots-Tag: none"); +header("X-Permitted-Cross-Domain-Policies: none"); +header("X-Frame-Options: DENY"); +header("Cache-Control: no-cache"); +header('Pragma: no-cache'); +header('Expires: -1'); + +// HTTP2 push headers +header("Link: ; rel=preload; as=script;,; rel=preload; as=script;,; rel=preload; as=style;,; rel=preload; as=image;, ; rel=preload; as=image;, rel=preconnect href=ncp-launcher.php;"); + ?> @@ -28,31 +58,6 @@ if ($ret == 0) { -; rel=preload; as=script;,; rel=preload; as=script;,; rel=preload; as=style;,; rel=preload; as=image;, ; rel=preload; as=image;, rel=preconnect href=ncp-launcher.php;"); - - ?> -- cgit v1.2.3