summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server.c50
-rw-r--r--types.h2
2 files changed, 44 insertions, 8 deletions
diff --git a/server.c b/server.c
index 3d02eb4..c4eb37d 100644
--- a/server.c
+++ b/server.c
@@ -262,7 +262,13 @@ uint32_t server_tryUserBind(server_t *server, struct string *binddn, struct stri
}
fmt_ldapbindrequeststring(bufoff, 3, binddn, password);
fmt_ldapmessage(bufoff - headerLen, id, BindRequest, bodyLen);
- if (!server_send(con, bufoff - headerLen, bodyLen + headerLen, FALSE)) {
+ con->bindLen = (int)(bodyLen + headerLen);
+ if (con->bindLen < 0 || con->bindLen > BINDLEN) {
+ printf("[Server] Error: bind too long");
+ con->bindLen = BINDLEN;
+ }
+ memcpy(con->bindBuffer, bufoff - headerLen, con->bindLen);
+ if (!server_haveOut(con)) {
printf("[Server] Could not send user bindrequest to server %s\n", server->addr);
server_free(con);
return 0;
@@ -336,13 +342,11 @@ static void server_callback(void *data, int haveIn, int haveOut, int doCleanup)
server_free(server);
return;
}
+ if (!server->sslConnected) return;
}
- // The connect above might have succeeded, so check again and start sending/receiving if so
- if (server->sslConnected) {
- // Since we don't know if the incoming data is just wrapped application data or ssl protocol stuff, we always call both
- server_haveIn(server);
- server_haveOut(server);
- }
+ // Since we don't know if the incoming data is just wrapped application data or ssl protocol stuff, we always call both
+ server_haveIn(server);
+ server_haveOut(server);
}
if (doCleanup || server->kill) {
server_free(server);
@@ -351,6 +355,7 @@ static void server_callback(void *data, int haveIn, int haveOut, int doCleanup)
static void server_haveIn(epoll_server_t *server)
{
+ if (server->ssl != NULL && !server->sslConnected) return;
for (;;) {
if (server->rbPos >= MAXMSGLEN) {
printf("[Proxy] Buffer overflow while reading from AD server. Disconnecting.\n");
@@ -445,6 +450,28 @@ BOOL server_send(epoll_server_t *server, const char *buffer, size_t len, const B
static BOOL server_haveOut(epoll_server_t * const server)
{
if (server->kill) return FALSE;
+ if (server->ssl != NULL && !server->sslConnected) return TRUE;
+ // Bind not sent/acknowledged yet - send bind if pending, otherwise do nothing
+ if (!server->bound) {
+ if (server->bindLen == 0) return TRUE;
+ int ret;
+ if (server->ssl == NULL) {
+ ret = write(server->fd, server->bindBuffer, server->bindLen);
+ } else {
+ ret = SSL_write(server->ssl, server->bindBuffer, server->bindLen);
+ }
+ if (ret <= 0) {
+ printf("[Server] Flushing bind to LDAP/AD failed...\n");
+ server->kill = TRUE;
+ return FALSE;
+ }
+ if (ret < server->bindLen) {
+ memmove(server->bindBuffer, server->bindBuffer + ret, server->bindLen - ret);
+ }
+ server->bindLen -= ret;
+ return TRUE;
+ }
+ // Only flush the regular send buffer (containing searches) if we know the bind succeeded
while (server->sbPos < server->sbFill) {
const ssize_t tosend = server->sbFill - server->sbPos;
ssize_t ret;
@@ -474,6 +501,7 @@ static BOOL server_haveOut(epoll_server_t * const server)
server->kill = TRUE;
return FALSE; // Closed
}
+ server->writeBlocked = FALSE;
}
server->sbPos += ret;
if (server->ssl != NULL) {
@@ -534,7 +562,13 @@ static BOOL server_ensureConnected(server_t *server)
con->kill = FALSE;
fmt_ldapbindrequest(bufoff, 3, server->bind, server->password);
fmt_ldapmessage(bufoff - headerLen, MSGID_BIND, BindRequest, bodyLen);
- if (!server_send(con, bufoff - headerLen, bodyLen + headerLen, FALSE)) {
+ con->bindLen = (int)(bodyLen + headerLen);
+ if (con->bindLen < 0 || con->bindLen > BINDLEN) {
+ printf("[Server] Error: bind too long");
+ con->bindLen = BINDLEN;
+ }
+ memcpy(con->bindBuffer, bufoff - headerLen, con->bindLen);
+ if (!server_haveOut(con)) {
printf("[Server] Sending bindrequest for shared connection failed for server %s\n", server->addr);
return FALSE;
}
diff --git a/types.h b/types.h
index 23888db..faa5292 100644
--- a/types.h
+++ b/types.h
@@ -76,6 +76,8 @@ struct _epoll_server_t_ {
size_t sbPos, sbFill, sbLen;
SSL *ssl; // NULL if not encrypted
char *sendBuffer; // Dynamically allocated, might or might not get huge
+ char bindBuffer[BINDLEN]; // Used for the bind request. We need this to prevent sending any requests before the server acknowledged the bind request
+ int bindLen; // Length of buffered bind request
epoll_client_t *fixedClient; // If client performed explicit bind, this is the client belonging to this connection
// Recv buffer (server's response)
size_t rbPos;