This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * @copyright Copyright (c) 2019 Julius Härtl <[email protected]> |
||
4 | * |
||
5 | * @author Julius Härtl <[email protected]> |
||
6 | * |
||
7 | * @license GNU AGPL version 3 or any later version |
||
8 | * |
||
9 | * This program is free software: you can redistribute it and/or modify |
||
10 | * it under the terms of the GNU Affero General Public License as |
||
11 | * published by the Free Software Foundation, either version 3 of the |
||
12 | * License, or (at your option) any later version. |
||
13 | * |
||
14 | * This program is distributed in the hope that it will be useful, |
||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
17 | * GNU Affero General Public License for more details. |
||
18 | * |
||
19 | * You should have received a copy of the GNU Affero General Public License |
||
20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
21 | * |
||
22 | */ |
||
23 | |||
24 | namespace OCA\Richdocuments\Service; |
||
25 | |||
26 | |||
27 | use OCA\Federation\TrustedServers; |
||
28 | use OCA\Files_Sharing\External\Storage as SharingExternalStorage; |
||
29 | use OCA\Richdocuments\TokenManager; |
||
30 | use OCP\AppFramework\Http\RedirectResponse; |
||
31 | use OCP\AppFramework\QueryException; |
||
32 | use OCP\Files\File; |
||
33 | use OCP\Files\InvalidPathException; |
||
34 | use OCP\Files\NotFoundException; |
||
35 | use OCP\Http\Client\IClientService; |
||
36 | use OCP\ICache; |
||
37 | use OCP\ICacheFactory; |
||
38 | use OCP\IConfig; |
||
39 | use OCP\ILogger; |
||
40 | |||
41 | class FederationService { |
||
42 | |||
43 | /** @var ICache */ |
||
44 | private $cache; |
||
45 | /** @var IClientService */ |
||
46 | private $clientService; |
||
47 | /** @var ILogger */ |
||
48 | private $logger; |
||
49 | /** @var TrustedServers */ |
||
50 | private $trustedServers; |
||
51 | /** @var IConfig */ |
||
52 | private $config; |
||
53 | /** @var TokenManager */ |
||
54 | private $tokenManager; |
||
55 | |||
56 | public function __construct(ICacheFactory $cacheFactory, IClientService $clientService, ILogger $logger, TokenManager $tokenManager, IConfig $config) { |
||
57 | $this->cache = $cacheFactory->createDistributed('richdocuments_remote/'); |
||
58 | $this->clientService = $clientService; |
||
59 | $this->logger = $logger; |
||
60 | $this->tokenManager = $tokenManager; |
||
61 | $this->config = $config; |
||
62 | try { |
||
63 | $this->trustedServers = \OC::$server->query( \OCA\Federation\TrustedServers::class); |
||
64 | } catch (QueryException $e) {} |
||
65 | } |
||
66 | |||
67 | /** |
||
68 | * @param $remote |
||
69 | * @return string |
||
70 | * @throws \Exception |
||
71 | */ |
||
72 | public function getRemoteCollaboraURL($remote) { |
||
73 | // If no protocol is provided we default to https |
||
74 | if (strpos($remote, 'http://') !== 0 && strpos($remote, 'https://') !== 0) { |
||
75 | $remote = 'https://' . $remote; |
||
76 | } |
||
77 | |||
78 | if (!$this->isTrustedRemote($remote)) { |
||
79 | throw new \Exception('Unable to determine collabora URL of remote server ' . $remote . ' - Remote is not a trusted server'); |
||
80 | } |
||
81 | $remoteCollabora = $this->cache->get('richdocuments_remote/' . $remote); |
||
82 | if ($remoteCollabora !== null) { |
||
83 | return $remoteCollabora; |
||
84 | } |
||
85 | try { |
||
86 | $client = $this->clientService->newClient(); |
||
87 | $response = $client->get($remote . '/ocs/v2.php/apps/richdocuments/api/v1/federation?format=json', ['timeout' => 5]); |
||
88 | $data = \json_decode($response->getBody(), true); |
||
89 | $remoteCollabora = $data['ocs']['data']['wopi_url']; |
||
90 | $this->cache->set('richdocuments_remote/' . $remote, $remoteCollabora, 3600); |
||
91 | return $remoteCollabora; |
||
92 | } catch (\Throwable $e) { |
||
93 | $this->logger->info('Unable to determine collabora URL of remote server ' . $remote, ['exception' => $e]); |
||
0 ignored issues
–
show
|
|||
94 | $this->cache->set('richdocuments_remote/' . $remote, '', 300); |
||
95 | } |
||
96 | return ''; |
||
97 | } |
||
98 | |||
99 | public function isTrustedRemote($domainWithPort) { |
||
100 | if (strpos($domainWithPort, 'http://') === 0 || strpos($domainWithPort, 'https://') === 0) { |
||
101 | $port = parse_url($domainWithPort, PHP_URL_PORT); |
||
102 | $domainWithPort = parse_url($domainWithPort, PHP_URL_HOST) . ($port ? ':' . $port : ''); |
||
103 | } |
||
104 | |||
105 | if ($this->trustedServers !== null && $this->trustedServers->isTrustedServer($domainWithPort)) { |
||
106 | return true; |
||
107 | } |
||
108 | |||
109 | $domain = $this->getDomainWithoutPort($domainWithPort); |
||
110 | |||
111 | $trustedList = $this->config->getSystemValue('gs.trustedHosts', []); |
||
112 | if (!is_array($trustedList)) { |
||
113 | return false; |
||
114 | } |
||
115 | |||
116 | foreach ($trustedList as $trusted) { |
||
117 | if (!is_string($trusted)) { |
||
118 | break; |
||
119 | } |
||
120 | $regex = '/^' . implode('[-\.a-zA-Z0-9]*', array_map(function ($v) { |
||
121 | return preg_quote($v, '/'); |
||
122 | }, explode('*', $trusted))) . '$/i'; |
||
123 | if (preg_match($regex, $domain) || preg_match($regex, $domainWithPort)) { |
||
124 | return true; |
||
125 | } |
||
126 | } |
||
127 | |||
128 | return false; |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * Strips a potential port from a domain (in format domain:port) |
||
133 | * @param string $host |
||
134 | * @return string $host without appended port |
||
135 | */ |
||
136 | private function getDomainWithoutPort($host) { |
||
137 | $pos = strrpos($host, ':'); |
||
138 | if ($pos !== false) { |
||
139 | $port = substr($host, $pos + 1); |
||
140 | if (is_numeric($port)) { |
||
141 | $host = substr($host, 0, $pos); |
||
142 | } |
||
143 | } |
||
144 | return $host; |
||
145 | } |
||
146 | |||
147 | public function getRemoteDirectUrl($remote, $shareToken, $filePath) { |
||
148 | if ($this->getRemoteCollaboraURL() === '') { |
||
149 | return ''; |
||
150 | } |
||
151 | try { |
||
152 | $client = $this->clientService->newClient(); |
||
153 | $response = $client->post($remote . '/ocs/v2.php/apps/richdocuments/api/v1/federation/direct?format=json', [ |
||
154 | 'timeout' => 5, |
||
155 | 'body' => [ |
||
156 | 'shareToken' => $shareToken, |
||
157 | 'filePath' => $filePath |
||
158 | ] |
||
159 | ]); |
||
160 | $data = \json_decode($response->getBody(), true); |
||
161 | return $data['ocs']['data']; |
||
162 | } catch (\Throwable $e) { |
||
163 | $this->logger->info('Unable to determine collabora URL of remote server ' . $remote, ['exception' => $e]); |
||
0 ignored issues
–
show
The method
OCP\ILogger::info() has been deprecated with message: 20.0.0 use \Psr\Log\LoggerInterface::info
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.
Loading history...
|
|||
164 | } |
||
165 | return null; |
||
166 | } |
||
167 | |||
168 | public function getRemoteFileDetails($remote, $remoteToken) { |
||
169 | if (!$this->isTrustedRemote($remote)) { |
||
170 | $this->logger->info('Unable to determine collabora URL of remote server ' . $remote . ' - Remote is not a trusted server'); |
||
171 | return null; |
||
172 | } |
||
173 | try { |
||
174 | $client = $this->clientService->newClient(); |
||
175 | $response = $client->post($remote . '/ocs/v2.php/apps/richdocuments/api/v1/federation?format=json', [ |
||
176 | 'timeout' => 5, |
||
177 | 'body' => [ |
||
178 | 'token' => $remoteToken |
||
179 | ] |
||
180 | ]); |
||
181 | $responseBody = $response->getBody(); |
||
182 | $data = \json_decode($responseBody, true, 512); |
||
183 | $this->logger->debug('Reveived remote file details for ' . $remoteToken . ' from ' . $remote . ': ' . $responseBody); |
||
184 | return $data['ocs']['data']; |
||
185 | } catch (\Throwable $e) { |
||
186 | $this->logger->error('Unable to fetch remote file details for ' . $remoteToken . ' from ' . $remote, ['exception' => $e]); |
||
187 | } |
||
188 | return null; |
||
189 | } |
||
190 | |||
191 | /** |
||
192 | * @param File $item |
||
193 | * @return string|null |
||
194 | * @throws NotFoundException |
||
195 | * @throws InvalidPathException |
||
196 | */ |
||
197 | public function getRemoteRedirectURL(File $item, $direct = null) { |
||
198 | if ($item->getStorage()->instanceOfStorage(SharingExternalStorage::class)) { |
||
199 | $remote = $item->getStorage()->getRemote(); |
||
200 | $remoteCollabora = $this->getRemoteCollaboraURL($remote); |
||
201 | if ($remoteCollabora !== '') { |
||
202 | if ($direct === null) { |
||
203 | $wopi = $this->tokenManager->getRemoteToken($item); |
||
204 | } else { |
||
205 | $wopi = $this->tokenManager->getRemoteTokenFromDirect($item, $direct->getUid()); |
||
206 | } |
||
207 | $url = rtrim($remote, '/') . '/index.php/apps/richdocuments/remote?shareToken=' . $item->getStorage()->getToken() . |
||
208 | '&remoteServer=' . $wopi->getServerHost() . |
||
209 | '&remoteServerToken=' . $wopi->getToken(); |
||
210 | if ($item->getInternalPath() !== '') { |
||
211 | $url .= '&filePath=' . $item->getInternalPath(); |
||
212 | } |
||
213 | return $url; |
||
214 | } |
||
215 | throw new NotFoundException('Failed to connect to remote collabora instance for ' . $item->getId()); |
||
216 | } |
||
217 | return null; |
||
218 | } |
||
219 | } |
||
220 |
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.