From cbe66c290b343f54a6741cb420bac17225d51285 Mon Sep 17 00:00:00 2001 From: tpearson Date: Thu, 22 Sep 2011 19:47:58 +0000 Subject: [PATCH] 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 --- Makefile | 1 - src/smartauth_displayfinder | 30 ------ src/smartauthmon.cpp | 183 +++++++++++++++++++++++++----------- 3 files changed, 127 insertions(+), 87 deletions(-) delete mode 100755 src/smartauth_displayfinder 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/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 #include +#include #include #include @@ -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