summaryrefslogtreecommitdiffstats
path: root/tdmlib
diff options
context:
space:
mode:
Diffstat (limited to 'tdmlib')
-rw-r--r--tdmlib/CMakeLists.txt85
-rw-r--r--tdmlib/Makefile.am30
-rw-r--r--tdmlib/dmctl.cpp442
-rw-r--r--tdmlib/dmctl.h93
-rw-r--r--tdmlib/kgreet_classic.cpp513
-rw-r--r--tdmlib/kgreet_classic.h88
-rw-r--r--tdmlib/kgreet_pam.cpp675
-rw-r--r--tdmlib/kgreet_pam.h94
-rw-r--r--tdmlib/kgreet_winbind.cpp679
-rw-r--r--tdmlib/kgreet_winbind.h101
-rw-r--r--tdmlib/kgreeterplugin.h407
-rw-r--r--tdmlib/tdmtsak.cpp180
-rw-r--r--tdmlib/tdmtsak.h144
13 files changed, 3531 insertions, 0 deletions
diff --git a/tdmlib/CMakeLists.txt b/tdmlib/CMakeLists.txt
new file mode 100644
index 000000000..a2565fe1d
--- /dev/null
+++ b/tdmlib/CMakeLists.txt
@@ -0,0 +1,85 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/tdm/kfrontend
+ ${CMAKE_BINARY_DIR}
+ ${TDE_INCLUDE_DIR}
+ ${TQT_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+if( BUILD_TDM )
+
+
+##### headers ###################################
+
+install( FILES kgreeterplugin.h DESTINATION ${INCLUDE_INSTALL_DIR} )
+
+
+##### kgreet_classic (module) ###################
+
+tde_add_kpart( kgreet_classic AUTOMOC
+ SOURCES kgreet_classic.cpp
+ LINK tdeui-shared
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+)
+
+
+##### kgreet_pam (module) #######################
+
+tde_add_kpart( kgreet_pam AUTOMOC
+ SOURCES kgreet_pam.cpp
+ LINK tdeui-shared
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+)
+
+
+##### kgreet_winbind (module) ###################
+
+tde_add_kpart( kgreet_winbind AUTOMOC
+ SOURCES kgreet_winbind.cpp
+ LINK tdeui-shared
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+)
+
+
+
+endif( BUILD_TDM )
+
+
+##### dmctl (static) ############################
+
+if( BUILD_KICKER OR BUILD_KDESKTOP OR BUILD_TDM OR BUILD_KSMSERVER )
+
+ tde_add_library( dmctl STATIC_PIC
+ SOURCES dmctl.cpp
+ LINK Xau
+ )
+
+endif( )
+
+##### tdmtsak (executable) #######################
+
+if( BUILD_TSAK )
+ tde_add_executable( tdmtsak
+ SOURCES tdmtsak.cpp
+ LINK ${TQT_LIBRARIES}
+ DESTINATION ${BIN_INSTALL_DIR}
+ SETUID
+ DESCRIPTION "Secure Attention Key interface for TDM"
+ AUTHORS "Timothy Pearson"
+ )
+endif( BUILD_TSAK )
diff --git a/tdmlib/Makefile.am b/tdmlib/Makefile.am
new file mode 100644
index 000000000..f21f59bd5
--- /dev/null
+++ b/tdmlib/Makefile.am
@@ -0,0 +1,30 @@
+AM_CPPFLAGS = -I$(top_srcdir)/tdm/kfrontend $(all_includes)
+
+kde_module_LTLIBRARIES = kgreet_classic.la kgreet_pam.la kgreet_winbind.la
+
+kgreet_classic_la_SOURCES = kgreet_classic.cpp
+kgreet_classic_la_LDFLAGS = -module -no-undefined $(KDE_PLUGIN) $(all_libraries)
+kgreet_classic_la_LIBADD = $(LIB_TDEUI)
+
+kgreet_pam_la_SOURCES = kgreet_pam.cpp
+kgreet_pam_la_LDFLAGS = -module -no-undefined $(KDE_PLUGIN) $(all_libraries)
+kgreet_pam_la_LIBADD = $(LIB_TDEUI)
+
+kgreet_winbind_la_SOURCES = kgreet_winbind.cpp
+kgreet_winbind_la_LDFLAGS = -module -no-undefined $(KDE_PLUGIN) $(all_libraries)
+kgreet_winbind_la_LIBADD = $(LIB_TDEUI)
+
+noinst_LTLIBRARIES = libdmctl.la
+libdmctl_la_SOURCES = dmctl.cpp
+libdmctl_la_LDFLAGS = $(all_libraries) -no-undefined
+libdmctl_la_LIBADD = $(LIB_TDECORE) -lXau
+
+METASOURCES = AUTO
+
+noinst_HEADERS = dmctl.h kgreet_classic.h kgreet_winbind.h
+include_HEADERS = kgreeterplugin.h
+
+messages:
+ $(XGETTEXT) $(kgreet_classic_la_SOURCES) -o $(podir)/kgreet_classic.pot
+ $(XGETTEXT) $(kgreet_winbind_la_SOURCES) -o $(podir)/kgreet_winbind.pot
+ $(XGETTEXT) $(libdmctl_la_SOURCES) -o $(podir)/libdmctl.pot
diff --git a/tdmlib/dmctl.cpp b/tdmlib/dmctl.cpp
new file mode 100644
index 000000000..41a5cb206
--- /dev/null
+++ b/tdmlib/dmctl.cpp
@@ -0,0 +1,442 @@
+/*
+ Copyright (C) 2004 Oswald Buddenhagen <ossi@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the Lesser GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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 Lesser GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "dmctl.h"
+
+#ifdef Q_WS_X11
+
+#include <klocale.h>
+#include <dcopclient.h>
+
+#include <tqregexp.h>
+
+#include <X11/Xauth.h>
+#include <X11/Xlib.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+static enum { Dunno, NoDM, NewTDM, OldTDM, GDM } DMType = Dunno;
+static const char *ctl, *dpy;
+
+DM::DM() : fd( -1 )
+{
+ char *ptr;
+ struct sockaddr_un sa;
+
+ if (DMType == Dunno) {
+ if (!(dpy = ::getenv( "DISPLAY" )))
+ DMType = NoDM;
+ else if ((ctl = ::getenv( "DM_CONTROL" )))
+ DMType = NewTDM;
+ else if ((ctl = ::getenv( "XDM_MANAGED" )) && ctl[0] == '/')
+ DMType = OldTDM;
+ else if (::getenv( "GDMSESSION" ))
+ DMType = GDM;
+ else
+ DMType = NoDM;
+ }
+ switch (DMType) {
+ default:
+ return;
+ case NewTDM:
+ case GDM:
+ if ((fd = ::socket( PF_UNIX, SOCK_STREAM, 0 )) < 0)
+ return;
+ sa.sun_family = AF_UNIX;
+ if (DMType == GDM) {
+ strcpy( sa.sun_path, "/var/run/gdm_socket" );
+ if (::connect( fd, (struct sockaddr *)&sa, sizeof(sa) )) {
+ strcpy( sa.sun_path, "/tmp/.gdm_socket" );
+ if (::connect( fd, (struct sockaddr *)&sa, sizeof(sa) )) {
+ ::close( fd );
+ fd = -1;
+ break;
+ }
+ }
+ GDMAuthenticate();
+ } else {
+ if ((ptr = const_cast<char*>(strchr( dpy, ':' ))))
+ ptr = strchr( ptr, '.' );
+ snprintf( sa.sun_path, sizeof(sa.sun_path),
+ "%s/dmctl-%.*s/socket",
+ ctl, ptr ? int(ptr - dpy) : 512, dpy );
+ if (::connect( fd, (struct sockaddr *)&sa, sizeof(sa) )) {
+ ::close( fd );
+ fd = -1;
+ }
+ }
+ break;
+ case OldTDM:
+ {
+ TQString tf( ctl );
+ tf.truncate( tf.find( ',' ) );
+ fd = ::open( tf.latin1(), O_WRONLY );
+ }
+ break;
+ }
+}
+
+DM::~DM()
+{
+ if (fd >= 0)
+ close( fd );
+}
+
+bool
+DM::exec( const char *cmd )
+{
+ TQCString buf;
+
+ return exec( cmd, buf );
+}
+
+/**
+ * Execute a TDM/GDM remote control command.
+ * @param cmd the command to execute. FIXME: undocumented yet.
+ * @param buf the result buffer.
+ * @return result:
+ * @li If true, the command was successfully executed.
+ * @p ret might contain addional results.
+ * @li If false and @p ret is empty, a communication error occurred
+ * (most probably TDM is not running).
+ * @li If false and @p ret is non-empty, it contains the error message
+ * from TDM.
+ */
+bool
+DM::exec( const char *cmd, TQCString &buf )
+{
+ bool ret = false;
+ int tl;
+ unsigned len = 0;
+
+ if (fd < 0)
+ goto busted;
+
+ tl = strlen( cmd );
+ if (::write( fd, cmd, tl ) != tl) {
+ bust:
+ ::close( fd );
+ fd = -1;
+ busted:
+ buf.resize( 0 );
+ return false;
+ }
+ if (DMType == OldTDM) {
+ buf.resize( 0 );
+ return true;
+ }
+ for (;;) {
+ if (buf.size() < 128)
+ buf.resize( 128 );
+ else if (buf.size() < len * 2)
+ buf.resize( len * 2 );
+ if ((tl = ::read( fd, buf.data() + len, buf.size() - len)) <= 0) {
+ if (tl < 0 && errno == EINTR)
+ continue;
+ goto bust;
+ }
+ len += tl;
+ if (buf[len - 1] == '\n') {
+ buf[len - 1] = 0;
+ if (len > 2 && (buf[0] == 'o' || buf[0] == 'O') &&
+ (buf[1] == 'k' || buf[1] == 'K') && buf[2] <= 32)
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+}
+
+bool
+DM::canShutdown()
+{
+ if (DMType == OldTDM)
+ return strstr( ctl, ",maysd" ) != 0;
+
+ TQCString re;
+
+ if (DMType == GDM)
+ return exec( "QUERY_LOGOUT_ACTION\n", re ) && re.find("HALT") >= 0;
+
+ return exec( "caps\n", re ) && re.find( "\tshutdown" ) >= 0;
+}
+
+void
+DM::shutdown( KApplication::ShutdownType shutdownType,
+ KApplication::ShutdownMode shutdownMode, /* NOT Default */
+ const TQString &bootOption )
+{
+ if (shutdownType == KApplication::ShutdownTypeNone)
+ return;
+
+ bool cap_ask;
+ if (DMType == NewTDM) {
+ TQCString re;
+ cap_ask = exec( "caps\n", re ) && re.find( "\tshutdown ask" ) >= 0;
+ } else {
+ if (!bootOption.isEmpty())
+ return;
+ cap_ask = false;
+ }
+ if (!cap_ask && shutdownMode == KApplication::ShutdownModeInteractive)
+ shutdownMode = KApplication::ShutdownModeForceNow;
+
+ TQCString cmd;
+ if (DMType == GDM) {
+ cmd.append( shutdownMode == KApplication::ShutdownModeForceNow ?
+ "SET_LOGOUT_ACTION " : "SET_SAFE_LOGOUT_ACTION " );
+ cmd.append( shutdownType == KApplication::ShutdownTypeReboot ?
+ "REBOOT\n" : "HALT\n" );
+ } else {
+ cmd.append( "shutdown\t" );
+ cmd.append( shutdownType == KApplication::ShutdownTypeReboot ?
+ "reboot\t" : "halt\t" );
+ if (!bootOption.isEmpty())
+ cmd.append( "=" ).append( bootOption.local8Bit() ).append( "\t" );
+ cmd.append( shutdownMode == KApplication::ShutdownModeInteractive ?
+ "ask\n" :
+ shutdownMode == KApplication::ShutdownModeForceNow ?
+ "forcenow\n" :
+ shutdownMode == KApplication::ShutdownModeTryNow ?
+ "trynow\n" : "schedule\n" );
+ }
+ exec( cmd.data() );
+}
+
+bool
+DM::bootOptions( TQStringList &opts, int &defopt, int &current )
+{
+ if (DMType != NewTDM)
+ return false;
+
+ TQCString re;
+ if (!exec( "listbootoptions\n", re ))
+ return false;
+
+ opts = TQStringList::split( '\t', TQString::fromLocal8Bit( re.data() ) );
+ if (opts.size() < 4)
+ return false;
+
+ bool ok;
+ defopt = opts[2].toInt( &ok );
+ if (!ok)
+ return false;
+ current = opts[3].toInt( &ok );
+ if (!ok)
+ return false;
+
+ opts = TQStringList::split( ' ', opts[1] );
+ for (TQStringList::Iterator it = opts.begin(); it != opts.end(); ++it)
+ (*it).replace( "\\s", " " );
+
+ return true;
+}
+
+void
+DM::setLock( bool on )
+{
+ if (DMType != GDM)
+ exec( on ? "lock\n" : "unlock\n" );
+}
+
+bool
+DM::isSwitchable()
+{
+ if (DMType == OldTDM)
+ return dpy[0] == ':';
+
+ if (DMType == GDM)
+ return exec( "QUERY_VT\n" );
+
+ TQCString re;
+
+ return exec( "caps\n", re ) && re.find( "\tlocal" ) >= 0;
+}
+
+int
+DM::numReserve()
+{
+ if (DMType == GDM)
+ return 1; /* Bleh */
+
+ if (DMType == OldTDM)
+ return strstr( ctl, ",rsvd" ) ? 1 : -1;
+
+ TQCString re;
+ int p;
+
+ if (!(exec( "caps\n", re ) && (p = re.find( "\treserve " )) >= 0))
+ return -1;
+ return atoi( re.data() + p + 9 );
+}
+
+void
+DM::startReserve()
+{
+ if (DMType == GDM)
+ exec("FLEXI_XSERVER\n");
+ else
+ exec("reserve\n");
+}
+
+bool
+DM::localSessions( SessList &list )
+{
+ if (DMType == OldTDM)
+ return false;
+
+ TQCString re;
+
+ if (DMType == GDM) {
+ if (!exec( "CONSOLE_SERVERS\n", re ))
+ return false;
+ TQStringList sess = TQStringList::split( TQChar(';'), re.data() + 3 );
+ for (TQStringList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
+ TQStringList ts = TQStringList::split( TQChar(','), *it, true );
+ SessEnt se;
+ se.display = ts[0];
+ se.user = ts[1];
+ se.vt = ts[2].toInt();
+ se.session = "<unknown>";
+ se.self = ts[0] == ::getenv( "DISPLAY" ); /* Bleh */
+ se.tty = false;
+ list.append( se );
+ }
+ } else {
+ if (!exec( "list\talllocal\n", re ))
+ return false;
+ TQStringList sess = TQStringList::split( TQChar('\t'), re.data() + 3 );
+ for (TQStringList::ConstIterator it = sess.begin(); it != sess.end(); ++it) {
+ TQStringList ts = TQStringList::split( TQChar(','), *it, true );
+ SessEnt se;
+ se.display = ts[0];
+ if (ts[1][0] == '@')
+ se.from = ts[1].mid( 1 ), se.vt = 0;
+ else
+ se.vt = ts[1].mid( 2 ).toInt();
+ se.user = ts[2];
+ se.session = ts[3];
+ se.self = (ts[4].find( '*' ) >= 0);
+ se.tty = (ts[4].find( 't' ) >= 0);
+ list.append( se );
+ }
+ }
+ return true;
+}
+
+void
+DM::sess2Str2( const SessEnt &se, TQString &user, TQString &loc )
+{
+ if (se.tty) {
+ user = i18n("user: ...", "%1: TTY login").arg( se.user );
+ loc = se.vt ? TQString(TQString("vt%1").arg( se.vt )) : se.display ;
+ } else {
+ user =
+ se.user.isEmpty() ?
+ se.session.isEmpty() ?
+ i18n("Unused") :
+ se.session == "<remote>" ?
+ i18n("X login on remote host") :
+ TQString(i18n("... host", "X login on %1").arg( se.session )) :
+ se.session == "<unknown>" ?
+ se.user :
+ TQString(i18n("user: session type", "%1: %2")
+ .arg( se.user ).arg( se.session ));
+ loc =
+ se.vt ?
+ TQString(TQString("%1, vt%2").arg( se.display ).arg( se.vt )) :
+ se.display;
+ }
+}
+
+TQString
+DM::sess2Str( const SessEnt &se )
+{
+ TQString user, loc;
+
+ sess2Str2( se, user, loc );
+ return i18n("session (location)", "%1 (%2)").arg( user ).arg( loc );
+}
+
+bool
+DM::switchVT( int vt )
+{
+ if (DMType == GDM)
+ return exec( TQString(TQString("SET_VT %1\n").arg(vt)).latin1() );
+
+ return exec( TQString(TQString("activate\tvt%1\n").arg(vt)).latin1() );
+}
+
+void
+DM::lockSwitchVT( int vt )
+{
+ if (switchVT( vt ))
+ kapp->dcopClient()->send( "kdesktop", "KScreensaverIface", "lock()", TQString("") );
+}
+
+void
+DM::GDMAuthenticate()
+{
+ FILE *fp;
+ const char *dpy, *dnum, *dne;
+ int dnl;
+ Xauth *xau;
+
+ dpy = DisplayString( TQPaintDevice::x11AppDisplay() );
+ if (!dpy) {
+ dpy = ::getenv( "DISPLAY" );
+ if (!dpy)
+ return;
+ }
+ dnum = strchr( dpy, ':' ) + 1;
+ dne = strchr( dpy, '.' );
+ dnl = dne ? dne - dnum : strlen( dnum );
+
+ /* XXX should do locking */
+ if (!(fp = fopen( XauFileName(), "r" )))
+ return;
+
+ while ((xau = XauReadAuth( fp ))) {
+ if (xau->family == FamilyLocal &&
+ xau->number_length == dnl && !memcmp( xau->number, dnum, dnl ) &&
+ xau->data_length == 16 &&
+ xau->name_length == 18 && !memcmp( xau->name, "MIT-MAGIC-COOKIE-1", 18 ))
+ {
+ TQString cmd( "AUTH_LOCAL " );
+ for (int i = 0; i < 16; i++)
+ cmd += TQString::number( (uchar)xau->data[i], 16 ).rightJustify( 2, '0');
+ cmd += "\n";
+ if (exec( cmd.latin1() )) {
+ XauDisposeAuth( xau );
+ break;
+ }
+ }
+ XauDisposeAuth( xau );
+ }
+
+ fclose (fp);
+}
+
+#endif // Q_WS_X11
diff --git a/tdmlib/dmctl.h b/tdmlib/dmctl.h
new file mode 100644
index 000000000..da5aa2b0b
--- /dev/null
+++ b/tdmlib/dmctl.h
@@ -0,0 +1,93 @@
+/*
+ Copyright (C) 2004,2005 Oswald Buddenhagen <ossi@kde.org>
+ Copyright (C) 2005 Stephan Kulow <coolo@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the Lesser GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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 Lesser GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef DMCTL_H
+#define DMCTL_H
+
+#include <kapplication.h>
+
+struct SessEnt {
+ TQString display, from, user, session;
+ int vt;
+ bool self:1, tty:1;
+};
+
+typedef TQValueList<SessEnt> SessList;
+
+class DM {
+
+#ifdef Q_WS_X11
+
+public:
+ DM();
+ ~DM();
+
+ bool canShutdown();
+ void shutdown( KApplication::ShutdownType shutdownType,
+ KApplication::ShutdownMode shutdownMode,
+ const TQString &bootOption = TQString::null );
+
+ void setLock( bool on );
+
+ bool isSwitchable();
+ int numReserve();
+ void startReserve();
+ bool localSessions( SessList &list );
+ bool switchVT( int vt );
+ void lockSwitchVT( int vt );
+
+ bool bootOptions( TQStringList &opts, int &dflt, int &curr );
+
+ static TQString sess2Str( const SessEnt &se );
+ static void sess2Str2( const SessEnt &se, TQString &user, TQString &loc );
+
+private:
+ int fd;
+
+ bool exec( const char *cmd, TQCString &ret );
+ bool exec( const char *cmd );
+
+ void GDMAuthenticate();
+
+#else // Q_WS_X11
+
+public:
+ DM() {}
+
+ bool canShutdown() { return false; }
+ void shutdown( KApplication::ShutdownType shutdownType,
+ KApplication::ShutdownMode shutdownMode,
+ const TQString &bootOption = TQString::null ) {}
+
+ void setLock( bool ) {}
+
+ bool isSwitchable() { return false; }
+ int numReserve() { return -1; }
+ void startReserve() {}
+ bool localSessions( SessList &list ) { return false; }
+ void switchVT( int vt ) {}
+
+ bool bootOptions( TQStringList &opts, int &dflt, int &curr );
+
+#endif // Q_WS_X11
+
+}; // class DM
+
+#endif // DMCTL_H
diff --git a/tdmlib/kgreet_classic.cpp b/tdmlib/kgreet_classic.cpp
new file mode 100644
index 000000000..b37f2bab7
--- /dev/null
+++ b/tdmlib/kgreet_classic.cpp
@@ -0,0 +1,513 @@
+/*
+
+Conversation widget for tdm greeter
+
+Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+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 of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include "kgreet_classic.h"
+#include "themer/tdmthemer.h"
+#include "themer/tdmitem.h"
+
+#include <klocale.h>
+#include <klineedit.h>
+#include <kpassdlg.h>
+#include <kuser.h>
+
+#include <tqregexp.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+
+class TDMPasswordEdit : public KPasswordEdit {
+public:
+ TDMPasswordEdit( TQWidget *parent ) : KPasswordEdit( parent, 0 ) {}
+ TDMPasswordEdit( KPasswordEdit::EchoModes echoMode, TQWidget *parent ) : KPasswordEdit( echoMode, parent, 0 ) {}
+protected:
+ virtual void contextMenuEvent( TQContextMenuEvent * ) {}
+};
+
+static int echoMode;
+
+KClassicGreeter::KClassicGreeter( KGreeterPluginHandler *_handler,
+ KdmThemer *themer,
+ TQWidget *parent, TQWidget *pred,
+ const TQString &_fixedEntity,
+ Function _func, Context _ctx ) :
+ TQObject(),
+ KGreeterPlugin( _handler ),
+ fixedUser( _fixedEntity ),
+ func( _func ),
+ ctx( _ctx ),
+ exp( -1 ),
+ pExp( -1 ),
+ running( false )
+{
+ KdmItem *user_entry = 0, *pw_entry = 0;
+ TQGridLayout *grid = 0;
+ int line = 0;
+
+ layoutItem = 0;
+
+ if (themer &&
+ (!(user_entry = themer->findNode( "user-entry" )) ||
+ !(pw_entry = themer->findNode( "pw-entry" ))))
+ themer = 0;
+
+ if (!themer)
+ grid = new TQGridLayout( 0, 0, 10 );
+ layoutItem = TQT_TQLAYOUTITEM(grid);
+
+ loginLabel = passwdLabel = passwd1Label = passwd2Label = 0;
+ loginEdit = 0;
+ passwdEdit = passwd1Edit = passwd2Edit = 0;
+ if (ctx == ExUnlock || ctx == ExChangeTok)
+ fixedUser = KUser().loginName();
+ if (func != ChAuthTok) {
+ if (fixedUser.isEmpty()) {
+ loginEdit = new KLineEdit( parent );
+ loginEdit->setContextMenuEnabled( false );
+ connect( loginEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotLoginLostFocus()) );
+ connect( loginEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotActivity()) );
+ connect( loginEdit, TQT_SIGNAL(textChanged( const TQString & )), TQT_SLOT(slotActivity()) );
+ connect( loginEdit, TQT_SIGNAL(selectionChanged()), TQT_SLOT(slotActivity()) );
+ if (pred) {
+ parent->setTabOrder( pred, loginEdit );
+ pred = loginEdit;
+ }
+ if (!grid) {
+ loginEdit->adjustSize();
+ user_entry->setWidget( loginEdit );
+ } else {
+ loginLabel = new TQLabel( loginEdit, i18n("&Username:"), parent );
+ grid->addWidget( loginLabel, line, 0 );
+ grid->addWidget( loginEdit, line++, 1 );
+ }
+ } else if (ctx != Login && ctx != Shutdown && grid) {
+ loginLabel = new TQLabel( i18n("Username:"), parent );
+ grid->addWidget( loginLabel, line, 0 );
+ grid->addWidget( new TQLabel( fixedUser, parent ), line++, 1 );
+ }
+ if (echoMode == -1)
+ passwdEdit = new TDMPasswordEdit( parent );
+ else
+ passwdEdit = new TDMPasswordEdit( (KPasswordEdit::EchoModes)echoMode,
+ parent );
+ connect( passwdEdit, TQT_SIGNAL(textChanged( const TQString & )),
+ TQT_SLOT(slotActivity()) );
+ connect( passwdEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotActivity()) );
+ if (pred) {
+ parent->setTabOrder( pred, passwdEdit );
+ pred = passwdEdit;
+ }
+ if (!grid) {
+ passwdEdit->adjustSize();
+ pw_entry->setWidget( passwdEdit );
+ } else {
+ passwdLabel = new TQLabel( passwdEdit,
+ func == Authenticate ?
+ i18n("&Password:") :
+ i18n("Current &password:"),
+ parent );
+ grid->addWidget( passwdLabel, line, 0 );
+ grid->addWidget( passwdEdit, line++, 1 );
+ }
+ if (loginEdit)
+ loginEdit->setFocus();
+ else
+ passwdEdit->setFocus();
+ }
+ if (func != Authenticate) {
+ if (echoMode == -1) {
+ passwd1Edit = new TDMPasswordEdit( (KPasswordEdit::EchoModes)echoMode, parent );
+ passwd2Edit = new TDMPasswordEdit( (KPasswordEdit::EchoModes)echoMode, parent );
+ } else {
+ passwd1Edit = new TDMPasswordEdit( parent );
+ passwd2Edit = new TDMPasswordEdit( parent );
+ }
+ passwd1Label = new TQLabel( passwd1Edit, i18n("&New password:"), parent );
+ passwd2Label = new TQLabel( passwd2Edit, i18n("Con&firm password:"), parent );
+ if (pred) {
+ parent->setTabOrder( pred, passwd1Edit );
+ parent->setTabOrder( passwd1Edit, passwd2Edit );
+ }
+ if (grid) {
+ grid->addWidget( passwd1Label, line, 0 );
+ grid->addWidget( passwd1Edit, line++, 1 );
+ grid->addWidget( passwd2Label, line, 0 );
+ grid->addWidget( passwd2Edit, line, 1 );
+ }
+ if (!passwdEdit)
+ passwd1Edit->setFocus();
+ }
+}
+
+// virtual
+KClassicGreeter::~KClassicGreeter()
+{
+ abort();
+ if (!layoutItem) {
+ delete loginEdit;
+ delete passwdEdit;
+ return;
+ }
+ TQLayoutIterator it = TQT_TQLAYOUT(layoutItem)->iterator();
+ for (TQLayoutItem *itm = it.current(); itm; itm = ++it)
+ delete itm->widget();
+ delete layoutItem;
+}
+
+void // virtual
+KClassicGreeter::loadUsers( const TQStringList &users )
+{
+ KCompletion *userNamesCompletion = new KCompletion;
+ userNamesCompletion->setItems( users );
+ loginEdit->setCompletionObject( userNamesCompletion );
+ loginEdit->setAutoDeleteCompletionObject( true );
+ loginEdit->setCompletionMode( KGlobalSettings::CompletionAuto );
+}
+
+void // virtual
+KClassicGreeter::presetEntity( const TQString &entity, int field )
+{
+ loginEdit->setText( entity );
+ if (field == 1)
+ passwdEdit->setFocus();
+ else {
+ loginEdit->setFocus();
+ loginEdit->selectAll();
+ if (field == -1) {
+ passwdEdit->setText( " " );
+ passwdEdit->setEnabled( false );
+ authTok = false;
+ }
+ }
+ curUser = entity;
+}
+
+TQString // virtual
+KClassicGreeter::getEntity() const
+{
+ return fixedUser.isEmpty() ? loginEdit->text() : fixedUser;
+}
+
+void // virtual
+KClassicGreeter::setUser( const TQString &user )
+{
+ // assert( fixedUser.isEmpty() );
+ curUser = user;
+ loginEdit->setText( user );
+ passwdEdit->setFocus();
+ passwdEdit->selectAll();
+}
+
+void // virtual
+KClassicGreeter::setPassword( const TQString &pass )
+{
+ passwdEdit->erase();
+ passwdEdit->insert( pass );
+}
+
+void // virtual
+KClassicGreeter::setEnabled( bool enable )
+{
+ // assert( !passwd1Label );
+ // assert( func == Authenticate && ctx == Shutdown );
+// if (loginLabel)
+// loginLabel->setEnabled( enable );
+ passwdLabel->setEnabled( enable );
+ setActive( enable );
+ if (enable)
+ passwdEdit->setFocus();
+}
+
+void // private
+KClassicGreeter::returnData()
+{
+ switch (exp) {
+ case 0:
+ handler->gplugReturnText( (loginEdit ? loginEdit->text() :
+ fixedUser).local8Bit(),
+ KGreeterPluginHandler::IsUser );
+ break;
+ case 1:
+ handler->gplugReturnText( passwdEdit->password(),
+ KGreeterPluginHandler::IsPassword |
+ KGreeterPluginHandler::IsSecret );
+ break;
+ case 2:
+ handler->gplugReturnText( passwd1Edit->password(),
+ KGreeterPluginHandler::IsSecret );
+ break;
+ default: // case 3:
+ handler->gplugReturnText( passwd2Edit->password(),
+ KGreeterPluginHandler::IsNewPassword |
+ KGreeterPluginHandler::IsSecret );
+ break;
+ }
+}
+
+bool // virtual
+KClassicGreeter::textMessage( const char *text, bool err )
+{
+ if (!err &&
+ TQString( text ).find( TQRegExp( "^Changing password for [^ ]+$" ) ) >= 0)
+ return true;
+ return false;
+}
+
+void // virtual
+KClassicGreeter::textPrompt( const char *prompt, bool echo, bool nonBlocking )
+{
+ pExp = exp;
+ if (echo)
+ exp = 0;
+ else if (!authTok)
+ exp = 1;
+ else {
+ TQString pr( prompt );
+ if (pr.find( TQRegExp( "\\bpassword\\b", false ) ) >= 0) {
+ if (pr.find( TQRegExp( "\\b(re-?(enter|type)|again|confirm|repeat)\\b",
+ false ) ) >= 0)
+ exp = 3;
+ else if (pr.find( TQRegExp( "\\bnew\\b", false ) ) >= 0)
+ exp = 2;
+ else { // TQRegExp( "\\b(old|current)\\b", false ) is too strict
+ handler->gplugReturnText( "",
+ KGreeterPluginHandler::IsOldPassword |
+ KGreeterPluginHandler::IsSecret );
+ return;
+ }
+ } else {
+ handler->gplugMsgBox( TQMessageBox::Critical,
+ i18n("Unrecognized prompt \"%1\"")
+ .arg( prompt ) );
+ handler->gplugReturnText( 0, 0 );
+ exp = -1;
+ return;
+ }
+ }
+
+ if (pExp >= 0 && pExp >= exp) {
+ revive();
+ has = -1;
+ }
+
+ if (has >= exp || nonBlocking)
+ returnData();
+}
+
+bool // virtual
+KClassicGreeter::binaryPrompt( const char *, bool )
+{
+ // this simply cannot happen ... :}
+ return true;
+}
+
+void // virtual
+KClassicGreeter::start()
+{
+ authTok = !(passwdEdit && passwdEdit->isEnabled());
+ exp = has = -1;
+ running = true;
+}
+
+void // virtual
+KClassicGreeter::suspend()
+{
+}
+
+void // virtual
+KClassicGreeter::resume()
+{
+}
+
+void // virtual
+KClassicGreeter::next()
+{
+ // assert( running );
+ if (loginEdit && loginEdit->hasFocus()) {
+ passwdEdit->setFocus(); // will cancel running login if necessary
+ has = 0;
+ } else if (passwdEdit && passwdEdit->hasFocus()) {
+ if (passwd1Edit)
+ passwd1Edit->setFocus();
+ has = 1;
+ } else if (passwd1Edit) {
+ if (passwd1Edit->hasFocus()) {
+ passwd2Edit->setFocus();
+ has = 1; // sic!
+ } else
+ has = 3;
+ } else
+ has = 1;
+ if (exp < 0)
+ handler->gplugStart();
+ else if (has >= exp)
+ returnData();
+}
+
+void // virtual
+KClassicGreeter::abort()
+{
+ running = false;
+ if (exp >= 0) {
+ exp = -1;
+ handler->gplugReturnText( 0, 0 );
+ }
+}
+
+void // virtual
+KClassicGreeter::succeeded()
+{
+ // assert( running || timed_login );
+ if (!authTok) {
+ setActive( false );
+ if (passwd1Edit) {
+ authTok = true;
+ return;
+ }
+ } else
+ setActive2( false );
+ exp = -1;
+ running = false;
+}
+
+void // virtual
+KClassicGreeter::failed()
+{
+ // assert( running || timed_login );
+ setActive( false );
+ setActive2( false );
+ exp = -1;
+ running = false;
+}
+
+void // virtual
+KClassicGreeter::revive()
+{
+ // assert( !running );
+ setActive2( true );
+ if (authTok) {
+ passwd1Edit->erase();
+ passwd2Edit->erase();
+ passwd1Edit->setFocus();
+ } else {
+ passwdEdit->erase();
+ if (loginEdit && loginEdit->isEnabled())
+ passwdEdit->setEnabled( true );
+ else {
+ setActive( true );
+ if (loginEdit && loginEdit->text().isEmpty())
+ loginEdit->setFocus();
+ else
+ passwdEdit->setFocus();
+ }
+ }
+}
+
+void // virtual
+KClassicGreeter::clear()
+{
+ // assert( !running && !passwd1Edit );
+ passwdEdit->erase();
+ if (loginEdit) {
+ loginEdit->clear();
+ loginEdit->setFocus();
+ curUser = TQString::null;
+ } else
+ passwdEdit->setFocus();
+}
+
+
+// private
+
+void
+KClassicGreeter::setActive( bool enable )
+{
+ if (loginEdit)
+ loginEdit->setEnabled( enable );
+ if (passwdEdit)
+ passwdEdit->setEnabled( enable );
+}
+
+void
+KClassicGreeter::setActive2( bool enable )
+{
+ if (passwd1Edit) {
+ passwd1Edit->setEnabled( enable );
+ passwd2Edit->setEnabled( enable );
+ }
+}
+
+void
+KClassicGreeter::slotLoginLostFocus()
+{
+ if (!running)
+ return;
+ if (exp > 0) {
+ if (curUser == loginEdit->text())
+ return;
+ exp = -1;
+ handler->gplugReturnText( 0, 0 );
+ }
+ curUser = loginEdit->text();
+ handler->gplugSetUser( curUser );
+}
+
+void
+KClassicGreeter::slotActivity()
+{
+ if (running)
+ handler->gplugActivity();
+}
+
+// factory
+
+static bool init( const TQString &,
+ TQVariant (*getConf)( void *, const char *, const TQVariant & ),
+ void *ctx )
+{
+ echoMode = getConf( ctx, "EchoMode", TQVariant( -1 ) ).toInt();
+ KGlobal::locale()->insertCatalogue( "kgreet_classic" );
+ return true;
+}
+
+static void done( void )
+{
+ KGlobal::locale()->removeCatalogue( "kgreet_classic" );
+}
+
+static KGreeterPlugin *
+create( KGreeterPluginHandler *handler, KdmThemer *themer,
+ TQWidget *parent, TQWidget *predecessor,
+ const TQString &fixedEntity,
+ KGreeterPlugin::Function func,
+ KGreeterPlugin::Context ctx )
+{
+ return new KClassicGreeter( handler, themer, parent, predecessor, fixedEntity, func, ctx );
+}
+
+KDE_EXPORT kgreeterplugin_info kgreeterplugin_info = {
+ I18N_NOOP("Username + password (classic)"), "classic",
+ kgreeterplugin_info::Local | kgreeterplugin_info::Presettable,
+ init, done, create
+};
+
+#include "kgreet_classic.moc"
diff --git a/tdmlib/kgreet_classic.h b/tdmlib/kgreet_classic.h
new file mode 100644
index 000000000..1f467a528
--- /dev/null
+++ b/tdmlib/kgreet_classic.h
@@ -0,0 +1,88 @@
+/*
+
+Conversation widget for tdm greeter
+
+Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+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 of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#ifndef KGREET_CLASSIC_H
+#define KGREET_CLASSIC_H
+
+#include "kgreeterplugin.h"
+
+#include <tqobject.h>
+
+class KLineEdit;
+class KPasswordEdit;
+class KSimpleConfig;
+class TQGridLayout;
+class TQLabel;
+
+class KClassicGreeter : public TQObject, public KGreeterPlugin {
+ Q_OBJECT
+
+ public:
+ KClassicGreeter( KGreeterPluginHandler *handler,
+ KdmThemer *themer,
+ TQWidget *parent, TQWidget *predecessor,
+ const TQString &fixedEntitiy,
+ Function func, Context ctx );
+ ~KClassicGreeter();
+ virtual void loadUsers( const TQStringList &users );
+ virtual void presetEntity( const TQString &entity, int field );
+ virtual TQString getEntity() const;
+ virtual void setUser( const TQString &user );
+ virtual void setPassword( const TQString &pass );
+ virtual void setEnabled( bool on );
+ virtual bool textMessage( const char *message, bool error );
+ virtual void textPrompt( const char *prompt, bool echo, bool nonBlocking );
+ virtual bool binaryPrompt( const char *prompt, bool nonBlocking );
+ virtual void start();
+ virtual void suspend();
+ virtual void resume();
+ virtual void next();
+ virtual void abort();
+ virtual void succeeded();
+ virtual void failed();
+ virtual void revive();
+ virtual void clear();
+
+ public slots:
+ void slotLoginLostFocus();
+ void slotActivity();
+
+ private:
+ void setActive( bool enable );
+ void setActive2( bool enable );
+ void returnData();
+
+ TQLabel *loginLabel, *passwdLabel, *passwd1Label, *passwd2Label;
+ KLineEdit *loginEdit;
+ KPasswordEdit *passwdEdit, *passwd1Edit, *passwd2Edit;
+ KSimpleConfig *stsFile;
+ TQString fixedUser, curUser;
+ Function func;
+ Context ctx;
+ int exp, pExp, has;
+ bool running, authTok;
+};
+
+#endif /* KGREET_CLASSIC_H */
diff --git a/tdmlib/kgreet_pam.cpp b/tdmlib/kgreet_pam.cpp
new file mode 100644
index 000000000..82506fb43
--- /dev/null
+++ b/tdmlib/kgreet_pam.cpp
@@ -0,0 +1,675 @@
+/*
+
+Conversation widget for tdm greeter
+
+Copyright (C) 2008 Dirk Mueller <mueller@kde.org>
+
+based on classic tdm greeter:
+
+ Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org>
+ Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+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 of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include "kgreet_pam.h"
+#include "themer/tdmthemer.h"
+#include "themer/tdmlabel.h"
+
+#include <klocale.h>
+#include <klineedit.h>
+#include <kpassdlg.h>
+#include <kuser.h>
+
+#include <tqregexp.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqtimer.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+
+//#define PAM_GREETER_DEBUG
+
+class TDMPasswordEdit : public KPasswordEdit {
+public:
+ TDMPasswordEdit( TQWidget *parent ) : KPasswordEdit( parent, 0 ) {}
+ TDMPasswordEdit( KPasswordEdit::EchoModes echoMode, TQWidget *parent ) : KPasswordEdit( echoMode, parent, 0 ) {}
+protected:
+ virtual void contextMenuEvent( TQContextMenuEvent * ) {}
+};
+
+static FILE* log;
+static void kg_debug(const char* fmt, ...)
+{
+ va_list lst;
+ va_start(lst, fmt);
+
+#ifdef PAM_GREETER_DEBUG
+#if 0
+ vfprintf(log, fmt, lst);
+ fflush(log);
+#else
+ char buf[6000];
+ sprintf(buf, "*** %s\n", fmt);
+ vsyslog(LOG_WARNING, buf, lst);
+#endif
+#endif
+ va_end(lst);
+}
+
+static KPasswordEdit::EchoModes echoMode;
+
+KPamGreeter::KPamGreeter( KGreeterPluginHandler *_handler,
+ KdmThemer *themer,
+ TQWidget *parent, TQWidget *pred,
+ const TQString &_fixedEntity,
+ Function _func, Context _ctx ) :
+ TQObject(),
+ KGreeterPlugin( _handler ),
+ fixedUser( _fixedEntity ),
+ func( _func ),
+ ctx( _ctx ),
+ exp( -1 ),
+ pExp( -1 ),
+ running( false )
+{
+ ctx = Login;
+
+ kg_debug("KPamGreeter constructed\n");
+
+ m_parentWidget = parent;
+
+ KdmItem *user_entry = 0, *pw_entry = 0;
+ int line = 0;
+
+ layoutItem = 0;
+
+ if (themer &&
+ (!(user_entry = themer->findNode( "user-entry" )) ||
+ !(pw_entry = themer->findNode( "pw-entry" ))))
+ themer = 0;
+
+ m_themer = themer;
+
+ if (!themer)
+ layoutItem = TQT_TQLAYOUTITEM(new TQGridLayout( 0, 0, 10 ));
+
+ loginLabel = 0;
+ authLabel.clear();
+ authEdit.clear();
+ loginLabel = 0;
+ loginEdit = 0;
+ if (ctx == ExUnlock || ctx == ExChangeTok)
+ fixedUser = KUser().loginName();
+ if (func != ChAuthTok) {
+ kg_debug("func != ChAuthTok\n");
+ kg_debug("fixedUser: *%s*\n", fixedUser.latin1());
+
+ if (fixedUser.isEmpty()) {
+ loginEdit = new KLineEdit( parent );
+ loginEdit->setContextMenuEnabled( false );
+ connect( loginEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotLoginLostFocus()) );
+ connect( loginEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotActivity()) );
+ connect( loginEdit, TQT_SIGNAL(textChanged( const TQString & )), TQT_SLOT(slotActivity()) );
+ connect( loginEdit, TQT_SIGNAL(selectionChanged()), TQT_SLOT(slotActivity()) );
+ if (pred) {
+ parent->setTabOrder( pred, loginEdit );
+ pred = loginEdit;
+ }
+ if (!getLayoutItem()) {
+ loginEdit->adjustSize();
+ user_entry->setWidget( loginEdit );
+ } else {
+ loginLabel = new TQLabel( loginEdit, i18n("Username:"), parent );
+ getLayoutItem()->addWidget( loginLabel, line, 0 );
+ getLayoutItem()->addWidget( loginEdit, line++, 1 );
+ }
+ } else if (ctx != Login && ctx != Shutdown && getLayoutItem()) {
+ loginLabel = new TQLabel( i18n("Username:"), parent );
+ getLayoutItem()->addWidget( loginLabel, line, 0 );
+ getLayoutItem()->addWidget( new TQLabel( fixedUser, parent ), line++, 1 );
+ }
+#if 0
+ if (echoMode == -1)
+ passwdEdit = new TDMPasswordEdit( parent );
+ else
+ passwdEdit = new TDMPasswordEdit( echoMode,
+ parent );
+ connect( passwdEdit, TQT_SIGNAL(textChanged( const TQString & )),
+ TQT_SLOT(slotActivity()) );
+ connect( passwdEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotActivity()) );
+ if (pred) {
+ parent->setTabOrder( pred, passwdEdit );
+ pred = passwdEdit;
+ }
+ if (!getLayoutItem()) {
+ passwdEdit->adjustSize();
+ pw_entry->setWidget( passwdEdit );
+ } else {
+ passwdLabel = new TQLabel( passwdEdit,
+ func == Authenticate ?
+ i18n("hello &Password:") :
+ i18n("Current &password:"),
+ parent );
+ getLayoutItem()->addWidget( passwdLabel, line, 0 );
+ getLayoutItem()->addWidget( passwdEdit, line++, 1 );
+ }
+#endif
+ if (loginEdit)
+ loginEdit->setFocus();
+ }
+ if (func != Authenticate) {
+ if (echoMode == -1) {
+ authEdit << new TDMPasswordEdit( echoMode, parent );
+ authEdit << new TDMPasswordEdit( echoMode, parent );
+ } else {
+ authEdit << new TDMPasswordEdit( parent );
+ authEdit << new TDMPasswordEdit( parent );
+ }
+ authLabel << new TQLabel( authEdit[0], i18n("&New password:"), parent );
+ authLabel << new TQLabel( authEdit[1], i18n("Con&firm password:"), parent );
+ if (pred) {
+ parent->setTabOrder( pred, authEdit[0] );
+ parent->setTabOrder( authEdit[0], authEdit[1] );
+ }
+ if (getLayoutItem()) {
+ getLayoutItem()->addWidget( authLabel[0], line, 0 );
+ getLayoutItem()->addWidget( authEdit[0], line++, 1 );
+ getLayoutItem()->addWidget( authLabel[1], line, 0 );
+ getLayoutItem()->addWidget( authEdit[1], line, 1 );
+ }
+ if (authEdit.size() >= 2)
+ authEdit[1]->setFocus();
+ }
+}
+
+// virtual
+KPamGreeter::~KPamGreeter()
+{
+ kg_debug("KPamGreeter::~KPamGreeter");
+ abort();
+ if (!layoutItem) {
+ delete loginEdit;
+ return;
+ }
+ TQLayoutIterator it = TQT_TQLAYOUT(layoutItem)->iterator();
+ for (TQLayoutItem *itm = it.current(); itm; itm = ++it)
+ delete itm->widget();
+ delete layoutItem;
+ kg_debug("destructor finished, good bye");
+}
+
+void // virtual
+KPamGreeter::loadUsers( const TQStringList &users )
+{
+ KCompletion *userNamesCompletion = new KCompletion;
+ userNamesCompletion->setItems( users );
+ loginEdit->setCompletionObject( userNamesCompletion );
+ loginEdit->setAutoDeleteCompletionObject( true );
+ loginEdit->setCompletionMode( KGlobalSettings::CompletionAuto );
+}
+
+void // virtual
+KPamGreeter::presetEntity( const TQString &entity, int field )
+{
+ kg_debug("presetEntity(%s,%d) called!\n", entity.latin1(), field);
+ loginEdit->setText( entity );
+ if (field == 1 && authEdit.size() >= 1)
+ authEdit[0]->setFocus();
+ else {
+ loginEdit->setFocus();
+ loginEdit->selectAll();
+ if (field == -1 && authEdit.size() >= 1) {
+ authEdit[0]->setText( " " );
+ authEdit[0]->setEnabled( false );
+ authTok = false;
+ }
+ }
+ curUser = entity;
+}
+
+TQString // virtual
+KPamGreeter::getEntity() const
+{
+ return fixedUser.isEmpty() ? loginEdit->text() : fixedUser;
+}
+
+void // virtual
+KPamGreeter::setUser( const TQString &user )
+{
+ // assert( fixedUser.isEmpty() );
+ curUser = user;
+ loginEdit->setText( user );
+ if (authEdit.size() >= 1) {
+ authEdit[0]->setFocus();
+ authEdit[0]->selectAll();
+ }
+}
+
+void // virtual
+KPamGreeter::setPassword( const TQString &pass )
+{
+ authEdit[0]->erase();
+ authEdit[0]->insert( pass );
+}
+
+void // virtual
+KPamGreeter::setEnabled(bool enable)
+{
+ // assert( !passwd1Label );
+ // assert( func == Authenticate && ctx == Shutdown );
+// if (loginLabel)
+// loginLabel->setEnabled( enable );
+ authEdit[0]->setEnabled( enable );
+ setActive( enable );
+ if (enable)
+ authEdit[0]->setFocus();
+ }
+
+void // private
+KPamGreeter::returnData()
+{
+ kg_debug("*************** returnData called with exp %d\n", exp);
+
+
+ switch (exp) {
+ case 0:
+ handler->gplugReturnText( (loginEdit ? loginEdit->text() :
+ fixedUser).local8Bit(),
+ KGreeterPluginHandler::IsUser );
+ break;
+ case 1:
+ handler->gplugReturnText( authEdit[0]->password(),
+ KGreeterPluginHandler::IsPassword |
+ KGreeterPluginHandler::IsSecret );
+ break;
+ case 2:
+ handler->gplugReturnText( authEdit[1]->password(),
+ KGreeterPluginHandler::IsSecret );
+ break;
+ default: // case 3:
+ handler->gplugReturnText( authEdit[2]->password(),
+ KGreeterPluginHandler::IsNewPassword |
+ KGreeterPluginHandler::IsSecret );
+ break;
+ }
+}
+
+bool // virtual
+KPamGreeter::textMessage( const char *text, bool err )
+{
+ kg_debug(" ************** textMessage(%s, %d)\n", text, err);
+
+ if (!authEdit.size())
+ return false;
+
+ if (getLayoutItem()) {
+ TQLabel* label = new TQLabel(TQString::fromUtf8(text), m_parentWidget);
+ getLayoutItem()->addWidget(label, state+1, 0, 0);
+ }
+
+ return true;
+}
+
+void // virtual
+KPamGreeter::textPrompt( const char *prompt, bool echo, bool nonBlocking )
+{
+ kg_debug("textPrompt called with prompt %s echo %d nonBlocking %d", prompt, echo, nonBlocking);
+ kg_debug("state is %d, authEdit.size is %d\n", state, authEdit.size());
+
+ if (state == 0 && echo) {
+ if (loginLabel)
+ loginLabel->setText(TQString::fromUtf8(prompt));
+ else if (m_themer) {
+ KdmLabel *tdmlabel = static_cast<KdmLabel*>(m_themer->findNode("user-label"));
+ if (tdmlabel) {
+ //userLabel->setText(TQString::fromUtf8(prompt));
+ tdmlabel->label.text = TQString::fromUtf8(prompt);
+ TQTimer::singleShot(0, tdmlabel, TQT_SLOT(update()));
+ }
+ }
+ }
+ else if (state >= authEdit.size()) {
+ if (getLayoutItem()) {
+ TQLabel* label = new TQLabel(TQString::fromUtf8(prompt), m_parentWidget);
+ getLayoutItem()->addWidget(label, state+1, 0, 0);
+ kg_debug("added label widget to layout");
+ }
+ else if (m_themer) {
+ kg_debug("themer found!");
+ KdmItem *pw_label = 0;
+
+ KdmLabel *tdmlabel = static_cast<KdmLabel*>(m_themer->findNode("pw-label"));
+ if (tdmlabel) {
+ //userLabel->setText(TQString::fromUtf8(prompt));
+ TQString str = TQString::fromUtf8(prompt);
+ tdmlabel->label.text = str;
+ TQTimer::singleShot(0, tdmlabel, TQT_SLOT(update()));
+ }
+ }
+
+ TDMPasswordEdit* passwdEdit;
+
+ if (echoMode == -1)
+ passwdEdit = new TDMPasswordEdit( m_parentWidget );
+ else
+ passwdEdit = new TDMPasswordEdit( echoMode, m_parentWidget);
+ connect( passwdEdit, TQT_SIGNAL(textChanged( const TQString & )),
+ TQT_SLOT(slotActivity()) );
+ connect( passwdEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotActivity()) );
+ authEdit << passwdEdit;
+
+#if 1
+ for(TQValueList<KPasswordEdit*>::iterator it = authEdit.begin();
+ it != authEdit.end();
+ ++it) {
+ if ((*it)->isEnabled() && (*it)->text().isEmpty()) {
+ (*it)->setFocus();
+ break;
+ }
+ }
+#endif
+ if (getLayoutItem())
+ getLayoutItem()->addWidget(passwdEdit, state+1, 1, 0);
+
+ if (m_themer) {
+ kg_debug("themer found!");
+ KdmItem *pw_entry = 0;
+
+ pw_entry = m_themer->findNode("pw-entry");
+
+ if (pw_entry && passwdEdit)
+ pw_entry->setWidget(passwdEdit);
+
+ if (0) {
+ //userLabel->setText(TQString::fromUtf8(prompt));
+ //tdmlabel->label.text = TQString::fromUtf8(prompt);
+ //TQTimer::singleShot(0, tdmlabel, TQT_SLOT(update()));
+ }
+ }
+ else
+ kg_debug("no themer found!");
+ }
+ ++state;
+ pExp = exp;
+
+ exp = authEdit.size();
+ kg_debug("state %d exp: %d, has %d\n", state, exp, has);
+
+ if (has >= exp || nonBlocking)
+ returnData();
+}
+
+bool // virtual
+KPamGreeter::binaryPrompt( const char *, bool )
+{
+ // this simply cannot happen ... :}
+ return true;
+}
+
+void // virtual
+KPamGreeter::start()
+{
+ kg_debug("******* start() called\n");
+
+ while(authEdit.begin() != authEdit.end()) {
+ KPasswordEdit* item = *authEdit.remove(authEdit.begin());
+ delete item;
+ }
+
+ while(authLabel.begin() != authLabel.end()) {
+ TQLabel* item = *authLabel.remove(authLabel.begin());
+ delete item;
+ }
+
+ authTok = !(authEdit.size() >= 2 && authEdit[1]->isEnabled());
+ exp = has = -1;
+ state = 0;
+ running = true;
+ handler->gplugStart();
+}
+
+void // virtual
+KPamGreeter::suspend()
+{
+}
+
+void // virtual
+KPamGreeter::resume()
+{
+}
+
+void // virtual
+KPamGreeter::next()
+{
+ kg_debug("********* next() called state %d\n", state);
+
+ if (state == 0 && running && handler) {
+ kg_debug(" **** returned text!\n");
+ handler->gplugReturnText( (loginEdit ? loginEdit->text() :
+ fixedUser).local8Bit(),
+ KGreeterPluginHandler::IsUser );
+ setActive(false);
+ }
+
+ has = 0;
+
+ for(TQValueList<KPasswordEdit*>::iterator it = authEdit.begin();
+ it != authEdit.end();
+ ++it) {
+
+ has++;
+ if ((*it)->hasFocus()) {
+ ++it;
+ if (it != authEdit.end())
+ (*it)->setFocus();
+ break;
+ }
+ if (it == authEdit.end())
+ has = -1;
+ }
+
+ kg_debug(" has %d and exp %d\n", has, exp);
+
+#if 0
+ // assert( running );
+ if (loginEdit && loginEdit->hasFocus()) {
+ passwdEdit->setFocus(); // will cancel running login if necessary
+ has = 0;
+ } else if (passwdEdit && passwdEdit->hasFocus()) {
+ if (passwd1Edit)
+ passwd1Edit->setFocus();
+ has = 1;
+ } else if (passwd1Edit) {
+ if (passwd1Edit->hasFocus()) {
+ passwd2Edit->setFocus();
+ has = 1; // sic!
+ } else
+ has = 3;
+ } else
+ has = 1;
+ if (exp < 0)
+ handler->gplugStart();
+#endif
+ if (has >= exp)
+ returnData();
+}
+
+void // virtual
+KPamGreeter::abort()
+{
+ kg_debug("***** abort() called\n");
+
+ running = false;
+ if (exp >= 0) {
+ exp = -1;
+ handler->gplugReturnText( 0, 0 );
+ }
+}
+
+void // virtual
+KPamGreeter::succeeded()
+{
+ kg_debug("**** succeeded() called\n");
+
+ // assert( running || timed_login );
+ if (!authTok)
+ setActive( false );
+ else
+ setAllActive( false );
+ exp = -1;
+ running = false;
+}
+
+void // virtual
+KPamGreeter::failed()
+{
+ // assert( running || timed_login );
+ setActive( false );
+ setAllActive( false );
+ exp = -1;
+ running = false;
+}
+
+#include<assert.h>
+void // virtual
+KPamGreeter::revive()
+{
+ // assert( !running );
+ setAllActive( true );
+
+#if 1
+ if (authEdit.size() < 1)
+ return;
+#endif
+
+ assert(authEdit.size() >= 1);
+ if (authTok) {
+ authEdit[0]->erase();
+ if(authEdit.size() >= 2)
+ authEdit[1]->erase();
+ authEdit[0]->setFocus();
+ } else {
+ authEdit[0]->erase();
+ if (loginEdit && loginEdit->isEnabled())
+ authEdit[0]->setEnabled( true );
+ else {
+ setActive( true );
+ if (loginEdit && loginEdit->text().isEmpty())
+ loginEdit->setFocus();
+ else
+ authEdit[0]->setFocus();
+ }
+ }
+}
+
+void // virtual
+KPamGreeter::clear()
+{
+ // assert( !running && !passwd1Edit );
+ authEdit[0]->erase();
+ if (loginEdit) {
+ loginEdit->clear();
+ loginEdit->setFocus();
+ curUser = TQString::null;
+ } else
+ authEdit[0]->setFocus();
+}
+
+
+// private
+
+void
+KPamGreeter::setActive( bool enable )
+{
+ if (loginEdit)
+ loginEdit->setEnabled( enable );
+}
+
+void
+KPamGreeter::setAllActive( bool enable )
+{
+ for(TQValueList<KPasswordEdit*>::iterator it = authEdit.begin();
+ it != authEdit.end();
+ ++it)
+ (*it)->setEnabled( enable );
+}
+
+void
+KPamGreeter::slotLoginLostFocus()
+{
+ if (!running)
+ return;
+ if (exp > 0) {
+ if (curUser == loginEdit->text())
+ return;
+ exp = -1;
+ handler->gplugReturnText( 0, 0 );
+ }
+ curUser = loginEdit->text();
+ kg_debug("curUser is %s", curUser.latin1());
+ handler->gplugSetUser( curUser );
+}
+
+void
+KPamGreeter::slotActivity()
+{
+ kg_debug("slotActivity");
+
+ if (running)
+ handler->gplugActivity();
+}
+
+// factory
+
+static bool init( const TQString &,
+ TQVariant (*getConf)( void *, const char *, const TQVariant & ),
+ void *ctx )
+{
+ echoMode = (KPasswordEdit::EchoModes) getConf( ctx, "EchoMode", TQVariant( -1 ) ).toInt();
+ KGlobal::locale()->insertCatalogue( "kgreet_pam" );
+ return true;
+}
+
+static void done( void )
+{
+ KGlobal::locale()->removeCatalogue( "kgreet_pam" );
+ if (log && log != stderr)
+ fclose(log);
+ log = 0;
+}
+
+static KGreeterPlugin *
+create( KGreeterPluginHandler *handler, KdmThemer *themer,
+ TQWidget *parent, TQWidget *predecessor,
+ const TQString &fixedEntity,
+ KGreeterPlugin::Function func,
+ KGreeterPlugin::Context ctx )
+{
+ return new KPamGreeter( handler, themer, parent, predecessor, fixedEntity, func, ctx );
+}
+
+KDE_EXPORT kgreeterplugin_info kgreeterplugin_info = {
+ I18N_NOOP("Pam conversation plugin"), "pam",
+ kgreeterplugin_info::Local | kgreeterplugin_info::Presettable,
+ init, done, create
+};
+
+#include "kgreet_pam.moc"
diff --git a/tdmlib/kgreet_pam.h b/tdmlib/kgreet_pam.h
new file mode 100644
index 000000000..03c404c1e
--- /dev/null
+++ b/tdmlib/kgreet_pam.h
@@ -0,0 +1,94 @@
+/*
+
+Conversation widget for tdm greeter
+
+Copyright (C) 2008 Dirk Mueller <mueller@kde.org>
+
+
+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 of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#ifndef KGREET_CLASSIC_H
+#define KGREET_CLASSIC_H
+
+#include "kgreeterplugin.h"
+
+#include <tqobject.h>
+#include <tqlayout.h>
+
+class KLineEdit;
+class KPasswordEdit;
+class KSimpleConfig;
+class TQGridLayout;
+class TQLabel;
+
+class KPamGreeter : public TQObject, public KGreeterPlugin {
+ Q_OBJECT
+
+ public:
+ KPamGreeter( KGreeterPluginHandler *handler,
+ KdmThemer *themer,
+ TQWidget *parent, TQWidget *predecessor,
+ const TQString &fixedEntitiy,
+ Function func, Context ctx );
+ ~KPamGreeter();
+ virtual void loadUsers( const TQStringList &users );
+ virtual void presetEntity( const TQString &entity, int field );
+ virtual TQString getEntity() const;
+ virtual void setUser( const TQString &user );
+ virtual void setPassword( const TQString &pass );
+ virtual void setEnabled( bool on );
+ virtual bool textMessage( const char *message, bool error );
+ virtual void textPrompt( const char *prompt, bool echo, bool nonBlocking );
+ virtual bool binaryPrompt( const char *prompt, bool nonBlocking );
+ virtual void start();
+ virtual void suspend();
+ virtual void resume();
+ virtual void next();
+ virtual void abort();
+ virtual void succeeded();
+ virtual void failed();
+ virtual void revive();
+ virtual void clear();
+
+ TQGridLayout *getLayoutItem() const { return static_cast<TQGridLayout*>(TQT_TQLAYOUT(layoutItem)); }
+
+ public slots:
+ void slotLoginLostFocus();
+ void slotActivity();
+
+ private:
+ void setActive( bool enable );
+ void setAllActive( bool enable );
+ void returnData();
+
+ TQLabel *loginLabel;
+ TQValueList<TQLabel*> authLabel;
+ KLineEdit *loginEdit;
+ TQWidget* m_parentWidget;
+ TQValueList<KPasswordEdit*> authEdit;
+ KSimpleConfig *stsFile;
+ KdmThemer *m_themer;
+ TQString fixedUser, curUser;
+ Function func;
+ Context ctx;
+ int exp, pExp, has;
+ unsigned state;
+ bool running, authTok;
+};
+
+#endif /* KGREET_CLASSIC_H */
diff --git a/tdmlib/kgreet_winbind.cpp b/tdmlib/kgreet_winbind.cpp
new file mode 100644
index 000000000..d5626a3fd
--- /dev/null
+++ b/tdmlib/kgreet_winbind.cpp
@@ -0,0 +1,679 @@
+/*
+
+Conversation widget for tdm greeter
+
+Copyright (C) 1997, 1998, 2000 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2004 Oswald Buddenhagen <ossi@kde.org>
+
+
+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 of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include "kgreet_winbind.h"
+#include "themer/tdmthemer.h"
+#include "themer/tdmitem.h"
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <kpassdlg.h>
+#include <kuser.h>
+#include <kprocio.h>
+
+#include <tqregexp.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+
+#include <stdlib.h>
+
+class TDMPasswordEdit : public KPasswordEdit {
+public:
+ TDMPasswordEdit( TQWidget *parent ) : KPasswordEdit( parent, 0 ) {}
+ TDMPasswordEdit( KPasswordEdit::EchoModes echoMode, TQWidget *parent ) : KPasswordEdit( echoMode, parent, 0 ) {}
+protected:
+ virtual void contextMenuEvent( TQContextMenuEvent * ) {}
+};
+
+static int echoMode;
+static char separator;
+static TQStringList staticDomains;
+static TQString defaultDomain;
+
+static void
+splitEntity( const TQString &ent, TQString &dom, TQString &usr )
+{
+ int pos = ent.find( separator );
+ if (pos < 0)
+ dom = "<local>", usr = ent;
+ else
+ dom = ent.left( pos ), usr = ent.mid( pos + 1 );
+}
+
+KWinbindGreeter::KWinbindGreeter( KGreeterPluginHandler *_handler,
+ KdmThemer *themer,
+ TQWidget *parent, TQWidget *pred,
+ const TQString &_fixedEntity,
+ Function _func, Context _ctx ) :
+ TQObject(),
+ KGreeterPlugin( _handler ),
+ func( _func ),
+ ctx( _ctx ),
+ exp( -1 ),
+ pExp( -1 ),
+ running( false )
+{
+ KdmItem *user_entry = 0, *pw_entry = 0, *domain_entry = 0;
+ TQGridLayout *grid = 0;
+
+ int line = 0;
+ layoutItem = 0;
+
+ if (themer &&
+ (!(user_entry = themer->findNode( "user-entry" )) ||
+ !(pw_entry = themer->findNode( "pw-entry" )) ||
+ !(domain_entry = themer->findNode( "domain-entry" ))))
+ themer = 0;
+
+ if (!themer)
+ grid = new TQGridLayout( 0, 0, 10 );
+ layoutItem = TQT_TQLAYOUTITEM(grid);
+
+ domainLabel = loginLabel = passwdLabel = passwd1Label = passwd2Label = 0;
+ domainCombo = 0;
+ loginEdit = 0;
+ passwdEdit = passwd1Edit = passwd2Edit = 0;
+ m_domainLister = 0;
+ if (ctx == ExUnlock || ctx == ExChangeTok)
+ splitEntity( KUser().loginName(), fixedDomain, fixedUser );
+ else
+ splitEntity( _fixedEntity, fixedDomain, fixedUser );
+ if (func != ChAuthTok) {
+ if (fixedUser.isEmpty()) {
+ domainCombo = new KComboBox( parent );
+ connect( domainCombo, TQT_SIGNAL(activated( const TQString & )),
+ TQT_SLOT(slotChangedDomain( const TQString & )) );
+ connect( domainCombo, TQT_SIGNAL(activated( const TQString & )),
+ TQT_SLOT(slotLoginLostFocus()) );
+ connect( domainCombo, TQT_SIGNAL(activated( const TQString & )),
+ TQT_SLOT(slotActivity()) );
+ // should handle loss of focus
+ loginEdit = new KLineEdit( parent );
+ loginEdit->setContextMenuEnabled( false );
+
+ if (pred) {
+ parent->setTabOrder( pred, domainCombo );
+ parent->setTabOrder( domainCombo, loginEdit );
+ pred = loginEdit;
+ }
+ if (!grid) {
+ loginEdit->adjustSize();
+ domainCombo->adjustSize();
+ user_entry->setWidget( loginEdit );
+ domain_entry->setWidget( domainCombo );
+ } else {
+ domainLabel = new TQLabel( domainCombo, i18n("&Domain:"), parent );
+ loginLabel = new TQLabel( loginEdit, i18n("&Username:"), parent );
+ grid->addWidget( domainLabel, line, 0 );
+ grid->addWidget( domainCombo, line++, 1 );
+ grid->addWidget( loginLabel, line, 0 );
+ grid->addWidget( loginEdit, line++, 1 );
+ }
+ connect( loginEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotLoginLostFocus()) );
+ connect( loginEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotActivity()) );
+ connect( loginEdit, TQT_SIGNAL(textChanged( const TQString & )), TQT_SLOT(slotActivity()) );
+ connect( loginEdit, TQT_SIGNAL(selectionChanged()), TQT_SLOT(slotActivity()) );
+ connect(&mDomainListTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotStartDomainList()));
+ domainCombo->insertStringList( staticDomains );
+ TQTimer::singleShot(0, this, TQT_SLOT(slotStartDomainList()));
+ } else if (ctx != Login && ctx != Shutdown && grid) {
+ domainLabel = new TQLabel( i18n("Domain:"), parent );
+ grid->addWidget( domainLabel, line, 0 );
+ grid->addWidget( new TQLabel( fixedDomain, parent ), line++, 1 );
+ loginLabel = new TQLabel( i18n("Username:"), parent );
+ grid->addWidget( loginLabel, line, 0 );
+ grid->addWidget( new TQLabel( fixedUser, parent ), line++, 1 );
+ }
+ if (echoMode == -1)
+ passwdEdit = new TDMPasswordEdit( parent );
+ else
+ passwdEdit = new TDMPasswordEdit( (KPasswordEdit::EchoModes)echoMode,
+ parent );
+ connect( passwdEdit, TQT_SIGNAL(textChanged( const TQString & )),
+ TQT_SLOT(slotActivity()) );
+ connect( passwdEdit, TQT_SIGNAL(lostFocus()), TQT_SLOT(slotActivity()) );
+
+ if (!grid) {
+ passwdEdit->adjustSize();
+ pw_entry->setWidget( passwdEdit );
+ } else {
+ passwdLabel = new TQLabel( passwdEdit,
+ func == Authenticate ?
+ i18n("&Password:") :
+ i18n("Current &password:"),
+ parent );
+ if (pred) {
+ parent->setTabOrder( pred, passwdEdit );
+ pred = passwdEdit;
+ }
+ grid->addWidget( passwdLabel, line, 0 );
+ grid->addWidget( passwdEdit, line++, 1 );
+ }
+
+ if (loginEdit)
+ loginEdit->setFocus();
+ else
+ passwdEdit->setFocus();
+ }
+ if (func != Authenticate) {
+ if (echoMode == -1) {
+ passwd1Edit = new TDMPasswordEdit( (KPasswordEdit::EchoModes)echoMode, parent );
+ passwd2Edit = new TDMPasswordEdit( (KPasswordEdit::EchoModes)echoMode, parent );
+ } else {
+ passwd1Edit = new TDMPasswordEdit( parent );
+ passwd2Edit = new TDMPasswordEdit( parent );
+ }
+ passwd1Label = new TQLabel( passwd1Edit, i18n("&New password:"), parent );
+ passwd2Label = new TQLabel( passwd2Edit, i18n("Con&firm password:"), parent );
+ if (pred) {
+ parent->setTabOrder( pred, passwd1Edit );
+ parent->setTabOrder( passwd1Edit, passwd2Edit );
+ }
+ if (grid) {
+ grid->addWidget( passwd1Label, line, 0 );
+ grid->addWidget( passwd1Edit, line++, 1 );
+ grid->addWidget( passwd2Label, line, 0 );
+ grid->addWidget( passwd2Edit, line, 1 );
+ }
+ if (!passwdEdit)
+ passwd1Edit->setFocus();
+ }
+}
+
+// virtual
+KWinbindGreeter::~KWinbindGreeter()
+{
+ abort();
+ if (!layoutItem) {
+ delete loginEdit;
+ delete passwdEdit;
+ delete domainCombo;
+ return;
+ }
+ TQLayoutIterator it = TQT_TQLAYOUT(layoutItem)->iterator();
+ for (TQLayoutItem *itm = it.current(); itm; itm = ++it)
+ delete itm->widget();
+ delete layoutItem;
+ delete m_domainLister;
+}
+
+void
+KWinbindGreeter::slotChangedDomain( const TQString &dom )
+{
+ if (!loginEdit->completionObject())
+ return;
+ TQStringList users;
+ if (dom == "<local>") {
+ for (TQStringList::ConstIterator it = allUsers.begin(); it != allUsers.end(); ++it)
+ if ((*it).find( separator ) < 0)
+ users << *it;
+ } else {
+ TQString st( dom + separator );
+ for (TQStringList::ConstIterator it = allUsers.begin(); it != allUsers.end(); ++it)
+ if ((*it).startsWith( st ))
+ users << (*it).mid( st.length() );
+ }
+ loginEdit->completionObject()->setItems( users );
+}
+
+void // virtual
+KWinbindGreeter::loadUsers( const TQStringList &users )
+{
+ allUsers = users;
+ KCompletion *userNamesCompletion = new KCompletion;
+ loginEdit->setCompletionObject( userNamesCompletion );
+ loginEdit->setAutoDeleteCompletionObject( true );
+ loginEdit->setCompletionMode( KGlobalSettings::CompletionAuto );
+ slotChangedDomain( defaultDomain );
+}
+
+void // virtual
+KWinbindGreeter::presetEntity( const TQString &entity, int field )
+{
+ TQString dom, usr;
+ splitEntity( entity, dom, usr );
+ domainCombo->setCurrentItem( dom, true );
+ slotChangedDomain( dom );
+ loginEdit->setText( usr );
+ if (field > 1)
+ passwdEdit->setFocus();
+ else if (field == 1 || field == -1) {
+ if (field == -1) {
+ passwdEdit->setText( " " );
+ passwdEdit->setEnabled( false );
+ authTok = false;
+ }
+ loginEdit->setFocus();
+ loginEdit->selectAll();
+ }
+ curUser = entity;
+}
+
+TQString // virtual
+KWinbindGreeter::getEntity() const
+{
+ TQString dom, usr;
+ if (fixedUser.isEmpty())
+ dom = domainCombo->currentText(), usr = loginEdit->text();
+ else
+ dom = fixedDomain, usr = fixedUser;
+ return dom == "<local>" ? usr : dom + separator + usr;
+}
+
+void // virtual
+KWinbindGreeter::setUser( const TQString &user )
+{
+ // assert (fixedUser.isEmpty());
+ curUser = user;
+ TQString dom, usr;
+ splitEntity( user, dom, usr );
+ domainCombo->setCurrentItem( dom, true );
+ slotChangedDomain( dom );
+ loginEdit->setText( usr );
+ passwdEdit->setFocus();
+ passwdEdit->selectAll();
+}
+
+void // virtual
+KWinbindGreeter::setPassword( const TQString &pass )
+{
+ passwdEdit->erase();
+ passwdEdit->insert( pass );
+}
+
+void // virtual
+KWinbindGreeter::setEnabled( bool enable )
+{
+ // assert( !passwd1Label );
+ // assert( func == Authenticate && ctx == Shutdown );
+// if (domainCombo)
+// domainCombo->setEnabled( enable );
+// if (loginLabel)
+// loginLabel->setEnabled( enable );
+ passwdLabel->setEnabled( enable );
+ setActive( enable );
+ if (enable)
+ passwdEdit->setFocus();
+}
+
+void // private
+KWinbindGreeter::returnData()
+{
+ switch (exp) {
+ case 0:
+ handler->gplugReturnText( getEntity().local8Bit(),
+ KGreeterPluginHandler::IsUser );
+ break;
+ case 1:
+ handler->gplugReturnText( passwdEdit->password(),
+ KGreeterPluginHandler::IsPassword |
+ KGreeterPluginHandler::IsSecret );
+ break;
+ case 2:
+ handler->gplugReturnText( passwd1Edit->password(),
+ KGreeterPluginHandler::IsSecret );
+ break;
+ default: // case 3:
+ handler->gplugReturnText( passwd2Edit->password(),
+ KGreeterPluginHandler::IsNewPassword |
+ KGreeterPluginHandler::IsSecret );
+ break;
+ }
+}
+
+bool // virtual
+KWinbindGreeter::textMessage( const char *text, bool err )
+{
+ if (!err &&
+ TQString( text ).find( TQRegExp( "^Changing password for [^ ]+$" ) ) >= 0)
+ return true;
+ return false;
+}
+
+void // virtual
+KWinbindGreeter::textPrompt( const char *prompt, bool echo, bool nonBlocking )
+{
+ pExp = exp;
+ if (echo)
+ exp = 0;
+ else if (!authTok)
+ exp = 1;
+ else {
+ TQString pr( prompt );
+ if (pr.find( TQRegExp( "\\b(old|current)\\b", false ) ) >= 0) {
+ handler->gplugReturnText( "",
+ KGreeterPluginHandler::IsOldPassword |
+ KGreeterPluginHandler::IsSecret );
+ return;
+ } else if (pr.find( TQRegExp( "\\b(re-?(enter|type)|again|confirm|repeat)\\b",
+ false ) ) >= 0)
+ exp = 3;
+ else if (pr.find( TQRegExp( "\\bnew\\b", false ) ) >= 0)
+ exp = 2;
+ else {
+ handler->gplugMsgBox( TQMessageBox::Critical,
+ i18n("Unrecognized prompt \"%1\"")
+ .arg( prompt ) );
+ handler->gplugReturnText( 0, 0 );
+ exp = -1;
+ return;
+ }
+ }
+
+ if (pExp >= 0 && pExp >= exp) {
+ revive();
+ has = -1;
+ }
+
+ if (has >= exp || nonBlocking)
+ returnData();
+}
+
+bool // virtual
+KWinbindGreeter::binaryPrompt( const char *, bool )
+{
+ // this simply cannot happen ... :}
+ return true;
+}
+
+void // virtual
+KWinbindGreeter::start()
+{
+ authTok = !(passwdEdit && passwdEdit->isEnabled());
+ exp = has = -1;
+ running = true;
+}
+
+void // virtual
+KWinbindGreeter::suspend()
+{
+}
+
+void // virtual
+KWinbindGreeter::resume()
+{
+}
+
+void // virtual
+KWinbindGreeter::next()
+{
+ // assert( running );
+ if (domainCombo && domainCombo->hasFocus())
+ loginEdit->setFocus();
+ else if (loginEdit && loginEdit->hasFocus()) {
+ passwdEdit->setFocus(); // will cancel running login if necessary
+ has = 0;
+ } else if (passwdEdit && passwdEdit->hasFocus()) {
+ if (passwd1Edit)
+ passwd1Edit->setFocus();
+ has = 1;
+ } else if (passwd1Edit) {
+ if (passwd1Edit->hasFocus()) {
+ passwd2Edit->setFocus();
+ has = 1; // sic!
+ } else
+ has = 3;
+ } else
+ has = 1;
+ if (exp < 0)
+ handler->gplugStart();
+ else if (has >= exp)
+ returnData();
+}
+
+void // virtual
+KWinbindGreeter::abort()
+{
+ running = false;
+ if (exp >= 0) {
+ exp = -1;
+ handler->gplugReturnText( 0, 0 );
+ }
+}
+
+void // virtual
+KWinbindGreeter::succeeded()
+{
+ // assert( running || timed_login );
+ if (!authTok) {
+ setActive( false );
+ if (passwd1Edit) {
+ authTok = true;
+ return;
+ }
+ } else
+ setActive2( false );
+ exp = -1;
+ running = false;
+}
+
+void // virtual
+KWinbindGreeter::failed()
+{
+ // assert( running || timed_login );
+ setActive( false );
+ setActive2( false );
+ exp = -1;
+ running = false;
+}
+
+void // virtual
+KWinbindGreeter::revive()
+{
+ // assert( !running );
+ setActive2( true );
+ if (authTok) {
+ passwd1Edit->erase();
+ passwd2Edit->erase();
+ passwd1Edit->setFocus();
+ } else {
+ passwdEdit->erase();
+ if (loginEdit && loginEdit->isEnabled())
+ passwdEdit->setEnabled( true );
+ else {
+ setActive( true );
+ if (loginEdit && loginEdit->text().isEmpty())
+ loginEdit->setFocus();
+ else
+ passwdEdit->setFocus();
+ }
+ }
+}
+
+void // virtual
+KWinbindGreeter::clear()
+{
+ // assert( !running && !passwd1Edit );
+ passwdEdit->erase();
+ if (loginEdit) {
+ domainCombo->setCurrentItem( defaultDomain );
+ slotChangedDomain( defaultDomain );
+ loginEdit->clear();
+ loginEdit->setFocus();
+ curUser = TQString::null;
+ } else
+ passwdEdit->setFocus();
+}
+
+
+// private
+
+void
+KWinbindGreeter::setActive( bool enable )
+{
+ if (domainCombo)
+ domainCombo->setEnabled( enable );
+ if (loginEdit)
+ loginEdit->setEnabled( enable );
+ if (passwdEdit)
+ passwdEdit->setEnabled( enable );
+}
+
+void
+KWinbindGreeter::setActive2( bool enable )
+{
+ if (passwd1Edit) {
+ passwd1Edit->setEnabled( enable );
+ passwd2Edit->setEnabled( enable );
+ }
+}
+
+void
+KWinbindGreeter::slotLoginLostFocus()
+{
+ if (!running)
+ return;
+ TQString ent( getEntity() );
+ if (exp > 0) {
+ if (curUser == ent)
+ return;
+ exp = -1;
+ handler->gplugReturnText( 0, 0 );
+ }
+ curUser = ent;
+ handler->gplugSetUser( curUser );
+}
+
+void
+KWinbindGreeter::slotActivity()
+{
+ if (running)
+ handler->gplugActivity();
+}
+
+void
+KWinbindGreeter::slotStartDomainList()
+{
+ mDomainListTimer.stop();
+ mDomainListing.clear();
+
+ m_domainLister = new KProcIO;
+ connect(m_domainLister, TQT_SIGNAL(readReady(KProcIO*)), TQT_SLOT(slotReadDomainList()));
+ connect(m_domainLister, TQT_SIGNAL(processExited(KProcess*)), TQT_SLOT(slotEndDomainList()));
+
+ (*m_domainLister) << "wbinfo" << "--own-domain" << "--trusted-domains";
+ m_domainLister->setComm (KProcess::Stdout);
+ m_domainLister->start();
+}
+
+void
+KWinbindGreeter::slotReadDomainList()
+{
+ TQString line;
+
+ while ( m_domainLister->readln( line ) != -1 ) {
+ mDomainListing.append(line);
+ }
+}
+
+void
+KWinbindGreeter::slotEndDomainList()
+{
+ delete m_domainLister;
+ m_domainLister = 0;
+
+ TQStringList domainList;
+ domainList = staticDomains;
+
+ for (TQStringList::const_iterator it = mDomainListing.begin();
+ it != mDomainListing.end(); ++it) {
+
+ if (!domainList.contains(*it))
+ domainList.append(*it);
+ }
+
+ TQString current = domainCombo->currentText();
+
+ for (int i = 0; i < domainList.count(); ++i) {
+ if (i < domainCombo->count())
+ domainCombo->changeItem(domainList[i], i);
+ else
+ domainCombo->insertItem(domainList[i], i);
+ }
+
+ while (domainCombo->count() > domainList.count())
+ domainCombo->removeItem(domainCombo->count()-1);
+
+ domainCombo->setCurrentItem( current );
+
+ if (domainCombo->currentText() != current)
+ domainCombo->setCurrentItem( defaultDomain );
+
+ mDomainListTimer.start(5 * 1000);
+}
+
+// factory
+
+static bool init( const TQString &,
+ TQVariant (*getConf)( void *, const char *, const TQVariant & ),
+ void *ctx )
+{
+ echoMode = getConf( ctx, "EchoMode", TQVariant( -1 ) ).toInt();
+ staticDomains = TQStringList::split( ':', getConf( ctx, "winbind.Domains", TQVariant( "" ) ).toString() );
+ if (!staticDomains.contains("<local>"))
+ staticDomains << "<local>";
+
+ defaultDomain = getConf( ctx, "winbind.DefaultDomain", TQVariant( staticDomains.first() ) ).toString();
+ TQString sepstr = getConf( ctx, "winbind.Separator", TQVariant( TQString::null ) ).toString();
+ if (sepstr.isNull()) {
+ FILE *sepfile = popen( "wbinfo --separator 2>/dev/null", "r" );
+ if (sepfile) {
+ TQTextIStream( sepfile ) >> sepstr;
+ if (pclose( sepfile ))
+ sepstr = "\\";
+ } else
+ sepstr = "\\";
+ }
+ separator = sepstr[0].latin1();
+ KGlobal::locale()->insertCatalogue( "kgreet_winbind" );
+ return true;
+}
+
+static void done( void )
+{
+ KGlobal::locale()->removeCatalogue( "kgreet_winbind" );
+ // avoid static deletion problems ... hopefully
+ staticDomains.clear();
+ defaultDomain = TQString::null;
+}
+
+static KGreeterPlugin *
+create( KGreeterPluginHandler *handler, KdmThemer *themer,
+ TQWidget *parent, TQWidget *predecessor,
+ const TQString &fixedEntity,
+ KGreeterPlugin::Function func,
+ KGreeterPlugin::Context ctx )
+{
+ return new KWinbindGreeter( handler, themer, parent, predecessor, fixedEntity, func, ctx );
+}
+
+KDE_EXPORT kgreeterplugin_info kgreeterplugin_info = {
+ I18N_NOOP("Winbind / Samba"), "classic",
+ kgreeterplugin_info::Local | kgreeterplugin_info::Fielded | kgreeterplugin_info::Presettable,
+ init, done, create
+};
+
+#include "kgreet_winbind.moc"
diff --git a/tdmlib/kgreet_winbind.h b/tdmlib/kgreet_winbind.h
new file mode 100644
index 000000000..54f2653fc
--- /dev/null
+++ b/tdmlib/kgreet_winbind.h
@@ -0,0 +1,101 @@
+/*
+
+Conversation widget for tdm greeter
+
+Copyright (C) 1997, 1998 Steffen Hansen <hansen@kde.org>
+Copyright (C) 2000-2003 Oswald Buddenhagen <ossi@kde.org>
+
+
+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 of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#ifndef KGREET_WINBIND_H
+#define KGREET_WINBIND_H
+
+#include "kgreeterplugin.h"
+
+#include <tqobject.h>
+#include <tqtimer.h>
+
+class KComboBox;
+class KLineEdit;
+class KPasswordEdit;
+class KSimpleConfig;
+class TQGridLayout;
+class TQLabel;
+class KdmThemer;
+class KProcIO;
+
+class KWinbindGreeter : public TQObject, public KGreeterPlugin {
+ Q_OBJECT
+
+ public:
+ KWinbindGreeter( KGreeterPluginHandler *handler,
+ KdmThemer *themer,
+ TQWidget *parent, TQWidget *predecessor,
+ const TQString &fixedEntitiy,
+ Function func, Context ctx );
+ ~KWinbindGreeter();
+ virtual void loadUsers( const TQStringList &users );
+ virtual void presetEntity( const TQString &entity, int field );
+ virtual TQString getEntity() const;
+ virtual void setUser( const TQString &user );
+ virtual void setPassword( const TQString &pass );
+ virtual void setEnabled( bool on );
+ virtual bool textMessage( const char *message, bool error );
+ virtual void textPrompt( const char *prompt, bool echo, bool nonBlocking );
+ virtual bool binaryPrompt( const char *prompt, bool nonBlocking );
+ virtual void start();
+ virtual void suspend();
+ virtual void resume();
+ virtual void next();
+ virtual void abort();
+ virtual void succeeded();
+ virtual void failed();
+ virtual void revive();
+ virtual void clear();
+
+ public slots:
+ void slotLoginLostFocus();
+ void slotChangedDomain( const TQString &dom );
+ void slotActivity();
+ void slotStartDomainList();
+ void slotReadDomainList();
+ void slotEndDomainList();
+
+ private:
+ void setActive( bool enable );
+ void setActive2( bool enable );
+ void returnData();
+
+ TQLabel *domainLabel, *loginLabel, *passwdLabel, *passwd1Label, *passwd2Label;
+ KComboBox *domainCombo;
+ KLineEdit *loginEdit;
+ KPasswordEdit *passwdEdit, *passwd1Edit, *passwd2Edit;
+ KSimpleConfig *stsFile;
+ TQString fixedDomain, fixedUser, curUser;
+ TQStringList allUsers, mDomainListing;
+ KProcIO* m_domainLister;
+ TQTimer mDomainListTimer;
+
+ Function func;
+ Context ctx;
+ int exp, pExp, has;
+ bool running, authTok;
+};
+
+#endif /* KGREET_WINBIND_H */
diff --git a/tdmlib/kgreeterplugin.h b/tdmlib/kgreeterplugin.h
new file mode 100644
index 000000000..edf67f141
--- /dev/null
+++ b/tdmlib/kgreeterplugin.h
@@ -0,0 +1,407 @@
+/*
+
+ Authentication method specific conversation plugin for KDE's greeter widgets
+
+ Copyright (C) 2003 Oswald Buddenhagen <ossi@kde.org>
+ Copyright (C) 2003 Fabian Kaiser <xfk@softpro.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KGREETERPLUGIN_H
+#define KGREETERPLUGIN_H
+
+#include <tqvariant.h>
+#include <tqmessagebox.h>
+#include <kdemacros.h>
+
+class KdmThemer;
+
+class TQWidget;
+class TQLayoutItem;
+
+class KGreeterPluginHandler {
+public:
+ /* keep in sync with V_IS_* */
+ enum { IsSecret = 1, IsUser = 2, IsPassword = 4, IsOldPassword = 8,
+ IsNewPassword = 16 };
+ /**
+ * Reply to textPrompt().
+ * @param text text to return to core; null to abort auth cycle
+ * @param tag zero or one of Is*
+ */
+ virtual void gplugReturnText( const char *text, int tag ) = 0;
+ /**
+ * Reply to binaryPrompt().
+ * @param data data in pam_client format to return to the core;
+ * null to abort auth cycle
+ */
+ virtual void gplugReturnBinary( const char *data ) = 0;
+ /**
+ * Tell the greeter who is logging in.
+ * Call this preferably before gplugStart, as otherwise the .dmrc
+ * load will be delayed. Don't call at all if your plugin doesn't
+ * have the Local flag set. Call only for internally generated
+ * user changes.
+ * @param user the user logging in
+ */
+ virtual void gplugSetUser( const TQString &user ) = 0;
+ /**
+ * Start processing.
+ */
+ virtual void gplugStart() = 0;
+ /**
+ * Plugins that expect user input from a different device than the mouse or
+ * keyboard must call this when user activity is detected to prevent the
+ * greeter from resetting/going away. Events should be compressed to no
+ * more than ten per second; one every five seconds is actually enough.
+ * Events should be actual changes to the input fields, not random motion.
+ */
+ virtual void gplugActivity() = 0;
+ /**
+ * Show a message box on behalf of the talker.
+ * @param type message severity
+ * @param text message text
+ */
+ virtual void gplugMsgBox( TQMessageBox::Icon type, const TQString &text ) = 0;
+};
+
+/**
+ * Abstract base class for conversation plugins ("talkers") to be used with
+ * TDM, kdesktop_lock, etc.
+ * The authentication method used by a particular instance of a plugin
+ * may be configurable, but the instance must handle exactly one method,
+ * i.e., info->method must be determined at the latest at init() time.
+ */
+class KGreeterPlugin {
+public:
+ KGreeterPlugin( KGreeterPluginHandler *h ) : handler( h ) {}
+ virtual ~KGreeterPlugin() {}
+
+ /**
+ * Variations of the talker:
+ * - Authenticate: authentication
+ * - AuthChAuthTok: authentication and password change
+ * - ChAuthTok: password change
+ */
+ enum Function { Authenticate, AuthChAuthTok, ChAuthTok };
+
+ /**
+ * Contexts the talker can be used in:
+ * - Login: tdm login dialog
+ * - Shutdown: tdm shutdown dialog
+ * - Unlock: tdm unlock dialog (TODO)
+ * - ChangeTok: tdm password change dialog (TODO)
+ * - ExUnlock: kdesktop_lock unlock dialog
+ * - ExChangeTok: kdepasswd password change dialog (TODO)
+ *
+ * The Ex* contexts exist within a running session; the talker must know
+ * how to obtain the currently logged in user (+ domain/realm, etc.)
+ * itself (i.e., fixedEntity will be null). The non-Ex variants will have
+ * a fixedEntity passed in.
+ */
+ enum Context { Login, Shutdown, Unlock, ChangeTok,
+ ExUnlock, ExChangeTok };
+
+ /**
+ * Provide the talker with a list of selectable users. This can be used
+ * for autocompletion, etc.
+ * Will be called only when not running.
+ * @param users the users to load.
+ */
+ virtual void loadUsers( const TQStringList &users ) = 0;
+
+ /**
+ * Preload the talker with an (opaque to the greeter) entity.
+ * Will be called only when not running.
+ * @param entity the entity to preload the talker with. That
+ * will usually be something like "user" or "user@domain".
+ * @param field the sub-widget (probably line edit) to put the cursor into.
+ * If -1, preselect the user for timed login. This means pre-filling
+ * the password field with anything, disabling it, and placing the
+ * cursor in the user name field.
+ */
+ virtual void presetEntity( const TQString &entity, int field ) = 0;
+
+ /**
+ * Obtain the actually logged in entity.
+ * Will be called only after succeeded() was called.
+ */
+ virtual TQString getEntity() const = 0;
+
+ /**
+ * "Push" a user into the talker. That can be a click into the user list
+ * or successful authentication without the talker calling gplugSetUser.
+ * Will be called only when running.
+ * @param user the user to set. Note that this is a UNIX login, not a
+ * canonical entity
+ */
+ virtual void setUser( const TQString &user ) = 0;
+
+ /**
+ * "Push" a password into the talker.
+ * @param pass the password to set.
+ */
+ virtual void setPassword( const TQString &pass ) = 0;
+
+ /**
+ * En-/disable any widgets contained in the talker.
+ * Will be called only when not running.
+ * @param on the state to set
+ */
+ virtual void setEnabled( bool on ) = 0;
+
+ /**
+ * Called when a message from the authentication backend arrives.
+ * @param message the message received from the backend
+ * @param error if true, @p message is an error message, otherwise it's
+ * an informational message
+ * @return true means that the talker already handled the message, false
+ * that the greeter should display it in a message box
+ *
+ * FIXME: Filtering a message usually means that the backend issued a
+ * prompt and obtains the authentication data itself. However, in that
+ * state the backend is unresponsive, e.g., no shutdown is possible.
+ * The frontend could send the backend a signal, but the "escape path"
+ * within the backend is unclear (PAM won't like simply longjmp()ing
+ * out of it).
+ */
+ virtual bool textMessage( const char *message, bool error ) = 0;
+
+ /**
+ * Prompt the user for data. Reply by calling handler->gplugReturnText().
+ * @param propmt the prompt to display. It may be null, in which case
+ * "Username"/"Password" should be shown and the replies should be tagged
+ * with the respective Is* flag.
+ * @param echo if true, a normal input widget can be used, otherwise one that
+ * visually obscures the user's input.
+ * @param nonBlocking if true, report whatever is already available,
+ * otherwise wait for user input.
+ */
+ virtual void textPrompt( const char *prompt, bool echo, bool nonBlocking ) = 0;
+
+ /**
+ * Request binary authentication data from the talker. Reply by calling
+ * handler->gplugReturnBinary().
+ * @param prompt prompt in pam_client format
+ * @param nonBlocking if true, report whatever is already available,
+ * otherwise wait for user input.
+ * @return always true for now
+ *
+ * TODO:
+ * @return if true, the prompt was handled by the talker, otherwise the
+ * handler has to use libpam_client to obtain the authentication data.
+ * In that state the talker still can abort the data fetch by
+ * gplugReturn()ing a null array. When the data was obtained, another
+ * binaryPrompt with a null prompt will be issued.
+ */
+ virtual bool binaryPrompt( const char *prompt, bool nonBlocking ) = 0;
+
+ /**
+ * This can either
+ * - Start a processing cycle. Will be called only when not running.
+ * - Restart authTok cycle - will be called while running and implies
+ * revive(). PAM is a bit too clever, so we need this.
+ * In any case the talker is running afterwards.
+ */
+ virtual void start() = 0;
+
+ /**
+ * Request to suspend the auth. Make sure that a second talker of any
+ * type will be able to operate while this one is suspended (no busy
+ * device nodes, etc.).
+ * Will be called only if running within Login context. (Actually it
+ * won't be called at all, but be prepared.)
+ */
+ virtual void suspend() = 0;
+
+ /**
+ * Request to resume the auth from the point it was suspended at.
+ * Will be called only when suspended.
+ */
+ virtual void resume() = 0;
+
+ /**
+ * The "login" button was pressed in the greeter.
+ * This might call gplugReturn* or gplugStart.
+ * Will be called only when running.
+ */
+ virtual void next() = 0;
+
+ /**
+ * Abort auth cycle. Note that this should _not_ clear out already
+ * entered auth tokens if they are still on the screen.
+ * Will be called only when running and stops it.
+ */
+ virtual void abort() = 0;
+
+ /**
+ * Indicate successful end of the current phase.
+ * This is more or less a request to disable editable widgets
+ * responsible for the that phase.
+ * There will be no further attempt to enter that phase until the
+ * widget is destroyed.
+ * Will be called only when running and stops it.
+ */
+ virtual void succeeded() = 0;
+
+ /**
+ * Indicate unsuccessful end of the current phase.
+ * This is mostly a request to disable all editable widgets.
+ * The widget will be treated as dead until revive() is called.
+ * Will be called only when running and stops it.
+ */
+ virtual void failed() = 0;
+
+ /**
+ * Prepare retrying the previously failed phase.
+ * This is mostly a request to re-enable all editable widgets failed()
+ * disabled previously, clear the probably incorrect authentication tokens
+ * and to set the input focus appropriately.
+ * Will be called only after failed() (possibly with clear() in between),
+ * or after presetEntity() with field -1.
+ */
+ virtual void revive() = 0;
+
+ /**
+ * Clear any edit widgets, particularily anything set by setUser.
+ * Will be called only when not running.
+ */
+ virtual void clear() = 0;
+
+ /**
+ * Obtain the TQLayoutItem containg the widget(s) to actually handle the
+ * conversation. See TQLayout and TQWidgetItem for possible implementations.
+ */
+ TQLayoutItem *getLayoutItem() const { return layoutItem; }
+
+protected:
+ KGreeterPluginHandler *handler;
+ TQLayoutItem *layoutItem;
+};
+
+struct KDE_EXPORT kgreeterplugin_info {
+ /**
+ * Human readable name of this plugin (should be a little more
+ * informative than just the libary name). Must be I18N_NOOP()ed.
+ */
+ const char *name;
+
+ /**
+ * The authentication method to use - the meaning is up to the backend,
+ * but will usually be related to the PAM service.
+ */
+ const char *method;
+
+ /**
+ * Capabilities.
+ */
+ enum {
+ /**
+ * All users exist on the local system permanently (will be listed
+ * by getpwent()); an entity corresponds to a UNIX user.
+ */
+ Local = 1,
+ /**
+ * The entities consist of multiple fields.
+ * PluginOptions/<plugin>.FocusField is used instead of FocusPasswd.
+ */
+ Fielded = 2,
+ /**
+ * An entity can be preset, the talker has a widget where a user can
+ * be selected explicitly. If the method is "classic", timed login
+ * is possible, too.
+ * This also means that setUser/gplugSetUser can be used and a
+ * userlist can be shown at all - provided Local is set as well.
+ */
+ Presettable = 4
+ };
+
+ /*
+ * Capability flags.
+ */
+ int flags;
+
+ /**
+ * Call after loading the plugin.
+ *
+ * @param method if non-empty and the plugin is unable to handle that
+ * method, return false. If the plugin has a constant method defined
+ * above, it can ignore this parameter.
+ * @param getConf can be used to obtain configuration items from the
+ * greeter; you have to pass it the @p ctx pointer.
+ * The only predefined key (in TDM) is "EchoMode", which is an int
+ * (in fact, KPasswordEdit::EchoModes).
+ * Other keys are obtained from the PluginOptions option; see tdmrc
+ * for details.
+ * If the key is unknown, dflt is returned.
+ * @param ctx context pointer for @p getConf
+ * @return if false, unload the plugin again (don't call done() first)
+ */
+ bool (*init)( const TQString &method,
+ TQVariant (*getConf)( void *ctx, const char *key,
+ const TQVariant &dflt ),
+ void *ctx );
+
+ /**
+ * Call before unloading the plugin.
+ * This pointer can be null.
+ */
+ void (*done)( void );
+
+ /**
+ * Factory method to create an instance of the plugin.
+ * Note that multiple instances can exist at one time, but only
+ * one of them is active at any moment (the others would be suspended
+ * or not running at all).
+ * @param handler the object offering the necessary callbacks
+ * @param parent parent widget
+ * @param predecessor the focus widget before the conversation widget
+ * @param fixedEntity see below
+ * @param func see below
+ * @param ctx see below
+ * @return an instance of this conversation plugin
+ *
+ * Valid combinations of Function and Context:
+ * - Authenticate:Login - init
+ * - Authenticate:Shutdown - init, for now "root" is passed as fixedEntitiy
+ * and it is not supposed to be displayed. Plugins with Local not set
+ * might have to conjure something up to make getEntity() return a
+ * canonical entitiy. FIXME: don't restrict shutdown to root.
+ * - AuthChAuthTok:Login, AuthChAuthTok:Shutdown - cont/cont,
+ * only relevant for classic method (as it is relevant only for password-
+ * less logins, which always use classic). The login should not be shown -
+ * it is known to the user already; the backend won't ask for it, either.
+ * - ChAuthTok:Login & ChAuthTok:Shutdown - cont
+ * - Authenticate:Unlock & Authenticate:ExUnlock - init,
+ * AuthChAuthTok:ChangeTok & AuthChAuthTok:ExChangeTok - init/cont,
+ * display fixedEntity as labels. The backend does not ask for the UNIX
+ * login, as it already knows it - but it will ask for all components of
+ * the entity if it is no UNIX login.
+ *
+ * "init" means that the plugin is supposed to call gplugStart, "cont"
+ * that the backend is already in a cycle of the method the plugin was
+ * initialized with.
+ */
+ KGreeterPlugin *(*create)( KGreeterPluginHandler *handler,
+ KdmThemer *themer,
+ TQWidget *parent, TQWidget *predecessor,
+ const TQString &fixedEntity,
+ KGreeterPlugin::Function func,
+ KGreeterPlugin::Context ctx );
+};
+
+#endif
diff --git a/tdmlib/tdmtsak.cpp b/tdmlib/tdmtsak.cpp
new file mode 100644
index 000000000..18acd05d2
--- /dev/null
+++ b/tdmlib/tdmtsak.cpp
@@ -0,0 +1,180 @@
+/*
+ This file is part of the TDE project
+ Copyright (C) 2011 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "tdmtsak.h"
+
+#include <tqstringlist.h>
+
+#define FIFO_FILE "/tmp/ksocket-global/tsak"
+
+TQString exec(const char * cmd) {
+ FILE* pipe = popen(cmd, "r");
+ if (!pipe) return "ERROR";
+ char buffer[128];
+ TQString result = "";
+ while(!feof(pipe)) {
+ if(fgets(buffer, 128, pipe) != NULL)
+ result += buffer;
+ }
+ pclose(pipe);
+ return result;
+}
+
+bool is_vt_local() {
+ const char * currentDisplay;
+ currentDisplay = getenv ("DISPLAY");
+ if (currentDisplay == NULL) {
+ return false;
+ }
+ else {
+ TQString cvtName = "";
+ TQString output = exec("tdmctl list");
+ TQStringList sessionList = TQStringList::split('\t', output, false);
+ // See if the current session is local
+ for ( TQStringList::Iterator it = sessionList.begin(); it != sessionList.end(); ++it ) {
+ TQStringList sessionInfoList = TQStringList::split(',', *it, true);
+ if ((*(sessionInfoList.at(0))).startsWith(":")) {
+ if (TQString(currentDisplay).startsWith(*(sessionInfoList.at(0)))) {
+ return true;
+ }
+ }
+ }
+ // Not local
+ return false;
+ }
+}
+
+bool is_vt_active() {
+ const char * currentDisplay;
+ currentDisplay = getenv ("DISPLAY");
+ if (currentDisplay == NULL) {
+ return true;
+ }
+ else {
+ TQString cvtName = "";
+ TQString output = exec("tdmctl list");
+ TQString curConsole = exec("fgconsole");
+ bool intFound;
+ int curConsoleNum = curConsole.toInt(&intFound);
+ if (intFound == false) {
+ return true;
+ }
+ curConsole = TQString("vt%1").arg(curConsoleNum);;
+ TQStringList sessionList = TQStringList::split('\t', output, false);
+ for ( TQStringList::Iterator it = sessionList.begin(); it != sessionList.end(); ++it ) {
+ TQStringList sessionInfoList = TQStringList::split(',', *it, true);
+ if ((*(sessionInfoList.at(0))).startsWith(":")) {
+ if ((*(sessionInfoList.at(1))) == TQString(curConsole)) {
+ cvtName = (*(sessionInfoList.at(0)));
+ }
+ }
+ }
+ if (cvtName != "") {
+ if (TQString(currentDisplay).startsWith(cvtName)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ // See if the current session is local
+ // If it is, then the VT is not currently active and the SAK must be requested later when it is active
+ for ( TQStringList::Iterator it = sessionList.begin(); it != sessionList.end(); ++it ) {
+ TQStringList sessionInfoList = TQStringList::split(',', *it, true);
+ if ((*(sessionInfoList.at(0))).startsWith(":")) {
+ if (TQString(currentDisplay).startsWith(*(sessionInfoList.at(0)))) {
+ return false;
+ }
+ }
+ }
+ // Hmm, not local
+ // Do not reject the SAK
+ return true;
+ }
+ }
+}
+
+int main (int argc, char *argv[])
+{
+ int mPipe_fd;
+ char readbuf[128];
+ int numread;
+
+ int verifier_result = tde_sak_verify_calling_process();
+
+ bool isdm = false;
+ if (argc == 2) {
+ if (strcmp(argv[1], "dm") == 0) {
+ isdm = true;
+ }
+ }
+
+ if (!isdm) {
+ // Verify that the session is local
+ // Remote sessions cannot press the SAK for obvious reasons
+ if (!is_vt_local()) {
+ return 6; // SAK not available
+ }
+ }
+
+ if (verifier_result == 0) {
+ // OK, the calling process is authorized to retrieve SAK data
+ // First, flush the buffer
+ mPipe_fd = open(FIFO_FILE, O_RDONLY | O_NONBLOCK);
+ numread = 1;
+ while (numread > 0) {
+ numread = read(mPipe_fd, readbuf, 6);
+ }
+ close(mPipe_fd);
+ // Now wait for SAK press
+ mPipe_fd = open(FIFO_FILE, O_RDONLY);
+ while (mPipe_fd > -1) {
+ numread = read(mPipe_fd, readbuf, 6);
+ readbuf[numread] = 0;
+ readbuf[127] = 0;
+ if (strcmp(readbuf, "SAK\n\r") == 0) {
+ close(mPipe_fd);
+ if (is_vt_active()) {
+ return 0;
+ }
+ else {
+ usleep(100);
+ // Flush the buffer
+ mPipe_fd = open(FIFO_FILE, O_RDONLY | O_NONBLOCK);
+ numread = 1;
+ while (numread > 0) {
+ numread = read(mPipe_fd, readbuf, 6);
+ }
+ close(mPipe_fd);
+ mPipe_fd = open(FIFO_FILE, O_RDONLY);
+ }
+ }
+ else {
+ usleep(100);
+ }
+ }
+ close(mPipe_fd);
+ return 6;
+ }
+ else {
+ return verifier_result;
+ }
+} \ No newline at end of file
diff --git a/tdmlib/tdmtsak.h b/tdmlib/tdmtsak.h
new file mode 100644
index 000000000..1987a8218
--- /dev/null
+++ b/tdmlib/tdmtsak.h
@@ -0,0 +1,144 @@
+/*
+ This file is part of the TDE project
+ Copyright (C) 2011 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <termios.h>
+#include <signal.h>
+
+#include <tqstring.h>
+
+#include "config.h"
+
+// #define DEBUG
+
+inline int tde_sak_verify_calling_process()
+{
+ bool authorized = false;
+
+ // Root always has access to everything...
+ if (getuid() == 0) {
+ return 0;
+ }
+
+ pid_t parentproc = getppid();
+#ifdef DEBUG
+ printf("Parent pid is: %d\n\r", parentproc);
+#endif
+
+ char parentexecutable[8192];
+ TQString procparent = TQString("/proc/%1/exe").arg(parentproc);
+ int chars = readlink(procparent.ascii(), parentexecutable, sizeof(parentexecutable));
+ parentexecutable[chars] = 0;
+ parentexecutable[8191] = 0;
+ procparent = parentexecutable;
+#ifdef DEBUG
+ printf("Parent executable name and full path is: %s\n\r", procparent.ascii());
+#endif
+
+ TQString tdeBinaryPath = TQString(KDE_BINDIR "/");
+#ifdef DEBUG
+ printf("The TDE binary path is: %s\n\r", tdeBinaryPath.ascii());
+#endif
+
+ if (!procparent.startsWith(tdeBinaryPath)) {
+ printf("Unauthorized path detected in calling process\n\r");
+ return 2;
+ }
+ else {
+ procparent = procparent.mid(tdeBinaryPath.length());
+#ifdef DEBUG
+ printf("Parent executable name is: %s\n\r", procparent.ascii());
+#endif
+ if ((procparent == "kdesktop") || (procparent == "kdesktop_lock") || (procparent == "tdm")) {
+ authorized = true;
+ }
+ else if (procparent == "tdeinit") {
+ printf("tdeinit detected\n\r");
+ // A bit more digging is needed to see if this is an authorized process or not
+ // Get the tdeinit command
+ char tdeinitcmdline[8192];
+ FILE *fp = fopen(TQString("/proc/%1/cmdline").arg(parentproc).ascii(),"r");
+ if (fp != NULL) {
+ if (fgets (tdeinitcmdline, 8192, fp) != NULL)
+ fclose (fp);
+ }
+ tdeinitcmdline[8191] = 0;
+ TQString tdeinitCommand = tdeinitcmdline;
+
+ // Also get the environment, specifically the path
+ TQString tdeinitEnvironment;
+ char tdeinitenviron[8192];
+ fp = fopen(TQString("/proc/%1/environ").arg(parentproc).ascii(),"r");
+ if (fp != NULL) {
+ int c;
+ int pos = 0;
+ do {
+ c = fgetc(fp);
+ tdeinitenviron[pos] = c;
+ pos++;
+ if (c == 0) {
+ TQString curEnvLine = tdeinitenviron;
+ if (curEnvLine.startsWith("PATH=")) {
+ tdeinitEnvironment = curEnvLine.mid(5);
+ }
+ pos = 0;
+ }
+ } while ((c != EOF) && (pos < 8192));
+ fclose (fp);
+ }
+ tdeinitenviron[8191] = 0;
+
+#ifdef DEBUG
+ printf("Called executable name is: %s\n\r", tdeinitCommand.ascii());
+ printf("Environment is: %s\n\r", tdeinitEnvironment.ascii());
+#endif
+
+ if ((tdeinitCommand == "kdesktop [tdeinit]") && (tdeinitEnvironment.startsWith(KDE_BINDIR))) {
+ authorized = true;
+ }
+ else {
+ return 4;
+ }
+ }
+ else {
+ printf("Unauthorized calling process detected\n\r");
+ return 3;
+ }
+
+ if (authorized == true) {
+ return 0;
+ }
+ }
+
+ return 5;
+}
+
+#undef DEBUG \ No newline at end of file