diff options
-rw-r--r-- | ldadp.c | 2 | ||||
-rw-r--r-- | proxy.c | 142 | ||||
-rw-r--r-- | server.c | 10 | ||||
-rw-r--r-- | server.h | 2 | ||||
-rw-r--r-- | types.h | 1 |
5 files changed, 152 insertions, 5 deletions
@@ -129,6 +129,8 @@ static int loadConfig_handler(void *stuff, const char *section, const char *key, if (value[0] != '\0') server_setFingerprint(section, value); } else if (strcmp(key, "port") == 0) { server_setPort(section, value); + } else if (strcmp(key, "plainldap") == 0) { + server_setPlainLdap(section, value); } else { printf("Unknown ADS config option '%s' for server '%s'\n", key, section); } @@ -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) { @@ -52,6 +52,14 @@ void server_setPort(const char *server, const char *portStr) entry->port = (uint16_t)port; } +void server_setPlainLdap(const char *server, const char *enabledStr) +{ + server_t *entry = server_create(server); + if (entry == NULL) return; + entry->plainLdap = atoi(enabledStr) != 0 || strcmp(enabledStr, "true") == 0 + || strcmp(enabledStr, "True") == 0 || strcmp(enabledStr, "TRUE") == 0; +} + void server_setBind(const char *server, const char *bind) { server_t *entry = server_create(server); @@ -377,7 +385,7 @@ static void server_haveIn(epoll_server_t *server) memmove(server->readBuffer, server->readBuffer + len, server->rbPos - len); server->rbPos -= len; } - if ((ssize_t)buflen > ret) break; // Read less than buffer len, epoll will fire again + if (server->ssl == NULL && (ssize_t)buflen > ret) break; // Read less than buffer len, epoll will fire again } } @@ -8,6 +8,8 @@ struct SearchRequest; void server_setPort(const char *server, const char *portStr); +void server_setPlainLdap(const char *server, const char *enabledStr); + void server_setBind(const char *server, const char *bind); void server_setPassword(const char *server, const char *password); @@ -102,6 +102,7 @@ struct _server_t_ { char sid[SIDLEN]; char homeTemplate[MOUNTLEN]; unsigned char fingerprint[FINGERPRINTLEN]; + BOOL plainLdap; uint16_t port; SSL_CTX *sslContext; epoll_server_t con; |