diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 3b911a4..0000000 --- a/.gitattributes +++ /dev/null @@ -1,14 +0,0 @@ -/.github/ export-ignore -/tools/ export-ignore -/tests/ export-ignore -codecov.yml export-ignore -.editorconfig export-ignore -.gitattributes export-ignore -.gitignore export-ignore -psalm.xml export-ignore -psalm-dev.xml export-ignore -phpcs.xml export-ignore -phpunit.xml export-ignore -.php_cs.dist export-ignore -.markdownlintignore export-ignore -.markdownlintrc export-ignore diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index ee89027..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,37 +0,0 @@ ---- - -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - -version: 2 -updates: - - package-ecosystem: "github-actions" # See documentation for possible values - directory: "/" # Location of package manifests - schedule: - interval: "weekly" - groups: - all-actions: - patterns: ["*"] - - - package-ecosystem: "composer" # See documentation for possible values - directory: "/" # Location of package manifests - schedule: - interval: "weekly" - allow: - # Allow both direct and indirect updates for all packages - - dependency-type: "all" - ignore: - - dependency-name: "*" - update-types: ["version-update:semver-major"] - groups: - production-dependencies: - dependency-type: "production" - exclude-patterns: - - "symfony/*" - development-dependencies: - dependency-type: "development" - symfony: - patterns: - - "symfony/*" diff --git a/.github/workflows/autolock-conversations.yml b/.github/workflows/autolock-conversations.yml deleted file mode 100644 index 66797ba..0000000 --- a/.github/workflows/autolock-conversations.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- - -name: 'Lock Threads' - -on: # yamllint disable-line rule:truthy - schedule: - - cron: '0 0 * * *' - workflow_dispatch: - -permissions: - issues: write - pull-requests: write - -concurrency: - group: lock - -jobs: - action: - runs-on: ubuntu-latest - steps: - - uses: dessant/lock-threads@v6 - with: - issue-inactive-days: '90' - pr-inactive-days: '90' - log-output: true diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml deleted file mode 100644 index 97ca7e0..0000000 --- a/.github/workflows/documentation.yml +++ /dev/null @@ -1,56 +0,0 @@ ---- - -name: Documentation - -on: # yamllint disable-line rule:truthy - push: - branches: [master, simplesamlphp-*] - paths: - - '**.md' - pull_request: - branches: [master, simplesamlphp-*] - paths: - - '**.md' - workflow_dispatch: - -jobs: - quality: - name: Quality checks - runs-on: [ubuntu-latest] - - steps: - - uses: actions/checkout@v6 - - - name: Lint markdown files - uses: nosborn/github-action-markdown-cli@v3 - with: - files: . - ignore_path: .markdownlintignore - - - name: Perform spell check - uses: codespell-project/actions-codespell@v2 - with: - path: '**/*.md' - check_filenames: true - ignore_words_list: tekst - - build: - name: Build documentation - needs: quality - runs-on: [ubuntu-latest] - - steps: - - name: Run docs build - if: github.event_name != 'pull_request' - uses: actions/github-script@v9 - with: - # Token has to be generated on a user account that controls the docs-repository. - # The _only_ scope to select is "Access public repositories", nothing more. - github-token: ${{ secrets.PAT_TOKEN }} - script: | - await github.rest.actions.createWorkflowDispatch({ - owner: 'simplesamlphp', - repo: 'docs', - workflow_id: 'mk_docs.yml', - ref: 'main' - }) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml deleted file mode 100644 index abfceb5..0000000 --- a/.github/workflows/php.yml +++ /dev/null @@ -1,283 +0,0 @@ ---- - -name: CI - -on: # yamllint disable-line rule:truthy - push: - branches: ['**'] - paths-ignore: - - '**.md' - pull_request: - branches: [master, release-*] - paths-ignore: - - '**.md' - workflow_dispatch: - -jobs: - phplinter: - name: 'PHP-Linter' - strategy: - fail-fast: false - matrix: - php-version: ['8.3', '8.4', '8.5'] - - uses: simplesamlphp/simplesamlphp-test-framework/.github/workflows/reusable_phplinter.yml@v1.11.5 - with: - php-version: ${{ matrix.php-version }} - - linter: - name: 'Linter' - strategy: - fail-fast: false - - uses: simplesamlphp/simplesamlphp-test-framework/.github/workflows/reusable_linter.yml@v1.11.5 - with: - enable_eslinter: false - enable_jsonlinter: true - enable_stylelinter: false - enable_yamllinter: true - - unit-tests-linux: - name: "Unit tests, PHP ${{ matrix.php-versions }}, ${{ matrix.operating-system }}" - runs-on: ${{ matrix.operating-system }} - needs: [phplinter, linter] - strategy: - fail-fast: false - matrix: - operating-system: [ubuntu-latest] - php-versions: ['8.3', '8.4', '8.5'] - - steps: - - name: Setup PHP, with composer and extensions - # https://github.com/shivammathur/setup-php - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: ctype, date, dom, fileinfo, filter, hash, intl, mbstring, openssl,\ - pcre, posix, session, sodium, spl, xml - tools: composer - ini-values: error_reporting=E_ALL - coverage: pcov - - - name: Setup problem matchers for PHP - run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" - - - name: Setup problem matchers for PHPUnit - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - name: Set git to use LF - run: | - git config --global core.autocrlf false - git config --global core.eol lf - - - uses: actions/checkout@v6 - - - name: Get composer cache directory - run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$GITHUB_ENV" - - - name: Cache composer dependencies - uses: actions/cache@v5 - with: - path: $COMPOSER_CACHE - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install Composer dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Run unit tests with coverage - if: ${{ matrix.php-versions == '8.5' }} - run: vendor/bin/phpunit - - - name: Run unit tests (no coverage) - if: ${{ matrix.php-versions != '8.5' }} - run: vendor/bin/phpunit --no-coverage - - - name: Save coverage data - if: ${{ matrix.php-versions == '8.5' }} - uses: actions/upload-artifact@v7 - with: - name: coverage-data - path: ${{ github.workspace }}/build - - unit-tests-windows: - name: "Unit tests, PHP ${{ matrix.php-versions }}, ${{ matrix.operating-system }}" - runs-on: ${{ matrix.operating-system }} - needs: [linter, phplinter] - strategy: - fail-fast: true - matrix: - operating-system: [windows-latest] - php-versions: ['8.3', '8.4', '8.5'] - - steps: - - name: Setup PHP, with composer and extensions - # https://github.com/shivammathur/setup-php - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - extensions: ctype, date, dom, fileinfo, filter, hash, intl, mbstring, openssl,\ - pcre, posix, session, sodium, spl, xml, zip - tools: composer - ini-values: error_reporting=E_ALL - coverage: none - - - name: Setup problem matchers for PHP - run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" - - - name: Setup problem matchers for PHPUnit - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - name: Set git to use LF - run: | - git config --global core.autocrlf false - git config --global core.eol lf - - - uses: actions/checkout@v6 - - - name: Get composer cache directory - run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$env:GITHUB_ENV" - - - name: Cache composer dependencies - uses: actions/cache@v5 - with: - path: $COMPOSER_CACHE - key: ${{ runner.os }}-composer-${{ hashFiles('**\composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install Composer dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader --ignore-platform-req=ext-posix - - - name: Run unit tests - run: vendor/bin/phpunit --no-coverage - - quality: - name: Quality control - needs: [unit-tests-linux] - runs-on: [ubuntu-latest] - - steps: - - name: Setup PHP, with composer and extensions - id: setup-php - # https://github.com/shivammathur/setup-php - uses: shivammathur/setup-php@v2 - with: - # Should be the higest supported version, so we can use the newest tools - php-version: '8.5' - tools: composer, composer-require-checker, composer-unused, phpcs - extensions: ctype, date, dom, fileinfo, filter, hash, intl, mbstring, openssl,\ - pcre, posix, session, sodium, spl, xml - - - name: Setup problem matchers for PHP - run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" - - - uses: actions/checkout@v6 - - - name: Get composer cache directory - run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$GITHUB_ENV" - - - name: Cache composer dependencies - uses: actions/cache@v5 - with: - path: $COMPOSER_CACHE - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Validate composer.json and composer.lock - run: composer validate - - - name: Install Composer dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Check code for hard dependencies missing in composer.json - run: composer-require-checker check --config-file=tools/composer-require-checker.json composer.json - - - name: Check code for unused dependencies in composer.json - run: composer-unused - - - name: PHP Code Sniffer - run: vendor/bin/phpcs - - - name: PHPStan - run: | - vendor/bin/phpstan analyze -c phpstan.neon --debug - - - name: PHPStan (testsuite) - run: | - vendor/bin/phpstan analyze -c phpstan-dev.neon --debug - - security: - name: Security checks - needs: [unit-tests-linux] - runs-on: [ubuntu-latest] - steps: - - name: Setup PHP, with composer and extensions - # https://github.com/shivammathur/setup-php - uses: shivammathur/setup-php@v2 - with: - # Should be the lowest supported version - php-version: '8.3' - extensions: ctype, date, dom, fileinfo, filter, hash, intl, mbstring, openssl, pcre, posix,\ - session, sodium, spl, xml - tools: composer - coverage: none - - - name: Setup problem matchers for PHP - run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" - - - uses: actions/checkout@v6 - - - name: Get composer cache directory - run: echo COMPOSER_CACHE="$(composer config cache-files-dir)" >> "$GITHUB_ENV" - - - name: Cache composer dependencies - uses: actions/cache@v5 - with: - path: $COMPOSER_CACHE - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install Composer dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Security check for locked dependencies - run: composer audit - - - name: Update Composer dependencies - run: composer update --no-progress --prefer-dist --optimize-autoloader - - - name: Security check for updated dependencies - run: composer audit - - coverage: - name: Code coverage - runs-on: [ubuntu-latest] - needs: [unit-tests-linux] - steps: - - uses: actions/checkout@v6 - - - uses: actions/download-artifact@v8 - with: - name: coverage-data - path: ${{ github.workspace }}/build - - - name: Codecov - uses: codecov/codecov-action@v6 - with: - token: ${{ secrets.CODECOV_TOKEN }} - fail_ci_if_error: true - verbose: true - - cleanup: - name: Cleanup artifacts - needs: [unit-tests-linux, coverage] - runs-on: [ubuntu-latest] - if: | - always() && - needs.coverage.result == 'success' || - (needs.unit-tests-linux.result == 'success' && needs.coverage.result == 'skipped') - - steps: - - uses: geekyeggo/delete-artifact@v6 - with: - name: coverage-data diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 66ac39a..0000000 --- a/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -1 -2 -3 -.phplint.cache/ -.phpunit.cache/ -.phpunit.result.cache -composer.lock -composer.phar -phpunit.xml.bak -/super-linter-output/ -/vendor/ - -# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control -# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file -# composer.lock diff --git a/.markdownlintignore b/.markdownlintignore deleted file mode 100644 index 140fada..0000000 --- a/.markdownlintignore +++ /dev/null @@ -1 +0,0 @@ -vendor/* diff --git a/.markdownlintrc b/.markdownlintrc deleted file mode 100644 index b077f0e..0000000 --- a/.markdownlintrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "default": true, - "MD013": false -} diff --git a/.php_cs.dist b/.php_cs.dist index b46e7f8..e7d3146 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -1,7 +1,7 @@ in([ - __DIR__ . '/src', + __DIR__ . '/lib', __DIR__ . '/tests', ]) ; diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a090b62 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,31 @@ +sudo: required + +language: php + +php: + - 5.6 + - 7.0 + - 7.1 + - 7.2 + - 7.3 + +env: + - SIMPLESAMLPHP_VERSION=1.17.* + +before_script: + - composer require "simplesamlphp/simplesamlphp:${SIMPLESAMLPHP_VERSION}" --no-update + - composer update --no-interaction + - if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then composer require --dev vimeo/psalm:1.1.9; fi + +script: + - bin/check-syntax.sh + - if [[ "$TRAVIS_PHP_VERSION" == "5.6" ]]; then php vendor/phpunit/phpunit/phpunit; else php vendor/phpunit/phpunit/phpunit --no-coverage; fi + - if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then vendor/bin/psalm; fi + +after_success: + # Codecov, need to edit bash uploader for incorrect TRAVIS_PYTHON_VERSION environment variable matching, at least until codecov/codecov-bash#133 is resolved + - curl -s https://codecov.io/bash > .codecov + - sed -i -e 's/TRAVIS_.*_VERSION/^TRAVIS_.*_VERSION=/' .codecov + - chmod +x .codecov + - if [[ $TRAVIS_PHP_VERSION == "5.6" ]]; then ./.codecov -X gcov; fi +# - if [[ "$TRAVIS_PHP_VERSION" == "5.6" ]]; then bash <(curl -s https://codecov.io/bash); fi diff --git a/README.md b/README.md deleted file mode 100644 index ce92a5d..0000000 --- a/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Authcrypt - -![Build Status](https://github.com/simplesamlphp/simplesamlphp-module-authcrypt/actions/workflows/php.yml/badge.svg) -[![Coverage Status](https://codecov.io/gh/simplesamlphp/simplesamlphp-module-authcrypt/branch/master/graph/badge.svg)](https://codecov.io/gh/simplesamlphp/simplesamlphp-module-authcrypt) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/simplesamlphp/simplesamlphp-module-authcrypt/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/simplesamlphp/simplesamlphp-module-authcrypt/?branch=master) -[![Type Coverage](https://shepherd.dev/github/simplesamlphp/simplesamlphp-module-authcrypt/coverage.svg)](https://shepherd.dev/github/simplesamlphp/simplesamlphp-module-authcrypt) -[![Psalm Level](https://shepherd.dev/github/simplesamlphp/simplesamlphp-module-authcrypt/level.svg)](https://shepherd.dev/github/simplesamlphp/simplesamlphp-module-authcrypt) - -## Install - -Install with composer - -```bash -bin/composer require simplesamlphp/simplesamlphp-module-authcrypt -``` - -## Configuration - -Next thing you need to do is to enable the module: - -in `config.php`, search for the `module.enable` key and set `authcrypt` to true: - -```php -'module.enable' => [ 'authcrypt' => true, … ], -``` diff --git a/bin/check-syntax.sh b/bin/check-syntax.sh new file mode 100755 index 0000000..db6dc4b --- /dev/null +++ b/bin/check-syntax.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +PHP='/usr/bin/env php' +RETURN=0 + +# check PHP files +for FILE in `find lib tests -name "*.php"`; do + $PHP -l $FILE > /dev/null 2>&1 + if [ $? -ne 0 ]; then + echo "Syntax check failed for ${FILE}" + RETURN=`expr ${RETURN} + 1` + fi +done + +exit $RETURN diff --git a/codecov.yml b/codecov.yml index 66cf7b9..f7f39e1 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,19 +1,11 @@ ---- - coverage: status: - project: - default: - target: 0% - threshold: 2% - patch: false + project: yes + comment: layout: "diff" behavior: once require_changes: true - require_base: false - require_head: true + require_base: no + require_head: yes branches: null - -github_checks: - annotations: false diff --git a/composer.json b/composer.json index 532a986..c8c5aa8 100644 --- a/composer.json +++ b/composer.json @@ -17,15 +17,12 @@ }, "allow-plugins": { "composer/package-versions-deprecated": true, - "simplesamlphp/composer-module-installer": true, - "phpstan/extension-installer": true, - "dealerdirect/phpcodesniffer-composer-installer": true, - "simplesamlphp/composer-xmlprovider-installer": true + "simplesamlphp/composer-module-installer": true } }, "autoload": { "psr-4": { - "SimpleSAML\\Module\\authcrypt\\": "src/" + "SimpleSAML\\Module\\authcrypt\\": "lib/" } }, "autoload-dev": { @@ -34,17 +31,17 @@ } }, "require": { - "php": "^8.3", - - "simplesamlphp/assert": "^2.0", - "simplesamlphp/simplesamlphp": "^2.5@dev", + "php": ">=5.6", + "simplesamlphp/composer-module-installer": "~1.1", + "webmozart/assert": "~1.4", "whitehat101/apr1-md5": "~1.0" }, "require-dev": { - "simplesamlphp/simplesamlphp-test-framework": "^1.11" + "simplesamlphp/simplesamlphp": "^1.17", + "phpunit/phpunit": "~5.7" }, "support": { - "issues": "https://github.com/simplesamlphp/simplesamlphp-module-authcrypt/issues", - "source": "https://github.com/simplesamlphp/simplesamlphp-module-authcrypt" + "issues": "https://github.com/tvdijen/simplesamlphp-module-authcrypt/issues", + "source": "https://github.com/tvdijen/simplesamlphp-module-authcrypt" } } diff --git a/default-disable b/default-disable new file mode 100644 index 0000000..fa0bd82 --- /dev/null +++ b/default-disable @@ -0,0 +1,3 @@ +This file indicates that the default state of this module +is disabled. To enable, create a file named enable in the +same directory as this file. diff --git a/docs/authcrypt.md b/docs/authcrypt.md index c4b0a9e..148b9eb 100644 --- a/docs/authcrypt.md +++ b/docs/authcrypt.md @@ -1,4 +1,5 @@ -# AuthCrypt +AuthCrypt +========= This module provides two methods for authentication: @@ -8,69 +9,65 @@ This module provides two methods for authentication: `authcrypt:Htpasswd` : Username & password authentication against an `.htpasswd` file. -## authcrypt:Hash + +`authcrypt:Hash` +---------------- This is based on `exampleAuth:UserPass`, and adds support for hashed passwords. Hashes can be generated with the included command line tool `bin/pwgen.sh`. -This tool will interactively ask for a password, a hashing algorithm, and -whether or not you want to use a salt: +This tool will interactively ask for a password, a hashing algorithm , and whether or not you want to use a salt: -```bash -[user@server simplesamlphp]$ bin/pwgen.php -Enter password: hackme + [user@server simplesamlphp]$ bin/pwgen.php + Enter password: hackme + The following hashing algorithms are available: + md2 md4 md5 sha1 sha224 sha256 + sha384 sha512 ripemd128 ripemd160 ripemd256 ripemd320 + whirlpool tiger128,3 tiger160,3 tiger192,3 tiger128,4 tiger160,4 + tiger192,4 snefru snefru256 gost adler32 crc32 + crc32b salsa10 salsa20 haval128,3 haval160,3 haval192,3 + haval224,3 haval256,3 haval128,4 haval160,4 haval192,4 haval224,4 + haval256,4 haval128,5 haval160,5 haval192,5 haval224,5 haval256,5 -$2y$10$PnFsSEv.lda1Qlw4iMtmB.B.ab5y.aT56stBmo9hdCN.rUywQMChC -``` + Which one do you want? [sha256] + Do you want to use a salt? (yes/no) [yes] -Now create an authentication source in `config/authsources.php` and use the -resulting string as the password: + {SSHA256}y1mj3xsZ4/+LoQyPNVJzXUFfBcLHfwcHx1xxltxeQ1C5MeyEX/RxWA== -```php -'example-hashed' => [ - 'authCrypt:Hash', - 'student:$2y$10$PnFsSEv.lda1Qlw4iMtmB.B.ab5y.aT56stBmo9hdCN.rUywQMChC' => [ - 'uid' => ['student'], - 'eduPersonAffiliation' => ['member', 'student'], - ], -], -``` +Now create an authentication source in `config/authsources.php` and use the resulting string as the password: -This example creates a user `student` with password `hackme`, -and some attributes. + 'example-hashed' => array( + 'authCrypt:Hash', + 'student:{SSHA256}y1mj3xsZ4/+LoQyPNVJzXUFfBcLHfwcHx1xxltxeQ1C5MeyEX/RxWA==' => array( + 'uid' => array('student'), + 'eduPersonAffiliation' => array('member', 'student'), + ), + ), -### Compatibility +This example creates a user `student` with password `hackme`, and some attributes. -The generated hashes can also be used in `config.php` for the -administrative password: +### Compatibility ### +The generated hashes can also be used in `config.php` for the administrative password: -```php -'auth.adminpassword' => '$2y$10$PnFsSEv.lda1Qlw4iMtmB.B.ab5y.aT56stBmo9hdCN.rUywQMChC', -``` + 'auth.adminpassword' => '{SSHA256}y1mj3xsZ4/+LoQyPNVJzXUFfBcLHfwcHx1xxltxeQ1C5MeyEX/RxWA==', -Instead of generating hashes, you can also use existing ones from OpenLDAP, -provided that the `userPassword` attribute is stored as MD5, SMD5, SHA, or SSHA. +Instead of generating hashes, you can also use existing ones from OpenLDAP, provided that the `userPassword` attribute is stored as MD5, SMD5, SHA, or SSHA. -## authCrypt:Htpasswd -Authenticate users against an [`.htpasswd`](htpasswd) file. It can be used for -example when you migrate a web site from basic HTTP authentication to -SimpleSAMLphp. +`authCrypt:Htpasswd` +-------------------- -[htpasswd]: http://httpd.apache.org/docs/2.2/programs/htpasswd.html +Authenticate users against an [`.htpasswd`](http://httpd.apache.org/docs/2.2/programs/htpasswd.html) file. It can be used for example when you migrate a web site from basic HTTP authentication to SimpleSAMLphp. -The simple structure of the `.htpasswd` file does not allow for per-user -attributes, but you can define some static attributes for all users. +The simple structure of the `.htpasswd` file does not allow for per-user attributes, but you can define some static attributes for all users. -An example authentication source in `config/authsources.php` could look -like this: +An example authentication source in `config/authsources.php` could look like this: -```php - 'htpasswd' => [ + 'htpasswd' => array( 'authcrypt:Htpasswd', - 'htpasswd_file' => '/var/www/foo.edu/legacy_app/.htpasswd', - 'static_attributes' => [ - 'eduPersonAffiliation' => ['member', 'employee'], - 'Organization' => ['University of Foo'], - ], - ], -``` + 'htpasswd_file' => '/var/www/foo.edu/legacy_app/.htpasswd', + 'static_attributes' => array( + 'eduPersonAffiliation' => array('member', 'employee'), + 'Organization' => array('University of Foo'), + ), + ), + diff --git a/src/Auth/Source/Hash.php b/lib/Auth/Source/Hash.php similarity index 55% rename from src/Auth/Source/Hash.php rename to lib/Auth/Source/Hash.php index 655e507..4d1ee95 100644 --- a/src/Auth/Source/Hash.php +++ b/lib/Auth/Source/Hash.php @@ -1,17 +1,10 @@ :", * while the value of each element is a new array with the attributes for each user. - * - * @var array */ - private array $users; + private $users; /** * 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. * - * @throws \Exception in case of a configuration error. + * @throws Exception in case of a configuration error. */ - public function __construct(array $info, array $config) + public function __construct($info, $config) { + assert(is_array($info)); + assert(is_array($config)); + // Call the parent constructor first, as required by the interface parent::__construct($info, $config); @@ -51,28 +46,27 @@ public function __construct(array $info, array $config) // Validate and parse our configuration foreach ($config as $userpass => $attributes) { if (!is_string($userpass)) { - throw new Exception('Invalid : for authentication source ' . - $this->authId . ': ' . $userpass); + throw new \Exception('Invalid : for authentication source '. + $this->authId.': '.$userpass); } $userpass = explode(':', $userpass, 2); if (count($userpass) !== 2) { - throw new Exception('Invalid : for authentication source ' . - $this->authId . ': ' . $userpass[0]); + throw new \Exception('Invalid : for authentication source '. + $this->authId.': '.$userpass[0]); } $username = $userpass[0]; $passwordhash = $userpass[1]; try { - $attrUtils = new Utils\Attributes(); - $attributes = $attrUtils->normalizeAttributesArray($attributes); - } catch (Exception $e) { - throw new Exception('Invalid attributes for user ' . $username . - ' in authentication source ' . $this->authId . ': ' . + $attributes = Attributes::normalizeAttributesArray($attributes); + } catch (\Exception $e) { + throw new \Exception('Invalid attributes for user '.$username. + ' in authentication source '.$this->authId.': '. $e->getMessage()); } - $this->users[$username . ':' . $passwordhash] = $attributes; + $this->users[$username.':'.$passwordhash] = $attributes; } } @@ -89,26 +83,25 @@ public function __construct(array $info, array $config) * @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. * * @throws \SimpleSAML\Error\Error if authentication fails. */ - protected function login( - string $username, - #[\SensitiveParameter] - string $password, - ): array { - $cryptoUtils = new Utils\Crypto(); + protected function login($username, $password) + { + assert(is_string($username)); + assert(is_string($password)); + foreach ($this->users as $userpass => $attrs) { $matches = explode(':', $userpass, 2); if ($matches[0] === $username) { - if ($cryptoUtils->pwValid($matches[1], $password)) { + if (Crypto::pwValid($matches[1], $password)) { return $attrs; } else { - Logger::debug('Incorrect password "' . $password . '" for user ' . $username); + Logger::debug('Incorrect password "'.$password.'" for user '.$username); } } } - throw new Error\Error('WRONGUSERPASS'); + throw new \SimpleSAML\Error\Error('WRONGUSERPASS'); } } diff --git a/src/Auth/Source/Htpasswd.php b/lib/Auth/Source/Htpasswd.php similarity index 53% rename from src/Auth/Source/Htpasswd.php rename to lib/Auth/Source/Htpasswd.php index bb6d5e0..fc05800 100644 --- a/src/Auth/Source/Htpasswd.php +++ b/lib/Auth/Source/Htpasswd.php @@ -1,72 +1,65 @@ :". * - * @var array + * @var array */ - private array $users; + private $users; /** * An array containing static attributes for our users. * - * @var array + * @var array */ - private array $attributes = []; + private $attributes = []; /** * 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. * - * @throws \Exception if the htpasswd file is not readable or the static_attributes array is invalid. + * @throws Exception if the htpasswd file is not readable or the static_attributes array is invalid. */ - public function __construct(array $info, array $config) + public function __construct($info, $config) { + assert(is_array($info)); + assert(is_array($config)); + // Call the parent constructor first, as required by the interface parent::__construct($info, $config); $this->users = []; if (!$htpasswd = file_get_contents($config['htpasswd_file'])) { - throw new Exception('Could not read ' . $config['htpasswd_file']); + throw new \Exception('Could not read '.$config['htpasswd_file']); } $this->users = explode("\n", trim($htpasswd)); try { - $attrUtils = new Utils\Attributes(); - $this->attributes = $attrUtils->normalizeAttributesArray($config['static_attributes']); - } catch (Exception $e) { - throw new Exception('Invalid static_attributes in authentication source ' . - $this->authId . ': ' . $e->getMessage()); + $this->attributes = Attributes::normalizeAttributesArray($config['static_attributes']); + } catch (\Exception $e) { + throw new \Exception('Invalid static_attributes in authentication source '. + $this->authId.': '.$e->getMessage()); } } @@ -83,16 +76,15 @@ public function __construct(array $info, array $config) * @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. * * @throws \SimpleSAML\Error\Error if authentication fails. */ - protected function login( - string $username, - #[\SensitiveParameter] - string $password, - ): array { - $cryptoUtils = new Utils\Crypto(); + protected function login($username, $password) + { + assert(is_string($username)); + assert(is_string($password)); + foreach ($this->users as $userpass) { $matches = explode(':', $userpass, 2); if ($matches[0] == $username) { @@ -102,31 +94,28 @@ protected function login( $attributes = array_merge(['uid' => [$username]], $this->attributes); // Traditional crypt(3) - if ($cryptoUtils->secureCompare($crypted, crypt($password, $crypted))) { - Logger::debug('User ' . $username . ' authenticated successfully'); + if (Crypto::secureCompare($crypted, crypt($password, $crypted))) { + Logger::debug('User '.$username.' authenticated successfully'); Logger::warning( - 'CRYPT authentication is insecure. Please consider using something else.', + 'CRYPT authentication is insecure. Please consider using something else.' ); return $attributes; } // Apache's custom MD5 if (APR1_MD5::check($password, $crypted)) { - Logger::debug('User ' . $username . ' authenticated successfully'); - Logger::warning( - 'APR1 authentication is insecure. Please consider using something else.', - ); + Logger::debug('User '.$username.' authenticated successfully'); return $attributes; } // PASSWORD_BCRYPT - if ($cryptoUtils->pwValid($crypted, $password)) { - Logger::debug('User ' . $username . ' authenticated successfully'); + if (Crypto::pwValid($crypted, $password)) { + Logger::debug('User '.$username.' authenticated successfully'); return $attributes; } - throw new Error\Error('WRONGUSERPASS'); + throw new \SimpleSAML\Error\Error('WRONGUSERPASS'); } } - throw new Error\Error('WRONGUSERPASS'); + throw new \SimpleSAML\Error\Error('WRONGUSERPASS'); } } diff --git a/phpcs.xml b/phpcs.xml deleted file mode 100644 index 7e872ae..0000000 --- a/phpcs.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - By default it is less stringent about long lines than other coding standards - - - src - tests - - - - - - - - diff --git a/phpstan-dev.neon b/phpstan-dev.neon deleted file mode 100644 index 4d29b8b..0000000 --- a/phpstan-dev.neon +++ /dev/null @@ -1,4 +0,0 @@ -parameters: - level: 9 - paths: - - tests diff --git a/phpstan.neon b/phpstan.neon deleted file mode 100644 index db37782..0000000 --- a/phpstan.neon +++ /dev/null @@ -1,4 +0,0 @@ -parameters: - level: 6 - paths: - - src diff --git a/phpunit.xml b/phpunit.xml index a285b98..c0985fd 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,22 +1,19 @@ - - - - - - - - - - - - ./vendor/simplesamlphp/simplesamlphp-test-framework/src - ./tests - - - - - - ./src - - + + + + + tests/ + + + + + ./lib + + + + + + + + diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..5802afa --- /dev/null +++ b/psalm.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/bootstrap.php b/tests/bootstrap.php index f1d9882..603b889 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,12 +1,10 @@