From 2e37d6b71692508fa5d2764c1c80f3c7ca7c2894 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 26 Jun 2015 14:58:03 +0200 Subject: Send search requests on the same connection the explicit bind was done on, so the user's permissions regarding visibility of search results will be applied --- server.c | 99 ++++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 50 insertions(+), 49 deletions(-) (limited to 'server.c') diff --git a/server.c b/server.c index 91164bb..2fdb601 100644 --- a/server.c +++ b/server.c @@ -22,7 +22,6 @@ static int serverCount = 0; static void server_init(); static server_t *server_create(const char *server); -static void server_free(epoll_server_t *server); static void server_callback(void *data, int haveIn, int haveOut, int doCleanup); static void server_haveIn(epoll_server_t *server); static void server_haveOut(epoll_server_t * const server); @@ -171,6 +170,12 @@ server_t *server_getFromBase(struct string *in) uint32_t server_searchRequest(server_t *server, struct SearchRequest *req) { if (!server_ensureConnected(server)) return 0; + epoll_server_t * const s = &server->con; + return server_searchRequestOnConnection(s, req); +} + +uint32_t server_searchRequestOnConnection(epoll_server_t *server, struct SearchRequest *req) +{ const uint32_t msgid = msgId(); const size_t bodyLen = fmt_ldapsearchrequest(NULL, req); const size_t headerLen = fmt_ldapmessage(NULL, msgid, SearchRequest, bodyLen); @@ -178,36 +183,35 @@ uint32_t server_searchRequest(server_t *server, struct SearchRequest *req) char *bufoff = buffer + 50; fmt_ldapsearchrequest(bufoff, req); fmt_ldapmessage(bufoff - headerLen, msgid, SearchRequest, bodyLen); - epoll_server_t * const s = &server->con; - server_send(s, bufoff - headerLen, headerLen + bodyLen, FALSE); + server_send(server, bufoff - headerLen, headerLen + bodyLen, FALSE); return msgid; } -uint32_t server_tryUserBind(server_t *server, struct string *binddn, struct string *password) +uint32_t server_tryUserBind(server_t *server, struct string *binddn, struct string *password, epoll_server_t **newcon) { epoll_server_t *con = calloc(1, sizeof(epoll_server_t)); con->serverData = server; con->fd = -1; con->bound = FALSE; con->dynamic = TRUE; - printf("Connecting to AD '%s' for %.*ss bind...\n", server->addr, (int)binddn->l, binddn->s); con->sbPos = con->sbFill = 0; int sock = server_connectInternal(server); if (sock == -1) { + printf("[Proxy] Could not connect to AD for user bind.\n"); server_free(con); return 0; } - printf("[ADB] Connected, binding....\n"); helper_nonblock(sock); con->fd = sock; con->callback = &server_callback; if (ePoll_add(EPOLLIN | EPOLLOUT | EPOLLET, (epoll_item_t*)con) == -1) { - printf("[ADB] epoll_add failed for ad server %s\n", server->addr); + printf("[Proxy] epoll_add failed for AD server %s on user bind\n", server->addr); server_free(con); return 0; } // SSL if (!server_connectSsl(con)) { + printf("[Proxy] SSL handshake failed for AD server %s on user bind\n", server->addr); server_free(con); return 0; } @@ -218,13 +222,14 @@ uint32_t server_tryUserBind(server_t *server, struct string *binddn, struct stri char buffer[bodyLen + 50]; char *bufoff = buffer + 50; if (headerLen >= 50) { - printf("[ADB] bind too long for %s\n", server->addr); + printf("[Proxy] User bind too long for %s\n", server->addr); server_free(con); return 0; } fmt_ldapbindrequeststring(bufoff, 3, binddn, password); fmt_ldapmessage(bufoff - headerLen, id, BindRequest, bodyLen); server_send(con, bufoff - headerLen, bodyLen + headerLen, FALSE); + *newcon = con; return id; } @@ -254,8 +259,9 @@ static server_t *server_create(const char *server) return &servers[serverCount++]; } -static void server_free(epoll_server_t *server) +void server_free(epoll_server_t *server) { + proxy_removeServer(server); server->bound = FALSE; if (server->ssl != NULL) { SSL_free(server->ssl); @@ -267,7 +273,7 @@ static void server_free(epoll_server_t *server) } server->sbPos = server->sbFill = 0; if (server->dynamic) { - printf("Freeing Bind-AD-Connection\n"); + //printf("Freeing Bind-AD-Connection\n"); free(server->sendBuffer); free(server); } @@ -276,38 +282,37 @@ static void server_free(epoll_server_t *server) static void server_callback(void *data, int haveIn, int haveOut, int doCleanup) { epoll_server_t *server = (epoll_server_t *)data; - if (doCleanup || server->kill) { - server_free(server); - return; - } if (server->ssl == NULL) { // Plain connection if (haveIn) server_haveIn(server); if (haveOut) server_haveOut(server); - if (server->kill) server_free(server); - return; - } - // SSL - if (!server->sslConnected) { - // Still SSL-Connecting - if (!ssl_connectServer(server)) { - printf("SSL Server connect failed!\n"); - server_free(server); - return; + } else { + // SSL + if (!server->sslConnected) { + // Still SSL-Connecting + if (!ssl_connectServer(server)) { + printf("[Proxy] SSL handshake for AD server %s failed.\n", server->serverData->addr); + server_free(server); + 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); } - if (!server->sslConnected) return; } - // 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 (server->kill) server_free(server); + if (doCleanup || server->kill) { + server_free(server); + } } static void server_haveIn(epoll_server_t *server) { for (;;) { if (server->rbPos >= MAXMSGLEN) { - printf("[AD->Proxy] Read buffer overflow. Disconnecting.\n"); + printf("[Proxy] Buffer overflow while reading from AD server. Disconnecting.\n"); server->kill = TRUE; return; } @@ -316,11 +321,10 @@ static void server_haveIn(epoll_server_t *server) if (server->ssl == NULL) { // Plain ret = read(server->fd, server->readBuffer + server->rbPos, buflen); - printf("AD read %d (err %d)\n", (int)ret, errno); if (ret < 0 && errno == EINTR) continue; if (ret < 0 && errno == EAGAIN) break; + if (ret < 0) printf("[Proxy] AD Server %s gone while reading (ret=%d, errno=%d).\n", server->serverData->addr, (int)ret, errno); if (ret <= 0) { - printf("AD Server gone while reading.\n"); server->kill = TRUE; return; } @@ -330,7 +334,7 @@ static void server_haveIn(epoll_server_t *server) if (ret <= 0) { int err = SSL_get_error(server->ssl, ret); if (SSL_BLOCKED(err)) break; - printf("AD Server gone while reading (%d, %d).\n", (int)ret, err); + if (err != 0) printf("[Proxy] AD Server %s gone while reading (ret=%d, err=%d).\n", server->serverData->addr, (int)ret, err); server->kill = TRUE; return; } @@ -343,13 +347,13 @@ static void server_haveIn(epoll_server_t *server) if (consumed == 0) break; // Length-Header not complete len += consumed; if (len > server->rbPos) break; // Body not complete - printf("[AD] Received complete reply (need %d, have %d)...\n", (int)len, (int)server->rbPos); + //printf("[AD] Received complete reply (need %d, have %d)...\n", (int)len, (int)server->rbPos); if (!proxy_fromServer(server, len)) { if (server->dynamic) { server->kill = TRUE; return; } - printf("Error parsing reply from AD.\n"); + printf("[Proxy] Error parsing message from AD.\n"); // Let's try to go on with the next message.... } // Shift remaining buffer contents @@ -370,14 +374,13 @@ BOOL server_send(epoll_server_t *server, const char *buffer, size_t len, const B // Nothing in send buffer, fire away const int ret = write(server->fd, buffer, len); if (ret == 0 || (ret < 0 && errno != EINTR && errno != EAGAIN)) { - printf("Server gone when trying to send.\n"); + printf("[Proxy] AD Server %s gone when trying to send.\n", server->serverData->addr); return FALSE; } server->lastActive = time(NULL); if (ret == (int)len) return TRUE; // Couldn't send everything, continue with buffering logic below if (ret > 0) { - printf("[AD] Partial send (%d of %d)\n", ret, (int)len); buffer += ret; len -= (size_t)ret; } @@ -405,7 +408,7 @@ static void server_haveOut(epoll_server_t * const server) if (ret < 0 && errno == EINTR) continue; if (ret < 0 && errno == EAGAIN) return; if (ret <= 0) { - printf("Connection to AD Server failed while flushing (ret: %d, errno: %d)\n", (int)ret, errno); + printf("[Proxy] AD Server %s gone while flushing send buffer (ret=%d, errno=%d)\n", server->serverData->addr, (int)ret, errno); return; } } else { @@ -419,7 +422,7 @@ static void server_haveOut(epoll_server_t * const server) } else if (err == SSL_ERROR_SSL) { ssl_printErrors(NULL); } - printf("SSL server gone while sending (%d)\n", err); + printf("[Proxy] AD Server %s gone while flushing send buffer (ret=%d, err=%d)\n", server->serverData->addr, (int)ret, err); ERR_print_errors_fp(stdout); server->kill = TRUE; return; // Closed @@ -443,16 +446,14 @@ static BOOL server_ensureConnected(server_t *server) if (con->fd != -1 && con->lastActive + 120 > time(NULL)) return TRUE; if (con->fd != -1) close(con->fd); con->bound = FALSE; - printf("Connecting to AD '%s'...\n", server->addr); con->sbPos = con->sbFill = 0; int sock = server_connectInternal(server); if (sock == -1) return FALSE; - printf("Connected, binding....\n"); helper_nonblock(sock); con->fd = sock; con->callback = &server_callback; if (ePoll_add(EPOLLIN | EPOLLOUT | EPOLLET, (epoll_item_t*)con) == -1) { - printf("epoll_add failed for ad server %s\n", server->addr); + printf("[Proxy] epoll_add failed for ad server %s\n", server->addr); close(con->fd); con->fd = -1; return FALSE; @@ -469,7 +470,7 @@ static BOOL server_ensureConnected(server_t *server) char buffer[bodyLen + 50]; char *bufoff = buffer + 50; if (headerLen >= 50) { - printf("[AD] bind too long for %s\n", server->addr); + printf("[Proxy] bind too long for %s\n", server->addr); close(con->fd); con->fd = -1; return FALSE; @@ -488,7 +489,7 @@ static BOOL server_ensureSendBuffer(epoll_server_t * const s, const size_t len) } if (s->sbLen - s->sbFill < len) { if (s->writeBlocked) { - printf("SSL Write blocked and buffer to small (%d)\n", (int)s->sbLen); + printf("[Proxy] SSL write to AD server blocked and buffer to small (%d bytes)\n", (int)s->sbLen); return FALSE; } if (s->sbPos != 0) { @@ -512,17 +513,17 @@ static int server_connectInternal(server_t *server) if (server->lastLookup + 300 < time(NULL)) { sock = helper_connect4(server->addr, port, server->ip); if (sock == -1) { - printf("Could not resolve/connect to AD server %s\n", server->addr); + printf("[Proxy] Could not resolve hostname or connect to AD server %s\n", server->addr); return -1; } } else { sock = socket_tcp4b(); if (sock == -1) { - printf("Could not allocate socket for connection to AD\n"); + printf("[Proxy] Could not allocate socket for connection to AD server %s\n", server->addr); return -1; } if (socket_connect4(sock, server->ip, port) == -1) { - printf("Could not connect to cached IP of %s\n", server->addr); + printf("[Proxy] Could not connect to cached IP (%s) of %s\n", server->ip, server->addr); server->lastLookup = 0; close(sock); return -1; @@ -537,11 +538,11 @@ static BOOL server_connectSsl(epoll_server_t *server) server->sslConnected = FALSE; server->ssl = ssl_new(server->fd, server->serverData->sslContext); if (server->ssl == NULL) { - printf("Could not get SSL client from context\n"); + printf("[Proxy] Could not get SSL client from context\n"); return FALSE; } if (!ssl_connectServer(server)) { - printf("SSL connect failed.\n"); + printf("[Proxy] SSL connect to AD server %s failed.\n", server->serverData->addr); SSL_free(server->ssl); server->ssl = NULL; return FALSE; -- cgit v1.2.3-55-g7522