summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2011-09-22 19:47:58 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2011-09-22 19:47:58 +0000
commitcbe66c290b343f54a6741cb420bac17225d51285 (patch)
tree3a6579c5e9dcfcbfbd90c39d734b6b8bf65601a4
parent1e59465c8abdce055fd9cd3b66ea4547c88c688d (diff)
downloadsmartcardauth-cbe66c290b343f54a6741cb420bac17225d51285.tar.gz
smartcardauth-cbe66c290b343f54a6741cb420bac17225d51285.zip
Make smartauthmon use new kdm control sockets
This stabilizes login with smart cards on finicky Xorg servers git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/smartcardauth@1255016 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
-rwxr-xr-xMakefile1
-rwxr-xr-xsrc/smartauth_displayfinder30
-rw-r--r--src/smartauthmon.cpp183
3 files changed, 127 insertions, 87 deletions
diff --git a/Makefile b/Makefile
index 2301ea0..9259b90 100755
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,6 @@ install:
mkdir -p $(DESTDIR)/usr
cp -Rp src/ckpasswd usr/bin/smartauthckpasswd
cp -Rp src/smartauthmon usr/bin/smartauthmon
- cp -Rp src/smartauth_displayfinder usr/bin/smartauth_displayfinder
cp -Rp usr/* $(DESTDIR)/usr/
mkdir -p $(DESTDIR)/etc
diff --git a/src/smartauth_displayfinder b/src/smartauth_displayfinder
deleted file mode 100755
index cbe9dec..0000000
--- a/src/smartauth_displayfinder
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-
-mkdir -p /tmp/smartauthmon/
-ls /var/run/xdmctl > /tmp/smartauthmon/originalxdm
-
-# Set loop separator to end of line
-BAKIFS=$IFS
-IFS=$(echo -en "\n\b")
-exec 3<&0
-exec 0</tmp/smartauthmon/originalxdm
-newdisplayfound=0
-newdisplay=-1
-while read -r line
-do
- # use $line variable to process lines
- line=$(echo $line | grep 'xdmctl-:' | sed -e 's/xdmctl-://')
- if [ "`expr $line - $line 2>/dev/null`" == "0" ]; then
- echo "Found active display on $line"
- if [[ $newdisplayfound -eq 0 ]]; then
- tempnewdisplay=$((newdisplay + 1))
- if [[ $line -eq $tempnewdisplay ]]; then
- echo "Sequential display $line found after display $newdisplay..."
- newdisplay=$line
- fi
- fi
- fi
-done
-exec 0<&3
-newdisplay=$(($newdisplay + 1))
-rm -rf /tmp/smartauthmon/
diff --git a/src/smartauthmon.cpp b/src/smartauthmon.cpp
index 3c5dd98..88bccee 100644
--- a/src/smartauthmon.cpp
+++ b/src/smartauthmon.cpp
@@ -31,6 +31,7 @@
#include <signal.h>
#include <ftw.h>
+#include <tqdir.h>
#include <tqstring.h>
#include <tqstringlist.h>
@@ -46,7 +47,9 @@
// Some internal constants
#define CREATE_LIFE_CYCLE "01"
-#define tqarg arg
+#define KDM_CONTROL_FIFO_DIR "/tmp/ksocket-global/kdm"
+#define KDM_CONTROL_FIFO_FILE "/tmp/ksocket-global/kdm/kdmctl-%1"
+#define KDM_CONTROL_FIFO_SAK_FILE "/tmp/ksocket-global/kdm/kdmctl-sak-%1"
// In ckpass.o
extern "C" {
@@ -69,6 +72,17 @@ static TQString darray[MAXIMUM_VTS];
static FILE* opensc_explorer_file;
+struct sigaction usr_action;
+sigset_t block_mask;
+
+void handle_sigpipe(int sig)
+{
+ int uidnum;
+ if (sig == SIGPIPE) {
+ printf("Got SIGPIPE!\n\r"); fflush(stdout);
+ }
+}
+
TQString readfile(const char * filename) {
FILE *fp;
long len;
@@ -90,6 +104,20 @@ TQString readfile(const char * filename) {
return contents;
}
+int writefile(const char * filename, TQString contents) {
+ int fp;
+ long len;
+ char *buf;
+ fp=open(filename, O_WRONLY | O_NONBLOCK);
+ if (fp < 0) {
+ printf("[WARNING] Unable to open file %s for writing\n\r", filename); fflush(stdout);
+ return -1;
+ }
+ int retcode = write(fp, contents.ascii(), contents.length());
+ close(fp);
+ return retcode;
+}
+
TQString exec(const char * cmd) {
TQString bashcommand = cmd;
bashcommand = bashcommand.replace("\"", "\\\"");
@@ -278,6 +306,13 @@ int main (int argc, char *argv[])
printf("[DEBUG 390.0] Starting up\n\r"); fflush(stdout);
+ // Initialize signal handlers
+ sigfillset(&block_mask);
+ usr_action.sa_handler = handle_sigpipe;
+ usr_action.sa_mask = block_mask;
+ usr_action.sa_flags = 0;
+ sigaction(SIGPIPE, &usr_action, NULL);
+
// Create the secure directory and lock it down
secure_directory = SECURE_DIRECTORY_PATH;
rmrf(secure_directory.ascii());
@@ -565,68 +600,104 @@ int main (int argc, char *argv[])
if (foundsession == 0) {
printf("[DEBUG 400.c] Existing session not found, starting new...\n\r"); fflush(stdout);
- // Make sure that this is not display :0 (default login screen).
- // If it is, execute login. If not, create new session, then execute login
- int usebasedisplay=0;
- if (noactivesessions == 1) {
- newdisplay = exec("ls /var/run/xdmctl/ | grep 'xdmctl-:0'");
- printf("[DEBUG 400.d] %s\n\r", newdisplay.ascii()); fflush(stdout);
- if (newdisplay != "") {
- usebasedisplay=1;
+ // Get directory listing of kdm control socket directory
+ // Also start new X server if needed
+ bool have_valid_display = false;
+ bool display_has_sak = false;
+ bool writeerror = false;
+ newdisplayint = MAXIMUM_VTS+1;
+ while (have_valid_display == false) {
+ display_has_sak = false;
+ writeerror = false;
+ TQDir dr(KDM_CONTROL_FIFO_DIR);
+ dr.setFilter( TQDir::System );
+ dr.setSorting( TQDir::Name );
+ const TQFileInfoList *list = dr.entryInfoList();
+ if (list) {
+ TQFileInfoListIterator it( *list );
+ TQFileInfo *fi;
+ while ( (fi = it.current()) != NULL ) {
+ bool isint;
+ int tempdisplayint;
+ TQString tempdisplaystr;
+ tempdisplaystr = fi->fileName();
+ printf( "%s\n", fi->fileName().latin1() ); fflush(stdout);
+ if (fi->fileName().tqcontains("kdmctl-sak-")) {
+ tempdisplaystr = tempdisplaystr.replace("kdmctl-sak-", "");
+ tempdisplayint = tempdisplaystr.toInt(&isint);
+ if (isint) {
+ if (tempdisplayint < newdisplayint) {
+ newdisplayint = tempdisplayint;
+ display_has_sak = true;
+ }
+ }
+ }
+ else if (fi->fileName().tqcontains("kdmctl-")) {
+ tempdisplaystr = tempdisplaystr.replace("kdmctl-", "");
+ tempdisplayint = tempdisplaystr.toInt(&isint);
+ if (isint) {
+ if (tempdisplayint < newdisplayint) {
+ newdisplayint = tempdisplayint;
+ display_has_sak = false;
+ }
+ }
+ }
+ ++it;
+ }
+ if (display_has_sak) {
+ if (writefile(TQString(KDM_CONTROL_FIFO_SAK_FILE).tqarg(newdisplayint), "CLOSE\n") < 0) {
+ // Uh oh, something failed...
+ printf("Unable to write to KDM control socket %s\n\r", (TQString(KDM_CONTROL_FIFO_SAK_FILE).tqarg(newdisplayint)).ascii()); fflush(stdout);
+ unlink((TQString(KDM_CONTROL_FIFO_SAK_FILE).tqarg(newdisplayint)).ascii());
+ writeerror = true;
+ }
+ else {
+ struct stat buffer;
+ int status = -1;
+ int timeout_counter = 0;
+ while ((status != 0) && (timeout_counter < 30)) {
+ status = stat((TQString(KDM_CONTROL_FIFO_FILE).tqarg(newdisplayint)).ascii(), &buffer);
+ timeout_counter++;
+ usleep(100000);
+ }
+ }
+ }
+ else {
+ // Make sure the control socket is writable
+ if (writefile(TQString(KDM_CONTROL_FIFO_FILE).tqarg(newdisplayint), "PING\n") < 0) {
+ // Uh oh, something failed...
+ printf("Unable to write to KDM control socket %s\n\r", (TQString(KDM_CONTROL_FIFO_FILE).tqarg(newdisplayint)).ascii()); fflush(stdout);
+ unlink((TQString(KDM_CONTROL_FIFO_FILE).tqarg(newdisplayint)).ascii());
+ writeerror = true;
+ }
+ }
+ if (newdisplayint == (MAXIMUM_VTS+1)) {
+ writeerror = true;
+ systemexec(TRINITY_BIN_PREFIX "kdmctl -g reserve");
+ usleep(1000000);
+ }
+ if (writeerror)
+ have_valid_display = false;
+ else
+ have_valid_display = true;
}
- }
- if (!resultbkp.contains(":")) {
- newdisplay = exec("ls /var/run/xdmctl/ | grep 'xdmctl-:0'");
- printf("[DEBUG 400.d] %s\n\r", newdisplay.ascii()); fflush(stdout);
- if (newdisplay != "") {
- usebasedisplay=1;
+ else
+ {
+ // Could not find any existing kdm sessions; start a new one
+ systemexec(TRINITY_BIN_PREFIX "kdmctl -g reserve");
}
}
- printf("[DEBUG 400.e] Creating new session\n\r"); fflush(stdout);
- if (usebasedisplay) {
- printf("[DEBUG 400.e] Using base display\n\r"); fflush(stdout);
- }
- // Attempt login
-
-// // Find next sequential inactive display
-// // FIXME
-// // This assumes the original VT is on display 0 at all times,
-// // which is not always true
-// int minvt = 0;
-// TQStringList sessionList = TQStringList::split('\t', result, false);
-// for (newdisplayint = minvt; newdisplayint<MAXIMUM_VTS; newdisplayint++) {
-// bool displayfound = false;
-// for ( TQStringList::Iterator it = sessionList.begin(); it != sessionList.end(); ++it ) {
-// TQStringList sessionInfoList = TQStringList::split(',', *it, true);
-// if ((*(sessionInfoList.at(0))).startsWith(TQString(":%1").tqarg(newdisplayint))) {
-// displayfound = true;
-// }
-// }
-// if (displayfound == false) {
-// break;
-// }
-// }
-
- // This external bash code does not assume that the original VT is on display 0 at all times,
- // but it is a bit sloppy to have to call it from here. FIXME
- newdisplayint = systemexec("smartauth_displayfinder");
-
newdisplay = TQString(":%1").tqarg(newdisplayint);
- printf("[DEBUG 400.f] The next display to start will be %s\n\r", newdisplay.ascii()); fflush(stdout);
+ printf("[DEBUG 400.f] Logging in on display %s\n\r", newdisplay.ascii()); fflush(stdout);
- if (!usebasedisplay) {
- systemexec(TRINITY_BIN_PREFIX "kdmctl -g reserve");
- }
- TQString kdmctl_command = TQString("login\t%1\tnow\t%2\t%3\n").tqarg(newdisplay).tqarg(smartcard_username).tqarg(smartcard_password);
- FILE* kdmctlpipe = popen(TRINITY_BIN_PREFIX "kdmctl -g -", "w");
- if (pipe) {
- fputs(kdmctl_command.ascii(), kdmctlpipe);
- fflush(kdmctlpipe);
- pclose(kdmctlpipe);
+ // Construct login string
+ TQString logincommand = TQString("LOGIN\t%1\t%2\n").tqarg(smartcard_username).tqarg(smartcard_password);
+ if (writefile(TQString(KDM_CONTROL_FIFO_FILE).tqarg(newdisplayint), logincommand) < 0) {
+ // Uh oh, something failed...
+ printf("Unable to write to KDM control socket %s\n\r", (TQString(KDM_CONTROL_FIFO_FILE).tqarg(newdisplayint)).ascii()); fflush(stdout);
}
- sleep(2);
- systemexec((TQString(TRINITY_BIN_PREFIX "kdmctl -g activate %1").tqarg(newdisplay)).ascii());
+
udisplay=newdisplay;
}