From d5074436f7d8f9666fe1e6aac6d732ea62d182c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Andr=C3=A9e?= Date: Sat, 5 Dec 2015 21:09:45 +0100 Subject: [PATCH 1/2] Use libpassphrase when entering passwords. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libpassphrase can be compiled so that it can display the strength of the password, including telling the user that she is using a common passphrase. As a bonus, libpassphrase can be configured to do something else then just be slient without echoes. Signed-off-by: Mattias Andrée --- ChangeLog | 10 ++++++++ README | 1 + lib/Makefile.am | 6 +++-- lib/pwauth.c | 6 +++-- lib/xgetpass.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/xgetpass.h | 35 ++++++++++++++++++++++++++++ libmisc/pam_pass.c | 40 +++++++++++++++++++++++++++++++- src/gpasswd.c | 6 +++-- src/newgrp.c | 4 +++- src/passwd.c | 8 ++++--- src/sulogin.c | 6 +++-- 11 files changed, 176 insertions(+), 13 deletions(-) create mode 100644 lib/xgetpass.c create mode 100644 lib/xgetpass.h diff --git a/ChangeLog b/ChangeLog index 23cd5ae..bc43385 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2015-12-05 Mattias Andrée + + * lib/xgetpass.c: Add ability to use libpassphrase>=1449331105 instead of getpass. + * libmisc/pam_pass.c: Use xgetpass instead of misc_conv when entering (not retyping) the new password. + * lib/pwauth.c: Replace getpass with xgetpass. + * src/gpasswd.c: Likewise. + * src/newgrp.c: Likewise. + * src/passwd.c: Likewise. + * src/sulogin.c: Likewise. + 2014-05-09 Christian Perrier * Include patches only included in Debian for 4.2 diff --git a/README b/README index e531de6..5c27142 100644 --- a/README +++ b/README @@ -87,6 +87,7 @@ Leonard N. Zubkoff Luca Berra Lukáš Kuklínek Lutz Schwalowsky +Mattias Andrée Marc Ewing Martin Bene Martin Mares diff --git a/lib/Makefile.am b/lib/Makefile.am index 6db86cd..3fa3817 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -5,7 +5,7 @@ DEFS = noinst_LTLIBRARIES = libshadow.la -libshadow_la_LDFLAGS = -version-info 0:0:0 +libshadow_la_LDFLAGS = -version-info 0:0:0 -lpassphrase libshadow_la_SOURCES = \ commonio.c \ @@ -53,7 +53,9 @@ libshadow_la_SOURCES = \ shadowio.h \ shadowmem.c \ spawn.c \ - utent.c + utent.c \ + xgetpass.c \ + xgetpass.h if WITH_TCB libshadow_la_SOURCES += tcbfuncs.c tcbfuncs.h diff --git a/lib/pwauth.c b/lib/pwauth.c index 9e24fbf..6775465 100644 --- a/lib/pwauth.c +++ b/lib/pwauth.c @@ -3,6 +3,7 @@ * Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 2003 - 2006, Tomasz Kłoczko * Copyright (c) 2008 - 2009, Nicolas François + * Copyright (c) 2015 , Mattias Andrée * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,6 +46,7 @@ #include "defines.h" #include "pwauth.h" #include "getdef.h" +#include "xgetpass.h" #ifdef SKEY #include #endif @@ -161,7 +163,7 @@ int pw_auth (const char *cipher, #endif snprintf (prompt, sizeof prompt, cp, user); - clear = getpass (prompt); + clear = xgetpass (prompt, 0); if (NULL == clear) { static char c[1]; @@ -194,7 +196,7 @@ int pw_auth (const char *cipher, * -- AR 8/22/1999 */ if ((0 != retval) && ('\0' == input[0]) && use_skey) { - clear = getpass (prompt); + clear = xgetpass (prompt, 0); if (NULL == clear) { static char c[1]; diff --git a/lib/xgetpass.c b/lib/xgetpass.c new file mode 100644 index 0000000..a44ffc0 --- /dev/null +++ b/lib/xgetpass.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015 , Mattias Andrée + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the copyright holders or contributors may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#ident "$Id$" + +#include +#include +#include +#include +#include + +char *xgetpass (const char *prompt, int is_new) +{ + int fd, saved_errno; + char *pass; + + fd = open ("/dev/tty", O_RDWR); + if (-1 == fd) { + return NULL; + } + + passphrase_disable_echo1 (fd); + fprintf (stderr, "%s", prompt); + fflush (stderr); + pass = passphrase_read2 (fd, is_new + ? PASSPHRASE_READ_NEW | + PASSPHRASE_READ_SCREEN_FREE + : PASSPHRASE_READ_EXISTING); + saved_errno = errno; + passphrase_reenable_echo1 (fd); + errno = saved_errno; + return pass; + + /* + return getpass (prompt); + (void) is_new; + */ +} + diff --git a/lib/xgetpass.h b/lib/xgetpass.h new file mode 100644 index 0000000..b1abbb0 --- /dev/null +++ b/lib/xgetpass.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 , Mattias Andrée + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the copyright holders or contributors may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + */ + + +char *xgetpass (const char *prompt, int is_new); diff --git a/libmisc/pam_pass.c b/libmisc/pam_pass.c index a89bb2c..93029ec 100644 --- a/libmisc/pam_pass.c +++ b/libmisc/pam_pass.c @@ -2,6 +2,7 @@ * Copyright (c) 1997 - 1999, Marek Michałkiewicz * Copyright (c) 2001 - 2005, Tomasz Kłoczko * Copyright (c) 2008 , Nicolas François + * Copyright (c) 2015 , Mattias Andrée * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,22 +43,59 @@ #include #include #include +#include #include #include "defines.h" #include "pam_defs.h" #include "prototypes.h" +#include "xgetpass.h" + +static int xgetpass_conv (int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *appdata_ptr) +{ + struct pam_response *response; + static int first_enter = 0; + int current; + int saved_errno; + + if ((num_msg != 1) || (msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)) + return conv.conv (num_msg, msg, resp, appdata_ptr); + + response = calloc((size_t)1, sizeof(struct pam_response)); + if (response == NULL) { + return PAM_CONV_ERR; + } + + current = strchr(msg[0]->msg, '(') != NULL; + first_enter ^= !current; + response->resp_retcode = 0; + response->resp = xgetpass (msg[0]->msg, first_enter & !current); + if (response->resp == NULL) { + saved_errno = errno; + free(response); + errno = saved_errno; + return PAM_CONV_ERR; + } + + *resp = response; + return PAM_SUCCESS; +} + void do_pam_passwd (const char *user, bool silent, bool change_expired) { pam_handle_t *pamh = NULL; int flags = 0, ret; + struct pam_conv conv_proper = conv; + + conv_proper.conv = xgetpass_conv; if (silent) flags |= PAM_SILENT; if (change_expired) flags |= PAM_CHANGE_EXPIRED_AUTHTOK; - ret = pam_start ("passwd", user, &conv, &pamh); + ret = pam_start ("passwd", user, &conv_proper, &pamh); if (ret != PAM_SUCCESS) { fprintf (stderr, _("passwd: pam_start() failed, error %d\n"), ret); diff --git a/src/gpasswd.c b/src/gpasswd.c index 8959a35..811a93d 100644 --- a/src/gpasswd.c +++ b/src/gpasswd.c @@ -3,6 +3,7 @@ * Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 2001 - 2006, Tomasz Kłoczko * Copyright (c) 2007 - 2011, Nicolas François + * Copyright (c) 2015 , Mattias Andrée * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,6 +47,7 @@ #include "groupio.h" #include "nscd.h" #include "prototypes.h" +#include "xgetpass.h" #ifdef SHADOWGRP #include "sgroupio.h" #endif @@ -909,14 +911,14 @@ static void change_passwd (struct group *gr) printf (_("Changing the password for group %s\n"), group); for (retries = 0; retries < RETRIES; retries++) { - cp = getpass (_("New Password: ")); + cp = xgetpass (_("New Password: "), 1); if (NULL == cp) { exit (1); } STRFCPY (pass, cp); strzero (cp); - cp = getpass (_("Re-enter new password: ")); + cp = xgetpass (_("Re-enter new password: "), 0); if (NULL == cp) { exit (1); } diff --git a/src/newgrp.c b/src/newgrp.c index 49dd151..6ea3617 100644 --- a/src/newgrp.c +++ b/src/newgrp.c @@ -3,6 +3,7 @@ * Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 2001 - 2006, Tomasz Kłoczko * Copyright (c) 2007 - 2008, Nicolas François + * Copyright (c) 2015 , Mattias Andrée * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,6 +43,7 @@ #include "defines.h" #include "getdef.h" #include "prototypes.h" +#include "xgetpass.h" /*@-exitarg@*/ #include "exitcodes.h" @@ -171,7 +173,7 @@ static void check_perms (const struct group *grp, * get the password from her, and set the salt for * the decryption from the group file. */ - cp = getpass (_("Password: ")); + cp = xgetpass (_("Password: "), 0); if (NULL == cp) { goto failure; } diff --git a/src/passwd.c b/src/passwd.c index 3424f3b..c2cac67 100644 --- a/src/passwd.c +++ b/src/passwd.c @@ -3,6 +3,7 @@ * Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 2001 - 2006, Tomasz Kłoczko * Copyright (c) 2007 - 2011, Nicolas François + * Copyright (c) 2015 , Mattias Andrée * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,6 +56,7 @@ #include "pwauth.h" #include "pwio.h" #include "shadowio.h" +#include "xgetpass.h" /* * exit status values @@ -237,7 +239,7 @@ static int new_password (const struct passwd *pw) */ if (!amroot && ('\0' != crypt_passwd[0])) { - clear = getpass (_("Old password: ")); + clear = xgetpass (_("Old password: "), 1); if (NULL == clear) { return -1; } @@ -312,7 +314,7 @@ static int new_password (const struct passwd *pw) warned = false; for (i = getdef_num ("PASS_CHANGE_TRIES", 5); i > 0; i--) { - cp = getpass (_("New password: ")); + cp = xgetpass (_("New password: "), 1); if (NULL == cp) { memzero (orig, sizeof orig); return -1; @@ -339,7 +341,7 @@ static int new_password (const struct passwd *pw) warned = true; continue; } - cp = getpass (_("Re-enter new password: ")); + cp = xgetpass (_("Re-enter new password: "), 0); if (NULL == cp) { memzero (orig, sizeof orig); return -1; diff --git a/src/sulogin.c b/src/sulogin.c index ccbf2c5..1296856 100644 --- a/src/sulogin.c +++ b/src/sulogin.c @@ -3,6 +3,7 @@ * Copyright (c) 1996 - 2000, Marek Michałkiewicz * Copyright (c) 2002 - 2006, Tomasz Kłoczko * Copyright (c) 2007 - 2010, Nicolas François + * Copyright (c) 2015 , Mattias Andrée * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,6 +44,7 @@ #include "getdef.h" #include "prototypes.h" #include "pwauth.h" +#include "xgetpass.h" /*@-exitarg@*/ #include "exitcodes.h" @@ -202,10 +204,10 @@ static RETSIGTYPE catch_signals (unused int sig) */ /* get a password for root */ - cp = getpass (_( + cp = xgetpass (_( "\n" "Type control-d to proceed with normal startup,\n" -"(or give root password for system maintenance):")); +"(or give root password for system maintenance): "), 0); /* * XXX - can't enter single user mode if root password is * empty. I think this doesn't happen very often :-). But -- 2.6.3