Skip to content

Commit d104cc3

Browse files
committed
Refactoring library to modernize code base. Fix #16
- Added data types everywhere + strict types - Drop support for PHP < 8.1 - Renamed "Sasl" to "SASL" - SASL factroy is now an enum
1 parent 52dbc0e commit d104cc3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1509
-1838
lines changed

.envrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export XDEBUG_MODE=coverage
2+
export EJABBERD_VERSION=24.12
3+
export DOVECOT_VERSION=2.3.18

.github/workflows/ci.yml

Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -92,45 +92,6 @@ jobs:
9292
strategy:
9393
matrix:
9494
php:
95-
- version: 5.3
96-
phpunit: 4.8
97-
compat: true
98-
coverage: false
99-
- version: 5.4
100-
phpunit: 4.8
101-
compat: true
102-
coverage: false
103-
- version: 5.5
104-
phpunit: 4.8
105-
compat: true
106-
coverage: false
107-
- version: 5.6
108-
phpunit: 5.7
109-
compat: true
110-
coverage: false
111-
- version: 7.0
112-
phpunit: 6.5
113-
compat: true
114-
coverage: false
115-
- version: 7.1
116-
phpunit: 7.5
117-
compat: true
118-
coverage: false
119-
- version: 7.2
120-
phpunit: 8.5
121-
coverage: false
122-
- version: 7.3
123-
phpunit: 9.5
124-
coverage: false
125-
- version: 7.4
126-
phpunit: 9.5
127-
coverage: false
128-
- version: 8.0
129-
phpunit: 9.5
130-
coverage: false
131-
- version: 8.1
132-
phpunit: 9.5
133-
coverage: false
13495
- version: 8.2
13596
phpunit: 10.0
13697
coverage: true
@@ -185,13 +146,23 @@ jobs:
185146
run: |
186147
./vendor/bin/phpunit \
187148
--no-configuration \
149+
--display-skipped \
150+
--display-deprecations \
151+
--display-errors \
152+
--display-notices \
153+
--display-warnings \
188154
tests/src/
189155
190156
- name: Run test suite with code coverage
191157
if: ${{ matrix.php.coverage }}
192158
run: |
193159
./vendor/bin/phpunit \
194160
--no-configuration \
161+
--display-skipped \
162+
--display-deprecations \
163+
--display-errors \
164+
--display-notices \
165+
--display-warnings \
195166
--coverage-clover build/logs/clover.xml \
196167
--coverage-filter src/ \
197168
tests/src/

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ phpunit.xml
55
.phpunit.result.cache
66
.phpunit.cache/
77
.phpcs-cache
8+
.phpunit.cache/
89
*.log
10+
*.orig
911
codeclimate.json
1012
ocular.phar
1113
ocular.phar*

.scrutinizer.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ tools:
2525

2626
build:
2727
environment:
28-
php: 8.2.0
28+
php: 8.3.0
2929
nodes:
3030
analysis:
3131
tests:

LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Modified BSD License
33

44
Copyright (c) 2002-2003 Richard Heyes,
55
2014 Jaussoin Timothée,
6-
2014-2024 Fabian Grutschus
6+
2014-2025 Fabian Grutschus
77
All rights reserved.
88

99
Redistribution and use in source and binary forms, with or without modification,

README.md

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
# fabiang/sasl
22

