From 0f05883544c6b698ce76b524da4d13d77529eb31 Mon Sep 17 00:00:00 2001
From: tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>
Date: Thu, 22 Sep 2011 17:53:08 +0000
Subject: Add remote control socket to kdm

git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1255013 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
---
 kdesktop/lock/lockprocess.cc |   1 +
 kdm/kfrontend/kgreeter.cpp   | 100 +++++++++++++++++++++++++++++++++++++++++++
 kdm/kfrontend/kgreeter.h     |   8 ++++
 kdm/kfrontend/kgverify.cpp   |   7 +++
 kdm/kfrontend/kgverify.h     |   1 +
 kdm/kfrontend/sakdlg.cc      |  97 ++++++++++++++++++++++++++++++++++++++++-
 kdm/kfrontend/sakdlg.h       |   6 +++
 kdmlib/kgreet_classic.cpp    |   7 +++
 kdmlib/kgreet_classic.h      |   1 +
 kdmlib/kgreet_pam.cpp        |   7 +++
 kdmlib/kgreet_pam.h          |   1 +
 kdmlib/kgreet_winbind.cpp    |   7 +++
 kdmlib/kgreet_winbind.h      |   1 +
 kdmlib/kgreeterplugin.h      |   6 +++
 14 files changed, 249 insertions(+), 1 deletion(-)

