summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ldadp.c2
-rw-r--r--proxy.c142
-rw-r--r--server.c10
-rw-r--r--server.h2
-rw-r--r--types.h1
5 files changed, 152 insertions, 5 deletions
diff --git a/ldadp.c b/ldadp.c
index 3b8d5f6..a47fba0 100644
--- a/ldadp.c
+++ b/ldadp.c
@@ -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);
}
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) {
diff --git a/server.c b/server.c
index d24af1a..3dd69b5 100644
--- a/server.c
+++ b/server.c
@@ -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
}
}
diff --git a/server.h b/server.h
index 813634b..417fa88 100644
--- a/server.h
+++ b/server.h
@@ -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);
diff --git a/types.h b/types.h
index 183c41f..d39c3be 100644
--- a/types.h
+++ b/types.h
@@ -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;