diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-09-22 19:47:58 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-09-22 19:47:58 +0000 |
commit | cbe66c290b343f54a6741cb420bac17225d51285 (patch) | |
tree | 3a6579c5e9dcfcbfbd90c39d734b6b8bf65601a4 /src/smartauthmon.cpp | |
parent | 1e59465c8abdce055fd9cd3b66ea4547c88c688d (diff) | |
download | smartcardauth-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
Diffstat (limited to 'src/smartauthmon.cpp')
-rw-r--r-- | src/smartauthmon.cpp | 183 |
1 files changed, 127 insertions, 56 deletions
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; } |