From 865e36906d6bc1c471d5890b21349a75fcc047a3 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 1 Jun 2021 10:51:56 +0300 Subject: [PATCH 1/4] Fixed missing email conflict check when calling `Login::register()` --- CHANGELOG.md | 6 ++++++ classes/Login.php | 29 ++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89d2e4a..9e478e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v3.4.4 +## mm/dd/2021 + +1. [](#bugfix) + * Fixed missing email conflict check when calling `Login::register()` + # v3.4.3 ## 05/19/2021 diff --git a/classes/Login.php b/classes/Login.php index 27e321e..1fb9622 100755 --- a/classes/Login.php +++ b/classes/Login.php @@ -239,10 +239,15 @@ public function authenticate($credentials, $options = ['remember_me' => true]) */ public function register(array $data, array $files = []) { + // Add defaults and mandatory fields. + $data += [ + 'username' => null, + 'email' => null + ]; + if (!isset($data['groups'])) { //Add new user ACL settings $groups = (array) $this->config->get('plugins.login.user_registration.groups', []); - if (\count($groups) > 0) { $data['groups'] = $groups; } @@ -250,14 +255,12 @@ public function register(array $data, array $files = []) if (!isset($data['access'])) { $access = (array) $this->config->get('plugins.login.user_registration.access.site', []); - if (\count($access) > 0) { $data['access']['site'] = $access; } } // Validate fields from the form. - $username = $this->validateField('username', $data['username']); $password = $this->validateField('password1', $data['password'] ?? $data['password1'] ?? null); foreach ($data as $key => &$value) { $value = $this->validateField($key, $value, $key === 'password2' ? $password : ''); @@ -267,12 +270,24 @@ public function register(array $data, array $files = []) /** @var UserCollectionInterface $users */ $users = $this->grav['accounts']; - // Create user object and save it - $user = $users->load($username); - if ($user->exists()) { - throw new \RuntimeException('User ' . $username . ' cannot be registered: user already exists!'); + // Check whether username already exists. + $username = $data['username']; + if (!$username || !$users->find($username, ['username'])->exists()) { + /** @var Language $language */ + $language = $this->grav['language']; + + throw new \RuntimeException($language->translate(['PLUGIN_LOGIN.USERNAME_NOT_AVAILABLE', $username])); + } + // Check whether email already exists. + $email = $data['email']; + if (!$email || $users->find($email, ['email'])->exists()) { + /** @var Language $language */ + $language = $this->grav['language']; + + throw new \RuntimeException($language->translate(['PLUGIN_LOGIN.EMAIL_NOT_AVAILABLE', $email])); } + $user = $users->load($username); $user->update($data, $files); if (isset($data['groups'])) { $user->groups = $data['groups']; From b7996fda7a3b56432ef9e249584616d86d977517 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 2 Jun 2021 10:47:04 +0300 Subject: [PATCH 2/4] Minor regression --- classes/Login.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/classes/Login.php b/classes/Login.php index 1fb9622..c6a4a6b 100755 --- a/classes/Login.php +++ b/classes/Login.php @@ -267,12 +267,12 @@ public function register(array $data, array $files = []) } unset($value); - /** @var UserCollectionInterface $users */ - $users = $this->grav['accounts']; + /** @var UserCollectionInterface $accounts */ + $accounts = $this->grav['accounts']; // Check whether username already exists. $username = $data['username']; - if (!$username || !$users->find($username, ['username'])->exists()) { + if (!$username || $accounts->find($username, ['username'])->exists()) { /** @var Language $language */ $language = $this->grav['language']; @@ -280,14 +280,14 @@ public function register(array $data, array $files = []) } // Check whether email already exists. $email = $data['email']; - if (!$email || $users->find($email, ['email'])->exists()) { + if (!$email || $accounts->find($email, ['email'])->exists()) { /** @var Language $language */ $language = $this->grav['language']; throw new \RuntimeException($language->translate(['PLUGIN_LOGIN.EMAIL_NOT_AVAILABLE', $email])); } - $user = $users->load($username); + $user = $accounts->load($username); $user->update($data, $files); if (isset($data['groups'])) { $user->groups = $data['groups']; From 6cefeee20f74847e3d5b56bca7f126c42c7b8298 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Thu, 10 Jun 2021 09:39:31 +0300 Subject: [PATCH 3/4] Updated 2FA library --- CHANGELOG.md | 2 + composer.lock | 25 +- vendor/composer/InstalledVersions.php | 10 +- vendor/composer/installed.json | 33 +- vendor/composer/installed.php | 10 +- .../twofactorauth/.github/FUNDING.yml | 4 + .../twofactorauth/.github/workflows/test.yml | 27 + vendor/robthree/twofactorauth/.gitignore | 7 +- vendor/robthree/twofactorauth/.travis.yml | 15 - vendor/robthree/twofactorauth/README.md | 42 +- vendor/robthree/twofactorauth/composer.json | 19 +- vendor/robthree/twofactorauth/composer.lock | 980 ------------------ .../lib/Providers/Qr/BaconQrCodeProvider.php | 152 +++ .../Providers/Qr/BaseHTTPQRCodeProvider.php | 12 +- .../Providers/Qr/EndroidQrCodeProvider.php | 70 ++ .../Qr/EndroidQrCodeWithLogoProvider.php | 35 + .../lib/Providers/Qr/IQRCodeProvider.php | 17 +- .../Qr/ImageChartsQRCodeProvider.php | 47 +- .../lib/Providers/Qr/QRException.php | 4 +- .../lib/Providers/Qr/QRServerProvider.php | 81 +- .../lib/Providers/Qr/QRicketProvider.php | 58 +- .../lib/Providers/Rng/CSRNGProvider.php | 16 +- .../lib/Providers/Rng/HashRNGProvider.php | 35 +- .../lib/Providers/Rng/IRNGProvider.php | 11 +- .../lib/Providers/Rng/MCryptRNGProvider.php | 32 +- .../lib/Providers/Rng/OpenSSLRNGProvider.php | 37 +- .../lib/Providers/Rng/RNGException.php | 4 +- .../lib/Providers/Time/HttpTimeProvider.php | 43 +- .../lib/Providers/Time/ITimeProvider.php | 5 +- .../Time/LocalMachineTimeProvider.php | 8 +- .../lib/Providers/Time/NTPTimeProvider.php | 38 +- .../lib/Providers/Time/TimeException.php | 4 +- .../twofactorauth/lib/TwoFactorAuth.php | 184 +++- .../lib/TwoFactorAuthException.php | 2 +- vendor/robthree/twofactorauth/phpunit.xml | 18 +- .../twofactorauth/phpunit.xml.tmppica | 0 .../tests/MightNotMakeAssertions.php | 26 + .../Providers/Qr/IQRCodeProviderTest.php | 56 + .../tests/Providers/Qr/TestQrProvider.php | 24 + .../tests/Providers/Rng/CSRNGProviderTest.php | 30 + .../Providers/Rng/HashRNGProviderTest.php | 24 + .../tests/Providers/Rng/IRNGProviderTest.php | 61 ++ .../Providers/Rng/MCryptRNGProviderTest.php | 32 + .../tests/Providers/Rng/NeedsRngLengths.php | 9 + .../Providers/Rng/OpenSSLRNGProviderTest.php | 37 + .../tests/Providers/Rng/TestRNGProvider.php | 41 + .../Providers/Time/ITimeProviderTest.php | 53 + .../tests/Providers/Time/TestTimeProvider.php | 27 + .../twofactorauth/tests/TwoFactorAuthTest.php | 363 ++----- 49 files changed, 1399 insertions(+), 1471 deletions(-) create mode 100644 vendor/robthree/twofactorauth/.github/FUNDING.yml create mode 100644 vendor/robthree/twofactorauth/.github/workflows/test.yml delete mode 100644 vendor/robthree/twofactorauth/.travis.yml delete mode 100644 vendor/robthree/twofactorauth/composer.lock create mode 100644 vendor/robthree/twofactorauth/lib/Providers/Qr/BaconQrCodeProvider.php create mode 100755 vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeProvider.php create mode 100755 vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeWithLogoProvider.php delete mode 100644 vendor/robthree/twofactorauth/phpunit.xml.tmppica create mode 100644 vendor/robthree/twofactorauth/tests/MightNotMakeAssertions.php create mode 100644 vendor/robthree/twofactorauth/tests/Providers/Qr/IQRCodeProviderTest.php create mode 100644 vendor/robthree/twofactorauth/tests/Providers/Qr/TestQrProvider.php create mode 100644 vendor/robthree/twofactorauth/tests/Providers/Rng/CSRNGProviderTest.php create mode 100644 vendor/robthree/twofactorauth/tests/Providers/Rng/HashRNGProviderTest.php create mode 100644 vendor/robthree/twofactorauth/tests/Providers/Rng/IRNGProviderTest.php create mode 100644 vendor/robthree/twofactorauth/tests/Providers/Rng/MCryptRNGProviderTest.php create mode 100644 vendor/robthree/twofactorauth/tests/Providers/Rng/NeedsRngLengths.php create mode 100644 vendor/robthree/twofactorauth/tests/Providers/Rng/OpenSSLRNGProviderTest.php create mode 100644 vendor/robthree/twofactorauth/tests/Providers/Rng/TestRNGProvider.php create mode 100644 vendor/robthree/twofactorauth/tests/Providers/Time/ITimeProviderTest.php create mode 100644 vendor/robthree/twofactorauth/tests/Providers/Time/TestTimeProvider.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e478e5..3be1d67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # v3.4.4 ## mm/dd/2021 +1. [](#new) + * Updated 2FA library 1. [](#bugfix) * Fixed missing email conflict check when calling `Login::register()` diff --git a/composer.lock b/composer.lock index 04c04e3..df521be 100644 --- a/composer.lock +++ b/composer.lock @@ -160,24 +160,29 @@ }, { "name": "robthree/twofactorauth", - "version": "1.7.0", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/RobThree/TwoFactorAuth.git", - "reference": "37983bf675c5baca09d19d6705170489d0df0002" + "reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/37983bf675c5baca09d19d6705170489d0df0002", - "reference": "37983bf675c5baca09d19d6705170489d0df0002", + "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/30a38627ae1e7c9399dae67e265063cd6ec5276c", + "reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c", "shasum": "" }, "require": { "php": ">=5.6.0" }, "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", "phpunit/phpunit": "@stable" }, + "suggest": { + "bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider", + "endroid/qr-code": "Needed for EndroidQrCodeProvider" + }, "type": "library", "autoload": { "psr-4": { @@ -211,7 +216,17 @@ "issues": "https://github.com/RobThree/TwoFactorAuth/issues", "source": "https://github.com/RobThree/TwoFactorAuth" }, - "time": "2020-01-02T19:56:46+00:00" + "funding": [ + { + "url": "https://paypal.me/robiii", + "type": "custom" + }, + { + "url": "https://github.com/RobThree", + "type": "github" + } + ], + "time": "2021-03-09T18:24:05+00:00" } ], "packages-dev": [], diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php index 80fb1ce..44b1d36 100644 --- a/vendor/composer/InstalledVersions.php +++ b/vendor/composer/InstalledVersions.php @@ -29,7 +29,7 @@ class InstalledVersions 'aliases' => array ( ), - 'reference' => '5670bd44d33b738ccf1baaf1615b42f7dbab78cb', + 'reference' => 'b7996fda7a3b56432ef9e249584616d86d977517', 'name' => 'getgrav/grav-plugin-login', ), 'versions' => @@ -59,7 +59,7 @@ class InstalledVersions 'aliases' => array ( ), - 'reference' => '5670bd44d33b738ccf1baaf1615b42f7dbab78cb', + 'reference' => 'b7996fda7a3b56432ef9e249584616d86d977517', ), 'paragonie/random_compat' => array ( @@ -72,12 +72,12 @@ class InstalledVersions ), 'robthree/twofactorauth' => array ( - 'pretty_version' => '1.7.0', - 'version' => '1.7.0.0', + 'pretty_version' => '1.8.0', + 'version' => '1.8.0.0', 'aliases' => array ( ), - 'reference' => '37983bf675c5baca09d19d6705170489d0df0002', + 'reference' => '30a38627ae1e7c9399dae67e265063cd6ec5276c', ), ), ); diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 2d9caef..753dc33 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -150,26 +150,31 @@ }, { "name": "robthree/twofactorauth", - "version": "1.7.0", - "version_normalized": "1.7.0.0", + "version": "1.8.0", + "version_normalized": "1.8.0.0", "source": { "type": "git", "url": "https://github.com/RobThree/TwoFactorAuth.git", - "reference": "37983bf675c5baca09d19d6705170489d0df0002" + "reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/37983bf675c5baca09d19d6705170489d0df0002", - "reference": "37983bf675c5baca09d19d6705170489d0df0002", + "url": "https://api.github.com/repos/RobThree/TwoFactorAuth/zipball/30a38627ae1e7c9399dae67e265063cd6ec5276c", + "reference": "30a38627ae1e7c9399dae67e265063cd6ec5276c", "shasum": "" }, "require": { "php": ">=5.6.0" }, "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", "phpunit/phpunit": "@stable" }, - "time": "2020-01-02T19:56:46+00:00", + "suggest": { + "bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider", + "endroid/qr-code": "Needed for EndroidQrCodeProvider" + }, + "time": "2021-03-09T18:24:05+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -200,9 +205,23 @@ "php", "tfa" ], + "support": { + "issues": "https://github.com/RobThree/TwoFactorAuth/issues", + "source": "https://github.com/RobThree/TwoFactorAuth" + }, + "funding": [ + { + "url": "https://paypal.me/robiii", + "type": "custom" + }, + { + "url": "https://github.com/RobThree", + "type": "github" + } + ], "install-path": "../robthree/twofactorauth" } ], - "dev": true, + "dev": false, "dev-package-names": [] } diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index ebcf95a..d91f6f6 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -6,7 +6,7 @@ 'aliases' => array ( ), - 'reference' => '5670bd44d33b738ccf1baaf1615b42f7dbab78cb', + 'reference' => 'b7996fda7a3b56432ef9e249584616d86d977517', 'name' => 'getgrav/grav-plugin-login', ), 'versions' => @@ -36,7 +36,7 @@ 'aliases' => array ( ), - 'reference' => '5670bd44d33b738ccf1baaf1615b42f7dbab78cb', + 'reference' => 'b7996fda7a3b56432ef9e249584616d86d977517', ), 'paragonie/random_compat' => array ( @@ -49,12 +49,12 @@ ), 'robthree/twofactorauth' => array ( - 'pretty_version' => '1.7.0', - 'version' => '1.7.0.0', + 'pretty_version' => '1.8.0', + 'version' => '1.8.0.0', 'aliases' => array ( ), - 'reference' => '37983bf675c5baca09d19d6705170489d0df0002', + 'reference' => '30a38627ae1e7c9399dae67e265063cd6ec5276c', ), ), ); diff --git a/vendor/robthree/twofactorauth/.github/FUNDING.yml b/vendor/robthree/twofactorauth/.github/FUNDING.yml new file mode 100644 index 0000000..b2d7224 --- /dev/null +++ b/vendor/robthree/twofactorauth/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms + +github: [RobThree] +custom: ["https://paypal.me/robiii"] diff --git a/vendor/robthree/twofactorauth/.github/workflows/test.yml b/vendor/robthree/twofactorauth/.github/workflows/test.yml new file mode 100644 index 0000000..8b31e23 --- /dev/null +++ b/vendor/robthree/twofactorauth/.github/workflows/test.yml @@ -0,0 +1,27 @@ +name: Test + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] + + steps: + - uses: actions/checkout@v2 + + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + tools: composer + coverage: xdebug + + - uses: ramsey/composer-install@v1 + + - run: composer lint + - run: composer test diff --git a/vendor/robthree/twofactorauth/.gitignore b/vendor/robthree/twofactorauth/.gitignore index 8a25841..5c1c961 100644 --- a/vendor/robthree/twofactorauth/.gitignore +++ b/vendor/robthree/twofactorauth/.gitignore @@ -125,7 +125,7 @@ publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings +# TODO: Comment the next line if you want to checkin your web deploy settings # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj @@ -184,6 +184,9 @@ FakesAssemblies/ # Composer /vendor +composer.lock # .vs -.vs/ \ No newline at end of file +.vs/ + +.phpunit.result.cache diff --git a/vendor/robthree/twofactorauth/.travis.yml b/vendor/robthree/twofactorauth/.travis.yml deleted file mode 100644 index fdc6ff5..0000000 --- a/vendor/robthree/twofactorauth/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: php - -php: - - 5.6 - - 7.0 - - 7.1 - - 7.2 - - 7.3 - - 7.4 - -before_script: - - composer install - -script: - - vendor/bin/phpunit --coverage-text tests \ No newline at end of file diff --git a/vendor/robthree/twofactorauth/README.md b/vendor/robthree/twofactorauth/README.md index 3574ae9..b8fcc75 100644 --- a/vendor/robthree/twofactorauth/README.md +++ b/vendor/robthree/twofactorauth/README.md @@ -1,6 +1,6 @@ # ![Logo](https://raw.githubusercontent.com/RobThree/TwoFactorAuth/master/logo.png) PHP library for Two Factor Authentication -[![Build status](https://img.shields.io/travis/RobThree/TwoFactorAuth.svg?style=flat-square)](https://travis-ci.org/RobThree/TwoFactorAuth/) [![Latest Stable Version](https://img.shields.io/packagist/v/robthree/twofactorauth.svg?style=flat-square)](https://packagist.org/packages/robthree/twofactorauth) [![License](https://img.shields.io/packagist/l/robthree/twofactorauth.svg?style=flat-square)](LICENSE) [![Downloads](https://img.shields.io/packagist/dt/robthree/twofactorauth.svg?style=flat-square)](https://packagist.org/packages/robthree/twofactorauth) [![Code Climate](https://img.shields.io/codeclimate/github/RobThree/TwoFactorAuth.svg?style=flat-square)](https://codeclimate.com/github/RobThree/TwoFactorAuth) [![PayPal donate button](http://img.shields.io/badge/paypal-donate-orange.svg?style=flat-square)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6MB5M2SQLP636 "Keep me off the streets") +[![Build status](https://img.shields.io/github/workflow/status/RobThree/TwoFactorAuth/Test/master?style=flat-square)](https://github.com/RobThree/TwoFactorAuth/actions?query=branch%3Amaster) [![Latest Stable Version](https://img.shields.io/packagist/v/robthree/twofactorauth.svg?style=flat-square)](https://packagist.org/packages/robthree/twofactorauth) [![License](https://img.shields.io/packagist/l/robthree/twofactorauth.svg?style=flat-square)](LICENSE) [![Downloads](https://img.shields.io/packagist/dt/robthree/twofactorauth.svg?style=flat-square)](https://packagist.org/packages/robthree/twofactorauth) [![Code Climate](https://img.shields.io/codeclimate/github/RobThree/TwoFactorAuth.svg?style=flat-square)](https://codeclimate.com/github/RobThree/TwoFactorAuth) [![PayPal donate button](http://img.shields.io/badge/paypal-donate-orange.svg?style=flat-square)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6MB5M2SQLP636 "Keep me off the streets") PHP library for [two-factor (or multi-factor) authentication](http://en.wikipedia.org/wiki/Multi-factor_authentication) using [TOTP](http://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm) and [QR-codes](http://en.wikipedia.org/wiki/QR_code). Inspired by, based on but most importantly an *improvement* on '[PHPGangsta/GoogleAuthenticator](https://github.com/PHPGangsta/GoogleAuthenticator)'. There's a [.Net implementation](https://github.com/RobThree/TwoFactorAuth.Net) of this library as well. @@ -10,10 +10,15 @@ PHP library for [two-factor (or multi-factor) authentication](http://en.wikipedi ## Requirements -* Tested on PHP 5.6 up to 7.4 -* [cURL](http://php.net/manual/en/book.curl.php) when using the provided `ImageChartsQRCodeProvider` (default), `QRServerProvider` or `QRicketProvider` but you can also provide your own QR-code provider. +* Tested on PHP 5.6 up to 8.0 +* [cURL](http://php.net/manual/en/book.curl.php) when using the provided `QRServerProvider` (default), `ImageChartsQRCodeProvider` or `QRicketProvider` but you can also provide your own QR-code provider. * [random_bytes()](http://php.net/manual/en/function.random-bytes.php), [MCrypt](http://php.net/manual/en/book.mcrypt.php), [OpenSSL](http://php.net/manual/en/book.openssl.php) or [Hash](http://php.net/manual/en/book.hash.php) depending on which built-in RNG you use (TwoFactorAuth will try to 'autodetect' and use the best available); however: feel free to provide your own (CS)RNG. +Optionally, you may need: + +* [endroid/qr-code](https://github.com/endroid/qr-code) if using `EndroidQrCodeProvider` or `EndroidQrCodeWithLogoProvider`. +* [bacon/bacon-qr-code](https://github.com/Bacon/BaconQrCode) if using `BaconQrCodeProvider`. + ## Installation Run the following command: @@ -35,17 +40,17 @@ $tfa = new RobThree\Auth\TwoFactorAuth('My Company'); The TwoFactorAuth class constructor accepts 7 arguments (all optional): -Argument | Default value | Use +Argument | Default value | Use ------------------|---------------|-------------------------------------------------- `$issuer` | `null` | Will be displayed in the app as issuer name `$digits` | `6` | The number of digits the resulting codes will be `$period` | `30` | The number of seconds a code will be valid -`$algorithm` | `sha1` | The algorithm used +`$algorithm` | `sha1` | The algorithm used (one of `sha1`, `sha256`, `sha512`, `md5`) `$qrcodeprovider` | `null` | QR-code provider (more on this later) `$rngprovider` | `null` | Random Number Generator provider (more on this later) `$timeprovider` | `null` | Time provider (more on this later) -These arguments are all '`write once`'; the class will, for it's lifetime, use these values when generating / calculating codes. The number of digits, the period and algorithm are all set to values Google's Authticator app uses (and supports). You may specify `8` digits, a period of `45` seconds and the `sha256` algorithm but the authenticator app (be it Google's implementation, Authy or any other app) may or may not support these values. Your mileage may vary; keep it on the safe side if you don't control which app your audience uses. +These arguments are all '`write once`'; the class will, for it's lifetime, use these values when generating / calculating codes. The number of digits, the period and algorithm are all set to values Google's Authenticator app uses (and supports). You may specify `8` digits, a period of `45` seconds and the `sha256` algorithm but the authenticator app (be it Google's implementation, Authy or any other app) may or may not support these values. Your mileage may vary; keep it on the safe side if you don't control which app your audience uses. ### Step 1: Set up secret shared key @@ -64,9 +69,12 @@ The `createSecret()` method accepts two arguments: `$bits` (default: `80`) and ` Another, more user-friendly, way to get the shared secret into the app is to generate a [QR-code](http://en.wikipedia.org/wiki/QR_code) which can be scanned by the app. To generate these QR codes you can use any one of the built-in `QRProvider` classes: -1. `ImageChartsQRCodeProvider` (default) -2. `QRServerProvider` +1. `QRServerProvider` (default) +2. `ImageChartsQRCodeProvider` 3. `QRicketProvider` +4. `EndroidQrCodeProvider` (requires `endroid/qr-code` to be installed) +5. `EndroidQrCodeWithLogoProvider` (same, but supporting embedded images) +6. `BaconQrCodeProvider` (requires `bacon/bacon-qr-code` to be installed) ...or implement your own provider. To implement your own provider all you need to do is implement the `IQRCodeProvider` interface. You can use the built-in providers mentioned before to serve as an example or read the next chapter in this file. The built-in classes all use a 3rd (e.g. external) party (Image-charts, QRServer and QRicket) for the hard work of generating QR-codes (note: each of these services might at some point not be available or impose limitations to the number of codes generated per day, hour etc.). You could, however, easily use a project like [PHP QR Code](http://phpqrcode.sourceforge.net/) (or one of the [many others](https://packagist.org/search/?q=qr)) to generate your QR-codes without depending on external sources. Later on we'll [demonstrate](#qr-code-providers) how to do this. @@ -89,7 +97,9 @@ When the shared secret is added to the app, the app will be ready to start gener $result = $tfa->verifyCode($_SESSION['secret'], $_POST['verification']); ```` -`verifyCode()` will return either `true` (the code was valid) or `false` (the code was invalid; no points for you!). You may need to store `$secret` in a `$_SESSION` or other persistent storage between requests. The `verifyCode()` accepts, aside from `$secret` and `$code`, three more arguments. The first being `$discrepancy`. Since TOTP codes are based on time("slices") it is very important that the server (but also client) have a correct date/time. But because the two *may* differ a bit we usually allow a certain amount of leeway. Because generated codes are valid for a specific period (remember the `$period` argument in the `TwoFactorAuth`'s constructor?) we usually check the period directly before and the period directly after the current time when validating codes. So when the current time is `14:34:21`, which results in a 'current timeslice' of `14:34:00` to `14:34:30` we also calculate/verify the codes for `14:33:30` to `14:34:00` and for `14:34:30` to `14:35:00`. This gives us a 'window' of `14:33:30` to `14:35:00`. The `$discrepancy` argument specifies how many periods (or: timeslices) we check in either direction of the current time. The default `$discrepancy` of `1` results in (max.) 3 period checks: -1, current and +1 period. A `$discrepancy` of `4` would result in a larger window (or: bigger time difference between client and server) of -4, -3, -2, -1, current, +1, +2, +3 and +4 periods. +If you do extra validations with your `$_POST` values, just make sure the code is still submitted as string - even if that's a numeric code, casting it to integer is unreliable. Also, you may need to store `$secret` in a `$_SESSION` or other persistent storage between requests. `verifyCode()` will return either `true` (the code was valid) or `false` (the code was invalid; no points for you!). + + The `verifyCode()` accepts, aside from `$secret` and `$code`, three more arguments, with the first being `$discrepancy`. Since TOTP codes are based on time("slices") it is very important that the server (but also client) have a correct date/time. But because the two *may* differ a bit we usually allow a certain amount of leeway. Because generated codes are valid for a specific period (remember the `$period` argument in the `TwoFactorAuth`'s constructor?) we usually check the period directly before and the period directly after the current time when validating codes. So when the current time is `14:34:21`, which results in a 'current timeslice' of `14:34:00` to `14:34:30` we also calculate/verify the codes for `14:33:30` to `14:34:00` and for `14:34:30` to `14:35:00`. This gives us a 'window' of `14:33:30` to `14:35:00`. The `$discrepancy` argument specifies how many periods (or: timeslices) we check in either direction of the current time. The default `$discrepancy` of `1` results in (max.) 3 period checks: -1, current and +1 period. A `$discrepancy` of `4` would result in a larger window (or: bigger time difference between client and server) of -4, -3, -2, -1, current, +1, +2, +3 and +4 periods. The second, `$time`, allows you to check a code for a specific point in time. This argument has no real practical use but can be handy for unittesting etc. The default value, `null`, means: use the current time. @@ -105,10 +115,10 @@ All we need is 3 methods and a constructor: ````php public function __construct( - $issuer = null, + $issuer = null, $digits = 6, - $period = 30, - $algorithm = 'sha1', + $period = 30, + $algorithm = 'sha1', RobThree\Auth\Providers\Qr\IQRCodeProvider $qrcodeprovider = null, RobThree\Auth\Providers\Rng\IRNGProvider $rngprovider = null ); @@ -119,9 +129,9 @@ public function verifyCode($secret, $code, $discrepancy = 1, $time = null): bool ### QR-code providers -As mentioned before, this library comes with three 'built-in' QR-code providers. This chapter will touch the subject a bit but most of it should be self-explanatory. The `TwoFactorAuth`-class accepts a `$qrcodeprovider` argument which lets you specify a built-in or custom QR-code provider. All three built-in providers do a simple HTTP request to retrieve an image using cURL and implement the [`IQRCodeProvider`](lib/Providers/Qr/IQRCodeProvider.php) interface which is all you need to implement to write your own QR-code provider. +As mentioned before, this library comes with five 'built-in' QR-code providers. This chapter will touch the subject a bit but most of it should be self-explanatory. The `TwoFactorAuth`-class accepts a `$qrcodeprovider` argument which lets you specify a built-in or custom QR-code provider. All five built-in providers do a simple HTTP request to retrieve an image using cURL and implement the [`IQRCodeProvider`](lib/Providers/Qr/IQRCodeProvider.php) interface which is all you need to implement to write your own QR-code provider. -The default provider is the [`ImageChartsQRCodeProvider`](lib/Providers/Qr/ImageChartsQRCodeProvider.php) which uses the [image-charts.com replacement for Google Image Charts](https://image-charts.com) to render QR-codes. Then we have the [`QRServerProvider`](lib/Providers/Qr/QRServerProvider.php) which uses the [goqr.me API](http://goqr.me/api/doc/create-qr-code/) and finally we have the [`QRicketProvider`](lib/Providers/Qr/QRicketProvider.php) which uses the [QRickit API](http://qrickit.com/qrickit_apps/qrickit_api.php). All three inherit from a common (abstract) baseclass named [`BaseHTTPQRCodeProvider`](lib/Providers/Qr/BaseHTTPQRCodeProvider.php) because all three share the same functionality: retrieve an image from a 3rd party over HTTP. All three classes have constructors that allow you to tweak some settings and most, if not all, arguments should speak for themselves. If you're not sure which values are supported, click the links in this paragraph for documentation on the API's that are utilized by these classes. +The default provider is the [`QRServerProvider`](lib/Providers/Qr/QRServerProvider.php) which uses the [goqr.me API](http://goqr.me/api/doc/create-qr-code/) to render QR-codes. Then we have the [`ImageChartsQRCodeProvider`](lib/Providers/Qr/ImageChartsQRCodeProvider.php) which uses the [image-charts.com replacement for Google Image Charts](https://image-charts.com) to render QR-codes and the [`QRicketProvider`](lib/Providers/Qr/QRicketProvider.php) which uses the [QRickit API](http://qrickit.com/qrickit_apps/qrickit_api.php). These three providers all inherit from a common (abstract) baseclass named [`BaseHTTPQRCodeProvider`](lib/Providers/Qr/BaseHTTPQRCodeProvider.php) because all three share the same functionality: retrieve an image from a 3rd party over HTTP. Finally, we have [`EndroidQrCodeProvider`](lib/Providers/Qr/EndroidQrCodeProvider.php), [`EndroidQrCodeWithLogoProvider`](lib/Providers/Qr/EndroidQrCodeWithLogoProvider.php) and [`BaconQrCodeProvider`](lib/Providers/Qr/BaconQrCodeProvider.php) which require an optional dependency to be installed to use (see Requirements section above), but will generate the QR codes locally. All five classes have constructors that allow you to tweak some settings and most, if not all, arguments should speak for themselves. If you're not sure which values are supported, click the links in this paragraph for documentation on the API's that are utilized by these classes. If you don't like any of the built-in classes because you don't want to rely on external resources for example or because you're paranoid about sending the TOTP secret to these 3rd parties (which is useless to them since they miss *at least one* other factor in the [MFA process](http://en.wikipedia.org/wiki/Multi-factor_authentication)), feel tree to implement your own. The `IQRCodeProvider` interface couldn't be any simpler. All you need to do is implement 2 methods: @@ -148,7 +158,7 @@ class MyProvider implements IQRCodeProvider { public function getMimeType() { return 'image/png'; // This provider only returns PNG's } - + public function getQRCodeImage($qrtext, $size) { ob_start(); // 'Catch' QRCode's output QRCode::png($qrtext, null, QR_ECLEVEL_L, 3, 4); // We ignore $size and set it to 3 @@ -190,7 +200,7 @@ As to *why* these Time Providers are implemented: it allows the TwoFactorAuth li ## Integrations -- [CakePHP 3](https://github.com/andrej-griniuk/cakephp-two-factor-auth) +- [CakePHP 3](https://github.com/andrej-griniuk/cakephp-two-factor-auth) ## License diff --git a/vendor/robthree/twofactorauth/composer.json b/vendor/robthree/twofactorauth/composer.json index 50f8b86..847b2f8 100644 --- a/vendor/robthree/twofactorauth/composer.json +++ b/vendor/robthree/twofactorauth/composer.json @@ -1,7 +1,7 @@ { "name": "robthree/twofactorauth", "description": "Two Factor Authentication", - "version": "1.7.0", + "version": "1.8.0", "type": "library", "keywords": [ "Authentication", "Two Factor Authentication", "Multi Factor Authentication", "TFA", "MFA", "PHP", "Authenticator", "Authy" ], "homepage": "https://github.com/RobThree/TwoFactorAuth", @@ -21,7 +21,12 @@ "php": ">=5.6.0" }, "require-dev": { - "phpunit/phpunit": "@stable" + "phpunit/phpunit": "@stable", + "php-parallel-lint/php-parallel-lint": "^1.2" + }, + "suggest": { + "bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider", + "endroid/qr-code": "Needed for EndroidQrCodeProvider" }, "autoload": { "psr-4": { @@ -30,7 +35,15 @@ }, "autoload-dev": { "psr-4": { - "RobThree\\Auth\\Test\\": "tests" + "Tests\\": "tests/" } + }, + "scripts": { + "lint": [ + "parallel-lint --exclude vendor ." + ], + "test": [ + "XDEBUG_MODE=coverage phpunit" + ] } } diff --git a/vendor/robthree/twofactorauth/composer.lock b/vendor/robthree/twofactorauth/composer.lock deleted file mode 100644 index 63df937..0000000 --- a/vendor/robthree/twofactorauth/composer.lock +++ /dev/null @@ -1,980 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "content-hash": "9647de85f54ba6db237f5ff42ff85a1f", - "packages": [], - "packages-dev": [ - { - "name": "doctrine/instantiator", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", - "shasum": "" - }, - "require": { - "php": ">=5.3,<8.0-DEV" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2015-06-14T21:17:01+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "dflydev/markdown": "~1.0", - "erusev/parsedown": "~1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "phpDocumentor": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" - } - ], - "time": "2015-02-03T12:10:50+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.6.2", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0|^2.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.0", - "phpunit/phpunit": "^4.8 || ^5.6.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2016-11-21T14:58:47+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "2.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" - }, - "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2015-10-06T15:47:00+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2016-10-03T07:40:28+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21T13:50:34+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4|~5" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2016-05-12T18:03:57+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "1.4.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2016-11-15T14:06:22+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "4.8.35", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/791b1a67c25af50e230f841ee7a9c6eba507dc87", - "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.2.2", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" - }, - "suggest": { - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.8.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2017-02-06T05:18:07+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2015-10-02T06:51:40+00:00" - }, - { - "name": "sebastian/comparator", - "version": "1.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2017-01-29T09:50:25+00:00" - }, - { - "name": "sebastian/diff", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2015-12-08T07:14:41+00:00" - }, - { - "name": "sebastian/environment", - "version": "1.3.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2016-08-18T05:49:44+00:00" - }, - { - "name": "sebastian/exporter", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2016-06-17T09:04:28+00:00" - }, - { - "name": "sebastian/global-state", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2015-10-12T03:26:01+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11T19:50:13+00:00" - }, - { - "name": "sebastian/version", - "version": "1.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "shasum": "" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21T13:59:46+00:00" - }, - { - "name": "symfony/yaml", - "version": "v2.8.17", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "322a8c2dfbca15ad6b1b27e182899f98ec0e0153" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/322a8c2dfbca15ad6b1b27e182899f98ec0e0153", - "reference": "322a8c2dfbca15ad6b1b27e182899f98ec0e0153", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2017-01-21T16:40:50+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "phpunit/phpunit": 0 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": ">=5.3.0" - }, - "platform-dev": [] -} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Qr/BaconQrCodeProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Qr/BaconQrCodeProvider.php new file mode 100644 index 0000000..4d5cf01 --- /dev/null +++ b/vendor/robthree/twofactorauth/lib/Providers/Qr/BaconQrCodeProvider.php @@ -0,0 +1,152 @@ +borderWidth = $borderWidth; + $this->backgroundColour = $this->handleColour($backgroundColour); + $this->foregroundColour = $this->handleColour($foregroundColour); + $this->format = strtolower($format); + } + + /** + * Standard functions from IQRCodeProvider + */ + + public function getMimeType() + { + switch ($this->format) { + case 'png': + return 'image/png'; + case 'gif': + return 'image/gif'; + case 'jpg': + case 'jpeg': + return 'image/jpeg'; + case 'svg': + return 'image/svg+xml'; + case 'eps': + return 'application/postscript'; + } + + throw new \RuntimeException(sprintf('Unknown MIME-type: %s', $this->format)); + } + + public function getQRCodeImage($qrText, $size) + { + switch ($this->format) { + case 'svg': + $backend = new SvgImageBackEnd; + break; + case 'eps': + $backend = new EpsImageBackEnd; + break; + default: + $backend = new ImagickImageBackEnd($this->format); + } + + $output = $this->getQRCodeByBackend($qrText, $size, $backend); + + if ($this->format == 'svg') { + $svg = explode("\n", $output); + return $svg[1]; + } + + return $output; + } + + /** + * Abstract QR code generation function + * providing colour changing support + */ + private function getQRCodeByBackend($qrText, $size, ImageBackEndInterface $backend) + { + $rendererStyleArgs = array($size, $this->borderWidth); + + if (is_array($this->foregroundColour) && is_array($this->backgroundColour)) { + $rendererStyleArgs = array_merge($rendererStyleArgs, array( + null, + null, + Fill::withForegroundColor( + new Rgb(...$this->backgroundColour), + new Rgb(...$this->foregroundColour), + new EyeFill(null, null), + new EyeFill(null, null), + new EyeFill(null, null) + ) + )); + } + + $writer = new Writer(new ImageRenderer( + new RendererStyle(...$rendererStyleArgs), + $backend + )); + + return $writer->writeString($qrText); + } + + /** + * Ensure colour is an array of three values but also + * accept a string and assume its a 3 or 6 character hex + */ + private function handleColour($colour) + { + if (is_string($colour) && $colour[0] == '#') { + $hexToRGB = function ($input) { + // split the array into three chunks + $split = str_split(trim($input, '#'), strlen($input) / 3); + + // cope with three character hex reference + // three characters plus a # = 4 + if (strlen($input) == 4) { + array_walk($split, function (&$character) { + $character = str_repeat($character, 2); + }); + } + + // convert hex to rgb + return array_map('hexdec', $split); + }; + + return $hexToRGB($colour); + } + + if (is_array($colour) && count($colour) == 3) { + return $colour; + } + + throw new \RuntimeException('Invalid colour value'); + } +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Qr/BaseHTTPQRCodeProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Qr/BaseHTTPQRCodeProvider.php index 5cb3add..bcc8d56 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Qr/BaseHTTPQRCodeProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Qr/BaseHTTPQRCodeProvider.php @@ -4,12 +4,18 @@ abstract class BaseHTTPQRCodeProvider implements IQRCodeProvider { + /** @var bool */ protected $verifyssl; + /** + * @param string $url + * + * @return string|bool + */ protected function getContent($url) { $curlhandle = curl_init(); - + curl_setopt_array($curlhandle, array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, @@ -20,8 +26,8 @@ protected function getContent($url) CURLOPT_USERAGENT => 'TwoFactorAuth' )); $data = curl_exec($curlhandle); - + curl_close($curlhandle); return $data; } -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeProvider.php new file mode 100755 index 0000000..810aa9b --- /dev/null +++ b/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeProvider.php @@ -0,0 +1,70 @@ +bgcolor = $this->handleColor($bgcolor); + $this->color = $this->handleColor($color); + $this->margin = $margin; + $this->errorcorrectionlevel = $this->handleErrorCorrectionLevel($errorcorrectionlevel); + } + + public function getMimeType() + { + return 'image/png'; + } + + public function getQRCodeImage($qrtext, $size) + { + return $this->qrCodeInstance($qrtext, $size)->writeString(); + } + + protected function qrCodeInstance($qrtext, $size) + { + $qrCode = new QrCode($qrtext); + $qrCode->setSize($size); + + $qrCode->setErrorCorrectionLevel($this->errorcorrectionlevel); + $qrCode->setMargin($this->margin); + $qrCode->setBackgroundColor($this->bgcolor); + $qrCode->setForegroundColor($this->color); + + return $qrCode; + } + + private function handleColor($color) + { + $split = str_split($color, 2); + $r = hexdec($split[0]); + $g = hexdec($split[1]); + $b = hexdec($split[2]); + + return ['r' => $r, 'g' => $g, 'b' => $b, 'a' => 0]; + } + + private function handleErrorCorrectionLevel($level) + { + switch ($level) { + case 'L': + return ErrorCorrectionLevel::LOW(); + case 'M': + return ErrorCorrectionLevel::MEDIUM(); + case 'Q': + return ErrorCorrectionLevel::QUARTILE(); + case 'H': + return ErrorCorrectionLevel::HIGH(); + default: + return ErrorCorrectionLevel::HIGH(); + } + } +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeWithLogoProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeWithLogoProvider.php new file mode 100755 index 0000000..ed8cc98 --- /dev/null +++ b/vendor/robthree/twofactorauth/lib/Providers/Qr/EndroidQrCodeWithLogoProvider.php @@ -0,0 +1,35 @@ +logoPath = $path; + $this->logoSize = (array)$size; + } + + protected function qrCodeInstance($qrtext, $size) { + $qrCode = parent::qrCodeInstance($qrtext, $size); + + if ($this->logoPath) { + $qrCode->setLogoPath($this->logoPath); + if ($this->logoSize) { + $qrCode->setLogoSize($this->logoSize[0], $this->logoSize[1]); + } + } + + return $qrCode; + } +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Qr/IQRCodeProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Qr/IQRCodeProvider.php index 83ed67b..e53a5ad 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Qr/IQRCodeProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Qr/IQRCodeProvider.php @@ -4,6 +4,21 @@ interface IQRCodeProvider { + /** + * Generate and return the QR code to embed in a web page + * + * @param string $qrtext the value to encode in the QR code + * @param int $size the desired size of the QR code + * + * @return string file contents of the QR code + */ public function getQRCodeImage($qrtext, $size); + + /** + * Returns the appropriate mime type for the QR code + * that will be generated + * + * @return string + */ public function getMimeType(); -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Qr/ImageChartsQRCodeProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Qr/ImageChartsQRCodeProvider.php index cc094c3..ea46ed4 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Qr/ImageChartsQRCodeProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Qr/ImageChartsQRCodeProvider.php @@ -3,37 +3,58 @@ namespace RobThree\Auth\Providers\Qr; // https://image-charts.com -class ImageChartsQRCodeProvider extends BaseHTTPQRCodeProvider +class ImageChartsQRCodeProvider extends BaseHTTPQRCodeProvider { + /** @var string */ public $errorcorrectionlevel; + + /** @var int */ public $margin; - function __construct($verifyssl = false, $errorcorrectionlevel = 'L', $margin = 1) + /** + * @param bool $verifyssl + * @param string $errorcorrectionlevel + * @param int $margin + */ + public function __construct($verifyssl = false, $errorcorrectionlevel = 'L', $margin = 1) { - if (!is_bool($verifyssl)) - throw new \QRException('VerifySSL must be bool'); + if (!is_bool($verifyssl)) { + throw new QRException('VerifySSL must be bool'); + } $this->verifyssl = $verifyssl; - + $this->errorcorrectionlevel = $errorcorrectionlevel; $this->margin = $margin; } - - public function getMimeType() + + /** + * {@inheritdoc} + */ + public function getMimeType() { return 'image/png'; } - - public function getQRCodeImage($qrtext, $size) + + /** + * {@inheritdoc} + */ + public function getQRCodeImage($qrtext, $size) { return $this->getContent($this->getUrl($qrtext, $size)); } - - public function getUrl($qrtext, $size) + + /** + * @param string $qrtext the value to encode in the QR code + * @param int $size the desired size of the QR code + * + * @return string file contents of the QR code + */ + public function getUrl($qrtext, $size) { return 'https://image-charts.com/chart?cht=qr' - . '&chs=' . ceil($size/2) . 'x' . ceil($size/2) + . '&chs=' . ceil($size / 2) . 'x' . ceil($size / 2) . '&chld=' . $this->errorcorrectionlevel . '|' . $this->margin . '&chl=' . rawurlencode($qrtext); } -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Qr/QRException.php b/vendor/robthree/twofactorauth/lib/Providers/Qr/QRException.php index c28e829..4e75f77 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Qr/QRException.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Qr/QRException.php @@ -1,5 +1,7 @@ verifyssl = $verifyssl; - + $this->errorcorrectionlevel = $errorcorrectionlevel; $this->margin = $margin; $this->qzone = $qzone; @@ -26,37 +47,53 @@ function __construct($verifyssl = false, $errorcorrectionlevel = 'L', $margin = $this->color = $color; $this->format = $format; } - - public function getMimeType() + + /** + * {@inheritdoc} + */ + public function getMimeType() { - switch (strtolower($this->format)) - { - case 'png': + switch (strtolower($this->format)) { + case 'png': return 'image/png'; - case 'gif': + case 'gif': return 'image/gif'; - case 'jpg': - case 'jpeg': + case 'jpg': + case 'jpeg': return 'image/jpeg'; - case 'svg': + case 'svg': return 'image/svg+xml'; - case 'eps': + case 'eps': return 'application/postscript'; } - throw new \QRException(sprintf('Unknown MIME-type: %s', $this->format)); + throw new QRException(sprintf('Unknown MIME-type: %s', $this->format)); } - - public function getQRCodeImage($qrtext, $size) + + /** + * {@inheritdoc} + */ + public function getQRCodeImage($qrtext, $size) { return $this->getContent($this->getUrl($qrtext, $size)); } - - private function decodeColor($value) + + /** + * @param string $value + * + * @return string + */ + private function decodeColor($value) { return vsprintf('%d-%d-%d', sscanf($value, "%02x%02x%02x")); } - - public function getUrl($qrtext, $size) + + /** + * @param string $qrtext the value to encode in the QR code + * @param int|string $size the desired size of the QR code + * + * @return string file contents of the QR code + */ + public function getUrl($qrtext, $size) { return 'https://api.qrserver.com/v1/create-qr-code/' . '?size=' . $size . 'x' . $size @@ -68,4 +105,4 @@ public function getUrl($qrtext, $size) . '&format=' . strtolower($this->format) . '&data=' . rawurlencode($qrtext); } -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Qr/QRicketProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Qr/QRicketProvider.php index 59e27cc..166a8a9 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Qr/QRicketProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Qr/QRicketProvider.php @@ -3,45 +3,67 @@ namespace RobThree\Auth\Providers\Qr; // http://qrickit.com/qrickit_apps/qrickit_api.php -class QRicketProvider extends BaseHTTPQRCodeProvider +class QRicketProvider extends BaseHTTPQRCodeProvider { + /** @var string */ public $errorcorrectionlevel; - public $margin; - public $qzone; + + /** @var string */ public $bgcolor; + + /** @var string */ public $color; + + /** @var string */ public $format; - function __construct($errorcorrectionlevel = 'L', $bgcolor = 'ffffff', $color = '000000', $format = 'p') + /** + * @param string $errorcorrectionlevel + * @param string $bgcolor + * @param string $color + * @param string $format + */ + public function __construct($errorcorrectionlevel = 'L', $bgcolor = 'ffffff', $color = '000000', $format = 'p') { $this->verifyssl = false; - + $this->errorcorrectionlevel = $errorcorrectionlevel; $this->bgcolor = $bgcolor; $this->color = $color; $this->format = $format; } - - public function getMimeType() + + /** + * {@inheritdoc} + */ + public function getMimeType() { - switch (strtolower($this->format)) - { - case 'p': + switch (strtolower($this->format)) { + case 'p': return 'image/png'; - case 'g': + case 'g': return 'image/gif'; - case 'j': + case 'j': return 'image/jpeg'; } - throw new \QRException(sprintf('Unknown MIME-type: %s', $this->format)); + throw new QRException(sprintf('Unknown MIME-type: %s', $this->format)); } - - public function getQRCodeImage($qrtext, $size) + + /** + * {@inheritdoc} + */ + public function getQRCodeImage($qrtext, $size) { return $this->getContent($this->getUrl($qrtext, $size)); } - - public function getUrl($qrtext, $size) + + /** + * @param string $qrtext the value to encode in the QR code + * @param int|string $size the desired size of the QR code + * + * @return string file contents of the QR code + */ + public function getUrl($qrtext, $size) { return 'http://qrickit.com/api/qr' . '?qrsize=' . $size @@ -51,4 +73,4 @@ public function getUrl($qrtext, $size) . '&t=' . strtolower($this->format) . '&d=' . rawurlencode($qrtext); } -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Rng/CSRNGProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Rng/CSRNGProvider.php index 8dba7fc..088edab 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Rng/CSRNGProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Rng/CSRNGProvider.php @@ -4,11 +4,19 @@ class CSRNGProvider implements IRNGProvider { - public function getRandomBytes($bytecount) { + /** + * {@inheritdoc} + */ + public function getRandomBytes($bytecount) + { return random_bytes($bytecount); // PHP7+ } - - public function isCryptographicallySecure() { + + /** + * {@inheritdoc} + */ + public function isCryptographicallySecure() + { return true; } -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Rng/HashRNGProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Rng/HashRNGProvider.php index eb42577..d17a5f8 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Rng/HashRNGProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Rng/HashRNGProvider.php @@ -1,28 +1,43 @@ algorithm = $algorithm; } - - public function getRandomBytes($bytecount) { + + /** + * {@inheritdoc} + */ + public function getRandomBytes($bytecount) + { $result = ''; $hash = mt_rand(); for ($i = 0; $i < $bytecount; $i++) { - $hash = hash($this->algorithm, $hash.mt_rand(), true); - $result .= $hash[mt_rand(0, strlen($hash)-1)]; + $hash = hash($this->algorithm, $hash . mt_rand(), true); + $result .= $hash[mt_rand(0, strlen($hash) - 1)]; } return $result; } - - public function isCryptographicallySecure() { + + /** + * {@inheritdoc} + */ + public function isCryptographicallySecure() + { return false; } } diff --git a/vendor/robthree/twofactorauth/lib/Providers/Rng/IRNGProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Rng/IRNGProvider.php index 6be2800..e4e71c2 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Rng/IRNGProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Rng/IRNGProvider.php @@ -4,6 +4,15 @@ interface IRNGProvider { + /** + * @param int $bytecount the number of bytes of randomness to return + * + * @return string the random bytes + */ public function getRandomBytes($bytecount); + + /** + * @return bool whether this provider is cryptographically secure + */ public function isCryptographicallySecure(); -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Rng/MCryptRNGProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Rng/MCryptRNGProvider.php index 0eeab2c..d1b6430 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Rng/MCryptRNGProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Rng/MCryptRNGProvider.php @@ -4,20 +4,34 @@ class MCryptRNGProvider implements IRNGProvider { + /** @var int */ private $source; - - function __construct($source = MCRYPT_DEV_URANDOM) { + + /** + * @param int $source + */ + public function __construct($source = MCRYPT_DEV_URANDOM) + { $this->source = $source; } - - public function getRandomBytes($bytecount) { + + /** + * {@inheritdoc} + */ + public function getRandomBytes($bytecount) + { $result = @mcrypt_create_iv($bytecount, $this->source); - if ($result === false) - throw new \RNGException('mcrypt_create_iv returned an invalid value'); + if ($result === false) { + throw new RNGException('mcrypt_create_iv returned an invalid value'); + } return $result; } - - public function isCryptographicallySecure() { + + /** + * {@inheritdoc} + */ + public function isCryptographicallySecure() + { return true; } -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Rng/OpenSSLRNGProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Rng/OpenSSLRNGProvider.php index dc66c64..eb82b3b 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Rng/OpenSSLRNGProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Rng/OpenSSLRNGProvider.php @@ -4,22 +4,37 @@ class OpenSSLRNGProvider implements IRNGProvider { + /** @var bool */ private $requirestrong; - - function __construct($requirestrong = true) { + + /** + * @param bool $requirestrong + */ + public function __construct($requirestrong = true) + { $this->requirestrong = $requirestrong; } - - public function getRandomBytes($bytecount) { + + /** + * {@inheritdoc} + */ + public function getRandomBytes($bytecount) + { $result = openssl_random_pseudo_bytes($bytecount, $crypto_strong); - if ($this->requirestrong && ($crypto_strong === false)) - throw new \RNGException('openssl_random_pseudo_bytes returned non-cryptographically strong value'); - if ($result === false) - throw new \RNGException('openssl_random_pseudo_bytes returned an invalid value'); + if ($this->requirestrong && ($crypto_strong === false)) { + throw new RNGException('openssl_random_pseudo_bytes returned non-cryptographically strong value'); + } + if ($result === false) { + throw new RNGException('openssl_random_pseudo_bytes returned an invalid value'); + } return $result; } - - public function isCryptographicallySecure() { + + /** + * {@inheritdoc} + */ + public function isCryptographicallySecure() + { return $this->requirestrong; } -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Rng/RNGException.php b/vendor/robthree/twofactorauth/lib/Providers/Rng/RNGException.php index eb5e913..f9a11ac 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Rng/RNGException.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Rng/RNGException.php @@ -1,5 +1,7 @@ url = $url; $this->expectedtimeformat = $expectedtimeformat; - $this->options = $options; - if ($this->options === null) { - $this->options = array( + if ($options === null) { + $options = array( 'http' => array( 'method' => 'HEAD', 'follow_location' => false, @@ -32,9 +43,14 @@ function __construct($url = 'https://google.com', $expectedtimeformat = 'D, d M ) ); } + $this->options = $options; } - public function getTime() { + /** + * {@inheritdoc} + */ + public function getTime() + { try { $context = stream_context_create($this->options); $fd = fopen($this->url, 'rb', false, $context); @@ -42,13 +58,14 @@ public function getTime() { fclose($fd); foreach ($headers['wrapper_data'] as $h) { - if (strcasecmp(substr($h, 0, 5), 'Date:') === 0) - return \DateTime::createFromFormat($this->expectedtimeformat, trim(substr($h,5)))->getTimestamp(); + if (strcasecmp(substr($h, 0, 5), 'Date:') === 0) { + return DateTime::createFromFormat($this->expectedtimeformat, trim(substr($h, 5)))->getTimestamp(); + } } - throw new \TimeException(sprintf('Unable to retrieve time from %s (Invalid or no "Date:" header found)', $this->url)); - } - catch (Exception $ex) { - throw new \TimeException(sprintf('Unable to retrieve time from %s (%s)', $this->url, $ex->getMessage())); + throw new \Exception('Invalid or no "Date:" header found'); + } catch (\Exception $ex) { + throw new TimeException(sprintf('Unable to retrieve time from %s (%s)', $this->url, $ex->getMessage())); } + } -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Time/ITimeProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Time/ITimeProvider.php index a3b87a2..4799f17 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Time/ITimeProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Time/ITimeProvider.php @@ -4,5 +4,8 @@ interface ITimeProvider { + /** + * @return int the current timestamp according to this provider + */ public function getTime(); -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Time/LocalMachineTimeProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Time/LocalMachineTimeProvider.php index 572cedc..2fe6846 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Time/LocalMachineTimeProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Time/LocalMachineTimeProvider.php @@ -2,8 +2,10 @@ namespace RobThree\Auth\Providers\Time; -class LocalMachineTimeProvider implements ITimeProvider { - public function getTime() { +class LocalMachineTimeProvider implements ITimeProvider +{ + public function getTime() + { return time(); } -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/Providers/Time/NTPTimeProvider.php b/vendor/robthree/twofactorauth/lib/Providers/Time/NTPTimeProvider.php index d69a3a6..a701850 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Time/NTPTimeProvider.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Time/NTPTimeProvider.php @@ -7,24 +7,40 @@ */ class NTPTimeProvider implements ITimeProvider { + /** @var string */ public $host; + + /** @var int */ public $port; + + /** @var int */ public $timeout; - function __construct($host = 'time.google.com', $port = 123, $timeout = 1) + /** + * @param string $host + * @param int $port + * @param int $timeout + */ + public function __construct($host = 'time.google.com', $port = 123, $timeout = 1) { $this->host = $host; - if (!is_int($port) || $port <= 0 || $port > 65535) - throw new \TimeException('Port must be 0 < port < 65535'); + if (!is_int($port) || $port <= 0 || $port > 65535) { + throw new TimeException('Port must be 0 < port < 65535'); + } $this->port = $port; - if (!is_int($timeout) || $timeout < 0) - throw new \TimeException('Timeout must be >= 0'); + if (!is_int($timeout) || $timeout < 0) { + throw new TimeException('Timeout must be >= 0'); + } $this->timeout = $timeout; } - public function getTime() { + /** + * {@inheritdoc} + */ + public function getTime() + { try { /* Create a socket and connect to NTP server */ $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); @@ -36,19 +52,19 @@ public function getTime() { socket_send($sock, $msg, strlen($msg), 0); /* Receive response and close socket */ - if (socket_recv($sock, $recv, 48, MSG_WAITALL) === false) + if (socket_recv($sock, $recv, 48, MSG_WAITALL) === false) { throw new \Exception(socket_strerror(socket_last_error($sock))); + } socket_close($sock); /* Interpret response */ $data = unpack('N12', $recv); - $timestamp = sprintf('%u', $data[9]); + $timestamp = (int) sprintf('%u', $data[9]); /* NTP is number of seconds since 0000 UT on 1 January 1900 Unix time is seconds since 0000 UT on 1 January 1970 */ return $timestamp - 2208988800; - } - catch (Exception $ex) { - throw new \TimeException(sprintf('Unable to retrieve time from %s (%s)', $this->host, $ex->getMessage())); + } catch (\Exception $ex) { + throw new TimeException(sprintf('Unable to retrieve time from %s (%s)', $this->host, $ex->getMessage())); } } } diff --git a/vendor/robthree/twofactorauth/lib/Providers/Time/TimeException.php b/vendor/robthree/twofactorauth/lib/Providers/Time/TimeException.php index 8de544d..c5a06e2 100644 --- a/vendor/robthree/twofactorauth/lib/Providers/Time/TimeException.php +++ b/vendor/robthree/twofactorauth/lib/Providers/Time/TimeException.php @@ -1,5 +1,7 @@ issuer = $issuer; - if (!is_int($digits) || $digits <= 0) + if (!is_int($digits) || $digits <= 0) { throw new TwoFactorAuthException('Digits must be int > 0'); + } $this->digits = $digits; - if (!is_int($period) || $period <= 0) + if (!is_int($period) || $period <= 0) { throw new TwoFactorAuthException('Period must be int > 0'); + } $this->period = $period; $algorithm = strtolower(trim($algorithm)); - if (!in_array($algorithm, self::$_supportedalgos)) + if (!in_array($algorithm, self::$_supportedalgos)) { throw new TwoFactorAuthException('Unsupported algorithm: ' . $algorithm); + } $this->algorithm = $algorithm; $this->qrcodeprovider = $qrcodeprovider; $this->rngprovider = $rngprovider; @@ -46,22 +88,34 @@ function __construct($issuer = null, $digits = 6, $period = 30, $algorithm = 'sh /** * Create a new secret + * + * @param int $bits + * @param bool $requirecryptosecure + * + * @return string */ public function createSecret($bits = 80, $requirecryptosecure = true) { $secret = ''; - $bytes = ceil($bits / 5); //We use 5 bits of each byte (since we have a 32-character 'alphabet' / BASE32) - $rngprovider = $this->getRngprovider(); - if ($requirecryptosecure && !$rngprovider->isCryptographicallySecure()) + $bytes = (int) ceil($bits / 5); //We use 5 bits of each byte (since we have a 32-character 'alphabet' / BASE32) + $rngprovider = $this->getRngProvider(); + if ($requirecryptosecure && !$rngprovider->isCryptographicallySecure()) { throw new TwoFactorAuthException('RNG provider is not cryptographically secure'); + } $rnd = $rngprovider->getRandomBytes($bytes); - for ($i = 0; $i < $bytes; $i++) + for ($i = 0; $i < $bytes; $i++) { $secret .= self::$_base32[ord($rnd[$i]) & 31]; //Mask out left 3 bits for 0-31 values + } return $secret; } /** * Calculate the code with given secret and point in time + * + * @param string $secret + * @param ?int $time + * + * @return string */ public function getCode($secret, $time = null) { @@ -73,15 +127,23 @@ public function getCode($secret, $time = null) $value = unpack('N', $hashpart); // Unpack binary value $value = $value[1] & 0x7FFFFFFF; // Drop MSB, keep only 31 bits - return str_pad($value % pow(10, $this->digits), $this->digits, '0', STR_PAD_LEFT); + return str_pad((string) ($value % pow(10, $this->digits)), $this->digits, '0', STR_PAD_LEFT); } /** * Check if the code is correct. This will accept codes starting from ($discrepancy * $period) sec ago to ($discrepancy * period) sec from now + * + * @param string $secret + * @param string $code + * @param int $discrepancy + * @param ?int $time + * @param int $timeslice + * + * @return bool */ public function verifyCode($secret, $code, $discrepancy = 1, $time = null, &$timeslice = 0) { - $timetamp = $this->getTime($time); + $timestamp = $this->getTime($time); $timeslice = 0; @@ -90,7 +152,7 @@ public function verifyCode($secret, $code, $discrepancy = 1, $time = null, &$tim // of the match. Each iteration we either set the timeslice variable to the timeslice of the match // or set the value to itself. This is an effort to maintain constant execution time for the code. for ($i = -$discrepancy; $i <= $discrepancy; $i++) { - $ts = $timetamp + ($i * $this->period); + $ts = $timestamp + ($i * $this->period); $slice = $this->getTimeSlice($ts); $timeslice = $this->codeEquals($this->getCode($secret, $ts), $code) ? $slice : $timeslice; } @@ -100,17 +162,24 @@ public function verifyCode($secret, $code, $discrepancy = 1, $time = null, &$tim /** * Timing-attack safe comparison of 2 codes (see http://blog.ircmaxell.com/2014/11/its-all-about-time.html) + * + * @param string $safe + * @param string $user + * + * @return bool */ - private function codeEquals($safe, $user) { + private function codeEquals($safe, $user) + { if (function_exists('hash_equals')) { return hash_equals($safe, $user); } // In general, it's not possible to prevent length leaks. So it's OK to leak the length. The important part is that // we don't leak information about the difference of the two strings. - if (strlen($safe)===strlen($user)) { + if (strlen($safe) === strlen($user)) { $result = 0; - for ($i = 0; $i < strlen($safe); $i++) + for ($i = 0; $i < strlen($safe); $i++) { $result |= (ord($safe[$i]) ^ ord($user[$i])); + } return $result === 0; } return false; @@ -118,11 +187,18 @@ private function codeEquals($safe, $user) { /** * Get data-uri of QRCode + * + * @param string $label + * @param string $secret + * @param mixed $size + * + * @return string */ public function getQRCodeImageAsDataUri($label, $secret, $size = 200) { - if (!is_int($size) || $size <= 0) + if (!is_int($size) || $size <= 0) { throw new TwoFactorAuthException('Size must be int > 0'); + } $qrcodeprovider = $this->getQrCodeProvider(); return 'data:' @@ -133,37 +209,52 @@ public function getQRCodeImageAsDataUri($label, $secret, $size = 200) /** * Compare default timeprovider with specified timeproviders and ensure the time is within the specified number of seconds (leniency) + * @param ?array $timeproviders + * @param int $leniency + * + * @return void */ public function ensureCorrectTime(array $timeproviders = null, $leniency = 5) { - if ($timeproviders != null && !is_array($timeproviders)) - throw new TwoFactorAuthException('No timeproviders specified'); - - if ($timeproviders == null) + if ($timeproviders === null) { $timeproviders = array( - new Providers\Time\NTPTimeProvider(), - new Providers\Time\HttpTimeProvider() + new NTPTimeProvider(), + new HttpTimeProvider() ); + } // Get default time provider $timeprovider = $this->getTimeProvider(); // Iterate specified time providers foreach ($timeproviders as $t) { - if (!($t instanceof ITimeProvider)) + if (!($t instanceof ITimeProvider)) { throw new TwoFactorAuthException('Object does not implement ITimeProvider'); + } // Get time from default time provider and compare to specific time provider and throw if time difference is more than specified number of seconds leniency - if (abs($timeprovider->getTime() - $t->getTime()) > $leniency) + if (abs($timeprovider->getTime() - $t->getTime()) > $leniency) { throw new TwoFactorAuthException(sprintf('Time for timeprovider is off by more than %d seconds when compared to %s', $leniency, get_class($t))); + } } } - private function getTime($time) + /** + * @param ?int $time + * + * @return int + */ + private function getTime($time = null) { return ($time === null) ? $this->getTimeProvider()->getTime() : $time; } + /** + * @param int $time + * @param int $offset + * + * @return int + */ private function getTimeSlice($time = null, $offset = 0) { return (int)floor($time / $this->period) + ($offset * $this->period); @@ -171,6 +262,11 @@ private function getTimeSlice($time = null, $offset = 0) /** * Builds a string to be encoded in a QR code + * + * @param string $label + * @param string $secret + * + * @return string */ public function getQRText($label, $secret) { @@ -182,25 +278,33 @@ public function getQRText($label, $secret) . '&digits=' . intval($this->digits); } + /** + * @param string $value + * @return string + */ private function base32Decode($value) { - if (strlen($value)==0) return ''; + if (strlen($value) == 0) { + return ''; + } - if (preg_match('/[^'.preg_quote(self::$_base32dict).']/', $value) !== 0) + if (preg_match('/[^' . preg_quote(self::$_base32dict) . ']/', $value) !== 0) { throw new TwoFactorAuthException('Invalid base32 string'); + } $buffer = ''; - foreach (str_split($value) as $char) - { - if ($char !== '=') - $buffer .= str_pad(decbin(self::$_base32lookup[$char]), 5, 0, STR_PAD_LEFT); + foreach (str_split($value) as $char) { + if ($char !== '=') { + $buffer .= str_pad(decbin(self::$_base32lookup[$char]), 5, '0', STR_PAD_LEFT); + } } $length = strlen($buffer); $blocks = trim(chunk_split(substr($buffer, 0, $length - ($length % 8)), 8, ' ')); $output = ''; - foreach (explode(' ', $blocks) as $block) - $output .= chr(bindec(str_pad($block, 8, 0, STR_PAD_RIGHT))); + foreach (explode(' ', $blocks) as $block) { + $output .= chr(bindec(str_pad($block, 8, '0', STR_PAD_RIGHT))); + } return $output; } @@ -212,7 +316,7 @@ public function getQrCodeProvider() { // Set default QR Code provider if none was specified if (null === $this->qrcodeprovider) { - return $this->qrcodeprovider = new Providers\Qr\QRServerProvider(); + return $this->qrcodeprovider = new QRServerProvider(); } return $this->qrcodeprovider; } @@ -221,22 +325,22 @@ public function getQrCodeProvider() * @return IRNGProvider * @throws TwoFactorAuthException */ - public function getRngprovider() + public function getRngProvider() { if (null !== $this->rngprovider) { return $this->rngprovider; } if (function_exists('random_bytes')) { - return $this->rngprovider = new Providers\Rng\CSRNGProvider(); + return $this->rngprovider = new CSRNGProvider(); } if (function_exists('mcrypt_create_iv')) { - return $this->rngprovider = new Providers\Rng\MCryptRNGProvider(); + return $this->rngprovider = new MCryptRNGProvider(); } if (function_exists('openssl_random_pseudo_bytes')) { - return $this->rngprovider = new Providers\Rng\OpenSSLRNGProvider(); + return $this->rngprovider = new OpenSSLRNGProvider(); } if (function_exists('hash')) { - return $this->rngprovider = new Providers\Rng\HashRNGProvider(); + return $this->rngprovider = new HashRNGProvider(); } throw new TwoFactorAuthException('Unable to find a suited RNGProvider'); } @@ -249,8 +353,8 @@ public function getTimeProvider() { // Set default time provider if none was specified if (null === $this->timeprovider) { - return $this->timeprovider = new Providers\Time\LocalMachineTimeProvider(); + return $this->timeprovider = new LocalMachineTimeProvider(); } return $this->timeprovider; } -} \ No newline at end of file +} diff --git a/vendor/robthree/twofactorauth/lib/TwoFactorAuthException.php b/vendor/robthree/twofactorauth/lib/TwoFactorAuthException.php index af51b74..bce8370 100644 --- a/vendor/robthree/twofactorauth/lib/TwoFactorAuthException.php +++ b/vendor/robthree/twofactorauth/lib/TwoFactorAuthException.php @@ -4,4 +4,4 @@ use Exception; -class TwoFactorAuthException extends \Exception {} \ No newline at end of file +class TwoFactorAuthException extends Exception {} diff --git a/vendor/robthree/twofactorauth/phpunit.xml b/vendor/robthree/twofactorauth/phpunit.xml index 92c3a27..b2ff004 100644 --- a/vendor/robthree/twofactorauth/phpunit.xml +++ b/vendor/robthree/twofactorauth/phpunit.xml @@ -1,4 +1,4 @@ - + ./tests - - + + ./lib - - - \ No newline at end of file + + + + + + + diff --git a/vendor/robthree/twofactorauth/phpunit.xml.tmppica b/vendor/robthree/twofactorauth/phpunit.xml.tmppica deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/robthree/twofactorauth/tests/MightNotMakeAssertions.php b/vendor/robthree/twofactorauth/tests/MightNotMakeAssertions.php new file mode 100644 index 0000000..a7fbded --- /dev/null +++ b/vendor/robthree/twofactorauth/tests/MightNotMakeAssertions.php @@ -0,0 +1,26 @@ +assertTrue(true); + } +} diff --git a/vendor/robthree/twofactorauth/tests/Providers/Qr/IQRCodeProviderTest.php b/vendor/robthree/twofactorauth/tests/Providers/Qr/IQRCodeProviderTest.php new file mode 100644 index 0000000..86dd431 --- /dev/null +++ b/vendor/robthree/twofactorauth/tests/Providers/Qr/IQRCodeProviderTest.php @@ -0,0 +1,56 @@ +[\w\.\-\/]+);(?P\w+),(?P.*)/', $datauri, $m) === 1) { + return array( + 'mimetype' => $m['mimetype'], + 'encoding' => $m['encoding'], + 'data' => base64_decode($m['data']) + ); + } + + return null; + } + + /** + * @return void + */ + public function testTotpUriIsCorrect() + { + $qr = new TestQrProvider(); + + $tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr); + $data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE')); + $this->assertEquals('test/test', $data['mimetype']); + $this->assertEquals('base64', $data['encoding']); + $this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=Test%26Issuer&period=30&algorithm=SHA1&digits=6@200', $data['data']); + } + + /** + * @return void + */ + public function testGetQRCodeImageAsDataUriThrowsOnInvalidSize() + { + $qr = new TestQrProvider(); + + $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', $qr); + + $this->expectException(TwoFactorAuthException::class); + + $tfa->getQRCodeImageAsDataUri('Test', 'VMR466AB62ZBOKHE', 0); + } +} diff --git a/vendor/robthree/twofactorauth/tests/Providers/Qr/TestQrProvider.php b/vendor/robthree/twofactorauth/tests/Providers/Qr/TestQrProvider.php new file mode 100644 index 0000000..93242c2 --- /dev/null +++ b/vendor/robthree/twofactorauth/tests/Providers/Qr/TestQrProvider.php @@ -0,0 +1,24 @@ +rngTestLengths as $l) { + $this->assertEquals($l, strlen($rng->getRandomBytes($l))); + } + $this->assertTrue($rng->isCryptographicallySecure()); + } else { + $this->noAssertionsMade(); + } + } +} diff --git a/vendor/robthree/twofactorauth/tests/Providers/Rng/HashRNGProviderTest.php b/vendor/robthree/twofactorauth/tests/Providers/Rng/HashRNGProviderTest.php new file mode 100644 index 0000000..c99879d --- /dev/null +++ b/vendor/robthree/twofactorauth/tests/Providers/Rng/HashRNGProviderTest.php @@ -0,0 +1,24 @@ +rngTestLengths as $l) { + $this->assertEquals($l, strlen($rng->getRandomBytes($l))); + } + + $this->assertFalse($rng->isCryptographicallySecure()); + } +} diff --git a/vendor/robthree/twofactorauth/tests/Providers/Rng/IRNGProviderTest.php b/vendor/robthree/twofactorauth/tests/Providers/Rng/IRNGProviderTest.php new file mode 100644 index 0000000..8897673 --- /dev/null +++ b/vendor/robthree/twofactorauth/tests/Providers/Rng/IRNGProviderTest.php @@ -0,0 +1,61 @@ +expectException(TwoFactorAuthException::class); + $tfa->createSecret(); + } + + /** + * @return void + */ + public function testCreateSecretOverrideSecureDoesNotThrowOnInsecureRNG() + { + $rng = new TestRNGProvider(); + + $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng); + $this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret(80, false)); + } + + /** + * @return void + */ + public function testCreateSecretDoesNotThrowOnSecureRNGProvider() + { + $rng = new TestRNGProvider(true); + + $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng); + $this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret()); + } + + /** + * @return void + */ + public function testCreateSecretGeneratesDesiredAmountOfEntropy() + { + $rng = new TestRNGProvider(true); + + $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng); + $this->assertEquals('A', $tfa->createSecret(5)); + $this->assertEquals('AB', $tfa->createSecret(6)); + $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $tfa->createSecret(128)); + $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(160)); + $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(320)); + $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567A', $tfa->createSecret(321)); + } +} diff --git a/vendor/robthree/twofactorauth/tests/Providers/Rng/MCryptRNGProviderTest.php b/vendor/robthree/twofactorauth/tests/Providers/Rng/MCryptRNGProviderTest.php new file mode 100644 index 0000000..f6dd91e --- /dev/null +++ b/vendor/robthree/twofactorauth/tests/Providers/Rng/MCryptRNGProviderTest.php @@ -0,0 +1,32 @@ +rngTestLengths as $l) { + $this->assertEquals($l, strlen($rng->getRandomBytes($l))); + } + + $this->assertTrue($rng->isCryptographicallySecure()); + } else { + $this->noAssertionsMade(); + } + } +} diff --git a/vendor/robthree/twofactorauth/tests/Providers/Rng/NeedsRngLengths.php b/vendor/robthree/twofactorauth/tests/Providers/Rng/NeedsRngLengths.php new file mode 100644 index 0000000..7bbfed9 --- /dev/null +++ b/vendor/robthree/twofactorauth/tests/Providers/Rng/NeedsRngLengths.php @@ -0,0 +1,9 @@ +rngTestLengths as $l) { + $this->assertEquals($l, strlen($rng->getRandomBytes($l))); + } + + $this->assertTrue($rng->isCryptographicallySecure()); + } + + /** + * @return void + */ + public function testNonStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes() + { + $rng = new OpenSSLRNGProvider(false); + foreach ($this->rngTestLengths as $l) { + $this->assertEquals($l, strlen($rng->getRandomBytes($l))); + } + + $this->assertFalse($rng->isCryptographicallySecure()); + } +} diff --git a/vendor/robthree/twofactorauth/tests/Providers/Rng/TestRNGProvider.php b/vendor/robthree/twofactorauth/tests/Providers/Rng/TestRNGProvider.php new file mode 100644 index 0000000..7179521 --- /dev/null +++ b/vendor/robthree/twofactorauth/tests/Providers/Rng/TestRNGProvider.php @@ -0,0 +1,41 @@ +isSecure = $isSecure; + } + + /** + * {@inheritdoc} + */ + public function getRandomBytes($bytecount) + { + $result = ''; + + for ($i = 0; $i < $bytecount; $i++) { + $result .= chr($i); + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function isCryptographicallySecure() + { + return $this->isSecure; + } +} diff --git a/vendor/robthree/twofactorauth/tests/Providers/Time/ITimeProviderTest.php b/vendor/robthree/twofactorauth/tests/Providers/Time/ITimeProviderTest.php new file mode 100644 index 0000000..159e0c8 --- /dev/null +++ b/vendor/robthree/twofactorauth/tests/Providers/Time/ITimeProviderTest.php @@ -0,0 +1,53 @@ +ensureCorrectTime(array($tpr2)); // 128 - 123 = 5 => within default leniency + + $this->noAssertionsMade(); + } + + /** + * @return void + */ + public function testEnsureCorrectTimeThrowsOnIncorrectTime() + { + $tpr1 = new TestTimeProvider(123); + $tpr2 = new TestTimeProvider(124); + + $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1); + + $this->expectException(TwoFactorAuthException::class); + + $tfa->ensureCorrectTime(array($tpr2), 0); // We force a leniency of 0, 124-123 = 1 so this should throw + } + + /** + * @return void + */ + public function testEnsureDefaultTimeProviderReturnsCorrectTime() + { + $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1'); + $tfa->ensureCorrectTime(array(new TestTimeProvider(time())), 1); // Use a leniency of 1, should the time change between both time() calls + + $this->noAssertionsMade(); + } +} diff --git a/vendor/robthree/twofactorauth/tests/Providers/Time/TestTimeProvider.php b/vendor/robthree/twofactorauth/tests/Providers/Time/TestTimeProvider.php new file mode 100644 index 0000000..0fc2d12 --- /dev/null +++ b/vendor/robthree/twofactorauth/tests/Providers/Time/TestTimeProvider.php @@ -0,0 +1,27 @@ +time = $time; + } + + /** + * {@inheritdoc} + */ + public function getTime() + { + return $this->time; + } +} diff --git a/vendor/robthree/twofactorauth/tests/TwoFactorAuthTest.php b/vendor/robthree/twofactorauth/tests/TwoFactorAuthTest.php index a0f2f67..ca00df9 100644 --- a/vendor/robthree/twofactorauth/tests/TwoFactorAuthTest.php +++ b/vendor/robthree/twofactorauth/tests/TwoFactorAuthTest.php @@ -1,218 +1,151 @@ expectException(TwoFactorAuthException::class); new TwoFactorAuth('Test', 0); } /** - * @expectedException \RobThree\Auth\TwoFactorAuthException + * @return void */ - public function testConstructorThrowsOnInvalidPeriod() { + public function testConstructorThrowsOnInvalidPeriod() + { + $this->expectException(TwoFactorAuthException::class); new TwoFactorAuth('Test', 6, 0); } /** - * @expectedException \RobThree\Auth\TwoFactorAuthException + * @return void */ - public function testConstructorThrowsOnInvalidAlgorithm() { + public function testConstructorThrowsOnInvalidAlgorithm() + { + $this->expectException(TwoFactorAuthException::class); new TwoFactorAuth('Test', 6, 30, 'xxx'); } - public function testGetCodeReturnsCorrectResults() { - + /** + * @return void + */ + public function testGetCodeReturnsCorrectResults() + { $tfa = new TwoFactorAuth('Test'); $this->assertEquals('543160', $tfa->getCode('VMR466AB62ZBOKHE', 1426847216)); $this->assertEquals('538532', $tfa->getCode('VMR466AB62ZBOKHE', 0)); } /** - * @expectedException \RobThree\Auth\TwoFactorAuthException + * @return void */ - public function testCreateSecretThrowsOnInsecureRNGProvider() { - $rng = new TestRNGProvider(); - - $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng); - $tfa->createSecret(); - } - - public function testCreateSecretOverrideSecureDoesNotThrowOnInsecureRNG() { - $rng = new TestRNGProvider(); - - $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng); - $this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret(80, false)); - } - - public function testCreateSecretDoesNotThrowOnSecureRNGProvider() { - $rng = new TestRNGProvider(true); - - $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng); - $this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret()); - } - - public function testCreateSecretGeneratesDesiredAmountOfEntropy() { - $rng = new TestRNGProvider(true); - - $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng); - $this->assertEquals('A', $tfa->createSecret(5)); - $this->assertEquals('AB', $tfa->createSecret(6)); - $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $tfa->createSecret(128)); - $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(160)); - $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(320)); - $this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567A', $tfa->createSecret(321)); - } - - public function testEnsureCorrectTimeDoesNotThrowForCorrectTime() { - $tpr1 = new TestTimeProvider(123); - $tpr2 = new TestTimeProvider(128); - - $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1); - $tfa->ensureCorrectTime(array($tpr2)); // 128 - 123 = 5 => within default leniency - } - - /** - * @expectedException \RobThree\Auth\TwoFactorAuthException - */ - public function testEnsureCorrectTimeThrowsOnIncorrectTime() { - $tpr1 = new TestTimeProvider(123); - $tpr2 = new TestTimeProvider(124); - - $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, null, $tpr1); - $tfa->ensureCorrectTime(array($tpr2), 0); // We force a leniency of 0, 124-123 = 1 so this should throw - } - - - public function testEnsureDefaultTimeProviderReturnsCorrectTime() { - $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1'); - $tfa->ensureCorrectTime(array(new TestTimeProvider(time())), 1); // Use a leniency of 1, should the time change between both time() calls - } - - public function testEnsureAllTimeProvidersReturnCorrectTime() { + public function testEnsureAllTimeProvidersReturnCorrectTime() + { $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1'); $tfa->ensureCorrectTime(array( - new RobThree\Auth\Providers\Time\NTPTimeProvider(), // Uses pool.ntp.org by default - //new RobThree\Auth\Providers\Time\NTPTimeProvider('time.google.com'), // Somehow time.google.com and time.windows.com make travis timeout?? - new RobThree\Auth\Providers\Time\HttpTimeProvider(), // Uses google.com by default - new RobThree\Auth\Providers\Time\HttpTimeProvider('https://github.com'), - new RobThree\Auth\Providers\Time\HttpTimeProvider('https://yahoo.com'), + new \RobThree\Auth\Providers\Time\NTPTimeProvider(), // Uses pool.ntp.org by default + //new \RobThree\Auth\Providers\Time\NTPTimeProvider('time.google.com'), // Somehow time.google.com and time.windows.com make travis timeout?? + new \RobThree\Auth\Providers\Time\HttpTimeProvider(), // Uses google.com by default + new \RobThree\Auth\Providers\Time\HttpTimeProvider('https://github.com'), + new \RobThree\Auth\Providers\Time\HttpTimeProvider('https://yahoo.com'), )); + $this->noAssertionsMade(); } - public function testVerifyCodeWorksCorrectly() { - + /** + * @return void + */ + public function testVerifyCodeWorksCorrectly() + { $tfa = new TwoFactorAuth('Test', 6, 30); - $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847190)); - $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 29)); //Test discrepancy - $this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 30)); //Test discrepancy - $this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 - 1)); //Test discrepancy + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847190)); + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 29)); //Test discrepancy + $this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 + 30)); //Test discrepancy + $this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 0, 1426847190 - 1)); //Test discrepancy - $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 0)); //Test discrepancy - $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 35)); //Test discrepancy - $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 35)); //Test discrepancy + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 0)); //Test discrepancy + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 35)); //Test discrepancy + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 35)); //Test discrepancy - $this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 65)); //Test discrepancy - $this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 65)); //Test discrepancy + $this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 + 65)); //Test discrepancy + $this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 1, 1426847205 - 65)); //Test discrepancy - $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 + 65)); //Test discrepancy - $this->assertEquals(true , $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 - 65)); //Test discrepancy + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 + 65)); //Test discrepancy + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 2, 1426847205 - 65)); //Test discrepancy } - public function testVerifyCorrectTimeSliceIsReturned() { + /** + * @return void + */ + public function testVerifyCorrectTimeSliceIsReturned() + { $tfa = new TwoFactorAuth('Test', 6, 30); // We test with discrepancy 3 (so total of 7 codes: c-3, c-2, c-1, c, c+1, c+2, c+3 // Ensure each corresponding timeslice is returned correctly - $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '534113', 3, 1426847190, $timeslice1)); + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '534113', 3, 1426847190, $timeslice1)); $this->assertEquals(47561570, $timeslice1); - $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '819652', 3, 1426847190, $timeslice2)); + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '819652', 3, 1426847190, $timeslice2)); $this->assertEquals(47561571, $timeslice2); - $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '915954', 3, 1426847190, $timeslice3)); + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '915954', 3, 1426847190, $timeslice3)); $this->assertEquals(47561572, $timeslice3); - $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 3, 1426847190, $timeslice4)); + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '543160', 3, 1426847190, $timeslice4)); $this->assertEquals(47561573, $timeslice4); - $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '348401', 3, 1426847190, $timeslice5)); + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '348401', 3, 1426847190, $timeslice5)); $this->assertEquals(47561574, $timeslice5); - $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '648525', 3, 1426847190, $timeslice6)); + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '648525', 3, 1426847190, $timeslice6)); $this->assertEquals(47561575, $timeslice6); - $this->assertEquals(true, $tfa->verifyCode('VMR466AB62ZBOKHE', '170645', 3, 1426847190, $timeslice7)); + $this->assertTrue($tfa->verifyCode('VMR466AB62ZBOKHE', '170645', 3, 1426847190, $timeslice7)); $this->assertEquals(47561576, $timeslice7); // Incorrect code should return false and a 0 timeslice - $this->assertEquals(false, $tfa->verifyCode('VMR466AB62ZBOKHE', '111111', 3, 1426847190, $timeslice8)); + $this->assertFalse($tfa->verifyCode('VMR466AB62ZBOKHE', '111111', 3, 1426847190, $timeslice8)); $this->assertEquals(0, $timeslice8); } - public function testTotpUriIsCorrect() { - $qr = new TestQrProvider(); - - $tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr); - $data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE')); - $this->assertEquals('test/test', $data['mimetype']); - $this->assertEquals('base64', $data['encoding']); - $this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=Test%26Issuer&period=30&algorithm=SHA1&digits=6@200', $data['data']); - } - /** - * @expectedException \RobThree\Auth\TwoFactorAuthException + * @return void */ - public function testGetQRCodeImageAsDataUriThrowsOnInvalidSize() { - $qr = new TestQrProvider(); + public function testGetCodeThrowsOnInvalidBase32String1() + { + $tfa = new TwoFactorAuth('Test'); - $tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', $qr); - $tfa->getQRCodeImageAsDataUri('Test', 'VMR466AB62ZBOKHE', 0); - } + $this->expectException(TwoFactorAuthException::class); - /** - * @expectedException \RobThree\Auth\TwoFactorAuthException - */ - public function testGetCodeThrowsOnInvalidBase32String1() { - $tfa = new TwoFactorAuth('Test'); $tfa->getCode('FOO1BAR8BAZ9'); //1, 8 & 9 are invalid chars } /** - * @expectedException \RobThree\Auth\TwoFactorAuthException + * @return void */ - public function testGetCodeThrowsOnInvalidBase32String2() { + public function testGetCodeThrowsOnInvalidBase32String2() + { $tfa = new TwoFactorAuth('Test'); + + $this->expectException(TwoFactorAuthException::class); + $tfa->getCode('mzxw6==='); //Lowercase } - public function testKnownBase32DecodeTestVectors() { + /** + * @return void + */ + public function testKnownBase32DecodeTestVectors() + { // We usually don't test internals (e.g. privates) but since we rely heavily on base32 decoding and don't want // to expose this method nor do we want to give people the possibility of implementing / providing their own base32 // decoding/decoder (as we do with Rng/QR providers for example) we simply test the private base32Decode() method @@ -226,7 +159,7 @@ public function testKnownBase32DecodeTestVectors() { // Dave Thomas and Andy Hunt -- "Pragmatic Unit Testing $tfa = new TwoFactorAuth('Test'); - $method = new ReflectionMethod('RobThree\Auth\TwoFactorAuth', 'base32Decode'); + $method = new \ReflectionMethod(TwoFactorAuth::class, 'base32Decode'); $method->setAccessible(true); // Test vectors from: https://tools.ietf.org/html/rfc4648#page-12 @@ -239,14 +172,18 @@ public function testKnownBase32DecodeTestVectors() { $this->assertEquals('foobar', $method->invoke($tfa, 'MZXW6YTBOI======')); } - public function testKnownBase32DecodeUnpaddedTestVectors() { + /** + * @return void + */ + public function testKnownBase32DecodeUnpaddedTestVectors() + { // See testKnownBase32DecodeTestVectors() for the rationale behind testing the private base32Decode() method. // This test ensures that strings without the padding-char ('=') are also decoded correctly. // https://tools.ietf.org/html/rfc4648#page-4: // "In some circumstances, the use of padding ("=") in base-encoded data is not required or used." $tfa = new TwoFactorAuth('Test'); - $method = new ReflectionMethod('RobThree\Auth\TwoFactorAuth', 'base32Decode'); + $method = new \ReflectionMethod(TwoFactorAuth::class, 'base32Decode'); $method->setAccessible(true); // Test vectors from: https://tools.ietf.org/html/rfc4648#page-12 @@ -259,8 +196,11 @@ public function testKnownBase32DecodeUnpaddedTestVectors() { $this->assertEquals('foobar', $method->invoke($tfa, 'MZXW6YTBOI')); } - - public function testKnownTestVectors_sha1() { + /** + * @return void + */ + public function testKnownTestVectors_sha1() + { //Known test vectors for SHA1: https://tools.ietf.org/html/rfc6238#page-15 $secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ'; //== base32encode('12345678901234567890') $tfa = new TwoFactorAuth('Test', 8, 30, 'sha1'); @@ -272,7 +212,11 @@ public function testKnownTestVectors_sha1() { $this->assertEquals('65353130', $tfa->getCode($secret, 20000000000)); } - public function testKnownTestVectors_sha256() { + /** + * @return void + */ + public function testKnownTestVectors_sha256() + { //Known test vectors for SHA256: https://tools.ietf.org/html/rfc6238#page-15 $secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZA'; //== base32encode('12345678901234567890123456789012') $tfa = new TwoFactorAuth('Test', 8, 30, 'sha256'); @@ -284,7 +228,11 @@ public function testKnownTestVectors_sha256() { $this->assertEquals('77737706', $tfa->getCode($secret, 20000000000)); } - public function testKnownTestVectors_sha512() { + /** + * @return void + */ + public function testKnownTestVectors_sha512() + { //Known test vectors for SHA512: https://tools.ietf.org/html/rfc6238#page-15 $secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNA'; //== base32encode('1234567890123456789012345678901234567890123456789012345678901234') $tfa = new TwoFactorAuth('Test', 8, 30, 'sha512'); @@ -295,115 +243,4 @@ public function testKnownTestVectors_sha512() { $this->assertEquals('38618901', $tfa->getCode($secret, 2000000000)); $this->assertEquals('47863826', $tfa->getCode($secret, 20000000000)); } - - /** - * @requires function random_bytes - */ - public function testCSRNGProvidersReturnExpectedNumberOfBytes() { - $rng = new \RobThree\Auth\Providers\Rng\CSRNGProvider(); - foreach ($this->getRngTestLengths() as $l) - $this->assertEquals($l, strlen($rng->getRandomBytes($l))); - $this->assertEquals(true, $rng->isCryptographicallySecure()); - } - - /** - * @requires function hash_algos - * @requires function hash - */ - public function testHashRNGProvidersReturnExpectedNumberOfBytes() { - $rng = new \RobThree\Auth\Providers\Rng\HashRNGProvider(); - foreach ($this->getRngTestLengths() as $l) - $this->assertEquals($l, strlen($rng->getRandomBytes($l))); - $this->assertEquals(false, $rng->isCryptographicallySecure()); - } - - /** - * @requires function mcrypt_create_iv - */ - public function testMCryptRNGProvidersReturnExpectedNumberOfBytes() { - if (function_exists('mcrypt_create_iv')) { - $rng = new \RobThree\Auth\Providers\Rng\MCryptRNGProvider(); - foreach ($this->getRngTestLengths() as $l) - $this->assertEquals($l, strlen($rng->getRandomBytes($l))); - $this->assertEquals(true, $rng->isCryptographicallySecure()); - } - } - - /** - * @requires function openssl_random_pseudo_bytes - */ - public function testStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes() { - $rng = new \RobThree\Auth\Providers\Rng\OpenSSLRNGProvider(true); - foreach ($this->getRngTestLengths() as $l) - $this->assertEquals($l, strlen($rng->getRandomBytes($l))); - $this->assertEquals(true, $rng->isCryptographicallySecure()); - } - - /** - * @requires function openssl_random_pseudo_bytes - */ - public function testNonStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes() { - $rng = new \RobThree\Auth\Providers\Rng\OpenSSLRNGProvider(false); - foreach ($this->getRngTestLengths() as $l) - $this->assertEquals($l, strlen($rng->getRandomBytes($l))); - $this->assertEquals(false, $rng->isCryptographicallySecure()); - } - - - private function getRngTestLengths() { - return array(1, 16, 32, 256); - } - - private function DecodeDataUri($datauri) { - if (preg_match('/data:(?P[\w\.\-\/]+);(?P\w+),(?P.*)/', $datauri, $m) === 1) { - return array( - 'mimetype' => $m['mimetype'], - 'encoding' => $m['encoding'], - 'data' => base64_decode($m['data']) - ); - } - return null; - } } - -class TestRNGProvider implements IRNGProvider { - private $isSecure; - - function __construct($isSecure = false) { - $this->isSecure = $isSecure; - } - - public function getRandomBytes($bytecount) { - $result = ''; - for ($i=0; $i<$bytecount; $i++) - $result.=chr($i); - return $result; - - } - - public function isCryptographicallySecure() { - return $this->isSecure; - } -} - -class TestQrProvider implements IQRCodeProvider { - public function getQRCodeImage($qrtext, $size) { - return $qrtext . '@' . $size; - } - - public function getMimeType() { - return 'test/test'; - } -} - -class TestTimeProvider implements ITimeProvider { - private $time; - - function __construct($time) { - $this->time = $time; - } - - public function getTime() { - return $this->time; - } -} \ No newline at end of file From 31ab1cce12168001d61a5f76eb2c389e3ec5495f Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 16 Jun 2021 10:31:24 -0600 Subject: [PATCH 4/4] prepare for release --- CHANGELOG.md | 2 +- blueprints.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3be1d67..8349aac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # v3.4.4 -## mm/dd/2021 +## 06/16/2021 1. [](#new) * Updated 2FA library diff --git a/blueprints.yaml b/blueprints.yaml index 99c20d5..a10f2ef 100644 --- a/blueprints.yaml +++ b/blueprints.yaml @@ -1,7 +1,7 @@ name: Login slug: login type: plugin -version: 3.4.3 +version: 3.4.4 testing: false description: Enables user authentication and login screen. icon: sign-in