Hello community,
here is the log from the commit of package cryptconfig
checked in at Tue Mar 13 00:41:02 CET 2007.
--------
--- cryptconfig/cryptconfig.changes 2007-02-21 20:31:50.000000000 +0100
+++ /mounts/work_src_done/STABLE/cryptconfig/cryptconfig.changes 2007-03-12 18:19:50.189435000 +0100
@@ -1,0 +2,19 @@
+Mon Mar 12 18:19:30 CET 2007 - crivera@suse.de
+
+- Implement pam_sm_open_session() and pam_sm_close_session() for
+ pam_cryptpass. This lets us hook into the session stack, before pam_mount,
+ to verify that the authtok being used can decrypt the image key. If it
+ can't then we can prompt for the key password and sync the two. This
+ provides a much nicer experience for users of non-local auth mechanisms.
+ This fixes 253683.
+- Make root the owner of the unencrypted home directory. This is to avoid
+ confusion if the user logs in from a service that doesn't have pam_mount
+ in the stack. This fixes 245698.
+- Add a flag, --remove-data, that will remove the data in the user's
+ unencrypted home directory after it's been copied to the encrypted image.
+- Move the list of passwd services to cryptconfig.conf and add gnome-passwd
+ to the default list.
+- Add pam_cryptpass.so to the pam session stack before pam_mount to ensure
+ that the key file is in sync with the user's password. This fixes 253683.
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ cryptconfig.spec ++++++
--- /var/tmp/diff_new_pack.R12511/_old 2007-03-13 00:40:39.000000000 +0100
+++ /var/tmp/diff_new_pack.R12511/_new 2007-03-13 00:40:39.000000000 +0100
@@ -12,7 +12,7 @@
Name: cryptconfig
Version: 0.1.0
-Release: 15
+Release: 18
Group: System/Base
License: GNU Library General Public License v. 2.0 and 2.1 (LGPL)
Summary: A Utility to Configure Encrypted Home Directories and LUKS Partitions
@@ -62,6 +62,22 @@
%doc %{_mandir}/man8/cryptconfig.8.gz
%changelog
+* Mon Mar 12 2007 - crivera@suse.de
+- Implement pam_sm_open_session() and pam_sm_close_session() for
+ pam_cryptpass. This lets us hook into the session stack, before pam_mount,
+ to verify that the authtok being used can decrypt the image key. If it
+ can't then we can prompt for the key password and sync the two. This
+ provides a much nicer experience for users of non-local auth mechanisms.
+ This fixes 253683.
+- Make root the owner of the unencrypted home directory. This is to avoid
+ confusion if the user logs in from a service that doesn't have pam_mount
+ in the stack. This fixes 245698.
+- Add a flag, --remove-data, that will remove the data in the user's
+ unencrypted home directory after it's been copied to the encrypted image.
+- Move the list of passwd services to cryptconfig.conf and add gnome-passwd
+ to the default list.
+- Add pam_cryptpass.so to the pam session stack before pam_mount to ensure
+ that the key file is in sync with the user's password. This fixes 253683.
* Wed Feb 21 2007 - crivera@suse.de
- Remove 'su' from the list of pam config files to edit.
This fixes Bug 245702.
++++++ cryptconfig-0.1.0.tar.gz ++++++
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/cryptconfig-0.1.0/ChangeLog new/cryptconfig-0.1.0/ChangeLog
--- old/cryptconfig-0.1.0/ChangeLog 2007-02-21 20:21:01.000000000 +0100
+++ new/cryptconfig-0.1.0/ChangeLog 2007-03-05 22:56:19.000000000 +0100
@@ -1,3 +1,43 @@
+2007-03-05 Chris Rivera
+
+ * src/pam_cryptpass.c:
+
+ Implement pam_sm_open_session() and pam_sm_close_session(). This lets us
+ hook into the session stack, before pam_mount, to verify that the authtok
+ being used can decrypt the image key. If it can't then we can prompt
+ for the key password and sync the two. This provides a much nicer
+ experience for users of non-local auth mechanisms.
+
+ * src/cryptconfig.c:
+
+ Make root the owner of the unencrypted home directory. This is to avoid
+ confusion if the user logs in from a service that doesn't have pam_mount
+ in the stack. This fixes 245698.
+
+ Add a flag, --remove-data, that will remove the data in the user's
+ unencrypted home directory after it's been copied to the encrypted image.
+
+ * src/cryptconfig.h:
+
+ Remove unused PAM_PASSWD_CONF define.
+
+ * src/cryptconfig-lib.c:
+
+ Move the list of passwd services to cryptconfig.conf and add gnome-passwd
+ to the default list.
+
+ Add pam_cryptpass.so to the pam session stack before pam_mount to ensure
+ that the key file is in sync with the user's password.
+
+ Rename a few static functions to make them more accurate.
+
+ * run-cc-tests.py: update unit tests.
+
+2007-02-26 Chris Rivera
+
+ * src/cryptconfig-lib.c: Add an entry in cryptconfig.conf for pam passwd
+ services we need to modify and add gnome-passwd to the default list.
+
2007-02-21 Chris Rivera
* src/cryptconfig-lib.c: Add a check against a key file size threshold
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/cryptconfig-0.1.0/cryptconfig.conf new/cryptconfig-0.1.0/cryptconfig.conf
--- old/cryptconfig-0.1.0/cryptconfig.conf 2007-02-20 16:13:59.000000000 +0100
+++ new/cryptconfig-0.1.0/cryptconfig.conf 2007-02-26 21:22:17.000000000 +0100
@@ -1,2 +1,3 @@
[PAM]
Services=gdm;login;kdm;xdm;sudo
+PasswordServices=passwd;gnome-passwd
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/cryptconfig-0.1.0/src/cryptconfig.c new/cryptconfig-0.1.0/src/cryptconfig.c
--- old/cryptconfig-0.1.0/src/cryptconfig.c 2007-02-21 18:45:33.000000000 +0100
+++ new/cryptconfig-0.1.0/src/cryptconfig.c 2007-03-05 22:47:19.000000000 +0100
@@ -18,14 +18,18 @@
*
*/
+#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
+#include
#include
#include
+#include
+#include
#include "cryptconfig.h"
@@ -59,7 +63,7 @@
{
GError *err = NULL;
GOptionContext *ctx;
- gboolean ret, no_verify = FALSE, no_pam_mount = FALSE, final_ret = FALSE;
+ gboolean ret, no_verify = FALSE, no_pam_mount = FALSE, final_ret = FALSE, unlink_old_home = FALSE;
gboolean random_data = FALSE, no_copy = FALSE, force = FALSE, replace = FALSE;
gchar *key_file = NULL, *image_file = NULL, *existing_key_file = NULL;
gchar *fs_type = "ext3", *pass = NULL, *loop_device = NULL;
@@ -75,6 +79,7 @@
{ "no-copy", 0, 0, G_OPTION_ARG_NONE, &no_copy, N_("Don't copy user's existing data"), NULL },
{ "random", 0, 0, G_OPTION_ARG_NONE, &random_data, N_("Use random data to fill the image"), NULL },
{ "force", 0, 0, G_OPTION_ARG_NONE, &force, N_("Overwrite existing image and key"), NULL },
+ { "remove-data", 0, 0, G_OPTION_ARG_NONE, &unlink_old_home, N_("Remove the old home directory after data is copied"), NULL },
{ "replace", 0, 0, G_OPTION_ARG_NONE, &replace, N_("Replace an existing user entry in pam_mount"), NULL },
{ "fs-type", 0, 0, G_OPTION_ARG_STRING, &fs_type, N_("The filesystem type. The default is ext3"), NULL },
{ "image-file", 0, 0, G_OPTION_ARG_STRING, &image_file,
@@ -346,11 +351,28 @@
if (!copy_user_data (pent->pw_dir, temp_dir)) {
g_printerr (_("\nFailed to copy user data\n"));
goto cleanup;
+ } else if (unlink_old_home) {
+ if (!remove_home_directory (pent)) {
+ g_printerr ("\n%s\n", strerror (errno));
+ goto cleanup;
+ }
+
+ if (mkdir (pent->pw_dir, 0755)) {
+ g_printerr ("\nmkdir: %s\n", strerror (errno));
+ goto cleanup;
+ }
}
g_print (_("Done.\n"));
}
+ /* make root the owner of the unencrypted home directory */
+ if (chown (pent->pw_dir, 0, 0) ||
+ chmod (pent->pw_dir, 0755)) {
+ g_printerr ("%s\n", strerror (errno));
+ goto cleanup;
+ }
+
/* setup pam_mount unless told otherwise */
if (!no_pam_mount && !enable_pam_mount (user_field, image_file,
key_file ? key_file : existing_key_file)) {
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/cryptconfig-0.1.0/src/cryptconfig.h new/cryptconfig-0.1.0/src/cryptconfig.h
--- old/cryptconfig-0.1.0/src/cryptconfig.h 2007-02-21 20:09:47.000000000 +0100
+++ new/cryptconfig-0.1.0/src/cryptconfig.h 2007-03-05 22:15:03.000000000 +0100
@@ -15,7 +15,6 @@
#define KEY_FILE_SIZE_THRESHOLD 1048576
#define PAM_SERVICES_DIR "/etc/pam.d"
#define PAM_MOUNT_CONF "/etc/security/pam_mount.conf"
-#define PAM_PASSWD_CONF "/etc/pam.d/passwd"
#define CRYPTCONFIG_CONF SYSCONFDIR "/cryptconfig.conf"
gboolean luks_close (char *map_name);
@@ -62,4 +61,6 @@
gboolean get_random_key_data (gchar **key_data, size_t key_size);
gboolean temp_mount (char *fs_type, char *device, char **mount_point);
gboolean mount_dev (char *fs_type, char *device, char *mount_point);
+gboolean remove_home_directory (struct passwd *pent);
+
#endif
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/cryptconfig-0.1.0/src/cryptconfig-lib.c new/cryptconfig-0.1.0/src/cryptconfig-lib.c
--- old/cryptconfig-0.1.0/src/cryptconfig-lib.c 2007-02-21 20:22:32.000000000 +0100
+++ new/cryptconfig-0.1.0/src/cryptconfig-lib.c 2007-03-05 22:24:46.000000000 +0100
@@ -44,6 +44,7 @@
static long fs_min_sizes[] = { 10, 10, 40 };
static gchar *fs_list[] = { "ext3", "ext2", "reiserfs" };
static gchar *default_pam_services[] = { "gdm", "login", "kdm", "xdm", "sudo", NULL };
+static gchar *default_cryptpass_services[] = { "passwd", "gnome-passwd", NULL };
/*
* Manually copy the contents of old to new
@@ -292,68 +293,50 @@
}
/*
- * Add pam_cryptpass to the passwd service stack
+ * Get the list of pam services we need to modify. The list should
+ * be freed with g_strfreev(). We try and read the list from our
+ * conf and fall back to a default list if we have problems.
*/
-static gboolean enable_pam_cryptpass (void)
+static gchar **get_pam_services (gsize *size)
{
- FILE *fp;
- int fd;
- char buff[BUFF_SIZE];
-
- fd = open (PAM_PASSWD_CONF, O_RDWR | O_APPEND);
- if (fd == -1) {
- g_printerr (_("open: %s\n"), strerror (errno));
- return FALSE;
- }
-
- if (flock (fd, LOCK_EX)) {
- g_printerr (_("flock: %s\n"), strerror (errno));
- close (fd);
- return FALSE;
- }
-
- fp = fdopen (fd, "a+");
- if (!fp) {
- g_printerr (_("Failed to open pam"));
- close (fd);
- return FALSE;
- }
+ gchar **list = NULL, **ret = NULL;
+ GKeyFile *kf = g_key_file_new ();
+ gsize len;
+ int i;
- while (fgets (buff, BUFF_SIZE, fp)) {
- if (buff[0] != '#' && strstr (buff, "pam_cryptpass.so")) {
- fclose (fp);
- return TRUE;
+ if (!g_key_file_load_from_file (kf, CRYPTCONFIG_CONF, G_KEY_FILE_NONE, NULL) ||
+ !g_key_file_has_group (kf, "PAM")) {
+ g_printerr (_("Failed to load " CRYPTCONFIG_CONF ", using default list\n"));
+ list = g_strdupv (default_pam_services);
+ len = sizeof (default_pam_services) / sizeof (default_pam_services[0]) - 1;
+ } else {
+ list = g_key_file_get_string_list (kf, "PAM", "Services", &len, NULL);
+ if (!list) {
+ g_printerr (_("Failed to load service list from " CRYPTCONFIG_CONF ", using default list\n"));
+ list = g_strdupv (default_pam_services);
+ len = sizeof (default_pam_services) / sizeof (default_pam_services[0]) - 1;
}
}
- fprintf (fp, "password optional\tpam_cryptpass.so use_first_pass\n");
- fclose (fp);
- return TRUE;
-}
+ ret = g_new (gchar *, len + 1);
+ ret[len] = NULL;
+ *size = len;
-/*
- * The match_cb for removing cryptpass entries.
- */
-static gboolean disable_pam_cryptpass_cb (char *line, void *data)
-{
- return strstr (line, "pam_cryptpass.so") ? FALSE : TRUE;
-}
+ for (i = 0; i < len && list; i++) {
+ ret[i] = g_build_filename (PAM_SERVICES_DIR, list[i], NULL);
+ }
-/*
- * Remove pam_cryptpass from the passwd service stack
- */
-static gboolean disable_pam_cryptpass (void)
-{
- return filter_file (PAM_PASSWD_CONF, "passwd-XXXXXX",
- disable_pam_cryptpass_cb, NULL);
+ g_strfreev (list);
+ g_key_file_free (kf);
+ return ret;
}
/*
- * Get the list of pam services we need to modify. The list should
+ * Get the list of pam passwd services we need to modify. The list should
* be freed with g_strfreev(). We try and read the list from our
* conf and fall back to a default list if we have problems.
*/
-static gchar **get_pam_services (gsize *size)
+static gchar **get_pam_passwd_services (gsize *size)
{
gchar **list = NULL, **ret = NULL;
GKeyFile *kf = g_key_file_new ();
@@ -363,14 +346,14 @@
if (!g_key_file_load_from_file (kf, CRYPTCONFIG_CONF, G_KEY_FILE_NONE, NULL) ||
!g_key_file_has_group (kf, "PAM")) {
g_printerr (_("Failed to load " CRYPTCONFIG_CONF ", using default list\n"));
- list = g_strdupv (default_pam_services);
- len = sizeof (default_pam_services) / sizeof (default_pam_services[0]) - 1;
+ list = g_strdupv (default_cryptpass_services);
+ len = sizeof (default_cryptpass_services) / sizeof (default_cryptpass_services[0]) - 1;
} else {
- list = g_key_file_get_string_list (kf, "PAM", "Services", &len, NULL);
+ list = g_key_file_get_string_list (kf, "PAM", "PasswordServices", &len, NULL);
if (!list) {
g_printerr (_("Failed to load service list from " CRYPTCONFIG_CONF ", using default list\n"));
- list = g_strdupv (default_pam_services);
- len = sizeof (default_pam_services) / sizeof (default_pam_services[0]) - 1;
+ list = g_strdupv (default_cryptpass_services);
+ len = sizeof (default_cryptpass_services) / sizeof (default_cryptpass_services[0]) - 1;
}
}
@@ -388,9 +371,97 @@
}
/*
+ * Add pam_cryptpass to the passwd service stack
+ */
+static gboolean modify_pam_passwd_stacks (void)
+{
+ int i;
+ gchar **list;
+ gsize size;
+
+ list = get_pam_passwd_services (&size);
+ if (!list) {
+ g_printerr (_("Failed to get passwd services list\n"));
+ return FALSE;
+ }
+
+ for (i = 0; i < size; i++) {
+ FILE *fp;
+ int fd;
+ char buff[BUFF_SIZE];
+
+ fd = open (list[i], O_RDWR | O_APPEND);
+ if (fd == -1) {
+ g_printerr (_("open: %s\n"), strerror (errno));
+ return FALSE;
+ }
+
+ if (flock (fd, LOCK_EX)) {
+ g_printerr (_("flock: %s\n"), strerror (errno));
+ close (fd);
+ return FALSE;
+ }
+
+ fp = fdopen (fd, "a+");
+ if (!fp) {
+ g_printerr (_("Failed to open pam"));
+ close (fd);
+ return FALSE;
+ }
+
+ while (fgets (buff, BUFF_SIZE, fp)) {
+ if (buff[0] != '#' && strstr (buff, "pam_cryptpass.so")) {
+ fclose (fp);
+ return TRUE;
+ }
+ }
+
+ fprintf (fp, "password optional\tpam_cryptpass.so use_first_pass\n");
+ fclose (fp);
+ }
+
+ return TRUE;
+}
+
+/*
+ * The match_cb for removing cryptpass entries.
+ */
+static gboolean restore_pam_passwd_stacks_cb (char *line, void *data)
+{
+ return strstr (line, "pam_cryptpass.so") ? FALSE : TRUE;
+}
+
+/*
+ * Remove pam_cryptpass from the passwd service stack
+ */
+static gboolean restore_pam_passwd_stacks (void)
+{
+ int i;
+ gboolean ret = TRUE;
+ gchar **list;
+ gsize size;
+
+ list = get_pam_passwd_services (&size);
+ if (!list) {
+ g_printerr (_("Failed to get passwd services list\n"));
+ return FALSE;
+ }
+
+ for (i = 0; i < size; i++) {
+ if (g_file_test (list[i], G_FILE_TEST_EXISTS) &&
+ !filter_file (list[i], "passwd-XXXXXX",
+ restore_pam_passwd_stacks_cb, NULL)) {
+ ret = FALSE;
+ }
+ }
+
+ return ret;
+}
+
+/*
* Enable pam_mount in each of pam service configs.
*/
-static gboolean enable_pam_mount_services (void)
+static gboolean modify_pam_session_stacks (void)
{
gchar **list = NULL;
gboolean ret = TRUE;
@@ -413,7 +484,6 @@
fd = open (list[i], O_RDWR | O_APPEND);
if (fd == -1) {
- g_printerr (_("Unable to open '%s', skipping\n"), list[i]);
continue;
}
@@ -444,6 +514,7 @@
}
n = fprintf (config, "auth optional pam_mount.so use_first_pass\n"
+ "session optional pam_cryptpass.so\n"
"session required pam_mount.so\n");
if (n < 1)
ret = FALSE;
@@ -452,7 +523,7 @@
}
g_strfreev (list);
- return ret ? enable_pam_cryptpass () : FALSE;
+ return ret ? modify_pam_passwd_stacks () : FALSE;
}
/*
@@ -509,15 +580,16 @@
/*
* The match_cb for removing pam_mount.so entries.
*/
-static gboolean disable_pam_mount_services_cb (char *line, void *data)
+static gboolean restore_pam_session_stacks_cb (char *line, void *data)
{
- return strstr (line, "pam_mount.so") ? FALSE : TRUE;
+ return strstr (line, "pam_mount.so") ||
+ strstr (line, "pam_cryptpass.so") ? FALSE : TRUE;
}
/*
* Remove pam_mount from our pam service configs.
*/
-static gboolean disable_pam_mount_services (void)
+static gboolean restore_pam_session_stacks (void)
{
gchar **list;
gsize size;
@@ -533,14 +605,15 @@
if (!list[i])
break;
- if (!filter_file (list[i], "pam-service-XXXXXX",
- disable_pam_mount_services_cb, NULL)) {
+ if (g_file_test (list[i], G_FILE_TEST_EXISTS) &&
+ !filter_file (list[i], "pam-service-XXXXXX",
+ restore_pam_session_stacks_cb, NULL)) {
g_printerr (_("Failed to replace %s\n"), list[i]);
}
}
g_strfreev (list);
- return disable_pam_cryptpass ();
+ return restore_pam_passwd_stacks ();
}
/*
@@ -865,6 +938,7 @@
G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
NULL, NULL, NULL, NULL, &status, &err);
if (!ret) {
+ g_printerr ("%s\n", err->message);
g_error_free (err);
return FALSE;
}
@@ -1205,7 +1279,7 @@
fclose (fs);
if (n > 0)
- return enable_pam_mount_services ();
+ return modify_pam_session_stacks ();
else
return FALSE;
}
@@ -1240,7 +1314,7 @@
ret = filter_file (PAM_MOUNT_CONF, "pam-mount-conf-XXXXXX",
disable_pam_mount_cb, needle);
if (ret && !is_pam_mount_setup ())
- return disable_pam_mount_services ();
+ return restore_pam_session_stacks ();
else
return ret;
}
@@ -1261,7 +1335,7 @@
{
if (filter_file (PAM_MOUNT_CONF, "pam-mount-conf-XXXXXX",
disable_pam_mount_all_cb, NULL)) {
- return disable_pam_mount_services ();
+ return restore_pam_session_stacks ();
} else {
return FALSE;
}
@@ -1473,8 +1547,7 @@
}
/*
- * Mount device on a temporary directory. The mount_point string needs
- * to be freed by the caller.
+ * Mount device at mount_point.
*/
gboolean mount_dev (char *fs_type, char *device, char *mount_point)
{
@@ -1740,3 +1813,25 @@
g_free (extra_key_data);
return ret;
}
+
+/*
+ * Remove a user's home directory.
+ */
+gboolean remove_home_directory (struct passwd *pent)
+{
+ gchar *argv[] = { "/bin/rm", "-rf", pent->pw_dir, NULL };
+ GError *err;
+ gint status;
+ gboolean ret;
+
+ ret = g_spawn_sync (NULL, argv, NULL,
+ G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL, NULL, NULL, NULL, &status, &err);
+ if (!ret) {
+ g_printerr ("%s\n", err->message);
+ g_error_free (err);
+ return FALSE;
+ }
+
+ return WEXITSTATUS (status) ? FALSE : TRUE;
+}
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/cryptconfig-0.1.0/src/pam_cryptpass.c new/cryptconfig-0.1.0/src/pam_cryptpass.c
--- old/cryptconfig-0.1.0/src/pam_cryptpass.c 2007-02-20 20:55:48.000000000 +0100
+++ new/cryptconfig-0.1.0/src/pam_cryptpass.c 2007-03-08 23:05:47.000000000 +0100
@@ -36,7 +36,11 @@
#include
#define PAM_SM_PASSWORD
+#define PAM_SM_SESSION
+
#include
+#include
+#include
#include "cryptconfig.h"
@@ -107,6 +111,91 @@
return -1;
}
+/*
+ * There's a chance, when using non-local auth methods, that
+ * the key file password and the auth password will be out of
+ * sync. If we can detect this then we prompt for the old password
+ * and sync the key.
+ */
+static int prompt_for_old_auth_token (pam_handle_t *pamh, char **authtok)
+{
+ int ret;
+ struct pam_conv *conv = NULL;
+ struct pam_message msg;
+ const struct pam_message *pmsg = &msg;
+ struct pam_response *res = NULL;
+
+ ret = pam_get_item (pamh, PAM_CONV, (void *) &conv);
+ if (ret != PAM_SUCCESS || !conv) {
+ syslog (LOG_ERR, "Unable to get pam conversation data.\n");
+ return 1;
+ }
+
+ msg.msg_style = PAM_PROMPT_ECHO_OFF;
+ msg.msg = _("Enter key file password");
+
+ ret = conv->conv (1, &pmsg, &res, conv->appdata_ptr);
+ if (ret != PAM_SUCCESS || !res) {
+ syslog (LOG_ERR, "Unable to converse with the application.\n");
+ return 1;
+ }
+
+ *authtok = strdup (res->resp);
+ return 0;
+}
+
+/*
+ * Decrypt the key file with old_pw and encrypt it with new_pw.
+ */
+static int sync_key_file (const char *user, char *key_file, char *old_pw, char *new_pw)
+{
+ char *key_data = NULL;
+ struct passwd *pent;
+ int key_size, key_fd;
+ gboolean ret;
+
+ ret = decrypt_key (key_file, old_pw, &key_data, &key_size);
+ if (ret == FALSE) {
+ syslog (LOG_ERR, "Failed to decrypt key with old authtok\n");
+ return PAM_AUTHTOK_RECOVERY_ERR;
+ }
+
+ ret = encrypt_key (key_file, new_pw, key_data, key_size);
+ if (ret == FALSE) {
+ syslog (LOG_ERR, "Failed to encrypt key with new authtok\n");
+ free (key_data);
+ return PAM_AUTHTOK_ERR;
+ }
+
+ free (key_data);
+
+ /* change the owner of the fs key to the user */
+ pent = getpwnam (user);
+ if (!pent) {
+ syslog (LOG_ERR, "Failed to lookup user\n");
+ return PAM_AUTHTOK_ERR;
+ }
+
+ key_fd = open (key_file, O_RDONLY | O_NOFOLLOW);
+ if (key_fd == -1) {
+ syslog (LOG_ERR, "Failed to open %s: %s\n", key_file, strerror (errno));
+ return PAM_AUTHTOK_ERR;
+ }
+
+ if (fchown (key_fd, pent->pw_uid, 0)) {
+ syslog (LOG_ERR, "Failed to change the owner of %s: %s\n", key_file, strerror (errno));
+ close (key_fd);
+ return PAM_AUTHTOK_ERR;
+ }
+
+ close (key_fd);
+ syslog (LOG_INFO, "Password for %s was successfully changed.\n", key_file);
+ return PAM_SUCCESS;
+}
+
+/*
+ * The pam function called when the authok is changed.
+ */
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
@@ -141,9 +230,7 @@
*/
return PAM_SUCCESS;
} else if (flags & PAM_UPDATE_AUTHTOK) {
- char *pass_old, *pass_new, *key_data;
- struct passwd *pent;
- int key_size, key_fd;
+ char *pass_old = NULL, *pass_new = NULL;
/* update the password used to encrypt the key */
ret = pam_get_item (pamh, PAM_OLDAUTHTOK, (void *) &pass_old);
@@ -158,46 +245,70 @@
return PAM_AUTHTOK_ERR;
}
- ret = decrypt_key (key_file, pass_old, &key_data, &key_size);
- if (ret == FALSE) {
- syslog (LOG_ERR, "Failed to decrypt key with old authtok\n");
- return PAM_AUTHTOK_RECOVERY_ERR;
- }
+ return sync_key_file (user, key_file, pass_old, pass_new);
+ } else {
+ /* things are not good */
+ return PAM_ABORT;
+ }
+}
- ret = encrypt_key (key_file, pass_new, key_data, key_size);
- if (ret == FALSE) {
- syslog (LOG_ERR, "Failed to encrypt key with new authtok\n");
- free (key_data);
- return PAM_AUTHTOK_ERR;
- }
+/*
+ * We need this since we provide open_session, but we
+ * don't need to do anything
+ */
+PAM_EXTERN int pam_sm_close_session (pam_handle_t *pamh, int flags,
+ int argc, const char **argv)
+{
+ return PAM_IGNORE;
+}
- free (key_data);
-
- /* change the owner of the fs key to the user */
- pent = getpwnam (user);
- if (!pent) {
- syslog (LOG_ERR, "Failed to lookup user\n");
- return PAM_AUTHTOK_ERR;
- }
+/*
+ * We need to get the authtok pam_mount is going to try and use
+ * and make sure that we can decrypt the fs key. If we can't then
+ * the key is out of sync and we can prompt for the old authtok.
+ */
+PAM_EXTERN int pam_sm_open_session (pam_handle_t *pamh, int flags,
+ int argc, const char **argv)
+{
+ char *pass_curr = NULL, *pass_old = NULL, *key_data = NULL;
+ const char *user;
+ int ret, key_size;
+ char key_file[PATH_MAX];
+
+ /* Get the user name */
+ ret = pam_get_user (pamh, &user, NULL);
+ if (ret != PAM_SUCCESS)
+ return PAM_IGNORE;
- key_fd = open (key_file, O_RDONLY | O_NOFOLLOW);
- if (key_fd == -1) {
- syslog (LOG_ERR, "Failed to open %s: %s\n", key_file, strerror (errno));
- return PAM_AUTHTOK_ERR;
- }
+ /* Don't do anything if the user isn't using encrypted home dirs */
+ ret = get_key_file(user, key_file, PATH_MAX);
+ if (ret == -1)
+ return PAM_IGNORE;
- if (fchown (key_fd, pent->pw_uid, 0)) {
- syslog (LOG_ERR, "Failed to change the owner of %s: %s\n", key_file, strerror (errno));
- close (key_fd);
- return PAM_AUTHTOK_ERR;
- }
+ /*
+ * Get the authtok that pam_mount stores in the auth stack.
+ */
+ ret = pam_get_data (pamh, "pam_mount_system_authtok", (void *) &pass_curr);
+ if (ret != PAM_SUCCESS || pass_curr == NULL) {
+ syslog (LOG_ERR, "Failed to get pam_mount authtok\n");
+ return PAM_IGNORE;
+ }
- close (key_fd);
- syslog (LOG_INFO, "Password for %s was successfully changed.\n", key_file);
+ /*
+ * Try and decrypt the key. If we can't decrypt the key then
+ * we prompt for the old auth token.
+ */
+ if (!decrypt_key (key_file, pass_curr, &key_data, &key_size)) {
+ if (!prompt_for_old_auth_token (pamh, &pass_old)) {
+ int r = sync_key_file (user, key_file, pass_old, pass_curr);
+ free (pass_old);
+ return r;
+ } else {
+ syslog (LOG_ERR, "Failed to decrypt key with both authtoks\n");
+ return PAM_SESSION_ERR;
+ }
} else {
- /* things are not good */
- return PAM_ABORT;
+ free (key_data);
+ return PAM_SUCCESS;
}
-
- return PAM_SUCCESS;
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Remember to have fun...
---------------------------------------------------------------------
To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org
For additional commands, e-mail: opensuse-commit+help@opensuse.org