Skip to content

Commit eae1896

Browse files
Refactor OAuth\Server::generateKeys() for readability/debugging (#19688)
* Refactor OAuth\Server::generateKeys() for readability/debugging * Do no delete partial data
1 parent 8776788 commit eae1896

File tree

1 file changed

+93
-37
lines changed

1 file changed

+93
-37
lines changed

src/Glpi/OAuth/Server.php

Lines changed: 93 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,14 @@
4242
use League\OAuth2\Server\Grant\PasswordGrant;
4343
use League\OAuth2\Server\Grant\RefreshTokenGrant;
4444
use League\OAuth2\Server\ResourceServer;
45+
use RuntimeException;
46+
use Throwable;
4547

4648
final class Server
4749
{
50+
private const PRIVATE_KEY_PATH = GLPI_CONFIG_DIR . '/oauth.pem';
51+
private const PUBLIC_KEY_PATH = GLPI_CONFIG_DIR . '/oauth.pub';
52+
4853
/**
4954
* @var ClientRepository
5055
*/
@@ -177,43 +182,94 @@ public static function getScopeDescriptions(): array
177182

178183
public static function generateKeys(): void
179184
{
180-
$private_key_path = GLPI_CONFIG_DIR . '/oauth.pem';
181-
$public_key_path = GLPI_CONFIG_DIR . '/oauth.pub';
182-
if (!file_exists($private_key_path) && !file_exists($public_key_path)) {
183-
$config = [
184-
'digest_alg' => 'sha512',
185-
'private_key_bits' => 2048,
186-
'private_key_type' => OPENSSL_KEYTYPE_RSA,
187-
];
188-
$success = false;
189-
$error = null;
190-
$res = openssl_pkey_new($config);
191-
if ($res && openssl_pkey_export_to_file($res, $private_key_path)) {
192-
// Export public key to the public key file
193-
$pubkey = openssl_pkey_get_details($res);
194-
if ($pubkey !== false && file_put_contents($public_key_path, $pubkey['key']) === strlen($pubkey['key'])) {
195-
if (chmod($private_key_path, 0o660) && chmod($public_key_path, 0o660)) {
196-
$success = true;
197-
} else {
198-
$error = 'Unable to set permissions on the generated keys';
199-
}
200-
} else {
201-
$error = 'Unable to export public key';
202-
}
203-
} else {
204-
$error = 'Unable to generate keys';
205-
}
206-
207-
if (!$success) {
208-
// Key files didn't exist before and an error occured. We should try removing any that were created to be able to retry later
209-
if (file_exists($private_key_path)) {
210-
unlink($private_key_path);
211-
}
212-
if (file_exists($public_key_path)) {
213-
unlink($public_key_path);
214-
}
215-
throw new \RuntimeException($error);
216-
}
185+
if (
186+
file_exists(self::PRIVATE_KEY_PATH)
187+
&& file_exists(self::PUBLIC_KEY_PATH)
188+
) {
189+
// Keys are already generated
190+
return;
191+
}
192+
193+
// Partial data: unsure how to proceed, let the user review the files.
194+
if (
195+
file_exists(self::PRIVATE_KEY_PATH)
196+
&& !file_exists(self::PUBLIC_KEY_PATH)
197+
) {
198+
throw new RuntimeException("Mising file: " . self::PUBLIC_KEY_PATH);
199+
}
200+
if (
201+
file_exists(self::PUBLIC_KEY_PATH)
202+
&& !file_exists(self::PRIVATE_KEY_PATH)
203+
) {
204+
throw new RuntimeException("Mising file: " . self::PRIVATE_KEY_PATH);
205+
}
206+
207+
// If we reach this point, both file are missing and must be generated
208+
try {
209+
// Generate keys
210+
self::doGenerateKeys();
211+
} catch (Throwable $e) {
212+
// Make sure we don't save any partially generated data
213+
self::deleteKeys();
214+
215+
// Propagate exception
216+
throw $e;
217+
}
218+
}
219+
220+
private static function doGenerateKeys(): void
221+
{
222+
$config = [
223+
'digest_alg' => 'sha512',
224+
'private_key_bits' => 2048,
225+
'private_key_type' => OPENSSL_KEYTYPE_RSA,
226+
];
227+
228+
// Generate key
229+
$key = openssl_pkey_new($config);
230+
if ($key === false) {
231+
$error = openssl_error_string();
232+
throw new RuntimeException("Unable to generate keys: $error");
233+
}
234+
235+
// Export private key to file
236+
if (!openssl_pkey_export_to_file($key, self::PRIVATE_KEY_PATH)) {
237+
$error = openssl_error_string();
238+
throw new RuntimeException("Unable to export private key: $error");
239+
}
240+
241+
// Get public key
242+
$pubkey = openssl_pkey_get_details($key);
243+
if ($pubkey === false) {
244+
$error = openssl_error_string();
245+
throw new RuntimeException("Unable to get public key details: $error");
246+
}
247+
248+
// Export public key to file
249+
$written_bytes = file_put_contents(self::PUBLIC_KEY_PATH, $pubkey['key']);
250+
if (
251+
$written_bytes === false
252+
|| $written_bytes !== strlen($pubkey['key'])
253+
) {
254+
throw new RuntimeException('Unable to export public key');
255+
}
256+
257+
// Set permisisons to both key files
258+
if (
259+
!chmod(self::PRIVATE_KEY_PATH, 0o660)
260+
|| !chmod(self::PUBLIC_KEY_PATH, 0o660)
261+
) {
262+
throw new RuntimeException('Unable to set permissions on the generated keys');
263+
}
264+
}
265+
266+
private static function deleteKeys(): void
267+
{
268+
if (file_exists(self::PRIVATE_KEY_PATH)) {
269+
unlink(self::PRIVATE_KEY_PATH);
270+
}
271+
if (file_exists(self::PUBLIC_KEY_PATH)) {
272+
unlink(self::PUBLIC_KEY_PATH);
217273
}
218274
}
219275
}

0 commit comments

Comments
 (0)