/* Smart Card TDE Authentication Script (c) 2010-2011 Timothy Pearson This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #define _XOPEN_SOURCE 500 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Maximum number of virtual terminals on this system #define MAXIMUM_VTS 49 // The [secure] temporary directory for authentication #define SECURE_DIRECTORY_PATH "/tmp/smartauth" // The Trinity binary directory #define TRINITY_BIN_PREFIX "/opt/trinity/bin/" // Some internal constants #define CREATE_LIFE_CYCLE "01" #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" { int check_password(const char* username, const char* password); } static TQString secure_directory; static TQString command_mode; static TQString select_file; static TQString read_binary; static TQString update_binary; static TQString delete_file; static TQString get_challenge; static TQString external_auth; static TQString activate_file; static TQString hexidecimal_key; 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; char *buf; fp=fopen(filename, "rb"); if (fp == NULL) { printf("[WARNING] Unable to read from file %s\n\r", filename); fflush(stdout); return TQString(); } fseek(fp,0,SEEK_END); // Seek to end len=ftell(fp); // Get position at end (length) fseek(fp,0,SEEK_SET); // Seek to beginning buf=(char *)malloc(len+1); // Malloc the buffer fread(buf,len,1,fp); // Read file fclose(fp); buf[len]=0; TQString contents(buf); free(buf); // Free the buffer 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("\"", "\\\""); bashcommand = TQString("/bin/bash -c \"%1\"").tqarg(bashcommand); FILE* pipe = popen(bashcommand.ascii(), "r"); if (!pipe) return "ERROR"; char buffer[128]; TQString result = ""; while(!feof(pipe)) { if(fgets(buffer, 128, pipe) != NULL) { result += buffer; } } pclose(pipe); result.remove(result.length(), 1); return result; } int systemexec(const char * cmd) { TQString bashcommand = cmd; bashcommand = bashcommand.replace("\"", "\\\""); bashcommand = TQString("/bin/bash -c \"%1\"").tqarg(bashcommand); return system(bashcommand.ascii()) >> 8; } TQString execret(const char * cmd, int * retcode) { TQString bashcommand = cmd; bashcommand = bashcommand.replace("\"", "\\\""); bashcommand = TQString("/bin/bash -c \"%1\"").tqarg(bashcommand); FILE* pipe = popen(bashcommand.ascii(), "r"); if (!pipe) return "ERROR"; char buffer[128]; TQString result = ""; while(!feof(pipe)) { if(fgets(buffer, 128, pipe) != NULL) { result += buffer; } } *retcode = pclose(pipe) >> 8; result.remove(result.length(), 1); return result; } int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { int rv = remove(fpath); if (rv) perror(fpath); return rv; } int rmrf(const char *path) { return nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS); } TQString get_file(TQString prefix, TQString mode) { if (command_mode == "acos") { // Select EF prefix under DF 1000 systemexec((TQString("echo \"%1 %2\" > %3/query").tqarg(select_file).tqarg(prefix).tqarg(secure_directory)).ascii()); systemexec((TQString("scriptor %1/query 1> %2/response2").tqarg(secure_directory).tqarg(secure_directory)).ascii()); // printf("[DEBUG 100.0] %s\n\r", readfile((TQString("%1/response2").tqarg(secure_directory))).ascii()); fflush(stdout); // Read binary systemexec((TQString("echo \"%1\" > %2/query").tqarg(read_binary).tqarg(secure_directory)).ascii()); systemexec((TQString("scriptor %1/query 1> %2/response2").tqarg(secure_directory).tqarg(secure_directory)).ascii()); TQString authokresponse="90 00 : Normal processing"; TQString response1 = exec((TQString("cat %1/response2 | grep \"%2\"").tqarg(secure_directory).tqarg(authokresponse)).ascii()); if (response1 != "") { systemexec((TQString("cat %1/response2 | tr -d '\n' > %2/response4").tqarg(secure_directory).tqarg(secure_directory)).ascii()); TQString stringtoreplace="Using T=0 protocol00 B0 00 00 FF> 00 B0 00 00 FF< "; TQString newstring=""; systemexec((TQString("sed -i \"s#%1#%2#g\" %3/response4").tqarg(stringtoreplace).tqarg(newstring).tqarg(secure_directory)).ascii()); stringtoreplace=" 90 00 : Normal processing."; newstring=""; systemexec((TQString("sed -i \"s#%1#%2#g\" %3/response4").tqarg(stringtoreplace).tqarg(newstring).tqarg(secure_directory)).ascii()); if (mode == "text") { stringtoreplace=" 00"; newstring=""; systemexec((TQString("sed -i \"s#%1#%2#g\" %3/response4").tqarg(stringtoreplace).tqarg(newstring).tqarg(secure_directory)).ascii()); } // printf("[DEBUG 100.1] %s\n\r", readfile((TQString("%1/response4").tqarg(secure_directory))).ascii()); fflush(stdout); unlink((TQString("%1/lukskey").tqarg(secure_directory)).ascii()); systemexec((TQString("xxd -r -p %1/response4 %2/lukskey").tqarg(secure_directory).tqarg(secure_directory)).ascii()); return(TQString("%1/lukskey").tqarg(secure_directory)); } } if (command_mode == "cryptoflex") { TQString file = TQString(prefix).replace(' ', ""); unlink((TQString("3F00_%1").tqarg(file)).ascii()); // systemexec((TQString("echo \"get %1\" | opensc-explorer").tqarg(file)).ascii()); fputs((TQString("get %1\n").tqarg(file)).ascii(), opensc_explorer_file); fflush(opensc_explorer_file); int j; // Wait up to 2 seconds for the file to be written for (j=0;j<200;j++) { FILE* fp1 = fopen((TQString("3F00_%1").tqarg(file)).ascii(), "r"); if (fp1) { // file exists fclose(fp1); break; } usleep(10000); } usleep(100000); // [FIXME] Here I assume that the entire file will be written (after it was created) within 100us. This may not be correct in all cases! return TQString("3F00_%1").tqarg(file); } } void createfile(TQString prefix, TQString mode) { if (command_mode == "cryptoflex") { // Create transparent file with permissions: // delete, terminate, activate, deactivate, update, read for Key 1 and Key 2 only systemexec((TQString("echo \"F0 E0 00 FF 10 FF FF 00 %1 %2 01 3F 44 FF 44 01 03 11 FF 11\" > %3/query").tqarg(prefix).tqarg(mode).tqarg(secure_directory)).ascii()); systemexec((TQString("scriptor %1/query 1> %2/response2 2>/dev/null").tqarg(secure_directory).tqarg(secure_directory)).ascii()); } if (command_mode == "acos") { // Create transparent file with permissions: // delete, terminate, activate, deactivate, update, read for Key 1, Key 2, and Key 3 only (SE 04) // created in DF 1000 under MF, SE file is 10FE // SIZE TRANSPARENT systemexec((TQString("echo \"00 E0 00 00 1A 62 18 80 02 00 %1 82 01 01 83 02 %2 8A 01 %3 8C 08 7F 04 04 04 04 04 04 04\" > %4/query").tqarg(prefix).tqarg(mode).tqarg(CREATE_LIFE_CYCLE).tqarg(secure_directory)).ascii()); systemexec((TQString("scriptor %1/query 1> %2/response2 2>/dev/null").tqarg(secure_directory)).ascii()); printf("[DEBUG 300.0] %s\n\r", readfile((TQString("%1/response2").tqarg(secure_directory))).ascii()); fflush(stdout); } } void update_file(TQString prefix, TQString mode) { if (command_mode == "acos") { // Select EF prefix under DF 1000 systemexec((TQString("echo \"$SELECT_FILE %1\" > %2/query").tqarg(prefix).tqarg(secure_directory)).ascii()); systemexec((TQString("scriptor %1/query 1> %2/response2").tqarg(secure_directory).tqarg(secure_directory)).ascii()); printf("[DEBUG 200.0] %s\n\r", readfile((TQString("%1/response2").tqarg(secure_directory))).ascii()); fflush(stdout); // Update existing file // Zero pad input file systemexec((TQString("dd if=/dev/zero of=%1/response2 bs=1 count=255 2>/dev/null 1>/dev/null").tqarg(secure_directory)).ascii()); systemexec((TQString("dd if=%1 of=%2/response2 bs=1 count=255 conv=notrunc 2>/dev/null 1>/dev/null").tqarg(mode).tqarg(secure_directory)).ascii()); // Truncate to 255 bytes and expand to standard hex listing format systemexec((TQString("xxd -l 255 -ps -c 1 %1/response2 > %2/response").tqarg(secure_directory).tqarg(secure_directory)).ascii()); systemexec((TQString("cat %1/response | tr '\n' ' ' > %1/hexready").tqarg(secure_directory)).ascii()); TQString hexready = readfile((TQString("%1/hexready").tqarg(secure_directory)).ascii()); systemexec((TQString("echo \"%1 %2\" > %3/query").tqarg(update_binary).tqarg(hexready).tqarg(secure_directory)).ascii()); systemexec((TQString("scriptor %1/query 1> %2/response2 2>/dev/null").tqarg(secure_directory).tqarg(secure_directory)).ascii()); printf("[DEBUG 200.1] %s\n\r", readfile((TQString("%1/response2").tqarg(secure_directory))).ascii()); fflush(stdout); } if (command_mode == "cryptoflex") { // Delete old file systemexec((TQString("echo \"%1 $1\" > %2/query").tqarg(delete_file).tqarg(secure_directory)).ascii()); systemexec((TQString("scriptor %1/query 1> %2/response2 2>/dev/null").tqarg(secure_directory).tqarg(secure_directory)).ascii()); printf("[DEBUG 200.2] %s\n\r", readfile((TQString("%1/response2").tqarg(secure_directory))).ascii()); fflush(stdout); // Create new file createfile("FF", prefix); TQString file = TQString(prefix).replace(' ', ""); systemexec((TQString("echo \"put %1 %2\" | opensc-explorer").tqarg(file).tqarg(mode)).ascii()); } } int main (int argc, char *argv[]) { TQString smartcard_username; TQString oldsmartcard_username; TQString smartcard_password; TQString smartcard_slave; TQString lverify; TQString cverify; TQString udisplay; TQString newdisplay; TQString logouttest; TQString blankresult; TQString smartcard_minutes_raw; int timer; int smartcard_minutes; int internet_minutes; int newdisplayint; 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()); mkdir(secure_directory.ascii(), 600); chown(secure_directory.ascii(), 0, 0); chmod(secure_directory.ascii(), 600); secure_directory=exec("mktemp " SECURE_DIRECTORY_PATH "/smartauthmon.XXXXXXXXXX"); secure_directory.replace('\n', ""); rmrf(secure_directory.ascii()); mkdir(secure_directory.ascii(), 600); chown(secure_directory.ascii(), 0, 0); chmod(secure_directory.ascii(), 600); // Terminate old pcscd process from initrd system("killall -9 pcscd"); // See if required programs are installed TQString scriptor = exec("whereis scriptor"); if ( scriptor == "scriptor:" ) { printf("ERROR: scriptor is not installed! This program cannot continue!\n\r"); fflush(stdout); return 1; } TQString opensc = exec("whereis opensc-explorer"); if ( opensc == "opensc-explorer:" ) { printf("ERROR: opensc-explorer is not installed! This program cannot continue!\n\r"); fflush(stdout); return 1; } printf("[DEBUG 390.2] Reading keys\n\r"); fflush(stdout); // Read hexidecimal_key from the system crypto files FILE* fpkey = fopen("/etc/smartauth/smartauthmon.key", "rb"); if (fpkey == NULL) { printf("Smart card login has been disabled. Exiting...\n\r"); fflush(stdout); return 1; } else { fclose(fpkey); } hexidecimal_key = readfile("/etc/smartauth/smartauthmon.key"); hexidecimal_key.replace('\n', ""); oldsmartcard_username=""; printf("[DEBUG 400.0] Ready...\n\r"); fflush(stdout); while (1) { sleep(1); int output = systemexec("echo \"exit\" | timeout 1 scriptor 2>/dev/null 1>/dev/null"); if (output == 0) { printf("[DEBUG 400.1] Card inserted!\n\r"); fflush(stdout); systemexec("echo \"TAuthenticating SmartCard...\" > /tmp/ksocket-global/kdesktoplockcontrol &"); // Get card ATR systemexec((TQString("echo \"RESET\" > %1/query").tqarg(secure_directory)).ascii()); systemexec((TQString("scriptor %1/query 1> %2/response2").tqarg(secure_directory).tqarg(secure_directory)).ascii()); TQString authokresponse="OK: "; TQString response1 = exec((TQString("cat %1/response2 | grep \"%2\"").tqarg(secure_directory).tqarg(authokresponse)).ascii()); if (response1 != "") { systemexec((TQString("cat %1/response2 | tr -d '\n' > %2/response4").tqarg(secure_directory).tqarg(secure_directory)).ascii()); TQString stringtoreplace="Using T=0 protocolRESET> RESET< OK: "; TQString newstring=""; systemexec((TQString("sed -i \"s#%1#%2#g\" %3/response4").tqarg(stringtoreplace).tqarg(newstring).tqarg(secure_directory)).ascii()); TQString smartatr = readfile((TQString("%1/response4").tqarg(secure_directory)).ascii()); printf("[DEBUG 400.2] Got ATR: %s\n\r", smartatr.ascii()); fflush(stdout); if (smartatr == "3B BE 18 00 00 41 05 10 00 00 00 00 00 00 00 00 00 90 00 ") { printf("[DEBUG 400.3] Detected ACOS5 card\n\r"); fflush(stdout); command_mode="acos"; } if (smartatr == "3B 02 14 50 ") { printf("[DEBUG 400.3] Detected Schlumberger CryptoFlex card\n\r"); fflush(stdout); command_mode="cryptoflex"; } } else { printf("[DEBUG 400.3] No card detected!\n\r"); fflush(stdout); } if (command_mode == "cryptoflex") { get_challenge="C0 84 00 00 08"; external_auth="C0 82 00 00 07 01"; select_file="C0 A4 00 00 02"; delete_file="F0 E4 00 00 02"; } if (command_mode == "acos") { get_challenge="00 84 00 00 08"; external_auth="00 82 00 82 08"; // Key 2 select_file="00 A4 00 00 02"; delete_file="00 E4 00 00 00"; read_binary="00 B0 00 00 FF"; update_binary="00 D6 00 00 FF"; activate_file="00 44 00 00 02"; } // Authenticate card if (command_mode == "acos") { // Select MF systemexec((TQString("echo \"00 A4 00 00 00\" > %1/query").tqarg(secure_directory)).ascii()); systemexec((TQString("scriptor %1/query 1> %2/response2").tqarg(secure_directory).tqarg(secure_directory)).ascii()); printf("[DEBUG 400.4] %s\n\r", readfile((TQString("%1/response2").tqarg(secure_directory))).ascii()); fflush(stdout); // Select DF 1000 under MF systemexec((TQString("echo \"%1 10 00\" > %2/query").tqarg(select_file).tqarg(secure_directory)).ascii()); systemexec((TQString("scriptor %1/query 1> %2/response2").tqarg(secure_directory).tqarg(secure_directory)).ascii()); printf("[DEBUG 400.5] %s\n\r", readfile((TQString("%1/response2").tqarg(secure_directory))).ascii()); fflush(stdout); } systemexec((TQString("echo %1 > %2/authscript").tqarg(get_challenge).tqarg(secure_directory)).ascii()); systemexec((TQString("scriptor %1/authscript | grep 'Normal processing' > %2/challenge").tqarg(secure_directory).tqarg(secure_directory)).ascii()); systemexec((TQString("perl -pi -e 's/ //g' %1/challenge").tqarg(secure_directory)).ascii()); systemexec((TQString("perl -pi -e 's/:Normalprocessing.//g' %1/challenge").tqarg(secure_directory)).ascii()); systemexec((TQString("perl -pi -e 's//dev/null 1>/dev/null").tqarg(secure_directory).tqarg(secure_directory)).ascii()); // Expand to standard hex listing format systemexec((TQString("xxd -g 1 %1/response2 %2/response").tqarg(secure_directory).tqarg(secure_directory)).ascii()); systemexec((TQString("dd if=%1/response of=%2/response2 bs=1 count=23 skip=9 2>/dev/null 1>/dev/null").tqarg(secure_directory).tqarg(secure_directory)).ascii()); } if (command_mode == "cryptoflex") { // Truncate to 6 bytes systemexec((TQString("dd if=%1/response of=%2/response2 bs=1 count=6 2>/dev/null 1>/dev/null").tqarg(secure_directory).tqarg(secure_directory)).ascii()); // Expand to standard hex listing format systemexec((TQString("xxd -g 1 %1/response2 %2/response").tqarg(secure_directory).tqarg(secure_directory)).ascii()); systemexec((TQString("dd if=%1/response of=%2/response2 bs=1 count=17 skip=9 2>/dev/null 1>/dev/null").tqarg(secure_directory).tqarg(secure_directory)).ascii()); } // Assemble the response file TQString response2 = readfile((TQString("%1/response2").tqarg(secure_directory)).ascii()); response1 = TQString("%1 %2").tqarg(external_auth).tqarg(response2); systemexec((TQString("echo %1 > %2/response").tqarg(response1).tqarg(secure_directory)).ascii()); // Send the response! systemexec((TQString("scriptor %1/response > %2/response2").tqarg(secure_directory).tqarg(secure_directory)).ascii()); // Get the result authokresponse = "< 90 00 : Normal processing"; response1 = exec((TQString("cat %1/response2 | grep \"%2\"").tqarg(secure_directory).tqarg(authokresponse)).ascii()); printf("[DEBUG 400.6] %s\n\r", response1.ascii()); fflush(stdout); if (response1 != "") { printf("[DEBUG 400.7] Smart card validation successfull!\n\r"); fflush(stdout); if (command_mode == "cryptoflex") { opensc_explorer_file = popen("opensc-explorer 2>/dev/null 1>/dev/null", "w"); } // Get username and password TQString response = get_file("10 02", "text"); smartcard_username = readfile(response); smartcard_username = smartcard_username.replace('\n', ""); unlink(response.ascii()); response = get_file("10 03", "text"); smartcard_password = readfile(response.ascii()); smartcard_password = smartcard_password.replace('\n', ""); unlink(response.ascii()); response = get_file("10 04", "text"); smartcard_slave = readfile(response); smartcard_slave = smartcard_slave.replace('\n', ""); unlink(response.ascii()); if (smartcard_slave == "SLAVE") { get_file("10 05", "text"); smartcard_minutes_raw = readfile(response); smartcard_minutes_raw = smartcard_minutes_raw.replace('\n', ""); unlink(response.ascii()); get_file("10 06", "text"); internet_minutes = readfile(response).toInt(); unlink(response.ascii()); } } else { printf("[DEBUG 400.7] This card does not recognize this system!\n\r"); fflush(stdout); systemexec("echo \"EInvalid SmartCard Inserted\" > /tmp/ksocket-global/kdesktoplockcontrol &"); sleep(1); smartcard_username=""; unlink((TQString("%1/password").tqarg(secure_directory)).ascii()); smartcard_slave=""; } if (smartcard_slave == "SLAVE") { if (smartcard_minutes_raw == "") { smartcard_minutes=1; } else { smartcard_minutes = smartcard_minutes_raw.toInt(); } // Decrement minutes on card if (smartcard_minutes > 0) { smartcard_minutes=smartcard_minutes-1; systemexec((TQString("echo %1 > %2/minutes").tqarg(smartcard_minutes).tqarg(secure_directory)).ascii()); update_file("10 05", TQString("%1/minutes").tqarg(secure_directory)); } if (smartcard_minutes == 0) { printf("[DEBUG 400.8] Minutes have been used up!\n\r"); fflush(stdout); // Prohibit logon smartcard_username=""; unlink((TQString("%1/password").tqarg(secure_directory)).ascii()); } mkdir("/etc/smartmon", 644); systemexec((TQString("echo %1 > /etc/smartmon/minutesremaining").tqarg(smartcard_minutes)).ascii()); chmod("/etc/smartmon/minutesremaining", 755); } // Initialize variables int loginok=1; // Try to do the authentication TQString result=""; int timeout=0; int errcode=0; int waserror=0; int noactivesessions=0; result = exec(TRINITY_BIN_PREFIX "kdmctl -g list"); if (result == "ok") { noactivesessions=1; result="okbutempty"; } printf("[DEBUG 400.9] %s\n\r", result.ascii()); fflush(stdout); TQString resultbkp=result; if (errcode == 0) { // Allow KDM to finish starting if (waserror == 1) { sleep(10); } // Zero the desktop array int index=0; while (index < MAXIMUM_VTS) { darray[index]=""; index++; } if (result != "okbutempty") { TQStringList sessionList = TQStringList::split('\t', result, false); for ( TQStringList::Iterator it = sessionList.begin(); it != sessionList.end(); ++it ) { TQStringList sessionInfoList = TQStringList::split(',', *it, true); if ((*(sessionInfoList.at(0))).startsWith(":")) { darray[(*(sessionInfoList.at(0))).mid(1).toInt()] = (*(sessionInfoList.at(2))); } } } // See if the desired user is already logged in index=0; int foundsession=0; while (index < MAXIMUM_VTS) { if (darray[index] == smartcard_username) { if (darray[index] != "") { printf("[DEBUG 400.a] Found existing session on desktop: %d\n\r", index); fflush(stdout); foundsession=1; udisplay = TQString(":%1").tqarg(index); // Check password if (check_password(smartcard_username.ascii(), smartcard_password.ascii()) == 0) { systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface quit\"").tqarg(smartcard_username).tqarg(udisplay)).ascii()); systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface enable false\"").tqarg(smartcard_username).tqarg(udisplay)).ascii()); systemexec((TQString(TRINITY_BIN_PREFIX "kdmctl activate %1").tqarg(udisplay)).ascii()); } else { systemexec("echo \"EUnauthorized SmartCard Inserted\" > /tmp/ksocket-global/kdesktoplockcontrol &"); } } else { printf("[DEBUG 400.b] Username not specified\n\r"); fflush(stdout); foundsession=2; sleep(1); } } index++; } if (foundsession == 0) { printf("[DEBUG 400.c] Existing session not found, starting new...\n\r"); fflush(stdout); // 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(3000000); } if (writeerror) have_valid_display = false; else have_valid_display = true; } else { // KDM is probably not running yet, as its control directory does not exist // Wait for 10 seconds and try again usleep(10000000); } } newdisplay = TQString(":%1").tqarg(newdisplayint); printf("[DEBUG 400.f] Logging in on display %s\n\r", newdisplay.ascii()); fflush(stdout); // 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); } systemexec((TQString(TRINITY_BIN_PREFIX "kdmctl -g activate %1").tqarg(newdisplay)).ascii()); udisplay=newdisplay; } if (smartcard_slave == "SLAVE") { if (smartcard_minutes < 5) { systemexec((TQString("su %1 -c \"export DISPLAY=%2; zenity --warning --text 'You have less than 5 minutes of computer time remaining' || exit 0\" &").tqarg(smartcard_username).tqarg(udisplay)).ascii()); } } unlink((TQString("%1/password").tqarg(secure_directory)).ascii()); // if (loginok == 1) { // Wait for SmartCard removal systemexec("echo \"C\" > /tmp/ksocket-global/kdesktoplockcontrol &"); timer=60; output=0; while (output == 0) { sleep(1); systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface quit\"").tqarg(smartcard_username).tqarg(udisplay)).ascii()); systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface enable false\"").tqarg(smartcard_username).tqarg(udisplay)).ascii()); output = systemexec("echo \"exit\" | scriptor 2>/dev/null 1>/dev/null"); if (smartcard_slave == "SLAVE") { timer--; if (timer == 0) { // 60 seconds have passed, decrement minutes on card smartcard_minutes--; systemexec((TQString("echo %1 > /etc/smartmon/minutesremaining").tqarg(smartcard_minutes)).ascii()); chmod("/etc/smartmon/minutesremaining", 755); timer=60; systemexec((TQString("echo %1 > %2/minutes").tqarg(smartcard_minutes).tqarg(secure_directory)).ascii()); update_file("10 05", TQString("%1/minutes").tqarg(secure_directory)); if (smartcard_minutes == 0) { printf("[DEBUG 401.0] Minutes have been used up!\n\r"); fflush(stdout); // Prohibit logon smartcard_username=""; unlink((TQString("%1/password").tqarg(secure_directory)).ascii()); } mkdir("/etc/smartmon", 644); systemexec((TQString("echo %1 > /etc/smartmon/minutesremaining").tqarg(smartcard_minutes)).ascii()); chmod("/etc/smartmon/minutesremaining", 755); if (smartcard_minutes == 5) { systemexec((TQString("su %1 -c \"export DISPLAY=%2; zenity --warning --text 'You have less than 5 minutes of computer time remaining' || exit 0\" &").tqarg(smartcard_username).tqarg(udisplay)).ascii()); } if (smartcard_minutes == 0) { printf("[DEBUG 401.1] Minutes have been used up!\n\r"); fflush(stdout); printf("[DEBUG 401.2] Beginning logoff process\n\r"); fflush(stdout); output=254; } } } } printf("[DEBUG 401.3] Card removed\n\r"); fflush(stdout); // Is the user still logged in? result="ok"; timeout=0; errcode=0; result = exec(TRINITY_BIN_PREFIX "kdmctl -g list"); if (result == "ok") { noactivesessions=1; result="okbutempty"; } printf("[DEBUG 401.4] %s\n\r", result.ascii()); fflush(stdout); // Zero the desktop array index=0; while (index < MAXIMUM_VTS) { darray[index]=""; index++; } TQStringList sessionList = TQStringList::split('\t', result, false); for ( TQStringList::Iterator it = sessionList.begin(); it != sessionList.end(); ++it ) { TQStringList sessionInfoList = TQStringList::split(',', *it, true); if ((*(sessionInfoList.at(0))).startsWith(":")) { darray[(*(sessionInfoList.at(0))).mid(1).toInt()] = (*(sessionInfoList.at(2))); } } // See if the desired user is still logged in index=0; foundsession=0; while (index != MAXIMUM_VTS) { if (darray[index] == smartcard_username) { if (darray[index] != "") { printf("[DEBUG 401.5] Found existing session on desktop: %d\n\r", index); fflush(stdout); udisplay = TQString(":%1").tqarg(index); foundsession=1; errcode=1; timeout=0; blankresult=""; while (blankresult != "true") { systemexec((TQString(TRINITY_BIN_PREFIX "kdmctl -g activate %1").tqarg(udisplay)).ascii()); systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface enable true\"").tqarg(smartcard_username).tqarg(udisplay)).ascii()); systemexec((TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface lock\"").tqarg(smartcard_username).tqarg(udisplay)).ascii()); int retcode; blankresult = execret(TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface isBlanked\"").tqarg(smartcard_username).tqarg(udisplay).ascii(), &retcode); if (retcode != 0) { blankresult="true"; } blankresult = blankresult.replace('\n', ""); logouttest = exec((TQString("echo %1 | grep 'target display has no VT assigned'").tqarg(blankresult)).ascii()); if (logouttest != "") { printf("[DEBUG 401.6] User has logged out\n\r"); fflush(stdout); blankresult="true"; } } } else { printf("[DEBUG 401.7] Username not specified!\n\r"); fflush(stdout); sleep(1); } } index++; } // } } if (command_mode == "cryptoflex") { pclose(opensc_explorer_file); } smartcard_username=""; unlink("/etc/smartmon/minutesremaining"); systemexec("echo \"C\" > /tmp/ksocket-global/kdesktoplockcontrol &"); } } }