diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index ef7c973a2..41e8608d1 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -51,9 +51,8 @@ jobs:
with:
# Should be the higest supported version, so we can use the newest tools
php-version: '8.3'
- tools: composer, composer-require-checker, composer-unused, phpcs, psalm
- # optional performance gain for psalm: opcache
- extensions: ctype, date, dom, fileinfo, filter, hash, intl, ldap, mbstring, opcache, openssl, pcre, posix, spl, xml
+ tools: composer, composer-require-checker, composer-unused, phpcs
+ extensions: ctype, date, dom, fileinfo, filter, hash, intl, ldap, mbstring, openssl, pcre, posix, spl, xml
- name: Setup problem matchers for PHP
run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
@@ -85,27 +84,13 @@ jobs:
- name: PHP Code Sniffer
run: phpcs
- - name: Psalm
- continue-on-error: true
- run: |
- psalm -c psalm.xml \
- --show-info=true \
- --shepherd \
- --php-version=${{ steps.setup-php.outputs.php-version }}
-
- - name: Psalm (testsuite)
+ - name: PHPStan
run: |
- psalm -c psalm-dev.xml \
- --show-info=true \
- --shepherd \
- --php-version=${{ steps.setup-php.outputs.php-version }}
+ vendor/bin/phpstan analyze -c phpstan.neon --debug
- - name: Psalter
+ - name: PHPStan (testsuite)
run: |
- psalm --alter \
- --issues=UnnecessaryVarAnnotation \
- --dry-run \
- --php-version=${{ steps.setup-php.outputs.php-version }}
+ vendor/bin/phpstan analyze -c phpstan-dev.neon --debug
security:
name: Security checks
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
new file mode 100644
index 000000000..40bb15e35
--- /dev/null
+++ b/phpstan-baseline.neon
@@ -0,0 +1,21 @@
+parameters:
+ ignoreErrors:
+ -
+ message: "#^Call to an undefined method SimpleSAML\\\\Module\\\\ldap\\\\ConnectorInterface\\:\\:escapeFilterValue\\(\\)\\.$#"
+ count: 1
+ path: src/Auth/Process/AttributeAddFromLDAP.php
+
+ -
+ message: "#^Call to an undefined method SimpleSAML\\\\Module\\\\ldap\\\\ConnectorInterface\\:\\:escapeFilterValue\\(\\)\\.$#"
+ count: 1
+ path: src/Auth/Process/AttributeAddUsersGroups.php
+
+ -
+ message: "#^Call to an undefined method Symfony\\\\Component\\\\Ldap\\\\Adapter\\\\ConnectionInterface\\:\\:getResource\\(\\)\\.$#"
+ count: 1
+ path: src/Connector/ActiveDirectory.php
+
+ -
+ message: "#^Constructor of class SimpleSAML\\\\Module\\\\ldap\\\\Connector\\\\Ldap has an unused parameter \\$extension\\.$#"
+ count: 1
+ path: src/Connector/Ldap.php
diff --git a/phpstan-dev.neon b/phpstan-dev.neon
new file mode 100644
index 000000000..4d29b8b51
--- /dev/null
+++ b/phpstan-dev.neon
@@ -0,0 +1,4 @@
+parameters:
+ level: 9
+ paths:
+ - tests
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 000000000..ab978218a
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,6 @@
+parameters:
+ level: 3
+ paths:
+ - src
+includes:
+ - phpstan-baseline.neon
diff --git a/psalm-dev.xml b/psalm-dev.xml
deleted file mode 100644
index 6116331c7..000000000
--- a/psalm-dev.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/psalm.xml b/psalm.xml
deleted file mode 100644
index f15eb44fa..000000000
--- a/psalm.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Auth/InvalidCredentialResult.php b/src/Auth/InvalidCredentialResult.php
index 9f05f486b..83e5be90c 100644
--- a/src/Auth/InvalidCredentialResult.php
+++ b/src/Auth/InvalidCredentialResult.php
@@ -57,7 +57,7 @@ class InvalidCredentialResult
/**
* Map of keys to check the code against when using is* methods
*
- * @var array
+ * @var array>
*/
protected array $codeMap = [
self::KEY_INVALID_CREDENTIAL => [
@@ -155,7 +155,7 @@ public function getRawMessage(): string
/**
* Allows the default code mappings to be updated
- * @param array $codes
+ * @param array $codes
* @return void
*/
public function updateCodeMap(array $codes): void
@@ -167,7 +167,7 @@ public function updateCodeMap(array $codes): void
/**
* Allows the default code mappings to be replaced
*
- * @param array $codes
+ * @param array $codes
* @return void
*/
public function replaceCodeMap(array $codes): void
diff --git a/src/Auth/Process/AttributeAddFromLDAP.php b/src/Auth/Process/AttributeAddFromLDAP.php
index 3aac2d93f..57baa8e24 100644
--- a/src/Auth/Process/AttributeAddFromLDAP.php
+++ b/src/Auth/Process/AttributeAddFromLDAP.php
@@ -21,14 +21,14 @@ class AttributeAddFromLDAP extends BaseFilter
/**
* LDAP attributes to add to the request attributes
*
- * @var array
+ * @var string[]
*/
protected array $searchAttributes;
/**
* LDAP attributes to base64 encode
*
- * @var array
+ * @var string[]
*/
protected array $binaryAttributes;
@@ -55,7 +55,7 @@ class AttributeAddFromLDAP extends BaseFilter
/**
* Initialize this filter.
*
- * @param array $config Configuration information about this filter.
+ * @param array $config Configuration information about this filter.
* @param mixed $reserved For future use.
*/
public function __construct(array $config, $reserved)
@@ -83,7 +83,7 @@ public function __construct(array $config, $reserved)
/**
* Add attributes from an LDAP server.
*
- * @param array &$state The current request
+ * @param array &$state The current request
*/
public function process(array &$state): void
{
@@ -148,7 +148,6 @@ public function process(array &$state): void
$this->binaryAttributes,
);
foreach ($binaries as $binary) {
- /** @psalm-var array $attr */
$attr = $entry->getAttribute($binary);
$tmp[$binary] = array_map('base64_encode', $attr);
}
diff --git a/src/Auth/Process/AttributeAddUsersGroups.php b/src/Auth/Process/AttributeAddUsersGroups.php
index 9bcd5a30c..54597aad3 100644
--- a/src/Auth/Process/AttributeAddUsersGroups.php
+++ b/src/Auth/Process/AttributeAddUsersGroups.php
@@ -33,7 +33,7 @@ class AttributeAddUsersGroups extends BaseFilter
/**
* Initialize this filter.
*
- * @param array $config Configuration information about this filter.
+ * @param array $config Configuration information about this filter.
* @param mixed $reserved For future use.
*/
public function __construct(array $config, $reserved)
@@ -51,7 +51,7 @@ public function __construct(array $config, $reserved)
* LDAP search filters to be added to the base filters for this authproc-filter.
* It's an array of key => value pairs that will be translated to (key=value) in the ldap query.
*
- * @var array
+ * @var array
*/
protected array $additional_filters;
@@ -63,7 +63,7 @@ public function __construct(array $config, $reserved)
* are then added to the request attributes.
*
* @throws \SimpleSAML\Error\Exception
- * @param array &$state
+ * @param array &$state
*/
public function process(array &$state): void
{
@@ -124,8 +124,8 @@ public function process(array &$state): void
* get their group membership, recursively.
*
* @throws \SimpleSAML\Error\Exception
- * @param array $attributes
- * @return array
+ * @param array $attributes
+ * @return array
*/
protected function getGroups(array $attributes): array
{
@@ -291,13 +291,11 @@ protected function getGroups(array $attributes): array
$groups = [];
foreach ($entries as $entry) {
if ($entry->hasAttribute($return_attribute)) {
- /** @psalm-var array $values */
$values = $entry->getAttribute($return_attribute);
$groups[] = array_pop($values);
continue;
} elseif ($entry->hasAttribute(strtolower($return_attribute))) {
// Some backends return lowercase attributes
- /** @psalm-var array $values */
$values = $entry->getAttribute(strtolower($return_attribute));
$groups[] = array_pop($values);
continue;
@@ -330,9 +328,9 @@ protected function getGroups(array $attributes): array
* Avoids loops by only searching a DN once. Returns
* the list of groups found.
*
- * @param array $memberOf
- * @param array $options
- * @return array
+ * @param array $memberOf
+ * @param array $options
+ * @return array
*/
protected function search(array $memberOf, array $options): array
{
diff --git a/src/Auth/Process/BaseFilter.php b/src/Auth/Process/BaseFilter.php
index 45c012492..9fede589b 100644
--- a/src/Auth/Process/BaseFilter.php
+++ b/src/Auth/Process/BaseFilter.php
@@ -17,7 +17,11 @@
abstract class BaseFilter extends Auth\ProcessingFilter
{
- // TODO: Support ldap:LDAPMulti, if possible
+ /**
+ * TODO: Support ldap:LDAPMulti, if possible
+ *
+ * @var string[]
+ */
protected static array $ldapsources = ['ldap:Ldap', 'authX509:X509userCert'];
/**
@@ -25,14 +29,14 @@ abstract class BaseFilter extends Auth\ProcessingFilter
* name. Used for abstraction / configuration of the LDAP
* attribute names, which may change between dir service.
*
- * @var array
+ * @var array
*/
protected array $attribute_map;
/**
* The base DN of the LDAP connection. Used when searching the LDAP server.
*
- * @var array
+ * @var array
*/
protected array $searchBase;
@@ -64,7 +68,7 @@ abstract class BaseFilter extends Auth\ProcessingFilter
* List of LDAP object types, used to determine the type of
* object that a DN references.
*
- * @var array
+ * @var array
*/
protected array $type_map;
@@ -75,7 +79,7 @@ abstract class BaseFilter extends Auth\ProcessingFilter
* instance/object and stores everything in class members.
*
* @throws \SimpleSAML\Error\Exception
- * @param array &$config
+ * @param array &$config
* @param mixed $reserved
*/
public function __construct(array &$config, $reserved)
@@ -164,6 +168,7 @@ public function __construct(array &$config, $reserved)
* Parse authsource config
*
* @param string $as The name of the authsource
+ * @return array
*/
private function parseAuthSourceConfig(string $as): array
{
diff --git a/src/Auth/Source/Ldap.php b/src/Auth/Source/Ldap.php
index 10dd0f22f..2f840c0d6 100644
--- a/src/Auth/Source/Ldap.php
+++ b/src/Auth/Source/Ldap.php
@@ -49,8 +49,8 @@ class Ldap extends UserPassBase
/**
* Constructor for this authentication source.
*
- * @param array $info Information about this authentication source.
- * @param array $config Configuration.
+ * @param array $info Information about this authentication source.
+ * @param array $config Configuration.
*/
public function __construct(array $info, array $config)
{
@@ -71,11 +71,15 @@ public function __construct(array $info, array $config)
*
* @param string $username The username the user wrote.
* @param string $password The password the user wrote.
- * @param array|null $sasl_args SASL options
- * @return array Associative array with the users attributes.
+ * @param array $sasl_args SASL options
+ * @return array Associative array with the users attributes.
*/
- protected function loginSasl(string $username, #[\SensitiveParameter]string $password, array $sasl_args = []): array
- {
+ protected function loginSasl(
+ string $username,
+ #[\SensitiveParameter]
+ string $password,
+ array $sasl_args = [],
+ ): array {
if (preg_match('/^\s*$/', $password)) {
// The empty string is considered an anonymous bind to Symfony
throw new Error\Error('WRONGUSERPASS');
@@ -110,7 +114,7 @@ protected function loginSasl(string $username, #[\SensitiveParameter]string $pas
Assert::nullOrNotWhitespaceOnly($searchUsername);
$searchPassword = $this->ldapConfig->getOptionalString('search.password', null);
- Assert::nullOrnotWhitespaceOnly($searchPassword);
+ Assert::nullOrNotWhitespaceOnly($searchPassword);
try {
$this->connector->bind($searchUsername, $searchPassword);
@@ -164,7 +168,7 @@ protected function loginSasl(string $username, #[\SensitiveParameter]string $pas
*
* @param string $username The username the user wrote.
* @param string $password The password the user wrote.
- * @return array Associative array with the users attributes.
+ * @return array Associative array with the users attributes.
*/
protected function login(string $username, #[\SensitiveParameter]string $password): array
{
@@ -176,7 +180,7 @@ protected function login(string $username, #[\SensitiveParameter]string $passwor
* Attempt to find a user's attributes given its username.
*
* @param string $username The username who's attributes we want.
- * @return array Associative array with the users attributes.
+ * @return array Associative array with the users attributes.
*/
public function getAttributes(string $username): array
{
@@ -184,7 +188,7 @@ public function getAttributes(string $username): array
Assert::nullOrNotWhitespaceOnly($searchUsername);
$searchPassword = $this->ldapConfig->getOptionalString('search.password', null);
- Assert::nullOrnotWhitespaceOnly($searchPassword);
+ Assert::nullOrNotWhitespaceOnly($searchPassword);
try {
$this->connector->bind($searchUsername, $searchPassword);
@@ -232,7 +236,7 @@ public function getAttributes(string $username): array
/**
* @param \Symfony\Component\Ldap\Entry $entry
- * @return array
+ * @return array
*/
private function processAttributes(Entry $entry): array
{
diff --git a/src/Auth/Source/LdapMulti.php b/src/Auth/Source/LdapMulti.php
index 830d7a404..e3aef0d7c 100644
--- a/src/Auth/Source/LdapMulti.php
+++ b/src/Auth/Source/LdapMulti.php
@@ -33,16 +33,22 @@ class LdapMulti extends UserPassOrgBase
/**
* An array with mappings for organization => authsource.
+ *
+ * @var array
*/
private array $mapping;
/**
* An array with descriptions for organizations.
+ *
+ * @var array
*/
private array $orgs;
/**
* An array of organization IDs to LDAP configuration objects.
+ *
+ * @var array
*/
private array $ldapOrgs;
@@ -55,8 +61,8 @@ class LdapMulti extends UserPassOrgBase
/**
* Constructor for this authentication source.
*
- * @param array $info Information about this authentication source.
- * @param array $config Configuration.
+ * @param array $info Information about this authentication source.
+ * @param array $config Configuration.
*/
public function __construct(array $info, array $config)
{
@@ -109,15 +115,15 @@ public function __construct(array $info, array $config)
*
* @param string $username The username the user wrote.
* @param string $password The password the user wrote.
- * @param string $organizaion The organization the user chose.
- * @param array|null $sasl_args SASL options
- * @return array Associative array with the users attributes.
+ * @param string $organization The organization the user chose.
+ * @param array $sasl_args SASL options
+ * @return array Associative array with the users attributes.
*/
protected function loginSasl(
string $username,
#[\SensitiveParameter]string $password,
string $organization,
- ?array $sasl_args = [],
+ array $sasl_args = [],
): array {
if ($this->includeOrgInUsername) {
$username = $username . '@' . $organization;
@@ -134,10 +140,14 @@ protected function loginSasl(
$ldap = new class (['AuthId' => $authsource], $sourceConfig->toArray()) extends Ldap
{
+ /**
+ * @param array $sasl_args
+ * @return array
+ */
public function loginOverload(
string $username,
#[\SensitiveParameter]string $password,
- ?array $sasl_args,
+ array $sasl_args,
): array {
return $this->loginSasl($username, $password, $sasl_args);
}
@@ -146,23 +156,25 @@ public function loginOverload(
return $ldap->loginOverload($username, $password, $sasl_args);
}
+
/**
* Attempt to log in using the given username and password.
*
* @param string $username The username the user wrote.
* @param string $password The password the user wrote.
- * @param string $organizaion The organization the user chose.
- * @return array Associative array with the users attributes.
+ * @param string $organization The organization the user chose.
+ * @return array Associative array with the users attributes.
*/
protected function login(string $username, #[\SensitiveParameter]string $password, string $organization): array
{
return $this->loginSasl($username, $password, $organization);
}
+
/**
* Retrieve list of organizations.
*
- * @return array Associative array with the organizations.
+ * @return array Associative array with the organizations.
*/
protected function getOrganizations(): array
{
diff --git a/src/Connector/Ldap.php b/src/Connector/Ldap.php
index c62de6092..d5938a7f2 100644
--- a/src/Connector/Ldap.php
+++ b/src/Connector/Ldap.php
@@ -44,7 +44,7 @@ class Ldap implements ConnectorInterface
* @param int $version
* @param string $extension
* @param bool $debug
- * @param array $options
+ * @param array $options
*/
public function __construct(
string $connection_strings,
diff --git a/src/ConnectorInterface.php b/src/ConnectorInterface.php
index 63f265f61..4535ac117 100644
--- a/src/ConnectorInterface.php
+++ b/src/ConnectorInterface.php
@@ -64,9 +64,9 @@ public function whoami(): string;
/**
* Search the LDAP-directory for a specific object
*
- * @param array $searchBase
+ * @param string[] $searchBase
* @param string $filter
- * @param array $options
+ * @param array $options
* @param boolean $allowMissing
* @return \Symfony\Component\Ldap\Entry|null The result of the search or null if none found
* @psalm-return ($allowMissing is true ? \Symfony\Component\Ldap\Entry|null : \Symfony\Component\Ldap\Entry)
@@ -85,9 +85,9 @@ public function search(
/**
* Search the LDAP-directory for any object matching the search filter
*
- * @param array $searchBase
+ * @param string[] $searchBase
* @param string $filter
- * @param array $options
+ * @param array $options
* @param boolean $allowMissing
* @return \Symfony\Component\Ldap\Entry[] The result of the search
*