summaryrefslogtreecommitdiffstats
path: root/lib/libtdekrb
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-06-28 22:30:14 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-06-28 22:30:14 -0500
commite89735d72ae3b320c33f7ad95c3cbc9ea6d42f6c (patch)
tree082b8c247ba91b735394a9ba8d4f87bf416a389f /lib/libtdekrb
parent65ea633f475c7ab2b524dc1ffb369f6607df3e6b (diff)
downloadulab-e89735d72ae3b320c33f7ad95c3cbc9ea6d42f6c.tar.gz
ulab-e89735d72ae3b320c33f7ad95c3cbc9ea6d42f6c.zip
Convert krb client socket to stateful init
Diffstat (limited to 'lib/libtdekrb')
-rw-r--r--lib/libtdekrb/src/tdekrbclientsocket.cpp330
-rw-r--r--lib/libtdekrb/src/tdekrbclientsocket.h17
-rw-r--r--lib/libtdekrb/src/tdekrbserversocket.cpp23
3 files changed, 229 insertions, 141 deletions
diff --git a/lib/libtdekrb/src/tdekrbclientsocket.cpp b/lib/libtdekrb/src/tdekrbclientsocket.cpp
index 2736f5a..24acb29 100644
--- a/lib/libtdekrb/src/tdekrbclientsocket.cpp
+++ b/lib/libtdekrb/src/tdekrbclientsocket.cpp
@@ -23,6 +23,8 @@
#include <tqapplication.h>
#include <tqbuffer.h>
+#include <tqeventloop.h>
+#include <tqtimer.h>
#include <sasl.h>
#include <saslplug.h>
@@ -33,17 +35,17 @@
#define NET_SEC_BUF_SIZE (2048)
// When control comes back from processEvents() my object may be completely gone! This attempts to mitigate the risk
-#define SAFELY_PROCESS_EVENTS if (!m_canary) { \
- m_canary = new bool; \
- *m_canary = false; \
- } \
- bool* canary = m_canary; \
- tqApp->processEvents(); \
- if (*canary == true) { \
- delete canary; \
- return -1; \
- } \
- delete m_canary; \
+#define SAFELY_PROCESS_EVENTS if (!m_canary) { \
+ m_canary = new bool; \
+ *m_canary = false; \
+ } \
+ bool* canary = m_canary; \
+ tqApp->eventLoop()->processEvents(TQEventLoop::ExcludeUserInput); \
+ if (*canary == true) { \
+ delete canary; \
+ return -1; \
+ } \
+ delete m_canary; \
m_canary = NULL;
/* exception handling */
@@ -93,7 +95,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_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_canary(NULL), m_negotiatedMaxBufferSize(NET_SEC_BUF_SIZE) {
saslData = new SASLDataPrivate;
saslData->m_krbConnection = NULL;
m_buffer = new TQBuffer();
@@ -122,7 +124,7 @@ void TDEKerberosClientSocket::close() {
}
void TDEKerberosClientSocket::flush() {
- if (m_kerberosRequested) {
+ if (kerberosStatus() == KerberosInUse) {
// FIXME
// If a write buffer is implemented, it will need to be flushed before the following call is made
TQSocket::flush();
@@ -135,7 +137,7 @@ void TDEKerberosClientSocket::flush() {
TQIODevice::Offset TDEKerberosClientSocket::size() const {
TQIODevice::Offset ret;
- if (m_kerberosRequested) {
+ if (kerberosStatus() == KerberosInUse) {
ret = m_bufferLength;
}
else {
@@ -153,7 +155,7 @@ bool TDEKerberosClientSocket::at(TQIODevice::Offset off) {
long i;
bool ret;
- if (m_kerberosRequested) {
+ if (kerberosStatus() == KerberosInUse) {
if (off > 0) {
// Prevent overflow
if (off > (unsigned long)m_bufferLength) {
@@ -184,7 +186,7 @@ bool TDEKerberosClientSocket::at(TQIODevice::Offset off) {
bool TDEKerberosClientSocket::atEnd() const {
bool ret;
- if (m_kerberosRequested) {
+ if (kerberosStatus() == KerberosInUse) {
ret = TQSocket::atEnd();
}
else {
@@ -205,7 +207,7 @@ int TDEKerberosClientSocket::setUsingKerberos(bool krbactive) {
if (krbactive) {
m_kerberosRequested = true;
if ((!saslData->m_krbConnection) && (state() == TQSocket::Connected)) {
- ret = initializeKerberosInterface();
+ initializeKerberosInterface();
}
}
else {
@@ -230,7 +232,7 @@ TQ_LONG TDEKerberosClientSocket::readBlock(char *data, TQ_ULONG maxlen) {
long i;
TQ_LONG ret;
- if (m_kerberosRequested) {
+ if (kerberosStatus() == KerberosInUse) {
int reclen;
int wrlen;
char* buf = (char*)malloc(m_negotiatedMaxBufferSize);
@@ -277,7 +279,7 @@ TQ_LONG TDEKerberosClientSocket::readBlock(char *data, TQ_ULONG maxlen) {
TQ_LONG TDEKerberosClientSocket::writeBlock(const char *data, TQ_ULONG len) {
TQ_LONG ret;
- if (m_kerberosRequested) {
+ if (kerberosStatus() == KerberosInUse) {
ret = transmitEncryptedData(socket(), data, len);
}
else {
@@ -291,7 +293,7 @@ TQ_LONG TDEKerberosClientSocket::readLine(char *data, TQ_ULONG maxlen) {
long i;
TQ_LONG ret;
- if (m_kerberosRequested) {
+ if (kerberosStatus() == KerberosInUse) {
int reclen;
int wrlen;
char* buf = (char*)malloc(m_negotiatedMaxBufferSize);
@@ -340,7 +342,7 @@ TQString TDEKerberosClientSocket::readLine() {
TQString ret;
long maxlen;
- if (m_kerberosRequested) {
+ if (kerberosStatus() == KerberosInUse) {
int reclen;
int wrlen;
int readlen;
@@ -393,7 +395,7 @@ TQString TDEKerberosClientSocket::readLine() {
}
void TDEKerberosClientSocket::writeLine(TQString str) {
- if (m_kerberosRequested) {
+ if (kerberosStatus() == KerberosInUse) {
transmitEncryptedData(socket(), str.ascii(), str.length());
}
else {
@@ -561,6 +563,168 @@ int TDEKerberosClientSocket::receiveEncryptedData(char *buf, unsigned int truncl
return recv_len;
}
+TDEKerberosClientSocket::KerberosStatus TDEKerberosClientSocket::kerberosStatus() const {
+ if (!m_kerberosRequested) {
+ return KerberosNotRequested;
+ }
+ if (m_krbInitRunning) {
+ return KerberosInitializing;
+ }
+ if (m_krbInitState < 0) {
+ return KerberosFailure;
+ }
+ return KerberosInUse;
+}
+
+void TDEKerberosClientSocket::continueKerberosInitialization() {
+ int slen;
+ char buf[NET_SEC_BUF_SIZE];
+ unsigned int len;
+ const char *data;
+ const char *chosenmech;
+ sasl_ssf_t *ssf;
+
+ if (m_krbInitRunning) {
+ switch (m_krbInitState) {
+ case 0:
+ if (state() == TQSocket::Connected) {
+ 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;
+ 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;
+ return;
+ }
+
+ printf("[DEBUG] Using mechanism %s\n\r", chosenmech);
+ strcpy(buf, chosenmech);
+ if (data) {
+ if (NET_SEC_BUF_SIZE - strlen(buf) - 1 < len) {
+ printf("[ERROR] Insufficient buffer space to construct initial response!\n\r");
+ freeKerberosConnection();
+ m_krbInitState = -1;
+ m_krbInitRunning = false;
+ return;
+ }
+ printf("[DEBUG] Preparing initial response...\n\r");
+ memcpy(buf + strlen(buf) + 1, data, len);
+ len += (unsigned) strlen(buf) + 1;
+ data = NULL;
+ }
+ else {
+ len = (unsigned) strlen(buf);
+ }
+
+ printf("[DEBUG] Sending initial response...\n\r");
+ sendSASLDataToNetwork(buf, len, socket());
+
+ m_krbInitState = 1;
+ }
+ }
+ else {
+ m_krbInitState = -3;
+ m_krbInitRunning = false;
+ }
+ break;
+ case 1:
+ if (state() == TQSocket::Connected) {
+ if (m_krbInitResult == SASL_CONTINUE) {
+ 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;
+ return;
+ }
+ len = slen;
+ m_krbInitResult = sasl_client_step(saslData->m_krbConnection, buf, len, NULL, &data, &len);
+ if (m_krbInitResult != SASL_OK && m_krbInitResult != SASL_CONTINUE) {
+ printf("[ERROR] Performing SASL negotiation returned %s (%d)\n\r", sasl_errstring(m_krbInitResult, NULL, NULL), m_krbInitResult);
+ freeKerberosConnection();
+ m_krbInitState = -1;
+ m_krbInitRunning = false;
+ return;
+ }
+ if (data && len) {
+ printf("[DEBUG] Sending response...\n\r");
+ sendSASLDataToNetwork(data, len, socket());
+ }
+ else if (m_krbInitResult != SASL_OK || !m_krbInitServerLast) {
+ sendSASLDataToNetwork("", 0, socket());
+ }
+ }
+ }
+ else {
+ printf("[DEBUG] Negotiation complete!\n\r");
+ m_krbInitState = 2;
+ }
+ }
+ else {
+ m_krbInitState = -3;
+ m_krbInitRunning = false;
+ }
+ break;
+ case 2:
+ if (state() == TQSocket::Connected) {
+ m_krbInitResult = sasl_getprop(saslData->m_krbConnection, SASL_USERNAME, (const void **)&data);
+ if (m_krbInitResult != SASL_OK) {
+ printf("[WARNING] Unable to determine authenticated username!\n\r");
+ }
+ else {
+ printf("[DEBUG] Authenticated username: %s\n\r", data ? data : "(NULL)");
+ }
+
+ m_krbInitResult = sasl_getprop(saslData->m_krbConnection, SASL_DEFUSERREALM, (const void **)&data);
+ if (m_krbInitResult != SASL_OK) {
+ printf("[WARNING] Unable to determine authenticated realm!\n\r");
+ }
+ else {
+ printf("[DEBUG] Authenticated realm: %s\n\r", data ? data : "(NULL)");
+ }
+
+ 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_krbInitResult = sasl_getprop(saslData->m_krbConnection, SASL_MAXOUTBUF, (const void **)&m_negotiatedMaxBufferSize);
+ if (m_krbInitResult != SASL_OK) {
+ printf("[WARNING] Unable to determine maximum buffer size!\n\r");
+ m_negotiatedMaxBufferSize = NET_SEC_BUF_SIZE;
+ }
+ else {
+ printf("[DEBUG] Maximum buffer size: %d\n", m_negotiatedMaxBufferSize);
+ }
+ m_krbInitState = 3;
+ m_krbInitRunning = false;
+ }
+ else {
+ m_krbInitState = -3;
+ m_krbInitRunning = false;
+ }
+ break;
+ }
+ TQTimer::singleShot(0, this, SLOT(continueKerberosInitialization()));
+ }
+}
+
int TDEKerberosClientSocket::initializeKerberosInterface() {
if (state() != TQSocket::Connected) {
saslData->m_krbConnection = false;
@@ -568,15 +732,9 @@ int TDEKerberosClientSocket::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 *chosenmech;
- unsigned int len;
- int slen;
- const char *data;
- sasl_ssf_t *ssf;
char *iplocal = NULL;
char *ipremote = NULL;
const char *service = m_serviceName.ascii();
@@ -601,116 +759,28 @@ int TDEKerberosClientSocket::initializeKerberosInterface() {
secprops.maxbufsize = NET_SEC_BUF_SIZE;
secprops.max_ssf = UINT_MAX;
- result = sasl_client_init(saslData->m_callbacks);
- if (result != SASL_OK) {
- printf("[ERROR] Initializing libsasl returned %s (%d)\n\r", sasl_errstring(result, NULL, NULL), result);
- return -1;
- }
-
- result = sasl_client_new(service, fqdn, iplocal, ipremote, NULL, serverlast, &saslData->m_krbConnection);
- if (result != SASL_OK) {
- printf("[ERROR] Allocating sasl connection state returned %s (%d)\n\r", sasl_errstring(result, NULL, NULL), result);
+ m_krbInitResult = sasl_client_init(saslData->m_callbacks);
+ if (m_krbInitResult != SASL_OK) {
+ printf("[ERROR] Initializing libsasl returned %s (%d)\n\r", sasl_errstring(m_krbInitResult, NULL, NULL), m_krbInitResult);
return -1;
}
- result = sasl_setprop(saslData->m_krbConnection, SASL_SEC_PROPS, &secprops);
- if (result != SASL_OK) {
- printf("[ERROR] Setting security properties returned %s (%d)\n\r", sasl_errstring(result, NULL, NULL), result);
- freeKerberosConnection();
+ m_krbInitResult = sasl_client_new(service, fqdn, iplocal, ipremote, NULL, m_krbInitServerLast, &saslData->m_krbConnection);
+ if (m_krbInitResult != SASL_OK) {
+ printf("[ERROR] Allocating sasl connection state returned %s (%d)\n\r", sasl_errstring(m_krbInitResult, NULL, NULL), m_krbInitResult);
return -1;
}
- printf("[DEBUG] Waiting for mechanism list from server...\n\r");
- slen = getSASLDataFromNetwork(buf, NET_SEC_BUF_SIZE);
- if (slen < 0) {
- return -2;
- }
- len = slen;
-
- printf("Choosing best mechanism from: %s\n", buf);
-
- result = sasl_client_start(saslData->m_krbConnection, buf, NULL, &data, &len, &chosenmech);
- if (result != SASL_OK && result != SASL_CONTINUE) {
- printf("[ERROR] Starting SASL negotiation returned %s (%d)\n\r", sasl_errstring(result, NULL, NULL), result);
+ m_krbInitResult = sasl_setprop(saslData->m_krbConnection, SASL_SEC_PROPS, &secprops);
+ if (m_krbInitResult != SASL_OK) {
+ printf("[ERROR] Setting security properties returned %s (%d)\n\r", sasl_errstring(m_krbInitResult, NULL, NULL), m_krbInitResult);
freeKerberosConnection();
return -1;
}
- printf("[DEBUG] Using mechanism %s\n\r", chosenmech);
- strcpy(buf, chosenmech);
- if (data) {
- if (NET_SEC_BUF_SIZE - strlen(buf) - 1 < len) {
- printf("[ERROR] Insufficient buffer space to construct initial response!\n\r");
- freeKerberosConnection();
- return -1;
- }
- printf("[DEBUG] Preparing initial response...\n\r");
- memcpy(buf + strlen(buf) + 1, data, len);
- len += (unsigned) strlen(buf) + 1;
- data = NULL;
- }
- else {
- len = (unsigned) strlen(buf);
- }
-
- printf("[DEBUG] Sending initial response...\n\r");
- sendSASLDataToNetwork(buf, len, socket());
-
- while (result == SASL_CONTINUE) {
- printf("[DEBUG] Waiting for server reply...\n\r");
- slen = getSASLDataFromNetwork(buf, NET_SEC_BUF_SIZE);
- if (slen < 0) {
- return -2;
- }
- len = slen;
- result = sasl_client_step(saslData->m_krbConnection, buf, len, NULL, &data, &len);
- if (result != SASL_OK && result != SASL_CONTINUE) {
- printf("[ERROR] Performing SASL negotiation returned %s (%d)\n\r", sasl_errstring(result, NULL, NULL), result);
- freeKerberosConnection();
- return -1;
- }
- if (data && len) {
- printf("[DEBUG] Sending response...\n\r");
- sendSASLDataToNetwork(data, len, socket());
- }
- else if (result != SASL_OK || !serverlast) {
- sendSASLDataToNetwork("", 0, socket());
- }
- }
- printf("[DEBUG] Negotiation complete!\n\r");
-
- 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 {
- printf("[DEBUG] Authenticated username: %s\n\r", data ? data : "(NULL)");
- }
-
- 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 {
- printf("[DEBUG] Authenticated realm: %s\n\r", data ? data : "(NULL)");
- }
-
- 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);
- }
-
- result = sasl_getprop(saslData->m_krbConnection, SASL_MAXOUTBUF, (const void **)&m_negotiatedMaxBufferSize);
- if (result != SASL_OK) {
- printf("[WARNING] Unable to determine maximum buffer size!\n\r");
- m_negotiatedMaxBufferSize = NET_SEC_BUF_SIZE;
- }
- else {
- printf("[DEBUG] Maximum buffer size: %d\n", m_negotiatedMaxBufferSize);
- }
+ 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/tdekrbclientsocket.h b/lib/libtdekrb/src/tdekrbclientsocket.h
index ddba47a..48ec09a 100644
--- a/lib/libtdekrb/src/tdekrbclientsocket.h
+++ b/lib/libtdekrb/src/tdekrbclientsocket.h
@@ -33,6 +33,14 @@ class TDEKerberosClientSocket : public TQSocket
Q_OBJECT
public:
+ enum KerberosStatus {
+ KerberosNotRequested,
+ KerberosFailure,
+ KerberosInitializing,
+ KerberosInUse
+ };
+
+ public:
TDEKerberosClientSocket(TQObject *parent=0, const char *name=0);
virtual ~TDEKerberosClientSocket();
@@ -54,6 +62,8 @@ class TDEKerberosClientSocket : public TQSocket
void setServiceName(TQString name);
void setServerFQDN(TQString name);
+ KerberosStatus kerberosStatus() const;
+
private:
int initializeKerberosInterface();
void freeKerberosConnection();
@@ -62,6 +72,9 @@ class TDEKerberosClientSocket : public TQSocket
int transmitEncryptedData(int fd, const char* readbuf, int cc);
int receiveEncryptedData(char *buf, unsigned int trunclen, bool shouldblock=true);
+ private slots:
+ void continueKerberosInitialization();
+
private:
bool m_kerberosRequested;
TQString m_serviceName;
@@ -69,11 +82,15 @@ class TDEKerberosClientSocket : public TQSocket
int m_criticalSection;
TQBuffer* m_buffer;
long m_bufferLength;
+ bool m_krbInitRunning;
+ int m_krbInitState;
bool* m_canary;
private:
SASLDataPrivate *saslData;
unsigned int m_negotiatedMaxBufferSize;
+ int m_krbInitResult;
+ int m_krbInitServerLast;
};
#endif // TDEKRBCLIENTSOCKET_H \ No newline at end of file
diff --git a/lib/libtdekrb/src/tdekrbserversocket.cpp b/lib/libtdekrb/src/tdekrbserversocket.cpp
index e1e2c02..8e5c071 100644
--- a/lib/libtdekrb/src/tdekrbserversocket.cpp
+++ b/lib/libtdekrb/src/tdekrbserversocket.cpp
@@ -23,6 +23,7 @@
#include <tqapplication.h>
#include <tqbuffer.h>
+#include <tqeventloop.h>
#include <sasl.h>
#include <saslplug.h>
@@ -33,17 +34,17 @@
#define NET_SEC_BUF_SIZE (2048)
// When control comes back from processEvents() my object may be completely gone! This attempts to mitigate the risk
-#define SAFELY_PROCESS_EVENTS if (!m_canary) { \
- m_canary = new bool; \
- *m_canary = false; \
- } \
- bool* canary = m_canary; \
- tqApp->processEvents(); \
- if (*canary == true) { \
- delete canary; \
- return -1; \
- } \
- delete m_canary; \
+#define SAFELY_PROCESS_EVENTS if (!m_canary) { \
+ m_canary = new bool; \
+ *m_canary = false; \
+ } \
+ bool* canary = m_canary; \
+ tqApp->eventLoop()->processEvents(TQEventLoop::ExcludeUserInput); \
+ if (*canary == true) { \
+ delete canary; \
+ return -1; \
+ } \
+ delete m_canary; \
m_canary = NULL;
/* exception handling */