diff --git a/src/modules/users/CheckPWQuality.cpp b/src/modules/users/CheckPWQuality.cpp index 038adf27b..267db0987 100644 --- a/src/modules/users/CheckPWQuality.cpp +++ b/src/modules/users/CheckPWQuality.cpp @@ -22,6 +22,16 @@ #include +#ifdef HAVE_LIBPWQUALITY +#include +#endif + +#include + +static void _default_cleanup() +{ +} + PasswordCheck::PasswordCheck() : m_message() , m_accept( []( const QString& s ){ return true; } ) @@ -87,6 +97,41 @@ DEFINE_CHECK_FUNC(maxLength) } #ifdef HAVE_LIBPWQUALITY +/** + * Class that acts as a RAII placeholder for pwquality_settings_t pointers. + * Gets a new pointer and ensures it is deleted only once; provides + * convenience functions for setting options and checking passwords. + */ +class PWSettingsHolder +{ +public: + PWSettingsHolder() + : m_settings( pwquality_default_settings() ) + { + } + + ~PWSettingsHolder() + { + cDebug() << "Freeing PWQ@" << (void *)m_settings; + pwquality_free_settings( m_settings ); + } + + /// Sets an option via the configuration string @p v, = style. + int set( const QString& v ) + { + return pwquality_set_option( m_settings, v.toUtf8().constData() ); + } + + /// Checks the given password @p pwd against the current configuration + int check( const QString& pwd ) + { + return pwquality_check(m_settings, pwd.toUtf8().constData(), nullptr, nullptr, nullptr); + } + +private: + pwquality_settings_t* m_settings; +} ; + DEFINE_CHECK_FUNC(libpwquality) { if ( !value.canConvert( QVariant::List ) ) @@ -97,10 +142,44 @@ DEFINE_CHECK_FUNC(libpwquality) QVariantList l = value.toList(); unsigned int requirement_count = 0; + auto settings = std::make_shared(); for ( const auto& v : l ) { - cDebug() << " .. " << v.type() << v; - // TODO: pass strings on to libpwquality + if (v.type() == QVariant::String) + { + QString option = v.toString(); + int r = settings->set( option ); + if (r) + cDebug() << " .. WARNING: unrecognized libpwquality setting" << option; + else + { + cDebug() << " .. libpwquality setting" << option; + ++requirement_count; + } + } + else + cDebug() << " .. WARNING: unrecognized libpwquality setting" << v; + } + + /* Something actually added? */ + if (requirement_count) + { + checks.push_back( + PasswordCheck( + [parent]() + { + return tr( "Password is too weak" ); + }, + [settings]( const QString& s ) + { + int r = settings->check( s ); + if ( r < 0 ) + cDebug() << "WARNING: libpwquality error" << r; + else if ( r < 40 ) + cDebug() << "Password strength" << r << "too low"; + return r >= 40; + } + ) ); } } #endif