diff --git a/docs/settings.md b/docs/settings.md index 6f170af1acc..0cd1afe45c6 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -88,8 +88,8 @@ Legend: | `sip_bridge_shared_secret` | string | | Yes | 🖌️ | Shared secret allowing the SIP bridge to authenticate on the Nextcloud server | | `signaling_ticket_secret` | string | | Yes | | Secret used to secure the signaling tickets for guests (255 character random string) | | `signaling_token_alg` | string
`ES256`, `ES384`, `RS256`, `RS384`, `RS512` or `EdDSA` | `ES256` | Yes | | Algorithm for the signaling tickets | -| `signaling_token_privkey_*` | string | * | Yes | | Private key for the signaling ticket creation by the server | -| `signaling_token_pubkey_*` | string | * | Yes | | Public key for the signaling ticket creation by the server | +| `signaling_token_privkey` | string | `''` | No | | Private key for the signaling ticket creation by the server | +| `signaling_token_pubkey` | string | `''` | Yes | | Public key for the signaling ticket creation by the server | | `hosted_signaling_server_nonce` | string | | No | | Temporary nonce while configuring the hosted signaling server | | `hosted_signaling_server_account_id` | string | | No | | Account identifier of the hosted signaling server | | `matterbridge_binary` | string | | No | | Path to the matterbridge binary file | diff --git a/lib/Command/Signaling/VerifyKeys.php b/lib/Command/Signaling/VerifyKeys.php index a58a6285559..611936c6ba0 100644 --- a/lib/Command/Signaling/VerifyKeys.php +++ b/lib/Command/Signaling/VerifyKeys.php @@ -51,7 +51,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int if ($update) { $output->writeln('Stored public key for algorithm ' . strtolower($alg) . ' did not match stored private key.'); $output->writeln('A new public key was created and stored.'); - $this->appConfig->setAppValueString('signaling_token_pubkey_' . strtolower($alg), $publicKeyDerived); + $this->appConfig->setAppValueString(Config::SIGNALING_TOKEN_PUBKEY, $publicKeyDerived); return 0; } diff --git a/lib/Config.php b/lib/Config.php index 77ce7eb2797..45370032c5d 100644 --- a/lib/Config.php +++ b/lib/Config.php @@ -112,6 +112,8 @@ class Config { public const string CONVERSATIONS_LIST_STYLES = 'conversations_list_styles'; public const string SIGNALING_TICKET_SECRET = 'signaling_ticket_secret'; public const string SIGNALING_TOKEN_ALG = 'signaling_token_alg'; + public const string SIGNALING_TOKEN_PRIVKEY = 'signaling_token_privkey'; + public const string SIGNALING_TOKEN_PUBKEY = 'signaling_token_pubkey'; public const string HOSTED_SIGNALING_SERVER_NONCE = 'hosted_signaling_server_nonce'; public const string HOSTED_SIGNALING_SERVER_ACCOUNT_ID = 'hosted_signaling_server_account_id'; public const string HOSTED_SIGNALING_SERVER_ACCOUNT = 'hosted_signaling_server_account'; @@ -691,6 +693,10 @@ public function getSignalingServers(): array { * @return string */ public function getSignalingSecret(): string { + $secret = $this->appConfig->getAppValueString(self::SIGNALING_SERVERS_SECRET); + if (!empty($secret)) { + return $secret; + } $config = $this->appConfig->getAppValueArray(self::SIGNALING_SERVERS); return $config['secret'] ?? ''; } @@ -742,8 +748,9 @@ private function getSignalingTicketV1(?string $userId): string { } private function ensureSignalingTokenKeys(string $alg): void { - $secret = $this->appConfig->getAppValueString('signaling_token_privkey_' . strtolower($alg)); - if ($secret) { + $secret = $this->appConfig->getAppValueString(self::SIGNALING_TOKEN_PRIVKEY); + $currentAlg = $this->appConfig->getAppValueString(self::SIGNALING_TOKEN_ALG); + if ($secret && $alg === $currentAlg) { return; } @@ -776,8 +783,12 @@ private function ensureSignalingTokenKeys(string $alg): void { throw new \Exception('Unsupported algorithm ' . $alg); } - $this->appConfig->setAppValueString('signaling_token_privkey_' . strtolower($alg), $secret); - $this->appConfig->setAppValueString('signaling_token_pubkey_' . strtolower($alg), $public); + if ($alg !== $currentAlg) { + $this->appConfig->setAppValueString(self::SIGNALING_TOKEN_ALG, $alg); + } + + $this->appConfig->setAppValueString(self::SIGNALING_TOKEN_PRIVKEY, $secret); + $this->appConfig->setAppValueString(self::SIGNALING_TOKEN_PUBKEY, $public); } public function getSignalingTokenAlgorithm(): string { @@ -790,7 +801,7 @@ public function getSignalingTokenPrivateKey(?string $alg = null): string { } $this->ensureSignalingTokenKeys($alg); - return $this->appConfig->getAppValueString('signaling_token_privkey_' . strtolower($alg)); + return $this->appConfig->getAppValueString(self::SIGNALING_TOKEN_PRIVKEY); } public function getSignalingTokenPublicKey(?string $alg = null): string { @@ -799,7 +810,7 @@ public function getSignalingTokenPublicKey(?string $alg = null): string { } $this->ensureSignalingTokenKeys($alg); - return $this->appConfig->getAppValueString('signaling_token_pubkey_' . strtolower($alg)); + return $this->appConfig->getAppValueString(self::SIGNALING_TOKEN_PUBKEY); } public function deriveSignalingTokenPublicKey(#[SensitiveParameter] string $privateKey, string $alg): string { diff --git a/lib/ConfigLexicon.php b/lib/ConfigLexicon.php index ff60b29b4a1..d6ba2c6644a 100644 --- a/lib/ConfigLexicon.php +++ b/lib/ConfigLexicon.php @@ -234,6 +234,8 @@ public function getAppConfigs(): array { new Entry(Config::SIP_BRIDGE_DIALOUT, ValueType::BOOL, false, definition: 'SIP dial-out is allowed when a SIP bridge is configured', rename: 'sip_dialout'), new Entry(Config::SIGNALING_TICKET_SECRET, ValueType::STRING, '', definition: 'Secret used to secure the signaling tickets for guests (255 character random string)', flags: IAppConfig::FLAG_SENSITIVE), new Entry(Config::SIGNALING_TOKEN_ALG, ValueType::STRING, 'ES256', definition: 'Algorithm for the signaling tickets'), + new Entry(Config::SIGNALING_TOKEN_PRIVKEY, ValueType::STRING, '', definition: 'Private key for the signaling ticket creation by the server', flags: IAppConfig::FLAG_SENSITIVE), + new Entry(Config::SIGNALING_TOKEN_PUBKEY, ValueType::STRING, '', definition: 'Public key for the signaling ticket creation by the server'), new Entry(Config::SIGNALING_SERVERS, ValueType::ARRAY, ['servers' => [],'secret' => ''], definition: 'List of signaling servers, should be configured via the web interface or the OCC commands', flags: IAppConfig::FLAG_SENSITIVE), new Entry(Config::SIGNALING_SERVERS_SECRET, ValueType::STRING, '', flags: IAppConfig::FLAG_SENSITIVE), ]; diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index fd7614ef3b4..5b86208956a 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -195,8 +195,7 @@ protected function getTalkHashHeader(): array { json_encode($this->appConfig->getAppValueArray(Config::SIGNALING_SERVERS)), $this->appConfig->getAppValueString(Config::SIGNALING_TICKET_SECRET), $this->appConfig->getAppValueString(Config::SIGNALING_TOKEN_ALG), - $this->appConfig->getAppValueString('signaling_token_privkey_' . strtolower($this->appConfig->getAppValueString(Config::SIGNALING_TOKEN_ALG))), - $this->appConfig->getAppValueString('signaling_token_pubkey_' . strtolower($this->appConfig->getAppValueString(Config::SIGNALING_TOKEN_ALG))), + $this->appConfig->getAppValueString(Config::SIGNALING_TOKEN_PUBKEY), $this->appConfig->getAppValueBool(Config::CALL_RECORDING), json_encode($this->appConfig->getAppValueArray(Config::RECORDING_SERVERS)), json_encode($this->appConfig->getAppValueArray(Config::ALLOWED_GROUPS_TALK)), diff --git a/lib/Migration/RegenerateSignalingKeys.php b/lib/Migration/RegenerateSignalingKeys.php index 541bc840f97..3c4645c5a3c 100644 --- a/lib/Migration/RegenerateSignalingKeys.php +++ b/lib/Migration/RegenerateSignalingKeys.php @@ -38,8 +38,8 @@ public function run(IOutput $output): void { try { $this->talkConfig->getSignalingTicket(2, null); } catch (\Exception) { - $this->appConfig->setAppValueString('signaling_token_privkey_' . strtolower($alg), ''); - $this->appConfig->setAppValueString('signaling_token_pubkey_' . strtolower($alg), ''); + $this->appConfig->deleteAppValue(Config::SIGNALING_TOKEN_PRIVKEY); + $this->appConfig->deleteAppValue(Config::SIGNALING_TOKEN_PUBKEY); $this->talkConfig->getSignalingTokenPrivateKey($alg); } diff --git a/tests/php/ConfigTest.php b/tests/php/ConfigTest.php index d968409f0da..78f69e36a57 100644 --- a/tests/php/ConfigTest.php +++ b/tests/php/ConfigTest.php @@ -381,12 +381,12 @@ public function testSignalingTicketV2User(string $algo): void { $appConfig->setAppValueString(Config::SIGNALING_TOKEN_ALG, $algo); // Make sure new keys are generated. - $appConfig->deleteAppValue('signaling_token_privkey_' . strtolower($algo)); - $appConfig->deleteAppValue('signaling_token_pubkey_' . strtolower($algo)); + $appConfig->deleteAppValue(Config::SIGNALING_TOKEN_PRIVKEY); + $appConfig->deleteAppValue(Config::SIGNALING_TOKEN_PUBKEY); $ticket = $helper->getSignalingTicket(Config::SIGNALING_TICKET_V2, 'user1'); $this->assertNotNull($ticket); - $key = new Key($appConfig->getAppValueString('signaling_token_pubkey_' . strtolower($algo)), $algo); + $key = new Key($appConfig->getAppValueString(Config::SIGNALING_TOKEN_PUBKEY), $algo); $decoded = JWT::decode($ticket, $key); $this->assertEquals($now, $decoded->iat); @@ -414,12 +414,12 @@ public function testSignalingTicketV2Anonymous(string $algo): void { $appConfig->setAppValueString(Config::SIGNALING_TOKEN_ALG, $algo); // Make sure new keys are generated. - $appConfig->deleteAppValue('signaling_token_privkey_' . strtolower($algo)); - $appConfig->deleteAppValue('signaling_token_pubkey_' . strtolower($algo)); + $appConfig->deleteAppValue(Config::SIGNALING_TOKEN_PRIVKEY); + $appConfig->deleteAppValue(Config::SIGNALING_TOKEN_PUBKEY); $ticket = $helper->getSignalingTicket(Config::SIGNALING_TICKET_V2, null); $this->assertNotNull($ticket); - $key = new Key($appConfig->getAppValueString('signaling_token_pubkey_' . strtolower($algo)), $algo); + $key = new Key($appConfig->getAppValueString(Config::SIGNALING_TOKEN_PUBKEY), $algo); $decoded = JWT::decode($ticket, $key); $this->assertEquals($now, $decoded->iat); diff --git a/tests/php/Controller/SignalingControllerTest.php b/tests/php/Controller/SignalingControllerTest.php index a356088cc5d..d864ea88de0 100644 --- a/tests/php/Controller/SignalingControllerTest.php +++ b/tests/php/Controller/SignalingControllerTest.php @@ -567,8 +567,8 @@ private function validateBackendRandom($data, $random, $checksum) { return false; } - $this->appConfig->setAppValueString('signaling_servers_secret', 'MySecretValueMySecretValue1234567890'); - $signalingSecret = $this->appConfig->getAppValueString('signaling_servers_secret'); + $this->appConfig->setAppValueString(Config::SIGNALING_SERVERS_SECRET, 'MySecretValueMySecretValue1234567890'); + $signalingSecret = $this->appConfig->getAppValueString(Config::SIGNALING_SERVERS_SECRET); $hash = hash_hmac('sha256', $random . $data, $signalingSecret); return hash_equals($hash, strtolower((string)$checksum)); @@ -579,8 +579,8 @@ private function calculateBackendChecksum($data, $random) { return false; } - $this->appConfig->setAppValueString('signaling_servers_secret', 'MySecretValueMySecretValue1234567890'); - $signalingSecret = $this->appConfig->getAppValueString('signaling_servers_secret'); + $this->appConfig->setAppValueString(Config::SIGNALING_SERVERS_SECRET, 'MySecretValueMySecretValue1234567890'); + $signalingSecret = $this->appConfig->getAppValueString(Config::SIGNALING_SERVERS_SECRET); $hash = hash_hmac('sha256', $random . $data, $signalingSecret); return $hash; }