summaryrefslogtreecommitdiffstats
path: root/server.c
diff options
context:
space:
mode:
authorSimon Rettberg2015-10-23 12:38:53 +0200
committerSimon Rettberg2015-10-23 12:38:53 +0200
commitc12db031150b104e8811828fbfb2a97b270caafd (patch)
tree089f5bb40d5d7d0246d11fc6ca7214bf026815af /server.c
parentUpdate Makefile (diff)
downloadldadp-c12db031150b104e8811828fbfb2a97b270caafd.tar.gz
ldadp-c12db031150b104e8811828fbfb2a97b270caafd.tar.xz
ldadp-c12db031150b104e8811828fbfb2a97b270caafd.zip
Send search requests to server only after bind succeeded.
There are server implementations that ignore a search request if it is sent in the same packet as the bind request, apparently leaving it in some server side buffer. If another search request is received by the server afterwards, it suddenly discovers the first search request, handles it, and then proceeds to handle the second one. So we now buffer all search requests we want to forward to the server until we received a positive bind response from the server.
Diffstat (limited to 'server.c')
-rw-r--r--server.c50
1 files changed, 42 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;
}