commit
ef5fffc70e
15
CHANGES
15
CHANGES
@ -6,13 +6,22 @@ website will have to do for older versions.
|
|||||||
# 3.2.16 (unreleased) #
|
# 3.2.16 (unreleased) #
|
||||||
|
|
||||||
This release contains contributions from (alphabetically by first name):
|
This release contains contributions from (alphabetically by first name):
|
||||||
- No other contributors this time around.
|
- Bill Auger
|
||||||
|
|
||||||
## Core ##
|
## Core ##
|
||||||
- No changes to core functionality
|
- Some obscure build scenarios which would lead to bogus module-is-
|
||||||
|
misconfigured messages on startup have been resolved.
|
||||||
|
|
||||||
## Modules ##
|
## Modules ##
|
||||||
- No changes to module functionality
|
- The explanatory messages on the *users* page have moved to tooltips,
|
||||||
|
and placeholder text has been added to the fields. #1202
|
||||||
|
- The bad-password messages in the *users* page have been improved. #1261
|
||||||
|
- Password-checking in the *users* module has been substantially
|
||||||
|
changed. A new key *allowWeakPasswords* can be used to introduce
|
||||||
|
an additional checkbox to the page, which can then be used to
|
||||||
|
switch off strict password checking. (Thanks to Bill Auger)
|
||||||
|
- The icons used in password warnings on the *users* page have been
|
||||||
|
changed to the colorful status icons (rather than the thin red X).
|
||||||
|
|
||||||
|
|
||||||
# 3.2.15 (2019-10-11) #
|
# 3.2.15 (2019-10-11) #
|
||||||
|
@ -75,26 +75,6 @@ setButtonIcon( QPushButton* button, const QString& name )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Creates a button with a given icon-name
|
|
||||||
*
|
|
||||||
* Creates a new button as child of @p parent.
|
|
||||||
* Sets the named icon, if it exists, onto the button.
|
|
||||||
* Returns the new button.
|
|
||||||
*
|
|
||||||
* There is a QPushButton constructor that takes an icon,
|
|
||||||
* but it also needs a text and we've got translations
|
|
||||||
* to worry about as well as state.
|
|
||||||
*/
|
|
||||||
static inline QPushButton*
|
|
||||||
makeButton( QWidget* parent, const QString& name, const QString& label )
|
|
||||||
{
|
|
||||||
QPushButton* button = new QPushButton( parent );
|
|
||||||
button->setObjectName( name );
|
|
||||||
button->setText( label );
|
|
||||||
setButtonIcon( button, name );
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewManager::ViewManager( QObject* parent )
|
ViewManager::ViewManager( QObject* parent )
|
||||||
: QObject( parent )
|
: QObject( parent )
|
||||||
, m_currentStep( 0 )
|
, m_currentStep( 0 )
|
||||||
@ -110,9 +90,12 @@ ViewManager::ViewManager( QObject* parent )
|
|||||||
mainLayout->addWidget( m_stack );
|
mainLayout->addWidget( m_stack );
|
||||||
|
|
||||||
// Create buttons and sets an initial icon; the icons may change
|
// Create buttons and sets an initial icon; the icons may change
|
||||||
m_back = makeButton( m_widget, QStringLiteral( "go-previous" ), tr( "&Back" ) );
|
m_back = new QPushButton( getButtonIcon( QStringLiteral( "go-previous" ) ), tr( "&Back" ), m_widget );
|
||||||
m_next = makeButton( m_widget, QStringLiteral( "go-next" ), tr( "&Next" ) );
|
m_back->setObjectName( "view-button-back" );
|
||||||
m_quit = makeButton( m_widget, QStringLiteral( "dialog-cancel" ), tr( "&Cancel" ) );
|
m_next = new QPushButton( getButtonIcon( QStringLiteral( "go-next" ) ), tr( "&Next" ), m_widget );
|
||||||
|
m_next->setObjectName( "view-button-next" );
|
||||||
|
m_quit = new QPushButton( getButtonIcon( QStringLiteral( "dialog-cancel" ) ), tr( "&Cancel" ), m_widget );
|
||||||
|
m_quit->setObjectName( "view-button-cancel" );
|
||||||
|
|
||||||
CALAMARES_RETRANSLATE_SLOT( &ViewManager::updateButtonLabels )
|
CALAMARES_RETRANSLATE_SLOT( &ViewManager::updateButtonLabels )
|
||||||
|
|
||||||
|
@ -32,12 +32,12 @@
|
|||||||
|
|
||||||
PasswordCheck::PasswordCheck()
|
PasswordCheck::PasswordCheck()
|
||||||
: m_message()
|
: m_message()
|
||||||
, m_accept( []( const QString& ){ return true; } )
|
, m_accept( []( const QString& ) { return true; } )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PasswordCheck::PasswordCheck( const QString& m, AcceptFunc a )
|
PasswordCheck::PasswordCheck( const QString& m, AcceptFunc a )
|
||||||
: m_message( [m](){ return m; } )
|
: m_message( [m]() { return m; } )
|
||||||
, m_accept( a )
|
, m_accept( a )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -52,21 +52,14 @@ DEFINE_CHECK_FUNC( minLength )
|
|||||||
{
|
{
|
||||||
int minLength = -1;
|
int minLength = -1;
|
||||||
if ( value.canConvert( QVariant::Int ) )
|
if ( value.canConvert( QVariant::Int ) )
|
||||||
|
{
|
||||||
minLength = value.toInt();
|
minLength = value.toInt();
|
||||||
|
}
|
||||||
if ( minLength > 0 )
|
if ( minLength > 0 )
|
||||||
{
|
{
|
||||||
cDebug() << Logger::SubEntry << "minLength set to" << minLength;
|
cDebug() << Logger::SubEntry << "minLength set to" << minLength;
|
||||||
checks.push_back(
|
checks.push_back( PasswordCheck( []() { return QCoreApplication::translate( "PWQ", "Password is too short" ); },
|
||||||
PasswordCheck(
|
[minLength]( const QString& s ) { return s.length() >= minLength; } ) );
|
||||||
[]()
|
|
||||||
{
|
|
||||||
return QCoreApplication::translate( "PWQ", "Password is too short" );
|
|
||||||
},
|
|
||||||
[minLength]( const QString& s )
|
|
||||||
{
|
|
||||||
return s.length() >= minLength;
|
|
||||||
}
|
|
||||||
) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,21 +67,14 @@ DEFINE_CHECK_FUNC( maxLength )
|
|||||||
{
|
{
|
||||||
int maxLength = -1;
|
int maxLength = -1;
|
||||||
if ( value.canConvert( QVariant::Int ) )
|
if ( value.canConvert( QVariant::Int ) )
|
||||||
|
{
|
||||||
maxLength = value.toInt();
|
maxLength = value.toInt();
|
||||||
|
}
|
||||||
if ( maxLength > 0 )
|
if ( maxLength > 0 )
|
||||||
{
|
{
|
||||||
cDebug() << Logger::SubEntry << "maxLength set to" << maxLength;
|
cDebug() << Logger::SubEntry << "maxLength set to" << maxLength;
|
||||||
checks.push_back(
|
checks.push_back( PasswordCheck( []() { return QCoreApplication::translate( "PWQ", "Password is too long" ); },
|
||||||
PasswordCheck(
|
[maxLength]( const QString& s ) { return s.length() <= maxLength; } ) );
|
||||||
[]()
|
|
||||||
{
|
|
||||||
return QCoreApplication::translate("PWQ", "Password is too long" );
|
|
||||||
},
|
|
||||||
[maxLength]( const QString& s )
|
|
||||||
{
|
|
||||||
return s.length() <= maxLength;
|
|
||||||
}
|
|
||||||
) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,15 +87,17 @@ DEFINE_CHECK_FUNC( maxLength )
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/// @brief Handle libpwquality using void* to represent a long
|
/// @brief Handle libpwquality using void* to represent a long
|
||||||
static inline long mungeLong( void* p )
|
static inline long
|
||||||
|
mungeLong( void* p )
|
||||||
{
|
{
|
||||||
return static_cast<long>( reinterpret_cast<intptr_t>( p ) );
|
return static_cast< long >( reinterpret_cast< intptr_t >( p ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Handle libpwquality using void* to represent a char*
|
/// @brief Handle libpwquality using void* to represent a char*
|
||||||
static inline const char* mungeString( void* p )
|
static inline const char*
|
||||||
|
mungeString( void* p )
|
||||||
{
|
{
|
||||||
return reinterpret_cast<const char*>( p );
|
return reinterpret_cast< const char* >( p );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,16 +116,10 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~PWSettingsHolder()
|
~PWSettingsHolder() { pwquality_free_settings( m_settings ); }
|
||||||
{
|
|
||||||
pwquality_free_settings( m_settings );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets an option via the configuration string @p v, <key>=<value> style.
|
/// Sets an option via the configuration string @p v, <key>=<value> style.
|
||||||
int set( const QString& v )
|
int set( const QString& v ) { return pwquality_set_option( m_settings, v.toUtf8().constData() ); }
|
||||||
{
|
|
||||||
return pwquality_set_option( m_settings, v.toUtf8().constData() );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks the given password @p pwd against the current configuration
|
/// Checks the given password @p pwd against the current configuration
|
||||||
int check( const QString& pwd )
|
int check( const QString& pwd )
|
||||||
@ -148,10 +130,7 @@ public:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasExplanation() const
|
bool hasExplanation() const { return m_rv < 0; }
|
||||||
{
|
|
||||||
return m_rv < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is roughly the same as the function pwquality_strerror,
|
/* This is roughly the same as the function pwquality_strerror,
|
||||||
* only with QStrings instead, and using the Qt translation scheme.
|
* only with QStrings instead, and using the Qt translation scheme.
|
||||||
@ -164,16 +143,21 @@ public:
|
|||||||
m_auxerror = nullptr;
|
m_auxerror = nullptr;
|
||||||
|
|
||||||
if ( m_rv >= arbitrary_minimum_strength )
|
if ( m_rv >= arbitrary_minimum_strength )
|
||||||
|
{
|
||||||
return QString();
|
return QString();
|
||||||
|
}
|
||||||
if ( m_rv >= 0 )
|
if ( m_rv >= 0 )
|
||||||
return QCoreApplication::translate( "PWQ", "Password is too weak" );
|
{
|
||||||
|
return QCoreApplication::translate( "PWQ", "Password is too weak" );
|
||||||
|
}
|
||||||
|
|
||||||
switch ( m_rv )
|
switch ( m_rv )
|
||||||
{
|
{
|
||||||
case PWQ_ERROR_MEM_ALLOC:
|
case PWQ_ERROR_MEM_ALLOC:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
{
|
{
|
||||||
QString s = QCoreApplication::translate( "PWQ", "Memory allocation error when setting '%1'" ).arg( mungeString( auxerror ) );
|
QString s = QCoreApplication::translate( "PWQ", "Memory allocation error when setting '%1'" )
|
||||||
|
.arg( mungeString( auxerror ) );
|
||||||
free( auxerror );
|
free( auxerror );
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -189,58 +173,94 @@ public:
|
|||||||
case PWQ_ERROR_USER_CHECK:
|
case PWQ_ERROR_USER_CHECK:
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains the user name in some form" );
|
return QCoreApplication::translate( "PWQ", "The password contains the user name in some form" );
|
||||||
case PWQ_ERROR_GECOS_CHECK:
|
case PWQ_ERROR_GECOS_CHECK:
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains words from the real name of the user in some form" );
|
return QCoreApplication::translate(
|
||||||
|
"PWQ", "The password contains words from the real name of the user in some form" );
|
||||||
case PWQ_ERROR_BAD_WORDS:
|
case PWQ_ERROR_BAD_WORDS:
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains forbidden words in some form" );
|
return QCoreApplication::translate( "PWQ", "The password contains forbidden words in some form" );
|
||||||
case PWQ_ERROR_MIN_DIGITS:
|
case PWQ_ERROR_MIN_DIGITS:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains less than %1 digits" ).arg( mungeLong( auxerror ) );
|
{
|
||||||
|
return QCoreApplication::translate( "PWQ", "The password contains less than %1 digits" )
|
||||||
|
.arg( mungeLong( auxerror ) );
|
||||||
|
}
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains too few digits" );
|
return QCoreApplication::translate( "PWQ", "The password contains too few digits" );
|
||||||
case PWQ_ERROR_MIN_UPPERS:
|
case PWQ_ERROR_MIN_UPPERS:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains less than %1 uppercase letters" ).arg( mungeLong( auxerror ) );
|
{
|
||||||
|
return QCoreApplication::translate( "PWQ", "The password contains less than %1 uppercase letters" )
|
||||||
|
.arg( mungeLong( auxerror ) );
|
||||||
|
}
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains too few uppercase letters" );
|
return QCoreApplication::translate( "PWQ", "The password contains too few uppercase letters" );
|
||||||
case PWQ_ERROR_MIN_LOWERS:
|
case PWQ_ERROR_MIN_LOWERS:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains less than %1 lowercase letters" ).arg( mungeLong( auxerror ) );
|
{
|
||||||
|
return QCoreApplication::translate( "PWQ", "The password contains less than %1 lowercase letters" )
|
||||||
|
.arg( mungeLong( auxerror ) );
|
||||||
|
}
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains too few lowercase letters" );
|
return QCoreApplication::translate( "PWQ", "The password contains too few lowercase letters" );
|
||||||
case PWQ_ERROR_MIN_OTHERS:
|
case PWQ_ERROR_MIN_OTHERS:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains less than %1 non-alphanumeric characters" ).arg( mungeLong( auxerror ) );
|
{
|
||||||
|
return QCoreApplication::translate( "PWQ",
|
||||||
|
"The password contains less than %1 non-alphanumeric characters" )
|
||||||
|
.arg( mungeLong( auxerror ) );
|
||||||
|
}
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains too few non-alphanumeric characters" );
|
return QCoreApplication::translate( "PWQ", "The password contains too few non-alphanumeric characters" );
|
||||||
case PWQ_ERROR_MIN_LENGTH:
|
case PWQ_ERROR_MIN_LENGTH:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
return QCoreApplication::translate( "PWQ", "The password is shorter than %1 characters" ).arg( mungeLong( auxerror ) );
|
{
|
||||||
|
return QCoreApplication::translate( "PWQ", "The password is shorter than %1 characters" )
|
||||||
|
.arg( mungeLong( auxerror ) );
|
||||||
|
}
|
||||||
return QCoreApplication::translate( "PWQ", "The password is too short" );
|
return QCoreApplication::translate( "PWQ", "The password is too short" );
|
||||||
case PWQ_ERROR_ROTATED:
|
case PWQ_ERROR_ROTATED:
|
||||||
return QCoreApplication::translate( "PWQ", "The password is just rotated old one" );
|
return QCoreApplication::translate( "PWQ", "The password is just rotated old one" );
|
||||||
case PWQ_ERROR_MIN_CLASSES:
|
case PWQ_ERROR_MIN_CLASSES:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains less than %1 character classes" ).arg( mungeLong( auxerror ) );
|
{
|
||||||
|
return QCoreApplication::translate( "PWQ", "The password contains less than %1 character classes" )
|
||||||
|
.arg( mungeLong( auxerror ) );
|
||||||
|
}
|
||||||
return QCoreApplication::translate( "PWQ", "The password does not contain enough character classes" );
|
return QCoreApplication::translate( "PWQ", "The password does not contain enough character classes" );
|
||||||
case PWQ_ERROR_MAX_CONSECUTIVE:
|
case PWQ_ERROR_MAX_CONSECUTIVE:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains more than %1 same characters consecutively" ).arg( mungeLong( auxerror ) );
|
{
|
||||||
|
return QCoreApplication::translate( "PWQ",
|
||||||
|
"The password contains more than %1 same characters consecutively" )
|
||||||
|
.arg( mungeLong( auxerror ) );
|
||||||
|
}
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains too many same characters consecutively" );
|
return QCoreApplication::translate( "PWQ", "The password contains too many same characters consecutively" );
|
||||||
case PWQ_ERROR_MAX_CLASS_REPEAT:
|
case PWQ_ERROR_MAX_CLASS_REPEAT:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains more than %1 characters of the same class consecutively" ).arg( mungeLong( auxerror ) );
|
{
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains too many characters of the same class consecutively" );
|
return QCoreApplication::translate(
|
||||||
|
"PWQ", "The password contains more than %1 characters of the same class consecutively" )
|
||||||
|
.arg( mungeLong( auxerror ) );
|
||||||
|
}
|
||||||
|
return QCoreApplication::translate(
|
||||||
|
"PWQ", "The password contains too many characters of the same class consecutively" );
|
||||||
case PWQ_ERROR_MAX_SEQUENCE:
|
case PWQ_ERROR_MAX_SEQUENCE:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains monotonic sequence longer than %1 characters" ).arg( mungeLong( auxerror ) );
|
{
|
||||||
return QCoreApplication::translate( "PWQ", "The password contains too long of a monotonic character sequence" );
|
return QCoreApplication::translate(
|
||||||
|
"PWQ", "The password contains monotonic sequence longer than %1 characters" )
|
||||||
|
.arg( mungeLong( auxerror ) );
|
||||||
|
}
|
||||||
|
return QCoreApplication::translate( "PWQ",
|
||||||
|
"The password contains too long of a monotonic character sequence" );
|
||||||
case PWQ_ERROR_EMPTY_PASSWORD:
|
case PWQ_ERROR_EMPTY_PASSWORD:
|
||||||
return QCoreApplication::translate( "PWQ", "No password supplied" );
|
return QCoreApplication::translate( "PWQ", "No password supplied" );
|
||||||
case PWQ_ERROR_RNG:
|
case PWQ_ERROR_RNG:
|
||||||
return QCoreApplication::translate( "PWQ", "Cannot obtain random numbers from the RNG device" );
|
return QCoreApplication::translate( "PWQ", "Cannot obtain random numbers from the RNG device" );
|
||||||
case PWQ_ERROR_GENERATION_FAILED:
|
case PWQ_ERROR_GENERATION_FAILED:
|
||||||
return QCoreApplication::translate( "PWQ", "Password generation failed - required entropy too low for settings" );
|
return QCoreApplication::translate( "PWQ",
|
||||||
|
"Password generation failed - required entropy too low for settings" );
|
||||||
case PWQ_ERROR_CRACKLIB_CHECK:
|
case PWQ_ERROR_CRACKLIB_CHECK:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
{
|
{
|
||||||
/* Here the string comes from cracklib, don't free? */
|
/* Here the string comes from cracklib, don't free? */
|
||||||
return QCoreApplication::translate( "PWQ", "The password fails the dictionary check - %1" ).arg( mungeString( auxerror ) );
|
return QCoreApplication::translate( "PWQ", "The password fails the dictionary check - %1" )
|
||||||
|
.arg( mungeString( auxerror ) );
|
||||||
}
|
}
|
||||||
return QCoreApplication::translate( "PWQ", "The password fails the dictionary check" );
|
return QCoreApplication::translate( "PWQ", "The password fails the dictionary check" );
|
||||||
case PWQ_ERROR_UNKNOWN_SETTING:
|
case PWQ_ERROR_UNKNOWN_SETTING:
|
||||||
@ -254,7 +274,8 @@ public:
|
|||||||
case PWQ_ERROR_INTEGER:
|
case PWQ_ERROR_INTEGER:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
{
|
{
|
||||||
QString s = QCoreApplication::translate( "PWQ", "Bad integer value of setting - %1" ).arg( mungeString( auxerror ) );
|
QString s = QCoreApplication::translate( "PWQ", "Bad integer value of setting - %1" )
|
||||||
|
.arg( mungeString( auxerror ) );
|
||||||
free( auxerror );
|
free( auxerror );
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -262,7 +283,8 @@ public:
|
|||||||
case PWQ_ERROR_NON_INT_SETTING:
|
case PWQ_ERROR_NON_INT_SETTING:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
{
|
{
|
||||||
QString s = QCoreApplication::translate( "PWQ", "Setting %1 is not of integer type" ).arg( mungeString( auxerror ) );
|
QString s = QCoreApplication::translate( "PWQ", "Setting %1 is not of integer type" )
|
||||||
|
.arg( mungeString( auxerror ) );
|
||||||
free( auxerror );
|
free( auxerror );
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -270,7 +292,8 @@ public:
|
|||||||
case PWQ_ERROR_NON_STR_SETTING:
|
case PWQ_ERROR_NON_STR_SETTING:
|
||||||
if ( auxerror )
|
if ( auxerror )
|
||||||
{
|
{
|
||||||
QString s = QCoreApplication::translate( "PWQ", "Setting %1 is not of string type" ).arg( mungeString( auxerror ) );
|
QString s = QCoreApplication::translate( "PWQ", "Setting %1 is not of string type" )
|
||||||
|
.arg( mungeString( auxerror ) );
|
||||||
free( auxerror );
|
free( auxerror );
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -290,7 +313,7 @@ private:
|
|||||||
pwquality_settings_t* m_settings;
|
pwquality_settings_t* m_settings;
|
||||||
int m_rv;
|
int m_rv;
|
||||||
void* m_auxerror;
|
void* m_auxerror;
|
||||||
} ;
|
};
|
||||||
|
|
||||||
DEFINE_CHECK_FUNC( libpwquality )
|
DEFINE_CHECK_FUNC( libpwquality )
|
||||||
{
|
{
|
||||||
@ -302,7 +325,7 @@ DEFINE_CHECK_FUNC( libpwquality )
|
|||||||
|
|
||||||
QVariantList l = value.toList();
|
QVariantList l = value.toList();
|
||||||
unsigned int requirement_count = 0;
|
unsigned int requirement_count = 0;
|
||||||
auto settings = std::make_shared<PWSettingsHolder>();
|
auto settings = std::make_shared< PWSettingsHolder >();
|
||||||
for ( const auto& v : l )
|
for ( const auto& v : l )
|
||||||
{
|
{
|
||||||
if ( v.type() == QVariant::String )
|
if ( v.type() == QVariant::String )
|
||||||
@ -310,7 +333,9 @@ DEFINE_CHECK_FUNC( libpwquality )
|
|||||||
QString option = v.toString();
|
QString option = v.toString();
|
||||||
int r = settings->set( option );
|
int r = settings->set( option );
|
||||||
if ( r )
|
if ( r )
|
||||||
|
{
|
||||||
cWarning() << "unrecognized libpwquality setting" << option;
|
cWarning() << "unrecognized libpwquality setting" << option;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cDebug() << Logger::SubEntry << "libpwquality setting" << option;
|
cDebug() << Logger::SubEntry << "libpwquality setting" << option;
|
||||||
@ -318,28 +343,27 @@ DEFINE_CHECK_FUNC( libpwquality )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
cWarning() << "unrecognized libpwquality setting" << v;
|
cWarning() << "unrecognized libpwquality setting" << v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Something actually added? */
|
/* Something actually added? */
|
||||||
if ( requirement_count )
|
if ( requirement_count )
|
||||||
{
|
{
|
||||||
checks.push_back(
|
checks.push_back( PasswordCheck( [settings]() { return settings->explanation(); },
|
||||||
PasswordCheck(
|
[settings]( const QString& s ) {
|
||||||
[settings]()
|
int r = settings->check( s );
|
||||||
{
|
if ( r < 0 )
|
||||||
return settings->explanation();
|
{
|
||||||
},
|
cWarning() << "libpwquality error" << r;
|
||||||
[settings]( const QString& s )
|
}
|
||||||
{
|
else if ( r < settings->arbitrary_minimum_strength )
|
||||||
int r = settings->check( s );
|
{
|
||||||
if ( r < 0 )
|
cDebug() << "Password strength" << r << "too low";
|
||||||
cWarning() << "libpwquality error" << r;
|
}
|
||||||
else if ( r < settings->arbitrary_minimum_strength )
|
return r >= settings->arbitrary_minimum_strength;
|
||||||
cDebug() << "Password strength" << r << "too low";
|
} ) );
|
||||||
return r >= settings->arbitrary_minimum_strength;
|
|
||||||
}
|
|
||||||
) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,8 +35,8 @@ class PasswordCheck
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/** Return true if the string is acceptable. */
|
/** Return true if the string is acceptable. */
|
||||||
using AcceptFunc = std::function<bool( const QString& )>;
|
using AcceptFunc = std::function< bool( const QString& ) >;
|
||||||
using MessageFunc = std::function<QString()>;
|
using MessageFunc = std::function< QString() >;
|
||||||
|
|
||||||
/** Generate a @p message if @p filter returns true */
|
/** Generate a @p message if @p filter returns true */
|
||||||
PasswordCheck( MessageFunc message, AcceptFunc filter );
|
PasswordCheck( MessageFunc message, AcceptFunc filter );
|
||||||
@ -50,17 +50,14 @@ public:
|
|||||||
* according to this filter. Returns a message describing
|
* according to this filter. Returns a message describing
|
||||||
* what is wrong if not.
|
* what is wrong if not.
|
||||||
*/
|
*/
|
||||||
QString filter( const QString& s ) const
|
QString filter( const QString& s ) const { return m_accept( s ) ? QString() : m_message(); }
|
||||||
{
|
|
||||||
return m_accept( s ) ? QString() : m_message();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MessageFunc m_message;
|
MessageFunc m_message;
|
||||||
AcceptFunc m_accept;
|
AcceptFunc m_accept;
|
||||||
} ;
|
};
|
||||||
|
|
||||||
using PasswordCheckList = QVector<PasswordCheck>;
|
using PasswordCheckList = QVector< PasswordCheck >;
|
||||||
|
|
||||||
/* Each of these functions adds a check (if possible) to the list
|
/* Each of these functions adds a check (if possible) to the list
|
||||||
* of checks; they use the configuration value(s) from the
|
* of checks; they use the configuration value(s) from the
|
||||||
@ -68,16 +65,14 @@ using PasswordCheckList = QVector<PasswordCheck>;
|
|||||||
* may skip adding a check, and do nothing (it should log
|
* may skip adding a check, and do nothing (it should log
|
||||||
* an error, though).
|
* an error, though).
|
||||||
*/
|
*/
|
||||||
#define _xDEFINE_CHECK_FUNC(x) \
|
#define _xDEFINE_CHECK_FUNC( x ) add_check_##x( PasswordCheckList& checks, const QVariant& value )
|
||||||
add_check_##x( PasswordCheckList& checks, const QVariant& value )
|
#define DEFINE_CHECK_FUNC( x ) void _xDEFINE_CHECK_FUNC( x )
|
||||||
#define DEFINE_CHECK_FUNC(x) void _xDEFINE_CHECK_FUNC(x)
|
#define DECLARE_CHECK_FUNC( x ) void _xDEFINE_CHECK_FUNC( x );
|
||||||
#define DECLARE_CHECK_FUNC(x) void _xDEFINE_CHECK_FUNC(x);
|
|
||||||
|
|
||||||
DECLARE_CHECK_FUNC(minLength)
|
DECLARE_CHECK_FUNC( minLength )
|
||||||
DECLARE_CHECK_FUNC(maxLength)
|
DECLARE_CHECK_FUNC( maxLength )
|
||||||
#ifdef HAVE_LIBPWQUALITY
|
#ifdef HAVE_LIBPWQUALITY
|
||||||
DECLARE_CHECK_FUNC(libpwquality)
|
DECLARE_CHECK_FUNC( libpwquality )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
#include <CreateUserJob.h>
|
#include <CreateUserJob.h>
|
||||||
|
|
||||||
#include "JobQueue.h"
|
|
||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
#include "utils/Logger.h"
|
#include "JobQueue.h"
|
||||||
#include "utils/CalamaresUtilsSystem.h"
|
#include "utils/CalamaresUtilsSystem.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@ -72,17 +72,20 @@ CreateUserJob::exec()
|
|||||||
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||||
QDir destDir( gs->value( "rootMountPoint" ).toString() );
|
QDir destDir( gs->value( "rootMountPoint" ).toString() );
|
||||||
|
|
||||||
if ( gs->contains( "sudoersGroup" ) &&
|
if ( gs->contains( "sudoersGroup" ) && !gs->value( "sudoersGroup" ).toString().isEmpty() )
|
||||||
!gs->value( "sudoersGroup" ).toString().isEmpty() )
|
|
||||||
{
|
{
|
||||||
QFileInfo sudoersFi( destDir.absoluteFilePath( "etc/sudoers.d/10-installer" ) );
|
QFileInfo sudoersFi( destDir.absoluteFilePath( "etc/sudoers.d/10-installer" ) );
|
||||||
|
|
||||||
if ( !sudoersFi.absoluteDir().exists() )
|
if ( !sudoersFi.absoluteDir().exists() )
|
||||||
|
{
|
||||||
return Calamares::JobResult::error( tr( "Sudoers dir is not writable." ) );
|
return Calamares::JobResult::error( tr( "Sudoers dir is not writable." ) );
|
||||||
|
}
|
||||||
|
|
||||||
QFile sudoersFile( sudoersFi.absoluteFilePath() );
|
QFile sudoersFile( sudoersFi.absoluteFilePath() );
|
||||||
if (!sudoersFile.open( QIODevice::WriteOnly | QIODevice::Text ) )
|
if ( !sudoersFile.open( QIODevice::WriteOnly | QIODevice::Text ) )
|
||||||
|
{
|
||||||
return Calamares::JobResult::error( tr( "Cannot create sudoers file for writing." ) );
|
return Calamares::JobResult::error( tr( "Cannot create sudoers file for writing." ) );
|
||||||
|
}
|
||||||
|
|
||||||
QString sudoersGroup = gs->value( "sudoersGroup" ).toString();
|
QString sudoersGroup = gs->value( "sudoersGroup" ).toString();
|
||||||
|
|
||||||
@ -96,11 +99,12 @@ CreateUserJob::exec()
|
|||||||
QFileInfo groupsFi( destDir.absoluteFilePath( "etc/group" ) );
|
QFileInfo groupsFi( destDir.absoluteFilePath( "etc/group" ) );
|
||||||
QFile groupsFile( groupsFi.absoluteFilePath() );
|
QFile groupsFile( groupsFi.absoluteFilePath() );
|
||||||
if ( !groupsFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
if ( !groupsFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
||||||
|
{
|
||||||
return Calamares::JobResult::error( tr( "Cannot open groups file for reading." ) );
|
return Calamares::JobResult::error( tr( "Cannot open groups file for reading." ) );
|
||||||
|
}
|
||||||
QString groupsData = QString::fromLocal8Bit( groupsFile.readAll() );
|
QString groupsData = QString::fromLocal8Bit( groupsFile.readAll() );
|
||||||
QStringList groupsLines = groupsData.split( '\n' );
|
QStringList groupsLines = groupsData.split( '\n' );
|
||||||
for ( QStringList::iterator it = groupsLines.begin();
|
for ( QStringList::iterator it = groupsLines.begin(); it != groupsLines.end(); ++it )
|
||||||
it != groupsLines.end(); ++it )
|
|
||||||
{
|
{
|
||||||
int indexOfFirstToDrop = it->indexOf( ':' );
|
int indexOfFirstToDrop = it->indexOf( ':' );
|
||||||
it->truncate( indexOfFirstToDrop );
|
it->truncate( indexOfFirstToDrop );
|
||||||
@ -108,15 +112,13 @@ CreateUserJob::exec()
|
|||||||
|
|
||||||
foreach ( const QString& group, m_defaultGroups )
|
foreach ( const QString& group, m_defaultGroups )
|
||||||
if ( !groupsLines.contains( group ) )
|
if ( !groupsLines.contains( group ) )
|
||||||
CalamaresUtils::System::instance()->
|
CalamaresUtils::System::instance()->targetEnvCall( { "groupadd", group } );
|
||||||
targetEnvCall( { "groupadd", group } );
|
|
||||||
|
|
||||||
QString defaultGroups = m_defaultGroups.join( ',' );
|
QString defaultGroups = m_defaultGroups.join( ',' );
|
||||||
if ( m_autologin )
|
if ( m_autologin )
|
||||||
{
|
{
|
||||||
QString autologinGroup;
|
QString autologinGroup;
|
||||||
if ( gs->contains( "autologinGroup" ) &&
|
if ( gs->contains( "autologinGroup" ) && !gs->value( "autologinGroup" ).toString().isEmpty() )
|
||||||
!gs->value( "autologinGroup" ).toString().isEmpty() )
|
|
||||||
{
|
{
|
||||||
autologinGroup = gs->value( "autologinGroup" ).toString();
|
autologinGroup = gs->value( "autologinGroup" ).toString();
|
||||||
CalamaresUtils::System::instance()->targetEnvCall( { "groupadd", autologinGroup } );
|
CalamaresUtils::System::instance()->targetEnvCall( { "groupadd", autologinGroup } );
|
||||||
@ -131,26 +133,20 @@ CreateUserJob::exec()
|
|||||||
QDir existingHome( destDir.absolutePath() + shellFriendlyHome );
|
QDir existingHome( destDir.absolutePath() + shellFriendlyHome );
|
||||||
if ( existingHome.exists() )
|
if ( existingHome.exists() )
|
||||||
{
|
{
|
||||||
QString backupDirName = "dotfiles_backup_" +
|
QString backupDirName = "dotfiles_backup_" + QDateTime::currentDateTime().toString( "yyyy-MM-dd_HH-mm-ss" );
|
||||||
QDateTime::currentDateTime()
|
|
||||||
.toString( "yyyy-MM-dd_HH-mm-ss" );
|
|
||||||
existingHome.mkdir( backupDirName );
|
existingHome.mkdir( backupDirName );
|
||||||
|
|
||||||
CalamaresUtils::System::instance()->
|
CalamaresUtils::System::instance()->targetEnvCall(
|
||||||
targetEnvCall( { "sh",
|
{ "sh", "-c", "mv -f " + shellFriendlyHome + "/.* " + shellFriendlyHome + "/" + backupDirName } );
|
||||||
"-c",
|
|
||||||
"mv -f " +
|
|
||||||
shellFriendlyHome + "/.* " +
|
|
||||||
shellFriendlyHome + "/" +
|
|
||||||
backupDirName
|
|
||||||
} );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList useradd{ "useradd", "-m", "-U" };
|
QStringList useradd { "useradd", "-m", "-U" };
|
||||||
QString shell = gs->value( "userShell" ).toString();
|
QString shell = gs->value( "userShell" ).toString();
|
||||||
if ( !shell.isEmpty() )
|
if ( !shell.isEmpty() )
|
||||||
|
{
|
||||||
useradd << "-s" << shell;
|
useradd << "-s" << shell;
|
||||||
|
}
|
||||||
useradd << "-c" << m_fullName;
|
useradd << "-c" << m_fullName;
|
||||||
useradd << m_userName;
|
useradd << m_userName;
|
||||||
|
|
||||||
@ -161,8 +157,8 @@ CreateUserJob::exec()
|
|||||||
return commandResult.explainProcess( useradd, std::chrono::seconds( 10 ) /* bogus timeout */ );
|
return commandResult.explainProcess( useradd, std::chrono::seconds( 10 ) /* bogus timeout */ );
|
||||||
}
|
}
|
||||||
|
|
||||||
commandResult = CalamaresUtils::System::instance()->targetEnvCommand(
|
commandResult
|
||||||
{ "usermod", "-aG", defaultGroups, m_userName } );
|
= CalamaresUtils::System::instance()->targetEnvCommand( { "usermod", "-aG", defaultGroups, m_userName } );
|
||||||
if ( commandResult.getExitCode() )
|
if ( commandResult.getExitCode() )
|
||||||
{
|
{
|
||||||
cError() << "usermod failed" << commandResult.getExitCode();
|
cError() << "usermod failed" << commandResult.getExitCode();
|
||||||
@ -171,8 +167,7 @@ CreateUserJob::exec()
|
|||||||
|
|
||||||
QString userGroup = QString( "%1:%2" ).arg( m_userName ).arg( m_userName );
|
QString userGroup = QString( "%1:%2" ).arg( m_userName ).arg( m_userName );
|
||||||
QString homeDir = QString( "/home/%1" ).arg( m_userName );
|
QString homeDir = QString( "/home/%1" ).arg( m_userName );
|
||||||
commandResult = CalamaresUtils::System::instance()->targetEnvCommand(
|
commandResult = CalamaresUtils::System::instance()->targetEnvCommand( { "chown", "-R", userGroup, homeDir } );
|
||||||
{ "chown", "-R", userGroup, homeDir } );
|
|
||||||
if ( commandResult.getExitCode() )
|
if ( commandResult.getExitCode() )
|
||||||
{
|
{
|
||||||
cError() << "chown failed" << commandResult.getExitCode();
|
cError() << "chown failed" << commandResult.getExitCode();
|
||||||
|
@ -27,10 +27,7 @@ class CreateUserJob : public Calamares::Job
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
CreateUserJob( const QString& userName,
|
CreateUserJob( const QString& userName, const QString& fullName, bool autologin, const QStringList& defaultGroups );
|
||||||
const QString& fullName,
|
|
||||||
bool autologin,
|
|
||||||
const QStringList& defaultGroups );
|
|
||||||
QString prettyName() const override;
|
QString prettyName() const override;
|
||||||
QString prettyDescription() const override;
|
QString prettyDescription() const override;
|
||||||
QString prettyStatusMessage() const override;
|
QString prettyStatusMessage() const override;
|
||||||
|
@ -24,13 +24,9 @@
|
|||||||
|
|
||||||
QTEST_GUILESS_MAIN( PasswordTests )
|
QTEST_GUILESS_MAIN( PasswordTests )
|
||||||
|
|
||||||
PasswordTests::PasswordTests()
|
PasswordTests::PasswordTests() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PasswordTests::~PasswordTests()
|
PasswordTests::~PasswordTests() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PasswordTests::initTestCase()
|
PasswordTests::initTestCase()
|
||||||
@ -41,7 +37,7 @@ void
|
|||||||
PasswordTests::testSalt()
|
PasswordTests::testSalt()
|
||||||
{
|
{
|
||||||
QString s = SetPasswordJob::make_salt( 8 );
|
QString s = SetPasswordJob::make_salt( 8 );
|
||||||
QCOMPARE( s.length(), 4 + 8 ); // 8 salt chars, plus $6$, plus trailing $
|
QCOMPARE( s.length(), 4 + 8 ); // 8 salt chars, plus $6$, plus trailing $
|
||||||
QVERIFY( s.startsWith( "$6$" ) );
|
QVERIFY( s.startsWith( "$6$" ) );
|
||||||
QVERIFY( s.endsWith( '$' ) );
|
QVERIFY( s.endsWith( '$' ) );
|
||||||
qDebug() << "Obtained salt" << s;
|
qDebug() << "Obtained salt" << s;
|
||||||
|
@ -21,11 +21,11 @@
|
|||||||
#include "SetHostNameJob.h"
|
#include "SetHostNameJob.h"
|
||||||
|
|
||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
#include "utils/Logger.h"
|
|
||||||
#include "JobQueue.h"
|
#include "JobQueue.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
#include <QFile>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
SetHostNameJob::SetHostNameJob( const QString& hostname )
|
SetHostNameJob::SetHostNameJob( const QString& hostname )
|
||||||
: Calamares::Job()
|
: Calamares::Job()
|
||||||
@ -33,7 +33,8 @@ SetHostNameJob::SetHostNameJob( const QString& hostname )
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SetHostNameJob::prettyName() const
|
QString
|
||||||
|
SetHostNameJob::prettyName() const
|
||||||
{
|
{
|
||||||
return tr( "Set hostname %1" ).arg( m_hostname );
|
return tr( "Set hostname %1" ).arg( m_hostname );
|
||||||
}
|
}
|
||||||
@ -52,7 +53,8 @@ SetHostNameJob::prettyStatusMessage() const
|
|||||||
return tr( "Setting hostname %1." ).arg( m_hostname );
|
return tr( "Setting hostname %1." ).arg( m_hostname );
|
||||||
}
|
}
|
||||||
|
|
||||||
Calamares::JobResult SetHostNameJob::exec()
|
Calamares::JobResult
|
||||||
|
SetHostNameJob::exec()
|
||||||
{
|
{
|
||||||
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||||
|
|
||||||
@ -90,11 +92,21 @@ Calamares::JobResult SetHostNameJob::exec()
|
|||||||
// We also need to write the appropriate entries for /etc/hosts
|
// We also need to write the appropriate entries for /etc/hosts
|
||||||
QTextStream hostsfileout( &hostsfile );
|
QTextStream hostsfileout( &hostsfile );
|
||||||
// ipv4 support
|
// ipv4 support
|
||||||
hostsfileout << "127.0.0.1" << "\t" << "localhost" << "\n";
|
hostsfileout << "127.0.0.1"
|
||||||
hostsfileout << "127.0.1.1" << "\t" << m_hostname << "\n";
|
<< "\t"
|
||||||
|
<< "localhost"
|
||||||
|
<< "\n";
|
||||||
|
hostsfileout << "127.0.1.1"
|
||||||
|
<< "\t" << m_hostname << "\n";
|
||||||
// ipv6 support
|
// ipv6 support
|
||||||
hostsfileout << "::1" << "\t" << "localhost ip6-localhost ip6-loopback" << "\n";
|
hostsfileout << "::1"
|
||||||
hostsfileout << "ff02::1 ip6-allnodes" << "\n" << "ff02::2 ip6-allrouters" << "\n";
|
<< "\t"
|
||||||
|
<< "localhost ip6-localhost ip6-loopback"
|
||||||
|
<< "\n";
|
||||||
|
hostsfileout << "ff02::1 ip6-allnodes"
|
||||||
|
<< "\n"
|
||||||
|
<< "ff02::2 ip6-allrouters"
|
||||||
|
<< "\n";
|
||||||
hostsfile.close();
|
hostsfile.close();
|
||||||
|
|
||||||
return Calamares::JobResult::ok();
|
return Calamares::JobResult::ok();
|
||||||
|
@ -31,9 +31,10 @@ public:
|
|||||||
QString prettyDescription() const override;
|
QString prettyDescription() const override;
|
||||||
QString prettyStatusMessage() const override;
|
QString prettyStatusMessage() const override;
|
||||||
Calamares::JobResult exec() override;
|
Calamares::JobResult exec() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QString m_hostname;
|
const QString m_hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // SETHOSTNAMEJOB_CPP_H
|
#endif // SETHOSTNAMEJOB_CPP_H
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
#include <SetPasswordJob.h>
|
#include <SetPasswordJob.h>
|
||||||
|
|
||||||
#include "JobQueue.h"
|
|
||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
#include "utils/Logger.h"
|
#include "JobQueue.h"
|
||||||
#include "utils/CalamaresUtilsSystem.h"
|
#include "utils/CalamaresUtilsSystem.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|
||||||
@ -58,29 +58,27 @@ SetPasswordJob::prettyStatusMessage() const
|
|||||||
|
|
||||||
/// Returns a modular hashing salt for method 6 (SHA512) with a 16 character random salt.
|
/// Returns a modular hashing salt for method 6 (SHA512) with a 16 character random salt.
|
||||||
QString
|
QString
|
||||||
SetPasswordJob::make_salt(int length)
|
SetPasswordJob::make_salt( int length )
|
||||||
{
|
{
|
||||||
Q_ASSERT(length >= 8);
|
Q_ASSERT( length >= 8 );
|
||||||
Q_ASSERT(length <= 128);
|
Q_ASSERT( length <= 128 );
|
||||||
|
|
||||||
static const char salt_chars[] = {
|
static const char salt_chars[] = { '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
|
||||||
'.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
|
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
|
||||||
'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
|
||||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
|
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
|
||||||
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
|
|
||||||
's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
|
|
||||||
|
|
||||||
static_assert( sizeof(salt_chars) == 64, "Missing salt_chars");
|
static_assert( sizeof( salt_chars ) == 64, "Missing salt_chars" );
|
||||||
|
|
||||||
std::random_device r;
|
std::random_device r;
|
||||||
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
|
std::seed_seq seed { r(), r(), r(), r(), r(), r(), r(), r() };
|
||||||
std::mt19937_64 twister(seed);
|
std::mt19937_64 twister( seed );
|
||||||
|
|
||||||
std::uint64_t next;
|
std::uint64_t next;
|
||||||
int current_length = 0;
|
int current_length = 0;
|
||||||
|
|
||||||
QString salt_string;
|
QString salt_string;
|
||||||
salt_string.reserve(length + 10);
|
salt_string.reserve( length + 10 );
|
||||||
|
|
||||||
while ( current_length < length )
|
while ( current_length < length )
|
||||||
{
|
{
|
||||||
@ -89,11 +87,13 @@ SetPasswordJob::make_salt(int length)
|
|||||||
// to a single salt character.
|
// to a single salt character.
|
||||||
for ( unsigned int char_count = 0; char_count < 10; ++char_count )
|
for ( unsigned int char_count = 0; char_count < 10; ++char_count )
|
||||||
{
|
{
|
||||||
char c = salt_chars[next & 0b0111111];
|
char c = salt_chars[ next & 0b0111111 ];
|
||||||
next >>= 6;
|
next >>= 6;
|
||||||
salt_string.append( c );
|
salt_string.append( c );
|
||||||
if (++current_length >= length)
|
if ( ++current_length >= length )
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,34 +112,21 @@ SetPasswordJob::exec()
|
|||||||
return Calamares::JobResult::error( tr( "Bad destination system path." ),
|
return Calamares::JobResult::error( tr( "Bad destination system path." ),
|
||||||
tr( "rootMountPoint is %1" ).arg( destDir.absolutePath() ) );
|
tr( "rootMountPoint is %1" ).arg( destDir.absolutePath() ) );
|
||||||
|
|
||||||
if ( m_userName == "root" &&
|
if ( m_userName == "root" && m_newPassword.isEmpty() ) //special case for disabling root account
|
||||||
m_newPassword.isEmpty() ) //special case for disabling root account
|
|
||||||
{
|
{
|
||||||
int ec = CalamaresUtils::System::instance()->
|
int ec = CalamaresUtils::System::instance()->targetEnvCall( { "passwd", "-dl", m_userName } );
|
||||||
targetEnvCall( { "passwd",
|
|
||||||
"-dl",
|
|
||||||
m_userName } );
|
|
||||||
if ( ec )
|
if ( ec )
|
||||||
return Calamares::JobResult::error( tr( "Cannot disable root account." ),
|
return Calamares::JobResult::error( tr( "Cannot disable root account." ),
|
||||||
tr( "passwd terminated with error code %1." )
|
tr( "passwd terminated with error code %1." ).arg( ec ) );
|
||||||
.arg( ec ) );
|
|
||||||
return Calamares::JobResult::ok();
|
return Calamares::JobResult::ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString encrypted = QString::fromLatin1(
|
QString encrypted = QString::fromLatin1( crypt( m_newPassword.toUtf8(), make_salt( 16 ).toUtf8() ) );
|
||||||
crypt( m_newPassword.toUtf8(),
|
|
||||||
make_salt( 16 ).toUtf8() ) );
|
|
||||||
|
|
||||||
int ec = CalamaresUtils::System::instance()->
|
int ec = CalamaresUtils::System::instance()->targetEnvCall( { "usermod", "-p", encrypted, m_userName } );
|
||||||
targetEnvCall( { "usermod",
|
|
||||||
"-p",
|
|
||||||
encrypted,
|
|
||||||
m_userName } );
|
|
||||||
if ( ec )
|
if ( ec )
|
||||||
return Calamares::JobResult::error( tr( "Cannot set password for user %1." )
|
return Calamares::JobResult::error( tr( "Cannot set password for user %1." ).arg( m_userName ),
|
||||||
.arg( m_userName ),
|
tr( "usermod terminated with error code %1." ).arg( ec ) );
|
||||||
tr( "usermod terminated with error code %1." )
|
|
||||||
.arg( ec ) );
|
|
||||||
|
|
||||||
return Calamares::JobResult::ok();
|
return Calamares::JobResult::ok();
|
||||||
}
|
}
|
||||||
|
@ -27,13 +27,12 @@ class SetPasswordJob : public Calamares::Job
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SetPasswordJob( const QString& userName,
|
SetPasswordJob( const QString& userName, const QString& newPassword );
|
||||||
const QString& newPassword );
|
|
||||||
QString prettyName() const override;
|
QString prettyName() const override;
|
||||||
QString prettyStatusMessage() const override;
|
QString prettyStatusMessage() const override;
|
||||||
Calamares::JobResult exec() override;
|
Calamares::JobResult exec() override;
|
||||||
|
|
||||||
static QString make_salt(int length);
|
static QString make_salt( int length );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_userName;
|
QString m_userName;
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
#include "ui_page_usersetup.h"
|
#include "ui_page_usersetup.h"
|
||||||
|
|
||||||
#include "CreateUserJob.h"
|
#include "CreateUserJob.h"
|
||||||
#include "SetPasswordJob.h"
|
|
||||||
#include "SetHostNameJob.h"
|
#include "SetHostNameJob.h"
|
||||||
|
#include "SetPasswordJob.h"
|
||||||
|
|
||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
#include "JobQueue.h"
|
#include "JobQueue.h"
|
||||||
@ -45,12 +45,28 @@
|
|||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
#include <QRegExpValidator>
|
#include <QRegExpValidator>
|
||||||
|
|
||||||
|
static const QRegExp USERNAME_RX( "^[a-z_][a-z0-9_-]*[$]?$" );
|
||||||
|
static const QRegExp HOSTNAME_RX( "^[a-zA-Z0-9][-a-zA-Z0-9_]*$" );
|
||||||
|
static constexpr const int USERNAME_MAX_LENGTH = 31;
|
||||||
|
static constexpr const int HOSTNAME_MIN_LENGTH = 2;
|
||||||
|
static constexpr const int HOSTNAME_MAX_LENGTH = 63;
|
||||||
|
|
||||||
|
/** @brief How bad is the error for labelError() ? */
|
||||||
|
enum class Badness
|
||||||
|
{
|
||||||
|
Fatal,
|
||||||
|
Warning
|
||||||
|
};
|
||||||
|
|
||||||
/** Add an error message and pixmap to a label. */
|
/** Add an error message and pixmap to a label. */
|
||||||
static inline void
|
static inline void
|
||||||
labelError( QLabel* pix, QLabel* label, const QString& message )
|
labelError( QLabel* pix, QLabel* label, const QString& message, Badness bad = Badness::Fatal )
|
||||||
{
|
{
|
||||||
label->setText( message );
|
label->setText( message );
|
||||||
pix->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No, CalamaresUtils::Original, label->size() ) );
|
pix->setPixmap( CalamaresUtils::defaultPixmap( ( bad == Badness::Fatal ) ? CalamaresUtils::StatusError
|
||||||
|
: CalamaresUtils::StatusWarning,
|
||||||
|
CalamaresUtils::Original,
|
||||||
|
label->size() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Clear error, indicate OK on a label. */
|
/** Clear error, indicate OK on a label. */
|
||||||
@ -74,25 +90,20 @@ UsersPage::UsersPage( QWidget* parent )
|
|||||||
ui->setupUi( this );
|
ui->setupUi( this );
|
||||||
|
|
||||||
// Connect signals and slots
|
// Connect signals and slots
|
||||||
connect( ui->textBoxFullName, &QLineEdit::textEdited,
|
connect( ui->textBoxFullName, &QLineEdit::textEdited, this, &UsersPage::onFullNameTextEdited );
|
||||||
this, &UsersPage::onFullNameTextEdited );
|
connect( ui->textBoxUsername, &QLineEdit::textEdited, this, &UsersPage::onUsernameTextEdited );
|
||||||
connect( ui->textBoxUsername, &QLineEdit::textEdited,
|
connect( ui->textBoxHostname, &QLineEdit::textEdited, this, &UsersPage::onHostnameTextEdited );
|
||||||
this, &UsersPage::onUsernameTextEdited );
|
connect( ui->textBoxUserPassword, &QLineEdit::textChanged, this, &UsersPage::onPasswordTextChanged );
|
||||||
connect( ui->textBoxHostname, &QLineEdit::textEdited,
|
connect( ui->textBoxUserVerifiedPassword, &QLineEdit::textChanged, this, &UsersPage::onPasswordTextChanged );
|
||||||
this, &UsersPage::onHostnameTextEdited );
|
connect( ui->textBoxRootPassword, &QLineEdit::textChanged, this, &UsersPage::onRootPasswordTextChanged );
|
||||||
connect( ui->textBoxUserPassword, &QLineEdit::textChanged,
|
connect( ui->textBoxVerifiedRootPassword, &QLineEdit::textChanged, this, &UsersPage::onRootPasswordTextChanged );
|
||||||
this, &UsersPage::onPasswordTextChanged );
|
connect( ui->checkBoxValidatePassword, &QCheckBox::stateChanged, this, [this]( int checked ) {
|
||||||
connect( ui->textBoxUserVerifiedPassword, &QLineEdit::textChanged,
|
onPasswordTextChanged( ui->textBoxUserPassword->text() );
|
||||||
this, &UsersPage::onPasswordTextChanged );
|
onRootPasswordTextChanged( ui->textBoxRootPassword->text() );
|
||||||
connect( ui->textBoxRootPassword, &QLineEdit::textChanged,
|
checkReady( isReady() );
|
||||||
this, &UsersPage::onRootPasswordTextChanged );
|
} );
|
||||||
connect( ui->textBoxVerifiedRootPassword, &QLineEdit::textChanged,
|
connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, [this]( int checked ) {
|
||||||
this, &UsersPage::onRootPasswordTextChanged );
|
|
||||||
connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged,
|
|
||||||
this, [this]( int checked )
|
|
||||||
{
|
|
||||||
ui->labelChooseRootPassword->setVisible( !checked );
|
ui->labelChooseRootPassword->setVisible( !checked );
|
||||||
ui->labelExtraRootPassword->setVisible( !checked );
|
|
||||||
ui->labelRootPassword->setVisible( !checked );
|
ui->labelRootPassword->setVisible( !checked );
|
||||||
ui->labelRootPasswordError->setVisible( !checked );
|
ui->labelRootPasswordError->setVisible( !checked );
|
||||||
ui->textBoxRootPassword->setVisible( !checked );
|
ui->textBoxRootPassword->setVisible( !checked );
|
||||||
@ -105,47 +116,45 @@ UsersPage::UsersPage( QWidget* parent )
|
|||||||
|
|
||||||
setWriteRootPassword( true );
|
setWriteRootPassword( true );
|
||||||
ui->checkBoxReusePassword->setChecked( true );
|
ui->checkBoxReusePassword->setChecked( true );
|
||||||
|
ui->checkBoxValidatePassword->setChecked( true );
|
||||||
|
|
||||||
// Don't expand the explanations to "stupid wide", but keep them vaguely as-wide-as
|
setPasswordCheckboxVisible( false );
|
||||||
// the things they are explaining.
|
|
||||||
int boxWidth = qMax( qMax( ui->textBoxUsername->width(), ui->textBoxHostname->width() ), ui->textBoxUserPassword->width() );
|
|
||||||
ui->username_extra_label_2->setMaximumWidth( 3 * boxWidth );
|
|
||||||
ui->hostname_extra_label_2->setMaximumWidth( 3 * boxWidth );
|
|
||||||
ui->password_extra_label_3->setMaximumWidth( 3 * boxWidth );
|
|
||||||
|
|
||||||
CALAMARES_RETRANSLATE(
|
CALAMARES_RETRANSLATE_SLOT( &UsersPage::retranslate );
|
||||||
ui->retranslateUi( this );
|
|
||||||
if ( Calamares::Settings::instance()->isSetupMode() )
|
|
||||||
{
|
|
||||||
ui->username_extra_label_2->setText( tr( "<small>If more than one person will "
|
|
||||||
"use this computer, you can create multiple "
|
|
||||||
"accounts after setup.</small>" ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ui->username_extra_label_2->setText( tr( "<small>If more than one person will "
|
|
||||||
"use this computer, you can create multiple "
|
|
||||||
"accounts after installation.</small>" ) );
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UsersPage::~UsersPage()
|
UsersPage::~UsersPage()
|
||||||
{
|
{
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UsersPage::retranslate()
|
||||||
|
{
|
||||||
|
ui->retranslateUi( this );
|
||||||
|
if ( Calamares::Settings::instance()->isSetupMode() )
|
||||||
|
{
|
||||||
|
ui->textBoxUsername->setToolTip( tr( "<small>If more than one person will "
|
||||||
|
"use this computer, you can create multiple "
|
||||||
|
"accounts after setup.</small>" ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->textBoxUsername->setToolTip( tr( "<small>If more than one person will "
|
||||||
|
"use this computer, you can create multiple "
|
||||||
|
"accounts after installation.</small>" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
UsersPage::isReady()
|
UsersPage::isReady()
|
||||||
{
|
{
|
||||||
bool readyFields = m_readyFullName &&
|
bool readyFields = m_readyFullName && m_readyHostname && m_readyPassword && m_readyUsername;
|
||||||
m_readyHostname &&
|
|
||||||
m_readyPassword &&
|
|
||||||
m_readyUsername;
|
|
||||||
if ( !m_writeRootPassword || ui->checkBoxReusePassword->isChecked() )
|
if ( !m_writeRootPassword || ui->checkBoxReusePassword->isChecked() )
|
||||||
|
{
|
||||||
return readyFields;
|
return readyFields;
|
||||||
|
}
|
||||||
|
|
||||||
return readyFields && m_readyRootPassword;
|
return readyFields && m_readyRootPassword;
|
||||||
}
|
}
|
||||||
@ -156,38 +165,40 @@ UsersPage::createJobs( const QStringList& defaultGroupsList )
|
|||||||
{
|
{
|
||||||
QList< Calamares::job_ptr > list;
|
QList< Calamares::job_ptr > list;
|
||||||
if ( !isReady() )
|
if ( !isReady() )
|
||||||
|
{
|
||||||
return list;
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||||
|
|
||||||
Calamares::Job* j;
|
Calamares::Job* j;
|
||||||
j = new CreateUserJob( ui->textBoxUsername->text(),
|
j = new CreateUserJob( ui->textBoxUsername->text(),
|
||||||
ui->textBoxFullName->text().isEmpty() ?
|
ui->textBoxFullName->text().isEmpty() ? ui->textBoxUsername->text()
|
||||||
ui->textBoxUsername->text() :
|
: ui->textBoxFullName->text(),
|
||||||
ui->textBoxFullName->text(),
|
|
||||||
ui->checkBoxAutoLogin->isChecked(),
|
ui->checkBoxAutoLogin->isChecked(),
|
||||||
defaultGroupsList );
|
defaultGroupsList );
|
||||||
list.append( Calamares::job_ptr( j ) );
|
list.append( Calamares::job_ptr( j ) );
|
||||||
|
|
||||||
j = new SetPasswordJob( ui->textBoxUsername->text(),
|
j = new SetPasswordJob( ui->textBoxUsername->text(), ui->textBoxUserPassword->text() );
|
||||||
ui->textBoxUserPassword->text() );
|
|
||||||
list.append( Calamares::job_ptr( j ) );
|
list.append( Calamares::job_ptr( j ) );
|
||||||
|
|
||||||
if ( m_writeRootPassword )
|
if ( m_writeRootPassword )
|
||||||
{
|
{
|
||||||
gs->insert( "reuseRootPassword", ui->checkBoxReusePassword->isChecked() );
|
gs->insert( "reuseRootPassword", ui->checkBoxReusePassword->isChecked() );
|
||||||
if ( ui->checkBoxReusePassword->isChecked() )
|
if ( ui->checkBoxReusePassword->isChecked() )
|
||||||
j = new SetPasswordJob( "root",
|
{
|
||||||
ui->textBoxUserPassword->text() );
|
j = new SetPasswordJob( "root", ui->textBoxUserPassword->text() );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
j = new SetPasswordJob( "root",
|
{
|
||||||
ui->textBoxRootPassword->text() );
|
j = new SetPasswordJob( "root", ui->textBoxRootPassword->text() );
|
||||||
|
}
|
||||||
list.append( Calamares::job_ptr( j ) );
|
list.append( Calamares::job_ptr( j ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
j = new SetPasswordJob( "root",
|
j = new SetPasswordJob( "root",
|
||||||
"" ); //explicitly disable root password
|
"" ); //explicitly disable root password
|
||||||
list.append( Calamares::job_ptr( j ) );
|
list.append( Calamares::job_ptr( j ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +207,9 @@ UsersPage::createJobs( const QStringList& defaultGroupsList )
|
|||||||
|
|
||||||
gs->insert( "hostname", ui->textBoxHostname->text() );
|
gs->insert( "hostname", ui->textBoxHostname->text() );
|
||||||
if ( ui->checkBoxAutoLogin->isChecked() )
|
if ( ui->checkBoxAutoLogin->isChecked() )
|
||||||
|
{
|
||||||
gs->insert( "autologinUser", ui->textBoxUsername->text() );
|
gs->insert( "autologinUser", ui->textBoxUsername->text() );
|
||||||
|
}
|
||||||
|
|
||||||
gs->insert( "username", ui->textBoxUsername->text() );
|
gs->insert( "username", ui->textBoxUsername->text() );
|
||||||
gs->insert( "password", CalamaresUtils::obscure( ui->textBoxUserPassword->text() ) );
|
gs->insert( "password", CalamaresUtils::obscure( ui->textBoxUserPassword->text() ) );
|
||||||
@ -228,16 +241,19 @@ UsersPage::onFullNameTextEdited( const QString& textRef )
|
|||||||
ui->labelFullNameError->clear();
|
ui->labelFullNameError->clear();
|
||||||
ui->labelFullName->clear();
|
ui->labelFullName->clear();
|
||||||
if ( !m_customUsername )
|
if ( !m_customUsername )
|
||||||
|
{
|
||||||
ui->textBoxUsername->clear();
|
ui->textBoxUsername->clear();
|
||||||
|
}
|
||||||
if ( !m_customHostname )
|
if ( !m_customHostname )
|
||||||
|
{
|
||||||
ui->textBoxHostname->clear();
|
ui->textBoxHostname->clear();
|
||||||
|
}
|
||||||
m_readyFullName = false;
|
m_readyFullName = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ui->labelFullName->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes,
|
ui->labelFullName->setPixmap(
|
||||||
CalamaresUtils::Original,
|
CalamaresUtils::defaultPixmap( CalamaresUtils::Yes, CalamaresUtils::Original, ui->labelFullName->size() ) );
|
||||||
ui->labelFullName->size() ) );
|
|
||||||
m_readyFullName = true;
|
m_readyFullName = true;
|
||||||
fillSuggestions();
|
fillSuggestions();
|
||||||
}
|
}
|
||||||
@ -250,8 +266,7 @@ UsersPage::fillSuggestions()
|
|||||||
{
|
{
|
||||||
QString fullName = ui->textBoxFullName->text();
|
QString fullName = ui->textBoxFullName->text();
|
||||||
QRegExp rx( "[^a-zA-Z0-9 ]", Qt::CaseInsensitive );
|
QRegExp rx( "[^a-zA-Z0-9 ]", Qt::CaseInsensitive );
|
||||||
QString cleanName = CalamaresUtils::removeDiacritics( fullName )
|
QString cleanName = CalamaresUtils::removeDiacritics( fullName ).toLower().replace( rx, " " ).simplified();
|
||||||
.toLower().replace( rx, " " ).simplified();
|
|
||||||
QStringList cleanParts = cleanName.split( ' ' );
|
QStringList cleanParts = cleanName.split( ' ' );
|
||||||
|
|
||||||
if ( !m_customUsername )
|
if ( !m_customUsername )
|
||||||
@ -262,7 +277,9 @@ UsersPage::fillSuggestions()
|
|||||||
for ( int i = 1; i < cleanParts.length(); ++i )
|
for ( int i = 1; i < cleanParts.length(); ++i )
|
||||||
{
|
{
|
||||||
if ( !cleanParts.value( i ).isEmpty() )
|
if ( !cleanParts.value( i ).isEmpty() )
|
||||||
|
{
|
||||||
usernameSuggestion.append( cleanParts.value( i ).at( 0 ) );
|
usernameSuggestion.append( cleanParts.value( i ).at( 0 ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ( USERNAME_RX.indexIn( usernameSuggestion ) != -1 )
|
if ( USERNAME_RX.indexIn( usernameSuggestion ) != -1 )
|
||||||
{
|
{
|
||||||
@ -301,8 +318,8 @@ void
|
|||||||
UsersPage::validateUsernameText( const QString& textRef )
|
UsersPage::validateUsernameText( const QString& textRef )
|
||||||
{
|
{
|
||||||
QString text( textRef );
|
QString text( textRef );
|
||||||
QRegExp rx( USERNAME_RX );
|
QRegExpValidator val_whole( USERNAME_RX );
|
||||||
QRegExpValidator val( rx );
|
QRegExpValidator val_start( QRegExp( "[a-z_].*" ) ); // anchors are implicit in QRegExpValidator
|
||||||
int pos = -1;
|
int pos = -1;
|
||||||
|
|
||||||
if ( text.isEmpty() )
|
if ( text.isEmpty() )
|
||||||
@ -313,14 +330,21 @@ UsersPage::validateUsernameText( const QString& textRef )
|
|||||||
}
|
}
|
||||||
else if ( text.length() > USERNAME_MAX_LENGTH )
|
else if ( text.length() > USERNAME_MAX_LENGTH )
|
||||||
{
|
{
|
||||||
labelError( ui->labelUsername, ui->labelUsernameError,
|
labelError( ui->labelUsername, ui->labelUsernameError, tr( "Your username is too long." ) );
|
||||||
tr( "Your username is too long." ) );
|
|
||||||
m_readyUsername = false;
|
m_readyUsername = false;
|
||||||
}
|
}
|
||||||
else if ( val.validate( text, pos ) == QValidator::Invalid )
|
else if ( val_start.validate( text, pos ) == QValidator::Invalid )
|
||||||
{
|
{
|
||||||
labelError( ui->labelUsername, ui->labelUsernameError,
|
labelError( ui->labelUsername,
|
||||||
tr( "Your username contains invalid characters. Only lowercase letters and numbers are allowed." ) );
|
ui->labelUsernameError,
|
||||||
|
tr( "Your username must start with a lowercase letter or underscore." ) );
|
||||||
|
m_readyUsername = false;
|
||||||
|
}
|
||||||
|
else if ( val_whole.validate( text, pos ) == QValidator::Invalid )
|
||||||
|
{
|
||||||
|
labelError( ui->labelUsername,
|
||||||
|
ui->labelUsernameError,
|
||||||
|
tr( "Only lowercase letters, numbers, underscore and hyphen are allowed." ) );
|
||||||
m_readyUsername = false;
|
m_readyUsername = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -345,32 +369,30 @@ void
|
|||||||
UsersPage::validateHostnameText( const QString& textRef )
|
UsersPage::validateHostnameText( const QString& textRef )
|
||||||
{
|
{
|
||||||
QString text = textRef;
|
QString text = textRef;
|
||||||
QRegExp rx( HOSTNAME_RX );
|
QRegExpValidator val( HOSTNAME_RX );
|
||||||
QRegExpValidator val( rx );
|
|
||||||
int pos = -1;
|
int pos = -1;
|
||||||
|
|
||||||
if ( text.isEmpty() )
|
if ( text.isEmpty() )
|
||||||
{
|
{
|
||||||
ui->labelHostnameError->clear();
|
ui->labelHostnameError->clear();
|
||||||
ui->labelHostname->clear();
|
ui->labelHostname->clear();
|
||||||
m_readyHostname= false;
|
m_readyHostname = false;
|
||||||
}
|
}
|
||||||
else if ( text.length() < HOSTNAME_MIN_LENGTH )
|
else if ( text.length() < HOSTNAME_MIN_LENGTH )
|
||||||
{
|
{
|
||||||
labelError( ui->labelHostname, ui->labelHostnameError,
|
labelError( ui->labelHostname, ui->labelHostnameError, tr( "Your hostname is too short." ) );
|
||||||
tr( "Your hostname is too short." ) );
|
|
||||||
m_readyHostname = false;
|
m_readyHostname = false;
|
||||||
}
|
}
|
||||||
else if ( text.length() > HOSTNAME_MAX_LENGTH )
|
else if ( text.length() > HOSTNAME_MAX_LENGTH )
|
||||||
{
|
{
|
||||||
labelError( ui->labelHostname, ui->labelHostnameError,
|
labelError( ui->labelHostname, ui->labelHostnameError, tr( "Your hostname is too long." ) );
|
||||||
tr( "Your hostname is too long." ) );
|
|
||||||
m_readyHostname = false;
|
m_readyHostname = false;
|
||||||
}
|
}
|
||||||
else if ( val.validate( text, pos ) == QValidator::Invalid )
|
else if ( val.validate( text, pos ) == QValidator::Invalid )
|
||||||
{
|
{
|
||||||
labelError( ui->labelHostname, ui->labelHostnameError,
|
labelError( ui->labelHostname,
|
||||||
tr( "Your hostname contains invalid characters. Only letters, numbers and dashes are allowed." ) );
|
ui->labelHostnameError,
|
||||||
|
tr( "Only letters, numbers, underscore and hyphen are allowed." ) );
|
||||||
m_readyHostname = false;
|
m_readyHostname = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -382,46 +404,59 @@ UsersPage::validateHostnameText( const QString& textRef )
|
|||||||
emit checkReady( isReady() );
|
emit checkReady( isReady() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
UsersPage::onPasswordTextChanged( const QString& )
|
UsersPage::checkPasswordAcceptance( const QString& pw1, const QString& pw2, QLabel* badge, QLabel* message )
|
||||||
{
|
{
|
||||||
QString pw1 = ui->textBoxUserPassword->text();
|
|
||||||
QString pw2 = ui->textBoxUserVerifiedPassword->text();
|
|
||||||
|
|
||||||
// TODO: 3.3: remove empty-check and leave it to passwordRequirements
|
|
||||||
if ( pw1.isEmpty() && pw2.isEmpty() )
|
if ( pw1.isEmpty() && pw2.isEmpty() )
|
||||||
{
|
{
|
||||||
ui->labelUserPasswordError->clear();
|
// Not exactly labelOk() because we also don't want a checkmark OK
|
||||||
ui->labelUserPassword->clear();
|
badge->clear();
|
||||||
m_readyPassword = false;
|
message->clear();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else if ( pw1 != pw2 )
|
else if ( pw1 != pw2 )
|
||||||
{
|
{
|
||||||
labelError( ui->labelUserPassword, ui->labelUserPasswordError,
|
labelError( badge, message, tr( "Your passwords do not match!" ) );
|
||||||
tr( "Your passwords do not match!" ) );
|
return false;
|
||||||
m_readyPassword = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool ok = true;
|
bool failureIsFatal = ui->checkBoxValidatePassword->isChecked();
|
||||||
|
bool failureFound = false;
|
||||||
|
|
||||||
for ( auto pc : m_passwordChecks )
|
for ( auto pc : m_passwordChecks )
|
||||||
{
|
{
|
||||||
QString s = pc.filter( pw1 );
|
QString s = pc.filter( pw1 );
|
||||||
|
|
||||||
if ( !s.isEmpty() )
|
if ( !s.isEmpty() )
|
||||||
{
|
{
|
||||||
labelError( ui->labelUserPassword, ui->labelUserPasswordError, s );
|
labelError( badge, message, s, failureIsFatal ? Badness::Fatal : Badness::Warning );
|
||||||
ok = false;
|
failureFound = true;
|
||||||
m_readyPassword = false;
|
if ( failureIsFatal )
|
||||||
break;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ok )
|
if ( !failureFound )
|
||||||
{
|
{
|
||||||
labelOk( ui->labelUserPassword, ui->labelUserPasswordError );
|
labelOk( badge, message );
|
||||||
m_readyPassword = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Here, if failureFound is true then we've found **warnings**,
|
||||||
|
// which is ok to continue but the user should know.
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UsersPage::onPasswordTextChanged( const QString& )
|
||||||
|
{
|
||||||
|
m_readyPassword = checkPasswordAcceptance( ui->textBoxUserPassword->text(),
|
||||||
|
ui->textBoxUserVerifiedPassword->text(),
|
||||||
|
ui->labelUserPassword,
|
||||||
|
ui->labelUserPasswordError );
|
||||||
|
|
||||||
emit checkReady( isReady() );
|
emit checkReady( isReady() );
|
||||||
}
|
}
|
||||||
@ -429,48 +464,27 @@ UsersPage::onPasswordTextChanged( const QString& )
|
|||||||
void
|
void
|
||||||
UsersPage::onRootPasswordTextChanged( const QString& )
|
UsersPage::onRootPasswordTextChanged( const QString& )
|
||||||
{
|
{
|
||||||
QString pw1 = ui->textBoxRootPassword->text();
|
m_readyRootPassword = checkPasswordAcceptance( ui->textBoxRootPassword->text(),
|
||||||
QString pw2 = ui->textBoxVerifiedRootPassword->text();
|
ui->textBoxVerifiedRootPassword->text(),
|
||||||
|
ui->labelRootPassword,
|
||||||
// TODO: 3.3: remove empty-check and leave it to passwordRequirements
|
ui->labelRootPasswordError );
|
||||||
if ( pw1.isEmpty() && pw2.isEmpty() )
|
|
||||||
{
|
|
||||||
ui->labelRootPasswordError->clear();
|
|
||||||
ui->labelRootPassword->clear();
|
|
||||||
m_readyRootPassword = false;
|
|
||||||
}
|
|
||||||
else if ( pw1 != pw2 )
|
|
||||||
{
|
|
||||||
labelError( ui->labelRootPassword, ui->labelRootPasswordError,
|
|
||||||
tr( "Your passwords do not match!" ) );
|
|
||||||
m_readyRootPassword = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool ok = true;
|
|
||||||
for ( auto pc : m_passwordChecks )
|
|
||||||
{
|
|
||||||
QString s = pc.filter( pw1 );
|
|
||||||
if ( !s.isEmpty() )
|
|
||||||
{
|
|
||||||
labelError( ui->labelRootPassword, ui->labelRootPasswordError, s );
|
|
||||||
ok = false;
|
|
||||||
m_readyRootPassword = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ok )
|
|
||||||
{
|
|
||||||
labelOk( ui->labelRootPassword, ui->labelRootPasswordError );
|
|
||||||
m_readyRootPassword = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit checkReady( isReady() );
|
emit checkReady( isReady() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
UsersPage::setPasswordCheckboxVisible( bool visible )
|
||||||
|
{
|
||||||
|
ui->checkBoxValidatePassword->setVisible( visible );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UsersPage::setValidatePasswordDefault( bool checked )
|
||||||
|
{
|
||||||
|
ui->checkBoxValidatePassword->setChecked( checked );
|
||||||
|
emit checkReady( isReady() );
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UsersPage::setAutologinDefault( bool checked )
|
UsersPage::setAutologinDefault( bool checked )
|
||||||
{
|
{
|
||||||
@ -501,7 +515,9 @@ UsersPage::addPasswordCheck( const QString& key, const QVariant& value )
|
|||||||
{
|
{
|
||||||
add_check_libpwquality( m_passwordChecks, value );
|
add_check_libpwquality( m_passwordChecks, value );
|
||||||
}
|
}
|
||||||
#endif
|
#endif // CHECK_PWQUALITY
|
||||||
else
|
else
|
||||||
|
{
|
||||||
cWarning() << "Unknown password-check key" << key;
|
cWarning() << "Unknown password-check key" << key;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
class Page_UserSetup;
|
class Page_UserSetup;
|
||||||
@ -48,6 +50,8 @@ public:
|
|||||||
void onActivate();
|
void onActivate();
|
||||||
|
|
||||||
void setWriteRootPassword( bool show );
|
void setWriteRootPassword( bool show );
|
||||||
|
void setPasswordCheckboxVisible( bool visible );
|
||||||
|
void setValidatePasswordDefault( bool checked );
|
||||||
void setAutologinDefault( bool checked );
|
void setAutologinDefault( bool checked );
|
||||||
void setReusePasswordDefault( bool checked );
|
void setReusePasswordDefault( bool checked );
|
||||||
|
|
||||||
@ -73,16 +77,20 @@ signals:
|
|||||||
void checkReady( bool );
|
void checkReady( bool );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/** @brief Is the password acceptable?
|
||||||
|
*
|
||||||
|
* Checks the two copies of the password and places error messages in the
|
||||||
|
* given QLabels. Returns true (and clears the error messages) if the
|
||||||
|
* password is acceptable.
|
||||||
|
*/
|
||||||
|
bool checkPasswordAcceptance( const QString& pw1, const QString& pw2, QLabel* badge, QLabel* message );
|
||||||
|
|
||||||
|
void retranslate();
|
||||||
|
|
||||||
Ui::Page_UserSetup* ui;
|
Ui::Page_UserSetup* ui;
|
||||||
|
|
||||||
PasswordCheckList m_passwordChecks;
|
PasswordCheckList m_passwordChecks;
|
||||||
|
|
||||||
const QRegExp USERNAME_RX = QRegExp( "^[a-z_][a-z0-9_-]*[$]?$" );
|
|
||||||
const QRegExp HOSTNAME_RX = QRegExp( "^[a-zA-Z0-9][-a-zA-Z0-9_]*$" );
|
|
||||||
const int USERNAME_MAX_LENGTH = 31;
|
|
||||||
const int HOSTNAME_MIN_LENGTH = 2;
|
|
||||||
const int HOSTNAME_MAX_LENGTH = 63;
|
|
||||||
|
|
||||||
bool m_readyFullName;
|
bool m_readyFullName;
|
||||||
bool m_readyUsername;
|
bool m_readyUsername;
|
||||||
bool m_customUsername;
|
bool m_customUsername;
|
||||||
@ -94,4 +102,4 @@ private:
|
|||||||
bool m_writeRootPassword;
|
bool m_writeRootPassword;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // USERSPAGE_H
|
#endif // USERSPAGE_H
|
||||||
|
@ -29,22 +29,23 @@
|
|||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
#include "JobQueue.h"
|
#include "JobQueue.h"
|
||||||
|
|
||||||
CALAMARES_PLUGIN_FACTORY_DEFINITION( UsersViewStepFactory, registerPlugin<UsersViewStep>(); )
|
CALAMARES_PLUGIN_FACTORY_DEFINITION( UsersViewStepFactory, registerPlugin< UsersViewStep >(); )
|
||||||
|
|
||||||
UsersViewStep::UsersViewStep( QObject* parent )
|
UsersViewStep::UsersViewStep( QObject* parent )
|
||||||
: Calamares::ViewStep( parent )
|
: Calamares::ViewStep( parent )
|
||||||
, m_widget( new UsersPage() )
|
, m_widget( new UsersPage() )
|
||||||
{
|
{
|
||||||
emit nextStatusChanged( true );
|
emit nextStatusChanged( true );
|
||||||
connect( m_widget, &UsersPage::checkReady,
|
connect( m_widget, &UsersPage::checkReady, this, &UsersViewStep::nextStatusChanged );
|
||||||
this, &UsersViewStep::nextStatusChanged );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UsersViewStep::~UsersViewStep()
|
UsersViewStep::~UsersViewStep()
|
||||||
{
|
{
|
||||||
if ( m_widget && m_widget->parent() == nullptr )
|
if ( m_widget && m_widget->parent() == nullptr )
|
||||||
|
{
|
||||||
m_widget->deleteLater();
|
m_widget->deleteLater();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -116,68 +117,71 @@ UsersViewStep::onLeave()
|
|||||||
void
|
void
|
||||||
UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||||
{
|
{
|
||||||
if ( configurationMap.contains( "defaultGroups" ) &&
|
if ( configurationMap.contains( "defaultGroups" )
|
||||||
configurationMap.value( "defaultGroups" ).type() == QVariant::List )
|
&& configurationMap.value( "defaultGroups" ).type() == QVariant::List )
|
||||||
{
|
{
|
||||||
m_defaultGroups = configurationMap.value( "defaultGroups" ).toStringList();
|
m_defaultGroups = configurationMap.value( "defaultGroups" ).toStringList();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cWarning() << "Using fallback groups. Please check defaultGroups in users.conf";
|
cWarning() << "Using fallback groups. Please check defaultGroups in users.conf";
|
||||||
m_defaultGroups = QStringList{ "lp", "video", "network", "storage", "wheel", "audio" };
|
m_defaultGroups = QStringList { "lp", "video", "network", "storage", "wheel", "audio" };
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( configurationMap.contains( "autologinGroup" ) &&
|
if ( configurationMap.contains( "autologinGroup" )
|
||||||
configurationMap.value( "autologinGroup" ).type() == QVariant::String )
|
&& configurationMap.value( "autologinGroup" ).type() == QVariant::String )
|
||||||
{
|
{
|
||||||
Calamares::JobQueue::instance()->globalStorage()->insert( "autologinGroup",
|
Calamares::JobQueue::instance()->globalStorage()->insert(
|
||||||
configurationMap.value( "autologinGroup" ).toString() );
|
"autologinGroup", configurationMap.value( "autologinGroup" ).toString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( configurationMap.contains( "sudoersGroup" ) &&
|
if ( configurationMap.contains( "sudoersGroup" )
|
||||||
configurationMap.value( "sudoersGroup" ).type() == QVariant::String )
|
&& configurationMap.value( "sudoersGroup" ).type() == QVariant::String )
|
||||||
{
|
{
|
||||||
Calamares::JobQueue::instance()->globalStorage()->insert( "sudoersGroup",
|
Calamares::JobQueue::instance()->globalStorage()->insert( "sudoersGroup",
|
||||||
configurationMap.value( "sudoersGroup" ).toString() );
|
configurationMap.value( "sudoersGroup" ).toString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( configurationMap.contains( "setRootPassword" ) &&
|
if ( configurationMap.contains( "setRootPassword" )
|
||||||
configurationMap.value( "setRootPassword" ).type() == QVariant::Bool )
|
&& configurationMap.value( "setRootPassword" ).type() == QVariant::Bool )
|
||||||
{
|
{
|
||||||
Calamares::JobQueue::instance()->globalStorage()->insert( "setRootPassword",
|
Calamares::JobQueue::instance()->globalStorage()->insert(
|
||||||
configurationMap.value( "setRootPassword" ).toBool() );
|
"setRootPassword", configurationMap.value( "setRootPassword" ).toBool() );
|
||||||
m_widget->setWriteRootPassword( configurationMap.value( "setRootPassword" ).toBool() );
|
m_widget->setWriteRootPassword( configurationMap.value( "setRootPassword" ).toBool() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( configurationMap.contains( "doAutologin" ) &&
|
if ( configurationMap.contains( "doAutologin" )
|
||||||
configurationMap.value( "doAutologin" ).type() == QVariant::Bool )
|
&& configurationMap.value( "doAutologin" ).type() == QVariant::Bool )
|
||||||
{
|
{
|
||||||
m_widget->setAutologinDefault( configurationMap.value( "doAutologin" ).toBool() );
|
m_widget->setAutologinDefault( configurationMap.value( "doAutologin" ).toBool() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( configurationMap.contains( "doReusePassword" ) &&
|
if ( configurationMap.contains( "doReusePassword" )
|
||||||
configurationMap.value( "doReusePassword" ).type() == QVariant::Bool )
|
&& configurationMap.value( "doReusePassword" ).type() == QVariant::Bool )
|
||||||
{
|
{
|
||||||
m_widget->setReusePasswordDefault( configurationMap.value( "doReusePassword" ).toBool() );
|
m_widget->setReusePasswordDefault( configurationMap.value( "doReusePassword" ).toBool() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( configurationMap.contains( "passwordRequirements" ) &&
|
if ( configurationMap.contains( "passwordRequirements" )
|
||||||
configurationMap.value( "passwordRequirements" ).type() == QVariant::Map )
|
&& configurationMap.value( "passwordRequirements" ).type() == QVariant::Map )
|
||||||
{
|
{
|
||||||
auto pr_checks( configurationMap.value( "passwordRequirements" ).toMap() );
|
auto pr_checks( configurationMap.value( "passwordRequirements" ).toMap() );
|
||||||
|
|
||||||
for (decltype(pr_checks)::const_iterator i = pr_checks.constBegin();
|
for ( decltype( pr_checks )::const_iterator i = pr_checks.constBegin(); i != pr_checks.constEnd(); ++i )
|
||||||
i != pr_checks.constEnd(); ++i)
|
|
||||||
{
|
{
|
||||||
m_widget->addPasswordCheck( i.key(), i.value() );
|
m_widget->addPasswordCheck( i.key(), i.value() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_widget->setPasswordCheckboxVisible( CalamaresUtils::getBool( configurationMap, "allowWeakPasswords", false ) );
|
||||||
|
m_widget->setValidatePasswordDefault( !CalamaresUtils::getBool( configurationMap, "allowWeakPasswordsDefault", false) );
|
||||||
|
|
||||||
QString shell( QLatin1String( "/bin/bash" ) ); // as if it's not set at all
|
QString shell( QLatin1String( "/bin/bash" ) ); // as if it's not set at all
|
||||||
if ( configurationMap.contains( "userShell" ) )
|
if ( configurationMap.contains( "userShell" ) )
|
||||||
|
{
|
||||||
shell = CalamaresUtils::getString( configurationMap, "userShell" );
|
shell = CalamaresUtils::getString( configurationMap, "userShell" );
|
||||||
// Now it might be explicitly set to empty, which is ok
|
}
|
||||||
|
// Now it might be explicitly set to empty, which is ok
|
||||||
|
|
||||||
Calamares::JobQueue::instance()->globalStorage()->insert( "userShell", shell );
|
Calamares::JobQueue::instance()->globalStorage()->insert( "userShell", shell );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,4 +65,4 @@ private:
|
|||||||
|
|
||||||
CALAMARES_PLUGIN_FACTORY_DECLARATION( UsersViewStepFactory )
|
CALAMARES_PLUGIN_FACTORY_DECLARATION( UsersViewStepFactory )
|
||||||
|
|
||||||
#endif // USERSPAGEPLUGIN_H
|
#endif // USERSPAGEPLUGIN_H
|
||||||
|
@ -47,6 +47,9 @@
|
|||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Your Full Name</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -137,6 +140,9 @@
|
|||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>login</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -191,19 +197,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="username_extra_label_2">
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">font-weight: normal</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string notr="true"><Username extra label 2 text></string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_4">
|
<spacer name="verticalSpacer_4">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -246,6 +239,12 @@
|
|||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><small>This name will be used if you make the computer visible to others on a network.</small></string>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Computer Name</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -300,19 +299,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="hostname_extra_label_2">
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">font-weight: normal</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><small>This name will be used if you make the computer visible to others on a network.</small></string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_3">
|
<spacer name="verticalSpacer_3">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -355,9 +341,15 @@
|
|||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><small>Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.</small></string>
|
||||||
|
</property>
|
||||||
<property name="echoMode">
|
<property name="echoMode">
|
||||||
<enum>QLineEdit::Password</enum>
|
<enum>QLineEdit::Password</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Password</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -374,9 +366,15 @@
|
|||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><small>Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.</small></string>
|
||||||
|
</property>
|
||||||
<property name="echoMode">
|
<property name="echoMode">
|
||||||
<enum>QLineEdit::Password</enum>
|
<enum>QLineEdit::Password</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Repeat Password</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -431,19 +429,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="password_extra_label_3">
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">font-weight: normal</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><small>Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.</small></string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_5">
|
<spacer name="verticalSpacer_5">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -460,6 +445,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkBoxValidatePassword">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>When this box is checked, password-strength checking is done and you will not be able to use a weak password.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Require strong passwords.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="checkBoxAutoLogin">
|
<widget class="QCheckBox" name="checkBoxAutoLogin">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -516,9 +511,15 @@
|
|||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><small>Enter the same password twice, so that it can be checked for typing errors.</small></string>
|
||||||
|
</property>
|
||||||
<property name="echoMode">
|
<property name="echoMode">
|
||||||
<enum>QLineEdit::Password</enum>
|
<enum>QLineEdit::Password</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Password</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -535,9 +536,15 @@
|
|||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><small>Enter the same password twice, so that it can be checked for typing errors.</small></string>
|
||||||
|
</property>
|
||||||
<property name="echoMode">
|
<property name="echoMode">
|
||||||
<enum>QLineEdit::Password</enum>
|
<enum>QLineEdit::Password</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Repeat Password</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -592,19 +599,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="labelExtraRootPassword">
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">font-weight: normal</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><small>Enter the same password twice, so that it can be checked for typing errors.</small></string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_7">
|
<spacer name="verticalSpacer_7">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -27,26 +27,34 @@ defaultGroups:
|
|||||||
# the desktop environment on boot.
|
# the desktop environment on boot.
|
||||||
# Disable when your Distribution does not require such a group.
|
# Disable when your Distribution does not require such a group.
|
||||||
autologinGroup: autologin
|
autologinGroup: autologin
|
||||||
# You can control the initial state for the 'autologin checkbox' in UsersViewStep here.
|
# You can control the initial state for the 'autologin checkbox' here.
|
||||||
# Possible values are: true to enable or false to disable the checkbox by default
|
# Possible values are:
|
||||||
|
# - true to check or
|
||||||
|
# - false to uncheck
|
||||||
|
# These set the **initial** state of the checkbox.
|
||||||
doAutologin: true
|
doAutologin: true
|
||||||
|
|
||||||
# When set to a non-empty string, Calamares creates a sudoers file for the user.
|
# When *sudoersGroup* is set to a non-empty string, Calamares creates a
|
||||||
# /etc/sudoers.d/10-installer
|
# sudoers file for the user. This file is located at:
|
||||||
# Remember to add sudoersGroup to defaultGroups.
|
# `/etc/sudoers.d/10-installer`
|
||||||
|
# Remember to add the (value of) *sudoersGroup* to *defaultGroups*.
|
||||||
#
|
#
|
||||||
# If your Distribution already sets up a group of sudoers in its packaging,
|
# If your Distribution already sets up a group of sudoers in its packaging,
|
||||||
# remove this setting (delete or comment out the line below). Otherwise,
|
# remove this setting (delete or comment out the line below). Otherwise,
|
||||||
# the setting will be duplicated in the /etc/sudoers.d/10-installer file,
|
# the setting will be duplicated in the `/etc/sudoers.d/10-installer` file,
|
||||||
# potentially confusing users.
|
# potentially confusing users.
|
||||||
sudoersGroup: wheel
|
sudoersGroup: wheel
|
||||||
|
|
||||||
# Setting this to false , causes the root account to be disabled.
|
# Setting this to false , causes the root account to be disabled.
|
||||||
setRootPassword: true
|
setRootPassword: true
|
||||||
# You can control the initial state for the 'root password checkbox' in UsersViewStep here.
|
# You can control the initial state for the 'reuse password for root'
|
||||||
# Possible values are: true to enable or false to disable the checkbox by default.
|
# checkbox here. Possible values are:
|
||||||
# When enabled the user password is used for the root account too.
|
# - true to check or
|
||||||
# NOTE: doReusePassword requires setRootPassword to be enabled.
|
# - false to uncheck
|
||||||
|
#
|
||||||
|
# When checked, the user password is used for the root account too.
|
||||||
|
#
|
||||||
|
# NOTE: *doReusePassword* requires *setRootPassword* to be enabled.
|
||||||
doReusePassword: true
|
doReusePassword: true
|
||||||
|
|
||||||
# These are optional password-requirements that a distro can enforce
|
# These are optional password-requirements that a distro can enforce
|
||||||
@ -68,12 +76,36 @@ doReusePassword: true
|
|||||||
#
|
#
|
||||||
# (additional checks may be implemented in CheckPWQuality.cpp and
|
# (additional checks may be implemented in CheckPWQuality.cpp and
|
||||||
# wired into UsersPage.cpp)
|
# wired into UsersPage.cpp)
|
||||||
|
#
|
||||||
|
# - To disable specific password validations:
|
||||||
|
# comment out the relevant 'passwordRequirements' keys below.
|
||||||
|
# - To disable all password validations:
|
||||||
|
# set both 'allowWeakPasswords' and 'allowWeakPasswordsDefault' to true.
|
||||||
|
# (That will show the box *Allow weak passwords* in the user-
|
||||||
|
# interface, and check it by default).
|
||||||
passwordRequirements:
|
passwordRequirements:
|
||||||
minLength: -1 # Password at least this many characters
|
minLength: -1 # Password at least this many characters
|
||||||
maxLength: -1 # Password at most this many characters
|
maxLength: -1 # Password at most this many characters
|
||||||
libpwquality:
|
libpwquality:
|
||||||
- minlen=0
|
- minlen=0
|
||||||
- minclass=0
|
- minclass=0
|
||||||
|
|
||||||
|
# You can control the visibility of the 'strong passwords' checkbox here.
|
||||||
|
# Possible values are:
|
||||||
|
# - true to show or
|
||||||
|
# - false to hide (default)
|
||||||
|
# the checkbox. This checkbox allows the user to choose to disable
|
||||||
|
# password-strength-checks. By default the box is **hidden**, so
|
||||||
|
# that you have to pick a password that satisfies the checks.
|
||||||
|
allowWeakPasswords: false
|
||||||
|
# You can control the initial state for the 'strong passwords' checkbox here.
|
||||||
|
# Possible values are:
|
||||||
|
# - true to uncheck or
|
||||||
|
# - false to check (default)
|
||||||
|
# the checkbox by default. Since the box is labeled to enforce strong
|
||||||
|
# passwords, in order to **allow** weak ones by default, the box needs
|
||||||
|
# to be unchecked.
|
||||||
|
allowWeakPasswordsDefault: false
|
||||||
|
|
||||||
# Shell to be used for the regular user of the target system.
|
# Shell to be used for the regular user of the target system.
|
||||||
# There are three possible kinds of settings:
|
# There are three possible kinds of settings:
|
||||||
|
Loading…
Reference in New Issue
Block a user