summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2015-06-26 14:58:03 +0200
committerSimon Rettberg2015-06-26 14:58:03 +0200
commit2e37d6b71692508fa5d2764c1c80f3c7ca7c2894 (patch)
tree7a2e3240c380b9c532fc990dfefc1179eb3a1420
parentFix the fix of the fix of SSL (diff)
downloadldadp-2e37d6b71692508fa5d2764c1c80f3c7ca7c2894.tar.gz
ldadp-2e37d6b71692508fa5d2764c1c80f3c7ca7c2894.tar.xz
ldadp-2e37d6b71692508fa5d2764c1c80f3c7ca7c2894.zip
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
-rw-r--r--client.c30
-rw-r--r--client.h2
-rw-r--r--helper.c12
-rw-r--r--helper.h1
-rw-r--r--ldadp.c14
-rw-r--r--proxy.c98
-rw-r--r--proxy.h4
-rw-r--r--server.c99
-rw-r--r--server.h6
-rw-r--r--types.h12
10 files changed, 162 insertions, 116 deletions
diff --git a/client.c b/client.c
index f2c9683..906b718 100644
--- a/client.c
+++ b/client.c
@@ -15,7 +15,7 @@
static void client_haveIn(epoll_client_t *client);
static void client_haveOut(epoll_client_t *client);
-static void client_free(epoll_client_t *client)
+void client_free(epoll_client_t *client)
{
proxy_removeClient(client);
if (client->sendBuffer != NULL) free(client->sendBuffer);
@@ -31,7 +31,7 @@ void client_callback(void *data, int haveIn, int haveOut, int doCleanup)
{
epoll_client_t *client = (epoll_client_t*)data;
if (doCleanup || client->kill) {
- printf("Client gone (1).\n");
+ //printf("Client gone (1).\n");
client_free(client);
return;
}
@@ -40,7 +40,7 @@ void client_callback(void *data, int haveIn, int haveOut, int doCleanup)
if (haveIn) client_haveIn(client);
if (haveOut) client_haveOut(client);
if (client->kill) {
- printf("Client gone (2).\n");
+ //printf("Client gone (2).\n");
client_free(client);
}
return;
@@ -49,7 +49,7 @@ void client_callback(void *data, int haveIn, int haveOut, int doCleanup)
if (!client->sslAccepted) {
// Still SSL-Connecting
if (!ssl_acceptClient(client)) {
- printf("SSL Client accept failed.\n");
+ printf("[Proxy] SSL Client accept failed.\n");
client_free(client);
return;
}
@@ -59,7 +59,7 @@ void client_callback(void *data, int haveIn, int haveOut, int doCleanup)
client_haveIn(client);
client_haveOut(client);
if (client->kill) {
- printf("Client gone (3).\n");
+ //printf("Client gone (3).\n");
client_free(client);
}
}
@@ -68,7 +68,7 @@ static void client_haveIn(epoll_client_t *client)
{
for (;;) {
if (client->rbPos >= REQLEN) {
- printf("[C->Proxy] Read buffer overflow. Disconnecting.\n");
+ printf("[Proxy] Buffer overflow reading from client. Disconnecting.\n");
client->kill = TRUE;
return;
}
@@ -80,7 +80,7 @@ static void client_haveIn(epoll_client_t *client)
if (ret < 0 && errno == EINTR) continue;
if (ret < 0 && errno == EAGAIN) break;
if (ret <= 0) {
- printf("Client gone while reading.\n");
+ printf("[Proxy] Client gone while reading (ret=%d, errno=%d).\n", (int)ret, errno);
client->kill = TRUE;
return;
}
@@ -90,7 +90,7 @@ static void client_haveIn(epoll_client_t *client)
if (ret <= 0) {
int err = SSL_get_error(client->ssl, ret);
if (SSL_BLOCKED(err)) break;
- printf("Client gone while reading (%d, %d).\n", (int)ret, err);
+ printf("[Proxy] SSL client gone while reading (ret=%d, err=%d).\n", (int)ret, err);
client->kill = TRUE;
return;
}
@@ -104,9 +104,8 @@ static void client_haveIn(epoll_client_t *client)
if (consumed == 0) break; // Length-Header not complete
len += consumed;
if (len > client->rbPos) break; // Body not complete yet
- printf("Received complete requrest...\n");
if (!proxy_fromClient(client, len)) {
- printf("Error parsing request from client.\n");
+ printf("[Proxy] Error parsing request from client.\n");
client->kill = TRUE;
return;
}
@@ -134,7 +133,7 @@ static void client_haveOut(epoll_client_t *client)
if (ret < 0 && errno == EINTR) continue;
if (ret < 0 && errno == EAGAIN) return;
if (ret <= 0) {
- printf("Cannot send to client (ret: %d, errno: %d)\n", (int)ret, errno);
+ printf("[Proxy] Cannot send to client (ret=%d, errno=%d)\n", (int)ret, errno);
client->kill = TRUE;
return;
}
@@ -147,7 +146,7 @@ static void client_haveOut(epoll_client_t *client)
client->writeBlocked = TRUE;
return; // Blocking
}
- printf("SSL client gone while sending (%d)\n", err);
+ printf("[Proxy] SSL cannot send to client (ret=%d, err=%d)\n", (int)ret, err);
ERR_print_errors_fp(stdout);
client->kill = TRUE;
return; // Closed
@@ -173,7 +172,7 @@ BOOL client_send(epoll_client_t *client, const char *buffer, size_t len, const B
// Nothing in send buffer, fire away
const int ret = write(client->fd, buffer, len);
if (ret == 0 || (ret < 0 && errno != EINTR && errno != EAGAIN)) {
- printf("Client gone when trying to send.\n");
+ printf("[Proxy] Client gone when trying to send.\n");
client->kill = TRUE;
return FALSE;
}
@@ -187,7 +186,7 @@ BOOL client_send(epoll_client_t *client, const char *buffer, size_t len, const B
// Buffer...
if (client->sbLen - client->sbFill < len) { // Buffer too small?
if (client->writeBlocked) {
- printf("SSL Write blocked and buffer to small (%d)\n", (int)client->sbLen);
+ printf("[Proxy] SSL write to client blocked and buffer to small (%d bytes)\n", (int)client->sbLen);
client->kill = TRUE;
return FALSE;
}
@@ -198,7 +197,7 @@ BOOL client_send(epoll_client_t *client, const char *buffer, size_t len, const B
}
// Sanity
if (client->sbFill + len > MAX_SEND_BUFFER) {
- printf("Dropping client as the send buffer would exceed %d bytes.\n", (int)MAX_SEND_BUFFER);
+ printf("[Proxy] Dropping client as the send buffer would exceed %d bytes.\n", (int)MAX_SEND_BUFFER);
client->kill = TRUE;
return FALSE;
}
@@ -207,7 +206,6 @@ BOOL client_send(epoll_client_t *client, const char *buffer, size_t len, const B
client->kill = TRUE;
return FALSE;
}
- printf("Send Buffer now %d\n", (int)client->sbLen);
}
}
// Finally append to buffer
diff --git a/client.h b/client.h
index 9a19439..2cc8090 100644
--- a/client.h
+++ b/client.h
@@ -3,6 +3,8 @@
#include "types.h"
+void client_free(epoll_client_t *client);
+
void client_callback(void *data, int haveIn, int haveOut, int doCleanup);
BOOL client_send(epoll_client_t *client, const char *buffer, size_t len, const BOOL cork);
diff --git a/helper.c b/helper.c
index c938783..b125f42 100644
--- a/helper.c
+++ b/helper.c
@@ -111,6 +111,18 @@ void helper_printal(struct AttributeDescriptionList* a)
putchar('\n');
}
+void helper_printpal(struct PartialAttributeList *pal)
+{
+ printf("-- PAL --\n");
+ while (pal) {
+ printf("entry (");
+ if (pal->type.l && pal->type.s) printf("%.*s", (int)pal->type.l, pal->type.s);
+ printf("): ");
+ helper_printal(pal->values);
+ pal = pal->next;
+ }
+}
+
static void helper_printfilterInt(struct Filter* f)
{
if (f == NULL) {
diff --git a/helper.h b/helper.h
index 840813d..838078f 100644
--- a/helper.h
+++ b/helper.h
@@ -11,6 +11,7 @@ void helper_nonblock(const int fd);
void helper_printava(struct AttributeValueAssertion* a,const char* rel);
void helper_printal(struct AttributeDescriptionList* a);
+void helper_printpal(struct PartialAttributeList *pal);
void helper_printfilter(struct Filter* f);
static inline int min(const int a, const int b)
diff --git a/ldadp.c b/ldadp.c
index 8d320a8..3b8d5f6 100644
--- a/ldadp.c
+++ b/ldadp.c
@@ -27,6 +27,7 @@ int main(int argc, char **argv)
printf("Nö\n");
exit(1);
}
+ setbuf(stdout, NULL);
signal(SIGPIPE, SIG_IGN);
if (strcmp(argv[1], "-n") == 0 && argc > 2) {
isdaemon = FALSE;
@@ -77,11 +78,10 @@ static void listen_callback(void *data, int haveIn, int haveOut, int doCleanup)
uint16 port;
int sock = socket_accept4(listen->fd, remote, &port);
if (sock < 0) {
- printf("Error accepting new connection.\n");
+ printf("[Proxy] Error accepting new connection.\n");
return;
}
helper_nonblock(sock);
- printf("Accepted connection.\n");
SSL *ssl = NULL;
if (listen->sslContext != NULL) {
ssl = ssl_new(sock, listen->sslContext);
@@ -95,7 +95,7 @@ static void listen_callback(void *data, int haveIn, int haveOut, int doCleanup)
client->callback = &client_callback;
client->ssl = ssl;
if (ssl != NULL && !ssl_acceptClient(client)) {
- printf("SSL-Accepting client failed.\n");
+ printf("[Proxy] SSL-Accepting client failed.\n");
SSL_free(ssl);
close(sock);
free(client);
@@ -123,10 +123,10 @@ static int loadConfig_handler(void *stuff, const char *section, const char *key,
server_setPassword(section, value);
} else if (strcmp(key, "base") == 0) {
server_setBase(section, value);
- } else if (strcmp(key, "home") == 0 && *value != '\0') {
- server_setHomeTemplate(section, value);
- } else if (strcmp(key, "fingerprint") == 0 && *value != '\0') {
- server_setFingerprint(section, value);
+ } else if (strcmp(key, "home") == 0) {
+ if (value[0] != '\0') server_setHomeTemplate(section, value);
+ } else if (strcmp(key, "fingerprint") == 0) {
+ if (value[0] != '\0') server_setFingerprint(section, value);
} else if (strcmp(key, "port") == 0) {
server_setPort(section, value);
} else {
diff --git a/proxy.c b/proxy.c
index 5bfbac7..a709616 100644
--- a/proxy.c
+++ b/proxy.c
@@ -9,6 +9,7 @@
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <sys/socket.h>
#define MAXPENDING 200
#define MAX(a,b) ((a) > (b) ? (a) : (b))
@@ -36,12 +37,6 @@ typedef struct
attr_t attr;
} pending_t;
-typedef struct
-{
- const char *search;
- struct string replace;
-} replace_t;
-
static pending_t _pendingRequest[MAXPENDING];
static int _pendingCount = 0;
@@ -148,7 +143,7 @@ BOOL proxy_fromClient(epoll_client_t *client, const size_t maxLen)
size_t len;
const size_t res = scan_ldapmessage(client->readBuffer, client->readBuffer + maxLen, &messageId, &op, &len);
if (res == 0) return FALSE;
- printf("[C] scan_ldapmessage: Consumed %d, remaining length %d, id %lu, op %lu\n", (int)res, (int)len, messageId, op);
+ //printf("[C] scan_ldapmessage: Consumed %d, remaining length %d, id %lu, op %lu\n", (int)res, (int)len, messageId, op);
// TODO: Caching
switch (op) {
case BindRequest:
@@ -161,7 +156,7 @@ BOOL proxy_fromClient(epoll_client_t *client, const size_t maxLen)
return TRUE;
}
-void proxy_removeClient(const epoll_client_t *client)
+void proxy_removeClient(epoll_client_t * const client)
{
int i, lastValid = -1;
for (i = 0; i < _pendingCount; ++i) {
@@ -169,6 +164,20 @@ void proxy_removeClient(const epoll_client_t *client)
else if (_pendingRequest[i].client != NULL) lastValid = i;
}
_pendingCount = lastValid + 1;
+ if (client->fixedServer != NULL) {
+ client->fixedServer->kill = TRUE;
+ shutdown(client->fixedServer->fd, SHUT_RDWR);
+ client->fixedServer->fixedClient = NULL;
+ }
+}
+
+void proxy_removeServer(epoll_server_t * const server)
+{
+ if (server->fixedClient != NULL) {
+ server->fixedClient->kill = TRUE;
+ if (server->fixedClient->sbFill == 0) shutdown(server->fixedClient->fd, SHUT_RDWR);
+ server->fixedClient->fixedServer = NULL;
+ }
}
BOOL proxy_fromServer(epoll_server_t *server, const size_t maxLen)
@@ -179,7 +188,7 @@ BOOL proxy_fromServer(epoll_server_t *server, const size_t maxLen)
if (res == 0) {
return FALSE;
}
- printf("[AD] scan_ldapmessage: Consumed %d, remaining length %d, id %lu, op %lu\n", (int)res, (int)len, messageId, op);
+ //printf("[AD] scan_ldapmessage: Consumed %d, remaining length %d, id %lu, op %lu\n", (int)res, (int)len, messageId, op);
switch (op) {
case BindResponse:
return proxy_serverBindResponse(server, messageId, res, maxLen);
@@ -496,8 +505,8 @@ static void response_replacePal(server_t *server, struct PartialAttributeList **
ADDATTR(homeDirectory, "/home/%s", user);
ADDATTR(gecos, "%s,,,", user);
ADDATTR(cn, "%s", user);
+ if (wasNumeric) user++; // From here on, user is the real AD username, no leading 's'
if (attr->homeMount && server->homeTemplate[0] != '\0') {
- if (wasNumeric) user++;
ADDATTR(homeMount, server->homeTemplate, user, user, user, user, user, user);
}
// Do this here so user++ will have been executed
@@ -596,20 +605,22 @@ static BOOL proxy_clientSearchRequest(epoll_client_t *client, const unsigned lon
}
server_t *server = server_getFromBase(&req.baseObject);
if (server == NULL) {
- printf("scan_ldapsearchrequest: baseObj '%.*s' unknown (scope %d).\n", (int)req.baseObject.l, req.baseObject.s, (int)req.scope);
+ printf("[Client] Invalid search request: baseObj '%.*s' unknown (scope %d).\n", (int)req.baseObject.l, req.baseObject.s, (int)req.scope);
return FALSE;
}
- printf("scan_ldapsearchrequest: baseObj: %.*s, scope: %d, derefAliases: %d\n", (int)req.baseObject.l, req.baseObject.s, req.scope, req.derefAliases);
+ //printf("scan_ldapsearchrequest: baseObj: %.*s, scope: %d, derefAliases: %d\n", (int)req.baseObject.l, req.baseObject.s, req.scope, req.derefAliases);
// Try to figure out if this is a lookup for a user/multiple users, or something else (eg. group)
if (!request_isUserFilter(req.filter)) {
// Handle locally
- printf("Handling local:\n");
+ printf("[Client] Search request (handling local): ");
helper_printfilter(req.filter);
const BOOL ret = proxy_localSearchRequest(client, messageId, &req);
free_ldapsearchrequest(&req);
return ret;
}
// Forward
+ printf("[Client] Search request (forwarding): ");
+ helper_printfilter(req.filter);
if (req.sizeLimit == 0 || req.sizeLimit > 20) req.sizeLimit = 20; // TODO: Magic value
pending_t *pending = proxy_getFreePendingSlot(client);
if (pending == NULL) {
@@ -622,15 +633,15 @@ static BOOL proxy_clientSearchRequest(epoll_client_t *client, const unsigned lon
} else {
request_replaceAdl(server, &req.attributes, &pending->attr);
}
- helper_printfilter(req.filter);
request_replaceFilter(server, &req.filter);
- helper_printfilter(req.filter);
- helper_printal(req.attributes);
- //printf("Attrs: ");
- //for (size_t i = 0; i < sizeof(attr_t); ++i) putchar(((char*)&pending->attr)[i] == 0 ? '0' : '1');
- //putchar('\n');
+ //helper_printfilter(req.filter);
+ //helper_printal(req.attributes);
pending->clientMessageId = messageId;
- pending->serverMessageId = server_searchRequest(server, &req);
+ if (client->fixedServer == NULL) {
+ pending->serverMessageId = server_searchRequest(server, &req);
+ } else {
+ pending->serverMessageId = server_searchRequestOnConnection(client->fixedServer, &req);
+ }
if (pending->serverMessageId == 0) {
// Failed to forward.. TODO: Fail client
printf("Failed to forward search request.\n");
@@ -648,10 +659,9 @@ static BOOL proxy_serverSearchResult(epoll_server_t *server, const unsigned long
if (bodyBuffer == NULL) bodyBuffer = malloc(MAXMSGLEN);
pending_t *pending = proxy_getPendingFromServer(messageId);
if (pending == NULL) {
- printf("No client matching server message id %lu\n", messageId);
+ printf("[AD] Received message with unknown messageId %lu, ignoring\n", messageId);
return TRUE;
}
- printf("ServerID %lu -> ClientID %lu\n", messageId, pending->clientMessageId);
const char *body;
size_t bodyLen;
if (type == SearchResultDone) {
@@ -700,36 +710,43 @@ static BOOL proxy_clientBindRequest(epoll_client_t *client, const unsigned long
if (res == 0) return FALSE; // Parsing request failed
if (method != 0) {
// Other than simple bind - currently not supported
- printf("Unsupported bind method: %lu\n", method);
+ printf("[Client] Unsupported bind method: %lu\n", method);
bodyLen = fmt_ldapbindresponse(bufoff, authMethodNotSupported, "", "SIMPLE only", "");
} else {
// Simple bind :-)
- const size_t res2 = scan_ldapstring(client->readBuffer + offset + res, client->readBuffer + maxLen, &password);
- printf("scan_ldapbindrequest: Consumed %d, version %lu, method %lu, name '%.*s'\n", (int)(res + res2), version, method, (int)name.l, name.s);
+ password.l = 0;
+ scan_ldapstring(client->readBuffer + offset + res, client->readBuffer + maxLen, &password);
+ //printf("scan_ldapbindrequest: Consumed %d, version %lu, method %lu, name '%.*s'\n", (int)(res + res2), version, method, (int)name.l, name.s);
if (name.l == 0 && password.l == 0) {
// Anonymous bind used for "normal" lookups
- printf("Anonymous bind ok\n");
+ printf("[Client] Anonymous bind accepted\n");
bodyLen = fmt_ldapbindresponse(bufoff, success, "", "main screen turn on", "");
} else {
+ BOOL incorrect;
server_t *server = server_getFromBase(&name);
- if (server == NULL || strncmp(password.s, "\x08\x0a\x0d\x7fINCORRECT", 13) == 0 || isInt(&name, 0)) {
- // The INCORRECT part is some weird thing I saw pam_ldap do - save the round trip to AD and deny
- printf("Password INCORRECT or binddn unknown or numeric username\n");
+ if (server == NULL || (incorrect = (strncmp(password.s, "\x08\x0a\x0d\x7fINCORRECT", 13) == 0)) || isInt(&name, 0)) {
+ // The INCORRECT part is some weird thing I saw pam_ldap do - probably to identify misconfigured
+ // LDAP servers/accounts that will accept any password - save the round trip to AD and deny
+ if (!incorrect) printf("[Client] Numeric account or invalid binddn for %.*s\n", (int)name.l, name.s);
bodyLen = fmt_ldapbindresponse(bufoff, invalidCredentials, "", "invalid credentials", "");
} else {
- // Seems to be an actual bind - forward to AD - TODO: SASL (DIGEST-MD5?)
+ // Seems to be an actual bind - forward to AD - TODO: SASL (DIGEST-MD5? Something?)
fixUnNumeric(&name);
pending_t *pending = proxy_getFreePendingSlot(client);
- const unsigned long smid = server_tryUserBind(server, &name, &password);
+ epoll_server_t *con;
+ const unsigned long smid = server_tryUserBind(server, &name, &password, &con);
if (pending == NULL || smid == 0) {
// Busy
if (pending != NULL) pending->client = NULL;
- printf("Too many pending requests, or cannot connect to AD\n");
+ printf("[Client] Too many pending requests, or cannot connect to AD for bind\n");
bodyLen = fmt_ldapbindresponse(bufoff, busy, "", "can't handle it", "");
} else {
// Request queued, client needs to wait
+ printf("[Client] Forwarding bind to AD for user %.*s\n", (int)name.l, name.s);
pending->clientMessageId = messageId;
pending->serverMessageId = smid;
+ con->fixedClient = client;
+ client->fixedServer = con;
return TRUE;
}
}
@@ -747,8 +764,13 @@ static BOOL proxy_serverBindResponse(epoll_server_t *server, const unsigned long
struct string binddn, error, refer;
const size_t res = scan_ldapbindresponse(server->readBuffer + offset, server->readBuffer + maxLen, &result, &binddn, &error, &refer);
if (res == 0) return FALSE; // Parsing request failed
- printf("scan_ldapbindresponse: Consumed %d, result: %lu, binddn: %.*s, error: %.*s, referral: %.*s\n", (int)res, result, (int)binddn.l, binddn.s, (int)error.l, error.s, (int)refer.l, refer.s);
- if (result == success) server->bound = TRUE;
+ //printf("scan_ldapbindresponse: Consumed %d, result: %lu, binddn: %.*s, error: %.*s, referral: %.*s\n", (int)res, result, (int)binddn.l, binddn.s, (int)error.l, error.s, (int)refer.l, refer.s);
+ server->bound = (result == success);
+ if (server->bound) {
+ printf("[AD] Accepted credentials (#%lu)\n", messageId);
+ } else {
+ printf("[AD] Wrong credentials (#%lu)\n", messageId);
+ }
if (messageId <= 1) return TRUE;
// Was a forwarded auth
pending_t *pending = proxy_getPendingFromServer(messageId);
@@ -759,7 +781,7 @@ static BOOL proxy_serverBindResponse(epoll_server_t *server, const unsigned long
client_send(pending->client, buffer, headerLen, TRUE);
client_send(pending->client, server->readBuffer + offset, res, FALSE);
pending->client = NULL;
- return FALSE; // Return FALSE here so server.c will kill off this server connection
+ return server->bound; // Return FALSE here so server.c will kill off this server connection
}
// ---- Local handling ----
@@ -778,7 +800,7 @@ static void prependPal(struct SearchResultEntry *dest, struct PartialAttributeLi
static BOOL proxy_localFeatureReply(epoll_client_t *client, const unsigned long messageId)
{
- printf("Sending fake feature request reply\n");
+ printf("[Proxy] Sending static feature request reply to client\n");
struct SearchResultEntry sre;
struct PartialAttributeList vers;
struct AttributeDescriptionList versVal;
@@ -818,7 +840,7 @@ static BOOL proxy_localSearchRequest(epoll_client_t *client, const unsigned long
}
if (number == 1001 || name.l != 0) {
// At least one of them was set
- printf("Sending fake group membership\n");
+ printf("[Proxy] Sending static group membership to client\n");
struct SearchResultEntry sre;
struct PartialAttributeList gidNumber, cn, objectClass;
struct AttributeDescriptionList gidNumberVal, cnVal, objectClassVal;
@@ -835,7 +857,7 @@ static BOOL proxy_localSearchRequest(epoll_client_t *client, const unsigned long
fmt_ldapsearchresultentry(buffer + headerLen, &sre);
client_send(client, buffer, headerLen + bodyLen, TRUE);
} else {
- printf("Sending empty posixGroup search result.\n");
+ printf("[Proxy] Sending empty posixGroup search result to client.\n");
}
const size_t doneLen = fmt_ldapsearchresultdone(NULL, success, "", "", "");
const size_t doneHeaderLen = fmt_ldapmessage(NULL, messageId, SearchResultDone, doneLen);
diff --git a/proxy.h b/proxy.h
index c54f896..f9a781e 100644
--- a/proxy.h
+++ b/proxy.h
@@ -7,7 +7,9 @@ void proxy_init();
BOOL proxy_fromClient(epoll_client_t *client, const size_t maxLen);
-void proxy_removeClient(const epoll_client_t *client);
+void proxy_removeClient(epoll_client_t * const client);
+
+void proxy_removeServer(epoll_server_t * const server);
BOOL proxy_fromServer(epoll_server_t *server, const size_t maxLen);
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;
diff --git a/server.h b/server.h
index 6c4d889..813634b 100644
--- a/server.h
+++ b/server.h
@@ -20,13 +20,17 @@ void server_setFingerprint(const char *server, const char *fingerprint);
BOOL server_initServers();
+void server_free(epoll_server_t *server);
+
BOOL server_send(epoll_server_t *server, const char *buffer, size_t len, const BOOL cork);
server_t *server_getFromBase(struct string *in);
uint32_t server_searchRequest(server_t *server, struct SearchRequest *req);
-uint32_t server_tryUserBind(server_t *server, struct string *binddn, struct string *password);
+uint32_t server_searchRequestOnConnection(epoll_server_t *con, struct SearchRequest *req);
+
+uint32_t server_tryUserBind(server_t *server, struct string *binddn, struct string *password, epoll_server_t **newcon);
#endif
diff --git a/types.h b/types.h
index 373b52a..183c41f 100644
--- a/types.h
+++ b/types.h
@@ -22,6 +22,8 @@
#define FALSE (0)
typedef struct _server_t_ server_t;
+typedef struct _epoll_client_t_ epoll_client_t;
+typedef struct _epoll_server_t_ epoll_server_t;
/**
* General epoll struct, to be implemented by every epoll struct.
@@ -44,7 +46,7 @@ typedef struct {
/**
* epoll struct for a client we're serving.
*/
-typedef struct {
+struct _epoll_client_t_ {
void (*callback)(void *data, int haveIn, int haveOut, int doCleanup);
int fd;
//
@@ -56,15 +58,16 @@ typedef struct {
size_t sbPos, sbFill, sbLen;
SSL *ssl; // NULL if not encrypted
char *sendBuffer; // Dynamically allocated, might or might not get huge
+ epoll_server_t *fixedServer; // If client performed explicit bind, tie to server connection
// Recv buffer (client's request)
size_t rbPos;
char readBuffer[REQLEN]; // Static, queries > 4000 bytes simply not supported
-} epoll_client_t;
+};
/**
* epoll struct for a connection to AD.
*/
-typedef struct {
+struct _epoll_server_t_ {
void (*callback)(void *data, int haveIn, int haveOut, int doCleanup);
int fd;
//
@@ -72,6 +75,7 @@ typedef struct {
size_t sbPos, sbFill, sbLen;
SSL *ssl; // NULL if not encrypted
char *sendBuffer; // Dynamically allocated, might or might not get huge
+ 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;
char readBuffer[MAXMSGLEN];
@@ -82,7 +86,7 @@ typedef struct {
BOOL writeBlocked; // An SSL_write returned WANT_*, so we must not reallocate the current send buffer
time_t lastActive;
server_t *serverData;
-} epoll_server_t;
+};
/**
* Configuration data for an ADS we're proxying.