From eae502c629b8082c5a50410c50cf784c1ba3850f Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Sat, 21 Dec 2019 15:13:48 +0100 Subject: [PATCH] refactoring --- lam/lib/2factor.inc | 4 +- lam/lib/webauthn.inc | 208 +++++++++++++++++++++---------------------- 2 files changed, 105 insertions(+), 107 deletions(-) diff --git a/lam/lib/2factor.inc b/lam/lib/2factor.inc index 560067e3..d4499583 100644 --- a/lam/lib/2factor.inc +++ b/lam/lib/2factor.inc @@ -13,8 +13,6 @@ use \htmlOutputText; use \htmlDiv; use \LAMException; use Webauthn\PublicKeyCredentialCreationOptions; -use function LAM\LOGIN\WEBAUTHN\hasTokensRegistered; -use function LAM\LOGIN\WEBAUTHN\storeNewRegistration; /* This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) @@ -580,7 +578,7 @@ class WebauthnProvider extends BaseProvider { } $response = base64_decode($_POST['sig_response']); $registrationObject = PublicKeyCredentialCreationOptions::createFromString($_SESSION['webauthn_registration']); - if (storeNewRegistration($registrationObject, $response)) { + if ($webauthnManager->storeNewRegistration($registrationObject, $response)) { return true; } logNewMessage(LOG_ERR, 'Webauthn authentication failed'); diff --git a/lam/lib/webauthn.inc b/lam/lib/webauthn.inc index 81753416..0c79fd3a 100644 --- a/lam/lib/webauthn.inc +++ b/lam/lib/webauthn.inc @@ -119,6 +119,44 @@ class WebauthnManager { return $registrationObject; } + /** + * Verifies the registration and stores it in the database. + * + * @param PublicKeyCredentialCreationOptions $registration registration object + * @param string $clientResponse client response + * @return bool true if response is valid and registration succeeded + */ + public function storeNewRegistration($registration, $clientResponse) { + $decoder = $this->getCborDecoder(); + $tokenBindingHandler = new IgnoreTokenBindingHandler(); + $attestationSupportManager = $this->getAttestationSupportManager($decoder); + $attestationObjectLoader = $this->getAttestationObjectLoader($attestationSupportManager, $decoder); + $publicKeyCredentialLoader = $this->getPublicKeyCredentialLoader($attestationObjectLoader, $decoder); + $extensionOutputCheckerHandler = $this->getExtensionOutputChecker(); + $repository = new PublicKeyCredentialSourceRepositorySQLite(); + $responseValidator = new AuthenticatorAttestationResponseValidator( + $attestationSupportManager, $repository, $tokenBindingHandler, $extensionOutputCheckerHandler); + try { + $publicKeyCredential = $publicKeyCredentialLoader->load($clientResponse); + $authenticatorAttestationResponse = $publicKeyCredential->getResponse(); + if (!$authenticatorAttestationResponse instanceof AuthenticatorAttestationResponse) { + logNewMessage(LOG_ERR, 'Invalid webauthn response: ' . $clientResponse); + return false; + } + $symfonyRequest = Request::createFromGlobals(); + $psr17Factory = new Psr17Factory(); + $psrFactory = new PsrHttpFactory($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory); + $psr7Request = $psrFactory->createRequest($symfonyRequest); + $publicKeyCredentialSource = $responseValidator->check($authenticatorAttestationResponse, $registration, $psr7Request); + $repository->saveCredentialSource($publicKeyCredentialSource); + return true; + } + catch (\Throwable $exception) { + logNewMessage(LOG_ERR, 'Webauthn validation failed: ' . $exception->getMessage() . $exception->getTraceAsString()); + } + return false; + } + /** * Returns the user entity for the registration. * @@ -181,6 +219,72 @@ class WebauthnManager { return $keys; } + /** + * Returns a CBOR decoder. + * + * @return Decoder decoder + */ + private function getCborDecoder() { + return new Decoder(new TagObjectManager(), new OtherObjectManager()); + } + + /** + * Creates the attestation support manager. + * + * @param Decoder $decoder decoder + * @return AttestationStatementSupportManager manager + */ + private function getAttestationSupportManager($decoder) { + $manager = new AttestationStatementSupportManager(); + $manager->add(new NoneAttestationStatementSupport()); + $manager->add(new FidoU2FAttestationStatementSupport()); + $manager->add(new AndroidKeyAttestationStatementSupport($decoder)); + $manager->add(new TPMAttestationStatementSupport()); + $coseManager = new Manager(); + $coseManager->add(new ES256()); + $coseManager->add(new ES384()); + $coseManager->add(new ES512()); + $coseManager->add(new EdDSA()); + $coseManager->add(new RS1()); + $coseManager->add(new RS256()); + $coseManager->add(new RS384); + $coseManager->add(new RS512()); + $manager->add(new PackedAttestationStatementSupport($decoder, $coseManager)); + return $manager; + } + + /** + * Returns the attestation object loader. + * + * @param AttestationStatementSupportManager $manager support manager + * @param Decoder $decoder decoder + * @return AttestationObjectLoader attestation object loader + */ + private function getAttestationObjectLoader($manager, $decoder) { + return new AttestationObjectLoader($manager, $decoder); + } + + /** + * Creates the public key credential loader. + * + * @param AttestationObjectLoader $attestationObjectLoader attestation object loader + * @param Decoder $decoder decoder + * @return PublicKeyCredentialLoader public key credential loader + */ + private function getPublicKeyCredentialLoader($attestationObjectLoader, $decoder) { + return new PublicKeyCredentialLoader($attestationObjectLoader, $decoder); + } + + /** + * Returns the extension output checker handler. + * No extensions are checked at this time. + * + * @return ExtensionOutputCheckerHandler handler + */ + function getExtensionOutputChecker() { + return new ExtensionOutputCheckerHandler(); + } + /** * Returns the webauthn database. * @@ -192,110 +296,6 @@ class WebauthnManager { } -/** - * Verifies the registration and stores it in the database. - * - * @param PublicKeyCredentialCreationOptions $registration registration object - * @param string $clientResponse client response - * @return bool true if response is valid and registration succeeded - */ -function storeNewRegistration($registration, $clientResponse) { - $decoder = getCborDecoder(); - $tokenBindingHandler = new IgnoreTokenBindingHandler(); - $attestationSupportManager = getAttestationSupportManager($decoder); - $attestationObjectLoader = getAttestationObjectLoader($attestationSupportManager, $decoder); - $publicKeyCredentialLoader = getPublicKeyCredentialLoader($attestationObjectLoader, $decoder); - $extensionOutputCheckerHandler = getExtensionOutputChecker(); - $repository = new PublicKeyCredentialSourceRepositorySQLite(); - $responseValidator = new AuthenticatorAttestationResponseValidator( - $attestationSupportManager, $repository, $tokenBindingHandler, $extensionOutputCheckerHandler); - try { - $publicKeyCredential = $publicKeyCredentialLoader->load($clientResponse); - $authenticatorAttestationResponse = $publicKeyCredential->getResponse(); - if (!$authenticatorAttestationResponse instanceof AuthenticatorAttestationResponse) { - logNewMessage(LOG_ERR, 'Invalid webauthn response: ' . $clientResponse); - return false; - } - $symfonyRequest = Request::createFromGlobals(); - $psr17Factory = new Psr17Factory(); - $psrFactory = new PsrHttpFactory($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory); - $psr7Request = $psrFactory->createRequest($symfonyRequest); - $publicKeyCredentialSource = $responseValidator->check($authenticatorAttestationResponse, $registration, $psr7Request); - $repository->saveCredentialSource($publicKeyCredentialSource); - return true; - } - catch (\Throwable $exception) { - logNewMessage(LOG_ERR, 'Webauthn validation failed: ' . $exception->getMessage() . $exception->getTraceAsString()); - } - return false; -} - -/** - * Returns a CBOR decoder. - * - * @return Decoder decoder - */ -function getCborDecoder() { - return new Decoder(new TagObjectManager(), new OtherObjectManager()); -} - -/** - * Creates the attestation support manager. - * - * @param Decoder $decoder decoder - * @return AttestationStatementSupportManager manager - */ -function getAttestationSupportManager($decoder) { - $manager = new AttestationStatementSupportManager(); - $manager->add(new NoneAttestationStatementSupport()); - $manager->add(new FidoU2FAttestationStatementSupport()); - $manager->add(new AndroidKeyAttestationStatementSupport($decoder)); - $manager->add(new TPMAttestationStatementSupport()); - $coseManager = new Manager(); - $coseManager->add(new ES256()); - $coseManager->add(new ES384()); - $coseManager->add(new ES512()); - $coseManager->add(new EdDSA()); - $coseManager->add(new RS1()); - $coseManager->add(new RS256()); - $coseManager->add(new RS384); - $coseManager->add(new RS512()); - $manager->add(new PackedAttestationStatementSupport($decoder, $coseManager)); - return $manager; -} - -/** - * Returns the attestation object loader. - * - * @param AttestationStatementSupportManager $manager support manager - * @param Decoder $decoder decoder - * @return AttestationObjectLoader attestation object loader - */ -function getAttestationObjectLoader($manager, $decoder) { - return new AttestationObjectLoader($manager, $decoder); -} - -/** - * Creates the public key credential loader. - * - * @param AttestationObjectLoader $attestationObjectLoader attestation object loader - * @param Decoder $decoder decoder - * @return PublicKeyCredentialLoader public key credential loader - */ -function getPublicKeyCredentialLoader($attestationObjectLoader, $decoder) { - return new PublicKeyCredentialLoader($attestationObjectLoader, $decoder); -} - -/** - * Returns the extension output checker handler. - * No extensions are checked at this time. - * - * @return ExtensionOutputCheckerHandler handler - */ -function getExtensionOutputChecker() { - return new ExtensionOutputCheckerHandler(); -} - /** * Stores the public key credentials in the SQLite database. *