summaryrefslogtreecommitdiffstats
path: root/tdmlib/kgreet_pam.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tdmlib/kgreet_pam.cpp')
-rw-r--r--tdmlib/kgreet_pam.cpp675
1 files changed, 675 insertions, 0 deletions
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"