summaryrefslogtreecommitdiffstats
path: root/proxy.c
diff options
context:
space:
mode:
authorSimon Rettberg2015-09-12 14:33:23 +0200
committerSimon Rettberg2015-09-12 14:33:23 +0200
commitf49899e409c8dde0953c83cd766ff0be75b88381 (patch)
treedb736d065addc29bbdb5834750001a53718e2377 /proxy.c
parentError handling in server.c (diff)
downloadldadp-f49899e409c8dde0953c83cd766ff0be75b88381.tar.gz
ldadp-f49899e409c8dde0953c83cd766ff0be75b88381.tar.xz
ldadp-f49899e409c8dde0953c83cd766ff0be75b88381.zip
Support LDAP-LDAP proxying
Diffstat (limited to 'proxy.c')
-rw-r--r--proxy.c142
1 files changed, 138 insertions, 4 deletions
diff --git a/proxy.c b/proxy.c
index a709616..e71134f 100644
--- a/proxy.c
+++ b/proxy.c
@@ -160,7 +160,10 @@ void proxy_removeClient(epoll_client_t * const client)
{
int i, lastValid = -1;
for (i = 0; i < _pendingCount; ++i) {
- if (_pendingRequest[i].client == client) _pendingRequest[i].client = NULL;
+ if (_pendingRequest[i].client == client) {
+ printf("RemoveClient success %p\n", client);
+ _pendingRequest[i].client = NULL;
+ }
else if (_pendingRequest[i].client != NULL) lastValid = i;
}
_pendingCount = lastValid + 1;
@@ -261,6 +264,8 @@ static BOOL request_getGroupFilter(struct Filter *filter, struct string *wantedG
static void request_replaceFilter(server_t *server, struct Filter **filter);
static void request_replaceAdl(server_t *server, struct AttributeDescriptionList **adl, attr_t *attr);
static BOOL request_replaceAttribute(server_t *server, struct string *attribute, struct string *value, attr_t *attr);
+static void request_replaceAdlLdap(server_t *server, struct AttributeDescriptionList **adl, attr_t *attr);
+static BOOL request_replaceAttributeLdap(server_t *server, struct string *attribute, struct string *value, attr_t *attr);
static BOOL request_isUserFilter(struct Filter *filter)
{
@@ -386,6 +391,9 @@ static void request_replaceFilter(server_t *server, struct Filter **filter)
#define elifSETATTR(x) else if (equals(&(*adl)->a, &s_ ## x)) attr->x = TRUE, next = (*adl)->next, free(*adl), *adl = next
static void request_replaceAdl(server_t *server, struct AttributeDescriptionList **adl, attr_t *attr)
{
+ if (server->plainLdap) {
+ return request_replaceAdlLdap(server, adl, attr);
+ }
while (*adl != NULL) {
struct AttributeDescriptionList *next = NULL;
if (attr == NULL) { }
@@ -407,10 +415,12 @@ static void request_replaceAdl(server_t *server, struct AttributeDescriptionList
}
}
}
-#undef elifSETATTR
static BOOL request_replaceAttribute(server_t *server, struct string *attribute, struct string *value, attr_t *attr)
{
+ if (server->plainLdap) {
+ return request_replaceAttributeLdap(server, attribute, value, attr);
+ }
if (equals(attribute, &s_uid)) {
*attribute = s_sAMAccountName;
if (attr) attr->hasUser = TRUE;
@@ -438,11 +448,43 @@ static BOOL request_replaceAttribute(server_t *server, struct string *attribute,
return TRUE;
}
+// ----------------- LDAP to LDAP handling
+
+static void request_replaceAdlLdap(server_t *server, struct AttributeDescriptionList **adl, attr_t *attr)
+{
+ while (*adl != NULL) {
+ struct AttributeDescriptionList *next = NULL;
+ if (attr == NULL) { }
+ elifSETATTR(homeDirectory);
+ elifSETATTR(gidNumber);
+ elifSETATTR(gecos);
+ elifSETATTR(realAccount);
+ elifSETATTR(loginShell);
+ else request_replaceAttributeLdap(server, &(*adl)->a, NULL, attr);
+ if (*adl == NULL) break;
+ if (next == NULL) adl = &(*adl)->next; // If next is not NULL, we removed an entry, so we don't need to shift
+ }
+}
+
+static BOOL request_replaceAttributeLdap(server_t *server, struct string *attribute, struct string *value, attr_t *attr)
+{
+ if (equals(attribute, &s_uid)) {
+ // If uid is of format s[0-9]+, we assume that it's a numeric account name in AD, as a workaround
+ if (value == NULL) return FALSE;
+ fixUnNumeric(value);
+ }
+ return TRUE;
+}
+#undef elifSETATTR
+
// --------- AD to client replacements
static void response_replacePal(server_t *server, struct PartialAttributeList **pal, attr_t *attr);
static void response_replaceAdl(server_t *server, struct string *type, struct AttributeDescriptionList **adl, attr_t *attr);
static void response_replaceAttribute(server_t *server, struct string *attribute, struct string *value);
+static void response_replacePalLdap(server_t *server, struct PartialAttributeList **pal, attr_t *attr);
+static void response_replaceAdlLdap(server_t *server, struct string *type, struct AttributeDescriptionList **adl, attr_t *attr);
+static void response_replaceAttributeLdap(server_t *server, struct string *attribute, struct string *value);
static BOOL response_filterHomeDir(struct PartialAttributeList *pal);
static struct PartialAttributeList* response_addPal(struct PartialAttributeList *pal, struct string *attribute, const char *format, ...);
@@ -451,6 +493,9 @@ static struct PartialAttributeList* response_addPal(struct PartialAttributeList
#define elifDEL(x) else if (equals(&(*pal)->type, &s_ ## x)) next = (*pal)->next, del = TRUE
static void response_replacePal(server_t *server, struct PartialAttributeList **pal, attr_t *attr)
{
+ if (server->plainLdap) {
+ return response_replacePalLdap(server, pal, attr);
+ }
struct string *username = NULL;
struct AttributeDescriptionList *lastObjectClass = NULL;
struct PartialAttributeList *next = NULL;
@@ -523,11 +568,12 @@ static void response_replacePal(server_t *server, struct PartialAttributeList **
lastObjectClass->next->a = s_shadowAccount;
}
}
-#undef ADDATTR
-#undef elifDELATTR
static void response_replaceAdl(server_t *server, struct string *type, struct AttributeDescriptionList **adl, attr_t *attr)
{
+ if (server->plainLdap) {
+ return response_replaceAdlLdap(server, type, adl, attr);
+ }
while (*adl != NULL) {
struct AttributeDescriptionList *next = NULL;
// Maybe delete entries here later
@@ -543,6 +589,9 @@ static void response_replaceAdl(server_t *server, struct string *type, struct At
static void response_replaceAttribute(server_t *server, struct string *attribute, struct string *value)
{
+ if (server->plainLdap) {
+ return response_replaceAttributeLdap(server, attribute, value);
+ }
if (equals(attribute, &s_sAMAccountName)) {
*attribute = s_uid;
if (value != NULL) fixNumeric(value);
@@ -591,6 +640,89 @@ static struct PartialAttributeList* response_addPal(struct PartialAttributeList
return next;
}
+// ---- replace response for LDAP to LDAP
+
+static void response_replacePalLdap(server_t *server, struct PartialAttributeList **pal, attr_t *attr)
+{
+ struct string *username = NULL;
+ struct PartialAttributeList *next = NULL;
+ BOOL wasNumeric = FALSE;
+ while (*pal != NULL) {
+ BOOL del = FALSE;
+ if (0) { } // Remove fields we don't want from AD
+ elifDELATTR(gidNumber);
+ elifDELATTR(gecos);
+ elifDELATTR(loginShell);
+ elifDEL(mail);
+ elifDELATTR(cn);
+ elifDEL(memberOf);
+ else if (equals(&(*pal)->type, &s_homeDirectory)) {
+ // homeDirectory is set in AD - it can either be a local path (in which case it's useless)
+ // or a UNC path, which we can easily mount via mount.cifs
+ if (!response_filterHomeDir(*pal)) {
+ del = TRUE;
+ attr->homeMount = TRUE;
+ next = (*pal)->next;
+ } else {
+ attr->homeMount = FALSE;
+ }
+ }
+ // Entry should be removed, free structs
+ if (del) {
+ free_ldapadl((*pal)->values);
+ free(*pal);
+ *pal = next;
+ continue;
+ }
+ response_replaceAdlLdap(server, &(*pal)->type, &(*pal)->values, attr);
+ // Fetch user name so we can add our fake fields later
+ if (username == NULL && equals(&(*pal)->type, &s_uid)) {
+ username = &(*pal)->values->a;
+ if (username->l > 1 && username->s[0] == 's' && isInt(username, 1)) wasNumeric = TRUE;
+ }
+ pal = &(*pal)->next;
+ }
+ if (username != NULL) {
+ char *user = tmpbuffer_get();
+ snprintf(user, TMPLEN, "%.*s", (int)username->l, username->s);
+ 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') {
+ ADDATTR(homeMount, server->homeTemplate, user, user, user, user, user, user);
+ }
+ // Do this here so user++ will have been executed
+ ADDATTR(realAccount, "%s", user);
+ }
+ ADDATTR(loginShell, "/bin/bash");
+ ADDATTR(gidNumber, "1001");
+}
+#undef ADDATTR
+#undef elifDELATTR
+
+static void response_replaceAdlLdap(server_t *server, struct string *type, struct AttributeDescriptionList **adl, attr_t *attr)
+{
+ while (*adl != NULL) {
+ struct AttributeDescriptionList *next = NULL;
+ // Maybe delete entries here later
+ if (next != NULL) {
+ free(*adl);
+ *adl = next;
+ continue;
+ }
+ response_replaceAttributeLdap(server, type, &(*adl)->a);
+ adl = &(*adl)->next; // If next is not NULL, we removed an entry, so we don't need to shift
+ }
+}
+
+static void response_replaceAttributeLdap(server_t *server, struct string *attribute, struct string *value)
+{
+ if (equals(attribute, &s_uid)) {
+ if (value != NULL) fixNumeric(value);
+ }
+}
+
// -----
static BOOL proxy_clientSearchRequest(epoll_client_t *client, const unsigned long messageId, const size_t offset, const size_t maxLen)
@@ -647,6 +779,7 @@ static BOOL proxy_clientSearchRequest(epoll_client_t *client, const unsigned lon
printf("Failed to forward search request.\n");
pending->client = NULL;
}
+ printf("C->S: %lu -> %lu\n", pending->clientMessageId, pending->serverMessageId);
free_ldapsearchrequest(&req);
//
if (pending->client == NULL) return FALSE;
@@ -662,6 +795,7 @@ static BOOL proxy_serverSearchResult(epoll_server_t *server, const unsigned long
printf("[AD] Received message with unknown messageId %lu, ignoring\n", messageId);
return TRUE;
}
+ printf("S->C: %lu -> %lu\n", messageId, pending->clientMessageId);
const char *body;
size_t bodyLen;
if (type == SearchResultDone) {