summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--SECURITY.md25
-rw-r--r--apps/admin_audit/lib/AppInfo/Application.php1
-rw-r--r--apps/files/lib/Listener/LegacyLoadAdditionalScriptsAdapter.php2
-rw-r--r--apps/files_external/lib/Lib/Auth/Password/UserGlobalAuth.php5
-rw-r--r--apps/updatenotification/Makefile1
-rw-r--r--build/files-checker.php1
-rw-r--r--core/Command/Maintenance/Install.php5
-rw-r--r--lib/private/Session/CryptoWrapper.php18
-rw-r--r--lib/private/Session/Internal.php12
-rw-r--r--lib/private/Setup.php14
-rw-r--r--lib/private/Setup/MySQL.php27
11 files changed, 99 insertions, 12 deletions
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000000..ee4bdb12eca
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,25 @@
+# Security Policy
+
+## Supported Versions
+
+The latest three major release versions of Nextcloud are currently being supported with security updates.
+Please visit https://github.com/nextcloud/server/wiki/Maintenance-and-Release-Schedule for further details.
+
+## Reporting a Vulnerability
+
+Security is very important to us. If you have discovered a security issue with Nextcloud,
+please read our responsible disclosure guidelines and contact us at [hackerone.com/nextcloud](https://hackerone.com/nextcloud).
+Your report should include:
+
+- Product version
+- A vulnerability description
+- Reproduction steps
+
+A member of the security team will confirm the vulnerability, determine its impact, and develop a fix.
+The fix will be applied to the master branch, tested, and packaged in the next security release.
+The vulnerability will be publicly announced after the release. Finally, your name will be added
+to the [hall of fame](https://hackerone.com/nextcloud/thanks) as a thank you from the entire Nextcloud community. Note our
+[threat model](https://nextcloud.com/security/threat-model) to know what is expected behavior.
+
+
+Please visit https://nextcloud.com/security/ for further information about security.
diff --git a/apps/admin_audit/lib/AppInfo/Application.php b/apps/admin_audit/lib/AppInfo/Application.php
index 44d713f7df0..6d7eff012f0 100644
--- a/apps/admin_audit/lib/AppInfo/Application.php
+++ b/apps/admin_audit/lib/AppInfo/Application.php
@@ -134,6 +134,7 @@ class Application extends App {
Util::connectHook(Share::class, 'post_shared', $shareActions, 'shared');
Util::connectHook(Share::class, 'post_unshare', $shareActions, 'unshare');
+ Util::connectHook(Share::class, 'post_unshareFromSelf', $shareActions, 'unshare');
Util::connectHook(Share::class, 'post_update_permissions', $shareActions, 'updatePermissions');
Util::connectHook(Share::class, 'post_update_password', $shareActions, 'updatePassword');
Util::connectHook(Share::class, 'post_set_expiration_date', $shareActions, 'updateExpirationDate');
diff --git a/apps/files/lib/Listener/LegacyLoadAdditionalScriptsAdapter.php b/apps/files/lib/Listener/LegacyLoadAdditionalScriptsAdapter.php
index fc8926c08bb..938eb5a4819 100644
--- a/apps/files/lib/Listener/LegacyLoadAdditionalScriptsAdapter.php
+++ b/apps/files/lib/Listener/LegacyLoadAdditionalScriptsAdapter.php
@@ -31,7 +31,7 @@ use OC\EventDispatcher\SymfonyAdapter;
use OCA\Files\Event\LoadAdditionalScriptsEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
-use OCP\EventDispatcher\GenericEvent;
+use Symfony\Component\EventDispatcher\GenericEvent;
class LegacyLoadAdditionalScriptsAdapter implements IEventListener {
diff --git a/apps/files_external/lib/Lib/Auth/Password/UserGlobalAuth.php b/apps/files_external/lib/Lib/Auth/Password/UserGlobalAuth.php
index a0c7f91e6f7..9231e5b6a41 100644
--- a/apps/files_external/lib/Lib/Auth/Password/UserGlobalAuth.php
+++ b/apps/files_external/lib/Lib/Auth/Password/UserGlobalAuth.php
@@ -56,6 +56,11 @@ class UserGlobalAuth extends AuthMechanism {
}
public function saveBackendOptions(IUser $user, $id, $backendOptions) {
+ // backendOptions are set when invoked via Files app
+ // but they are not set when invoked via ext storage settings
+ if(!isset($backendOptions['user']) && !isset($backendOptions['password'])) {
+ return;
+ }
// make sure we're not setting any unexpected keys
$credentials = [
'user' => $backendOptions['user'],
diff --git a/apps/updatenotification/Makefile b/apps/updatenotification/Makefile
index 11c4eec98dd..ca810f6aa5a 100644
--- a/apps/updatenotification/Makefile
+++ b/apps/updatenotification/Makefile
@@ -44,6 +44,7 @@ package: clean build-js-production
--exclude=/CONTRIBUTING.md \
--exclude=/issue_template.md \
--exclude=/README.md \
+ --exclude=/SECURITY.md \
--exclude=/.gitignore \
--exclude=/.scrutinizer.yml \
--exclude=/.travis.yml \
diff --git a/build/files-checker.php b/build/files-checker.php
index 27604a07e30..34533698163 100644
--- a/build/files-checker.php
+++ b/build/files-checker.php
@@ -73,6 +73,7 @@ $expectedFiles = [
'remote.php',
'resources',
'robots.txt',
+ 'SECURITY.md',
'status.php',
'tests',
'themes',
diff --git a/core/Command/Maintenance/Install.php b/core/Command/Maintenance/Install.php
index f92d86d0243..fa18ef721b2 100644
--- a/core/Command/Maintenance/Install.php
+++ b/core/Command/Maintenance/Install.php
@@ -134,6 +134,10 @@ class Install extends Command {
} else {
$dbHost = $input->getOption('database-host');
}
+ if ($dbPort) {
+ // Append the port to the host so it is the same as in the config (there is no dbport config)
+ $dbHost .= ':' . $dbPort;
+ }
$dbTablePrefix = 'oc_';
if ($input->hasParameterOption('--database-table-prefix')) {
$dbTablePrefix = (string) $input->getOption('database-table-prefix');
@@ -183,7 +187,6 @@ class Install extends Command {
'dbpass' => $dbPass,
'dbname' => $dbName,
'dbhost' => $dbHost,
- 'dbport' => $dbPort,
'dbtableprefix' => $dbTablePrefix,
'adminlogin' => $adminLogin,
'adminpass' => $adminPassword,
diff --git a/lib/private/Session/CryptoWrapper.php b/lib/private/Session/CryptoWrapper.php
index bbaa907b268..b9dbc90edd6 100644
--- a/lib/private/Session/CryptoWrapper.php
+++ b/lib/private/Session/CryptoWrapper.php
@@ -86,7 +86,23 @@ class CryptoWrapper {
if($webRoot === '') {
$webRoot = '/';
}
- setcookie(self::COOKIE_NAME, $this->passphrase, 0, $webRoot, '', $secureCookie, true);
+
+ if (PHP_VERSION_ID < 70300) {
+ setcookie(self::COOKIE_NAME, $this->passphrase, 0, $webRoot, '', $secureCookie, true);
+ } else {
+ setcookie(
+ self::COOKIE_NAME,
+ $this->passphrase,
+ [
+ 'expires' => 0,
+ 'path' => $webRoot,
+ 'domain' => '',
+ 'secure' => $secureCookie,
+ 'httponly' => true,
+ 'samesite' => 'Lax',
+ ]
+ );
+ }
}
}
}
diff --git a/lib/private/Session/Internal.php b/lib/private/Session/Internal.php
index d235e9eb50b..b9aae76c3b0 100644
--- a/lib/private/Session/Internal.php
+++ b/lib/private/Session/Internal.php
@@ -56,7 +56,7 @@ class Internal extends Session {
set_error_handler([$this, 'trapError']);
$this->invoke('session_name', [$name]);
try {
- $this->invoke('session_start');
+ $this->startSession();
} catch (\Exception $e) {
setcookie($this->invoke('session_name'), '', -1, \OC::$WEBROOT ?: '/');
}
@@ -106,7 +106,7 @@ class Internal extends Session {
public function clear() {
$this->invoke('session_unset');
$this->regenerateId();
- $this->invoke('session_start', [], true);
+ $this->startSession();
$_SESSION = [];
}
@@ -214,4 +214,12 @@ class Internal extends Session {
$this->trapError($e->getCode(), $e->getMessage());
}
}
+
+ private function startSession() {
+ if (PHP_VERSION_ID < 70300) {
+ $this->invoke('session_start');
+ } else {
+ $this->invoke('session_start', [['cookie_samesite' => 'Lax']]);
+ }
+ }
}
diff --git a/lib/private/Setup.php b/lib/private/Setup.php
index 9b604895468..795c8cabcea 100644
--- a/lib/private/Setup.php
+++ b/lib/private/Setup.php
@@ -353,11 +353,9 @@ class Setup {
$this->config->setValues($newConfigValues);
+ $dbSetup->initialize($options);
try {
- $dbSetup->initialize($options);
$dbSetup->setupDatabase($username);
- // apply necessary migrations
- $dbSetup->runMigrations();
} catch (\OC\DatabaseSetupException $e) {
$error[] = [
'error' => $e->getMessage(),
@@ -371,6 +369,16 @@ class Setup {
];
return $error;
}
+ try {
+ // apply necessary migrations
+ $dbSetup->runMigrations();
+ } catch (Exception $e) {
+ $error[] = [
+ 'error' => 'Error while trying to initialise the database: ' . $e->getMessage(),
+ 'hint' => '',
+ ];
+ return $error;
+ }
//create the user and group
$user = null;
diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php
index 3f4dd616a2f..7371c7aeab2 100644
--- a/lib/private/Setup/MySQL.php
+++ b/lib/private/Setup/MySQL.php
@@ -34,6 +34,7 @@ namespace OC\Setup;
use OC\DB\MySqlTools;
use OCP\IDBConnection;
use OCP\ILogger;
+use Doctrine\DBAL\Platforms\MySQL80Platform;
class MySQL extends AbstractDatabase {
public $dbprettyname = 'MySQL/MariaDB';
@@ -57,6 +58,16 @@ class MySQL extends AbstractDatabase {
//fill the database if needed
$query='select count(*) from information_schema.tables where table_schema=? AND table_name = ?';
$connection->executeQuery($query, [$this->dbName, $this->tablePrefix.'users']);
+
+ $connection->close();
+ $connection = $this->connect();
+ try {
+ $connection->connect();
+ } catch (\Exception $e) {
+ $this->logger->logException($e);
+ throw new \OC\DatabaseSetupException($this->trans->t('MySQL username and/or password not valid'),
+ $this->trans->t('You need to enter details of an existing account.'));
+ }
}
/**
@@ -102,10 +113,18 @@ class MySQL extends AbstractDatabase {
$password = $this->dbPassword;
// we need to create 2 accounts, one for global use and one for local user. if we don't specify the local one,
// the anonymous user would take precedence when there is one.
- $query = "CREATE USER '$name'@'localhost' IDENTIFIED WITH mysql_native_password BY '$password'";
- $connection->executeUpdate($query);
- $query = "CREATE USER '$name'@'%' IDENTIFIED WITH mysql_native_password BY '$password'";
- $connection->executeUpdate($query);
+
+ if ($connection->getDatabasePlatform() instanceof Mysql80Platform) {
+ $query = "CREATE USER '$name'@'localhost' IDENTIFIED WITH mysql_native_password BY '$password'";
+ $connection->executeUpdate($query);
+ $query = "CREATE USER '$name'@'%' IDENTIFIED WITH mysql_native_password BY '$password'";
+ $connection->executeUpdate($query);
+ } else {
+ $query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'";
+ $connection->executeUpdate($query);
+ $query = "CREATE USER '$name'@'%' IDENTIFIED BY '$password'";
+ $connection->executeUpdate($query);
+ }
}
catch (\Exception $ex){
$this->logger->logException($ex, [