@ -24,11 +24,14 @@
# include <tqapplication.h>
# include <tqbuffer.h>
# include <tqeventloop.h>
# include <tqtimer.h>
# include <sasl.h>
# include <saslplug.h>
# include <saslutil.h>
# include <klocale.h>
# include "tdekrbserversocket.h"
# define NET_SEC_BUF_SIZE (2048)
@ -94,7 +97,7 @@ static int logSASLMessages(void *context __attribute__((unused)), int priority,
return SASL_OK ;
}
TDEKerberosServerSocket : : TDEKerberosServerSocket ( TQObject * parent , const char * name ) : TQSocket ( parent , name ) , m_kerberosRequested ( false ) , m_criticalSection ( 0 ) , m_bufferLength ( 0 ) , m_ canary( NULL ) , m_negotiatedMaxBufferSize ( NET_SEC_BUF_SIZE ) {
TDEKerberosServerSocket : : TDEKerberosServerSocket ( TQObject * parent , const char * name ) : TQSocket ( parent , name ) , m_kerberosRequested ( false ) , m_criticalSection ( 0 ) , m_bufferLength ( 0 ) , m_ krbInitRunning( false ) , m_krbInitState ( - 1 ) , m_dataTimeout ( - 1 ) , m_ canary( NULL ) , m_negotiatedMaxBufferSize ( NET_SEC_BUF_SIZE ) {
saslData = new SASLDataPrivate ;
saslData - > m_krbConnection = NULL ;
m_buffer = new TQBuffer ( ) ;
@ -110,7 +113,12 @@ TDEKerberosServerSocket::~TDEKerberosServerSocket() {
delete saslData ;
}
void TDEKerberosServerSocket : : setDataTimeout ( int timeoutms ) {
m_dataTimeout = timeoutms ;
}
bool TDEKerberosServerSocket : : open ( int mode ) {
setStatusMessage ( i18n ( " Opening socket " ) ) ;
bool ret = TQSocket : : open ( mode ) ;
if ( m_kerberosRequested ) {
initializeKerberosInterface ( ) ;
@ -120,6 +128,7 @@ bool TDEKerberosServerSocket::open(int mode) {
void TDEKerberosServerSocket : : close ( ) {
TQSocket : : close ( ) ;
setStatusMessage ( i18n ( " Socket closed " ) ) ;
}
void TDEKerberosServerSocket : : flush ( ) {
@ -452,8 +461,12 @@ int TDEKerberosServerSocket::getSASLDataFromNetwork(char *buf, int trunclen, boo
}
len = 0 ;
while ( 1 ) {
if ( shouldblock ) {
TQTimer dataTimeoutTimer ;
if ( m_dataTimeout > 0 ) {
dataTimeoutTimer . start ( m_dataTimeout , TRUE ) ;
}
while ( dataTimeoutTimer . isActive ( ) | | ( m_dataTimeout < 0 ) ) {
if ( ( shouldblock ) & & ( dataTimeoutTimer . isActive ( ) | | ( m_dataTimeout < 0 ) ) ) {
SAFELY_PROCESS_EVENTS
}
if ( state ( ) ! = TQSocket : : Connected ) {
@ -468,10 +481,13 @@ int TDEKerberosServerSocket::getSASLDataFromNetwork(char *buf, int trunclen, boo
if ( ba . data ( ) [ len ] ! = ' \r ' ) {
len + + ;
}
if ( m_dataTimeout > 0 ) {
dataTimeoutTimer . stop ( ) ;
dataTimeoutTimer . start ( m_dataTimeout , TRUE ) ;
}
}
else {
if ( shouldblock ) {
usleep ( 1000 ) ;
}
else {
@ -508,9 +524,14 @@ int TDEKerberosServerSocket::transmitEncryptedData(int fd, const char* readbuf,
long data_remaining ;
long remnant_position ;
TQTimer dataTimeoutTimer ;
if ( m_dataTimeout > 0 ) {
dataTimeoutTimer . start ( m_dataTimeout , TRUE ) ;
}
data_remaining = cc ;
remnant_position = 0 ;
while ( data_remaining > 0 ) {
while ( ( data_remaining > 0 ) & & ( dataTimeoutTimer . isActive ( ) | | ( m_dataTimeout < 0 ) ) ) {
int data_to_write_len ;
if ( data_remaining > ( m_negotiatedMaxBufferSize / 2 ) ) {
data_to_write_len = m_negotiatedMaxBufferSize / 2 ;
@ -526,7 +547,7 @@ int TDEKerberosServerSocket::transmitEncryptedData(int fd, const char* readbuf,
sendSASLDataToNetwork ( data , len , fd ) ;
data_remaining = data_remaining - data_to_write_len ;
remnant_position = remnant_position + data_to_write_len ;
if ( data_remaining > 0 ) {
if ( ( data_remaining > 0 ) & & ( dataTimeoutTimer . isActive ( ) | | ( m_dataTimeout < 0 ) ) ) {
SAFELY_PROCESS_EVENTS
}
}
@ -562,6 +583,185 @@ int TDEKerberosServerSocket::receiveEncryptedData(char *buf, unsigned int truncl
return recv_len ;
}
TDEKerberosServerSocket : : KerberosStatus TDEKerberosServerSocket : : kerberosStatus ( ) const {
if ( ! m_kerberosRequested ) {
return KerberosNotRequested ;
}
if ( m_krbInitRunning ) {
return KerberosInitializing ;
}
if ( m_krbInitState < 0 ) {
return KerberosFailure ;
}
return KerberosInUse ;
}
void TDEKerberosServerSocket : : setStatusMessage ( TQString message ) {
if ( message ! = m_prevStatusMessage ) {
emit ( statusMessageUpdated ( message ) ) ;
m_prevStatusMessage = message ;
}
}
void TDEKerberosServerSocket : : continueKerberosInitialization ( ) {
int slen ;
char buf [ NET_SEC_BUF_SIZE ] ;
unsigned int len ;
sasl_ssf_t * ssf ;
if ( m_krbInitRunning ) {
switch ( m_krbInitState ) {
case 0 :
if ( state ( ) = = TQSocket : : Connected ) {
setStatusMessage ( i18n ( " Waiting for client mechanism " ) ) ;
if ( canReadLine ( ) ) {
printf ( " [DEBUG] Waiting for client mechanism... \n \r " ) ;
slen = getSASLDataFromNetwork ( buf , NET_SEC_BUF_SIZE ) ;
if ( slen < 0 ) {
m_krbInitState = - 2 ;
m_krbInitRunning = false ;
setStatusMessage ( i18n ( " Kerberos connection failed " ) ) ;
return ;
}
len = slen ;
if ( strlen ( buf ) < len ) {
printf ( " [DEBUG] Initial response received \n \r " ) ;
// An initial response is present
m_krbInitData = buf + strlen ( buf ) + 1 ;
len = len - ( unsigned ) strlen ( buf ) - 1 ;
}
else {
m_krbInitData = NULL ;
len = 0 ;
}
m_krbInitResult = sasl_server_start ( saslData - > m_krbConnection , buf , m_krbInitData , len , & m_krbInitData , & len ) ;
if ( m_krbInitResult ! = SASL_OK & & m_krbInitResult ! = SASL_CONTINUE ) {
printf ( " [ERROR] Starting SASL negotiation returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , m_krbInitResult ) ;
freeKerberosConnection ( ) ;
m_krbInitState = - 1 ;
m_krbInitRunning = false ;
setStatusMessage ( i18n ( " Kerberos connection failed " ) ) ;
return ;
}
m_krbInitState = 1 ;
}
}
else {
m_krbInitState = - 3 ;
m_krbInitRunning = false ;
}
break ;
case 1 :
if ( state ( ) = = TQSocket : : Connected ) {
if ( m_krbInitResult = = SASL_CONTINUE ) {
if ( m_krbInitData ) {
printf ( " [DEBUG] Sending response... \n \r " ) ;
sendSASLDataToNetwork ( m_krbInitData , len , socket ( ) ) ;
}
else {
printf ( " [ERROR] No data to send! \n \r " ) ;
freeKerberosConnection ( ) ;
m_krbInitState = - 1 ;
m_krbInitRunning = false ;
setStatusMessage ( i18n ( " Kerberos connection failed " ) ) ;
return ;
}
m_krbInitState = 2 ;
}
else {
printf ( " [DEBUG] Negotiation complete \n \r " ) ;
m_krbInitState = 3 ;
}
}
else {
m_krbInitState = - 3 ;
m_krbInitRunning = false ;
setStatusMessage ( i18n ( " Kerberos connection failed " ) ) ;
return ;
}
break ;
case 2 :
if ( state ( ) = = TQSocket : : Connected ) {
setStatusMessage ( i18n ( " Waiting for client reply " ) ) ;
if ( canReadLine ( ) ) {
printf ( " [DEBUG] Waiting for client reply... \n \r " ) ;
slen = getSASLDataFromNetwork ( buf , NET_SEC_BUF_SIZE ) ;
if ( slen < 0 ) {
m_krbInitState = - 2 ;
m_krbInitRunning = false ;
setStatusMessage ( i18n ( " Kerberos connection failed " ) ) ;
return ;
}
len = slen ;
m_krbInitData = NULL ;
m_krbInitResult = sasl_server_step ( saslData - > m_krbConnection , buf , len , & m_krbInitData , & len ) ;
if ( m_krbInitResult ! = SASL_OK & & m_krbInitResult ! = SASL_CONTINUE ) {
printf ( " [ERROR] Performing SASL negotiation returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , m_krbInitResult ) ;
freeKerberosConnection ( ) ;
m_krbInitState = - 1 ;
m_krbInitRunning = false ;
setStatusMessage ( i18n ( " Kerberos connection failed " ) ) ;
return ;
}
m_krbInitState = 1 ;
}
}
else {
m_krbInitState = - 3 ;
m_krbInitRunning = false ;
setStatusMessage ( i18n ( " Kerberos connection failed " ) ) ;
return ;
}
break ;
case 3 :
if ( state ( ) = = TQSocket : : Connected ) {
if ( m_krbInitServerLast & & m_krbInitData ) {
printf ( " [DEBUG] Additional information needed to be sent \n \r " ) ;
sendSASLDataToNetwork ( m_krbInitData , len , socket ( ) ) ;
}
m_krbInitResult = sasl_getprop ( saslData - > m_krbConnection , SASL_USERNAME , ( const void * * ) & m_krbInitData ) ;
if ( m_krbInitResult ! = SASL_OK ) {
printf ( " [WARNING] Unable to determine authenticated username! \n \r " ) ;
}
else {
m_authenticatedUserName = m_krbInitData ? m_krbInitData : " (NULL) " ;
printf ( " [DEBUG] Authenticated username: %s \n \r " , m_authenticatedUserName . ascii ( ) ) ;
}
m_krbInitResult = sasl_getprop ( saslData - > m_krbConnection , SASL_DEFUSERREALM , ( const void * * ) & m_krbInitData ) ;
if ( m_krbInitResult ! = SASL_OK ) {
printf ( " [WARNING] Unable to determine authenticated realm! \n \r " ) ;
}
else {
m_authenticatedRealmName = m_krbInitData ? m_krbInitData : " (NULL) " ;
printf ( " [DEBUG] Authenticated realm: %s \n \r " , m_authenticatedRealmName . ascii ( ) ) ;
}
m_krbInitResult = sasl_getprop ( saslData - > m_krbConnection , SASL_SSF , ( const void * * ) & ssf ) ;
if ( m_krbInitResult ! = SASL_OK ) {
printf ( " [WARNING] Unable to determine SSF! \n \r " ) ;
}
else {
printf ( " [DEBUG] Authenticated SSF: %d \n " , * ssf ) ;
}
m_krbInitState = 4 ;
m_krbInitRunning = false ;
setStatusMessage ( i18n ( " Kerberos connection established " ) ) ;
return ;
}
else {
m_krbInitState = - 3 ;
m_krbInitRunning = false ;
setStatusMessage ( i18n ( " Kerberos connection failed " ) ) ;
return ;
}
break ;
}
TQTimer : : singleShot ( 0 , this , SLOT ( continueKerberosInitialization ( ) ) ) ;
}
}
int TDEKerberosServerSocket : : initializeKerberosInterface ( ) {
if ( state ( ) ! = TQSocket : : Connected ) {
saslData - > m_krbConnection = false ;
@ -569,16 +769,12 @@ int TDEKerberosServerSocket::initializeKerberosInterface() {
}
sasl_callback_t * callback ;
char buf [ NET_SEC_BUF_SIZE ] ;
int result = 0 ;
int serverlast = 0 ;
m_krbInitResult = 0 ;
m_krbInitServerLast = 0 ;
sasl_security_properties_t secprops ;
const char * ext_authid = NULL ;
unsigned int len ;
int slen ;
int count ;
const char * data ;
sasl_ssf_t * ssf ;
unsigned int len ;
// FIXME
// Populate these fields!
@ -606,116 +802,40 @@ int TDEKerberosServerSocket::initializeKerberosInterface() {
secprops . maxbufsize = NET_SEC_BUF_SIZE ;
secprops . max_ssf = UINT_MAX ;
result = sasl_server_init ( saslData - > m_callbacks , m_serviceName . ascii ( ) ) ;
if ( result ! = SASL_OK ) {
printf ( " [ERROR] Initializing libsasl returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , result) ;
m_k rbInitR esult = sasl_server_init ( saslData - > m_callbacks , m_serviceName . ascii ( ) ) ;
if ( m_k rbInitR esult ! = SASL_OK ) {
printf ( " [ERROR] Initializing libsasl returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , m_k rbInitR esult) ;
return - 1 ;
}
result = sasl_server_new ( m_serviceName . ascii ( ) , localdomain , userdomain , iplocal , ipremote , NULL , serverl ast, & saslData - > m_krbConnection ) ;
if ( result ! = SASL_OK ) {
printf ( " [ERROR] Allocating sasl connection state returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , result) ;
m_k rbInitR esult = sasl_server_new ( m_serviceName . ascii ( ) , localdomain , userdomain , iplocal , ipremote , NULL , m_krbInitServerL ast, & saslData - > m_krbConnection ) ;
if ( m_k rbInitR esult ! = SASL_OK ) {
printf ( " [ERROR] Allocating sasl connection state returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , m_k rbInitR esult) ;
return - 1 ;
}
result = sasl_setprop ( saslData - > m_krbConnection , SASL_SEC_PROPS , & secprops ) ;
m_k rbInitR esult = sasl_setprop ( saslData - > m_krbConnection , SASL_SEC_PROPS , & secprops ) ;
if ( result ! = SASL_OK ) {
printf ( " [ERROR] Setting security properties returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , result) ;
if ( m_k rbInitR esult ! = SASL_OK ) {
printf ( " [ERROR] Setting security properties returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , m_k rbInitR esult) ;
freeKerberosConnection ( ) ;
return - 1 ;
}
puts ( " [DEBUG] Generating client mechanism list... " ) ;
result = sasl_listmech ( saslData - > m_krbConnection , ext_authid , NULL , " " , NULL , & d ata, & len , & count ) ;
if ( result ! = SASL_OK ) {
printf ( " [ERROR] Generating client mechanism list returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , result) ;
m_k rbInitR esult = sasl_listmech ( saslData - > m_krbConnection , ext_authid , NULL , " " , NULL , & m_krbInitD ata, & len , & count ) ;
if ( m_k rbInitR esult ! = SASL_OK ) {
printf ( " [ERROR] Generating client mechanism list returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , m_k rbInitR esult) ;
freeKerberosConnection ( ) ;
return - 1 ;
}
printf ( " [DEBUG] Sending list of %d mechanism(s) \n \r " , count ) ;
sendSASLDataToNetwork ( d ata, len , socket ( ) ) ;
sendSASLDataToNetwork ( m_krbInitD ata, len , socket ( ) ) ;
printf ( " [DEBUG] Waiting for client mechanism... \n \r " ) ;
slen = getSASLDataFromNetwork ( buf , NET_SEC_BUF_SIZE ) ;
if ( slen < 0 ) {
return - 2 ;
}
len = slen ;
if ( strlen ( buf ) < len ) {
printf ( " [DEBUG] Initial response received \n \r " ) ;
// An initial response is present
data = buf + strlen ( buf ) + 1 ;
len = len - ( unsigned ) strlen ( buf ) - 1 ;
}
else {
data = NULL ;
len = 0 ;
}
result = sasl_server_start ( saslData - > m_krbConnection , buf , data , len , & data , & len ) ;
if ( result ! = SASL_OK & & result ! = SASL_CONTINUE ) {
printf ( " [ERROR] Starting SASL negotiation returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , result ) ;
freeKerberosConnection ( ) ;
return - 1 ;
}
while ( result = = SASL_CONTINUE ) {
if ( data ) {
printf ( " [DEBUG] Sending response... \n \r " ) ;
sendSASLDataToNetwork ( data , len , socket ( ) ) ;
}
else {
printf ( " [ERROR] No data to send! \n \r " ) ;
freeKerberosConnection ( ) ;
return - 1 ;
}
printf ( " [DEBUG] Waiting for client reply... \n \r " ) ;
slen = getSASLDataFromNetwork ( buf , NET_SEC_BUF_SIZE ) ;
if ( slen < 0 ) {
return - 2 ;
}
len = slen ;
data = NULL ;
result = sasl_server_step ( saslData - > m_krbConnection , buf , len , & data , & len ) ;
if ( result ! = SASL_OK & & result ! = SASL_CONTINUE ) {
printf ( " [ERROR] Performing SASL negotiation returned %s (%d) \n \r " , safe_sasl_errdetail ( saslData - > m_krbConnection ) , result ) ;
freeKerberosConnection ( ) ;
return - 1 ;
}
}
printf ( " [DEBUG] Negotiation complete \n \r " ) ;
if ( serverlast & & data ) {
printf ( " [DEBUG] Additional information needed to be sent \n \r " ) ;
sendSASLDataToNetwork ( data , len , socket ( ) ) ;
}
result = sasl_getprop ( saslData - > m_krbConnection , SASL_USERNAME , ( const void * * ) & data ) ;
if ( result ! = SASL_OK ) {
printf ( " [WARNING] Unable to determine authenticated username! \n \r " ) ;
}
else {
m_authenticatedUserName = data ? data : " (NULL) " ;
printf ( " [DEBUG] Authenticated username: %s \n \r " , m_authenticatedUserName . ascii ( ) ) ;
}
result = sasl_getprop ( saslData - > m_krbConnection , SASL_DEFUSERREALM , ( const void * * ) & data ) ;
if ( result ! = SASL_OK ) {
printf ( " [WARNING] Unable to determine authenticated realm! \n \r " ) ;
}
else {
m_authenticatedRealmName = data ? data : " (NULL) " ;
printf ( " [DEBUG] Authenticated realm: %s \n \r " , m_authenticatedRealmName . ascii ( ) ) ;
}
result = sasl_getprop ( saslData - > m_krbConnection , SASL_SSF , ( const void * * ) & ssf ) ;
if ( result ! = SASL_OK ) {
printf ( " [WARNING] Unable to determine SSF! \n \r " ) ;
}
else {
printf ( " [DEBUG] Authenticated SSF: %d \n " , * ssf ) ;
}
m_krbInitRunning = true ;
m_krbInitState = 0 ;
TQTimer : : singleShot ( 0 , this , SLOT ( continueKerberosInitialization ( ) ) ) ;
return 0 ;
}