From f49899e409c8dde0953c83cd766ff0be75b88381 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Sat, 12 Sep 2015 14:33:23 +0200 Subject: Support LDAP-LDAP proxying --- proxy.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 4 deletions(-) (limited to 'proxy.c') 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) { -- cgit v1.2.3-55-g7522