PluginProbe ʕ •ᴥ•ʔ
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization / 1.19.6
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization v1.19.6
1.19.8 1.19.7 1.19.6 1.19.5 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.11.0 1.12.0 1.13.0 1.14.0 1.15.0 1.15.1 1.15.2 1.15.3 1.16.0 1.16.1 1.16.2 1.16.3 1.16.4 1.16.5 1.16.6 1.16.7 1.16.8 1.17.0 1.17.6 1.17.7 1.17.8 1.17.9 1.18.0 1.18.1 1.18.2 1.18.3 1.18.4 1.18.5 1.18.6 1.18.7 1.18.8 1.18.9 1.19.0 1.19.1 1.19.2 1.19.3 1.19.4 1.3.19 1.3.20 1.4.0 1.4.1 1.5.0 1.5.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.16 1.5.17 1.5.18 1.5.19 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.7.0 1.7.1 1.8.0 1.8.1 1.8.3 1.9.0 1.9.1 1.9.2
nitropack / nitropack-sdk / NitroPack / SDK / Api / RemoteConfigFetcher.php
nitropack / nitropack-sdk / NitroPack / SDK / Api Last commit date
AdditionalDomains.php 1 year ago Base.php 8 months ago Cache.php 1 year ago ExcludedUrls.php 1 year ago Excludes.php 1 year ago Integration.php 1 year ago RemoteConfigFetcher.php 1 year ago RequestMaker.php 1 year ago Response.php 1 year ago ResponseStatus.php 1 year ago SafeMode.php 1 year ago SecureRequestMaker.php 1 year ago SignedBase.php 1 year ago Stats.php 1 year ago Tagger.php 1 year ago Url.php 1 year ago VariationCookie.php 1 year ago Varnish.php 1 year ago Warmup.php 1 year ago Webhook.php 1 year ago
RemoteConfigFetcher.php
162 lines
1 <?php
2 namespace NitroPack\SDK\Api;
3
4 // Responsible for fetching the config from the API
5 class RemoteConfigFetcher extends Base {
6
7 private $siteSecret;
8
9 private static $algorithm = 'sha512'; // which algorithm to use for calculating challenge responses - needs to be one of the algos reported by hash_algos();
10 private static $rounds = 5; // how many times to apply the algorithm
11
12 public function __construct($siteId, $siteSecret) {
13 parent::__construct($siteId);
14 $this->siteSecret = $siteSecret;
15 }
16
17 public function get() {
18 // initiate the config request, expecting to receive a challenge
19 $initiation = $this->initiateConfigRequest();
20 if ($initiation->getStatus() != ResponseStatus::OK) {
21 throw new \NitroPack\SDK\ConfigFetcherException('Error while initializing remote config fetch request. Response code: ' . $initiation->getStatus()); // TODO better error message and logging
22 }
23
24 try {
25 /* Expecting a json response like the following:
26 * { "cid": "...", "sc0": "...", "sc1": "...", "resp": "..." }
27 * where cid is the challenge id, sc0/1 are the two challenge strings, and resp is the challenge response for sc0 to verify the server knows the secret */
28 $challenge = json_decode($initiation->getBody(), true);
29 } catch (\Exception $e) {
30 throw new \NitroPack\SDK\ChallengeProcessingException('Error while processing remote config challenge'); // TODO better error message and logging
31 }
32
33 // verify that the challenge came from the API server
34 $expectedResponse = $this->calculateChallengeResponse($challenge['sc0']);
35
36 if (!$this->internal_hash_equals($expectedResponse, $challenge['resp'])) {
37 throw new \NitroPack\SDK\ChallengeVerificationException('API server failed challenge verification when fetching the remote config'); // TODO better error message and logging
38 }
39
40 $challengeResponse = $this->respondToChallenge($challenge['sc1'], $challenge['cid']);
41
42 if ($challengeResponse->getStatus() != ResponseStatus::OK) {
43 throw new \NitroPack\SDK\ConfigFetcherException('Error while receiving remote config. Response code: ' . $challengeResponse->getStatus()); // TODO better error message and logging
44 }
45
46 return $challengeResponse->getBody();
47 }
48
49 private function initiateConfigRequest() {
50 // start the config fetching process by sending the siteId to the server
51 $path = 'config/getchallenge/' . $this->siteId;
52 $httpResponse = $this->makeRequest($path, array(), array()); // path, headers, cookies
53 $status = ResponseStatus::getStatus($httpResponse->getStatusCode());
54 $body = $httpResponse->getBody();
55 return new Response($status, $body);
56 }
57
58 /**
59 * Calculates the challenge response and sends it to the API server
60 * $sc1 - the challenge sent by the server, whose challenge response was not provided
61 * $cId - the id of the challenge
62 */
63 private function respondToChallenge($sc1, $cId) {
64 $path = 'config/get/' . $this->siteId;
65 $headers = array(
66 'X-Challenge-Id' => $cId,
67 'X-Challenge-Response' => $this->calculateChallengeResponse($sc1)
68 );
69 $httpResponse = $this->makeRequest($path, $headers, array()); // path, headers, cookies
70 $status = ResponseStatus::getStatus($httpResponse->getStatusCode());
71 $body = $httpResponse->getBody();
72 return new Response($status, $body);
73 }
74
75 private function calculateChallengeResponse($challenge) {
76 // We cannot use the following algorithms, even if hash_algos reports them as available, since then we cannot offer the same algo across all php versions:
77 /**
78 * 5.3: Added md2, ripemd256, ripemd320, salsa10, salsa20, snefru256, sha224
79 * 5.4: Added joaat, fnv132, fnv164
80 * Removed Salsa10, Salsa 20
81 * 5.6: Added gost-crypto
82 * 7.1: Added sha512/224, sha512/256, sha3-224, sha3-256, sha3-384, sha3-512
83 */
84 $str = $this->siteSecret . $challenge;
85 for ($i = 0; $i < RemoteConfigFetcher::$rounds; ++$i) {
86 $str = hash(RemoteConfigFetcher::$algorithm, $str);
87 }
88 return $str;
89 }
90
91 /**
92 * internal_hash_equals is an implementation of the PHP 5.6+ hash_equals function
93 * Implementation taken from the MIT Licensed hash_equals library at https://github.com/realityking/hash_equals
94 * Copyright notice included below
95 *
96 * This [function] is part of the hash_equals library
97 *
98 * For the full copyright and license information, please view the LICENSE
99 * file that was distributed with this source code.
100 *
101 * @copyright Copyright (c) 2013-2014 Rouven Weßling <http://rouvenwessling.de>
102 * @license http://opensource.org/licenses/MIT MIT
103 *
104 * License text acquired from https://github.com/realityking/hash_equals/blob/master/LICENSE February 21, 2018
105 *
106 * The MIT License (MIT)
107 *
108 * Copyright (c) 2014 Rouven Weßling
109 *
110 * Permission is hereby granted, free of charge, to any person obtaining a copy
111 * of this software and associated documentation files (the "Software"), to deal
112 * in the Software without restriction, including without limitation the rights
113 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
114 * copies of the Software, and to permit persons to whom the Software is
115 * furnished to do so, subject to the following conditions:
116 *
117 * The above copyright notice and this permission notice shall be included in all
118 * copies or substantial portions of the Software.
119 *
120 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
121 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
122 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
123 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
124 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
125 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
126 * SOFTWARE.
127 */
128 protected static function internal_hash_equals($known_string, $user_string) {
129 // iSenseLabs modification to use the PHP function if available
130 if (function_exists('hash_equals')) {
131 return hash_equals($known_string, $user_string);
132 }
133 // We jump trough some hoops to match the internals errors as closely as possible
134 $argc = func_num_args();
135
136 if ($argc < 2) {
137 trigger_error("hash_equals() expects at least 2 parameters, {$argc} given", E_USER_WARNING);
138 return null;
139 }
140
141 if (!is_string($known_string)) {
142 trigger_error("hash_equals(): Expected known_string to be a string, " . gettype($known_string) . " given", E_USER_WARNING);
143 return false;
144 }
145 if (!is_string($user_string)) {
146 trigger_error("hash_equals(): Expected user_string to be a string, " . gettype($user_string) . " given", E_USER_WARNING);
147 return false;
148 }
149
150 if (strlen($known_string) !== strlen($user_string)) {
151 return false;
152 }
153 $len = strlen($known_string);
154 $result = 0;
155 for ($i = 0; $i < $len; $i++) {
156 $result |= (ord($known_string[$i]) ^ ord($user_string[$i]));
157 }
158 // They are only identical strings if $result is exactly 0...
159 return 0 === $result;
160 }
161 }
162