/* 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 & " ) ;
}
}
}