33
The PHP SASL Authentification Library.
4+
Full refactored version of the the original [Auth_SASL2 Pear package](http://pear.php.net/package/Auth_SASL2/).
5+
6+
Provides code to generate responses to common SASL mechanisms, including:
7+
8+
* Digest-MD5
9+
* Cram-MD5
10+
* Plain
11+
* Anonymous
12+
* Login (Pseudo mechanism)
13+
* SCRAM
414

515
[![PHP Version Require](https://poser.pugx.org/fabiang/sasl/require/php)](https://packagist.org/packages/fabiang/sasl)
616
[![Latest Stable Version](https://poser.pugx.org/fabiang/sasl/v/stable.svg)](https://packagist.org/packages/fabiang/sasl)
@@ -10,22 +20,17 @@ The PHP SASL Authentification Library.
1020
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/fabiang/sasl/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/fabiang/sasl/?branch=develop)
1121
[![Code Coverage](https://scrutinizer-ci.com/g/fabiang/sasl/badges/coverage.png?b=develop)](https://scrutinizer-ci.com/g/fabiang/sasl/?branch=develop)
1222

13-
Provides code to generate responses to common SASL mechanisms, including:
14-
* Digest-MD5
15-
* Cram-MD5
16-
* Plain
17-
* Anonymous
18-
* Login (Pseudo mechanism)
19-
* SCRAM
23+
## Security
2024

21-
Full refactored version of the the original [Auth_SASL2 Pear package](http://pear.php.net/package/Auth_SASL2/).
25+
Please note that MD5- and SHA1-based authentication mechanism are considered insecure.
26+
Therefore you should prefer at least SCRAM-SHA-256 for **non-secure connections (TLS)** when ever possible.
27+
For that reason Digest-MD5, Cram-MD5 and SCRAM-SHA-1 are deprecated and were removed in modern server software.
2228

2329
## Installation
2430

25-
The easiest way to install fabiang/sasl is by using Composer:
31+
The easiest way to install fabiang/sasl is by using [Composer](https://getcomposer.org):
2632

2733
```
28-
curl -sS https://getcomposer.org/installer | php
2934
composer require fabiang/sasl
3035
```
3136

@@ -34,24 +39,31 @@ composer require fabiang/sasl
3439
Use the factory method to create a authentication mechanism object:
3540

3641
```php
37-
use Fabiang\Sasl\Sasl;
42+
use Fabiang\SASL\SASL;
3843

39-
$factory = new Sasl;
40-
41-
$mechanism = $factory->factory('SCRAM-SHA-1', array(
44+
$mechanism = SASL::SCRAM_SHA3_256->mechanism([
4245
'authcid' => 'username',
4346
'secret' => 'password',
4447
'authzid' => 'authzid', // optional. Username to proxy as
4548
'service' => 'servicename', // optional. Name of the service
4649
'hostname' => 'hostname', // optional. Hostname of the service
47-
));
50+
]);
4851

4952
$response = $mechanism->createResponse();
5053
```
5154

55+
Or create from string:
56+
57+
```php
58+
// throws Fabiang\SASL\Exception\UnsupportedMechanismException
59+
$mechanism = SASL::fromString('SCRAM-SHA3-256')->mechanism([
60+
// ...
61+
]);
62+
```
63+
5264
Challenge-based authentication mechanisms implement the interface
53-
`Fabiang\Sasl\Authentication\ChallengeAuthenticationInterface`.
54-
For those mechanisms call the method again with the challenge:
65+
`Fabiang\SASL\Authentication\ChallengeAuthenticationInterface`.
66+
For those mechanisms call the method again with the challenge returned by the server:
5567

5668
```php
5769
$response = $mechanism->createResponse($challenge);
@@ -64,7 +76,7 @@ $response = $mechanism->createResponse($challenge);
6476
To verify the data returned by the server for SCRAM you can call:
6577

6678
```php
67-
$mechanism->verify($data);
79+
$trusted = $mechanism->verify($data);
6880
```
6981

7082
If the method returns false you should disconnect.
@@ -74,20 +86,21 @@ If the method returns false you should disconnect.
7486
To enable [downgrade protection for SCRAM](https://xmpp.org/extensions/xep-0474.html), you'll need to pass
7587
the allowed authentication mechanisms and channel-binding types via options to the factory:
7688

77-
**Note**: Channel-binding is currently not supported [due to limitations of PHP](https://github.com/php/php-src/issues/16766).
89+
**Note**: [Channel-binding](https://en.wikipedia.org/wiki/Salted_Challenge_Response_Authentication_Mechanism#Channel_binding)
90+
is currently not supported [due to limitations of PHP](https://github.com/php/php-src/issues/16766).
7891

7992
```php
80-
$mechanism = $factory->factory('SCRAM-SHA-1', array(
93+
$authentication = AuthenticationMechanism::SCRAM_SHA_1->mechanism([
8194
'authcid' => 'username',
8295
'secret' => 'password',
8396
'authzid' => 'authzid', // optional. Username to proxy as
8497
'service' => 'servicename', // optional. Name of the service
8598
'hostname' => 'hostname', // optional. Hostname of the service
86-
'downgrade_protection' => array( // optional. When `null` downgrade protection string from server won't be validated
87-
'allowed_mechanisms' => array('SCRAM-SHA-1-PLUS', 'SCRAM-SHA-1'), // allowed mechanisms by the server
88-
'allowed_channel_bindings' => array('tls-unique', 'tls-exporter', 'tls-server-end-point'), // allowed channel-binding types by the server
89-
),
90-
));
99+
'downgrade_protection' => [ // optional. When `null` downgrade protection string from server won't be validated
100+
'allowed_mechanisms' => ['SCRAM-SHA-1-PLUS', 'SCRAM-SHA-1'], // allowed mechanisms by the server
101+
'allowed_channel_bindings' => ['tls-unique', 'tls-exporter', 'tls-server-end-point'], // allowed channel-binding types by the server
102+
],
103+
]);
91104
```
92105

93106
### Required options
@@ -96,15 +109,17 @@ List of options required by authentication mechanisms.
96109
For mechanisms that are challenge-based you'll need to call `createResponse()`
97110
again and send the returned value to the server.
98111

99-
| Mechanism | Authcid | Secret | Authzid | Service | Hostname | Challenge |
100-
| ---------- | ------- | ------ | -------- | ------- | -------- | --------- |
101-
| Anonymous | yes | no | no | no | no | no |
102-
| Cram-MD5 | yes | yes | no | no | no | yes |
103-
| Digest-MD5 | yes | yes | optional | yes | yes | yes |
104-
| External | no | no | yes | no | no | no |
105-
| Login | yes | yes | no | no | no | no |
106-
| Plain | yes | yes | optional | no | no | no |
107-
| SCRAM-* | yes | yes | optional | no | no | yes |
112+
| Mechanism | Authcid | Secret | Authzid | Service | Hostname | | Challenge |
113+
| ---------- | -------- | ------ | -------- | ------- | -------- | --- | --------- |
114+
| Anonymous | optional | no | no | no | no | | no |
115+
| Cram-MD5 | yes | yes | no | no | no | | yes |
116+
| Digest-MD5 | yes | yes | optional | yes | yes | | yes |
117+
| External | no | no | optional | no | no | | no |
118+
| Login | yes | yes | no | no | no | | no |
119+
| Plain | yes | yes | optional | no | no | | no |
120+
| SCRAM-* | yes | yes | optional | no | no | | yes |
121+
122+
Authcid = e.g. username, Secret = e.g. password
108123

109124
## Unit tests
110125

behat.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ default:
33
authentication_features:
44
paths: [ "%paths.base%/tests/features/" ]
55
contexts:
6-
- Fabiang\Sasl\Behat\XMPPContext:
6+
- Fabiang\SASL\Behat\XMPPContext:
77
- localhost
88
- 15222
99
# Extra test server for https://dyn.eightysoft.de/xeps/xep-0474.html
@@ -13,7 +13,7 @@ default:
1313
- testpass
1414
- "%paths.base%/tests/log/features/"
1515
- tlsv1.2
16-
- Fabiang\Sasl\Behat\POP3Context:
16+
- Fabiang\SASL\Behat\POP3Context:
1717
- localhost
1818
- 1110
1919
- vmail

composer.json

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,28 @@
2525
],
2626
"autoload": {
2727
"psr-4": {
28-
"Fabiang\\Sasl\\": "src/"
28+
"Fabiang\\SASL\\": "src/"
2929
},
30-
"files": ["src/throwable.php"]
30+
"files": [
31+
"src/deprecated.php",
32+
"src/override.php"
33+
]
3134
},
3235
"autoload-dev": {
3336
"psr-4": {
34-
"Fabiang\\Sasl\\Behat\\": "tests/features/bootstrap",
35-
"Fabiang\\Sasl\\": "tests/src"
36-
},
37-
"files": ["tests/compat.php"]
37+
"Fabiang\\SASL\\Behat\\": "tests/features/bootstrap",
38+
"Fabiang\\SASL\\": "tests/src"
39+
}
3840
},
3941
"require": {
40-
"php": "^5.3.3 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
42+
"php": "~8.2.0 || ~8.3.0 || ~8.4.0"
4143
},
4244
"require-dev": {
43-
"behat/behat": "^3.6",
44-
"phpunit/phpunit": ">=4.8",
45+
"behat/behat": "^3.18",
46+
"phpunit/phpunit": "^10.0 || ^11.5",
4547
"slevomat/coding-standard": "*",
4648
"squizlabs/php_codesniffer": "*",
47-
"vimeo/psalm": "^5.23"
49+
"vimeo/psalm": "^6.0"
4850
},
4951
"config": {
5052
"sort-packages": true,
@@ -55,7 +57,7 @@
5557
"scripts": {
5658
"phpcs": "phpcs",
5759
"psalm": "psalm",
58-
"phpunit": "phpunit",
60+
"phpunit": "phpunit --display-phpunit-deprecations --display-skipped --display-deprecations --display-errors --display-notices --display-warnings",
5961
"behat": "behat",
6062
"test": [
6163
"@psalm",

docker-compose.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
version: '3'
21
services:
32
xmpp:
4-
image: ejabberd/ecs:${EJABBERD_VERSION:-24.02}
3+
image: ejabberd/ecs:${EJABBERD_VERSION:-24.12}
54
volumes:
65
- "./tests/config/ejabberd/ejabberd.yml:/home/ejabberd/conf/ejabberd.yml"
76
- "./tests/config/ejabberd/ejabberd.db:/home/ejabberd/database/ejabberd.db"
@@ -27,7 +26,7 @@ services:
2726
- CTL_ON_CREATE=register testuser localhost testpass
2827

2928
mail:
30-
image: dovecot/dovecot:2.3.18
29+
image: dovecot/dovecot:${DOVECOT_VERSION:-2.3.18}
3130
volumes:
3231
- "./tests/config/dovecot/dovecot.conf:/etc/dovecot/dovecot.conf"
3332
- "./tests/config/dovecot/users:/etc/dovecot/users"

0 commit comments

Comments
 (0)