From 18af18b35b72834284e079d79fae45a3d642676f Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Mon, 17 Mar 2014 19:21:35 +0100 Subject: More progress.. Warning: Contains very ugly temporary hack for uidNumber<->objectSid mapping ;) --- proxy.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 86 insertions(+), 25 deletions(-) (limited to 'proxy.c') diff --git a/proxy.c b/proxy.c index c627238..ca4dfc1 100644 --- a/proxy.c +++ b/proxy.c @@ -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; +} + -- cgit v1.2.3-55-g7522