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
v3.5.13-sru
tpearson 13 years ago
parent 1e59465c8a
commit cbe66c290b

@ -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

@ -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/

@ -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;
}

Loading…
Cancel
Save