diff --git a/kdesktop/lock/lockprocess.cc b/kdesktop/lock/lockprocess.cc
index 93fe4d9ae..6347f00b5 100644
--- a/kdesktop/lock/lockprocess.cc
+++ b/kdesktop/lock/lockprocess.cc
@@ -605,6 +605,7 @@ bool LockProcess::dontLock()
 //---------------------------------------------------------------------------
 void LockProcess::quitSaver()
 {
+    DISABLE_CONTINUOUS_LOCKDLG_DISPLAY
     if (closeCurrentWindow()) {
         TQTimer::singleShot( 0, this, SLOT(quitSaver()) );
         return;
diff --git a/kdm/kfrontend/kgreeter.cpp b/kdm/kfrontend/kgreeter.cpp
index fd4f07d96..0a476d2b9 100644
--- a/kdm/kfrontend/kgreeter.cpp
+++ b/kdm/kfrontend/kgreeter.cpp
@@ -71,8 +71,25 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 #include <utmp.h>
 #include <utmpx.h>
 
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.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 <X11/Xlib.h>
 
+#define FIFO_DIR "/tmp/ksocket-global/kdm"
+#define FIFO_FILE "/tmp/ksocket-global/kdm/kdmctl-%1"
+#define FIFO_SAK_FILE "/tmp/ksocket-global/kdm/kdmctl-sak-%1"
+
 class UserListView : public KListView {
   public:
         UserListView( bool _them, TQWidget *parent = 0, const char *name = 0 )
@@ -161,6 +178,8 @@ KGreeter::KGreeter( bool framed )
   , prevValid( true )
   , needLoad( false )
   , themed( framed )
+  , mPipe_fd( -1 )
+  , closingDown( false )
 {
 	stsFile = new KSimpleConfig( _stsFile );
 	stsFile->setGroup( "PrevUser" );
@@ -185,16 +204,95 @@ KGreeter::KGreeter( bool framed )
 		curPlugin = 0;
 		pluginList = KGVerify::init( _pluginsLogin );
 	}
+
+	TQTimer::singleShot( 0, this, TQT_SLOT(handleInputPipe()) );
 }
 
 KGreeter::~KGreeter()
 {
+	if (mPipe_fd != -1) {
+		closingDown = true;
+		::close(mPipe_fd);
+		::unlink(mPipeFilename.ascii());
+	}
 	hide();
 	delete userList;
 	delete verify;
 	delete stsFile;
 }
 
+void KGreeter::handleInputPipe(void) {
+	if (closingDown) {
+		::unlink(mPipeFilename.ascii());
+		return;
+	}
+
+	if (isShown() == false) {
+		TQTimer::singleShot( 100, this, TQT_SLOT(handleInputPipe()) );
+		return;
+	}
+
+	char readbuf[2048];
+	int displayNumber;
+	TQString currentDisplay;
+	currentDisplay = TQString(getenv("DISPLAY"));
+	currentDisplay = currentDisplay.replace(":", "");
+	displayNumber = currentDisplay.toInt();
+	mPipeFilename = TQString(FIFO_FILE).tqarg(displayNumber);
+	::unlink((TQString(FIFO_SAK_FILE).tqarg(displayNumber)).ascii());
+
+	/* Create the FIFOs if they do not exist */
+	umask(0);
+	struct stat buffer;
+	int status;
+	status = stat(FIFO_DIR, &buffer);
+	if (status == 0) {
+		int file_mode = ((buffer.st_mode & S_IRWXU) >> 6) * 100;
+		file_mode = file_mode + ((buffer.st_mode & S_IRWXG) >> 3) * 10;
+		file_mode = file_mode + ((buffer.st_mode & S_IRWXO) >> 0) * 1;
+		if ((file_mode != 600) || (buffer.st_uid != 0) || (buffer.st_gid != 0)) {
+			::unlink(mPipeFilename.ascii());
+			printf("[WARNING] Possible security breach!  Please check permissions on " FIFO_DIR " (must be 600 and owned by root/root, got %d %d/%d).  Not listening for login credentials on remote control socket.\n", file_mode, buffer.st_uid, buffer.st_gid); fflush(stdout);
+			return;
+		}
+	}
+	mkdir(FIFO_DIR,0600);
+	mknod(mPipeFilename.ascii(), S_IFIFO|0600, 0);
+	chmod(mPipeFilename.ascii(), 0600);
+
+	mPipe_fd = ::open(mPipeFilename.ascii(), O_RDONLY | O_NONBLOCK);
+	int numread;
+	TQString inputcommand = "";
+	while ((!inputcommand.contains('\n')) && (!closingDown)) {
+		numread = ::read(mPipe_fd, readbuf, 2048);
+		readbuf[numread] = 0;
+		readbuf[2047] = 0;
+		inputcommand += readbuf;
+		tqApp->processEvents();
+	}
+	if (closingDown) {
+		::unlink(mPipeFilename.ascii());
+		return;
+	}
+	inputcommand = inputcommand.replace('\n', "");
+	TQStringList commandList = TQStringList::split('\t', inputcommand, false);
+	if ((*(commandList.at(0))) == "LOGIN") {
+		if (verify) {
+			verify->setUser( (*(commandList.at(1))) );
+			verify->setPassword( (*(commandList.at(2))) );
+			accept();
+		}
+	}
+	if (!closingDown) {
+		TQTimer::singleShot( 0, this, TQT_SLOT(handleInputPipe()) );
+		::close(mPipe_fd);
+		::unlink(mPipeFilename.ascii());
+	}
+	else {
+		::unlink(mPipeFilename.ascii());
+	}
+}
+
 void KGreeter::readFacesList()
 {
     FILE *f = fopen( TQFile::encodeName( _faceDir + "/.randomlist" ), "rt" );
@@ -742,6 +840,7 @@ KGreeter::verifyOk()
 		GSendStr( "default" );
 	}
 	GSendInt( G_Ready );
+	closingDown = true;
 	done( ex_exit );
 }
 
@@ -1165,6 +1264,7 @@ KThemedGreeter::slotAskAdminPassword()
   if (k.exec()) {
 	GSendInt(G_Ready);
 	hide();
+	closingDown = true;
 	done(ex_exit);
    }
 }
