Skip to content

Commit 43eb52c

Browse files
committed
Fix. Remote Calls. Skip check if no sign of RC action provided in Request.
1 parent 4dbf269 commit 43eb52c

File tree

2 files changed

+270
-4
lines changed

2 files changed

+270
-4
lines changed

lib/Cleantalk/ApbctWP/RemoteCalls.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,13 @@ class RemoteCalls
3131
*/
3232
public static function check()
3333
{
34-
return Request::get('spbc_remote_call_token')
35-
? self::checkWithToken()
36-
: self::checkWithoutToken();
34+
//do not check token logic if no RC action sign found
35+
if ( Request::getString('spbc_remote_call_action') ) {
36+
return Request::getString('spbc_remote_call_token')
37+
? self::checkWithToken()
38+
: self::checkWithoutToken();
39+
}
40+
return false;
3741
}
3842

3943
public static function checkWithToken()
@@ -107,7 +111,7 @@ public static function perform()
107111
// Check Access key
108112
if (
109113
(self::checkToken($token)) ||
110-
(self::checkWithoutToken() && self::isAllowedWithoutToken($action))
114+
(self::isAllowedWithoutToken($action) && self::checkWithoutToken())
111115
) {
112116
// Flag to let plugin know that Remote Call is running.
113117
$apbct->rc_running = true;

tests/ApbctWP/TestRemoteCalls.php

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
<?php
2+
3+
use PHPUnit\Framework\TestCase;
4+
use Cleantalk\ApbctWP\RemoteCalls;
5+
6+
class TestRemoteCalls extends TestCase
7+
{
8+
protected function tearDown(): void
9+
{
10+
// Reset global after each test
11+
global $apbct;
12+
$apbct = null;
13+
}
14+
15+
/** @test */
16+
public function checkReturnsFalseWhenNoActionProvided()
17+
{
18+
$_REQUEST = [];
19+
\Cleantalk\ApbctWP\Variables\Request::getInstance()->variables = $_REQUEST;
20+
$this->assertFalse(RemoteCalls::check());
21+
}
22+
23+
/** @test */
24+
public function checkCallsCheckWithTokenWhenTokenProvided()
25+
{
26+
$_REQUEST = [
27+
'spbc_remote_call_action' => 'antispam',
28+
'spbc_remote_call_token' => 'token',
29+
//any token is allowed on check() stage, containment will be checked on perform()
30+
'plugin_name' => 'antispam',
31+
];
32+
33+
\Cleantalk\ApbctWP\Variables\Request::getInstance()->variables = $_REQUEST;
34+
35+
// checkWithToken returns true
36+
$this->assertTrue(RemoteCalls::check());
37+
}
38+
39+
/** @test */
40+
public function checkCallsCheckWithoutTokenWhenNoTokenProvided()
41+
{
42+
global $apbct;
43+
44+
$_REQUEST = [
45+
'spbc_remote_call_action' => 'get_fresh_wpnonce', //allowed action
46+
'plugin_name' => 'antispam',
47+
];
48+
49+
\Cleantalk\ApbctWP\Variables\Request::getInstance()->variables = $_REQUEST;
50+
51+
$apbct = new stdClass();
52+
$apbct->key_is_ok = true;
53+
$apbct->api_key = null;
54+
$apbct->data = [];
55+
$apbct->data['moderate_ip'] = null;
56+
57+
// checkWithoutToken returns true
58+
$this->assertTrue(RemoteCalls::check());
59+
}
60+
61+
public function checkCallsCheckWithTokenWhenEmptyTokenProvided()
62+
{
63+
$_REQUEST = [
64+
'spbc_remote_call_action' => 'antispam',
65+
//any token is allowed on check() stage, containment will be checked on perform()
66+
'plugin_name' => 'antispam',
67+
];
68+
69+
\Cleantalk\ApbctWP\Variables\Request::getInstance()->variables = $_REQUEST;
70+
71+
// checkWithToken returns true
72+
$this->assertFalse(RemoteCalls::check());
73+
}
74+
75+
/** @test */
76+
public function checkCallsCheckWithoutTokenWhenActioNIsNotAllowed()
77+
{
78+
global $apbct;
79+
80+
$_REQUEST = [
81+
'spbc_remote_call_action' => 'debug', //rejected action
82+
'plugin_name' => 'antispam',
83+
];
84+
85+
\Cleantalk\ApbctWP\Variables\Request::getInstance()->variables = $_REQUEST;
86+
87+
$apbct = new stdClass();
88+
$apbct->key_is_ok = true;
89+
$apbct->api_key = null;
90+
$apbct->data = [];
91+
$apbct->data['moderate_ip'] = null;
92+
93+
// checkWithoutToken returns true
94+
$this->assertFalse(RemoteCalls::check());
95+
}
96+
97+
/** @test */
98+
public function itHidesSensitiveDataInFlatArray()
99+
{
100+
$input = [
101+
'apikey' => '1234567890',
102+
'user_token' => 'abcdef',
103+
'salt' => 'qwerty12345',
104+
'normal_key' => 'visible'
105+
];
106+
107+
$method = new ReflectionMethod(RemoteCalls::class, 'hideSensitiveData');
108+
$method->setAccessible(true);
109+
110+
$result = $method->invoke(null, $input);
111+
112+
$this->assertEquals('12******90', $result['apikey']);
113+
$this->assertEquals('ab**ef', $result['user_token']);
114+
$this->assertEquals('qw*******45', $result['salt']);
115+
$this->assertEquals('visible', $result['normal_key']);
116+
}
117+
118+
/** @test */
119+
public function itHidesSensitiveDataInNestedArray()
120+
{
121+
$input = [
122+
'level1' => [
123+
'level2' => [
124+
'apikey' => 'abcdefghij'
125+
]
126+
]
127+
];
128+
129+
$method = new ReflectionMethod(RemoteCalls::class, 'hideSensitiveData');
130+
$method->setAccessible(true);
131+
132+
$result = $method->invoke(null, $input);
133+
134+
$this->assertEquals(
135+
'ab******ij',
136+
$result['level1']['level2']['apikey']
137+
);
138+
}
139+
140+
/** @test */
141+
public function itMasksShortSensitiveValues()
142+
{
143+
$input = [
144+
'apikey' => '1234'
145+
];
146+
147+
$method = new ReflectionMethod(RemoteCalls::class, 'hideSensitiveData');
148+
$method->setAccessible(true);
149+
150+
$result = $method->invoke(null, $input);
151+
152+
$this->assertEquals('****', $result['apikey']);
153+
}
154+
155+
/** @test */
156+
public function itDoesNotModifyNonArrayInput()
157+
{
158+
$method = new ReflectionMethod(RemoteCalls::class, 'hideSensitiveData');
159+
$method->setAccessible(true);
160+
161+
$result = $method->invoke(null, 'string');
162+
163+
$this->assertEquals('string', $result);
164+
}
165+
166+
/** @test */
167+
public function itValidatesMd5Token()
168+
{
169+
global $apbct;
170+
171+
$apbct = new stdClass();
172+
$apbct->api_key = 'testKey';
173+
$apbct->data = [];
174+
175+
$validToken = strtolower(md5('testKey'));
176+
177+
$method = new ReflectionMethod(RemoteCalls::class, 'checkToken');
178+
$method->setAccessible(true);
179+
180+
$this->assertTrue($method->invoke(null, $validToken));
181+
}
182+
183+
/** @test */
184+
public function itValidatesSha256Token()
185+
{
186+
global $apbct;
187+
188+
$apbct = new stdClass();
189+
$apbct->api_key = 'testKey';
190+
$apbct->data = [];
191+
192+
$validToken = strtolower(hash('sha256', 'testKey'));
193+
194+
$method = new ReflectionMethod(RemoteCalls::class, 'checkToken');
195+
$method->setAccessible(true);
196+
197+
$this->assertTrue($method->invoke(null, $validToken));
198+
}
199+
200+
/** @test */
201+
public function itReturnsFalseForInvalidToken()
202+
{
203+
global $apbct;
204+
205+
$apbct = new stdClass();
206+
$apbct->api_key = 'testKey';
207+
$apbct->data = [];
208+
209+
$method = new ReflectionMethod(RemoteCalls::class, 'checkToken');
210+
$method->setAccessible(true);
211+
212+
$this->assertFalse($method->invoke(null, 'invalidToken'));
213+
}
214+
215+
/** @test */
216+
public function itReturnsFalseIfNoApiKeyProvided()
217+
{
218+
global $apbct;
219+
220+
$apbct = new stdClass();
221+
$apbct->api_key = null;
222+
$apbct->data = [];
223+
$apbct->data['moderate_ip'] = null;
224+
225+
$method = new ReflectionMethod(RemoteCalls::class, 'checkToken');
226+
$method->setAccessible(true);
227+
228+
$this->assertFalse($method->invoke(null, md5('anything')));
229+
}
230+
231+
/** @test */
232+
public function itMapsSettingTitlesCorrectly()
233+
{
234+
$settings = [
235+
'apikey' => '123',
236+
'forms__registrations_test' => 1,
237+
'unknown_key' => 'abc'
238+
];
239+
240+
$method = new ReflectionMethod(RemoteCalls::class, 'getSettings');
241+
$method->setAccessible(true);
242+
243+
$result = $method->invoke(null, $settings);
244+
245+
$this->assertArrayHasKey('apikey - Access key', $result);
246+
$this->assertArrayHasKey('forms__registrations_test - Registration Forms', $result);
247+
$this->assertEquals('123', $result['apikey - Access key']);
248+
$this->assertEquals(1, $result['forms__registrations_test - Registration Forms']);
249+
$this->assertEquals('abc', $result['unknown_key']);
250+
}
251+
252+
/** @test */
253+
public function itDetectsAllowedActionsWithoutToken()
254+
{
255+
$method = new ReflectionMethod(RemoteCalls::class, 'isAllowedWithoutToken');
256+
$method->setAccessible(true);
257+
258+
$this->assertTrue($method->invoke(null, 'get_fresh_wpnonce'));
259+
$this->assertTrue($method->invoke(null, 'post_api_key'));
260+
$this->assertFalse($method->invoke(null, 'update_license'));
261+
}
262+
}

0 commit comments

Comments
 (0)