Add optional libpwquality support for new LUKS passwords.

If password is entered through terminal (no keyfile specified)
and cryptsetup is compiled with --enable-pwquality, default
system pwquality settings are used to check password quality.
This commit is contained in:
Milan Broz
2012-12-19 17:25:11 +01:00
parent c950cf265f
commit e030e3bd15
7 changed files with 131 additions and 25 deletions

View File

@@ -91,6 +91,20 @@ AC_DEFUN([NO_FIPS], [
fi fi
]) ])
dnl ==========================================================================
dnl pwquality library (cryptsetup CLI only)
AC_ARG_ENABLE([pwquality], AS_HELP_STRING([--enable-pwquality],[enable password quality checking]),
[with_pwquality=$enableval],
[with_pwquality=no])
if test "x$with_pwquality" = "xyes"; then
AC_DEFINE(ENABLE_PWQUALITY, 1, [Enable password quality checking])
PKG_CHECK_MODULES([PWQUALITY], [pwquality >= 1.0.0],,
AC_MSG_ERROR([You need pwquality library.]))
PWQUALITY_STATIC_LIBS=$PWQUALITY_LIBS
fi
dnl ========================================================================== dnl ==========================================================================
dnl Crypto backend functions dnl Crypto backend functions
@@ -287,6 +301,9 @@ fi
AC_SUBST([DEVMAPPER_LIBS]) AC_SUBST([DEVMAPPER_LIBS])
AC_SUBST([DEVMAPPER_STATIC_LIBS]) AC_SUBST([DEVMAPPER_STATIC_LIBS])
AC_SUBST([PWQUALITY_LIBS])
AC_SUBST([PWQUALITY_STATIC_LIBS])
AC_SUBST([CRYPTO_CFLAGS]) AC_SUBST([CRYPTO_CFLAGS])
AC_SUBST([CRYPTO_LIBS]) AC_SUBST([CRYPTO_LIBS])
AC_SUBST([CRYPTO_STATIC_LIBS]) AC_SUBST([CRYPTO_STATIC_LIBS])

View File

@@ -752,6 +752,16 @@ actually belongs to the header given. In fact you can specify an
arbitrary device as the ciphertext device for \fIopen\fR arbitrary device as the ciphertext device for \fIopen\fR
with the \-\-header option. Use with care. with the \-\-header option. Use with care.
.TP .TP
.B "\-\-force-password\fR"
Do not use password quality checking for new LUKS passwords.
This option applies only to \fIluksFormat\fR, \fIluksAddKey\fR and
\fIluksChangeKey\fR and is ignored if cryptsetup is built without
password quality checking support.
For more info about password quality check, see manual page
for \fBpwquality.conf(5)\fR.
.TP
.B "\-\-version" .B "\-\-version"
Show the program version. Show the program version.
.TP .TP

View File

@@ -15,13 +15,15 @@ cryptsetup_SOURCES = \
$(top_builddir)/lib/utils_loop.c \ $(top_builddir)/lib/utils_loop.c \
$(top_builddir)/lib/utils_fips.c \ $(top_builddir)/lib/utils_fips.c \
utils_tools.c \ utils_tools.c \
utils_password.c \
cryptsetup.c \ cryptsetup.c \
cryptsetup.h cryptsetup.h
cryptsetup_LDADD = \ cryptsetup_LDADD = \
$(top_builddir)/lib/libcryptsetup.la \ $(top_builddir)/lib/libcryptsetup.la \
@POPT_LIBS@ \ @POPT_LIBS@ \
@FIPSCHECK_LIBS@ @FIPSCHECK_LIBS@ \
@PWQUALITY_LIBS@
cryptsetup_CFLAGS = -Wall cryptsetup_CFLAGS = -Wall
@@ -34,6 +36,7 @@ cryptsetup_static_CFLAGS = $(cryptsetup_CFLAGS)
cryptsetup_static_LDFLAGS = -all-static cryptsetup_static_LDFLAGS = -all-static
cryptsetup_static_LDADD = $(cryptsetup_LDADD) \ cryptsetup_static_LDADD = $(cryptsetup_LDADD) \
@CRYPTO_STATIC_LIBS@ \ @CRYPTO_STATIC_LIBS@ \
@PWQUALITY_STATIC_LIBS@ \
@DEVMAPPER_STATIC_LIBS@ \ @DEVMAPPER_STATIC_LIBS@ \
@UUID_LIBS@ @UUID_LIBS@
endif endif

View File

