From c3a94473055e098a52ef865a4d2942a1a7d8bf7c Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 12 Feb 2015 15:08:06 +0100 Subject: Hack in support for numeric account names --- proxy.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) (limited to 'proxy.c') diff --git a/proxy.c b/proxy.c index c888c2f..38f94e9 100644 --- a/proxy.c +++ b/proxy.c @@ -22,6 +22,7 @@ typedef struct BOOL uid; BOOL uidNumber; BOOL cn; + BOOL realAccount; // Internal BOOL hasUser; } attr_t; @@ -46,9 +47,41 @@ static int _pendingCount = 0; static struct string s_shadowAccount, s_posixAccount, s_user, s_uid, s_sAMAccountName, s_objectSid; static struct string s_objectClass, s_objectclass, s_homeDirectory, s_gidNumber, s_gecos, s_cn, s_dn, s_posixGroup; static struct string s_loginShell, s_uidNumber, s_mail, s_objectCategory, s_memberOf, s_distinguishedName; -static struct string s_1001, s_homeMount, s_member, s_memberUid; +static struct string s_1001, s_homeMount, s_member, s_memberUid, s_realAccount; static struct string str_ADUSER; +// HACK +static BOOL isInt(struct string *value, int start) +{ + size_t i; + for (i = start; i < value->l; ++i) { + if (value->s[i] < '0' || value->s[i] > '9') return FALSE; + } + return TRUE; +} +static void fixUnNumeric(struct string *value) +{ + if (value == NULL || value->l < 2) return; + if (value->s[0] != 's') return; + if (!isInt(value, 1)) return; + value->s++; + value->l--; +} +static void fixNumeric(struct string *value) +{ + size_t i; + if (value == NULL || value->l < 1 || value->l > 18) return; + if (!isInt(value, 0)) return; + char *buf = tmpbuffer_get(); + buf[0] = 's'; + for (i = 0; i < value->l; ++i) { + buf[i+1] = value->s[i]; + } + value->s = buf; + value->l++; +} +// END HACK + // static BOOL proxy_clientBindRequest(epoll_client_t *client, const unsigned long messageId, const size_t offset, const size_t maxLen); @@ -90,6 +123,7 @@ void proxy_init() SETSTR(dn); SETSTR(member); SETSTR(memberUid); + SETSTR(realAccount); SETSTR(1001); // TODO: configurable str_ADUSER.s = "ad_user"; @@ -303,6 +337,7 @@ static void request_replaceAdl(server_t *server, struct AttributeDescriptionList elifSETATTR(homeDirectory); elifSETATTR(gidNumber); elifSETATTR(gecos); + elifSETATTR(realAccount); elifSETATTR(loginShell); else request_replaceAttribute(server, &(*adl)->a, NULL, attr); if (*adl == NULL) break; @@ -324,6 +359,10 @@ static void request_replaceAttribute(server_t *server, struct string *attribute, if (equals(attribute, &s_uid)) { *attribute = s_sAMAccountName; if (attr) attr->hasUser = TRUE; + // 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; + fixUnNumeric(value); + ////// ################### } else if (equals(attribute, &s_homeMount)) { *attribute = s_homeDirectory; if (attr != NULL) attr->homeMount = TRUE; @@ -358,6 +397,7 @@ static void response_replacePal(server_t *server, struct PartialAttributeList ** struct string *username = NULL; struct AttributeDescriptionList *lastObjectClass = NULL; struct PartialAttributeList *next = NULL; + BOOL wasNumeric = FALSE; while (*pal != NULL) { BOOL del = FALSE; if (0) { } // Remove fields we don't want from AD @@ -390,6 +430,7 @@ static void response_replacePal(server_t *server, struct PartialAttributeList ** // 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; } // Map objectClass user back to posixAccount and shadowAccount if (lastObjectClass == NULL && iequals(&(*pal)->type, &s_objectclass)) { @@ -408,8 +449,11 @@ static void response_replacePal(server_t *server, struct PartialAttributeList ** ADDATTR(gecos, "%s,,,", user); ADDATTR(cn, "%s", user); if (attr->homeMount && server->homeTemplate[0] != '\0') { + if (wasNumeric) user++; ADDATTR(homeMount, server->homeTemplate, user, user, user, user, user, user); } + // Do this here so user++ will have been executed + ADDATTR(realAccount, "%s", user); } if (lastObjectClass != NULL) { ADDATTR(loginShell, "/bin/bash"); @@ -444,6 +488,7 @@ static void response_replaceAttribute(server_t *server, struct string *attribute { if (equals(attribute, &s_sAMAccountName)) { *attribute = s_uid; + if (value != NULL) fixNumeric(value); } else if (equals(attribute, &s_objectSid)) { *attribute = s_uidNumber; if (value == NULL) return; @@ -512,7 +557,7 @@ static BOOL proxy_clientSearchRequest(epoll_client_t *client, const unsigned lon return ret; } // Forward - if (req.sizeLimit == 0 || req.sizeLimit > 500) req.sizeLimit = 500; // TODO: Magic value + if (req.sizeLimit == 0 || req.sizeLimit > 20) req.sizeLimit = 20; // TODO: Magic value pending_t *pending = proxy_getFreePendingSlot(client); if (pending == NULL) { printf("No more slots for pending requests\n"); @@ -613,12 +658,13 @@ static BOOL proxy_clientBindRequest(epoll_client_t *client, const unsigned long bodyLen = fmt_ldapbindresponse(bufoff, success, "", "main screen turn on", ""); } else { server_t *server = server_getFromBase(&name); - if (server == NULL || strncmp(password.s, "\x08\x0a\x0d\x7fINCORRECT", 13) == 0) { + if (server == NULL || strncmp(password.s, "\x08\x0a\x0d\x7fINCORRECT", 13) == 0 || isInt(&name, 0)) { // The INCORRECT part is some weird thing I saw pam_ldap do - save the round trip to AD and deny - printf("Password INCORRECT or binddn unknown\n"); + printf("Password INCORRECT or binddn unknown or numeric username\n"); bodyLen = fmt_ldapbindresponse(bufoff, invalidCredentials, "", "invalid credentials", ""); } else { // Seems to be an actual bind - forward to AD - TODO: SASL (DIGEST-MD5?) + fixUnNumeric(&name); pending_t *pending = proxy_getFreePendingSlot(client); const unsigned long smid = server_tryUserBind(server, &name, &password); if (pending == NULL || smid == 0) { -- cgit v1.2.3-55-g7522