function checkAndActivate($fields) { try { $deferredParams = Otp::getDeferredParams(); if (!$deferredParams['USER_ID']) { throw new \Bitrix\Security\Mfa\OtpException(Loc::getMessage('SECURITY_AUTH_OTP_MANDATORY_UNKNOWN_ERROR')); } $otp = Otp::getByUser($deferredParams['USER_ID']); $binarySecret = pack('H*', $fields['SECRET']); $otp->regenerate($binarySecret)->syncParameters($fields['SYNC1'], $fields['SYNC2'])->save(); $deferredParams[Otp::REJECTED_KEY] = OTP::REJECT_BY_CODE; Otp::setDeferredParams($deferredParams); $result = array('status' => 'ok'); } catch (\Bitrix\Security\Mfa\OtpException $e) { $result = array('status' => 'error', 'error' => $e->getMessage()); } return $result; }
/** * @return array */ protected function toEdit() { /** @global CUser $USER */ global $USER; if (!$USER->IsAuthorized()) { return array('status' => 'error', 'error' => 'auth_error'); } if (!check_bitrix_sessid()) { return array('status' => 'error', 'error' => 'sessid_check_failed'); } if ($this->request['action'] !== 'otp_check_activate') { return array('status' => 'error', 'error' => 'unknown_action'); } if (!CModule::includeModule('security')) { return array('status' => 'error', 'error' => 'security_not_installed'); } try { $otp = Otp::getByUser($USER->getid()); $binarySecret = pack('H*', $this->request->getPost('secret')); $otp->regenerate($binarySecret)->syncParameters($this->request->getPost('sync1'), $this->request->getPost('sync2'))->save(); return array('status' => 'ok'); } catch (\Bitrix\Security\Mfa\OtpException $e) { return array('status' => 'error', 'error' => $e->getMessage()); } }
/** * @return array */ protected function toView() { /* @global CUser $USER */ global $USER; if (!CModule::includeModule('security')) { return array('MESSAGE' => Loc::getMessage('SECURITY_AUTH_OTP_MANDATORY_MODULE_ERROR')); } if (!Otp::isOtpRequiredByMandatory()) { return array('MESSAGE' => Loc::getMessage('SECURITY_AUTH_OTP_MANDATORY_NOT_REQUIRED')); } if ($USER->IsAuthorized()) { return array('MESSAGE' => Loc::getMessage('SECURITY_AUTH_OTP_MANDATORY_AUTH_ERROR')); } $deferredParams = Otp::getDeferredParams(); if (!$deferredParams['USER_ID']) { return array('MESSAGE' => Loc::getMessage('SECURITY_AUTH_OTP_MANDATORY_UNKNOWN_ERROR')); } $result = array(); $otp = Otp::getByUser($deferredParams['USER_ID']); $otp->regenerate(); $result['SECRET'] = $otp->getHexSecret(); $result['TYPE'] = $otp->getType(); $result['APP_SECRET'] = $otp->getAppSecret(); $result['APP_SECRET_SPACED'] = chunk_split($result['APP_SECRET'], 4, ' '); $result['PROVISION_URI'] = $otp->getProvisioningUri(); $result['SUCCESSFUL_URL'] = $this->arParams['SUCCESSFUL_URL']; $result['TWO_CODE_REQUIRED'] = $otp->getAlgorithm()->isTwoCodeRequired(); $result['OTP'] = $otp; return $result; }
/** * @param $arFields * @return bool */ public static function update($arFields) { global $USER; $userId = intval($arFields['USER_ID']); $result = null; if (!$userId) { return true; } $otp = Otp::getByUser($userId); $canAdminOtp = !Otp::isMandatoryUsing() && $userId == $USER->GetID() || $USER->CanDoOperation('security_edit_user_otp'); try { if ($arFields['ACTIVE'] !== 'Y' && $otp->isActivated()) { if ($canAdminOtp) { $otp->deactivate(); return true; } return false; } if ($arFields['DEACTIVATE_UNTIL'] > 0 && $otp->isActivated()) { if ($canAdminOtp) { $otp->deactivate((int) $arFields['DEACTIVATE_UNTIL']); return true; } return false; } $secret = substr(trim($arFields['SECRET']), 0, 64); if (!$secret) { if ($canAdminOtp) { $otp->delete(); return true; } return false; } if ($otp->getHexSecret() != $secret) { // We want to connect new device $binarySecret = pack('H*', $secret); $otp->regenerate($binarySecret); } if ($arFields['TYPE']) { $otp->setType($arFields['TYPE']); } $sync1 = trim($arFields['SYNC1']); $sync2 = trim($arFields['SYNC2']); if ($sync1 || $sync2) { $otp->syncParameters($sync1, $sync2); } $otp->setActive(true)->save(); } catch (OtpException $e) { /** @global CMain $APPLICATION */ global $APPLICATION; $ex = array(); $ex[] = array('id' => 'security_otp', 'text' => $e->getMessage()); $APPLICATION->ThrowException(new CAdminException($ex)); return false; } return true; }
<?php use Bitrix\Main\Config\Option; use Bitrix\Security\Mfa\Otp; use Bitrix\Security\Mfa\RecoveryCodesTable; require_once $_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_admin_before.php"; /** * @global CMain $APPLICATION * @global CUser $USER */ IncludeModuleLangFile(__FILE__); $request = Bitrix\Main\Context::getCurrent()->getRequest(); $userId = (int) ($request['user'] ?: $USER->getId()); $userOtp = Otp::getByUser($userId); if (!CModule::includeModule('security')) { ShowError('Security module not installed'); } if (!$userOtp->isActivated()) { ShowError('OTP inactive'); } if (!Otp::isRecoveryCodesEnabled()) { ShowError('OTP Recovery codes are disabled'); } if (!$userId || $userId != $USER->getId() && !$USER->CanDoOperation('security_edit_user_otp')) { ShowError('Not enough permissions'); } if (isset($request['action']) && $request['action'] === 'download') { $codes = getRecoveryCodes($userId); $response = ''; $counter = 0; foreach ($codes as $code) {
?> <tr> <td><?php echo GetMessage("SEC_OTP_NEW_ACCESS_DENIED"); ?> </td> </tr> <?php return; } if ($ID <= 0 || $USER->getID() != $ID && !$USER->CanDoOperation('security_edit_user_otp')) { return; } CJSCore::Init(array('qrcode', 'ajax', 'window')); $APPLICATION->AddHeadScript('/bitrix/js/security/admin/page/user-edit.js'); $otp = Otp::getByUser($ID); $deactivateUntil = $otp->getDeactivateUntil(); $availableTypes = Otp::getAvailableTypes(); $availableTypesDescription = \Bitrix\Security\Mfa\Otp::getTypesDescription(); $currentPage = $APPLICATION->GetCurPageParam(sprintf('%s_active_tab=%s', $tabControl->name, $tabControl->tabs[$tabControl->tabIndex]['DIV']), array(sprintf('%s_active_tab', $tabControl->name))); $deactivateDays = array(); $deactivateDays[] = GetMessage("SEC_OTP_NO_DAYS"); for ($i = 1; $i <= 10; $i++) { $deactivateDays[$i] = FormatDate("ddiff", time() - 60 * 60 * 24 * $i); } $jsMessages = array('SEC_OTP_ERROR_TITLE' => GetMessage('SEC_OTP_ERROR_TITLE'), 'SEC_OTP_UNKNOWN_ERROR' => GetMessage('SEC_OTP_UNKNOWN_ERROR')); $jsSettings = array('userId' => (int) $ID, 'successfulUrl' => $currentPage, 'deactivateDays' => $deactivateDays, 'availableTypes' => $availableTypesDescription); ?> <script id="otp-user-edit-messages" type="application/json"><?php echo \Bitrix\Main\Web\Json::encode($jsMessages); ?>
protected function checkRequirements() { /** @global CUser $USER */ global $USER; if (!$USER->IsAuthorized()) { return Loc::getMessage("SECURITY_USER_RECOVERY_CODES_AUTH_ERROR"); } if (!CModule::includeModule('security')) { return Loc::getMessage("SECURITY_USER_RECOVERY_CODES_MODULE_ERROR"); } $otp = Otp::getByUser($USER->getID()); if (!$otp->isActivated()) { return Loc::getMessage("SECURITY_USER_RECOVERY_CODES_OTP_NOT_ACTIVE"); } if (!Otp::isRecoveryCodesEnabled()) { return Loc::getMessage("SECURITY_USER_RECOVERY_CODES_DISABLED"); } return null; }
function regenerateRecoveryCodes($userId) { if (!Otp::getByUser($userId)->isActivated()) { ShowError('OTP inactive'); } CUserOptions::SetOption('security', 'recovery_codes_generated', time()); RecoveryCodesTable::regenerateCodes($userId); return getRecoveryCodes($userId, false); }
<?php /** * @global int $ID - Edited user id * @global \CUser $USER * @global CMain $APPLICATION * @global string $security_SYNC1 - First code * @global string $security_SYNC2 - Second code */ $securityWarningTmp = ""; $security_res = true; if ($ID > 0 && CModule::IncludeModule("security") && check_bitrix_sessid() && $USER->CanDoOperation('security_edit_user_otp') && $security_SYNC1) { try { $otp = \Bitrix\Security\Mfa\Otp::getByUser($ID); $otp->syncParameters($security_SYNC1, $security_SYNC2); $otp->save(); } catch (\Bitrix\Security\Mfa\OtpException $e) { $APPLICATION->ThrowException($e->getMessage()); $security_res = false; } }