diff options
-rw-r--r-- | cui/Library_cui.mk | 3 | ||||
-rw-r--r-- | cui/source/dialogs/passwdomdlg.cxx | 13 | ||||
-rw-r--r-- | cui/source/inc/PasswordStrength.hxx | 28 | ||||
-rw-r--r-- | cui/source/util/PasswordStrength.cxx | 48 | ||||
-rw-r--r-- | include/sal/log-areas.dox | 2 | ||||
-rw-r--r-- | include/svl/PasswordHelper.hxx | 25 | ||||
-rw-r--r-- | svl/Library_svl.mk | 2 | ||||
-rw-r--r-- | svl/source/misc/PasswordHelper.cxx | 48 | ||||
-rw-r--r-- | uui/source/masterpasscrtdlg.cxx | 7 | ||||
-rw-r--r-- | uui/source/masterpasscrtdlg.hxx | 1 | ||||
-rw-r--r-- | uui/uiconfig/ui/setmasterpassworddlg.ui | 23 |
11 files changed, 108 insertions, 92 deletions
diff --git a/cui/Library_cui.mk b/cui/Library_cui.mk index 4a41c10baa2c..e122d2b734c4 100644 --- a/cui/Library_cui.mk +++ b/cui/Library_cui.mk @@ -71,13 +71,11 @@ $(eval $(call gb_Library_use_externals,cui,\ boost_headers \ $(call gb_Helper_optional,OPENCL,\ clew) \ - icui18n \ icuuc \ icu_headers \ libxml2 \ orcus-parser \ orcus \ - zxcvbn-c \ zxing \ )) @@ -244,7 +242,6 @@ $(eval $(call gb_Library_add_exception_objects,cui,\ cui/source/tabpages/tptrans \ cui/source/tabpages/transfrm \ cui/source/util/FontFeatures \ - cui/source/util/PasswordStrength \ cui/source/dialogs/widgettestdlg \ )) diff --git a/cui/source/dialogs/passwdomdlg.cxx b/cui/source/dialogs/passwdomdlg.cxx index 189738b45e3c..a7e95a29f3b4 100644 --- a/cui/source/dialogs/passwdomdlg.cxx +++ b/cui/source/dialogs/passwdomdlg.cxx @@ -18,10 +18,10 @@ */ #include <sfx2/objsh.hxx> +#include <svl/PasswordHelper.hxx> #include <vcl/svapp.hxx> #include <officecfg/Office/Common.hxx> #include <passwdomdlg.hxx> -#include <PasswordStrength.hxx> #include <strings.hrc> #include <dialmgr.hxx> @@ -41,14 +41,16 @@ IMPL_LINK_NOARG(PasswordToOpenModifyDialog, OkBtnClickHdl, weld::Button&, void) { if (m_oPasswordPolicy) { - if (!passwordCompliesPolicy(m_xPasswdToOpenED->get_text().toUtf8().getStr())) + if (!SvPasswordHelper::PasswordMeetsPolicy(m_xPasswdToOpenED->get_text(), + m_oPasswordPolicy)) { m_xPasswdToOpenED->grab_focus(); return; } if (m_xOpenReadonlyCB->get_active() - && !passwordCompliesPolicy(m_xPasswdToModifyED->get_text().toUtf8().getStr())) + && !SvPasswordHelper::PasswordMeetsPolicy(m_xPasswdToModifyED->get_text(), + m_oPasswordPolicy)) { m_xPasswdToModifyED->grab_focus(); return; @@ -115,7 +117,8 @@ IMPL_LINK(PasswordToOpenModifyDialog, ChangeHdl, weld::Entry&, rEntry, void) } assert(pIndicator); - bool bPasswordMeetsPolicy = passwordCompliesPolicy(aPasswordText.toUtf8().getStr()); + bool bPasswordMeetsPolicy + = SvPasswordHelper::PasswordMeetsPolicy(aPasswordText, m_oPasswordPolicy); if (pLevelBar) { rEntry.set_message_type(bPasswordMeetsPolicy ? weld::EntryMessageType::Normal @@ -126,7 +129,7 @@ IMPL_LINK(PasswordToOpenModifyDialog, ChangeHdl, weld::Entry&, rEntry, void) // if password doesn't meet policy cap the percentage at 70% if (pLevelBar) pLevelBar->set_percentage( - std::min(getPasswordStrengthPercentage(aPasswordText.toUtf8().getStr()), + std::min(SvPasswordHelper::GetPasswordStrengthPercentage(aPasswordText), bPasswordMeetsPolicy ? std::numeric_limits<double>::max() : 70.0)); if (m_nMaxPasswdLen) diff --git a/cui/source/inc/PasswordStrength.hxx b/cui/source/inc/PasswordStrength.hxx deleted file mode 100644 index e8c9e86a83cb..000000000000 --- a/cui/source/inc/PasswordStrength.hxx +++ /dev/null @@ -1,28 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -/** Get password strength percentage - - Maps the received password entropy bits to password strength percentage. - 0 bits -> 0% - >= 112 bits -> 100% - - @param pPassword null terminated password string. - @returns Password strength percentage in the range [0.0, 100.0] -*/ -double getPasswordStrengthPercentage(const char* pPassword); - -/** Checks if the password meets the password policies - - @param pPassword null terminated password string. - @returns true if password meets the policy or there is no policy enforced. -*/ -bool passwordCompliesPolicy(const char* pPassword); - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/util/PasswordStrength.cxx b/cui/source/util/PasswordStrength.cxx deleted file mode 100644 index 678ad2f74e76..000000000000 --- a/cui/source/util/PasswordStrength.cxx +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include <PasswordStrength.hxx> -#include <officecfg/Office/Common.hxx> -#include <unicode/regex.h> -#include <unicode/unistr.h> -#include <unicode/errorcode.h> -#include <sal/log.hxx> -#include <zxcvbn.h> - -double getPasswordStrengthPercentage(const char* pPassword) -{ - static constexpr double fMaxStrengthBits = 112.0; - return std::min(100.0, ZxcvbnMatch(pPassword, nullptr, nullptr) * 100.0 / fMaxStrengthBits); -} - -bool passwordCompliesPolicy(const char* pPassword) -{ - std::optional<OUString> oPasswordPolicy - = officecfg::Office::Common::Security::Scripting::PasswordPolicy::get(); - if (oPasswordPolicy) - { - icu::ErrorCode aStatus; - icu::UnicodeString sPassword(pPassword); - icu::UnicodeString sRegex(oPasswordPolicy->getStr()); - icu::RegexMatcher aRegexMatcher(sRegex, sPassword, 0, aStatus); - - if (aRegexMatcher.matches(aStatus)) - return true; - - if (aStatus.isFailure()) - { - SAL_INFO("cui.util", "Password policy regular expression failed with error: " - << aStatus.errorName()); - } - return false; - } - return true; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox index 0b3907e08610..0315b006f333 100644 --- a/include/sal/log-areas.dox +++ b/include/sal/log-areas.dox @@ -128,7 +128,6 @@ certain functionality. @li @c cui.factory @li @c cui.options @li @c cui.tabpages -@li @c cui.util @section drawinglayer @@ -388,6 +387,7 @@ certain functionality. @li @c svl @li @c svl.crypto @li @c svl.items +@li @c svl.misc @li @c svl.numbers @section svtools diff --git a/include/svl/PasswordHelper.hxx b/include/svl/PasswordHelper.hxx index aa7e55867343..405b3962aab6 100644 --- a/include/svl/PasswordHelper.hxx +++ b/include/svl/PasswordHelper.hxx @@ -23,6 +23,7 @@ #include <sal/config.h> #include <string_view> +#include <optional> #include <svl/svldllapi.h> #include <sal/types.h> @@ -48,6 +49,30 @@ public: ODF 1.2, requiring UTF-8 encoding. */ SVL_DLLPUBLIC static bool CompareHashPassword(const css::uno::Sequence<sal_Int8>& rOldPassHash, std::u16string_view sNewPass); + + /** Get password strength percentage + + Maps the calculated password entropy bit amount to password strength percentage: + 0 bits -> 0% + >= 112 bits -> 100% + + @param pPassword null terminated password string. + @returns Password strength percentage in the range [0.0, 100.0] + */ + SVL_DLLPUBLIC static double GetPasswordStrengthPercentage(const char* pPassword); + SVL_DLLPUBLIC static double GetPasswordStrengthPercentage(const OUString& aPassword); + + /** Checks if the password meets the password policies + + @param pPassword null terminated password string. + @param oPasswordPolicy Regular expression string that defines the password policy. + + @returns true if password meets the policy or there is no policy enforced. + */ + SVL_DLLPUBLIC static bool PasswordMeetsPolicy(const char* pPassword, + const std::optional<OUString>& oPasswordPolicy); + SVL_DLLPUBLIC static bool PasswordMeetsPolicy(const OUString& aPassword, + const std::optional<OUString>& oPasswordPolicy); }; #endif diff --git a/svl/Library_svl.mk b/svl/Library_svl.mk index aee540d56514..56923d712ced 100644 --- a/svl/Library_svl.mk +++ b/svl/Library_svl.mk @@ -25,9 +25,11 @@ $(eval $(call gb_Library_use_externals,svl,\ curl) \ dtoa \ icu_headers \ + icui18n \ icuuc \ mdds_headers \ libxml2 \ + zxcvbn-c \ )) $(eval $(call gb_Library_set_componentfile,svl,svl/util/svl,services)) diff --git a/svl/source/misc/PasswordHelper.cxx b/svl/source/misc/PasswordHelper.cxx index 41d7bf1ea68b..cfae72f64937 100644 --- a/svl/source/misc/PasswordHelper.cxx +++ b/svl/source/misc/PasswordHelper.cxx @@ -22,6 +22,11 @@ #include <comphelper/hash.hxx> #include <rtl/digest.h> #include <memory> +#include <unicode/regex.h> +#include <unicode/unistr.h> +#include <unicode/errorcode.h> +#include <zxcvbn.h> +#include <sal/log.hxx> using namespace com::sun::star; @@ -129,4 +134,47 @@ bool SvPasswordHelper::CompareHashPassword(const uno::Sequence<sal_Int8>& rOldPa return bResult; } +double SvPasswordHelper::GetPasswordStrengthPercentage(const char* pPassword) +{ + // Entropy bits corresponding to 100% password strength + static constexpr double fMaxPassStrengthEntorpyBits = 112.0; + return std::min(100.0, + ZxcvbnMatch(pPassword, nullptr, nullptr) * 100.0 / fMaxPassStrengthEntorpyBits); +} + +double SvPasswordHelper::GetPasswordStrengthPercentage(const OUString& aPassword) +{ + OString aPasswordUtf8 = aPassword.toUtf8(); + return GetPasswordStrengthPercentage(aPasswordUtf8.getStr()); +} + +bool SvPasswordHelper::PasswordMeetsPolicy(const char* pPassword, + const std::optional<OUString>& oPasswordPolicy) +{ + if (oPasswordPolicy) + { + icu::ErrorCode aStatus; + icu::UnicodeString sPassword(pPassword); + icu::UnicodeString sRegex(oPasswordPolicy->getStr()); + icu::RegexMatcher aRegexMatcher(sRegex, sPassword, 0, aStatus); + + if (aRegexMatcher.matches(aStatus)) + return true; + + SAL_WARN_IF( + aStatus.isFailure(), "svl.misc", + "Password policy regular expression failed with error: " << aStatus.errorName()); + + return false; + } + return true; +} + +bool SvPasswordHelper::PasswordMeetsPolicy(const OUString& aPassword, + const std::optional<OUString>& oPasswordPolicy) +{ + OString aPasswordUtf8 = aPassword.toUtf8(); + return PasswordMeetsPolicy(aPasswordUtf8.getStr(), oPasswordPolicy); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/masterpasscrtdlg.cxx b/uui/source/masterpasscrtdlg.cxx index 4801bec28f85..2216ea5a1d48 100644 --- a/uui/source/masterpasscrtdlg.cxx +++ b/uui/source/masterpasscrtdlg.cxx @@ -21,6 +21,7 @@ #include <vcl/svapp.hxx> #include <vcl/weld.hxx> #include <strings.hrc> +#include <svl/PasswordHelper.hxx> #include "masterpasscrtdlg.hxx" // MasterPasswordCreateDialog--------------------------------------------------- @@ -28,7 +29,10 @@ IMPL_LINK_NOARG(MasterPasswordCreateDialog, EditHdl_Impl, weld::Entry&, void) { - m_xOKBtn->set_sensitive(m_xEDMasterPasswordCrt->get_text().getLength() >= 1); + OUString aPasswordText = m_xEDMasterPasswordCrt->get_text(); + m_xOKBtn->set_sensitive(aPasswordText.getLength() >= 1); + m_xPasswdStrengthBar->set_percentage( + SvPasswordHelper::GetPasswordStrengthPercentage(aPasswordText)); } IMPL_LINK_NOARG(MasterPasswordCreateDialog, OKHdl_Impl, weld::Button&, void) @@ -55,6 +59,7 @@ MasterPasswordCreateDialog::MasterPasswordCreateDialog(weld::Window* pParent, co , m_xEDMasterPasswordCrt(m_xBuilder->weld_entry("password1")) , m_xEDMasterPasswordRepeat(m_xBuilder->weld_entry("password2")) , m_xOKBtn(m_xBuilder->weld_button("ok")) + , m_xPasswdStrengthBar(m_xBuilder->weld_level_bar("password1levelbar")) { m_xOKBtn->set_sensitive(false); m_xOKBtn->connect_clicked( LINK( this, MasterPasswordCreateDialog, OKHdl_Impl ) ); diff --git a/uui/source/masterpasscrtdlg.hxx b/uui/source/masterpasscrtdlg.hxx index a8695fc1ed27..f7f01cda79cc 100644 --- a/uui/source/masterpasscrtdlg.hxx +++ b/uui/source/masterpasscrtdlg.hxx @@ -29,6 +29,7 @@ private: std::unique_ptr<weld::Entry> m_xEDMasterPasswordCrt; std::unique_ptr<weld::Entry> m_xEDMasterPasswordRepeat; std::unique_ptr<weld::Button> m_xOKBtn; + std::unique_ptr<weld::LevelBar> m_xPasswdStrengthBar; DECL_LINK(OKHdl_Impl, weld::Button&, void); DECL_LINK(EditHdl_Impl, weld::Entry&, void); diff --git a/uui/uiconfig/ui/setmasterpassworddlg.ui b/uui/uiconfig/ui/setmasterpassworddlg.ui index 0402b4de7b35..52cec48eb30a 100644 --- a/uui/uiconfig/ui/setmasterpassworddlg.ui +++ b/uui/uiconfig/ui/setmasterpassworddlg.ui @@ -130,18 +130,29 @@ </packing> </child> <child> + <object class="GtkLevelBar" id="password1levelbar"> + <property name="visible">True</property> + <property name="can-focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> <object class="GtkLabel" id="label3"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label" translatable="yes" context="setmasterpassworddlg|label3">_Reenter password:</property> - <property name="use_underline">True</property> - <property name="mnemonic_widget">password2</property> + <property name="use-underline">True</property> + <property name="mnemonic-widget">password2</property> <property name="xalign">0</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">3</property> + <property name="position">4</property> </packing> </child> <child> @@ -161,7 +172,7 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">4</property> + <property name="position">5</property> </packing> </child> <child> @@ -180,7 +191,7 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">5</property> + <property name="position">6</property> </packing> </child> </object> |