From 5117e3f4dee4ad7ec766367842d7105c4c8bf9ba Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Sat, 7 Jul 2012 02:23:13 +0200 Subject: [PATCH] Add a mechanism to set the PIN Add DBus and libaccountsservice API to set the PIN for users, as well as pam-password-helper support to talk to pam_pin.so https://bugs.freedesktop.org/show_bug.cgi?id=51833 --- data/org.freedesktop.Accounts.User.xml | 49 ++++++++++++++++++ po/accounts-service.pot | 22 ++++---- src/libaccountsservice/act-user.c | 78 ++++++++++++++-------------- src/libaccountsservice/act-user.h | 4 ++ src/pam-password-helper.c | 17 +++++-- src/user.c | 87 ++++++++++++++++++++++++++++++++ 6 files changed, 202 insertions(+), 55 deletions(-) diff --git a/data/org.freedesktop.Accounts.User.xml b/data/org.freedesktop.Accounts.User.xml index 6ac7186..6c63526 100644 --- a/data/org.freedesktop.Accounts.User.xml +++ b/data/org.freedesktop.Accounts.User.xml @@ -497,6 +497,55 @@ + + + + + + The password. + + + + + + + The password hint. + + + + + + + The PIN + + + + + + + Sets a new password for this user. + + + Note that setting a PIN has the side-effect of + unlocking the account. + + + + The caller needs one of the following PolicyKit authorizations: + + + org.freedesktop.accounts.user-administration + To change the password of a user + + + + + if the caller lacks the appropriate PolicyKit authorization + if the operation failed + + + + diff --git a/po/accounts-service.pot b/po/accounts-service.pot index 550a494..d80fdea 100644 --- a/po/accounts-service.pot +++ b/po/accounts-service.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-03-17 14:45-0400\n" +"POT-Creation-Date: 2012-07-07 02:22+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,42 +18,42 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" #: ../data/org.freedesktop.accounts.policy.in.h:1 -msgid "Authentication is required to change the login screen configuration" +msgid "Change your own user data" msgstr "" #: ../data/org.freedesktop.accounts.policy.in.h:2 -msgid "Authentication is required to change user data" +msgid "Authentication is required to change your own user data" msgstr "" #: ../data/org.freedesktop.accounts.policy.in.h:3 -msgid "Authentication is required to change your own user data" +msgid "Manage user accounts" msgstr "" #: ../data/org.freedesktop.accounts.policy.in.h:4 -msgid "Change the login screen configuration" +msgid "Authentication is required to change user data" msgstr "" #: ../data/org.freedesktop.accounts.policy.in.h:5 -msgid "Change your own user data" +msgid "Change the login screen configuration" msgstr "" #: ../data/org.freedesktop.accounts.policy.in.h:6 -msgid "Manage user accounts" +msgid "Authentication is required to change the login screen configuration" msgstr "" -#: ../src/main.c:141 +#: ../src/main.c:93 msgid "Output version information and exit" msgstr "" -#: ../src/main.c:142 +#: ../src/main.c:94 msgid "Replace existing instance" msgstr "" -#: ../src/main.c:143 +#: ../src/main.c:95 msgid "Enable debugging code" msgstr "" -#: ../src/main.c:163 +#: ../src/main.c:115 msgid "" "Provides D-Bus interfaces for querying and manipulating\n" "user account information." diff --git a/src/libaccountsservice/act-user.c b/src/libaccountsservice/act-user.c index f42d00d..a07ee38 100644 --- a/src/libaccountsservice/act-user.c +++ b/src/libaccountsservice/act-user.c @@ -1448,42 +1448,6 @@ act_user_set_account_type (ActUser *user, } } -static gchar -salt_char (GRand *rand) -{ - gchar salt[] = "ABCDEFGHIJKLMNOPQRSTUVXYZ" - "abcdefghijklmnopqrstuvxyz" - "./0123456789"; - - return salt[g_rand_int_range (rand, 0, G_N_ELEMENTS (salt))]; -} - -static gchar * -make_crypted (const gchar *plain) -{ - GString *salt; - gchar *result; - GRand *rand; - gint i; - - rand = g_rand_new (); - salt = g_string_sized_new (21); - - /* SHA 256 */ - g_string_append (salt, "$6$"); - for (i = 0; i < 16; i++) { - g_string_append_c (salt, salt_char (rand)); - } - g_string_append_c (salt, '$'); - - result = g_strdup (crypt (plain, salt->str)); - - g_string_free (salt, TRUE); - g_rand_free (rand); - - return result; -} - /** * act_user_set_password: * @user: the user object to alter. @@ -1507,17 +1471,51 @@ act_user_set_password (ActUser *user, g_return_if_fail (password != NULL); g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy)); - crypted = make_crypted (password); if (!accounts_user_call_set_password_sync (user->accounts_proxy, - crypted, + password, hint, NULL, &error)) { g_warning ("SetPassword call failed: %s", error->message); g_error_free (error); } - memset (crypted, 0, strlen (crypted)); - g_free (crypted); +} + +/** + * act_user_set_pin: + * @user: the user object to alter. + * @password: the current user password + * @hint: a hint to help user recall password + * @pin: the new PIN + * + * Changes the password of @user to @password, and sets + * the PIN for local logins to @pin. + * @hint is displayed to the user if they forget the password. + * + * Note this function is synchronous and ignores errors. + **/ +void +act_user_set_pin (ActUser *user, + const gchar *password, + const gchar *hint, + const gchar *pin) +{ + GError *error = NULL; + gchar *crypted; + + g_return_if_fail (ACT_IS_USER (user)); + g_return_if_fail (password != NULL); + g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy)); + + if (!accounts_user_call_set_pin_sync (user->accounts_proxy, + password, + hint, + pin, + NULL, + &error)) { + g_warning ("SetPassword call failed: %s", error->message); + g_error_free (error); + } } /** diff --git a/src/libaccountsservice/act-user.h b/src/libaccountsservice/act-user.h index 7ce49fd..bedd8a2 100644 --- a/src/libaccountsservice/act-user.h +++ b/src/libaccountsservice/act-user.h @@ -97,6 +97,10 @@ void act_user_set_account_type (ActUser *user, void act_user_set_password (ActUser *user, const gchar *password, const gchar *hint); +void act_user_set_pin (ActUser *user, + const gchar *password, + const gchar *hint, + const gchar *pin); void act_user_set_password_mode (ActUser *user, ActUserPasswordMode password_mode); void act_user_set_locked (ActUser *user, diff --git a/src/pam-password-helper.c b/src/pam-password-helper.c index afcffc5..d569734 100644 --- a/src/pam-password-helper.c +++ b/src/pam-password-helper.c @@ -22,12 +22,14 @@ #include #include +#include #include #include #include #include -char *password; +const char *password; +const char *pin; static int answer_pam_message (int num_msg, @@ -43,7 +45,10 @@ answer_pam_message (int num_msg, into each question, and hope that configuration is correct. */ for (i = 0; i < num_msg; i++) { - resps[i].resp = strdup(password); + if (strcmp((*msg)[i].msg, "PIN") == 0) + resps[i].resp = pin ? strdup(pin) : NULL; + else + resps[i].resp = strdup(password); resps[i].resp_retcode = 0; } @@ -61,13 +66,17 @@ main (int argc, struct pam_conv conv = { answer_pam_message, NULL }; int res; - if (argc != 2) { - fprintf (stderr, "Wrong number of arguments passed, 1 expected\n"); + if (argc < 3) { + fprintf (stderr, "Wrong number of arguments passed, at least 2 expected\n"); return 1; } username = argv[1]; password = argv[2]; + if (argc == 4) + pin = argv[3]; + else + pin = NULL; res = pam_start ("accountsservice", username, &conv, &pamh); diff --git a/src/user.c b/src/user.c index 4625092..9cf3052 100644 --- a/src/user.c +++ b/src/user.c @@ -1551,6 +1551,92 @@ user_set_password (AccountsUser *auser, } static void +user_change_pin_authorized_cb (Daemon *daemon, + User *user, + GDBusMethodInvocation *context, + gpointer data) + +{ + gchar **strings = data; + GError *error; + const gchar *argv[6]; + + sys_log (context, + "set password and hint of user '%s' (%d)", + user->user_name, user->uid); + + g_object_freeze_notify (G_OBJECT (user)); + + argv[0] = LIBEXECDIR "/accounts-daemon-pam-password-helper"; + argv[1] = user->user_name; + argv[2] = strings[0]; + argv[3] = strings[2]; + argv[4] = NULL; + + error = NULL; + if (!spawn_with_login_uid (context, argv, &error)) { + throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); + g_error_free (error); + return; + } + + if (user->password_mode != PASSWORD_MODE_REGULAR) { + user->password_mode = PASSWORD_MODE_REGULAR; + g_object_notify (G_OBJECT (user), "password-mode"); + } + + if (user->locked) { + user->locked = FALSE; + g_object_notify (G_OBJECT (user), "locked"); + } + + if (g_strcmp0 (user->password_hint, strings[1]) != 0) { + g_free (user->password_hint); + user->password_hint = g_strdup (strings[1]); + g_object_notify (G_OBJECT (user), "password-hint"); + } + + save_extra_data (user); + + g_object_thaw_notify (G_OBJECT (user)); + + accounts_user_emit_changed (ACCOUNTS_USER (user)); + + accounts_user_complete_set_pin (ACCOUNTS_USER (user), context); +} + +static gboolean +user_set_pin (AccountsUser *auser, + GDBusMethodInvocation *context, + const gchar *password, + const gchar *hint, + const gchar *pin) +{ + User *user = (User*)auser; + gchar **data; + + data = g_new (gchar *, 3); + data[0] = g_strdup (password); + data[1] = g_strdup (hint); + data[2] = g_strdup (pin); + data[3] = NULL; + + daemon_local_check_auth (user->daemon, + user, + "org.freedesktop.accounts.user-administration", + TRUE, + user_change_pin_authorized_cb, + context, + data, + (GDestroyNotify)free_passwords); + + memset ((char*)password, 0, strlen (password)); + memset ((char*)pin, 0, strlen (pin)); + + return TRUE; +} + +static void user_change_automatic_login_authorized_cb (Daemon *daemon, User *user, GDBusMethodInvocation *context, @@ -1854,6 +1940,7 @@ user_accounts_user_iface_init (AccountsUserIface *iface) iface->handle_set_location = user_set_location; iface->handle_set_locked = user_set_locked; iface->handle_set_password = user_set_password; + iface->handle_set_pin = user_set_pin; iface->handle_set_password_mode = user_set_password_mode; iface->handle_set_real_name = user_set_real_name; iface->handle_set_shell = user_set_shell; -- 1.7.10.4