diff --git a/clients/tde/src/app/remotemdi.cpp b/clients/tde/src/app/remotemdi.cpp index 3e5c075..e1d4236 100644 --- a/clients/tde/src/app/remotemdi.cpp +++ b/clients/tde/src/app/remotemdi.cpp @@ -30,7 +30,7 @@ using namespace std; #include "dialogs/selectserverdlg.h" RemoteMDI::RemoteMDI() - : KMdiMainFrm(0, "RemoteMDI", KMdi::ChildframeMode), m_children(0), m_rsvSvrSocket(NULL) + : KMdiMainFrm(0, "RemoteMDI", KMdi::ChildframeMode), m_children(0), m_rsvSvrSocket(NULL), connToServerConnecting(false), connToServerState(-1), connToServerTimeoutTimer(NULL) { setXMLFile("remotelabui.rc"); @@ -75,10 +75,10 @@ RemoteMDI::~RemoteMDI() } if (m_rsvSvrSocket) { + m_rsvSvrSocket->clearPendingData(); m_rsvSvrSocket->close(); - while (m_rsvSvrSocket->state() == TQSocket::Closing) { - tqApp->processEvents(); - } + delete m_rsvSvrSocket; + m_rsvSvrSocket = NULL; } } @@ -137,46 +137,54 @@ void RemoteMDI::startModule() { } } -void RemoteMDI::connectToServer() { - if (m_rsvSvrSocket) { - if (m_rsvSvrSocket->state() != TQSocket::Idle) { - printf("[DEBUG] Not connecting because the socket is still in state %d\n\r", m_rsvSvrSocket->state()); fflush(stdout); - return; - } - } - - connect_action->setEnabled(false); - disconnect_action->setEnabled(true); - - // Connect to the central reservation/control server - if (!m_rsvSvrSocket) { - m_rsvSvrSocket = new TDEKerberosClientSocket(this); - connect(m_rsvSvrSocket, SIGNAL(connectionClosed()), this, SLOT(connectionClosedHandler())); - } - m_rsvSvrSocket->setServiceName("remotefpga"); - if (m_serverHost != "") { - m_rsvSvrSocket->setServerFQDN(m_serverHost); - m_rsvSvrSocket->connectToHost(m_serverHost, 4004); - TQTimer connectionTimeout; - connectionTimeout.start(5000, TRUE); - while ((m_rsvSvrSocket->state() == TQSocket::Connecting) || (m_rsvSvrSocket->state() == TQSocket::HostLookup)) { - tqApp->processEvents(); - if (!connectionTimeout.isActive()) { +void RemoteMDI::finishConnectingToServer() { + if (connToServerConnecting) { + switch(connToServerState) { + case 0: + if (!connToServerTimeoutTimer) { + connToServerTimeoutTimer = new TQTimer; + connToServerTimeoutTimer->start(5000, TRUE); + } + if ((m_rsvSvrSocket->state() == TQSocket::Connecting) || (m_rsvSvrSocket->state() == TQSocket::HostLookup)) { + if (!connToServerTimeoutTimer->isActive()) { + connToServerState = -3; + connToServerConnecting = false; + disconnectFromServer(); + KMessageBox::error(this, i18n("Unable to establish connection to remote server"), i18n("Connection Failed")); + } + } + else { + if (m_rsvSvrSocket->state() == TQSocket::Connected) { + printf("[DEBUG] Initial connection established...\n\r"); fflush(stdout); + m_rsvSvrSocket->setDataTimeout(5000); + m_rsvSvrSocket->setUsingKerberos(true); + connToServerState = 1; + } + else { + connToServerState = -1; + connToServerConnecting = false; + disconnectFromServer(); + KMessageBox::error(this, i18n("Unable to establish connection to remote server"), i18n("Connection Failed")); + } + } break; - } - } - connectionTimeout.stop(); - if (m_rsvSvrSocket->state() == TQSocket::Connected) { - printf("[DEBUG] Initial connection established...\n\r"); fflush(stdout); - m_rsvSvrSocket->setUsingKerberos(true); - while (m_rsvSvrSocket->kerberosStatus() == TDEKerberosClientSocket::KerberosInitializing) { - tqApp->processEvents(); - } - if (m_rsvSvrSocket->kerberosStatus() != TDEKerberosClientSocket::KerberosInUse) { - disconnectFromServer(); - KMessageBox::error(this, i18n("Unable to establish Kerberos protocol with remote server

