summaryrefslogtreecommitdiffstats
path: root/proxy.c
diff options
context:
space:
mode:
authorSimon Rettberg2015-06-26 14:58:03 +0200
committerSimon Rettberg2015-06-26 14:58:03 +0200
commit2e37d6b71692508fa5d2764c1c80f3c7ca7c2894 (patch)
tree7a2e3240c380b9c532fc990dfefc1179eb3a1420 /proxy.c
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
Diffstat (limited to 'proxy.c')
-rw-r--r--proxy.c98
1 files changed, 60 insertions, 38 deletions
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);