@@ -1369,7 +1369,8 @@ int main(int argc, const char **argv)
{ "header", '\0', POPT_ARG_STRING, &opt_header_device, 0, N_("Device or file with separated LUKS header."), NULL }, { "header", '\0', POPT_ARG_STRING, &opt_header_device, 0, N_("Device or file with separated LUKS header."), NULL },
{ "test-passphrase", '\0', POPT_ARG_NONE, &opt_test_passphrase, 0, N_("Do not activate device, just check passphrase."), NULL }, { "test-passphrase", '\0', POPT_ARG_NONE, &opt_test_passphrase, 0, N_("Do not activate device, just check passphrase."), NULL },
{ "hidden", '\0', POPT_ARG_NONE, &opt_hidden, 0, N_("Use hidden header (hidden TCRYPT device) ."), NULL }, { "hidden", '\0', POPT_ARG_NONE, &opt_hidden, 0, N_("Use hidden header (hidden TCRYPT device) ."), NULL },
{ "type", 'M', POPT_ARG_STRING, &opt_type, 0, N_("Type of device metadata: luks, plain, loopaes, tcrypt."), NULL }, { "type", 'M', POPT_ARG_STRING, &opt_type, 0, N_("Type of device metadata: luks, plain, loopaes, tcrypt."), NULL },
{ "force-password", '\0', POPT_ARG_NONE, &opt_force_password, 0, N_("Disable password quality check (if enabled)."), NULL },
POPT_TABLEEND POPT_TABLEEND
}; };
poptContext popt_context; poptContext popt_context;

View File

@@ -56,6 +56,7 @@
extern int opt_debug; extern int opt_debug;
extern int opt_verbose; extern int opt_verbose;
extern int opt_batch_mode; extern int opt_batch_mode;
extern int opt_force_password;
/* Common tools */ /* Common tools */
void clogger(struct crypt_device *cd, int level, const char *file, int line, void clogger(struct crypt_device *cd, int level, const char *file, int line,
@@ -74,6 +75,7 @@ extern volatile int quit;
void set_int_block(int block); void set_int_block(int block);
void set_int_handler(int block); void set_int_handler(int block);
void check_signal(int *r); void check_signal(int *r);
int tools_signals_blocked(void);
int tools_get_key(const char *prompt, int tools_get_key(const char *prompt,
char **key, size_t *key_size, char **key, size_t *key_size,

90
src/utils_password.c Normal file
View File

@@ -0,0 +1,90 @@
/*
* Password quality check wrapper
*
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012, Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "cryptsetup.h"
int opt_force_password = 0;
#if ENABLE_PWQUALITY
#include <pwquality.h>
static int tools_check_pwquality(const char *password)
{
int r;
void *auxerror;
pwquality_settings_t *pwq;
log_dbg("Checking new password using default pwquality settings.");
pwq = pwquality_default_settings();
if (!pwq)
return -EINVAL;
r = pwquality_read_config(pwq, NULL, &auxerror);
if (r) {
log_err(_("Cannot check passsword quality: %s\n"),
pwquality_strerror(NULL, 0, r, auxerror));
pwquality_free_settings(pwq);
return -EINVAL;
}
r = pwquality_check(pwq, password, NULL, NULL, &auxerror);
if (r < 0) {
log_err(_("Password quality check failed:\n %s\n"),
pwquality_strerror(NULL, 0, r, auxerror));
r = -EPERM;
} else {
log_dbg("New password libpwquality score is %d.", r);
r = 0;
}
pwquality_free_settings(pwq);
return r;
}
#else /* ENABLE_PWQUALITY */
static int tools_check_pwquality(const char *password)
{
return 0;
}
#endif /* ENABLE_PWQUALITY */
int tools_get_key(const char *prompt,
char **key, size_t *key_size,
size_t keyfile_offset, size_t keyfile_size_max,
const char *key_file,
int timeout, int verify, int pwquality,
struct crypt_device *cd)
{
int r, block;
block = tools_signals_blocked();
if (block)
set_int_block(0);
r = crypt_get_key(prompt, key, key_size, keyfile_offset,
keyfile_size_max, key_file, timeout, verify, cd);
if (block && !quit)
set_int_block(1);
/* Check pwquality for password (not keyfile) */
if (pwquality && !opt_force_password && !key_file && !r)
r = tools_check_pwquality(*key);
return r;
}

View File

@@ -35,6 +35,11 @@ static void int_handler(int sig __attribute__((__unused__)))
quit++; quit++;
} }
int tools_signals_blocked(void)
{
return signals_blocked;
}
void set_int_block(int block) void set_int_block(int block)
{ {
sigset_t signals_open; sigset_t signals_open;
@@ -67,28 +72,6 @@ void check_signal(int *r)
*r = -EINTR; *r = -EINTR;
} }
/* crypt_get_key() with signal handler */
int tools_get_key(const char *prompt,
char **key, size_t *key_size,
size_t keyfile_offset, size_t keyfile_size_max,
const char *key_file,
int timeout, int verify, int pwquality,
struct crypt_device *cd)
{
int r, block;
block = signals_blocked;
if (block)
set_int_block(0);
r = crypt_get_key(prompt, key, key_size, keyfile_offset,
keyfile_size_max, key_file, timeout, verify, cd);
if (block && !quit)
set_int_block(1);
return r;
}
__attribute__((format(printf, 5, 6))) __attribute__((format(printf, 5, 6)))
void clogger(struct crypt_device *cd, int level, const char *file, int line, void clogger(struct crypt_device *cd, int level, const char *file, int line,
const char *format, ...) const char *format, ...)
@@ -151,7 +134,7 @@ int yesDialog(const char *msg, void *usrptr __attribute__((unused)))
size_t size = 0; size_t size = 0;
int r = 1, block; int r = 1, block;
block = signals_blocked; block = tools_signals_blocked();
if (block) if (block)
set_int_block(0); set_int_block(0);