Please verify that you currently hold a valid Kerberos ticket"), i18n("Connection Failed")); - } - else { + case 1: + if (m_rsvSvrSocket->kerberosStatus() == TDEKerberosClientSocket::KerberosInitializing) { + // Do nothing + } + else { + if (m_rsvSvrSocket->kerberosStatus() != TDEKerberosClientSocket::KerberosInUse) { + connToServerState = -1; + connToServerConnecting = false; + disconnectFromServer(); + KMessageBox::error(this, i18n("Unable to establish Kerberos protocol with remote server

Please verify that you currently hold a valid Kerberos ticket"), i18n("Connection Failed")); + } + else { + connToServerState = 2; + } + } + break; + case 2: // Connection established! // Read magic number and proto version from server TQDataStream* ds = new TQDataStream(m_rsvSvrSocket); @@ -194,19 +202,43 @@ void RemoteMDI::connectToServer() { disconnectFromServer(); KMessageBox::error(this, i18n("The remote server is not compatible with this client"), i18n("Connection Failed")); } - } + connToServerState = 3; + connToServerConnecting = false; + processLockouts(); + break; } - else { - disconnectFromServer(); - KMessageBox::error(this, i18n("Unable to establish connection to remote server"), i18n("Connection Failed")); + + TQTimer::singleShot(0, this, SLOT(finishConnectingToServer())); + } +} + +void RemoteMDI::connectToServer() { + if (m_rsvSvrSocket) { + if (m_rsvSvrSocket->state() != TQSocket::Idle) { + printf("[DEBUG] Not connecting because the socket is still in state %d\n\r", m_rsvSvrSocket->state()); fflush(stdout); + return; } } - else { - disconnectFromServer(); - KMessageBox::error(this, i18n("The address of the remote server has not been specified"), i18n("Connection Failed")); + + connect_action->setEnabled(false); + disconnect_action->setEnabled(true); + + // Connect to the central reservation/control server + if (!m_rsvSvrSocket) { + m_rsvSvrSocket = new TDEKerberosClientSocket(this); + connect(m_rsvSvrSocket, SIGNAL(connectionClosed()), this, SLOT(connectionClosedHandler())); + connect(m_rsvSvrSocket, TQT_SIGNAL(statusMessageUpdated(const TQString&)), statusBar(), TQT_SLOT(message(const TQString&) )); } + m_rsvSvrSocket->setServiceName("remotefpga"); + if (m_serverHost != "") { + m_rsvSvrSocket->setServerFQDN(m_serverHost); + m_rsvSvrSocket->connectToHost(m_serverHost, 4004); - processLockouts(); + // Finish connecting when appropriate + connToServerState = 0; + connToServerConnecting = true; + TQTimer::singleShot(0, this, SLOT(finishConnectingToServer())); + } } void RemoteMDI::promptForStationType() { @@ -290,7 +322,7 @@ void RemoteMDI::connectionClosedHandler() { void RemoteMDI::processLockouts() { bool connected = false; if (m_rsvSvrSocket) { - connected = (m_rsvSvrSocket->state() == TQSocket::Connected); + connected = ((m_rsvSvrSocket->state() == TQSocket::Connected) && (connToServerConnecting == false) && (connToServerState > 0)); } printf("[RAJA DEBUG 600.0] connected: %d\n\r", connected); fflush(stdout); diff --git a/clients/tde/src/app/remotemdi.h b/clients/tde/src/app/remotemdi.h index a7b62b2..d1a8263 100644 --- a/clients/tde/src/app/remotemdi.h +++ b/clients/tde/src/app/remotemdi.h @@ -59,6 +59,7 @@ class RemoteMDI : public KMdiMainFrm void configToolbars(); void configKeys(); void connectToServer(); + void finishConnectingToServer(); void disconnectFromServer(); void promptForStationType(); void connectionClosedHandler(); @@ -74,6 +75,10 @@ class RemoteMDI : public KMdiMainFrm TDEKerberosClientSocket* m_rsvSvrSocket; + bool connToServerConnecting; + int connToServerState; + TQTimer *connToServerTimeoutTimer; + private: KAction *connect_action; KAction *disconnect_action; diff --git a/clients/tde/src/part/fpgaview/part.cpp b/clients/tde/src/part/fpgaview/part.cpp index 2b3cf8d..1ca9b6e 100644 --- a/clients/tde/src/part/fpgaview/part.cpp +++ b/clients/tde/src/part/fpgaview/part.cpp @@ -158,6 +158,7 @@ printf("[RAJA DEBUG 200.1] In FPGAViewPart::connectToServer TRIED TO CONNECT TWI if (m_socket->state() != TQSocket::Connected) { return -1; } + m_socket->setDataTimeout(5000); m_socket->setUsingKerberos(true); while (m_socket->kerberosStatus() == TDEKerberosClientSocket::KerberosInitializing) { tqApp->eventLoop()->processEvents(TQEventLoop::AllEvents); diff --git a/lib/libtdekrb/src/tdekrbclientsocket.cpp b/lib/libtdekrb/src/tdekrbclientsocket.cpp index 24acb29..7e39fcf 100644 --- a/lib/libtdekrb/src/tdekrbclientsocket.cpp +++ b/lib/libtdekrb/src/tdekrbclientsocket.cpp @@ -30,6 +30,8 @@ #include #include +#include + #include "tdekrbclientsocket.h" #define NET_SEC_BUF_SIZE (2048) @@ -95,7 +97,7 @@ static int logSASLMessages(void *context __attribute__((unused)), int priority, return SASL_OK; } -TDEKerberosClientSocket::TDEKerberosClientSocket(TQObject *parent, const char *name) : TQSocket(parent, name), m_kerberosRequested(false), m_criticalSection(0), m_bufferLength(0), m_krbInitRunning(false), m_krbInitState(-1), m_canary(NULL), m_negotiatedMaxBufferSize(NET_SEC_BUF_SIZE) { +TDEKerberosClientSocket::TDEKerberosClientSocket(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(); @@ -111,7 +113,12 @@ TDEKerberosClientSocket::~TDEKerberosClientSocket() { delete saslData; } +void TDEKerberosClientSocket::setDataTimeout(int timeoutms) { + m_dataTimeout = timeoutms; +} + bool TDEKerberosClientSocket::open(int mode) { + setStatusMessage(i18n("Establishing initial connection to server")); bool ret = TQSocket::open(mode); if (m_kerberosRequested) { initializeKerberosInterface(); @@ -121,6 +128,7 @@ bool TDEKerberosClientSocket::open(int mode) { void TDEKerberosClientSocket::close() { TQSocket::close(); + setStatusMessage(i18n("Disconnected")); } void TDEKerberosClientSocket::flush() { @@ -453,8 +461,12 @@ int TDEKerberosClientSocket::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) { @@ -469,10 +481,13 @@ int TDEKerberosClientSocket::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 { @@ -509,9 +524,14 @@ int TDEKerberosClientSocket::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; @@ -527,7 +547,7 @@ int TDEKerberosClientSocket::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 } } @@ -576,6 +596,13 @@ TDEKerberosClientSocket::KerberosStatus TDEKerberosClientSocket::kerberosStatus( return KerberosInUse; } +void TDEKerberosClientSocket::setStatusMessage(TQString message) { + if (message != m_prevStatusMessage) { + emit(statusMessageUpdated(message)); + m_prevStatusMessage = message; + } +} + void TDEKerberosClientSocket::continueKerberosInitialization() { int slen; char buf[NET_SEC_BUF_SIZE]; @@ -588,27 +615,30 @@ void TDEKerberosClientSocket::continueKerberosInitialization() { switch (m_krbInitState) { case 0: if (state() == TQSocket::Connected) { + setStatusMessage(i18n("Waiting for mechanism list from server")); if (canReadLine()) { printf("[DEBUG] Waiting for mechanism list from server...\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; - + printf("Choosing best mechanism from: %s\n", buf); - + m_krbInitResult = sasl_client_start(saslData->m_krbConnection, buf, NULL, &data, &len, &chosenmech); if (m_krbInitResult != SASL_OK && m_krbInitResult != SASL_CONTINUE) { printf("[ERROR] Starting SASL negotiation returned %s (%d)\n\r", sasl_errstring(m_krbInitResult, NULL, NULL), m_krbInitResult); freeKerberosConnection(); m_krbInitState = -1; m_krbInitRunning = false; + setStatusMessage(i18n("Kerberos connection failed")); return; } - + printf("[DEBUG] Using mechanism %s\n\r", chosenmech); strcpy(buf, chosenmech); if (data) { @@ -617,6 +647,7 @@ void TDEKerberosClientSocket::continueKerberosInitialization() { freeKerberosConnection(); m_krbInitState = -1; m_krbInitRunning = false; + setStatusMessage(i18n("Kerberos connection failed")); return; } printf("[DEBUG] Preparing initial response...\n\r"); @@ -627,7 +658,7 @@ void TDEKerberosClientSocket::continueKerberosInitialization() { else { len = (unsigned) strlen(buf); } - + printf("[DEBUG] Sending initial response...\n\r"); sendSASLDataToNetwork(buf, len, socket()); @@ -642,12 +673,14 @@ void TDEKerberosClientSocket::continueKerberosInitialization() { case 1: if (state() == TQSocket::Connected) { if (m_krbInitResult == SASL_CONTINUE) { + setStatusMessage(i18n("Waiting for server reply")); if (canReadLine()) { printf("[DEBUG] Waiting for server 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; @@ -657,6 +690,7 @@ void TDEKerberosClientSocket::continueKerberosInitialization() { freeKerberosConnection(); m_krbInitState = -1; m_krbInitRunning = false; + setStatusMessage(i18n("Kerberos connection failed")); return; } if (data && len) { @@ -676,6 +710,8 @@ void TDEKerberosClientSocket::continueKerberosInitialization() { else { m_krbInitState = -3; m_krbInitRunning = false; + setStatusMessage(i18n("Kerberos connection failed")); + return; } break; case 2: @@ -714,10 +750,14 @@ void TDEKerberosClientSocket::continueKerberosInitialization() { } m_krbInitState = 3; m_krbInitRunning = false; + setStatusMessage(i18n("Kerberos connection established")); + return; } else { m_krbInitState = -3; m_krbInitRunning = false; + setStatusMessage(i18n("Kerberos connection failed")); + return; } break; } diff --git a/lib/libtdekrb/src/tdekrbclientsocket.h b/lib/libtdekrb/src/tdekrbclientsocket.h index 48ec09a..8f4a287 100644 --- a/lib/libtdekrb/src/tdekrbclientsocket.h +++ b/lib/libtdekrb/src/tdekrbclientsocket.h @@ -62,6 +62,8 @@ class TDEKerberosClientSocket : public TQSocket void setServiceName(TQString name); void setServerFQDN(TQString name); + void setDataTimeout(int timeoutms); + KerberosStatus kerberosStatus() const; private: @@ -71,10 +73,14 @@ class TDEKerberosClientSocket : public TQSocket int getSASLDataFromNetwork(char *buf, int trunclen, bool shouldblock=true); int transmitEncryptedData(int fd, const char* readbuf, int cc); int receiveEncryptedData(char *buf, unsigned int trunclen, bool shouldblock=true); + void setStatusMessage(TQString message); private slots: void continueKerberosInitialization(); + signals: + void statusMessageUpdated(const TQString&); + private: bool m_kerberosRequested; TQString m_serviceName; @@ -84,6 +90,8 @@ class TDEKerberosClientSocket : public TQSocket long m_bufferLength; bool m_krbInitRunning; int m_krbInitState; + TQString m_prevStatusMessage; + int m_dataTimeout; bool* m_canary; private: 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 #include #include +#include #include #include #include +#include + #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 diff --git a/lib/libtdekrb/src/tdekrbserversocket.h b/lib/libtdekrb/src/tdekrbserversocket.h index 80c84fd..4a315ca 100644 --- a/lib/libtdekrb/src/tdekrbserversocket.h +++ b/lib/libtdekrb/src/tdekrbserversocket.h @@ -32,6 +32,14 @@ class TDEKerberosServerSocket : public TQSocket { Q_OBJECT + public: + enum KerberosStatus { + KerberosNotRequested, + KerberosFailure, + KerberosInitializing, + KerberosInUse + }; + public: TDEKerberosServerSocket(TQObject *parent=0, const char *name=0); virtual ~TDEKerberosServerSocket(); @@ -53,6 +61,10 @@ class TDEKerberosServerSocket : public TQSocket int setUsingKerberos(bool krbactive); void setServiceName(TQString name); void setServerFQDN(TQString name); + + void setDataTimeout(int timeoutms); + + KerberosStatus kerberosStatus() const; private: int initializeKerberosInterface(); @@ -61,6 +73,13 @@ class TDEKerberosServerSocket : public TQSocket int getSASLDataFromNetwork(char *buf, int trunclen, bool shouldblock=true); int transmitEncryptedData(int fd, const char* readbuf, int cc); int receiveEncryptedData(char *buf, unsigned int trunclen, bool shouldblock=true); + void setStatusMessage(TQString message); + + private slots: + void continueKerberosInitialization(); + + signals: + void statusMessageUpdated(const TQString&); protected: TQString m_authenticatedUserName; @@ -73,11 +92,18 @@ class TDEKerberosServerSocket : public TQSocket int m_criticalSection; TQBuffer* m_buffer; long m_bufferLength; + bool m_krbInitRunning; + int m_krbInitState; + TQString m_prevStatusMessage; + int m_dataTimeout; bool* m_canary; private: SASLDataPrivate *saslData; unsigned int m_negotiatedMaxBufferSize; + int m_krbInitResult; + int m_krbInitServerLast; + const char *m_krbInitData; }; #endif // TDEKRBSERVERSOCKET_H \ No newline at end of file diff --git a/servers/auth_server_lin/src/auth_conn.cpp b/servers/auth_server_lin/src/auth_conn.cpp index 87eb314..65c131f 100644 --- a/servers/auth_server_lin/src/auth_conn.cpp +++ b/servers/auth_server_lin/src/auth_conn.cpp @@ -106,7 +106,12 @@ void AuthSocket::connectionClosedHandler() { } int AuthSocket::initiateKerberosHandshake() { - if (setUsingKerberos(true) == 0) { + // RAJA FIXME + setUsingKerberos(true); + while (kerberosStatus() == TDEKerberosServerSocket::KerberosInitializing) { + tqApp->processEvents(); + } + if (kerberosStatus() == TDEKerberosServerSocket::KerberosInUse) { TQ_UINT32 magicnum = MAGIC_NUMBER; TQ_UINT32 protover = PROTOCOL_VERSION; diff --git a/servers/fpga_server_lin/src/fpga_conn.cpp b/servers/fpga_server_lin/src/fpga_conn.cpp index 4c6f65e..b1b0451 100644 --- a/servers/fpga_server_lin/src/fpga_conn.cpp +++ b/servers/fpga_server_lin/src/fpga_conn.cpp @@ -88,7 +88,12 @@ void FPGASocket::connectionClosedHandler() { } int FPGASocket::initiateKerberosHandshake() { - if (setUsingKerberos(true) == 0) { + // RAJA FIXME + setUsingKerberos(true); + while (kerberosStatus() == TDEKerberosServerSocket::KerberosInitializing) { + tqApp->processEvents(); + } + if (kerberosStatus() == TDEKerberosServerSocket::KerberosInUse) { TQDataStream ds(this); ds << TQString("OK");