From e030e3bd15b6b94e2fded4502d1fa16100e99aef Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Wed, 19 Dec 2012 17:25:11 +0100 Subject: [PATCH] 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. --- configure.in | 17 ++++++++++ man/cryptsetup.8 | 10 ++++++ src/Makefile.am | 5 ++- src/cryptsetup.c | 3 +- src/cryptsetup.h | 2 ++ src/utils_password.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils_tools.c | 29 ++++------------- 7 files changed, 131 insertions(+), 25 deletions(-) create mode 100644 src/utils_password.c diff --git a/configure.in b/configure.in index ed84b2f..3922d55 100644 --- a/configure.in +++ b/configure.in @@ -92,6 +92,20 @@ AC_DEFUN([NO_FIPS], [ ]) 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 Crypto backend functions AC_DEFUN([CONFIGURE_GCRYPT], [ @@ -287,6 +301,9 @@ fi AC_SUBST([DEVMAPPER_LIBS]) AC_SUBST([DEVMAPPER_STATIC_LIBS]) +AC_SUBST([PWQUALITY_LIBS]) +AC_SUBST([PWQUALITY_STATIC_LIBS]) + AC_SUBST([CRYPTO_CFLAGS]) AC_SUBST([CRYPTO_LIBS]) AC_SUBST([CRYPTO_STATIC_LIBS]) diff --git a/man/cryptsetup.8 b/man/cryptsetup.8 index 41ad39f..5a294df 100644 --- a/man/cryptsetup.8 +++ b/man/cryptsetup.8 @@ -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 with the \-\-header option. Use with care. .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" Show the program version. .TP diff --git a/src/Makefile.am b/src/Makefile.am index f071acc..969aa6c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,13 +15,15 @@ cryptsetup_SOURCES = \ $(top_builddir)/lib/utils_loop.c \ $(top_builddir)/lib/utils_fips.c \ utils_tools.c \ + utils_password.c \ cryptsetup.c \ cryptsetup.h cryptsetup_LDADD = \ $(top_builddir)/lib/libcryptsetup.la \ @POPT_LIBS@ \ - @FIPSCHECK_LIBS@ + @FIPSCHECK_LIBS@ \ + @PWQUALITY_LIBS@ cryptsetup_CFLAGS = -Wall @@ -34,6 +36,7 @@ cryptsetup_static_CFLAGS = $(cryptsetup_CFLAGS) cryptsetup_static_LDFLAGS = -all-static cryptsetup_static_LDADD = $(cryptsetup_LDADD) \ @CRYPTO_STATIC_LIBS@ \ + @PWQUALITY_STATIC_LIBS@ \ @DEVMAPPER_STATIC_LIBS@ \ @UUID_LIBS@ endif diff --git a/src/cryptsetup.c b/src/cryptsetup.c index 3e66975..3659b73 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -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 }, { "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 }, - { "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 }; poptContext popt_context; diff --git a/src/cryptsetup.h b/src/cryptsetup.h index fa870b6..0eb9c55 100644 --- a/src/cryptsetup.h +++ b/src/cryptsetup.h @@ -56,6 +56,7 @@ extern int opt_debug; extern int opt_verbose; extern int opt_batch_mode; +extern int opt_force_password; /* Common tools */ 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_handler(int block); void check_signal(int *r); +int tools_signals_blocked(void); int tools_get_key(const char *prompt, char **key, size_t *key_size, diff --git a/src/utils_password.c b/src/utils_password.c new file mode 100644 index 0000000..795ba59 --- /dev/null +++ b/src/utils_password.c @@ -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 + +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; +} diff --git a/src/utils_tools.c b/src/utils_tools.c index 418f53e..6210536 100644 --- a/src/utils_tools.c +++ b/src/utils_tools.c @@ -35,6 +35,11 @@ static void int_handler(int sig __attribute__((__unused__))) quit++; } +int tools_signals_blocked(void) +{ + return signals_blocked; +} + void set_int_block(int block) { sigset_t signals_open; @@ -67,28 +72,6 @@ void check_signal(int *r) *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))) void clogger(struct crypt_device *cd, int level, const char *file, int line, const char *format, ...) @@ -151,7 +134,7 @@ int yesDialog(const char *msg, void *usrptr __attribute__((unused))) size_t size = 0; int r = 1, block; - block = signals_blocked; + block = tools_signals_blocked(); if (block) set_int_block(0); -- 2.7.4