gnome-control-center/gnome-control-center-passwd-dialog.patch

1543 lines
47 KiB
Diff
Raw Normal View History

Index: gnome-control-center-2.19.4/capplets/Makefile.am
===================================================================
--- gnome-control-center-2.19.4.orig/capplets/Makefile.am
+++ gnome-control-center-2.19.4/capplets/Makefile.am
@@ -8,7 +8,8 @@ always_built_SUBDIRS = \
sound \
keybindings \
network \
- windows
+ windows \
+ passwd
SUBDIRS = $(always_built_SUBDIRS)
Index: gnome-control-center-2.19.4/capplets/passwd/ChangeLog
===================================================================
--- /dev/null
+++ gnome-control-center-2.19.4/capplets/passwd/ChangeLog
@@ -0,0 +1,2 @@
+2005-02-04 Shakti Sen <shprasad@novell.com>
+ * Added the password change GUI utility
Index: gnome-control-center-2.19.4/capplets/passwd/Makefile.am
===================================================================
--- /dev/null
+++ gnome-control-center-2.19.4/capplets/passwd/Makefile.am
@@ -0,0 +1,37 @@
+SUBDIRS = pam
+bin_PROGRAMS = gnome-passwd
+
+gnome_passwd_SOURCES = gnome-passwd.c \
+ pam-passwd.c \
+ pam-passwd.h
+gnome_passwd_LDADD = \
+ $(GNOMECC_CAPPLETS_LIBS) \
+ $(PASSWD_PAM_LIBS)
+
+@INTLTOOL_DESKTOP_RULE@
+
+Gladedir = $(pkgdatadir)/glade
+Glade_DATA = gnome-passwd.glade
+
+pixmapdir = $(pkgdatadir)/pixmaps
+pixmap_DATA = change-password.png
+
+desktopdir = $(datadir)/applications
+desktop_in_files = gnome-passwd.desktop.in
+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
+
+INCLUDES = \
+ $(GNOMECC_CAPPLETS_CFLAGS) \
+ $(PASSWD_PAM_INCLUDEDIR) \
+ -DGNOMELOCALEDIR="\"$(datadir)/locale\"" \
+ -DGNOMECC_DATA_DIR="\"$(pkgdatadir)\"" \
+ -DGNOMECC_GLADE_DIR="\"$(pkgdatadir)/glade\"" \
+ -DINSTALL_PREFIX=\"$(prefix)\"
+
+
+
+CLEANFILES = $(GNOMECC_CAPPLETS_CLEANFILES) $(desktop_in_files) $(desktop_DATA)
+EXTRA_DIST = $(glade_DATA) $(desktop_icons_DATA) $(desktop_in_files) $(desktop_DATA)
+
+install-exec-hook:
+ chmod o-r $(DESTDIR)$(bindir)/gnome-passwd
Index: gnome-control-center-2.19.4/capplets/passwd/gnome-passwd.c
===================================================================
--- /dev/null
+++ gnome-control-center-2.19.4/capplets/passwd/gnome-passwd.c
@@ -0,0 +1,214 @@
+/* gnome-passwd.c: password change capplet
+ *
+ * Copyright (C) 2005 Novell Inc.
+ *
+ * Written by: Shakti Sen <shprasad@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libgnome/libgnome.h>
+#include <gconf/gconf-client.h>
+#include <glade/glade.h>
+#include <gnome.h>
+#include <libgnomevfs/gnome-vfs-uri.h>
+#include <pwd.h>
+#include <X11/XKBlib.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkx.h>
+
+#include "capplet-util.h"
+#include "pam-passwd.h"
+
+static gboolean
+is_caps_lock_on ()
+{
+ Display *dsp;
+ gint states;
+ dsp = GDK_DISPLAY ();
+ if (XkbGetIndicatorState (dsp, XkbUseCoreKbd, &states) != Success)
+ return FALSE;
+
+ return (states & ShiftMask) != 0;
+
+}
+
+void
+cb_activate_entry_old_passwd (GtkEntry *entry, gpointer data)
+{
+ GtkWidget *new_passwd_entry;
+
+ new_passwd_entry = glade_xml_get_widget (GLADE_XML (data), "new_passwd_entry");
+ gtk_widget_grab_focus (new_passwd_entry);
+}
+
+void
+cb_activate_entry_new_passwd (GtkEntry *entry, gpointer data)
+{
+ GtkWidget *confirm_passwd_entry;
+
+ confirm_passwd_entry = glade_xml_get_widget (GLADE_XML (data), "confirm_passwd_entry");
+ gtk_widget_grab_focus (confirm_passwd_entry);
+}
+
+void
+cb_activate_entry_confirm_passwd (GtkEntry *entry, gpointer data)
+{
+ GtkWidget *ok_button;
+ GtkWidget *passwd_dialog;
+
+ ok_button = glade_xml_get_widget (GLADE_XML (data), "okbutton1");
+ passwd_dialog = glade_xml_get_widget (GLADE_XML (data), "passwd_dialog");
+
+ if (GTK_WIDGET_SENSITIVE (ok_button))
+ cb_dialog_response (GTK_DIALOG (passwd_dialog), GTK_RESPONSE_OK, data);
+}
+
+void
+cb_changed_confirmation_match (GtkEntry *entry, gpointer data)
+{
+ GtkWidget *new_passwd_entry;
+ GtkWidget *confirm_passwd_entry;
+ GtkWidget *status_label;
+ GtkWidget *ok_button;
+ gchar *new_passwd;
+ gchar *confirm_passwd;
+ gchar *message = NULL;
+ gboolean active = FALSE;
+
+ ok_button = glade_xml_get_widget (GLADE_XML (data), "okbutton1");
+
+ new_passwd_entry = glade_xml_get_widget (GLADE_XML (data), "new_passwd_entry");
+ new_passwd = g_strdup (gtk_entry_get_text (GTK_ENTRY (new_passwd_entry)));
+
+ confirm_passwd_entry = glade_xml_get_widget (GLADE_XML (data), "confirm_passwd_entry");
+ confirm_passwd = g_strdup (gtk_entry_get_text (GTK_ENTRY (confirm_passwd_entry)));
+ status_label = glade_xml_get_widget (GLADE_XML (data), "label4");
+
+ if (!strcmp (new_passwd, confirm_passwd)) {
+ if (strlen (new_passwd) == 0) {
+ message = _("New Password empty");
+ } else {
+ message = _("Passwords match");
+ active = TRUE;
+ }
+ } else
+ message = _("Passwords do not match");
+
+ gtk_widget_set_sensitive (ok_button, active);
+ gtk_label_set (GTK_LABEL (status_label), message);
+
+ g_free (new_passwd);
+ g_free (confirm_passwd);
+}
+
+static void
+setup_dialog (GladeXML *dialog)
+{
+ struct passwd* passwd_info = NULL;
+ uid_t cur_uid;
+ gchar *label;
+ GtkWidget *passwd_dialog;
+ GtkWidget *caps_lock_dialog;
+ GtkWidget *old_passwd_entry;
+ GtkWidget *new_passwd_entry;
+ GtkWidget *confirm_passwd_entry;
+ GtkWidget *old_passwd_label;
+ GtkWidget *ok_button;
+
+ GtkWidget *widget = glade_xml_get_widget (dialog, "label1");
+ ok_button = glade_xml_get_widget (dialog, "okbutton1");
+
+ cur_uid = getuid ();
+ passwd_info = getpwuid (cur_uid);
+
+ label = g_strdup_printf (_("<b>Changing Password for User '%s'</b>"), passwd_info->pw_name);
+ gtk_label_set_markup (GTK_LABEL (widget), label);
+ g_free (label);
+ g_signal_connect (WID ("passwd_dialog"), "response",
+ G_CALLBACK (cb_dialog_response), dialog);
+ g_signal_connect (WID ("passwd_dialog"), "destroy",
+ G_CALLBACK (gtk_main_quit), dialog);
+ old_passwd_entry = glade_xml_get_widget (dialog, "old_passwd_entry");
+ new_passwd_entry = glade_xml_get_widget (dialog, "new_passwd_entry");
+ confirm_passwd_entry = glade_xml_get_widget (dialog, "confirm_passwd_entry");
+ g_signal_connect (old_passwd_entry, "activate",
+ G_CALLBACK (cb_activate_entry_old_passwd), dialog);
+ g_signal_connect (new_passwd_entry, "activate",
+ G_CALLBACK (cb_activate_entry_new_passwd), dialog);
+ g_signal_connect (confirm_passwd_entry, "activate",
+ G_CALLBACK (cb_activate_entry_confirm_passwd), dialog);
+
+ g_signal_connect (confirm_passwd_entry, "changed",
+ G_CALLBACK (cb_changed_confirmation_match), dialog);
+ g_signal_connect (new_passwd_entry, "changed",
+ G_CALLBACK (cb_changed_confirmation_match), dialog);
+ cb_changed_confirmation_match(NULL, dialog);
+
+ if (cur_uid == 0) {
+ old_passwd_label = glade_xml_get_widget (dialog, "oldlabel");
+ gtk_widget_set_sensitive (old_passwd_entry, FALSE);
+ gtk_widget_set_sensitive (old_passwd_label, FALSE);
+ gtk_widget_grab_focus (new_passwd_entry);
+ }
+ else
+ gtk_widget_grab_focus (old_passwd_entry);
+
+
+ gtk_widget_set_sensitive (ok_button, FALSE);
+ passwd_dialog = WID ("passwd_dialog");
+ capplet_set_icon (passwd_dialog, "change-password");
+ gtk_widget_show_all (passwd_dialog);
+
+ if (is_caps_lock_on ()) {
+ caps_lock_dialog = gtk_message_dialog_new (GTK_WINDOW (passwd_dialog),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ _("You have got capslock on!\nPasswords are case-sensitive."));
+
+ g_signal_connect (G_OBJECT (caps_lock_dialog), "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+ gtk_widget_show (caps_lock_dialog);
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ GladeXML *dialog;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ gnome_program_init ("gnome-passwd", VERSION,
+ LIBGNOMEUI_MODULE,
+ argc, argv, GNOME_PARAM_NONE);
+
+ dialog = glade_xml_new (GNOMECC_DATA_DIR "/glade/gnome-passwd.glade",
+ "passwd_dialog", NULL);
+
+ setup_dialog (dialog);
+ gtk_main ();
+
+ return 0;
+}
Index: gnome-control-center-2.19.4/capplets/passwd/gnome-passwd.desktop.in.in
===================================================================
--- /dev/null
+++ gnome-control-center-2.19.4/capplets/passwd/gnome-passwd.desktop.in.in
@@ -0,0 +1,15 @@
+[Desktop Entry]
+Encoding=UTF-8
+_Name=Change Password
+_Comment=Change your password
+Exec=gnome-passwd
+Icon=change-password-48
+Terminal=false
+Type=Application
+StartupNotify=true
+Categories=GNOME;Settings;
+OnlyShowIn=GNOME;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=control-center
+X-GNOME-Bugzilla-Component=password
+X-GNOME-Bugzilla-Version=@VERSION@
Index: gnome-control-center-2.19.4/capplets/passwd/gnome-passwd.glade
===================================================================
--- /dev/null
+++ gnome-control-center-2.19.4/capplets/passwd/gnome-passwd.glade
@@ -0,0 +1,318 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+<requires lib="gnome"/>
+
+<widget class="GtkDialog" id="passwd_dialog">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Change Password</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">False</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="icon">change-password.png</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="has_separator">False</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="cancelbutton1">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="okbutton1">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">True</property>
+ <property name="label">gtk-ok</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-5</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">6</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+
+ <child>
+ <widget class="GtkLabel" id="oldlabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Old Password:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">old_passwd_entry</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="newlabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_New Password:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">new_passwd_entry</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="confirmlabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Confirm Password:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">confirm_passwd_entry</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="old_passwd_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">False</property>
+ <property name="max_length">1024</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="new_passwd_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">False</property>
+ <property name="max_length">1024</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="confirm_passwd_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">False</property>
+ <property name="max_length">1024</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Changing Password for User '%s'&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">6</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">6</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Password confirmation empty</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_CENTER</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
Index: gnome-control-center-2.19.4/capplets/passwd/pam-passwd.c
===================================================================
--- /dev/null
+++ gnome-control-center-2.19.4/capplets/passwd/pam-passwd.c
@@ -0,0 +1,255 @@
+/* pam-passwd.c: password change capplet
+ *
+ * Copyright (C) 2005 Novell Inc.
+ *
+ * Written by: Shakti Sen <shprasad@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <libgnome/libgnome.h>
+#include <glade/glade.h>
+#include <glib.h>
+#include <glade/glade.h>
+#include <gnome.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include "config.h"
+#include "pam-passwd.h"
+
+gboolean
+chpasswd_write (gint fd, gchar *msg, gint msg_len) {
+
+ while (msg_len > 0) {
+ gint bytes_written;
+
+ bytes_written = write (fd, msg, msg_len);
+
+ if (bytes_written < 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ return FALSE;
+ }
+
+ msg = msg + bytes_written;
+ msg_len -= bytes_written;
+ }
+ return TRUE;
+}
+
+#define OUTPUT_MAX 16384
+
+gboolean
+authenticate_and_change_passwd (gchar* old_passwd,
+ gchar* new_passwd,
+ gchar* confirm_passwd,
+ GError** error)
+{
+ gint childExitStat = 0;
+ gint child_pid;
+ gint std_input;
+ gint std_output;
+ gint std_error;
+ gint errCode = 0;
+ gboolean retval;
+ GString *snd_old_passwd;
+ GString *snd_new_passwd;
+ GString *snd_confirm_passwd;
+ gchar* command[] = {INSTALL_PREFIX "/sbin/change-passwd", NULL};
+ gchar output [OUTPUT_MAX];
+ gint output_i = 0;
+
+#ifdef DEBUG
+ gchar ch;
+#endif
+
+ snd_old_passwd = g_string_new (OLD_PASSWD_MSG_TITLE);
+ snd_old_passwd = g_string_append (snd_old_passwd, old_passwd);
+
+ snd_new_passwd = g_string_new (NEW_PASSWD_MSG_TITLE);
+ snd_new_passwd = g_string_append (snd_new_passwd, new_passwd);
+
+ snd_confirm_passwd = g_string_new (CONFIRM_PASSWD_MSG_TITLE);
+ snd_confirm_passwd = g_string_append (snd_confirm_passwd, confirm_passwd);
+
+ retval = g_spawn_async_with_pipes (NULL,
+ command,
+ NULL,
+ G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL,
+ NULL,
+ &child_pid,
+ &std_input,
+ &std_output,
+ &std_error,
+ error);
+ if (!retval) {
+ g_set_error (error, 0, errno, _("Could not start helper program.\nCould not change password"));
+ return FALSE;
+ }
+
+ if (write (std_input, (void *)&(snd_old_passwd->len), sizeof (snd_old_passwd->len)) < 0) {
+ g_set_error (error, 0, errno, _("Unknown error while changing password.\nCould not change password"));
+ return FALSE;
+ }
+ if (!chpasswd_write (std_input, snd_old_passwd->str, snd_old_passwd->len)) {
+ g_set_error (error, 0, errno, _("Unknown error while changing password.\nCould not change password"));
+ return FALSE;
+ }
+
+ if (write (std_input, (void *)&(snd_new_passwd->len), sizeof (snd_new_passwd->len)) < 0) {
+ g_set_error (error, 0, errno, _("Unknown error while changing password.\nCould not change password"));
+ return FALSE;
+ }
+ if (!chpasswd_write (std_input, snd_new_passwd->str, snd_new_passwd->len)) {
+ g_set_error (error, 0, errno, _("Unknown error while changing password.\nCould not change password"));
+ return FALSE;
+ }
+
+ if (write (std_input, (void *)&(snd_confirm_passwd->len), sizeof (snd_confirm_passwd->len)) < 0) {
+ g_set_error (error, 0, errno, _("Unknown error while changing password.\nCould not change password"));
+ return FALSE;
+ }
+ if (!chpasswd_write (std_input, snd_confirm_passwd->str, snd_confirm_passwd->len)) {
+ g_set_error (error, 0, errno, _("Unknown error while changing password.\nCould not change password"));
+ return FALSE;
+ }
+
+ while (output_i < OUTPUT_MAX - 1 && read (std_error, &output [output_i], 1))
+ output_i++;
+
+ /* Eliminate trailing newlines */
+ do {
+ output [output_i--] = '\0';
+ } while (output_i >= 0 && output [output_i] == '\n');
+
+ waitpid (child_pid, &childExitStat, 0);
+
+ /* Use the errCode for displaying errors. */
+ if (WIFEXITED (childExitStat)) {
+ errCode = WEXITSTATUS (childExitStat);
+
+ switch (errCode) {
+ case 0:
+ g_set_error (error, 0, errCode, _("Password changed successfully"));
+ return TRUE;
+ case 7:
+ g_set_error (error, 0, errCode, _("Old password doesn't match. Please try again."));
+ return FALSE;
+ case 101:
+ g_set_error (error, 0, errCode, _("Password is insecure.\nPlease choose a new password."));
+ return FALSE;
+ case 102:
+ g_set_error (error, 0, errCode, _("Password confirmation doesn't match New Password.\nPlease retype new password and confirmation"));
+ return FALSE;
+ case 121:
+ g_set_error (error, 0, errCode, _("Protocol error"));
+ return FALSE;
+ default:
+ if (output [0] != '\0')
+ g_set_error (error, 0, errCode, output);
+ else
+ g_set_error (error, 0, errCode, _("Unknown error while changing password.\nCould not change password"));
+ return FALSE;
+ }
+ }
+
+
+ g_set_error (error, 0, errCode, _("Unknown error while changing password.\nCould not change password"));
+ return FALSE;
+}
+
+void
+cb_dialog_response (GtkDialog *dialog, gint response_id, gpointer data)
+{
+ if (response_id == GTK_RESPONSE_HELP)
+ /* Documentation not available */;
+
+ if (response_id == GTK_RESPONSE_OK) {
+ GtkWidget *old_passwd_entry;
+ GtkWidget *new_passwd_entry;
+ GtkWidget *conf_passwd_entry;
+ GtkWidget *ok_button;
+ GladeXML *xml = GLADE_XML (data);
+ GtkWidget *ok_dialog;
+ GtkWidget *err_dialog;
+ GtkWidget *status_label;
+ GError* error = NULL;
+ gchar *old_passwd = NULL;
+ gchar *new_passwd = NULL;
+ gchar *conf_passwd = NULL;
+ uid_t uid;
+ struct passwd* cur_user_passwd = NULL;
+
+ uid = getuid ();
+ cur_user_passwd = getpwuid (uid);
+
+ ok_button = glade_xml_get_widget (xml, "okbutton1");
+ status_label = glade_xml_get_widget (xml, "label4");
+
+ old_passwd_entry = glade_xml_get_widget (xml, "old_passwd_entry");
+ old_passwd = g_strdup (gtk_entry_get_text (GTK_ENTRY (old_passwd_entry)));
+ new_passwd_entry = glade_xml_get_widget (xml, "new_passwd_entry");
+ new_passwd = g_strdup (gtk_entry_get_text (GTK_ENTRY (new_passwd_entry)));
+
+ conf_passwd_entry = glade_xml_get_widget (xml, "confirm_passwd_entry");
+ conf_passwd = g_strdup (gtk_entry_get_text (GTK_ENTRY (conf_passwd_entry)));
+
+ if (!authenticate_and_change_passwd (old_passwd, new_passwd, conf_passwd, &error)) {
+
+ err_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ error->message);
+ gtk_widget_show (err_dialog);
+ gtk_dialog_run (GTK_DIALOG (err_dialog));
+ gtk_widget_destroy (GTK_WIDGET (err_dialog));
+ gtk_widget_set_sensitive (ok_button, FALSE);
+ gtk_entry_set_text (GTK_ENTRY (old_passwd_entry), "");
+ gtk_entry_set_text (GTK_ENTRY (new_passwd_entry), "");
+ gtk_entry_set_text (GTK_ENTRY (conf_passwd_entry), "");
+ if (uid == 0)
+ gtk_widget_grab_focus (new_passwd_entry);
+ else
+ gtk_widget_grab_focus (old_passwd_entry);
+ return;
+ }
+ else {
+ if (error->code == 0) {
+ ok_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ _("Success:\n%s"),
+ error->message);
+ gtk_widget_show (ok_dialog);
+ gtk_dialog_run (GTK_DIALOG (ok_dialog));
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ gtk_main_quit ();
+ }
+ }
+ }
+ if (response_id == GTK_RESPONSE_CANCEL) {
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ gtk_main_quit ();
+ }
+}
Index: gnome-control-center-2.19.4/capplets/passwd/pam-passwd.h
===================================================================
--- /dev/null
+++ gnome-control-center-2.19.4/capplets/passwd/pam-passwd.h
@@ -0,0 +1,48 @@
+/* pam-passwd.h: password change capplet
+ *
+ * Copyright (C) 2005 Novell Inc.
+ *
+ * Written by: Shakti Sen <shprasad@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __PAM_PASSWD_H
+#define __PAM_PASSWD_H
+
+#include <gnome.h>
+
+#define OLD_PASSWD_MSG_TITLE "old_passwd:"
+#define NEW_PASSWD_MSG_TITLE "new_passwd:"
+#define CONFIRM_PASSWD_MSG_TITLE "confirm_passwd:"
+
+typedef struct _PAMError PAMError;
+typedef struct _PasswdMsg PasswdMsg;
+
+struct _PAMError {
+ gint error_code;
+ gchar *error_msg;
+};
+
+struct _PasswdMsg {
+ gint len;
+ gchar* msg;
+};
+
+void
+cb_dialog_response (GtkDialog *dialog, gint response_id, gpointer data);
+
+#endif /* __PAM_PASSWD_H */
Index: gnome-control-center-2.19.4/capplets/passwd/pam/Makefile.am
===================================================================
--- /dev/null
+++ gnome-control-center-2.19.4/capplets/passwd/pam/Makefile.am
@@ -0,0 +1,15 @@
+sbin_PROGRAMS = change-passwd
+
+change_passwd_SOURCES = helper-passwd.c
+
+change_passwd_LDADD = \
+ $(PASSWD_PAM_LIBS)
+
+pamdir=/etc/pam.d
+pam_DATA=gnome-passwd
+
+@INTLTOOL_DESKTOP_RULE@
+
+install-exec-hook:
+ chmod u+s $(DESTDIR)$(sbindir)/change-passwd
+
Index: gnome-control-center-2.19.4/capplets/passwd/pam/gnome-passwd
===================================================================
--- /dev/null
+++ gnome-control-center-2.19.4/capplets/passwd/pam/gnome-passwd
@@ -0,0 +1,6 @@
+#%PAM-1.0
+auth include common-auth
+account include common-account
+password include common-password
+session include common-session
+
Index: gnome-control-center-2.19.4/capplets/passwd/pam/helper-passwd.c
===================================================================
--- /dev/null
+++ gnome-control-center-2.19.4/capplets/passwd/pam/helper-passwd.c
@@ -0,0 +1,520 @@
+/* helper-passwd.c: password change capplet
+ *
+ * Copyright (C) 2005 Novell Inc.
+ *
+ * Written by: Shakti Sen <shprasad@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <pwd.h>
+
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+
+/* PAM headers */
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+#include <security/pam_modules.h>
+
+#include "config.h"
+
+/* Maximum number of arguments,
+ old-passwd, new-passwd and confirm-passwd
+ Incase of 'root' old-passwd is empty string.
+*/
+#define MAX_NUMBER_OF_ARGS 3
+
+/* Password-protocol-message defines */
+#define OLD_PASSWD_MSG_TITLE "old_passwd:"
+#define NEW_PASSWD_MSG_TITLE "new_passwd:"
+#define CONFIRM_PASSWD_MSG_TITLE "confirm_passwd:"
+
+/* Indexes corresponding to the type of passwds */
+#define OLD_PASSWD_INDEX 0
+#define NEW_PASSWD_INDEX 1
+#define CONFIRM_PASSWD_INDEX 2
+
+/* Length of the password */
+#define BUFFER_BASE_SIZE 256
+
+/* Custom error codes */
+#define CHPWD_ERR_RES_ALLOC 105
+#define CHPWD_ERR_IN_PROTOCOL 121
+
+/* Custom PAM error-codes */
+#define CUSTOM_PAM_ERR_BAD_PASSWORD 101
+#define CUSTOM_PAM_ERR_PASSWORD_MISMATCH 102
+#define CUSTOM_PAM_ERR_PASSWORD_CHANGE_ABORTED 103
+
+#define TRUE 1
+#define FALSE 0
+
+/* Counter to hold the current-number of conversation */
+static int cnt = 0;
+static char *pam_last_msg = NULL;
+
+/* Argument list that holds old-passwd, new-passwd and
+ confirm-passwd values
+*/
+char *args[] = {NULL, NULL, NULL};
+
+void
+exit_in_peace (int error_code)
+{
+ int i = 0;
+
+ for (i = 0; i < MAX_NUMBER_OF_ARGS; i++) {
+ if (args [i])
+ free (args [i]);
+ }
+
+ /* B'bye and see you later */
+ exit (error_code);
+}
+
+int
+environment_settings (void)
+{
+ struct rlimit rlim;
+ int retval = -1;
+
+ /* Don't create a core file. */
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ retval = setrlimit (RLIMIT_CORE, &rlim);
+ if (retval < 0)
+ return retval;
+
+ /* Set all limits to unlimited to avoid to run in any
+ problems later. */
+ rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
+ retval = setrlimit (RLIMIT_AS, &rlim);
+ if (retval < 0)
+ return retval;
+
+ retval = setrlimit (RLIMIT_CPU, &rlim);
+ if (retval < 0)
+ return retval;
+
+ retval = setrlimit (RLIMIT_DATA, &rlim);
+ if (retval < 0)
+ return retval;
+
+ retval = setrlimit (RLIMIT_FSIZE, &rlim);
+ if (retval < 0)
+ return retval;
+
+ retval = setrlimit (RLIMIT_RSS, &rlim);
+ if (retval < 0)
+ return retval;
+
+ retval = setrlimit (RLIMIT_STACK, &rlim);
+ if (retval < 0)
+ return retval;
+
+ /* Ignore all signals which may make trouble */
+ signal (SIGALRM, SIG_IGN);
+ signal (SIGXFSZ, SIG_IGN);
+ signal (SIGHUP, SIG_IGN);
+ signal (SIGINT, SIG_IGN);
+ signal (SIGPIPE, SIG_IGN);
+ signal (SIGQUIT, SIG_IGN);
+ signal (SIGTERM, SIG_IGN);
+ signal (SIGTSTP, SIG_IGN);
+ signal (SIGTTOU, SIG_IGN);
+
+ return 0;
+}
+
+char*
+chpwd_strlower (const char* source)
+{
+ char *dest;
+ char *iterator;
+
+ if (!source)
+ return NULL;
+
+ dest = malloc (strlen (source) + 1);
+ if (!dest)
+ return NULL;
+
+ iterator = dest;
+
+ while ((*iterator++ = tolower (*(source++))));
+ return dest;
+}
+
+char*
+chpwd_strcasestr (const char* haystack, const char* needle)
+{
+ char* haystack_lower;
+ char* needle_lower;
+ char* found = NULL;
+ int index;
+
+ if (!haystack || !needle)
+ return NULL;
+
+ haystack_lower = chpwd_strlower (haystack);
+ needle_lower = chpwd_strlower (needle);
+
+ if (haystack_lower && needle_lower)
+ found = strstr (haystack_lower, needle_lower);
+ if (!found)
+ return NULL;
+
+ index = found - haystack_lower;
+
+ if (index < 0)
+ return NULL;
+
+ found = (char *)(haystack + index);
+
+ free (haystack_lower);
+ free (needle_lower);
+
+ return found;
+}
+
+int
+ignorable_error (const char* err_msg)
+{
+ int retval = 0;
+
+ if (chpwd_strcasestr (err_msg, "bad password")) {
+ retval = 0;
+ } else if (chpwd_strcasestr (err_msg, "do not match")) {
+ retval = 0;
+ } else if (chpwd_strcasestr (err_msg, "change aborted")) {
+ retval = 1;
+ }
+
+ return retval;
+}
+
+int
+converse (int n,
+ const struct pam_message **msg,
+ struct pam_response **resp,
+ void *data)
+{
+ struct pam_response *aresp;
+ int i;
+
+ if (n <= 0 || n > PAM_MAX_NUM_MSG)
+ return (PAM_CONV_ERR);
+
+ if ((aresp = calloc (n, sizeof (*aresp))) == NULL)
+ return (PAM_BUF_ERR);
+
+ for (i = 0; i < n; ++i) {
+
+ aresp[i].resp_retcode = 0;
+ aresp[i].resp = NULL;
+
+ switch (msg[i]->msg_style) {
+
+ case PAM_PROMPT_ECHO_OFF:
+
+ /* Do we need to return any ERROR status? */
+ if (cnt >= MAX_NUMBER_OF_ARGS)
+ break;
+
+#ifdef DEBUG
+ fprintf(stderr,"Message style is PAM_PROMPT_ECHO_OFF\n");
+ fprintf(stderr,"What is in the buffer for %d?\n", cnt);
+ fprintf(stderr,"\t\t%s\n", args [cnt]);
+#endif
+
+ /* PAM calls expects a pointer that they can free it */
+ aresp[i].resp = strdup (args [cnt]);
+
+ if (aresp[i].resp == NULL)
+ goto fail;
+ cnt++;
+ break;
+
+ case PAM_PROMPT_ECHO_ON:
+#ifdef DEBUG
+ fprintf(stderr,"Message style is PAM_PROMPT_ECHO_ON\n");
+ fprintf(stderr,"Message is: %s\n", msg[i]->msg);
+#endif
+ /* The user name is passed as the argument.
+ So, nothing to do here */
+
+ break;
+
+ case PAM_ERROR_MSG:
+#ifdef DEBUG
+ fprintf(stderr,"Message style is PAM_ERROR_MSG\n");
+ fprintf(stderr,"Error: %s\n", msg[i]->msg);
+#endif
+ if (!ignorable_error (msg[i]->msg)) {
+ if (msg[i]->msg && (!pam_last_msg || (pam_last_msg && strcmp (msg[i]->msg, pam_last_msg)))) {
+ fprintf (stderr, "%s\n\n", msg[i]->msg);
+ }
+
+ if (msg[i]->msg) {
+ if (pam_last_msg)
+ free (pam_last_msg);
+ pam_last_msg = strdup (msg[i]->msg);
+ }
+ goto fail;
+ }
+ break;
+
+ case PAM_TEXT_INFO:
+#ifdef DEBUG
+ fprintf(stderr,"Message style is PAM_TEXT_INFO\n");
+ fprintf(stderr,"Warn: %s\n", msg[i]->msg);
+#endif
+
+ if (msg[i]->msg && (!pam_last_msg || (pam_last_msg && strcmp (msg[i]->msg, pam_last_msg)))) {
+ fprintf (stderr, "%s\n\n", msg[i]->msg);
+ }
+
+ if (msg[i]->msg) {
+ if (pam_last_msg)
+ free (pam_last_msg);
+ pam_last_msg = strdup (msg[i]->msg);
+ }
+
+ break;
+
+ default:
+ goto fail;
+ }
+ }
+
+ *resp = aresp;
+ return (PAM_SUCCESS);
+
+ fail:
+ for (i = 0; i < n; ++i) {
+ if (aresp[i].resp != NULL) {
+ memset (aresp[i].resp, 0, strlen (aresp[i].resp));
+ free (aresp[i].resp);
+ }
+ }
+ memset (aresp, 0, n * sizeof (*aresp));
+ *resp = NULL;
+ return (PAM_CONV_ERR);
+}
+
+
+static struct pam_conv conv = {
+ converse,
+ NULL
+};
+
+/* WARN: Do not free the memory returned in **pwd */
+int
+decode_message (char *msg,
+ char **pwd)
+{
+ char *delimiter = NULL;
+
+ delimiter = strchr (msg, ':');
+ if (!delimiter)
+ return -1;
+
+#ifdef DEBUG
+ fprintf(stderr,"Password : %s", delimiter+1);
+#endif
+
+ *pwd = (char *)delimiter+1;
+
+ if (!strncmp (msg, OLD_PASSWD_MSG_TITLE, strlen (OLD_PASSWD_MSG_TITLE)))
+ return OLD_PASSWD_INDEX;
+ else if (!strncmp (msg, NEW_PASSWD_MSG_TITLE, strlen (NEW_PASSWD_MSG_TITLE)))
+ return NEW_PASSWD_INDEX;
+ else if (!strncmp (msg, CONFIRM_PASSWD_MSG_TITLE, strlen (CONFIRM_PASSWD_MSG_TITLE)))
+ return CONFIRM_PASSWD_INDEX;
+ else
+ return -1;
+}
+
+/* Returns bytes read, but thie call doesn't have to be repeated. */
+static int
+chpwd_read (int fd, char *buffer, int length)
+{
+ int bytes_left = length;
+ int bytes_read;
+ while (bytes_left > 0) {
+ bytes_read = read (fd, buffer + length - bytes_left, bytes_left);
+ if (bytes_read < 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ return bytes_read;
+ }
+ if (bytes_read == 0)
+ break;
+ bytes_left -= bytes_read;
+ }
+ return length - bytes_left;
+}
+
+int
+handle_password_protocol ()
+{
+ int pwd_index = -1;
+ int count = 0;
+ char* msg = NULL;
+ char* passwd = NULL;
+ size_t msg_len = 0;
+
+ while (count++ < MAX_NUMBER_OF_ARGS) {
+
+ if (chpwd_read (STDIN_FILENO, (char *) &msg_len, sizeof (msg_len)) != sizeof (msg_len)) {
+ return TRUE;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr,"Message Length: %d\n", msg_len);
+#endif
+
+ /* Avoid allocating a huge amount of memory. */
+ if (msg_len >= 1024) {
+ return TRUE;
+ }
+
+ msg = (char*) malloc (msg_len + 1);
+ if (!msg)
+ return TRUE;
+
+ if (chpwd_read (STDIN_FILENO, (char *) msg, msg_len) != msg_len)
+ return TRUE;
+ msg[msg_len] = '\0';
+
+#ifdef DEBUG
+ fprintf(stderr,"Message : %s\n", msg);
+#endif
+
+ pwd_index = decode_message (msg, &passwd);
+
+ if (pwd_index < 0) {
+ free (msg);
+ return TRUE;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr,"Password : %s\n", passwd);
+#endif
+
+ args [pwd_index] = strdup (passwd);
+
+ if (args[pwd_index] == NULL) {
+ free(msg);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ pam_handle_t *pamh=NULL;
+ int retval = 0;
+ struct stat filebuf;
+ struct passwd *user = NULL;
+ uid_t uid;
+
+ /* We exit if our standard input does not come from
+ a pipe. This is to avoid the user from running the helper app
+ from command line. No messages either. Just quit silently.
+ */
+ if (fstat (STDIN_FILENO, &filebuf) < 0)
+ exit_in_peace (1);
+ if (!S_ISFIFO (filebuf.st_mode)) {
+ exit_in_peace (1);
+ }
+
+
+ /* We do not support command line arguments */
+ if (argc > 1)
+ exit_in_peace (1);
+
+ /* Get the user name from UID */
+ uid = getuid ();
+ user = getpwuid (uid);
+ if(!user)
+ exit_in_peace (1);
+
+ /* Set the ulimit and ignore signals */
+
+ retval = environment_settings ();
+ if (retval < 0)
+ exit_in_peace (CHPWD_ERR_RES_ALLOC);
+
+ if (handle_password_protocol ())
+ exit_in_peace (CHPWD_ERR_IN_PROTOCOL);
+
+ /* Make sure that args[cnt] contains the correct information */
+ if (uid == 0)
+ cnt++;
+
+ retval = pam_start ("gnome-passwd", user->pw_name, &conv, &pamh);
+ if (retval != PAM_SUCCESS) {
+#ifdef DEBUG
+ fprintf(stderr,"Error initializing PAM library.");
+#endif
+ exit_in_peace (1);
+ }
+
+#ifdef DEBUG
+ fprintf(stderr,"PAM library initialization successfull.\n");
+#endif
+
+ /* Validate the account for password expiries etc.. */
+ retval = pam_acct_mgmt (pamh, 0);
+ if(retval != PAM_SUCCESS) {
+#ifdef DEBUG
+ fprintf(stderr,pam_strerror (pamh, retval));
+#endif
+ exit_in_peace (retval);
+ }
+
+#ifdef DEBUG
+ fprintf(stderr,"Account validation is successfull.\n");
+#endif
+
+ retval = pam_chauthtok (pamh, 0);
+ if (retval != PAM_SUCCESS) {
+#ifdef DEBUG
+ fprintf(stderr,pam_strerror (pamh, retval));
+#endif
+ exit_in_peace (retval);
+ }
+
+ /* close PAM */
+ if (pam_end (pamh,retval) != PAM_SUCCESS) {
+ pamh = NULL;
+#ifdef DEBUG
+ fprintf(stderr,"Failed to unload-PAM-libraries. \n");
+#endif
+ exit_in_peace (2);
+ }
+ return 0;
+}
Index: gnome-control-center-2.19.4/configure.in
===================================================================
--- gnome-control-center-2.19.4.orig/configure.in
+++ gnome-control-center-2.19.4/configure.in
@@ -292,6 +292,18 @@ if test "x$enable_hal" != "xno"; then
AC_SUBST(HAL_LIBS)
fi
+ dnl =======================================
+dnl Required For PAM
+dnl =======================================
+
+PASSWD_PAM_LIBDIR='-L/usr/include'
+PASSWD_PAM_LIBS="$PASSWD_PAM_LIBS -lpam"
+PASSWD_PAM_INCLUDEDIR="$PASSWD_PAM_INCLUDEDIR -I /use/include"
+
+dnl AC_SUBST(PASSWD_PAM_LIBDIR)
+AC_SUBST(PASSWD_PAM_LIBS)
+AC_SUBST(PASSWD_PAM_INCLUDEDIR)
+
dnl ==============================================
dnl End: Check that we meet the dependencies
dnl ==============================================
@@ -498,6 +510,9 @@ capplets/mouse/Makefile
capplets/mouse/gnome-settings-mouse.desktop.in
capplets/network/Makefile
capplets/network/gnome-network-preferences.desktop.in
+capplets/passwd/Makefile
+capplets/passwd/pam/Makefile
+capplets/passwd/gnome-passwd.desktop.in
capplets/sound/Makefile
capplets/sound/gnome-settings-sound.desktop.in
capplets/windows/Makefile
Index: gnome-control-center-2.19.4/po/POTFILES.in
===================================================================
--- gnome-control-center-2.19.4.orig/po/POTFILES.in
+++ gnome-control-center-2.19.4/po/POTFILES.in
@@ -62,6 +62,10 @@ capplets/mouse/gnome-settings-mouse.desk
capplets/network/gnome-network-preferences.c
capplets/network/gnome-network-preferences.desktop.in.in
capplets/network/gnome-network-preferences.glade
+capplets/passwd/gnome-passwd.desktop.in.in
+capplets/passwd/gnome-passwd.c
+capplets/passwd/pam-passwd.c
+capplets/passwd/gnome-passwd.glade
capplets/sound/gnome-settings-sound.desktop.in.in
capplets/sound/mixer-support.c
capplets/sound/pipeline-tests.c