diff --git a/exec/lib/RemoteLoginUrlClient.php b/exec/lib/RemoteLoginUrlClient.php index 55248f3..6ac1539 100644 --- a/exec/lib/RemoteLoginUrlClient.php +++ b/exec/lib/RemoteLoginUrlClient.php @@ -67,8 +67,10 @@ final class RemoteLoginUrlClient 'login-url', '--user=' . $request->username, '--redirect-url=' . $request->redirectPath, - '--expiry=' . $request->ttl . 's', ]); + if ($request->ttl > 0) { + $command[] = '--expiry=' . $request->ttl . 's'; + } if ($request->userIpBound) { $command[] = '--ip=' . $request->clientIp; } diff --git a/exec/lib/Settings.php b/exec/lib/Settings.php index 73c218e..f70dc96 100644 --- a/exec/lib/Settings.php +++ b/exec/lib/Settings.php @@ -62,7 +62,7 @@ final class Settings 'MAIL_LOGIN_TARGET_NAME' => 'mx1', 'MAIL_LOGIN_TARGET_BASE_URL' => 'https://mx1.mojserwer.pl:2222', 'MAIL_LOGIN_REDIRECT_URL' => '/', - 'LOGIN_KEY_TTL' => '30', + 'LOGIN_KEY_TTL' => '14400', 'USER_IP_BOUND' => '1', 'IP_MASK' => '1', 'MAIL_LOGIN_SOURCE_SERVER_NAME' => '', @@ -128,7 +128,7 @@ final class Settings public function loginKeyTtl(): int { - return (int)$this->getString('LOGIN_KEY_TTL', '30'); + return (int)$this->getString('LOGIN_KEY_TTL', '14400'); } public function userIpBound(): bool @@ -252,8 +252,8 @@ final class Settings throw new InvalidArgumentException('LOGIN_KEY_TTL must be an integer'); } $ttl = (int)$ttlRaw; - if ($ttl < 5 || $ttl > 300) { - throw new InvalidArgumentException('LOGIN_KEY_TTL must be between 5 and 300 seconds'); + if ($ttl !== 0 && ($ttl < 5 || $ttl > 86400)) { + throw new InvalidArgumentException('LOGIN_KEY_TTL must be 0 or between 5 and 86400 seconds'); } if (!in_array($this->getString('USER_IP_BOUND', ''), ['0', '1'], true)) { throw new InvalidArgumentException('USER_IP_BOUND must be 0 or 1'); diff --git a/plugin-settings.conf b/plugin-settings.conf index 351ef38..329ee1b 100644 --- a/plugin-settings.conf +++ b/plugin-settings.conf @@ -18,8 +18,10 @@ MAIL_LOGIN_TARGET_NAME=mx1 MAIL_LOGIN_TARGET_BASE_URL=https://mx1.mojserwer.pl:2222 MAIL_LOGIN_REDIRECT_URL=/ -# Czas życia jednorazowego login URL w sekundach. Dozwolony zakres: 5-300. -LOGIN_KEY_TTL=30 +# Czas życia jednorazowego login URL w sekundach. +# 0 = nie przekazuj --expiry i użyj domyślnego DirectAdmin login_hash_expiry_minutes. +# Dozwolony zakres: 0 albo 5-86400. Domyślnie 14400 sekund, czyli 4h. +LOGIN_KEY_TTL=14400 # 1 = przypnij URL do IP przeglądarki użytkownika, 0 = nie przypinaj do IP. USER_IP_BOUND=1 diff --git a/plugin.conf b/plugin.conf index 89d7d09..5f1fe24 100644 --- a/plugin.conf +++ b/plugin.conf @@ -2,7 +2,7 @@ name=mail-login id=mail-login type=user author=HITME.PL -version=1.0.11 +version=1.0.12 active=no installed=no user_run_as=root diff --git a/tests/package_contents_test.php b/tests/package_contents_test.php index b8d1e85..99456a0 100644 --- a/tests/package_contents_test.php +++ b/tests/package_contents_test.php @@ -8,7 +8,7 @@ test('plugin metadata and packaging docs match project rules', function (): void assert_contains('name=mail-login', $conf); assert_contains('id=mail-login', $conf); assert_contains('type=user', $conf); - assert_contains('version=1.0.11', $conf); + assert_contains('version=1.0.12', $conf); assert_contains('user_run_as=root', $conf); assert_contains('/Users/marek/GPT/ChatGPT/da_plugins/mail-login/src', $packing); assert_contains('/Users/marek/GPT/ChatGPT/da_plugins/mail-login/archives/X.Y.Z/mail-login.tar.gz', $packing); diff --git a/tests/remote_login_url_client_test.php b/tests/remote_login_url_client_test.php index 0ed682c..c0ac2da 100644 --- a/tests/remote_login_url_client_test.php +++ b/tests/remote_login_url_client_test.php @@ -51,6 +51,20 @@ test('remote login url client builds helper ssh command when mode is helper', fu assert_same('1782810000', $command[$pos + 8]); }); +test('remote login url client omits expiry when ttl is zero', function (): void { + $settings = Settings::fromArray([ + 'MAIL_LOGIN_TARGET_BASE_URL' => 'https://mx1.domena.pl:2222', + 'MAIL_LOGIN_SSH_HOST' => 'mx1.domena.pl', + 'MAIL_LOGIN_SSH_IDENTITY' => '/secure/key', + 'MAIL_LOGIN_SSH_KNOWN_HOSTS' => '/secure/known_hosts', + 'LOGIN_KEY_TTL' => '0', + ]); + $request = new LoginUrlRequest('mxtest', 'h4.domena.pl', 'h4', 0, true, '198.51.100.10', '/', 1782810000); + $command = RemoteLoginUrlClient::buildCommand($settings, $request); + + assert_not_contains('--expiry=', implode(' ', $command)); +}); + test('remote login url client validates helper output before returning it', function (): void { $settings = Settings::fromArray(['MAIL_LOGIN_TARGET_BASE_URL' => 'https://mx1.domena.pl:2222']); $request = new LoginUrlRequest('mxtest', 'h4.domena.pl', 'h4', 30, true, '198.51.100.10', '/', 1782810000); diff --git a/tests/settings_test.php b/tests/settings_test.php index 9daab50..369a0b2 100644 --- a/tests/settings_test.php +++ b/tests/settings_test.php @@ -6,7 +6,7 @@ require_once PLUGIN_ROOT . '/exec/lib/Settings.php'; test('settings expose secure defaults from plugin-settings.conf', function (): void { $settings = Settings::fromArray([]); - assert_same(30, $settings->loginKeyTtl()); + assert_same(14400, $settings->loginKeyTtl()); assert_true($settings->userIpBound()); assert_true($settings->ipMask()); assert_same('MASKED', $settings->auditClientIp('198.51.100.10')); @@ -22,7 +22,7 @@ test('settings runtime file is the directadmin plugin settings file', function ( }); test('settings reject login key ttl outside production range', function (): void { - foreach (['4', '301', 'abc'] as $ttl) { + foreach (['4', '86401', 'abc'] as $ttl) { try { Settings::fromArray(['LOGIN_KEY_TTL' => $ttl]); throw new RuntimeException('Expected invalid TTL to fail: ' . $ttl); @@ -47,6 +47,12 @@ test('settings accept explicit ttl and user ip binding toggle', function (): voi assert_same(2, $settings->mxLoginMode()); }); +test('settings accept zero login key ttl as directadmin default expiry', function (): void { + $settings = Settings::fromArray(['LOGIN_KEY_TTL' => '0']); + + assert_same(0, $settings->loginKeyTtl()); +}); + test('settings reject unsupported ip mask values', function (): void { foreach (['yes', '2', ''] as $mask) { try {