diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000000..9178a49e25633 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,4 @@ +# .git-blame-ignore-revs + +# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/.github/workflows/smb-kerberos.yml b/.github/workflows/smb-kerberos.yml index c069d665a6ae6..064b6f5e635e9 100644 --- a/.github/workflows/smb-kerberos.yml +++ b/.github/workflows/smb-kerberos.yml @@ -1,20 +1,17 @@ name: Samba Kerberos SSO on: - push: - branches: - - master - - stable* - paths: - - 'apps/files_external/**' - - '.github/workflows/smb-kerberos.yml' pull_request: paths: - 'apps/files_external/**' - '.github/workflows/smb-kerberos.yml' +concurrency: + group: smb-kerberos-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + jobs: smb-kerberos-tests: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 if: ${{ github.repository_owner != 'nextcloud-gmbh' }} @@ -22,21 +19,30 @@ jobs: steps: - name: Checkout server - uses: actions/checkout@v3 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: submodules: true + - name: Checkout user_saml + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + repository: nextcloud/user_saml + path: apps/user_saml + ref: stable-5.2 - name: Pull images run: | - docker pull icewind1991/samba-krb-test-dc - docker pull icewind1991/samba-krb-test-apache - docker pull icewind1991/samba-krb-test-client + docker pull ghcr.io/icewind1991/samba-krb-test-dc + docker pull ghcr.io/icewind1991/samba-krb-test-apache + docker pull ghcr.io/icewind1991/samba-krb-test-client + docker tag ghcr.io/icewind1991/samba-krb-test-dc icewind1991/samba-krb-test-dc + docker tag ghcr.io/icewind1991/samba-krb-test-apache icewind1991/samba-krb-test-apache + docker tag ghcr.io/icewind1991/samba-krb-test-client icewind1991/samba-krb-test-client - name: Setup AD-DC run: | - cp apps/files_external/tests/*.sh . mkdir data sudo chown -R 33 data apps config - DC_IP=$(./start-dc.sh) - ./start-apache.sh $DC_IP $PWD + DC_IP=$(apps/files_external/tests/start-dc.sh) + sleep 1 + apps/files_external/tests/start-apache.sh $DC_IP $PWD echo "DC_IP=$DC_IP" >> $GITHUB_ENV - name: Set up Nextcloud run: | @@ -61,9 +67,9 @@ jobs: chmod 0777 /tmp/shared/cookies echo "SAML login" - ./client-cmd.sh ${{ env.DC_IP }} curl -c /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/index.php/apps/user_saml/saml/login + apps/files_external/tests/client-cmd.sh ${{ env.DC_IP }} curl -c /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/index.php/apps/user_saml/saml/login echo "Check we are logged in" - CONTENT=$(./client-cmd.sh ${{ env.DC_IP }} curl -b /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/remote.php/webdav/smb/test.txt) + CONTENT=$(apps/files_external/tests/client-cmd.sh ${{ env.DC_IP }} curl -b /shared/cookies/jar -s --negotiate -u testuser@DOMAIN.TEST: --delegation always http://httpd.domain.test/remote.php/webdav/smb/test.txt) CONTENT=$(echo $CONTENT | head -n 1 | tr -d '[:space:]') [[ $CONTENT == "testfile" ]] - name: Show logs @@ -71,4 +77,5 @@ jobs: run: | docker exec --user 33 apache ./occ log:file FILEPATH=$(docker exec --user 33 apache ./occ log:file | grep "Log file:" | cut -d' ' -f3) + echo "$FILEPATH:" docker exec --user 33 apache cat $FILEPATH diff --git a/.github/workflows/static-code-analysis.yml b/.github/workflows/static-code-analysis.yml index 2c979333cd40e..cda55ab4c4c92 100644 --- a/.github/workflows/static-code-analysis.yml +++ b/.github/workflows/static-code-analysis.yml @@ -23,7 +23,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: '8.0' - extensions: apcu,ctype,curl,dom,fileinfo,ftp,gd,intl,json,ldap,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip + extensions: apcu,ctype,curl,dom,fileinfo,ftp,gd,imagick,intl,json,ldap,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip coverage: none env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -57,7 +57,7 @@ jobs: uses: shivammathur/setup-php@master with: php-version: '8.0' - extensions: ctype,curl,dom,fileinfo,gd,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip + extensions: ctype,curl,dom,fileinfo,gd,imagick,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip coverage: none - name: Composer install @@ -85,7 +85,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: '8.0' - extensions: ctype,curl,dom,fileinfo,gd,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip + extensions: ctype,curl,dom,fileinfo,gd,imagick,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip coverage: none env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index bd8f1c0a0e796..7e3f1cc03c2de 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -235,7 +235,7 @@ 'OCA\\DAV\\Events\\SubscriptionUpdatedEvent' => $baseDir . '/../lib/Events/SubscriptionUpdatedEvent.php', 'OCA\\DAV\\Exception\\ServerMaintenanceMode' => $baseDir . '/../lib/Exception/ServerMaintenanceMode.php', 'OCA\\DAV\\Exception\\UnsupportedLimitOnInitialSyncException' => $baseDir . '/../lib/Exception/UnsupportedLimitOnInitialSyncException.php', - 'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => $baseDir . '/../lib/Files/BrowserErrorPagePlugin.php', + 'OCA\\DAV\\Files\\ErrorPagePlugin' => $baseDir . '/../lib/Files/ErrorPagePlugin.php', 'OCA\\DAV\\Files\\FileSearchBackend' => $baseDir . '/../lib/Files/FileSearchBackend.php', 'OCA\\DAV\\Files\\FilesHome' => $baseDir . '/../lib/Files/FilesHome.php', 'OCA\\DAV\\Files\\LazySearchBackend' => $baseDir . '/../lib/Files/LazySearchBackend.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index c9d2abe059faf..f259de693d87b 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -250,7 +250,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Events\\SubscriptionUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/SubscriptionUpdatedEvent.php', 'OCA\\DAV\\Exception\\ServerMaintenanceMode' => __DIR__ . '/..' . '/../lib/Exception/ServerMaintenanceMode.php', 'OCA\\DAV\\Exception\\UnsupportedLimitOnInitialSyncException' => __DIR__ . '/..' . '/../lib/Exception/UnsupportedLimitOnInitialSyncException.php', - 'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => __DIR__ . '/..' . '/../lib/Files/BrowserErrorPagePlugin.php', + 'OCA\\DAV\\Files\\ErrorPagePlugin' => __DIR__ . '/..' . '/../lib/Files/ErrorPagePlugin.php', 'OCA\\DAV\\Files\\FileSearchBackend' => __DIR__ . '/..' . '/../lib/Files/FileSearchBackend.php', 'OCA\\DAV\\Files\\FilesHome' => __DIR__ . '/..' . '/../lib/Files/FilesHome.php', 'OCA\\DAV\\Files\\LazySearchBackend' => __DIR__ . '/..' . '/../lib/Files/LazySearchBackend.php', diff --git a/apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php b/apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php index 8928d05b93c96..ddee241f52866 100644 --- a/apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php +++ b/apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php @@ -31,18 +31,14 @@ namespace OCA\DAV\CalDAV\WebcalCaching; use Exception; -use GuzzleHttp\HandlerStack; -use GuzzleHttp\Middleware; +use GuzzleHttp\RequestOptions; use OCA\DAV\CalDAV\CalDavBackend; use OCP\Http\Client\IClientService; use OCP\Http\Client\LocalServerException; use OCP\IConfig; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; use Psr\Log\LoggerInterface; use Sabre\DAV\Exception\BadRequest; use Sabre\DAV\PropPatch; -use Sabre\DAV\Xml\Property\Href; use Sabre\VObject\Component; use Sabre\VObject\DateTimeParser; use Sabre\VObject\InvalidDataException; @@ -76,7 +72,7 @@ public function __construct(CalDavBackend $calDavBackend, IClientService $client $this->logger = $logger; } - public function refreshSubscription(string $principalUri, string $uri) { + public function refreshSubscription(string $principalUri, string $uri): void { $subscription = $this->getSubscription($principalUri, $uri); $mutations = []; if (!$subscription) { @@ -84,7 +80,7 @@ public function refreshSubscription(string $principalUri, string $uri) { } $webcalData = $this->queryWebcalFeed($subscription, $mutations); - if (!$webcalData) { + if ($webcalData === null) { return; } @@ -127,7 +123,7 @@ public function refreshSubscription(string $principalUri, string $uri) { $calendarData = $vObject->serialize(); try { $this->calDavBackend->createCalendarObject($subscription['id'], $objectUri, $calendarData, CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION); - } catch (NoInstancesException | BadRequest $ex) { + } catch (NoInstancesException|BadRequest $ex) { $this->logger->error('Unable to create calendar object from subscription {subscriptionId}', ['exception' => $ex, 'subscriptionId' => $subscription['id'], 'source' => $subscription['source']]); } } @@ -139,7 +135,7 @@ public function refreshSubscription(string $principalUri, string $uri) { $this->updateSubscription($subscription, $mutations); } catch (ParseException $ex) { - $this->logger->error("Subscription {subscriptionId} could not be refreshed due to a parsing error", ['exception' => $ex, 'subscriptionId' => $subscription['id']]); + $this->logger->error('Subscription {subscriptionId} could not be refreshed due to a parsing error', ['exception' => $ex, 'subscriptionId' => $subscription['id']]); } } @@ -165,106 +161,81 @@ function ($sub) use ($uri) { * gets webcal feed from remote server */ private function queryWebcalFeed(array $subscription, array &$mutations): ?string { - $client = $this->clientService->newClient(); - - $didBreak301Chain = false; - $latestLocation = null; - - $handlerStack = HandlerStack::create(); - $handlerStack->push(Middleware::mapRequest(function (RequestInterface $request) { - return $request - ->withHeader('Accept', 'text/calendar, application/calendar+json, application/calendar+xml') - ->withHeader('User-Agent', 'Nextcloud Webcal Service'); - })); - $handlerStack->push(Middleware::mapResponse(function (ResponseInterface $response) use (&$didBreak301Chain, &$latestLocation) { - if (!$didBreak301Chain) { - if ($response->getStatusCode() !== 301) { - $didBreak301Chain = true; - } else { - $latestLocation = $response->getHeader('Location'); - } - } - return $response; - })); - - $allowLocalAccess = $this->config->getAppValue('dav', 'webcalAllowLocalAccess', 'no'); $subscriptionId = $subscription['id']; $url = $this->cleanURL($subscription['source']); if ($url === null) { return null; } - try { - $params = [ - 'allow_redirects' => [ - 'redirects' => 10 - ], - 'handler' => $handlerStack, - 'nextcloud' => [ - 'allow_local_address' => $allowLocalAccess === 'yes', - ] - ]; - - $user = parse_url($subscription['source'], PHP_URL_USER); - $pass = parse_url($subscription['source'], PHP_URL_PASS); - if ($user !== null && $pass !== null) { - $params['auth'] = [$user, $pass]; - } - - $response = $client->get($url, $params); - $body = $response->getBody(); + $allowLocalAccess = $this->config->getAppValue('dav', 'webcalAllowLocalAccess', 'no'); - if ($latestLocation) { - $mutations['{http://calendarserver.org/ns/}source'] = new Href($latestLocation); - } + $params = [ + 'nextcloud' => [ + 'allow_local_address' => $allowLocalAccess === 'yes', + ], + RequestOptions::HEADERS => [ + 'User-Agent' => 'Nextcloud Webcal Service', + 'Accept' => 'text/calendar, application/calendar+json, application/calendar+xml', + ], + ]; + + $user = parse_url($subscription['source'], PHP_URL_USER); + $pass = parse_url($subscription['source'], PHP_URL_PASS); + if ($user !== null && $pass !== null) { + $params[RequestOptions::AUTH] = [$user, $pass]; + } - $contentType = $response->getHeader('Content-Type'); - $contentType = explode(';', $contentType, 2)[0]; - switch ($contentType) { - case 'application/calendar+json': - try { - $jCalendar = Reader::readJson($body, Reader::OPTION_FORGIVING); - } catch (Exception $ex) { - // In case of a parsing error return null - $this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]); - return null; - } - return $jCalendar->serialize(); - - case 'application/calendar+xml': - try { - $xCalendar = Reader::readXML($body); - } catch (Exception $ex) { - // In case of a parsing error return null - $this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]); - return null; - } - return $xCalendar->serialize(); - - case 'text/calendar': - default: - try { - $vCalendar = Reader::read($body); - } catch (Exception $ex) { - // In case of a parsing error return null - $this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]); - return null; - } - return $vCalendar->serialize(); - } + try { + $client = $this->clientService->newClient(); + $response = $client->get($url, $params); } catch (LocalServerException $ex) { $this->logger->warning("Subscription $subscriptionId was not refreshed because it violates local access rules", [ 'exception' => $ex, ]); - return null; } catch (Exception $ex) { $this->logger->warning("Subscription $subscriptionId could not be refreshed due to a network error", [ 'exception' => $ex, ]); - return null; } + + $body = $response->getBody(); + + $contentType = $response->getHeader('Content-Type'); + $contentType = explode(';', $contentType, 2)[0]; + switch ($contentType) { + case 'application/calendar+json': + try { + $jCalendar = Reader::readJson($body, Reader::OPTION_FORGIVING); + } catch (Exception $ex) { + // In case of a parsing error return null + $this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]); + return null; + } + return $jCalendar->serialize(); + + case 'application/calendar+xml': + try { + $xCalendar = Reader::readXML($body); + } catch (Exception $ex) { + // In case of a parsing error return null + $this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]); + return null; + } + return $xCalendar->serialize(); + + case 'text/calendar': + default: + try { + $vCalendar = Reader::read($body); + } catch (Exception $ex) { + // In case of a parsing error return null + $this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]); + return null; + } + return $vCalendar->serialize(); + } } /** diff --git a/apps/dav/lib/Connector/Sabre/Server.php b/apps/dav/lib/Connector/Sabre/Server.php index 6cf6fa954c8db..0831a47b49198 100644 --- a/apps/dav/lib/Connector/Sabre/Server.php +++ b/apps/dav/lib/Connector/Sabre/Server.php @@ -43,4 +43,27 @@ public function __construct($treeOrNode = null) { self::$exposeVersion = false; $this->enablePropfindDepthInfinity = true; } + + // Copied from 3rdparty/sabre/dav/lib/DAV/Server.php + // Should be them exact same without the exception output. + public function start(): void { + try { + // If nginx (pre-1.2) is used as a proxy server, and SabreDAV as an + // origin, we must make sure we send back HTTP/1.0 if this was + // requested. + // This is mainly because nginx doesn't support Chunked Transfer + // Encoding, and this forces the webserver SabreDAV is running on, + // to buffer entire responses to calculate Content-Length. + $this->httpResponse->setHTTPVersion($this->httpRequest->getHTTPVersion()); + + // Setting the base url + $this->httpRequest->setBaseUrl($this->getBaseUri()); + $this->invokeMethod($this->httpRequest, $this->httpResponse); + } catch (\Throwable $e) { + try { + $this->emit('exception', [$e]); + } catch (\Exception $ignore) { + } + } + } } diff --git a/apps/dav/lib/Connector/Sabre/ServerFactory.php b/apps/dav/lib/Connector/Sabre/ServerFactory.php index 755d13f837184..5725e42b04f84 100644 --- a/apps/dav/lib/Connector/Sabre/ServerFactory.php +++ b/apps/dav/lib/Connector/Sabre/ServerFactory.php @@ -34,7 +34,7 @@ use OCP\Files\Folder; use OCA\DAV\AppInfo\PluginManager; use OCA\DAV\DAV\ViewOnlyPlugin; -use OCA\DAV\Files\BrowserErrorPagePlugin; +use OCA\DAV\Files\ErrorPagePlugin; use OCP\Files\Mount\IMountManager; use OCP\IConfig; use OCP\IDBConnection; @@ -120,9 +120,7 @@ public function createServer(string $baseUri, $server->addPlugin(new \OCA\DAV\Connector\Sabre\FakeLockerPlugin()); } - if (BrowserErrorPagePlugin::isBrowserRequest($this->request)) { - $server->addPlugin(new BrowserErrorPagePlugin()); - } + $server->addPlugin(new ErrorPagePlugin($this->request, $this->config)); // wait with registering these until auth is handled and the filesystem is setup $server->on('beforeMethod:*', function () use ($server, $objectTree, $viewCallBack) { diff --git a/apps/dav/lib/DAV/ViewOnlyPlugin.php b/apps/dav/lib/DAV/ViewOnlyPlugin.php index 0ae472460beda..035266af5b1cc 100644 --- a/apps/dav/lib/DAV/ViewOnlyPlugin.php +++ b/apps/dav/lib/DAV/ViewOnlyPlugin.php @@ -58,6 +58,7 @@ public function initialize(Server $server): void { //Sabre\DAV\CorePlugin::httpGet $this->server->on('method:GET', [$this, 'checkViewOnly'], 90); $this->server->on('method:COPY', [$this, 'checkViewOnly'], 90); + $this->server->on('method:MOVE', [$this, 'checkViewOnly'], 90); } /** diff --git a/apps/dav/lib/Files/BrowserErrorPagePlugin.php b/apps/dav/lib/Files/ErrorPagePlugin.php similarity index 57% rename from apps/dav/lib/Files/BrowserErrorPagePlugin.php rename to apps/dav/lib/Files/ErrorPagePlugin.php index b3ce591bd4a8e..59d49cb8fda7c 100644 --- a/apps/dav/lib/Files/BrowserErrorPagePlugin.php +++ b/apps/dav/lib/Files/ErrorPagePlugin.php @@ -24,17 +24,22 @@ */ namespace OCA\DAV\Files; -use OC\AppFramework\Http\Request; use OC_Template; use OCP\AppFramework\Http\ContentSecurityPolicy; +use OCP\IConfig; use OCP\IRequest; use Sabre\DAV\Exception; use Sabre\DAV\Server; use Sabre\DAV\ServerPlugin; -class BrowserErrorPagePlugin extends ServerPlugin { - /** @var Server */ - private $server; +class ErrorPagePlugin extends ServerPlugin { + private ?Server $server = null; + + public function __construct( + private IRequest $request, + private IConfig $config, + ) { + } /** * This initializes the plugin. @@ -43,36 +48,13 @@ class BrowserErrorPagePlugin extends ServerPlugin { * addPlugin is called. * * This method should set up the required event subscriptions. - * - * @param Server $server - * @return void */ - public function initialize(Server $server) { + public function initialize(Server $server): void { $this->server = $server; $server->on('exception', [$this, 'logException'], 1000); } - /** - * @param IRequest $request - * @return bool - */ - public static function isBrowserRequest(IRequest $request) { - if ($request->getMethod() !== 'GET') { - return false; - } - return $request->isUserAgent([ - Request::USER_AGENT_IE, - Request::USER_AGENT_MS_EDGE, - Request::USER_AGENT_CHROME, - Request::USER_AGENT_FIREFOX, - Request::USER_AGENT_SAFARI, - ]); - } - - /** - * @param \Exception $ex - */ - public function logException(\Exception $ex) { + public function logException(\Throwable $ex): void { if ($ex instanceof Exception) { $httpCode = $ex->getHTTPCode(); $headers = $ex->getHTTPHeaders($this->server); @@ -82,7 +64,7 @@ public function logException(\Exception $ex) { } $this->server->httpResponse->addHeaders($headers); $this->server->httpResponse->setStatus($httpCode); - $body = $this->generateBody($httpCode); + $body = $this->generateBody($ex, $httpCode); $this->server->httpResponse->setBody($body); $csp = new ContentSecurityPolicy(); $this->server->httpResponse->addHeader('Content-Security-Policy', $csp->buildPolicy()); @@ -91,20 +73,34 @@ public function logException(\Exception $ex) { /** * @codeCoverageIgnore - * @return bool|string + * @return string */ - public function generateBody(int $httpCode) { - $request = \OC::$server->getRequest(); - - $templateName = 'exception'; - if ($httpCode === 403 || $httpCode === 404) { - $templateName = (string)$httpCode; + public function generateBody(\Throwable $ex, int $httpCode): mixed { + if ($this->acceptHtml()) { + $templateName = 'exception'; + $renderAs = 'guest'; + if ($httpCode === 403 || $httpCode === 404) { + $templateName = (string)$httpCode; + } + } else { + $templateName = 'xml_exception'; + $renderAs = null; + $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); } - $content = new OC_Template('core', $templateName, 'guest'); + $debug = $this->config->getSystemValueBool('debug', false); + + $content = new OC_Template('core', $templateName, $renderAs); $content->assign('title', $this->server->httpResponse->getStatusText()); - $content->assign('remoteAddr', $request->getRemoteAddress()); - $content->assign('requestID', $request->getId()); + $content->assign('remoteAddr', $this->request->getRemoteAddress()); + $content->assign('requestID', $this->request->getId()); + $content->assign('debugMode', $debug); + $content->assign('errorClass', get_class($ex)); + $content->assign('errorMsg', $ex->getMessage()); + $content->assign('errorCode', $ex->getCode()); + $content->assign('file', $ex->getFile()); + $content->assign('line', $ex->getLine()); + $content->assign('exception', $ex); return $content->fetchPage(); } @@ -113,6 +109,15 @@ public function generateBody(int $httpCode) { */ public function sendResponse() { $this->server->sapi->sendResponse($this->server->httpResponse); - exit(); + } + + private function acceptHtml(): bool { + foreach (explode(',', $this->request->getHeader('Accept')) as $part) { + $subparts = explode(';', $part); + if (str_ends_with($subparts[0], '/html')) { + return true; + } + } + return false; } } diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index fe6428361ced2..dac505520d606 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -67,7 +67,7 @@ use OCA\DAV\DAV\PublicAuth; use OCA\DAV\DAV\ViewOnlyPlugin; use OCA\DAV\Events\SabrePluginAuthInitEvent; -use OCA\DAV\Files\BrowserErrorPagePlugin; +use OCA\DAV\Files\ErrorPagePlugin; use OCA\DAV\Files\LazySearchBackend; use OCA\DAV\Profiler\ProfilerPlugin; use OCA\DAV\Provisioning\Apple\AppleProvisioningPlugin; @@ -242,9 +242,7 @@ public function __construct(IRequest $request, string $baseUri) { $this->server->addPlugin(new FakeLockerPlugin()); } - if (BrowserErrorPagePlugin::isBrowserRequest($request)) { - $this->server->addPlugin(new BrowserErrorPagePlugin()); - } + $this->server->addPlugin(new ErrorPagePlugin($this->request, \OC::$server->getConfig())); $lazySearchBackend = new LazySearchBackend(); $this->server->addPlugin(new SearchPlugin($lazySearchBackend)); diff --git a/apps/dav/tests/travis/caldavtest/tests/CalDAV/sync-report.xml b/apps/dav/tests/travis/caldavtest/tests/CalDAV/sync-report.xml index cf4fcde251f4d..388d9df841383 100644 --- a/apps/dav/tests/travis/caldavtest/tests/CalDAV/sync-report.xml +++ b/apps/dav/tests/travis/caldavtest/tests/CalDAV/sync-report.xml @@ -2712,7 +2712,7 @@ prepostcondition error - {DAV:}valid-sync-token + {http://sabredav.org/ns}exception ignoreextras diff --git a/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php b/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php index 5ae62ea8b74f1..62bfd5f828dec 100644 --- a/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php +++ b/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php @@ -26,7 +26,6 @@ */ namespace OCA\DAV\Tests\unit\CalDAV\WebcalCaching; -use GuzzleHttp\HandlerStack; use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CalDAV\WebcalCaching\RefreshWebcalService; use OCP\Http\Client\IClient; @@ -120,9 +119,7 @@ public function testRun(string $body, string $contentType, string $result): void $client->expects($this->once()) ->method('get') - ->with('https://foo.bar/bla2', $this->callback(function ($obj) { - return $obj['allow_redirects']['redirects'] === 10 && $obj['handler'] instanceof HandlerStack; - })) + ->with('https://foo.bar/bla2') ->willReturn($response); $response->expects($this->once()) @@ -188,9 +185,7 @@ public function testRunCreateCalendarNoException(string $body, string $contentTy $client->expects($this->once()) ->method('get') - ->with('https://foo.bar/bla2', $this->callback(function ($obj) { - return $obj['allow_redirects']['redirects'] === 10 && $obj['handler'] instanceof HandlerStack; - })) + ->with('https://foo.bar/bla2') ->willReturn($response); $response->expects($this->once()) @@ -212,7 +207,7 @@ public function testRunCreateCalendarNoException(string $body, string $contentTy $noInstanceException = new NoInstancesException("can't add calendar object"); $this->caldavBackend->expects($this->once()) - ->method("createCalendarObject") + ->method('createCalendarObject') ->willThrowException($noInstanceException); $this->logger->expects($this->once()) @@ -265,9 +260,7 @@ public function testRunCreateCalendarBadRequest(string $body, string $contentTyp $client->expects($this->once()) ->method('get') - ->with('https://foo.bar/bla2', $this->callback(function ($obj) { - return $obj['allow_redirects']['redirects'] === 10 && $obj['handler'] instanceof HandlerStack; - })) + ->with('https://foo.bar/bla2') ->willReturn($response); $response->expects($this->once()) @@ -289,7 +282,7 @@ public function testRunCreateCalendarBadRequest(string $body, string $contentTyp $badRequestException = new BadRequest("can't add reach calendar url"); $this->caldavBackend->expects($this->once()) - ->method("createCalendarObject") + ->method('createCalendarObject') ->willThrowException($badRequestException); $this->logger->expects($this->once()) @@ -367,7 +360,7 @@ public function testRunLocalURL(string $source): void { $this->logger->expects($this->once()) ->method('warning') - ->with("Subscription 42 was not refreshed because it violates local access rules", ['exception' => $localServerException]); + ->with('Subscription 42 was not refreshed because it violates local access rules', ['exception' => $localServerException]); $refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub123'); } @@ -411,15 +404,11 @@ public function testInvalidUrl(): void { ]); $client = $this->createMock(IClient::class); - $this->clientService->expects($this->once()) - ->method('newClient') - ->with() - ->willReturn($client); + $this->clientService->expects($this->never()) + ->method('newClient'); - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('dav', 'webcalAllowLocalAccess', 'no') - ->willReturn('no'); + $this->config->expects($this->never()) + ->method('getAppValue'); $client->expects($this->never()) ->method('get'); diff --git a/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php b/apps/dav/tests/unit/DAV/ErrorPagePluginTest.php similarity index 86% rename from apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php rename to apps/dav/tests/unit/DAV/ErrorPagePluginTest.php index b6ec05afd7875..3c87574e8d28f 100644 --- a/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php +++ b/apps/dav/tests/unit/DAV/ErrorPagePluginTest.php @@ -23,11 +23,11 @@ */ namespace OCA\DAV\Tests\unit\DAV; -use OCA\DAV\Files\BrowserErrorPagePlugin; +use OCA\DAV\Files\ErrorPagePlugin; use Sabre\DAV\Exception\NotFound; use Sabre\HTTP\Response; -class BrowserErrorPagePluginTest extends \Test\TestCase { +class ErrorPagePluginTest extends \Test\TestCase { /** * @dataProvider providesExceptions @@ -35,8 +35,8 @@ class BrowserErrorPagePluginTest extends \Test\TestCase { * @param $exception */ public function test($expectedCode, $exception): void { - /** @var BrowserErrorPagePlugin | \PHPUnit\Framework\MockObject\MockObject $plugin */ - $plugin = $this->getMockBuilder(BrowserErrorPagePlugin::class)->setMethods(['sendResponse', 'generateBody'])->getMock(); + /** @var ErrorPagePlugin | \PHPUnit\Framework\MockObject\MockObject $plugin */ + $plugin = $this->getMockBuilder(ErrorPagePlugin::class)->disableOriginalConstructor()->setMethods(['sendResponse', 'generateBody'])->getMock(); $plugin->expects($this->once())->method('generateBody')->willReturn(':boom:'); $plugin->expects($this->once())->method('sendResponse'); /** @var \Sabre\DAV\Server | \PHPUnit\Framework\MockObject\MockObject $server */ diff --git a/apps/files_external/lib/Lib/Auth/Password/GlobalAuth.php b/apps/files_external/lib/Lib/Auth/Password/GlobalAuth.php index dff5bf8662533..99fb03007ea86 100644 --- a/apps/files_external/lib/Lib/Auth/Password/GlobalAuth.php +++ b/apps/files_external/lib/Lib/Auth/Password/GlobalAuth.php @@ -37,6 +37,7 @@ */ class GlobalAuth extends AuthMechanism { public const CREDENTIALS_IDENTIFIER = 'password::global'; + private const PWD_PLACEHOLDER = '************************'; /** @var ICredentialsManager */ protected $credentialsManager; @@ -59,11 +60,18 @@ public function getAuth($uid) { 'password' => '' ]; } else { + $auth['password'] = self::PWD_PLACEHOLDER; return $auth; } } public function saveAuth($uid, $user, $password) { + // Use old password if it has not changed. + if ($password === self::PWD_PLACEHOLDER) { + $auth = $this->credentialsManager->retrieve($uid, self::CREDENTIALS_IDENTIFIER); + $password = $auth['password']; + } + $this->credentialsManager->store($uid, self::CREDENTIALS_IDENTIFIER, [ 'user' => $user, 'password' => $password diff --git a/build/ca-bundle-etag.txt b/build/ca-bundle-etag.txt index aa05e09184869..faad55357deed 100644 --- a/build/ca-bundle-etag.txt +++ b/build/ca-bundle-etag.txt @@ -1 +1 @@ -"37d19-61c3b1405de33" +"3955f-622d4deb06d62" diff --git a/build/files-checker.php b/build/files-checker.php index 8913b8a9fdc44..08cc971f82be8 100644 --- a/build/files-checker.php +++ b/build/files-checker.php @@ -29,6 +29,7 @@ '.eslintignore', '.eslintrc.js', '.git', + '.git-blame-ignore-revs', '.gitattributes', '.github', '.gitignore', diff --git a/build/integration/features/caldav.feature b/build/integration/features/caldav.feature index e2cb4f8dc9235..dc0f44af46007 100644 --- a/build/integration/features/caldav.feature +++ b/build/integration/features/caldav.feature @@ -3,8 +3,7 @@ Feature: caldav Given user "user0" exists When "admin" requests calendar "user0/MyCalendar" on the endpoint "/remote.php/dav/calendars/" Then The CalDAV HTTP status code should be "404" - And The exception is "Sabre\DAV\Exception\NotFound" - And The error message is "Node with name 'MyCalendar' could not be found" + And The exception is "Internal Server Error" Scenario: Accessing a not shared calendar of another user Given user "user0" exists @@ -12,8 +11,7 @@ Feature: caldav Given The CalDAV HTTP status code should be "201" When "user0" requests calendar "admin/MyCalendar" on the endpoint "/remote.php/dav/calendars/" Then The CalDAV HTTP status code should be "404" - And The exception is "Sabre\DAV\Exception\NotFound" - And The error message is "Node with name 'MyCalendar' could not be found" + And The exception is "Internal Server Error" Scenario: Accessing a not shared calendar of another user via the legacy endpoint Given user "user0" exists @@ -28,8 +26,7 @@ Feature: caldav Given user "user0" exists When "user0" requests calendar "admin/MyCalendar" on the endpoint "/remote.php/dav/calendars/" Then The CalDAV HTTP status code should be "404" - And The exception is "Sabre\DAV\Exception\NotFound" - And The error message is "Node with name 'MyCalendar' could not be found" + And The exception is "Internal Server Error" Scenario: Accessing a not existing calendar of another user via the legacy endpoint Given user "user0" exists @@ -42,8 +39,7 @@ Feature: caldav Given user "user0" exists When "user0" requests calendar "admin/MyCalendar" on the endpoint "/remote.php/dav/calendars/" Then The CalDAV HTTP status code should be "404" - And The exception is "Sabre\DAV\Exception\NotFound" - And The error message is "Node with name 'MyCalendar' could not be found" + And The exception is "Internal Server Error" Scenario: Creating a new calendar When "admin" creates a calendar named "MyCalendar" @@ -64,8 +60,7 @@ Feature: caldav Given user "user0" exists When "user0" sends a create calendar request to "admin/MyCalendar2" on the endpoint "/remote.php/dav/calendars/" Then The CalDAV HTTP status code should be "404" - And The exception is "Sabre\DAV\Exception\NotFound" - And The error message is "Node with name 'admin' could not be found" + And The exception is "Internal Server Error" Scenario: Create calendar request for existing calendar of another user Given user "user0" exists @@ -73,5 +68,4 @@ Feature: caldav Then The CalDAV HTTP status code should be "201" When "user0" sends a create calendar request to "admin/MyCalendar2" on the endpoint "/remote.php/dav/calendars/" Then The CalDAV HTTP status code should be "404" - And The exception is "Sabre\DAV\Exception\NotFound" - And The error message is "Node with name 'admin' could not be found" + And The exception is "Internal Server Error" diff --git a/build/integration/features/carddav.feature b/build/integration/features/carddav.feature index 9c9df6ddd94be..15f1e95e73770 100644 --- a/build/integration/features/carddav.feature +++ b/build/integration/features/carddav.feature @@ -2,15 +2,13 @@ Feature: carddav Scenario: Accessing a not existing addressbook of another user Given user "user0" exists When "admin" requests addressbook "user0/MyAddressbook" with statuscode "404" on the endpoint "/remote.php/dav/addressbooks/users/" - And The CardDAV exception is "Sabre\DAV\Exception\NotFound" - And The CardDAV error message is "Addressbook with name 'MyAddressbook' could not be found" + And The CardDAV exception is "Internal Server Error" Scenario: Accessing a not shared addressbook of another user Given user "user0" exists Given "admin" creates an addressbook named "MyAddressbook" with statuscode "201" When "user0" requests addressbook "admin/MyAddressbook" with statuscode "404" on the endpoint "/remote.php/dav/addressbooks/users/" - And The CardDAV exception is "Sabre\DAV\Exception\NotFound" - And The CardDAV error message is "Addressbook with name 'MyAddressbook' could not be found" + And The CardDAV exception is "Internal Server Error" Scenario: Accessing a not existing addressbook of another user via legacy endpoint Given user "user0" exists @@ -28,8 +26,7 @@ Feature: carddav Scenario: Accessing a not existing addressbook of myself Given user "user0" exists When "user0" requests addressbook "admin/MyAddressbook" with statuscode "404" on the endpoint "/remote.php/dav/addressbooks/users/" - And The CardDAV exception is "Sabre\DAV\Exception\NotFound" - And The CardDAV error message is "Addressbook with name 'MyAddressbook' could not be found" + And The CardDAV exception is "Internal Server Error" Scenario: Creating a new addressbook When "admin" creates an addressbook named "MyAddressbook" with statuscode "201" @@ -67,13 +64,11 @@ Feature: carddav Given user "user0" exists When "user0" sends a create addressbook request to "admin/MyAddressbook2" on the endpoint "/remote.php/dav/addressbooks/" Then The CardDAV HTTP status code should be "404" - And The CardDAV exception is "Sabre\DAV\Exception\NotFound" - And The CardDAV error message is "File not found: admin in 'addressbooks'" + And The CardDAV exception is "Internal Server Error" Scenario: Create addressbook request for existing addressbook of another user Given user "user0" exists When "admin" creates an addressbook named "MyAddressbook2" with statuscode "201" When "user0" sends a create addressbook request to "admin/MyAddressbook2" on the endpoint "/remote.php/dav/addressbooks/" Then The CardDAV HTTP status code should be "404" - And The CardDAV exception is "Sabre\DAV\Exception\NotFound" - And The CardDAV error message is "File not found: admin in 'addressbooks'" + And The CardDAV exception is "Internal Server Error" diff --git a/core/templates/exception.php b/core/templates/exception.php index d26e9ff4f94ed..324724e67ace2 100644 --- a/core/templates/exception.php +++ b/core/templates/exception.php @@ -4,20 +4,7 @@ style('core', ['styles', 'header']); -function print_exception(Throwable $e, \OCP\IL10N $l): void { - print_unescaped('
');
-	p($e->getTraceAsString());
-	print_unescaped('
'); - - if ($e->getPrevious() !== null) { - print_unescaped('
'); - print_unescaped('

'); - p($l->t('Previous')); - print_unescaped('

'); - - print_exception($e->getPrevious(), $l); - } -} +require_once __DIR__ . '/print_exception.php'; ?>
diff --git a/core/templates/print_exception.php b/core/templates/print_exception.php new file mode 100644 index 0000000000000..2def6d4e9d904 --- /dev/null +++ b/core/templates/print_exception.php @@ -0,0 +1,21 @@ +'); + p($e->getTraceAsString()); + print_unescaped(''); + + if ($e->getPrevious() !== null) { + print_unescaped('
'); + print_unescaped('

'); + p($l->t('Previous')); + print_unescaped('

'); + + print_exception($e->getPrevious(), $l); + } +} diff --git a/core/templates/print_xml_exception.php b/core/templates/print_xml_exception.php new file mode 100644 index 0000000000000..94452d8ae9d3f --- /dev/null +++ b/core/templates/print_xml_exception.php @@ -0,0 +1,16 @@ +getTraceAsString()); + + if ($e->getPrevious() !== null) { + print_unescaped(''); + print_exception($e->getPrevious(), $l); + print_unescaped(''); + } +} diff --git a/core/templates/xml_exception.php b/core/templates/xml_exception.php new file mode 100644 index 0000000000000..ba808c88595c2 --- /dev/null +++ b/core/templates/xml_exception.php @@ -0,0 +1,39 @@ +' . "\n"); +?> + + t('Internal Server Error')) ?> + + t('The server was unable to complete your request.')) ?> + t('If this happens again, please send the technical details below to the server administrator.')) ?> + t('More details can be found in the server log.')) ?> + + t('For more details see the documentation ↗.'))?>: + + + + + + + + + + + + + + + + + + + + diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index 9dd862abb3175..d455bd4c46613 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -53,6 +53,7 @@ use OCP\Mail\IMailer; use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\IAttributes; +use OCP\Share\IManager; use OCP\Share\IShare; use OCP\Share\IShareProvider; use function str_starts_with; @@ -94,15 +95,17 @@ class DefaultShareProvider implements IShareProvider { private $config; public function __construct( - IDBConnection $connection, - IUserManager $userManager, - IGroupManager $groupManager, - IRootFolder $rootFolder, - IMailer $mailer, - Defaults $defaults, - IFactory $l10nFactory, - IURLGenerator $urlGenerator, - IConfig $config) { + IDBConnection $connection, + IUserManager $userManager, + IGroupManager $groupManager, + IRootFolder $rootFolder, + IMailer $mailer, + Defaults $defaults, + IFactory $l10nFactory, + IURLGenerator $urlGenerator, + IConfig $config, + private IManager $shareManager, + ) { $this->dbConn = $connection; $this->userManager = $userManager; $this->groupManager = $groupManager; @@ -1302,6 +1305,7 @@ public function groupDeleted($gid) { * * @param string $uid * @param string $gid + * @return void */ public function userDeletedFromGroup($uid, $gid) { /* @@ -1313,7 +1317,7 @@ public function userDeletedFromGroup($uid, $gid) { ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP))) ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid))); - $cursor = $qb->execute(); + $cursor = $qb->executeQuery(); $ids = []; while ($row = $cursor->fetch()) { $ids[] = (int)$row['id']; @@ -1330,7 +1334,45 @@ public function userDeletedFromGroup($uid, $gid) { ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))) ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($uid))) ->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY))); - $qb->execute(); + $qb->executeStatement(); + } + } + + if ($this->shareManager->shareWithGroupMembersOnly()) { + $user = $this->userManager->get($uid); + if ($user === null) { + return; + } + $userGroups = $this->groupManager->getUserGroupIds($user); + + // Delete user shares received by the user from users in the group. + $userReceivedShares = $this->shareManager->getSharedWith($uid, IShare::TYPE_USER, null, -1); + foreach ($userReceivedShares as $share) { + $owner = $this->userManager->get($share->getSharedBy()); + if ($owner === null) { + continue; + } + $ownerGroups = $this->groupManager->getUserGroupIds($owner); + $mutualGroups = array_intersect($userGroups, $ownerGroups); + + if (count($mutualGroups) === 0) { + $this->shareManager->deleteShare($share); + } + } + + // Delete user shares from the user to users in the group. + $userEmittedShares = $this->shareManager->getSharesBy($uid, IShare::TYPE_USER, null, true, -1); + foreach ($userEmittedShares as $share) { + $recipient = $this->userManager->get($share->getSharedWith()); + if ($recipient === null) { + continue; + } + $recipientGroups = $this->groupManager->getUserGroupIds($recipient); + $mutualGroups = array_intersect($userGroups, $recipientGroups); + + if (count($mutualGroups) === 0) { + $this->shareManager->deleteShare($share); + } } } } diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index c339d62da14f6..dfca218d54278 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -776,13 +776,25 @@ public function createShare(IShare $share) { $this->linkCreateChecks($share); $this->setLinkParent($share); - // For now ignore a set token. - $share->setToken( - $this->secureRandom->generate( + for ($i = 0; $i <= 3; $i++) { + $token = $this->secureRandom->generate( \OC\Share\Constants::TOKEN_LENGTH, \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE - ) - ); + ); + + try { + $this->getShareByToken($token); + } catch (\OCP\Share\Exceptions\ShareNotFound $e) { + // Set the unique token + $share->setToken($token); + break; + } + + // Abort after 3 failed attempts + if ($i >= 3) { + throw new \Exception('Unable to generate a unique share token after 3 attempts.'); + } + } // Verify the expiration date $share = $this->validateExpirationDateLink($share); diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php index 6abfb372a4d1e..f861eafda7f0f 100644 --- a/lib/private/Share20/ProviderFactory.php +++ b/lib/private/Share20/ProviderFactory.php @@ -104,7 +104,8 @@ protected function defaultShareProvider() { $this->serverContainer->query(Defaults::class), $this->serverContainer->getL10NFactory(), $this->serverContainer->getURLGenerator(), - $this->serverContainer->getConfig() + $this->serverContainer->getConfig(), + $this->serverContainer->get(IManager::class), ); } diff --git a/resources/codesigning/root.crl b/resources/codesigning/root.crl index 871a8d8f99409..18ecbd554bf63 100644 --- a/resources/codesigning/root.crl +++ b/resources/codesigning/root.crl @@ -1,8 +1,8 @@ -----BEGIN X509 CRL----- -MIII9DCCB9wCAQEwDQYJKoZIhvcNAQELBQAwezELMAkGA1UEBhMCREUxGzAZBgNV +MIIJHjCCCAYCAQEwDQYJKoZIhvcNAQELBQAwezELMAkGA1UEBhMCREUxGzAZBgNV BAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzEXMBUGA1UECgwOTmV4dGNsb3VkIEdtYkgx NjA0BgNVBAMMLU5leHRjbG91ZCBDb2RlIFNpZ25pbmcgSW50ZXJtZWRpYXRlIEF1 -dGhvcml0eRcNMjQwNjI2MTYxNzE0WhcNMzQwNTA1MTYxNzE0WjCCBvkwEwICEAIX +dGhvcml0eRcNMjQxMDE4MDcxNzU5WhcNMzQwODI3MDcxNzU5WjCCByMwEwICEAIX DTIxMDQxOTA5NTI0NVowEwICEBAXDTE2MTAxNzEyMDkxOVowEwICEBYXDTE3MTEy MzE3MzUyOVowEwICEBcXDTE3MDIyMDEwMDIzOFowEwICEBgXDTE5MDEzMDEzMDEy NVowEwICEBwXDTE4MDIwMjEwNTIzOVowEwICEB8XDTE5MDEzMDEzMDEzM1owEwIC @@ -26,25 +26,26 @@ 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 -----END X509 CRL----- diff --git a/resources/config/ca-bundle.crt b/resources/config/ca-bundle.crt index 86d6cd80cc066..f2c24a589d982 100644 --- a/resources/config/ca-bundle.crt +++ b/resources/config/ca-bundle.crt @@ -1,7 +1,9 @@ ## ## Bundle of CA Root Certificates ## -## Certificate data from Mozilla as of: Tue Jul 2 03:12:04 2024 GMT +## Certificate data from Mozilla as of: Tue Sep 24 03:12:04 2024 GMT +## +## Find updated versions here: https://curl.se/docs/caextract.html ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates @@ -14,7 +16,7 @@ ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.29. -## SHA256: 456ff095dde6dd73354c5c28c73d9c06f53b61a803963414cb91a1d92945cdd3 +## SHA256: 36105b01631f9fc03b1eca779b44a30a1a5890b9bf8dc07ccb001a07301e01cf ## @@ -3566,3 +3568,99 @@ Y1w8ndYn81LsF7Kpryz3dvgwHQYDVR0OBBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB cFBTApFwhVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dGXSaQ pYXFuXqUPoeovQA= -----END CERTIFICATE----- + +TWCA CYBER Root CA +================== +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQMQswCQYDVQQG +EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB +IENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQG +EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB +IENZQkVSIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1s +Ts6P40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxFavcokPFh +V8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/34bKS1PE2Y2yHer43CdT +o0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684iJkXXYJndzk834H/nY62wuFm40AZoNWDT +Nq5xQwTxaWV4fPMf88oon1oglWa0zbfuj3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK +/c/WMw+f+5eesRycnupfXtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkH +IuNZW0CP2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDAS9TM +fAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDAoS/xUgXJP+92ZuJF +2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzCkHDXShi8fgGwsOsVHkQGzaRP6AzR +wyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83 +QOGt4A1WNzAdBgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB +AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0ttGlTITVX1olN +c79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn68xDiBaiA9a5F/gZbG0jAn/x +X9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNnTKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDR +IG4kqIQnoVesqlVYL9zZyvpoBJ7tRCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq +/p1hvIbZv97Tujqxf36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0R +FxbIQh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz8ppy6rBe +Pm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4NxKfKjLji7gh7MMrZQzv +It6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzXxeSDwWrruoBa3lwtcHb4yOWHh8qgnaHl +IhInD0Q9HWzq1MKLL295q39QpsQZp6F6t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X +-----END CERTIFICATE----- + +SecureSign Root CA12 +==================== +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT +ZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgwNTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJ +BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU +U2VjdXJlU2lnbiBSb290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3 +emhFKxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mtp7JIKwcc +J/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zdJ1M3s6oYwlkm7Fsf0uZl +fO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gurFzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBF +EaCeVESE99g2zvVQR9wsMJvuwPWW0v4JhscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1Uef +NzFJM3IFTQy2VYzxV4+Kh9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsFAAOC +AQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6LdmmQOmFxv3Y67ilQi +LUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJmBClnW8Zt7vPemVV2zfrPIpyMpce +mik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPS +vWKErI4cqc1avTc7bgoitPQV55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhga +aaI5gdka9at/yOPiZwud9AzqVN/Ssq+xIvEg37xEHA== +-----END CERTIFICATE----- + +SecureSign Root CA14 +==================== +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEMBQAwUTELMAkG +A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT +ZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgwNzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJ +BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU +U2VjdXJlU2lnbiBSb290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh +1oq/FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOgvlIfX8xn +bacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy6pJxaeQp8E+BgQQ8sqVb +1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa +/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9JkdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOE +kJTRX45zGRBdAuVwpcAQ0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSx +jVIHvXiby8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac18iz +ju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs0Wq2XSqypWa9a4X0 +dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIABSMbHdPTGrMNASRZhdCyvjG817XsY +AFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVLApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQAB +o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeq +YR3r6/wtbyPk86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E +rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ibed87hwriZLoA +ymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopTzfFP7ELyk+OZpDc8h7hi2/Ds +Hzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHSDCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPG +FrojutzdfhrGe0K22VoF3Jpf1d+42kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6q +nsb58Nn4DSEC5MUoFlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/ +OfVyK4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6dB7h7sxa +OgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtlLor6CZpO2oYofaphNdgO +pygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB365jJ6UeTo3cKXhZ+PmhIIynJkBugnLN +eLLIjzwec+fBH7/PzqUqm9tEZDKgu39cJRNItX+S +-----END CERTIFICATE----- + +SecureSign Root CA15 +==================== +-----BEGIN CERTIFICATE----- +MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMwUTELMAkGA1UE +BhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRTZWN1 +cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMyNTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNV +BAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2Vj +dXJlU2lnbiBSb290IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5G +dCx4wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSRZHX+AezB +2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT9DAKBggqhkjOPQQDAwNoADBlAjEA2S6J +fl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJ +SwdLZrWeqrqgHkHZAXQ6bkU6iYAZezKYVWOr62Nuk22rGwlgMU4= +-----END CERTIFICATE----- diff --git a/tests/lib/Share20/DefaultShareProviderTest.php b/tests/lib/Share20/DefaultShareProviderTest.php index 0a6f106a5dba9..75acae1ffcaee 100644 --- a/tests/lib/Share20/DefaultShareProviderTest.php +++ b/tests/lib/Share20/DefaultShareProviderTest.php @@ -39,6 +39,7 @@ use OCP\IUserManager; use OCP\L10N\IFactory; use OCP\Mail\IMailer; +use OCP\Share\IManager as IShareManager; use OCP\Share\IShare; use PHPUnit\Framework\MockObject\MockObject; @@ -82,6 +83,9 @@ class DefaultShareProviderTest extends \Test\TestCase { /** @var IConfig|MockObject */ protected $config; + /** @var IShareManager&MockObject */ + protected $shareManager; + protected function setUp(): void { $this->dbConn = \OC::$server->getDatabaseConnection(); $this->userManager = $this->createMock(IUserManager::class); @@ -93,6 +97,7 @@ protected function setUp(): void { $this->defaults = $this->getMockBuilder(Defaults::class)->disableOriginalConstructor()->getMock(); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->config = $this->createMock(IConfig::class); + $this->shareManager = $this->createMock(IShareManager::class); $this->userManager->expects($this->any())->method('userExists')->willReturn(true); @@ -108,7 +113,8 @@ protected function setUp(): void { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->config, + $this->shareManager, ); } @@ -132,8 +138,8 @@ protected function tearDown(): void { * @return int */ private function addShareToDB($shareType, $sharedWith, $sharedBy, $shareOwner, - $itemType, $fileSource, $fileTarget, $permissions, $token, $expiration, - $parent = null) { + $itemType, $fileSource, $fileTarget, $permissions, $token, $expiration, + $parent = null) { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share'); @@ -469,7 +475,8 @@ public function testDeleteSingleShare() { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->config, + $this->shareManager, ]) ->setMethods(['getShareById']) ->getMock(); @@ -564,7 +571,8 @@ public function testDeleteGroupShareWithUserGroupShares() { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->config, + $this->shareManager, ]) ->setMethods(['getShareById']) ->getMock(); @@ -2524,7 +2532,8 @@ public function testGetSharesInFolder() { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->config, + $this->shareManager, ); $password = md5(time()); @@ -2622,7 +2631,8 @@ public function testGetAccessListNoCurrentAccessRequired() { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->config, + $this->shareManager, ); $u1 = $userManager->createUser('testShare1', 'test'); @@ -2718,7 +2728,8 @@ public function testGetAccessListCurrentAccessRequired() { $this->defaults, $this->l10nFactory, $this->urlGenerator, - $this->config + $this->config, + $this->shareManager, ); $u1 = $userManager->createUser('testShare1', 'test');