/*
* Remote Laboratory Authentication Server
*
* 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 3 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 , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* ( c ) 2012 Timothy Pearson
* Raptor Engineering
* http : //www.raptorengineeringinc.com
*/
# include <stdlib.h>
# include <grp.h>
# include <pwd.h>
# include <tqtimer.h>
# include <tdelocale.h>
# include <tdecmdlineargs.h>
# include "auth_conn.h"
# define STATISTICS_SERVER_START_EVENT 0
# define STATISTICS_SERVER_STOP_EVENT 1
# define STATISTICS_NEW_CONNECTION_EVENT 2
# define STATISTICS_DISCONNECTION_EVENT 3
/* exception handling */
struct exit_exception {
int c ;
exit_exception ( int c ) : c ( c ) { }
} ;
/*
The AuthSocket class provides a socket that is connected with a client .
For every client that connects to the server , the server creates a new
instance of this class .
*/
AuthSocket : : AuthSocket ( int sock , int serverID , TQObject * parent , const char * name ) :
TDEKerberosServerSocket ( parent , name ) , m_criticalSection ( 0 ) , m_stationID ( - 1 ) , m_bound ( false ) , m_serviceID ( 0 ) , m_serverID ( serverID ) , m_terminationStamp ( 0 ) , m_servActive ( false ) , m_servState ( 0 ) , m_servClientSocket ( NULL ) , m_servClientTimeout ( NULL ) , m_loopTimer ( NULL ) , m_pollTimer ( NULL ) , m_config ( static_cast < AuthServer * > ( parent ) - > m_config ) , m_database ( NULL ) , m_databaseStationsCursor ( NULL ) ,
m_databaseServicesCursor ( NULL ) , m_databaseServiceTypesCursor ( NULL ) , m_databasePermissionsCursor ( NULL ) , m_databaseActivityCursor ( NULL ) , m_databaseStatisticsCursor ( NULL )
{
// Initialize timers
m_kerberosInitTimer = new TQTimer ( ) ;
connect ( m_kerberosInitTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( finishKerberosHandshake ( ) ) ) ;
setServiceName ( " ulab " ) ;
m_loopBuffer . resize ( 8192 ) ; // 8kB
line = 0 ;
connect ( this , SIGNAL ( connectionClosed ( ) ) , SLOT ( connectionClosedHandler ( ) ) ) ;
setSocket ( sock ) ;
if ( connectToDatabase ( ) ! = 0 ) {
exit ( 1 ) ;
}
m_pollTimer = new TQTimer ( ) ;
connect ( m_pollTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( pollFlags ( ) ) ) ;
m_pollTimer - > start ( 0 , TRUE ) ;
}
AuthSocket : : ~ AuthSocket ( ) {
if ( m_kerberosInitTimer ) {
m_kerberosInitTimer - > stop ( ) ;
delete m_kerberosInitTimer ;
m_kerberosInitTimer = NULL ;
}
if ( m_pollTimer ) {
m_pollTimer - > stop ( ) ;
delete m_pollTimer ;
m_pollTimer = NULL ;
}
if ( m_loopTimer ) {
m_loopTimer - > stop ( ) ;
delete m_loopTimer ;
m_loopTimer = NULL ;
}
if ( m_databaseStationsCursor ) {
delete m_databaseStationsCursor ;
}
if ( m_databaseServicesCursor ) {
delete m_databaseServicesCursor ;
}
if ( m_databaseServiceTypesCursor ) {
delete m_databaseServiceTypesCursor ;
}
if ( m_databasePermissionsCursor ) {
delete m_databasePermissionsCursor ;
}
if ( m_databaseActivityCursor ) {
delete m_databaseActivityCursor ;
}
if ( m_databaseStatisticsCursor ) {
delete m_databaseStatisticsCursor ;
}
if ( m_servClientSocket ) {
delete m_servClientSocket ;
}
}
void AuthSocket : : close ( ) {
if ( state ( ) = = TQSocket : : Connected ) {
TDEKerberosServerSocket : : close ( ) ;
connectionClosedHandler ( ) ;
}
}
void AuthSocket : : connectionClosedHandler ( ) {
printf ( " [DEBUG] Connection from %s closed \n \r " , m_remoteHost . ascii ( ) ) ;
updateStatistics ( STATISTICS_DISCONNECTION_EVENT ) ;
// Update database
m_databaseActivityCursor - > select ( TQString ( " station='%1' AND username='%2' AND realmname='%3' AND serviceid=%4 " ) . arg ( m_stationID ) . arg ( m_authenticatedUserName ) . arg ( m_authenticatedRealmName ) . arg ( m_serviceID ) ) ;
if ( m_databaseActivityCursor - > next ( ) ) {
m_databaseActivityCursor - > primeDelete ( ) ;
m_databaseActivityCursor - > del ( true ) ;
}
if ( m_criticalSection > 0 ) {
throw exit_exception ( - 1 ) ;
}
}
void AuthSocket : : initiateKerberosHandshake ( ) {
setUsingKerberos ( true ) ;
m_kerberosInitTimer - > start ( 100 , TRUE ) ;
}
void AuthSocket : : finishKerberosHandshake ( ) {
if ( kerberosStatus ( ) = = TDEKerberosServerSocket : : KerberosInitializing ) {
m_kerberosInitTimer - > start ( 100 , TRUE ) ;
return ;
}
if ( kerberosStatus ( ) = = TDEKerberosServerSocket : : KerberosInUse ) {
TQ_UINT32 magicnum = MAGIC_NUMBER ;
TQ_UINT32 protover = PROTOCOL_VERSION ;
TQDataStream ds ( this ) ;
ds . setPrintableData ( true ) ;
ds < < magicnum ;
ds < < protover ;
writeEndOfFrame ( ) ;
enterCommandLoop ( ) ;
return ;
}
else {
printf ( " [DEBUG] Connection from %s closed due to Kerberos failure \n \r " , m_remoteHost . ascii ( ) ) ; fflush ( stdout ) ;
close ( ) ;
return ;
}
}
int AuthSocket : : servLoop ( ) {
bool transferred_data ;
transferred_data = false ;
if ( m_servActive ) {
TQString command ;
TQDataStream ds ( this ) ;
ds . setPrintableData ( true ) ;
TDEKerberosClientSocket : : KerberosStatus krbstat ;
switch ( m_servState ) {
case 0 :
if ( ! m_servClientTimeout ) {
m_servClientTimeout = new TQTimer ( ) ;
m_servClientTimeout - > start ( 5000 , TRUE ) ;
}
if ( ( m_servClientSocket - > state ( ) = = TQSocket : : Connecting ) | | ( m_servClientSocket - > state ( ) = = TQSocket : : HostLookup ) ) {
if ( ! m_servClientTimeout - > isActive ( ) ) {
m_servClientSocket - > close ( ) ;
ds < < TQString ( " ERRNOTAVL " ) ;
writeEndOfFrame ( ) ;
printf ( " [DEBUG] Connection failed to %s:%d for user %s@%s \n \r " , m_srvServiceHostName . ascii ( ) , m_srvServicePort , m_authenticatedUserName . ascii ( ) , m_authenticatedRealmName . ascii ( ) ) ; fflush ( stdout ) ;
m_servActive = false ;
delete m_servClientTimeout ;
m_servClientTimeout = NULL ;
close ( ) ;
}
}
else {
if ( m_servClientTimeout ) {
m_servClientTimeout - > stop ( ) ;
delete m_servClientTimeout ;
m_servClientTimeout = NULL ;
}
transferred_data = true ;
m_servState = 1 ;
}
break ;
case 1 :
if ( m_servClientSocket - > state ( ) = = TQSocket : : Connected ) {
m_servClientSocket - > setUsingKerberos ( true ) ;
m_servState = 2 ;
}
else {
m_servClientSocket - > close ( ) ;
ds < < TQString ( " ERRNOTAVL " ) ;
writeEndOfFrame ( ) ;
printf ( " [DEBUG] Connection failed to %s:%d for user %s@%s \n \r " , m_srvServiceHostName . ascii ( ) , m_srvServicePort , m_authenticatedUserName . ascii ( ) , m_authenticatedRealmName . ascii ( ) ) ; fflush ( stdout ) ;
m_servActive = false ;
delete m_servClientTimeout ;
m_servClientTimeout = NULL ;
close ( ) ;
}
break ;
case 2 :
krbstat = m_servClientSocket - > kerberosStatus ( ) ;
if ( ( krbstat = = TDEKerberosClientSocket : : KerberosInitializing ) | | ( krbstat = = TDEKerberosClientSocket : : KerberosInUse ) ) {
if ( krbstat = = TDEKerberosClientSocket : : KerberosInUse ) {
transferred_data = true ;
m_servState = 3 ;
}
}
else {
m_servClientSocket - > close ( ) ;
ds < < TQString ( " ERRNOTAVL " ) ;
writeEndOfFrame ( ) ;
printf ( " [DEBUG] Connection failed to %s:%d for user %s@%s due to Kerberos failure \n \r " , m_srvServiceHostName . ascii ( ) , m_srvServicePort , m_authenticatedUserName . ascii ( ) , m_authenticatedRealmName . ascii ( ) ) ; fflush ( stdout ) ;
m_servActive = false ;
delete m_servClientTimeout ;
m_servClientTimeout = NULL ;
close ( ) ;
}
break ;
case 3 :
if ( ! m_servClientTimeout ) {
m_servClientTimeout = new TQTimer ( ) ;
m_servClientTimeout - > start ( 5000 , TRUE ) ;
}
if ( m_servClientSocket - > state ( ) = = TQSocket : : Connected ) {
if ( m_servClientSocket - > canReadFrame ( ) ) {
TQDataStream clientDS ( m_servClientSocket ) ;
clientDS . setPrintableData ( true ) ;
TQString server_reply ;
clientDS > > server_reply ;
m_servClientSocket - > clearFrameTail ( ) ;
if ( server_reply = = " OK " ) {
ds < < TQString ( " OK " ) ;
writeEndOfFrame ( ) ;
transferred_data = true ;
m_servState = 4 ;
}
else {
m_servClientSocket - > close ( ) ;
ds < < TQString ( " ERRNOTAVL " ) ;
writeEndOfFrame ( ) ;
printf ( " [DEBUG] Connection failed to %s:%d for user %s@%s due to remote server returning %s \n \r " , m_srvServiceHostName . ascii ( ) , m_srvServicePort , m_authenticatedUserName . ascii ( ) , m_authenticatedRealmName . ascii ( ) , server_reply . ascii ( ) ) ; fflush ( stdout ) ;
m_servActive = false ;
delete m_servClientTimeout ;
m_servClientTimeout = NULL ;
close ( ) ;
}
}
else {
if ( ! m_servClientTimeout - > isActive ( ) ) {
// Timeout!
m_servClientSocket - > close ( ) ;
ds < < TQString ( " ERRNOTAVL " ) ;
writeEndOfFrame ( ) ;
printf ( " [DEBUG] Connection failed to %s:%d for user %s@%s \n \r " , m_srvServiceHostName . ascii ( ) , m_srvServicePort , m_authenticatedUserName . ascii ( ) , m_authenticatedRealmName . ascii ( ) ) ; fflush ( stdout ) ;
m_servActive = false ;
delete m_servClientTimeout ;
m_servClientTimeout = NULL ;
close ( ) ;
}
}
}
else {
m_servClientSocket - > close ( ) ;
ds < < TQString ( " ERRNOTAVL " ) ;
writeEndOfFrame ( ) ;
printf ( " [DEBUG] Connection failed to %s:%d for user %s@%s \n \r " , m_srvServiceHostName . ascii ( ) , m_srvServicePort , m_authenticatedUserName . ascii ( ) , m_authenticatedRealmName . ascii ( ) ) ; fflush ( stdout ) ;
m_servActive = false ;
delete m_servClientTimeout ;
m_servClientTimeout = NULL ;
close ( ) ;
}
break ;
case 4 :
if ( m_servClientSocket - > state ( ) = = TQSocket : : Connected ) {
TQ_LONG reclen ;
if ( canReadData ( ) ) {
reclen = readBlock ( m_loopBuffer . data ( ) , m_loopBuffer . size ( ) ) ;
if ( reclen > 0 ) {
m_servClientSocket - > writeBlock ( m_loopBuffer . data ( ) , reclen ) ;
m_servClientSocket - > flush ( ) ;
transferred_data = true ;
}
else {
printf ( " [WARNING] Remote server advertised data available but no data was able to be read! \n \r " ) ;
}
}
if ( m_servClientSocket - > canReadData ( ) ) {
reclen = m_servClientSocket - > readBlock ( m_loopBuffer . data ( ) , m_loopBuffer . size ( ) ) ;
if ( reclen > 0 ) {
writeBlock ( m_loopBuffer . data ( ) , reclen ) ;
flush ( ) ;
transferred_data = true ;
}
else {
printf ( " [WARNING] Remote client advertised data available but no data was able to be read! \n \r " ) ;
}
}
}
else {
m_servClientSocket - > close ( ) ;
ds < < TQString ( " ERRNOTAVL " ) ;
writeEndOfFrame ( ) ;
printf ( " [DEBUG] Connection terminated by remote host %s:%d for user %s@%s \n \r " , m_srvServiceHostName . ascii ( ) , m_srvServicePort , m_authenticatedUserName . ascii ( ) , m_authenticatedRealmName . ascii ( ) ) ; fflush ( stdout ) ;
m_servActive = false ;
close ( ) ;
}
break ;
}
}
if ( transferred_data ) {
return 1 ;
}
else {
return 0 ;
}
}
void AuthSocket : : pollFlags ( ) {
if ( ( m_bound ) | | ( m_servActive ) ) {
unsigned long long timestamp = TQDateTime : : currentDateTime ( ) . toTime_t ( ) ;
m_databaseActivityCursor - > select ( TQString ( " station='%1' AND username='%2' AND realmname='%3' AND serviceid=%4 " ) . arg ( m_stationID ) . arg ( m_authenticatedUserName ) . arg ( m_authenticatedRealmName ) . arg ( m_serviceID ) ) ;
if ( m_databaseActivityCursor - > next ( ) ) {
m_terminationStamp = m_databaseActivityCursor - > value ( " terminate " ) . toLongLong ( ) ;
if ( m_terminationStamp > 0 ) {
if ( m_terminationStamp < = timestamp ) {
printf ( " [DEBUG] Got termination request from database (%lld <= %lld) \n \r " , m_terminationStamp , timestamp ) ; fflush ( stdout ) ;
close ( ) ;
}
}
}
}
m_pollTimer - > start ( 1000 , TRUE ) ;
}
void AuthSocket : : updateStatistics ( int eventType ) {
// Update statistics
long long sessionID = - 1 ;
m_databaseActivityCursor - > select ( TQString ( " station='%1' AND username='%2' AND realmname='%3' AND serverid='%4' AND serviceid='%5' " ) . arg ( m_stationID ) . arg ( m_authenticatedUserName ) . arg ( m_authenticatedRealmName ) . arg ( m_serverID ) . arg ( m_serviceID ) ) ;
if ( m_databaseActivityCursor - > next ( ) ) {
sessionID = m_databaseActivityCursor - > value ( " pk " ) . toInt ( ) ;
}
TQString userID = m_authenticatedUserName + " @ " + m_authenticatedRealmName ;
TQSqlRecord * buffer = m_databaseStatisticsCursor - > primeInsert ( ) ;
buffer - > setValue ( " timestamp " , TQDateTime : : currentDateTime ( ) . toTime_t ( ) ) ;
buffer - > setValue ( " eventtypeid " , eventType ) ;
buffer - > setValue ( " serverid " , m_stationID ) ;
buffer - > setValue ( " sessionid " , sessionID ) ;
buffer - > setValue ( " typeid " , m_serviceID ) ;
buffer - > setValue ( " userid " , userID ) ;
m_databaseStatisticsCursor - > insert ( ) ;
}
void AuthSocket : : commandLoop ( ) {
bool transferred_data ;
if ( m_servActive ) {
transferred_data = false ;
if ( servLoop ( ) = = 1 ) {
transferred_data = true ;
}
if ( transferred_data ) {
if ( m_loopTimer ) m_loopTimer - > start ( 0 , TRUE ) ;
}
else {
if ( m_loopTimer ) m_loopTimer - > start ( 100 , TRUE ) ;
}
return ;
}
m_criticalSection + + ;
try {
transferred_data = false ;
if ( state ( ) = = TQSocket : : Connected ) {
if ( canReadFrame ( ) ) {
TQString command ;
TQDataStream ds ( this ) ;
ds . setPrintableData ( true ) ;
transferred_data = true ;
ds > > command ;
clearFrameTail ( ) ;
if ( command ! = " " ) {
printf ( " [DEBUG] Got command %s from user %s@%s \n \r " , command . ascii ( ) , m_authenticatedUserName . ascii ( ) , m_authenticatedRealmName . ascii ( ) ) ; fflush ( stdout ) ;
if ( command = = " LIST " ) {
// Send list of available servers...
m_slist . clear ( ) ;
// Get all stations from the database
m_databaseStationsCursor - > select ( ) ;
while ( m_databaseStationsCursor - > next ( ) ) {
bool authorized = false ;
bool in_use = false ;
bool multi_use = false ;
int ngroups = 0 ;
gid_t * groups ;
struct passwd * pw ;
struct group * gr ;
groups = ( gid_t * ) malloc ( ngroups * sizeof ( gid_t ) ) ;
if ( groups = = NULL ) {
printf ( " [ERROR] Unable to allocate memory \n \r " ) ; fflush ( stdout ) ;
exit ( EXIT_FAILURE ) ;
}
pw = getpwnam ( m_authenticatedUserName . ascii ( ) ) ;
if ( pw = = NULL ) {
printf ( " [WARNING] Unable to get detailed information for user '%s', ignoring \n \r " , m_authenticatedUserName . ascii ( ) ) ; fflush ( stdout ) ;
continue ;
}
if ( getgrouplist ( m_authenticatedUserName . ascii ( ) , pw - > pw_gid , groups , & ngroups ) = = - 1 ) {
free ( groups ) ;
groups = ( gid_t * ) malloc ( ngroups * sizeof ( gid_t ) ) ;
if ( getgrouplist ( m_authenticatedUserName . ascii ( ) , pw - > pw_gid , groups , & ngroups ) = = - 1 ) {
printf ( " [WARNING] Unable to get groups for user '%s', ignoring \n \r " , m_authenticatedUserName . ascii ( ) ) ; fflush ( stdout ) ;
continue ;
}
}
int i ;
m_databasePermissionsCursor - > select ( TQString ( " station=%1 " ) . arg ( m_databaseStationsCursor - > value ( " pk " ) . toInt ( ) ) ) ;
while ( m_databasePermissionsCursor - > next ( ) ) {
for ( i = 0 ; i < ngroups ; i + + ) {
gr = getgrgid ( groups [ i ] ) ;
if ( gr ! = NULL ) {
if ( m_databasePermissionsCursor - > value ( " groupname " ) . toString ( ) = = TQString ( gr - > gr_name ) ) {
authorized = true ;
}
}
}
}
m_databaseActivityCursor - > select ( TQString ( " station=%1 " ) . arg ( m_databaseStationsCursor - > value ( " pk " ) . toInt ( ) ) ) ;
while ( m_databaseActivityCursor - > next ( ) ) {
if ( m_databaseActivityCursor - > value ( " username " ) . toString ( ) ! = " " ) {
in_use = true ;
}
}
if ( authorized ) {
StationType st ;
st . id = m_databaseStationsCursor - > value ( " pk " ) . toInt ( ) ;
st . name = m_databaseStationsCursor - > value ( " name " ) . toString ( ) ;
st . description = m_databaseStationsCursor - > value ( " description " ) . toString ( ) ;
m_databaseServicesCursor - > select ( TQString ( " station=%1 " ) . arg ( m_databaseStationsCursor - > value ( " pk " ) . toInt ( ) ) ) ;
while ( m_databaseServicesCursor - > next ( ) ) {
m_databaseServiceTypesCursor - > select ( TQString ( " serviceid=%1 " ) . arg ( m_databaseServicesCursor - > value ( " servicetype " ) . toInt ( ) ) ) ;
ServiceType svt ;
if ( m_databaseServiceTypesCursor - > next ( ) ) {
svt . type = m_databaseServiceTypesCursor - > value ( " serviceid " ) . toInt ( ) ;
svt . name = m_databaseServiceTypesCursor - > value ( " name " ) . toString ( ) ;
svt . description = m_databaseServiceTypesCursor - > value ( " description " ) . toString ( ) ;
svt . clientLibrary = m_databaseServiceTypesCursor - > value ( " client_library " ) . toString ( ) ;
svt . version = m_databaseServiceTypesCursor - > value ( " version " ) . toInt ( ) ;
char tempchar ;
tempchar = m_databaseServiceTypesCursor - > value ( " single_instance " ) . toInt ( ) ;
svt . singleInstance = ( tempchar ! = 0 ) ;
if ( ! svt . singleInstance ) multi_use = true ;
}
if ( svt . name = = " " ) {
svt . name = i18n ( " <unknown> " ) ;
}
if ( svt . description = = " " ) {
svt . description = i18n ( " <unknown> " ) ;
}
st . services . append ( svt ) ;
}
if ( ( ! in_use ) | | ( multi_use ) ) {
m_slist . append ( st ) ;
}
}
}
ds < < m_slist ;
writeEndOfFrame ( ) ;
}
else if ( command = = " BIND " ) {
// Get desired Station Type from client
StationType st ;
ds > > st ;
clearFrameTail ( ) ;
// Attempt to bind to station matching desired Service Type list...
m_stationID = - 1 ;
// Ensure that this user is not already connected
int activeID = - 1 ;
m_databaseActivityCursor - > select ( TQString ( " username='%1' AND realmname='%2' " ) . arg ( m_authenticatedUserName ) . arg ( m_authenticatedRealmName ) ) ;
if ( m_databaseActivityCursor - > next ( ) ) {
activeID = m_databaseActivityCursor - > value ( " station " ) . toInt ( ) ;
}
if ( activeID < 0 ) {
for ( StationList : : Iterator it ( m_slist . begin ( ) ) ; it ! = m_slist . end ( ) ; + + it ) {
if ( ( * it ) . services = = st . services ) {
m_stationID = ( * it ) . id ;
break ;
}
}
if ( m_stationID < 0 ) {
ds < < TQString ( " ERRUNAVAL " ) ;
writeEndOfFrame ( ) ;
}
else {
m_bound = true ;
m_serviceID = 0 ;
// Update database
TQSqlRecord * buffer = m_databaseActivityCursor - > primeInsert ( ) ;
buffer - > setValue ( " station " , m_stationID ) ;
buffer - > setValue ( " username " , m_authenticatedUserName ) ;
buffer - > setValue ( " realmname " , m_authenticatedRealmName ) ;
buffer - > setValue ( " logontime " , TQDateTime : : currentDateTime ( ) . toTime_t ( ) ) ;
buffer - > setValue ( " serverid " , m_serverID ) ;
buffer - > setValue ( " serviceid " , m_serviceID ) ;
buffer - > setValue ( " terminate " , 0 ) ;
m_databaseActivityCursor - > insert ( ) ;
updateStatistics ( STATISTICS_NEW_CONNECTION_EVENT ) ;
ds < < TQString ( " OK " ) ;
writeEndOfFrame ( ) ;
}
}
else {
ds < < TQString ( " ERRPREVCN " ) ;
writeEndOfFrame ( ) ;
}
}
else if ( command = = " SERV " ) {
// Get client library name from the client
TQString libname ;
ds > > libname ;
clearFrameTail ( ) ;
printf ( " [DEBUG] SERV command parameter was %s from user %s@%s \n \r " , libname . ascii ( ) , m_authenticatedUserName . ascii ( ) , m_authenticatedRealmName . ascii ( ) ) ; fflush ( stdout ) ;
m_databaseActivityCursor - > select ( TQString ( " username='%1' AND realmname='%2' AND serviceid=0 " ) . arg ( m_authenticatedUserName ) . arg ( m_authenticatedRealmName ) ) ;
if ( m_databaseActivityCursor - > next ( ) ) {
m_stationID = m_databaseActivityCursor - > value ( " station " ) . toInt ( ) ;
}
if ( m_bound = = true ) {
ds < < TQString ( " ERRINVCMD " ) ;
writeEndOfFrame ( ) ;
}
else {
if ( m_stationID < 0 ) {
ds < < TQString ( " ERRNOCONN " ) ;
writeEndOfFrame ( ) ;
}
else {
// Find the service ID for the specified client library name
TQInt32List sidList ;
m_databaseServiceTypesCursor - > select ( TQString ( " client_library='%1' " ) . arg ( libname ) ) ;
if ( m_databaseServiceTypesCursor - > next ( ) ) {
sidList . append ( m_databaseServiceTypesCursor - > value ( " serviceid " ) . toInt ( ) ) ;
}
if ( sidList . empty ( ) ) {
ds < < TQString ( " ERRNOSERV " ) ;
writeEndOfFrame ( ) ;
}
else {
// Attempt to connect to the backend server
TQ_INT32 sid = - 1 ;
while ( 1 ) {
m_databaseServicesCursor - > select ( TQString ( " servicetype=%1 AND station=%2 " ) . arg ( sidList [ 0 ] ) . arg ( m_stationID ) ) ;
if ( m_databaseServicesCursor - > next ( ) ) {
sid = sidList [ 0 ] ;
break ;
}
sidList . remove ( sidList . at ( 0 ) ) ;
if ( sidList . isEmpty ( ) ) {
break ;
}
}
if ( sid ! = - 1 ) {
// Enforce single instance flags
bool available = true ;
m_databaseServiceTypesCursor - > select ( TQString ( " serviceid=%1 " ) . arg ( sid ) ) ;
if ( m_databaseServiceTypesCursor - > next ( ) ) {
char tempchar ;
tempchar = m_databaseServiceTypesCursor - > value ( " single_instance " ) . toInt ( ) ;
if ( tempchar ! = 0 ) {
// Verify that service is not already in use
m_databaseActivityCursor - > select ( TQString ( " station=%1 AND serviceid=%2 " ) . arg ( m_stationID ) . arg ( sid ) ) ;
while ( m_databaseActivityCursor - > next ( ) ) {
if ( m_databaseActivityCursor - > value ( " username " ) . toString ( ) ! = " " ) {
available = false ;
}
}
}
}
if ( available ) {
m_srvServiceHostName = m_databaseServicesCursor - > value ( " hostname " ) . toString ( ) ;
m_srvServicePort = m_databaseServicesCursor - > value ( " port " ) . toInt ( ) ;
// Update database
m_serviceID = sid ;
TQSqlRecord * buffer = m_databaseActivityCursor - > primeInsert ( ) ;
buffer - > setValue ( " station " , m_stationID ) ;
buffer - > setValue ( " username " , m_authenticatedUserName ) ;
buffer - > setValue ( " realmname " , m_authenticatedRealmName ) ;
buffer - > setValue ( " logontime " , TQDateTime : : currentDateTime ( ) . toTime_t ( ) ) ;
buffer - > setValue ( " serverid " , m_serverID ) ;
buffer - > setValue ( " serviceid " , m_serviceID ) ;
buffer - > setValue ( " terminate " , 0 ) ;
m_databaseActivityCursor - > insert ( ) ;
updateStatistics ( STATISTICS_NEW_CONNECTION_EVENT ) ;
if ( ! m_servClientSocket ) m_servClientSocket = new TDEKerberosClientSocket ;
m_servClientSocket - > setServiceName ( " ulab " ) ;
m_servClientSocket - > setServerFQDN ( m_srvServiceHostName ) ;
m_servClientSocket - > connectToHost ( m_srvServiceHostName , m_srvServicePort ) ;
m_servState = 0 ;
m_servActive = true ;
}
else {
ds < < TQString ( " ERRNOSERV " ) ;
writeEndOfFrame ( ) ;
}
}
else {
ds < < TQString ( " ERRNOSERV " ) ;
writeEndOfFrame ( ) ;
}
}
}
}
}
else if ( command = = " TSTP " ) {
ds < < m_terminationStamp ;
writeEndOfFrame ( ) ;
}
else {
ds < < TQString ( " ERRINVCMD " ) ;
writeEndOfFrame ( ) ;
}
}
}
m_criticalSection - - ;
if ( transferred_data ) {
if ( m_loopTimer ) m_loopTimer - > start ( 0 , TRUE ) ;
}
else {
if ( m_loopTimer ) m_loopTimer - > start ( 100 , TRUE ) ;
}
return ;
}
}
catch ( . . . ) {
m_criticalSection - - ;
return ;
}
}
int AuthSocket : : enterCommandLoop ( ) {
if ( ! m_loopTimer ) {
m_loopTimer = new TQTimer ( ) ;
connect ( m_loopTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( commandLoop ( ) ) ) ;
}
if ( m_loopTimer ) m_loopTimer - > start ( 0 , TRUE ) ;
return 0 ;
}
int AuthSocket : : connectToDatabase ( ) {
if ( m_database ) {
return - 2 ;
}
m_database = TQSqlDatabase : : database ( ) ;
if ( ! m_database ) {
printf ( " [ERROR] Database was not constructed by the application \n \r " ) ; fflush ( stdout ) ;
return - 1 ;
}
m_databaseStationsCursor = new TQSqlCursor ( " stations " , TRUE , m_database ) ;
m_databaseServicesCursor = new TQSqlCursor ( " services " , TRUE , m_database ) ;
m_databaseServiceTypesCursor = new TQSqlCursor ( " servicetypes " , TRUE , m_database ) ;
m_databasePermissionsCursor = new TQSqlCursor ( " permissions " , TRUE , m_database ) ;
m_databaseActivityCursor = new TQSqlCursor ( " activity " , TRUE , m_database ) ;
m_databaseStatisticsCursor = new TQSqlCursor ( " statistics " , TRUE , m_database ) ;
return 0 ;
}
/*
The AuthServer class handles new connections to the server . For every
client that connects , it creates a new AuthSocket - - that instance is now
responsible for the communication with that client .
*/
AuthServer : : AuthServer ( TQObject * parent ) :
TQServerSocket ( 4004 , 1 , parent ) , m_database ( NULL ) {
m_config = new KSimpleConfig ( " ulab_authserver.conf " , false ) ;
if ( connectToDatabase ( ) ! = 0 ) {
exit ( 1 ) ;
}
m_serverID = 0 ;
TDECmdLineArgs * const args = TDECmdLineArgs : : parsedArgs ( ) ;
if ( ( args ) & & ( args - > count ( ) > 0 ) ) {
m_serverID = TQString ( args - > arg ( 0 ) ) . toInt ( ) ;
}
// Delete existing activity entries for this server ID
TQSqlCursor databaseActivityCursor ( " activity " , TRUE , m_database ) ;
databaseActivityCursor . select ( TQString ( " serverid='%1' " ) . arg ( m_serverID ) ) ;
while ( databaseActivityCursor . next ( ) ) {
databaseActivityCursor . primeDelete ( ) ;
databaseActivityCursor . del ( false ) ;
}
// Update statistics
TQSqlCursor databaseStatisticsCursor ( " statistics " , TRUE , m_database ) ;
TQSqlRecord * buffer = databaseStatisticsCursor . primeInsert ( ) ;
buffer - > setValue ( " timestamp " , TQDateTime : : currentDateTime ( ) . toTime_t ( ) ) ;
buffer - > setValue ( " eventtypeid " , STATISTICS_SERVER_START_EVENT ) ;
databaseStatisticsCursor . insert ( ) ;
if ( ! ok ( ) ) {
printf ( " [ERROR] Failed to bind to port 4004 \n \r " ) ;
exit ( 1 ) ;
}
printf ( " [INFO] Server started on port 4004 \n \r " ) ; fflush ( stdout ) ;
}
AuthServer : : ~ AuthServer ( ) {
if ( m_sqlPingTimer ) {
m_sqlPingTimer - > stop ( ) ;
delete m_sqlPingTimer ;
m_sqlPingTimer = NULL ;
}
// Update statistics
TQSqlCursor databaseStatisticsCursor ( " statistics " , TRUE , m_database ) ;
TQSqlRecord * buffer = databaseStatisticsCursor . primeInsert ( ) ;
buffer - > setValue ( " timestamp " , TQDateTime : : currentDateTime ( ) . toTime_t ( ) ) ;
buffer - > setValue ( " eventtypeid " , STATISTICS_SERVER_STOP_EVENT ) ;
databaseStatisticsCursor . insert ( ) ;
if ( m_database ) {
TQSqlDatabase : : removeDatabase ( m_database ) ;
m_database = NULL ;
}
delete m_config ;
}
int AuthServer : : connectToDatabase ( ) {
m_config - > setGroup ( " Database " ) ;
m_database = TQSqlDatabase : : addDatabase ( m_config - > readEntry ( " driver " ) ) ;
m_database - > setDatabaseName ( m_config - > readEntry ( " database " ) ) ;
m_database - > setUserName ( m_config - > readEntry ( " username " ) ) ;
m_database - > setPassword ( m_config - > readEntry ( " password " ) ) ;
m_database - > setHostName ( m_config - > readEntry ( " server " ) ) ;
if ( ! m_database - > open ( ) ) {
printf ( " [ERROR] Failed to connect to control database on server '%s' [%s] \n \r " , m_database - > hostName ( ) . ascii ( ) , m_database - > lastError ( ) . text ( ) . ascii ( ) ) ; fflush ( stdout ) ;
TQSqlDatabase : : removeDatabase ( m_database ) ;
m_database = NULL ;
return - 1 ;
}
if ( ! m_database - > tables ( ) . contains ( " stations " ) ) {
m_database - > close ( ) ;
printf ( " [ERROR] Control database '%s' on '%s' does not contain the required 'stations' table \n \r " , m_database - > databaseName ( ) . ascii ( ) , m_database - > hostName ( ) . ascii ( ) ) ; fflush ( stdout ) ;
TQSqlDatabase : : removeDatabase ( m_database ) ;
m_database = NULL ;
return - 1 ;
}
if ( ! m_database - > tables ( ) . contains ( " services " ) ) {
m_database - > close ( ) ;
printf ( " [ERROR] Control database '%s' on '%s' does not contain the required 'services' table \n \r " , m_database - > databaseName ( ) . ascii ( ) , m_database - > hostName ( ) . ascii ( ) ) ; fflush ( stdout ) ;
TQSqlDatabase : : removeDatabase ( m_database ) ;
m_database = NULL ;
return - 1 ;
}
if ( ! m_database - > tables ( ) . contains ( " servicetypes " ) ) {
m_database - > close ( ) ;
printf ( " [ERROR] Control database '%s' on '%s' does not contain the required 'servicetypes' table \n \r " , m_database - > databaseName ( ) . ascii ( ) , m_database - > hostName ( ) . ascii ( ) ) ; fflush ( stdout ) ;
TQSqlDatabase : : removeDatabase ( m_database ) ;
m_database = NULL ;
return - 1 ;
}
if ( ! m_database - > tables ( ) . contains ( " permissions " ) ) {
m_database - > close ( ) ;
printf ( " [ERROR] Control database '%s' on '%s' does not contain the required 'permissions' table \n \r " , m_database - > databaseName ( ) . ascii ( ) , m_database - > hostName ( ) . ascii ( ) ) ; fflush ( stdout ) ;
TQSqlDatabase : : removeDatabase ( m_database ) ;
m_database = NULL ;
return - 1 ;
}
if ( ! m_database - > tables ( ) . contains ( " activity " ) ) {
m_database - > close ( ) ;
printf ( " [ERROR] Control database '%s' on '%s' does not contain the required 'activity' table \n \r " , m_database - > databaseName ( ) . ascii ( ) , m_database - > hostName ( ) . ascii ( ) ) ; fflush ( stdout ) ;
TQSqlDatabase : : removeDatabase ( m_database ) ;
m_database = NULL ;
return - 1 ;
}
// FIXME
// We currently have no way to handle something as simple as the database server going offline!
// Start database ping process
m_sqlPingTimer = new TQTimer ( ) ;
connect ( m_sqlPingTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( pingSQLServer ( ) ) ) ;
m_sqlPingTimer - > start ( 60 * 1000 ) ;
return 0 ;
}
void AuthServer : : pingSQLServer ( ) {
// FIXME
// We might as well gather statistics here...
TQSqlQuery query ;
query . exec ( " SELECT * FROM activity " ) ;
}
void AuthServer : : newConnection ( int socket ) {
AuthSocket * s = new AuthSocket ( socket , m_serverID , this ) ;
s - > m_remoteHost = s - > peerAddress ( ) . toString ( ) ;
printf ( " [DEBUG] New connection from %s \n \r " , s - > m_remoteHost . ascii ( ) ) ;
connect ( s , SIGNAL ( connectionClosed ( ) ) , s , SLOT ( deleteLater ( ) ) ) ;
s - > initiateKerberosHandshake ( ) ;
emit newConnect ( s ) ;
}