From 09db91bc33d35f108a6bb6a23e45a87be0af8a1b Mon Sep 17 00:00:00 2001 From: Rostislav Wolny Date: Tue, 17 Sep 2019 14:32:45 +0200 Subject: [PATCH] Always use length of database link_token for token validation [MAILPOET-2364] --- lib/Models/Subscriber.php | 6 ++++-- tests/integration/Models/SubscriberTest.php | 13 +++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/Models/Subscriber.php b/lib/Models/Subscriber.php index 203899345b..dfd4662534 100644 --- a/lib/Models/Subscriber.php +++ b/lib/Models/Subscriber.php @@ -138,10 +138,12 @@ class Subscriber extends Model { } function verifyToken($token) { + $database_token = $this->getLinkToken(); + $request_token = substr($token, 0, strlen($database_token)); return call_user_func( 'hash_equals', - $this->getLinkToken(), - $token + $database_token, + $request_token ); } diff --git a/tests/integration/Models/SubscriberTest.php b/tests/integration/Models/SubscriberTest.php index 98005c5b0a..440b0a3259 100644 --- a/tests/integration/Models/SubscriberTest.php +++ b/tests/integration/Models/SubscriberTest.php @@ -686,6 +686,18 @@ class SubscriberTest extends \MailPoetTest { expect($subscriber->verifyToken('faketoken'))->false(); } + function testItVerifiesOldVersionOfSubscriberToken() { + $subscriber = Subscriber::createOrUpdate([ + 'email' => $this->test_data['email'], + ]); + $subscriber->link_token = 'abcdef'; + $token = $subscriber->getLinkToken(); + expect($subscriber->verifyToken($token))->true(); + expect($subscriber->verifyToken('abcdefghijk'))->true(); + expect($subscriber->verifyToken('faketoken'))->false(); + expect($subscriber->verifyToken('fake'))->false(); + } + function testItBulkDeletesSubscribers() { $segment = Segment::createOrUpdate( [ @@ -823,6 +835,7 @@ class SubscriberTest extends \MailPoetTest { expect($values['last_name'])->equals(''); expect($values['status'])->equals(Subscriber::STATUS_UNCONFIRMED); expect(strlen($values['unsubscribe_token']))->equals(15); + expect(strlen($values['link_token']))->equals(32); } function testItSetsDefaultStatusDependingOnSingupConfirmationOption() {