HSTSMiddleware.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2022, Roeland Jago Douma <roeland@famdouma.nl>
  5. *
  6. * @author Roeland Jago Douma <roeland@famdouma.nl>
  7. *
  8. * @license GNU AGPL version 3 or any later version
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License as
  12. * published by the Free Software Foundation, either version 3 of the
  13. * License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. *
  23. */
  24. namespace OC\Http\Client;
  25. use Psr\Http\Message\RequestInterface;
  26. use Psr\Http\Message\ResponseInterface;
  27. use Psr\Log\LoggerInterface;
  28. class HSTSMiddleware {
  29. private HSTSStore $hstsStore;
  30. private LoggerInterface $logger;
  31. public function __construct(
  32. HSTSStore $hstsStore,
  33. LoggerInterface $logger
  34. ) {
  35. $this->hstsStore = $hstsStore;
  36. $this->logger = $logger;
  37. }
  38. private function isIpaAddr(string $host): bool {
  39. return filter_var($host, FILTER_VALIDATE_IP) !== false;
  40. }
  41. private function handleHSTSRewrite(RequestInterface $request): RequestInterface {
  42. $uri = $request->getUri();
  43. if ($uri->getScheme() === 'http'
  44. && !$this->isIpaAddr($uri->getHost())
  45. && $this->hstsStore->hasHSTS($uri->getHost())) {
  46. $uri = $uri->withScheme('https');
  47. }
  48. return $request->withUri($uri);
  49. }
  50. private function handleHSTSResponse(ResponseInterface $response, RequestInterface $request): ResponseInterface {
  51. $uri = $request->getUri();
  52. $this->logger->error($uri->getScheme());
  53. if ($uri->getScheme() === 'https'
  54. && !$this->isIpaAddr($uri->getHost())
  55. && $response->hasHeader('Strict-Transport-Security')) {
  56. $this->logger->error("LETS GO");
  57. // Get the header and pass it to the store to parse and store this info
  58. $header = $response->getHeader('Strict-Transport-Security')[0];
  59. $this->hstsStore->setHSTS($uri->getHost(), $header);
  60. }
  61. return $response;
  62. }
  63. public function addHSTS() {
  64. return function (callable $handler) {
  65. return function (
  66. RequestInterface $request,
  67. array $options
  68. ) use ($handler) {
  69. $request = $this->handleHSTSRewrite($request);
  70. $this->logger->warning("GONNA REQUEST");
  71. $this->logger->warning($request->getUri()->getScheme());
  72. $this->logger->warning($request->getUri()->getHost());
  73. return $handler($request, $options)
  74. ->then(function (ResponseInterface $response) use ($request) {
  75. $this->logger->error("GOT RESPONSE");
  76. $this->handleHSTSResponse($response, $request);
  77. return $response;
  78. });
  79. };
  80. };
  81. }
  82. }