1543 lines
47 KiB
Diff
1543 lines
47 KiB
Diff
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"><b>Changing Password for User '%s'</b></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
|