<commit_before><?php

declare(strict_types=1);

/*
 * eduVPN - End-user friendly VPN.
 *
 * Copyright: 2016-2021, The Commons Conservancy eduVPN Programme
 * SPDX-License-Identifier: AGPL-3.0+
 */

namespace LC\Portal\Http\Auth;

use LC\Portal\Http\Auth\Exception\RadiusException;
use LC\Portal\Http\UserInfo;
use LC\Portal\LoggerInterface;
use RuntimeException;

class RadiusCredentialValidator implements CredentialValidatorInterface
{
    private LoggerInterface $logger;
    private array $serverList;
    private ?string $radiusRealm;
    private ?string $nasIdentifier;
    private ?int $permissionAttribute;

    public function __construct(LoggerInterface $logger, array $serverList, ?string $radiusRealm, ?string $nasIdentifier = null, ?int $permissionAttribute)
    {
        if (false === \extension_loaded('radius')) {
            throw new RuntimeException('"radius" PHP extension not available');
        }
        $this->logger = $logger;
        $this->serverList = $serverList;
        $this->radiusRealm = $radiusRealm;
        $this->nasIdentifier = $nasIdentifier;
        $this->permissionAttribute = $permissionAttribute;
    }

    /**
     * @return false|\LC\Portal\Http\UserInfo
     */
    public function isValid(string $authUser, string $authPass)
    {
        // add realm when requested
        if (null !== $this->radiusRealm) {
            $authUser = sprintf('%s@%s', $authUser, $this->radiusRealm);
        }

        $radiusAuth = radius_auth_open();

        foreach ($this->serverList as $radiusServer) {
            if (false === radius_add_server(
                $radiusAuth,
                $radiusServer['host'],
                \array_key_exists('port', $radiusServer) ? $radiusServer['port'] : 1812,
                $radiusServer['secret'],
                5,  // timeout
                3   // max_tries
            )) {
                $errorMsg = sprintf('RADIUS error: %s', radius_strerror($radiusAuth));
                $this->logger->error($errorMsg);

                throw new RadiusException($errorMsg);
            }
        }

        if (false === radius_create_request($radiusAuth, \RADIUS_ACCESS_REQUEST)) {
            $errorMsg = sprintf('RADIUS error: %s', radius_strerror($radiusAuth));
            $this->logger->error($errorMsg);

            throw new RadiusException($errorMsg);
        }

        radius_put_attr($radiusAuth, \RADIUS_USER_NAME, $authUser);
        radius_put_attr($radiusAuth, \RADIUS_USER_PASSWORD, $authPass);
        if (null !== $this->nasIdentifier) {
            radius_put_attr($radiusAuth, \RADIUS_NAS_IDENTIFIER, $this->nasIdentifier);
        }

        /** @var int|false $radiusResponse */
        $radiusResponse = radius_send_request($radiusAuth);
        if (false === $radiusResponse) {
            $errorMsg = sprintf('RADIUS error: %s', radius_strerror($radiusAuth));
            $this->logger->error($errorMsg);

            throw new RadiusException($errorMsg);
        }<commit_msg>sent PR for psalm fix instead<commit_after><?php

declare(strict_types=1);

/*
 * eduVPN - End-user friendly VPN.
 *
 * Copyright: 2016-2021, The Commons Conservancy eduVPN Programme
 * SPDX-License-Identifier: AGPL-3.0+
 */

namespace LC\Portal\Http\Auth;

use LC\Portal\Http\Auth\Exception\RadiusException;
use LC\Portal\Http\UserInfo;
use LC\Portal\LoggerInterface;
use RuntimeException;

class RadiusCredentialValidator implements CredentialValidatorInterface
{
    private LoggerInterface $logger;
    private array $serverList;
    private ?string $radiusRealm;
    private ?string $nasIdentifier;
    private ?int $permissionAttribute;

    public function __construct(LoggerInterface $logger, array $serverList, ?string $radiusRealm, ?string $nasIdentifier = null, ?int $permissionAttribute)
    {
        if (false === \extension_loaded('radius')) {
            throw new RuntimeException('"radius" PHP extension not available');
        }
        $this->logger = $logger;
        $this->serverList = $serverList;
        $this->radiusRealm = $radiusRealm;
        $this->nasIdentifier = $nasIdentifier;
        $this->permissionAttribute = $permissionAttribute;
    }

    /**
     * @return false|\LC\Portal\Http\UserInfo
     */
    public function isValid(string $authUser, string $authPass)
    {
        // add realm when requested
        if (null !== $this->radiusRealm) {
            $authUser = sprintf('%s@%s', $authUser, $this->radiusRealm);
        }

        $radiusAuth = radius_auth_open();

        foreach ($this->serverList as $radiusServer) {
            if (false === radius_add_server(
                $radiusAuth,
                $radiusServer['host'],
                \array_key_exists('port', $radiusServer) ? $radiusServer['port'] : 1812,
                $radiusServer['secret'],
                5,  // timeout
                3   // max_tries
            )) {
                $errorMsg = sprintf('RADIUS error: %s', radius_strerror($radiusAuth));
                $this->logger->error($errorMsg);

                throw new RadiusException($errorMsg);
            }
        }

        if (false === radius_create_request($radiusAuth, \RADIUS_ACCESS_REQUEST)) {
            $errorMsg = sprintf('RADIUS error: %s', radius_strerror($radiusAuth));
            $this->logger->error($errorMsg);

            throw new RadiusException($errorMsg);
        }

        radius_put_attr($radiusAuth, \RADIUS_USER_NAME, $authUser);
        radius_put_attr($radiusAuth, \RADIUS_USER_PASSWORD, $authPass);
        if (null !== $this->nasIdentifier) {
            radius_put_attr($radiusAuth, \RADIUS_NAS_IDENTIFIER, $this->nasIdentifier);
        }

        $radiusResponse = radius_send_request($radiusAuth);
        if (false === $radiusResponse) {
            $errorMsg = sprintf('RADIUS error: %s', radius_strerror($radiusAuth));
            $this->logger->error($errorMsg);

            throw new RadiusException($errorMsg);
        }
{'fraction_non_alphanumeric': 0.1254203093476799, 'fraction_numerical': 0.0057162071284465365, 'mean_word_length': 2.612021857923497, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6976512', 'n_tokens_mistral': 1740, 'n_tokens_neox': 1665, 'n_words': 336}