diff options
author | Simon Rettberg | 2014-03-17 19:21:35 +0100 |
---|---|---|
committer | Simon Rettberg | 2014-03-17 19:21:35 +0100 |
commit | 18af18b35b72834284e079d79fae45a3d642676f (patch) | |
tree | b622d709bb19c06651b4bed884d85aaaae6442df | |
parent | Lean and mean initial commit (diff) | |
download | ldadp-18af18b35b72834284e079d79fae45a3d642676f.tar.gz ldadp-18af18b35b72834284e079d79fae45a3d642676f.tar.xz ldadp-18af18b35b72834284e079d79fae45a3d642676f.zip |
More progress.. Warning: Contains very ugly temporary hack for uidNumber<->objectSid mapping ;)
-rw-r--r-- | ldadp.c | 3 | ||||
-rw-r--r-- | proxy.c | 111 | ||||
-rw-r--r-- | server.c | 39 | ||||
-rw-r--r-- | server.h | 6 | ||||
-rw-r--r-- | types.h | 2 |
5 files changed, 91 insertions, 70 deletions
@@ -73,9 +73,6 @@ static int loadConfig_handler(void *stuff, const char *section, const char *key, if (strcmp(key, "base") == 0) { server_setBase(section, value); } - if (strcmp(key, "alias") == 0) { - server_setAlias(section, value); - } return 1; } @@ -40,10 +40,13 @@ typedef struct static pending_t _pendingRequest[MAXPENDING]; static int _pendingCount = 0; -static struct string s_shadowAccount, s_user, s_uid, s_sAMAccountName, s_objectSid; -static struct string s_objectclass, s_homeDirectory, s_gidNumber, s_gecos, s_dn; +static struct string s_shadowAccount, s_posixAccount, s_user, s_uid, s_sAMAccountName, s_objectSid; +static struct string s_objectclass, s_homeDirectory, s_gidNumber, s_gecos, s_dn, s_posixGroup; static struct string s_loginShell, s_uidNumber, s_mail, s_objectCategory, s_memberOf, s_distinguishedName; +static char osHack[200], osHackNum[12]; +static int osHackLen = 0; + // static int proxy_clientBindRequest(epoll_client_t *client, const unsigned long messageId, const size_t offset, const size_t maxLen); @@ -51,6 +54,8 @@ static int proxy_serverBindResponse(epoll_server_t *server, const unsigned long static int proxy_clientSearchRequest(epoll_client_t *client, const unsigned long messageId, const size_t offset, const size_t maxLen); static int proxy_serverSearchResult(epoll_server_t *server, const unsigned long messageId, const unsigned long type, const size_t offset, const size_t maxLen); +static int proxy_localSearchRequest(epoll_client_t *client, const unsigned long messageId, const struct SearchRequest *req); + // #define SETSTR(x) s_ ## x.s = #x; s_ ## x.l = strlen( #x ) @@ -60,6 +65,8 @@ void proxy_init() if (done) return; done = 1; SETSTR(shadowAccount); + SETSTR(posixAccount); + SETSTR(posixGroup); SETSTR(user); SETSTR(uid); SETSTR(sAMAccountName); @@ -178,10 +185,26 @@ static inline int iequals(struct string *a, struct string *b) // ---- client to AD replacements //#define PREF(...) do { pref(spaces, prefix); printf(__VA_ARGS__); } while (0) +static BOOL request_isUserFilter(struct Filter *filter); static void request_replaceFilter(struct Filter *filter); static void request_replaceAdl(struct AttributeDescriptionList **adl, attr_t *attr); static void request_replaceAttribute(struct string *attribute, struct string *value); +static BOOL request_isUserFilter(struct Filter *filter) +{ + for (; filter != NULL; filter = filter->next) { + if (filter->x != NULL && request_isUserFilter(filter->x)) return TRUE; + if (filter->type != EQUAL) continue; + if (iequals(&filter->ava.desc, &s_objectclass) && + (equals(&filter->ava.value, &s_posixAccount) || equals(&filter->ava.value, &s_shadowAccount))) { + return TRUE; + } else if (equals(&filter->ava.desc, &s_uid) || equals(&filter->ava.desc, &s_uidNumber)) { + return TRUE; + } + } + return FALSE; +} + static void request_replaceFilter(struct Filter *filter) { for (; filter != NULL; filter = filter->next) { @@ -205,7 +228,6 @@ static void request_replaceAdl(struct AttributeDescriptionList **adl, attr_t *at elifSETATTR(gidNumber); elifSETATTR(gecos); elifSETATTR(loginShell); - elifSETATTR(uidNumber); else request_replaceAttribute(&(*adl)->a, NULL); 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 @@ -220,6 +242,15 @@ static void request_replaceAttribute(struct string *attribute, struct string *va } else if (iequals(attribute, &s_objectclass)) { if (value == NULL) return; if (equals(value, &s_shadowAccount)) *value = s_user; + else if (equals(value, &s_posixAccount)) *value = s_user; + } else if (equals(attribute, &s_uidNumber)) { + *attribute = s_objectSid; + if (value == NULL) return; + uint32_t tmp = 0; + for (size_t i = 0; i < value->l; ++i) tmp = tmp * 10 + (value->s[i] - '0'); + memcpy(osHack + osHackLen, &tmp, 4); + value->s = osHack; + value->l = osHackLen + 4; } } @@ -236,6 +267,7 @@ static void response_replacePal(struct PartialAttributeList **pal, attr_t *attr) { struct string *username = NULL; struct PartialAttributeList *last = NULL; + struct AttributeDescriptionList *lastObjectClass = NULL; while (*pal != NULL) { last = *pal; struct PartialAttributeList *next = NULL; @@ -257,6 +289,14 @@ static void response_replacePal(struct PartialAttributeList **pal, attr_t *attr) if (username == NULL && equals(&(*pal)->type, &s_uid)) { username = &(*pal)->values->a; } + // Map objectClass user back to posixAccount and shadowAccount + if (lastObjectClass == NULL && iequals(&(*pal)->type, &s_objectclass)) { + BOOL hasUser = FALSE; + for (struct AttributeDescriptionList *adl = (*pal)->values; adl != NULL; adl = adl->next) { + if (!hasUser && iequals(&adl->a, &s_user)) hasUser = TRUE; + if (hasUser && adl->next == NULL) lastObjectClass = adl; + } + } pal = &(*pal)->next; } if (username != NULL) { @@ -265,6 +305,13 @@ static void response_replacePal(struct PartialAttributeList **pal, attr_t *attr) ADDATTR(loginShell, "/bin/bash"); ADDATTR(gidNumber, "1001"); } + if (lastObjectClass != NULL) { + lastObjectClass->next = calloc(1, sizeof(struct AttributeDescriptionList)); + lastObjectClass->next->a = s_posixAccount; + lastObjectClass = lastObjectClass->next; + lastObjectClass->next = calloc(1, sizeof(struct AttributeDescriptionList)); + lastObjectClass->next->a = s_shadowAccount; + } } #undef ADDATTR #undef elifDELATTR @@ -288,20 +335,17 @@ static void response_replaceAttribute(struct string *attribute, struct string *v { if (equals(attribute, &s_sAMAccountName)) { *attribute = s_uid; - } else if (iequals(attribute, &s_objectclass)) { + } else if (equals(attribute, &s_objectSid)) { + *attribute = s_uidNumber; if (value == NULL) return; - if (equals(value, &s_user)) *value = s_shadowAccount; - } else if ( - equals(attribute, &s_dn) || - equals(attribute, &s_distinguishedName) || - equals(attribute, &s_memberOf) || - equals(attribute, &s_objectCategory) - ) { - if (value == NULL) return; - struct string alias; - if (server_baseToAlias(value, &alias) != -1) { - *value = alias; + if (osHackLen == 0 && value->l > 4) { + osHackLen = value->l - 4; + memcpy(osHack, value->s, osHackLen); } + int tmp; + memcpy(&tmp, value->s + value->l - 4, 4); + value->l = snprintf(osHackNum, 10, "%u", tmp); + value->s = osHackNum; } } @@ -325,20 +369,26 @@ static struct PartialAttributeList* response_addPal(struct PartialAttributeList static int proxy_clientSearchRequest(epoll_client_t *client, const unsigned long messageId, const size_t offset, const size_t maxLen) { struct SearchRequest req; - struct string realBase; const size_t res = scan_ldapsearchrequest(client->readBuffer + offset, client->readBuffer + maxLen, &req); if (res == 0) return -1; - const int server = server_aliasToBase(&req.baseObject, &realBase); + const int server = server_getFromBase(&req.baseObject); if (server == -1) { - printf("scan_ldapsearchrequest: baseObj %.*s unknown.\n", (int)req.baseObject.l, req.baseObject.s); + printf("scan_ldapsearchrequest: baseObj '%.*s' unknown.\n", (int)req.baseObject.l, req.baseObject.s); return -1; } - req.baseObject = realBase; - printf("scan_ldapsearchrequest: baseO: %.*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); + // + if (!request_isUserFilter(req.filter)) { + // Handle locally + const int ret = proxy_localSearchRequest(client, messageId, &req); + free_ldapsearchrequest(&req); + return ret; + } // pending_t *pending = proxy_getFreePendingSlot(client); if (pending == NULL) { printf("No more slots for pending requests\n"); + free_ldapsearchrequest(&req); return -1; } if (req.attributes == NULL) { @@ -385,10 +435,6 @@ static int proxy_serverSearchResult(epoll_server_t *server, const unsigned long struct SearchResultEntry sre; const size_t res = scan_ldapsearchresultentry(server->readBuffer + offset, server->readBuffer + maxLen, &sre); if (res == 0) return -1; - struct string alias; - if (server_baseToAlias(&sre.objectName, &alias) != -1) { - sre.objectName = alias; - } response_replacePal(&sre.attributes, &pending->attr); bodyLen = fmt_ldapsearchresultentry(NULL, &sre); if (bodyLen == 0) { @@ -423,9 +469,17 @@ static int proxy_clientBindRequest(epoll_client_t *client, const unsigned long m if (res == 0) return -1; // Parsing request failed 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', bindpw: '%.*s'\n", (int)(res + res2), version, method, (int)name.l, name.s, (int)password.l, password.s); + //for (int i = 0; i < password.l; ++i) printf("%c(%x)\n", password.s[i], (int)password.s[i]); char buffer[800]; char *bufoff = buffer + 100; - const size_t bodyLen = fmt_ldapbindresponse(bufoff, 0, "", "main screen turn on", ""); + size_t bodyLen; + if (strncmp(password.s, "\x08\x0a\x0d\x7fINCORRECT", 13) != 0) { // FIXME: Drexhack! + printf("Password OK\n"); + bodyLen = fmt_ldapbindresponse(bufoff, 0, "", "main screen turn on", ""); + } else { + printf("Password WRONG\n"); + bodyLen = fmt_ldapbindresponse(bufoff, 49, "", "nix da", ""); + } const size_t headerLen = fmt_ldapmessage(NULL, messageId, BindResponse, bodyLen); if (headerLen > 100) return -1; // Too long - don't care fmt_ldapmessage(bufoff - headerLen, messageId, BindResponse, bodyLen); @@ -443,3 +497,10 @@ static int proxy_serverBindResponse(epoll_server_t *server, const unsigned long return 0; } +// ---- Local handling ---- + +static int proxy_localSearchRequest(epoll_client_t *client, const unsigned long messageId, const struct SearchRequest *req) +{ + return -1; +} + @@ -21,7 +21,6 @@ #define MSGID_BIND 1 typedef struct { - size_t aliasLen; size_t baseLen; char ip[4]; time_t lastLookup; @@ -29,7 +28,6 @@ typedef struct { char bind[BINDLEN]; char password[PWLEN]; char base[BASELEN]; - char alias[ALIASLEN]; epoll_server_t con; } server_t; @@ -77,59 +75,28 @@ void server_setBase(const char *server, const char *base) entry->base[entry->baseLen] = '\0'; } -void server_setAlias(const char *server, const char *alias) -{ - server_t *entry = server_create(server); - if (entry == NULL) return; - if (snprintf(entry->alias, ALIASLEN, "%s", alias) >= ALIASLEN) printf("Warning: SearchBase Alias for %s is too long.\n", server); - entry->aliasLen = normalize_dn(entry->alias, entry->alias, min(strlen(entry->alias), ALIASLEN - 1)); - entry->alias[entry->aliasLen] = '\0'; -} - void server_initServers() { int i; printf("%d servers configured.\n", serverCount); for (i = 0; i < serverCount; ++i) { - printf("%s:\n Bind: %s\n Base: %s\n Proxy Alias: %s\n", servers[i].addr, servers[i].bind, servers[i].base, servers[i].alias); + printf("%s:\n Bind: %s\n Base: %s\n", servers[i].addr, servers[i].bind, servers[i].base); server_ensureConnected(i); } } // What the proxy calls -int server_aliasToBase(struct string *in, struct string *out) -{ - int i; - char buffer[TMPLEN]; - const size_t searchLen = normalize_dn(buffer, in->s, min(in->l, TMPLEN - 1)); - buffer[searchLen] = '\0'; - // Now buffer contains the normalized wanted alias. Try to find a match in the server list - for (i = 0; i < serverCount; ++i) { - if (searchLen < servers[i].aliasLen) continue; - if (strcmp(servers[i].alias, buffer + (searchLen - servers[i].aliasLen)) == 0) { - // Found, handle - tmpbuffer_format(out, "%.*s%s", (int)(searchLen - servers[i].aliasLen), buffer, servers[i].base); - return i; - } - } - return -1; -} - -int server_baseToAlias(struct string *in, struct string *out) +int server_getFromBase(struct string *in) { int i; char buffer[TMPLEN]; const size_t searchLen = normalize_dn(buffer, in->s, min(in->l, TMPLEN - 1)); buffer[searchLen] = '\0'; - // Now buffer contains the normalized wanted base. Try to find a match in the server list + // Now buffer contains the normalized wanted bind/domain/whatev. Try to find a match in the server list for (i = 0; i < serverCount; ++i) { - printf("Comparing %s (%s) to %s\n", buffer, buffer + (searchLen - servers[i].baseLen), servers[i].base); if (searchLen < servers[i].baseLen) continue; if (strcmp(servers[i].base, buffer + (searchLen - servers[i].baseLen)) == 0) { - // Found, handle - tmpbuffer_format(out, "%.*s%s", (int)(searchLen - servers[i].baseLen), buffer, servers[i].alias); - printf("Match, returning %s\n", out->s); return i; } } @@ -12,15 +12,11 @@ void server_setPassword(const char *server, const char *password); void server_setBase(const char *server, const char *base); -void server_setAlias(const char *server, const char *alias); - void server_initServers(); int server_send(epoll_server_t *server, const char *buffer, size_t len, const BOOL cork); -int server_aliasToBase(struct string *in, struct string *out); - -int server_baseToAlias(struct string *in, struct string *out); +int server_getFromBase(struct string *in); uint32_t server_searchRequest(int server, struct SearchRequest *req); @@ -6,7 +6,7 @@ #include <time.h> #define REQLEN 4000 -#define MAXMSGLEN 10000 +#define MAXMSGLEN 100000 #define BOOL uint8_t #define TRUE 1 |