@ -15,13 +15,20 @@
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
*
* ( c ) 2012 - 201 3 Timothy Pearson
* ( c ) 2012 - 201 4 Timothy Pearson
* Raptor Engineering
* Raptor Engineering
* http : //www.raptorengineeringinc.com
* http : //www.raptorengineeringinc.com
*/
*/
# include <stdlib.h>
# include <stdlib.h>
// getLocalMachineFQDN
# include <unistd.h>
# include <netdb.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <grp.h>
# include <grp.h>
# include <pwd.h>
# include <pwd.h>
@ -37,6 +44,8 @@
# define STATISTICS_NEW_CONNECTION_EVENT 2
# define STATISTICS_NEW_CONNECTION_EVENT 2
# define STATISTICS_DISCONNECTION_EVENT 3
# define STATISTICS_DISCONNECTION_EVENT 3
# define DB_SCHEMA_VERSION 1
/* exception handling */
/* exception handling */
struct exit_exception {
struct exit_exception {
int c ;
int c ;
@ -48,8 +57,8 @@ struct exit_exception {
For every client that connects to the server , the server creates a new
For every client that connects to the server , the server creates a new
instance of this class .
instance of this class .
*/
*/
AuthSocket : : AuthSocket ( int sock , int serverID , TQObject * parent , const char * name ) :
AuthSocket : : AuthSocket ( int sock , TQString localMachineFQDN , TQObject * parent , const char * name ) :
TDEKerberosServerSocket ( parent , name ) , m_criticalSection ( 0 ) , m_stationID ( - 1 ) , m_bound ( false ) , m_serviceID ( 0 ) , m_ serverID( serverID ) , m_pollInterval ( 10 ) , 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 ) ,
TDEKerberosServerSocket ( parent , name ) , m_criticalSection ( 0 ) , m_stationID ( - 1 ) , m_bound ( false ) , m_serviceID ( 0 ) , m_ localMachineFQDN( localMachineFQDN ) , m_pollInterval ( 10 ) , 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 ) , m_databaseStatusCursor ( NULL )
m_databaseServicesCursor ( NULL ) , m_databaseServiceTypesCursor ( NULL ) , m_databasePermissionsCursor ( NULL ) , m_databaseActivityCursor ( NULL ) , m_databaseStatisticsCursor ( NULL ) , m_databaseStatusCursor ( NULL )
{
{
// Read settings
// Read settings
@ -368,7 +377,7 @@ void AuthSocket::pollFlags() {
void AuthSocket : : updateStatistics ( int eventType ) {
void AuthSocket : : updateStatistics ( int eventType ) {
// Update statistics
// Update statistics
long long sessionID = - 1 ;
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 ) ) ;
m_databaseActivityCursor - > select ( TQString ( " station='%1' AND username='%2' AND realmname='%3' AND arbiter ='%4' AND serviceid='%5'" ) . arg ( m_stationID ) . arg ( m_authenticatedUserName ) . arg ( m_authenticatedRealmName ) . arg ( m_ localMachineFQDN ) . arg ( m_serviceID ) ) ;
if ( m_databaseActivityCursor - > next ( ) ) {
if ( m_databaseActivityCursor - > next ( ) ) {
sessionID = m_databaseActivityCursor - > value ( " pk " ) . toInt ( ) ;
sessionID = m_databaseActivityCursor - > value ( " pk " ) . toInt ( ) ;
}
}
@ -376,7 +385,8 @@ void AuthSocket::updateStatistics(int eventType) {
TQSqlRecord * buffer = m_databaseStatisticsCursor - > primeInsert ( ) ;
TQSqlRecord * buffer = m_databaseStatisticsCursor - > primeInsert ( ) ;
buffer - > setValue ( " timestamp " , TQDateTime : : currentDateTime ( ) . toTime_t ( ) ) ;
buffer - > setValue ( " timestamp " , TQDateTime : : currentDateTime ( ) . toTime_t ( ) ) ;
buffer - > setValue ( " eventtypeid " , eventType ) ;
buffer - > setValue ( " eventtypeid " , eventType ) ;
buffer - > setValue ( " serverid " , m_stationID ) ;
buffer - > setValue ( " arbiter " , m_localMachineFQDN ) ;
buffer - > setValue ( " stationid " , m_stationID ) ;
buffer - > setValue ( " sessionid " , sessionID ) ;
buffer - > setValue ( " sessionid " , sessionID ) ;
buffer - > setValue ( " typeid " , m_serviceID ) ;
buffer - > setValue ( " typeid " , m_serviceID ) ;
buffer - > setValue ( " userid " , userID ) ;
buffer - > setValue ( " userid " , userID ) ;
@ -554,10 +564,10 @@ void AuthSocket::commandLoop() {
// Update database
// Update database
TQSqlRecord * buffer = m_databaseActivityCursor - > primeInsert ( ) ;
TQSqlRecord * buffer = m_databaseActivityCursor - > primeInsert ( ) ;
buffer - > setValue ( " station " , m_stationID ) ;
buffer - > setValue ( " station " , m_stationID ) ;
buffer - > setValue ( " arbiter " , m_localMachineFQDN ) ;
buffer - > setValue ( " username " , m_authenticatedUserName ) ;
buffer - > setValue ( " username " , m_authenticatedUserName ) ;
buffer - > setValue ( " realmname " , m_authenticatedRealmName ) ;
buffer - > setValue ( " realmname " , m_authenticatedRealmName ) ;
buffer - > setValue ( " logontime " , TQDateTime : : currentDateTime ( ) . toTime_t ( ) ) ;
buffer - > setValue ( " logontime " , TQDateTime : : currentDateTime ( ) . toTime_t ( ) ) ;
buffer - > setValue ( " serverid " , m_serverID ) ;
buffer - > setValue ( " serviceid " , m_serviceID ) ;
buffer - > setValue ( " serviceid " , m_serviceID ) ;
buffer - > setValue ( " terminate " , 0 ) ;
buffer - > setValue ( " terminate " , 0 ) ;
m_databaseActivityCursor - > insert ( ) ;
m_databaseActivityCursor - > insert ( ) ;
@ -645,10 +655,10 @@ void AuthSocket::commandLoop() {
m_serviceID = sid ;
m_serviceID = sid ;
TQSqlRecord * buffer = m_databaseActivityCursor - > primeInsert ( ) ;
TQSqlRecord * buffer = m_databaseActivityCursor - > primeInsert ( ) ;
buffer - > setValue ( " station " , m_stationID ) ;
buffer - > setValue ( " station " , m_stationID ) ;
buffer - > setValue ( " arbiter " , m_localMachineFQDN ) ;
buffer - > setValue ( " username " , m_authenticatedUserName ) ;
buffer - > setValue ( " username " , m_authenticatedUserName ) ;
buffer - > setValue ( " realmname " , m_authenticatedRealmName ) ;
buffer - > setValue ( " realmname " , m_authenticatedRealmName ) ;
buffer - > setValue ( " logontime " , TQDateTime : : currentDateTime ( ) . toTime_t ( ) ) ;
buffer - > setValue ( " logontime " , TQDateTime : : currentDateTime ( ) . toTime_t ( ) ) ;
buffer - > setValue ( " serverid " , m_serverID ) ;
buffer - > setValue ( " serviceid " , m_serviceID ) ;
buffer - > setValue ( " serviceid " , m_serviceID ) ;
buffer - > setValue ( " terminate " , 0 ) ;
buffer - > setValue ( " terminate " , 0 ) ;
m_databaseActivityCursor - > insert ( ) ;
m_databaseActivityCursor - > insert ( ) ;
@ -745,21 +755,32 @@ int AuthSocket::connectToDatabase() {
AuthServer : : AuthServer ( TQObject * parent ) :
AuthServer : : AuthServer ( TQObject * parent ) :
TQServerSocket ( 4004 , 1 , parent ) , m_database ( NULL ) {
TQServerSocket ( 4004 , 1 , parent ) , m_database ( NULL ) {
m_localMachineFQDN = getLocalMachineFQDN ( ) ;
m_config = new KSimpleConfig ( " ulab_authserver.conf " , false ) ;
m_config = new KSimpleConfig ( " ulab_authserver.conf " , false ) ;
if ( connectToDatabase ( ) ! = 0 ) {
if ( connectToDatabase ( ) ! = 0 ) {
exit ( 1 ) ;
exit ( 1 ) ;
}
}
m_serverID = 0 ;
// Verify schema version
TDECmdLineArgs * const args = TDECmdLineArgs : : parsedArgs ( ) ;
bool schemaValid = 0 ;
if ( ( args ) & & ( args - > count ( ) > 0 ) ) {
uint schemaVersion = 0 ;
m_serverID = TQString ( args - > arg ( 0 ) ) . toInt ( ) ;
TQSqlCursor databaseDBSchemaCursor ( " dbschema " , TRUE , m_database ) ;
databaseDBSchemaCursor . select ( TQString ( " skey='revision' " ) ) ;
if ( databaseDBSchemaCursor . next ( ) ) {
schemaVersion = databaseDBSchemaCursor . value ( " value " ) . toUInt ( ) ;
if ( schemaVersion = = DB_SCHEMA_VERSION ) {
schemaValid = 1 ;
}
}
if ( ! schemaValid ) {
printf ( " [ERROR] Schema version not present or incorrect (got %d expected %d) \n \r " , schemaVersion , DB_SCHEMA_VERSION ) ;
exit ( 1 ) ;
}
}
// Delete existing activity entries for this server ID
// Delete existing activity entries for this server ID
TQSqlCursor databaseActivityCursor ( " activity " , TRUE , m_database ) ;
TQSqlCursor databaseActivityCursor ( " activity " , TRUE , m_database ) ;
databaseActivityCursor . select ( TQString ( " serverid='%1' " ) . arg ( m_serverID ) ) ;
databaseActivityCursor . select ( TQString ( " arbiter='%1'" ) . arg ( m_localMachineFQDN ) ) ;
while ( databaseActivityCursor . next ( ) ) {
while ( databaseActivityCursor . next ( ) ) {
databaseActivityCursor . primeDelete ( ) ;
databaseActivityCursor . primeDelete ( ) ;
databaseActivityCursor . del ( false ) ;
databaseActivityCursor . del ( false ) ;
@ -805,12 +826,17 @@ AuthServer::~AuthServer() {
int AuthServer : : connectToDatabase ( ) {
int AuthServer : : connectToDatabase ( ) {
m_config - > setGroup ( " Database " ) ;
m_config - > setGroup ( " Database " ) ;
m_database = TQSqlDatabase : : addDatabase ( m_config - > readEntry ( " driver " ) ) ;
TQString databaseDriver = m_config - > readEntry ( " driver " ) ;
m_database = TQSqlDatabase : : addDatabase ( databaseDriver ) ;
m_database - > setDatabaseName ( m_config - > readEntry ( " database " ) ) ;
m_database - > setDatabaseName ( m_config - > readEntry ( " database " ) ) ;
m_database - > setUserName ( m_config - > readEntry ( " username " ) ) ;
m_database - > setUserName ( m_config - > readEntry ( " username " ) ) ;
m_database - > setPassword ( m_config - > readEntry ( " password " ) ) ;
m_database - > setPassword ( m_config - > readEntry ( " password " ) ) ;
m_database - > setHostName ( m_config - > readEntry ( " server " ) ) ;
m_database - > setHostName ( m_config - > readEntry ( " server " ) ) ;
if ( databaseDriver . contains ( " MYSQL " ) ) {
m_database - > setConnectOptions ( " MYSQL_OPT_RECONNECT " ) ;
}
if ( ! m_database - > open ( ) ) {
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 ) ;
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 ) ;
TQSqlDatabase : : removeDatabase ( m_database ) ;
@ -858,10 +884,8 @@ int AuthServer::connectToDatabase() {
return - 1 ;
return - 1 ;
}
}
// FIXME
// We currently have no way to handle something as simple as the database server going offline!
// Start database ping process
// Start database ping process
// When combined with the MYSQL_OPT_RECONNECT flag passed above, this will keep the connection open even if the database server goes offline and then comes back online
m_sqlPingTimer = new TQTimer ( ) ;
m_sqlPingTimer = new TQTimer ( ) ;
connect ( m_sqlPingTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( pingSQLServer ( ) ) ) ;
connect ( m_sqlPingTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( pingSQLServer ( ) ) ) ;
m_sqlPingTimer - > start ( 60 * 1000 ) ;
m_sqlPingTimer - > start ( 60 * 1000 ) ;
@ -870,14 +894,35 @@ int AuthServer::connectToDatabase() {
}
}
void AuthServer : : pingSQLServer ( ) {
void AuthServer : : pingSQLServer ( ) {
// FIXME
if ( m_database ) {
// We might as well gather statistics here...
m_database - > ping ( ) ;
TQSqlQuery query ;
}
query . exec ( " SELECT * FROM activity " ) ;
}
TQString AuthServer : : getLocalMachineFQDN ( ) {
struct addrinfo hints , * res ;
int err ;
char hostname [ 1024 ] ;
hostname [ 1023 ] = ' \0 ' ;
gethostname ( hostname , 1023 ) ;
memset ( & hints , 0 , sizeof hints ) ;
hints . ai_socktype = SOCK_STREAM ;
hints . ai_family = AF_UNSPEC ;
hints . ai_flags = AI_CANONNAME ;
if ( ( err = getaddrinfo ( hostname , NULL , & hints , & res ) ) ! = 0 ) {
return TQString : : null ;
}
TQString ret ( res - > ai_canonname ) ;
freeaddrinfo ( res ) ;
return ret ;
}
}
void AuthServer : : newConnection ( int socket ) {
void AuthServer : : newConnection ( int socket ) {
AuthSocket * s = new AuthSocket ( socket , m_serverID , this ) ;
AuthSocket * s = new AuthSocket ( socket , m_ localMachineFQDN , this ) ;
s - > m_remoteHost = s - > peerAddress ( ) . toString ( ) ;
s - > m_remoteHost = s - > peerAddress ( ) . toString ( ) ;
printf ( " [DEBUG] New connection from %s \n \r " , s - > m_remoteHost . ascii ( ) ) ;
printf ( " [DEBUG] New connection from %s \n \r " , s - > m_remoteHost . ascii ( ) ) ;
connect ( s , SIGNAL ( connectionClosed ( ) ) , s , SLOT ( deleteLater ( ) ) ) ;
connect ( s , SIGNAL ( connectionClosed ( ) ) , s , SLOT ( deleteLater ( ) ) ) ;