diff options
Diffstat (limited to 'lib/libtdekrb/src/tdekrbserversocket.cpp')
-rw-r--r-- | lib/libtdekrb/src/tdekrbserversocket.cpp | 330 |
1 files changed, 225 insertions, 105 deletions
diff --git a/lib/libtdekrb/src/tdekrbserversocket.cpp b/lib/libtdekrb/src/tdekrbserversocket.cpp index 8e5c071..4840c16 100644 --- a/lib/libtdekrb/src/tdekrbserversocket.cpp +++ b/lib/libtdekrb/src/tdekrbserversocket.cpp @@ -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_krbInitResult = sasl_server_init(saslData->m_callbacks, m_serviceName.ascii()); + if (m_krbInitResult != SASL_OK) { + printf("[ERROR] Initializing libsasl returned %s (%d)\n\r", safe_sasl_errdetail(saslData->m_krbConnection), m_krbInitResult); return -1; } - result = sasl_server_new(m_serviceName.ascii(), localdomain, userdomain, iplocal, ipremote, NULL, serverlast, &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_krbInitResult = sasl_server_new(m_serviceName.ascii(), localdomain, userdomain, iplocal, ipremote, NULL, m_krbInitServerLast, &saslData->m_krbConnection); + if (m_krbInitResult != SASL_OK) { + printf("[ERROR] Allocating sasl connection state returned %s (%d)\n\r", safe_sasl_errdetail(saslData->m_krbConnection), m_krbInitResult); return -1; } - result = sasl_setprop(saslData->m_krbConnection, SASL_SEC_PROPS, &secprops); + m_krbInitResult = 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_krbInitResult != SASL_OK) { + printf("[ERROR] Setting security properties returned %s (%d)\n\r", safe_sasl_errdetail(saslData->m_krbConnection), m_krbInitResult); freeKerberosConnection(); return -1; } puts("[DEBUG] Generating client mechanism list..."); - result = sasl_listmech(saslData->m_krbConnection, ext_authid, NULL, " ", NULL, &data, &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_krbInitResult = sasl_listmech(saslData->m_krbConnection, ext_authid, NULL, " ", NULL, &m_krbInitData, &len, &count); + if (m_krbInitResult != SASL_OK) { + printf("[ERROR] Generating client mechanism list returned %s (%d)\n\r", safe_sasl_errdetail(saslData->m_krbConnection), m_krbInitResult); freeKerberosConnection(); return -1; } printf("[DEBUG] Sending list of %d mechanism(s)\n\r", count); - sendSASLDataToNetwork(data, len, socket()); + sendSASLDataToNetwork(m_krbInitData, 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; }
\ No newline at end of file |