getPeer(); try { if (OneTimePasswordManager::usesOtp($peer->getUuid())) { return $rpcRequest->produceError(StandardError::METHOD_NOT_ALLOWED, "Cannot set One Time Password when one is already set, use 'settingsUpdateOtp' instead"); } } catch (DatabaseOperationException $e) { throw new StandardException('Failed to check One Time Password due to an internal exception', StandardError::INTERNAL_SERVER_ERROR, $e); } try { $usesPassword = PasswordManager::usesPassword($peer); } catch (DatabaseOperationException $e) { throw new StandardException('Failed to check password usage due to an internal exception', StandardError::INTERNAL_SERVER_ERROR, $e); } // Password verification is required to set an OTP if a password is set if($usesPassword) { if(!$rpcRequest->containsParameter('password')) { return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'When a password is set, the current password must be provided to set an OTP'); } if(!Cryptography::validateSha512($rpcRequest->getParameter('password'))) { return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'The provided password is not a valid SHA-512 hash'); } try { if(!PasswordManager::verifyPassword($peer, $rpcRequest->getParameter('password'))) { return $rpcRequest->produceError(StandardError::FORBIDDEN, 'The provided password is incorrect'); } } catch(Exception $e) { throw new StandardException('Failed to verify password due to an internal exception', StandardError::INTERNAL_SERVER_ERROR, $e); } } try { // Create a new OTP and return the OTP URI to the client $totpUri = OneTimePasswordManager::createOtp($peer); // Remove the SET_PASSWORD flag & update the session flow if necessary SessionManager::updateFlow($request->getSession(), [SessionFlags::SET_OTP]); } catch(Exception $e) { throw new StandardException('Failed to set password due to an internal exception', StandardError::INTERNAL_SERVER_ERROR, $e); } return $rpcRequest->produceResponse($totpUri); } }