You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
848 lines
32 KiB
848 lines
32 KiB
/* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#define _XOPEN_SOURCE 500
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <limits.h>
|
|
#include <dirent.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/select.h>
|
|
#include <sys/time.h>
|
|
#include <termios.h>
|
|
#include <signal.h>
|
|
#include <ftw.h>
|
|
|
|
#include <tqdir.h>
|
|
#include <tqstring.h>
|
|
#include <tqstringlist.h>
|
|
|
|
// 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
|
|
#ifndef TRINTIY_BIN_PREFIX
|
|
#define TRINITY_BIN_PREFIX "/opt/trinity/bin/"
|
|
#endif
|
|
|
|
// Some internal constants
|
|
#define CREATE_LIFE_CYCLE "01"
|
|
|
|
#define TDM_CONTROL_FIFO_DIR "/tmp/tdesocket-global/tdm"
|
|
#define TDM_CONTROL_FIFO_FILE "/tmp/tdesocket-global/tdm/tdmctl-%1"
|
|
#define TDM_CONTROL_FIFO_SAK_FILE "/tmp/tdesocket-global/tdm/tdmctl-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"); fflush(stdout);
|
|
}
|
|
}
|
|
|
|
TQString readfile(const TQString filename) {
|
|
FILE *fp;
|
|
long len;
|
|
char *buf;
|
|
fp=fopen(filename.local8Bit(), "rb");
|
|
if (fp == NULL) {
|
|
printf("[WARNING] Unable to read from file %s\n", filename.local8Bit().data()); 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 TQString filename, TQString contents) {
|
|
int fp;
|
|
long len;
|
|
char *buf;
|
|
fp=open(filename.local8Bit(), O_WRONLY | O_NONBLOCK);
|
|
if (fp < 0) {
|
|
printf("[WARNING] Unable to open file %s for writing\n", filename.local8Bit().data()); fflush(stdout);
|
|
return -1;
|
|
}
|
|
int retcode = write(fp, contents.ascii(), contents.length());
|
|
close(fp);
|
|
return retcode;
|
|
}
|
|
|
|
TQString exec(const TQString cmd) {
|
|
TQString bashcommand = cmd;
|
|
bashcommand = bashcommand.replace("\"", "\\\"");
|
|
bashcommand = TQString("/bin/bash -c \"%1\"").arg(bashcommand);
|
|
FILE* pipe = popen(bashcommand.local8Bit(), "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 TQString cmd) {
|
|
TQString bashcommand = cmd;
|
|
bashcommand = bashcommand.replace("\"", "\\\"");
|
|
bashcommand = TQString("/bin/bash -c \"%1\"").arg(bashcommand);
|
|
return system(bashcommand.local8Bit()) >> 8;
|
|
}
|
|
|
|
TQString execret(const TQString cmd, int * retcode) {
|
|
TQString bashcommand = cmd;
|
|
bashcommand = bashcommand.replace("\"", "\\\"");
|
|
bashcommand = TQString("/bin/bash -c \"%1\"").arg(bashcommand);
|
|
FILE* pipe = popen(bashcommand.local8Bit(), "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").arg(select_file).arg(prefix).arg(secure_directory));
|
|
systemexec(TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory));
|
|
// printf("[DEBUG 100.0] %s\n", readfile(TQString("%1/response2").arg(secure_directory)).local8Bit().data()); fflush(stdout);
|
|
|
|
// Read binary
|
|
systemexec(TQString("echo \"%1\" > %2/query").arg(read_binary).arg(secure_directory));
|
|
systemexec(TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory));
|
|
TQString authokresponse="90 00 : Normal processing";
|
|
TQString response1 = exec(TQString("cat %1/response2 | grep \"%2\"").arg(secure_directory).arg(authokresponse));
|
|
if (response1 != "") {
|
|
systemexec(TQString("cat %1/response2 | tr -d '\n' > %2/response4").arg(secure_directory).arg(secure_directory));
|
|
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").arg(stringtoreplace).arg(newstring).arg(secure_directory));
|
|
stringtoreplace=" 90 00 : Normal processing.";
|
|
newstring="";
|
|
systemexec(TQString("sed -i \"s#%1#%2#g\" %3/response4").arg(stringtoreplace).arg(newstring).arg(secure_directory));
|
|
if (mode == "text") {
|
|
stringtoreplace=" 00";
|
|
newstring="";
|
|
systemexec(TQString("sed -i \"s#%1#%2#g\" %3/response4").arg(stringtoreplace).arg(newstring).arg(secure_directory));
|
|
}
|
|
// printf("[DEBUG 100.1] %s\n", readfile(TQString("%1/response4").arg(secure_directory)).local8Bit().data()); fflush(stdout);
|
|
unlink((TQString("%1/lukskey").arg(secure_directory)).local8Bit());
|
|
systemexec(TQString("xxd -r -p %1/response4 %2/lukskey").arg(secure_directory).arg(secure_directory));
|
|
return(TQString("%1/lukskey").arg(secure_directory));
|
|
}
|
|
}
|
|
|
|
if (command_mode == "cryptoflex") {
|
|
TQString file = TQString(prefix).replace(' ', "");
|
|
unlink((TQString("3F00_%1").arg(file)).local8Bit());
|
|
// systemexec(TQString("echo \"get %1\" | opensc-explorer").arg(file));
|
|
fputs((TQString("get %1\n").arg(file)).local8Bit(), 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").arg(file)).local8Bit(), "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").arg(file);
|
|
}
|
|
|
|
return TQString("");
|
|
}
|
|
|
|
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").arg(prefix).arg(mode).arg(secure_directory));
|
|
systemexec(TQString("scriptor %1/query 1> %2/response2 2>/dev/null").arg(secure_directory).arg(secure_directory));
|
|
}
|
|
|
|
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").arg(prefix).arg(mode).arg(CREATE_LIFE_CYCLE).arg(secure_directory));
|
|
systemexec(TQString("scriptor %1/query 1> %2/response2 2>/dev/null").arg(secure_directory));
|
|
printf("[DEBUG 300.0] %s\n", readfile(TQString("%1/response2").arg(secure_directory)).local8Bit().data()); 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").arg(prefix).arg(secure_directory));
|
|
systemexec(TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory));
|
|
printf("[DEBUG 200.0] %s\n", readfile(TQString("%1/response2").arg(secure_directory)).local8Bit().data()); 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").arg(secure_directory));
|
|
systemexec(TQString("dd if=%1 of=%2/response2 bs=1 count=255 conv=notrunc 2>/dev/null 1>/dev/null").arg(mode).arg(secure_directory));
|
|
|
|
// Truncate to 255 bytes and expand to standard hex listing format
|
|
systemexec(TQString("xxd -l 255 -ps -c 1 %1/response2 > %2/response").arg(secure_directory).arg(secure_directory));
|
|
systemexec(TQString("cat %1/response | tr '\n' ' ' > %1/hexready").arg(secure_directory));
|
|
TQString hexready = readfile(TQString("%1/hexready").arg(secure_directory));
|
|
systemexec(TQString("echo \"%1 %2\" > %3/query").arg(update_binary).arg(hexready).arg(secure_directory));
|
|
systemexec(TQString("scriptor %1/query 1> %2/response2 2>/dev/null").arg(secure_directory).arg(secure_directory));
|
|
printf("[DEBUG 200.1] %s\n", readfile(TQString("%1/response2").arg(secure_directory)).local8Bit().data()); fflush(stdout);
|
|
}
|
|
|
|
if (command_mode == "cryptoflex") {
|
|
// Delete old file
|
|
systemexec(TQString("echo \"%1 $1\" > %2/query").arg(delete_file).arg(secure_directory));
|
|
systemexec(TQString("scriptor %1/query 1> %2/response2 2>/dev/null").arg(secure_directory).arg(secure_directory));
|
|
printf("[DEBUG 200.2] %s\n", readfile(TQString("%1/response2").arg(secure_directory)).local8Bit().data()); fflush(stdout);
|
|
|
|
// Create new file
|
|
createfile("FF", prefix);
|
|
TQString file = TQString(prefix).replace(' ', "");
|
|
systemexec(TQString("echo \"put %1 %2\" | opensc-explorer").arg(file).arg(mode));
|
|
}
|
|
}
|
|
|
|
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"); 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.local8Bit());
|
|
mkdir(secure_directory.local8Bit(), 600);
|
|
chown(secure_directory.local8Bit(), 0, 0);
|
|
chmod(secure_directory.local8Bit(), 600);
|
|
secure_directory=exec(TQString("mktemp %1/smartauthmon.XXXXXXXXXX").arg(SECURE_DIRECTORY_PATH));
|
|
secure_directory.replace('\n', "");
|
|
rmrf(secure_directory.local8Bit());
|
|
mkdir(secure_directory.local8Bit(), 600);
|
|
chown(secure_directory.local8Bit(), 0, 0);
|
|
chmod(secure_directory.local8Bit(), 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"); 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"); fflush(stdout);
|
|
return 1;
|
|
}
|
|
|
|
printf("[DEBUG 390.2] Reading keys\n"); 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"); 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"); 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"); fflush(stdout);
|
|
systemexec("echo \"TAuthenticating SmartCard...\" > /tmp/tdesocket-global/kdesktoplockcontrol &");
|
|
|
|
// Get card ATR
|
|
systemexec(TQString("echo \"RESET\" > %1/query").arg(secure_directory));
|
|
systemexec(TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory));
|
|
TQString authokresponse="OK: ";
|
|
TQString response1 = exec(TQString("cat %1/response2 | grep \"%2\"").arg(secure_directory).arg(authokresponse));
|
|
if (response1 != "") {
|
|
systemexec(TQString("cat %1/response2 | tr -d '\n' > %2/response4").arg(secure_directory).arg(secure_directory));
|
|
TQString stringtoreplace="Using T=0 protocolRESET> RESET< OK: ";
|
|
TQString newstring="";
|
|
systemexec(TQString("sed -i \"s#%1#%2#g\" %3/response4").arg(stringtoreplace).arg(newstring).arg(secure_directory));
|
|
TQString smartatr = readfile(TQString("%1/response4").arg(secure_directory));
|
|
printf("[DEBUG 400.2] Got ATR: %s\n", smartatr.local8Bit().data()); 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"); fflush(stdout);
|
|
command_mode="acos";
|
|
}
|
|
if (smartatr == "3B 02 14 50 ") {
|
|
printf("[DEBUG 400.3] Detected Schlumberger CryptoFlex card\n"); fflush(stdout);
|
|
command_mode="cryptoflex";
|
|
}
|
|
}
|
|
else {
|
|
printf("[DEBUG 400.3] No card detected!\n"); 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").arg(secure_directory));
|
|
systemexec(TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory));
|
|
printf("[DEBUG 400.4] %s\n", readfile(TQString("%1/response2").arg(secure_directory)).local8Bit().data()); fflush(stdout);
|
|
|
|
// Select DF 1000 under MF
|
|
systemexec(TQString("echo \"%1 10 00\" > %2/query").arg(select_file).arg(secure_directory));
|
|
systemexec(TQString("scriptor %1/query 1> %2/response2").arg(secure_directory).arg(secure_directory));
|
|
printf("[DEBUG 400.5] %s\n", readfile(TQString("%1/response2").arg(secure_directory)).local8Bit().data()); fflush(stdout);
|
|
}
|
|
|
|
systemexec(TQString("echo %1 > %2/authscript").arg(get_challenge).arg(secure_directory));
|
|
|
|
systemexec(TQString("scriptor %1/authscript | grep 'Normal processing' > %2/challenge").arg(secure_directory).arg(secure_directory));
|
|
systemexec(TQString("perl -pi -e 's/ //g' %1/challenge").arg(secure_directory));
|
|
systemexec(TQString("perl -pi -e 's/:Normalprocessing.//g' %1/challenge").arg(secure_directory));
|
|
systemexec(TQString("perl -pi -e 's/<//g' %1/challenge").arg(secure_directory));
|
|
systemexec(TQString("xxd -r -p %1/challenge %2/challenge").arg(secure_directory).arg(secure_directory));
|
|
|
|
// Now DES encrypt the challenge
|
|
// Later, change the initialization vector to random if possible
|
|
|
|
// Create the response from the challenge
|
|
systemexec(TQString("openssl des-ecb -in %1/challenge -out %2/response -K %3 -iv 1").arg(secure_directory).arg(secure_directory).arg(hexidecimal_key));
|
|
|
|
if (command_mode == "acos") {
|
|
// Truncate to 8 bytes
|
|
systemexec(TQString("dd if=%1/response of=%2/response2 bs=1 count=8 2>/dev/null 1>/dev/null").arg(secure_directory).arg(secure_directory));
|
|
|
|
// Expand to standard hex listing format
|
|
systemexec(TQString("xxd -g 1 %1/response2 %2/response").arg(secure_directory).arg(secure_directory));
|
|
systemexec(TQString("dd if=%1/response of=%2/response2 bs=1 count=23 skip=9 2>/dev/null 1>/dev/null").arg(secure_directory).arg(secure_directory));
|
|
}
|
|
|
|
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").arg(secure_directory).arg(secure_directory));
|
|
|
|
// Expand to standard hex listing format
|
|
systemexec(TQString("xxd -g 1 %1/response2 %2/response").arg(secure_directory).arg(secure_directory));
|
|
systemexec(TQString("dd if=%1/response of=%2/response2 bs=1 count=17 skip=9 2>/dev/null 1>/dev/null").arg(secure_directory).arg(secure_directory));
|
|
}
|
|
|
|
// Assemble the response file
|
|
TQString response2 = readfile(TQString("%1/response2").arg(secure_directory));
|
|
response1 = TQString("%1 %2").arg(external_auth).arg(response2);
|
|
systemexec(TQString("echo %1 > %2/response").arg(response1).arg(secure_directory));
|
|
|
|
// Send the response!
|
|
systemexec(TQString("scriptor %1/response > %2/response2").arg(secure_directory).arg(secure_directory));
|
|
|
|
// Get the result
|
|
authokresponse = "< 90 00 : Normal processing";
|
|
response1 = exec(TQString("cat %1/response2 | grep \"%2\"").arg(secure_directory).arg(authokresponse));
|
|
printf("[DEBUG 400.6] %s\n", response1.local8Bit().data()); fflush(stdout);
|
|
if (response1 != "") {
|
|
printf("[DEBUG 400.7] Smart card validation successfull!\n"); 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.local8Bit());
|
|
response = get_file("10 03", "text");
|
|
smartcard_password = readfile(response);
|
|
smartcard_password = smartcard_password.replace('\n', "");
|
|
unlink(response.local8Bit());
|
|
response = get_file("10 04", "text");
|
|
smartcard_slave = readfile(response);
|
|
smartcard_slave = smartcard_slave.replace('\n', "");
|
|
unlink(response.local8Bit());
|
|
if (smartcard_slave == "SLAVE") {
|
|
get_file("10 05", "text");
|
|
smartcard_minutes_raw = readfile(response);
|
|
smartcard_minutes_raw = smartcard_minutes_raw.replace('\n', "");
|
|
unlink(response.local8Bit());
|
|
get_file("10 06", "text");
|
|
internet_minutes = readfile(response).toInt();
|
|
unlink(response.local8Bit());
|
|
}
|
|
}
|
|
else {
|
|
printf("[DEBUG 400.7] This card does not recognize this system!\n"); fflush(stdout);
|
|
systemexec("echo \"EInvalid SmartCard Inserted\" > /tmp/tdesocket-global/kdesktoplockcontrol &");
|
|
sleep(1);
|
|
smartcard_username="";
|
|
unlink((TQString("%1/password").arg(secure_directory)).local8Bit());
|
|
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").arg(smartcard_minutes).arg(secure_directory));
|
|
update_file("10 05", TQString("%1/minutes").arg(secure_directory));
|
|
}
|
|
|
|
if (smartcard_minutes == 0) {
|
|
printf("[DEBUG 400.8] Minutes have been used up!\n"); fflush(stdout);
|
|
// Prohibit logon
|
|
smartcard_username="";
|
|
unlink((TQString("%1/password").arg(secure_directory)).local8Bit());
|
|
}
|
|
|
|
mkdir("/etc/smartmon", 644);
|
|
systemexec(TQString("echo %1 > /etc/smartmon/minutesremaining").arg(smartcard_minutes));
|
|
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 "tdmctl -g list");
|
|
if (result == "ok") {
|
|
noactivesessions=1;
|
|
result="okbutempty";
|
|
}
|
|
printf("[DEBUG 400.9] %s\n", result.local8Bit().data()); fflush(stdout);
|
|
TQString resultbkp=result;
|
|
|
|
if (errcode == 0) {
|
|
// Allow TDM 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", index); fflush(stdout);
|
|
foundsession=1;
|
|
udisplay = TQString(":%1").arg(index);
|
|
// Check password
|
|
if (check_password(smartcard_username.local8Bit(), smartcard_password.local8Bit()) == 0) {
|
|
systemexec(TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface quit\"").arg(smartcard_username).arg(udisplay));
|
|
systemexec(TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface enable false\"").arg(smartcard_username).arg(udisplay));
|
|
systemexec(TQString(TRINITY_BIN_PREFIX "tdmctl activate %1").arg(udisplay));
|
|
}
|
|
else {
|
|
systemexec("echo \"EUnauthorized SmartCard Inserted\" > /tmp/tdesocket-global/kdesktoplockcontrol &");
|
|
}
|
|
}
|
|
else {
|
|
printf("[DEBUG 400.b] Username not specified\n"); fflush(stdout);
|
|
foundsession=2;
|
|
sleep(1);
|
|
}
|
|
}
|
|
index++;
|
|
}
|
|
|
|
if (foundsession == 0) {
|
|
printf("[DEBUG 400.c] Existing session not found, starting new...\n"); fflush(stdout);
|
|
|
|
// Get directory listing of tdm 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(TDM_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().contains("tdmctl-sak-")) {
|
|
tempdisplaystr = tempdisplaystr.replace("tdmctl-sak-", "");
|
|
tempdisplayint = tempdisplaystr.toInt(&isint);
|
|
if (isint) {
|
|
if (tempdisplayint < newdisplayint) {
|
|
newdisplayint = tempdisplayint;
|
|
display_has_sak = true;
|
|
}
|
|
}
|
|
}
|
|
else if (fi->fileName().contains("tdmctl-")) {
|
|
tempdisplaystr = tempdisplaystr.replace("tdmctl-", "");
|
|
tempdisplayint = tempdisplaystr.toInt(&isint);
|
|
if (isint) {
|
|
if (tempdisplayint < newdisplayint) {
|
|
newdisplayint = tempdisplayint;
|
|
display_has_sak = false;
|
|
}
|
|
}
|
|
}
|
|
++it;
|
|
}
|
|
if (display_has_sak) {
|
|
if (writefile(TQString(TDM_CONTROL_FIFO_SAK_FILE).arg(newdisplayint), "CLOSE\n") < 0) {
|
|
// Uh oh, something failed...
|
|
printf("Unable to write to TDM control socket %s\n", (TQString(TDM_CONTROL_FIFO_SAK_FILE).arg(newdisplayint)).local8Bit().data()); fflush(stdout);
|
|
unlink((TQString(TDM_CONTROL_FIFO_SAK_FILE).arg(newdisplayint)).local8Bit());
|
|
writeerror = true;
|
|
}
|
|
else {
|
|
struct stat buffer;
|
|
int status = -1;
|
|
int timeout_counter = 0;
|
|
while ((status != 0) && (timeout_counter < 30)) {
|
|
status = stat((TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint)).local8Bit(), &buffer);
|
|
timeout_counter++;
|
|
usleep(100000);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// Make sure the control socket is writable
|
|
if (writefile(TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint), "PING\n") < 0) {
|
|
// Uh oh, something failed...
|
|
printf("Unable to write to TDM control socket %s\n", (TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint)).local8Bit().data()); fflush(stdout);
|
|
unlink((TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint)).local8Bit());
|
|
writeerror = true;
|
|
}
|
|
}
|
|
if (newdisplayint == (MAXIMUM_VTS+1)) {
|
|
writeerror = true;
|
|
systemexec(TRINITY_BIN_PREFIX "tdmctl -g reserve");
|
|
usleep(3000000);
|
|
}
|
|
if (writeerror)
|
|
have_valid_display = false;
|
|
else
|
|
have_valid_display = true;
|
|
}
|
|
else
|
|
{
|
|
// TDM is probably not running yet, as its control directory does not exist
|
|
// Wait for 10 seconds and try again
|
|
usleep(10000000);
|
|
}
|
|
}
|
|
|
|
newdisplay = TQString(":%1").arg(newdisplayint);
|
|
printf("[DEBUG 400.f] Logging in on display %s\n", newdisplay.local8Bit().data()); fflush(stdout);
|
|
|
|
// Construct login string
|
|
TQString logincommand = TQString("LOGIN\t%1\t%2\n").arg(smartcard_username).arg(smartcard_password);
|
|
if (writefile(TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint), logincommand) < 0) {
|
|
// Uh oh, something failed...
|
|
printf("Unable to write to TDM control socket %s\n", (TQString(TDM_CONTROL_FIFO_FILE).arg(newdisplayint)).local8Bit().data()); fflush(stdout);
|
|
}
|
|
|
|
systemexec(TQString(TRINITY_BIN_PREFIX "tdmctl -g activate %1").arg(newdisplay));
|
|
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\" &").arg(smartcard_username).arg(udisplay));
|
|
}
|
|
}
|
|
|
|
unlink((TQString("%1/password").arg(secure_directory)).local8Bit());
|
|
|
|
// if (loginok == 1) {
|
|
// Wait for SmartCard removal
|
|
systemexec("echo \"C\" > /tmp/tdesocket-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\"").arg(smartcard_username).arg(udisplay));
|
|
systemexec(TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface enable false\"").arg(smartcard_username).arg(udisplay));
|
|
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").arg(smartcard_minutes));
|
|
chmod("/etc/smartmon/minutesremaining", 755);
|
|
|
|
timer=60;
|
|
|
|
systemexec(TQString("echo %1 > %2/minutes").arg(smartcard_minutes).arg(secure_directory));
|
|
update_file("10 05", TQString("%1/minutes").arg(secure_directory));
|
|
|
|
if (smartcard_minutes == 0) {
|
|
printf("[DEBUG 401.0] Minutes have been used up!\n"); fflush(stdout);
|
|
// Prohibit logon
|
|
smartcard_username="";
|
|
unlink((TQString("%1/password").arg(secure_directory)).local8Bit());
|
|
}
|
|
|
|
mkdir("/etc/smartmon", 644);
|
|
systemexec(TQString("echo %1 > /etc/smartmon/minutesremaining").arg(smartcard_minutes));
|
|
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\" &").arg(smartcard_username).arg(udisplay));
|
|
}
|
|
|
|
if (smartcard_minutes == 0) {
|
|
printf("[DEBUG 401.1] Minutes have been used up!\n"); fflush(stdout);
|
|
printf("[DEBUG 401.2] Beginning logoff process\n"); fflush(stdout);
|
|
output=254;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
printf("[DEBUG 401.3] Card removed\n"); fflush(stdout);
|
|
|
|
// Is the user still logged in?
|
|
result="ok";
|
|
timeout=0;
|
|
errcode=0;
|
|
result = exec(TRINITY_BIN_PREFIX "tdmctl -g list");
|
|
if (result == "ok") {
|
|
noactivesessions=1;
|
|
result="okbutempty";
|
|
}
|
|
printf("[DEBUG 401.4] %s\n", result.local8Bit().data()); 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", index); fflush(stdout);
|
|
udisplay = TQString(":%1").arg(index);
|
|
foundsession=1;
|
|
errcode=1;
|
|
timeout=0;
|
|
blankresult="";
|
|
while (blankresult != "true") {
|
|
systemexec(TQString(TRINITY_BIN_PREFIX "tdmctl -g activate %1").arg(udisplay));
|
|
systemexec(TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface enable true\"").arg(smartcard_username).arg(udisplay));
|
|
systemexec(TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface lock\"").arg(smartcard_username).arg(udisplay));
|
|
int retcode;
|
|
blankresult = execret(TQString("su %1 -c \"export DISPLAY=%2; " TRINITY_BIN_PREFIX "dcop kdesktop KScreensaverIface isBlanked\"").arg(smartcard_username).arg(udisplay), &retcode);
|
|
if (retcode != 0) {
|
|
blankresult="true";
|
|
}
|
|
blankresult = blankresult.replace('\n', "");
|
|
|
|
logouttest = exec(TQString("echo %1 | grep 'target display has no VT assigned'").arg(blankresult));
|
|
if (logouttest != "") {
|
|
printf("[DEBUG 401.6] User has logged out\n"); fflush(stdout);
|
|
blankresult="true";
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
printf("[DEBUG 401.7] Username not specified!\n"); fflush(stdout);
|
|
sleep(1);
|
|
}
|
|
}
|
|
index++;
|
|
}
|
|
// }
|
|
}
|
|
|
|
if (command_mode == "cryptoflex") {
|
|
pclose(opensc_explorer_file);
|
|
}
|
|
|
|
smartcard_username="";
|
|
unlink("/etc/smartmon/minutesremaining");
|
|
systemexec("echo \"C\" > /tmp/tdesocket-global/kdesktoplockcontrol &");
|
|
}
|
|
}
|
|
}
|