diff --git a/kdm/kfrontend/kgreeter.h b/kdm/kfrontend/kgreeter.h
index 8675f052a..b481d7bad 100644
--- a/kdm/kfrontend/kgreeter.h
+++ b/kdm/kfrontend/kgreeter.h
@@ -71,6 +71,7 @@ class KGreeter : public KGDialog, public KGVerifyHandler {
 	void slotUserClicked( TQListViewItem * );
 	void slotSessionSelected( int );
 	void slotUserEntered();
+	void handleInputPipe();
 
   public:
 	TQString curUser, dName;
@@ -104,6 +105,13 @@ class KGreeter : public KGDialog, public KGVerifyHandler {
   private slots:
 	void slotLoadPrevWM();
 
+  private:
+	int mPipe_fd;
+	TQString mPipeFilename;
+
+  protected:
+	bool closingDown;
+
   public: // from KGVerifyHandler
 	virtual void verifyPluginChanged( int id );
 	virtual void verifyClear();
diff --git a/kdm/kfrontend/kgverify.cpp b/kdm/kfrontend/kgverify.cpp
index 337b45644..b7f57a5bd 100644
--- a/kdm/kfrontend/kgverify.cpp
+++ b/kdm/kfrontend/kgverify.cpp
@@ -268,6 +268,13 @@ KGVerify::setUser( const TQString &user )
 	gplugActivity();
 }
 
+void
+KGVerify::setPassword( const TQString &pass )
+{
+	greet->setPassword( pass );
+	gplugActivity();
+}
+
 void
 KGVerify::start()
 {
diff --git a/kdm/kfrontend/kgverify.h b/kdm/kfrontend/kgverify.h
index 0d76b5e7f..41451d800 100644
--- a/kdm/kfrontend/kgverify.h
+++ b/kdm/kfrontend/kgverify.h
@@ -100,6 +100,7 @@ class KGVerify : public TQObject, public KGreeterPluginHandler {
 	void presetEntity( const TQString &entity, int field );
 	TQString getEntity() const;
 	void setUser( const TQString &user );
+	void setPassword( const TQString &pass );
 	/* virtual */ void selectPlugin( int id );
 	bool entitiesLocal() const;
 	bool entitiesFielded() const;
diff --git a/kdm/kfrontend/sakdlg.cc b/kdm/kfrontend/sakdlg.cc
index 2db602409..b19e18ed0 100644
--- a/kdm/kfrontend/sakdlg.cc
+++ b/kdm/kfrontend/sakdlg.cc
@@ -38,7 +38,9 @@
 #include <tqlistview.h>
 #include <tqheader.h>
 #include <tqcheckbox.h>
+#include <tqtimer.h>
 
+#include <fcntl.h>
 #include <ctype.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -52,12 +54,29 @@
 #include <X11/Xatom.h>
 #include <fixx11h.h>
 
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.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 "kfdialog.h"
 
 #ifndef AF_LOCAL
 # define AF_LOCAL	AF_UNIX
 #endif
 
+#define FIFO_DIR "/tmp/ksocket-global/kdm"
+#define FIFO_FILE "/tmp/ksocket-global/kdm/kdmctl-%1"
+#define FIFO_SAK_FILE "/tmp/ksocket-global/kdm/kdmctl-sak-%1"
+
 bool trinity_desktop_lock_use_system_modal_dialogs = TRUE;
 extern bool trinity_desktop_lock_use_sak;
 
@@ -67,7 +86,7 @@ extern bool trinity_desktop_lock_use_sak;
 //
 SAKDlg::SAKDlg(TQWidget *parent)
     : TQDialog(parent, "information dialog", true, (trinity_desktop_lock_use_system_modal_dialogs?((WFlags)WStyle_StaysOnTop):((WFlags)WX11BypassWM))),
-      mUnlockingFailed(false)
+      mUnlockingFailed(false), mPipe_fd(-1), closingDown(false)
 {
     if (trinity_desktop_lock_use_system_modal_dialogs) {
         // Signal that we do not want any window controls to be shown at all
@@ -109,21 +128,97 @@ SAKDlg::SAKDlg(TQWidget *parent)
     *mSAKProcess << "kdmtsak" << "dm";
     connect(mSAKProcess, TQT_SIGNAL(processExited(KProcess*)), this, TQT_SLOT(slotSAKProcessExited()));
     mSAKProcess->start();
+
+    TQTimer::singleShot( 0, this, TQT_SLOT(handleInputPipe()) );
 }
 
 void SAKDlg::slotSAKProcessExited()
 {
     int retcode = mSAKProcess->exitStatus();
     if (retcode != 0) trinity_desktop_lock_use_sak = false;
+    closingDown = true;
     hide();
 }
 
+void SAKDlg::handleInputPipe(void) {
+	if (closingDown) {
+		::unlink(mPipeFilename.ascii());
+		return;
+	}
+
+	if (isShown() == false) {
+		TQTimer::singleShot( 100, this, TQT_SLOT(handleInputPipe()) );
+		return;
+	}
+
+	char readbuf[2048];
+	int displayNumber;
+	TQString currentDisplay;
+	currentDisplay = TQString(getenv("DISPLAY"));
+	currentDisplay = currentDisplay.replace(":", "");
+	displayNumber = currentDisplay.toInt();
+	mPipeFilename = TQString(FIFO_SAK_FILE).tqarg(displayNumber);
+	::unlink((TQString(FIFO_FILE).tqarg(displayNumber)).ascii());
+
+	/* Create the FIFOs if they do not exist */
+	umask(0);
+	struct stat buffer;
+	int status;
+	status = stat(FIFO_DIR, &buffer);
+	if (status == 0) {
+		int file_mode = ((buffer.st_mode & S_IRWXU) >> 6) * 100;
+		file_mode = file_mode + ((buffer.st_mode & S_IRWXG) >> 3) * 10;
+		file_mode = file_mode + ((buffer.st_mode & S_IRWXO) >> 0) * 1;
+		if ((file_mode != 600) || (buffer.st_uid != 0) || (buffer.st_gid != 0)) {
+			::unlink(mPipeFilename.ascii());
+			printf("[WARNING] Possible security breach!  Please check permissions on " FIFO_DIR " (must be 600 and owned by root/root, got %d %d/%d).  Not listening for login credentials on remote control socket.\n", file_mode, buffer.st_uid, buffer.st_gid); fflush(stdout);
+			return;
+		}
+	}
+	mkdir(FIFO_DIR,0600);
+	mknod(mPipeFilename.ascii(), S_IFIFO|0600, 0);
+	chmod(mPipeFilename.ascii(), 0600);
+
+	mPipe_fd = ::open(mPipeFilename.ascii(), O_RDONLY | O_NONBLOCK);
+	int numread;
+	TQString inputcommand = "";
+	while ((!inputcommand.contains('\n')) && (!closingDown)) {
+		numread = ::read(mPipe_fd, readbuf, 2048);
+		readbuf[numread] = 0;
+		readbuf[2047] = 0;
+		inputcommand += readbuf;
+		tqApp->processEvents();
+	}
+	if (closingDown) {
+		::unlink(mPipeFilename.ascii());
+		return;
+	}
+	inputcommand = inputcommand.replace('\n', "");
+	TQStringList commandList = TQStringList::split('\t', inputcommand, false);
+	if ((*(commandList.at(0))) == "CLOSE") {
+		mSAKProcess->kill();
+	}
+	if (!closingDown) {
+		TQTimer::singleShot( 0, this, TQT_SLOT(handleInputPipe()) );
+		::close(mPipe_fd);
+		::unlink(mPipeFilename.ascii());
+	}
+	else {
+		::unlink(mPipeFilename.ascii());
+	}
+}
+
 SAKDlg::~SAKDlg()
 {
     if ((mSAKProcess) && (mSAKProcess->isRunning())) {
         mSAKProcess->kill(SIGTERM);
         delete mSAKProcess;
     }
+    if (mPipe_fd != -1) {
+        closingDown = true;
+        ::close(mPipe_fd);
+        ::unlink(mPipeFilename.ascii());
+    }
     hide();
 }
 
diff --git a/kdm/kfrontend/sakdlg.h b/kdm/kfrontend/sakdlg.h
index d94322f79..a930707b1 100644
--- a/kdm/kfrontend/sakdlg.h
+++ b/kdm/kfrontend/sakdlg.h
@@ -38,6 +38,7 @@ public:
 
 private slots:
     void slotSAKProcessExited();
+    void handleInputPipe();
 
 protected slots:
     virtual void reject();
@@ -52,6 +53,11 @@ private:
     TQStringList::iterator currLayout;
     int         sPid, sFd;
     KProcess*   mSAKProcess;
+    int         mPipe_fd;
+    TQString mPipeFilename;
+
+protected:
+    bool closingDown;
 };
 
 #endif
diff --git a/kdmlib/kgreet_classic.cpp b/kdmlib/kgreet_classic.cpp
index 50f959596..8117429a8 100644
--- a/kdmlib/kgreet_classic.cpp
+++ b/kdmlib/kgreet_classic.cpp
@@ -217,6 +217,13 @@ KClassicGreeter::setUser( const TQString &user )
 	passwdEdit->selectAll();
 }
 
+void // virtual
+KClassicGreeter::setPassword( const TQString &pass )
+{
+	passwdEdit->erase();
+	passwdEdit->insert( pass );
+}
+
 void // virtual
 KClassicGreeter::setEnabled( bool enable )
 {
diff --git a/kdmlib/kgreet_classic.h b/kdmlib/kgreet_classic.h
index 1467f3b99..07bf35957 100644
--- a/kdmlib/kgreet_classic.h
+++ b/kdmlib/kgreet_classic.h
@@ -50,6 +50,7 @@ class KClassicGreeter : public TQObject, public KGreeterPlugin {
 	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 );
diff --git a/kdmlib/kgreet_pam.cpp b/kdmlib/kgreet_pam.cpp
index 5a9c2cbe8..19c797b44 100644
--- a/kdmlib/kgreet_pam.cpp
+++ b/kdmlib/kgreet_pam.cpp
@@ -263,6 +263,13 @@ KPamGreeter::setUser( const TQString &user )
         }
 }
 
+void // virtual
+KPamGreeter::setPassword( const TQString &pass )
+{
+	authEdit[0]->erase();
+	authEdit[0]->insert( pass );
+}
+
 void // virtual
 KPamGreeter::setEnabled(bool enable)
 {
diff --git a/kdmlib/kgreet_pam.h b/kdmlib/kgreet_pam.h
index 8691b3350..0be454674 100644
--- a/kdmlib/kgreet_pam.h
+++ b/kdmlib/kgreet_pam.h
@@ -50,6 +50,7 @@ class KPamGreeter : public TQObject, public KGreeterPlugin {
 	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 );
diff --git a/kdmlib/kgreet_winbind.cpp b/kdmlib/kgreet_winbind.cpp
index ae55a4b0f..8ae12144b 100644
--- a/kdmlib/kgreet_winbind.cpp
+++ b/kdmlib/kgreet_winbind.cpp
@@ -297,6 +297,13 @@ KWinbindGreeter::setUser( const TQString &user )
 	passwdEdit->selectAll();
 }
 
+void // virtual
+KWinbindGreeter::setPassword( const TQString &pass )
+{
+	passwdEdit->erase();
+	passwdEdit->insert( pass );
+}
+
 void // virtual
 KWinbindGreeter::setEnabled( bool enable )
 {
diff --git a/kdmlib/kgreet_winbind.h b/kdmlib/kgreet_winbind.h
index c57dc64fd..055296e34 100644
--- a/kdmlib/kgreet_winbind.h
+++ b/kdmlib/kgreet_winbind.h
@@ -54,6 +54,7 @@ class KWinbindGreeter : public TQObject, public KGreeterPlugin {
 	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 );
diff --git a/kdmlib/kgreeterplugin.h b/kdmlib/kgreeterplugin.h
index 44799a622..61d9b519a 100644
--- a/kdmlib/kgreeterplugin.h
+++ b/kdmlib/kgreeterplugin.h
@@ -151,6 +151,12 @@ public:
      */
     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.
-- 
cgit v1.2.3

