summaryrefslogtreecommitdiffstats
path: root/proxy.c
diff options
context:
space:
mode:
authorSimon Rettberg2021-03-15 15:27:37 +0100
committerSimon Rettberg2021-03-15 15:27:37 +0100
commit6f0e193c0895a62c93329df4a15bd9e5e84e080c (patch)
treedb29fd7043889f872ebc81cf287f5a4b5ccdc899 /proxy.c
parentMore tmpbuffers (diff)
downloadldadp-6f0e193c0895a62c93329df4a15bd9e5e84e080c.tar.gz
ldadp-6f0e193c0895a62c93329df4a15bd9e5e84e080c.tar.xz
ldadp-6f0e193c0895a62c93329df4a15bd9e5e84e080c.zip
Fix and improve numeric uid handlingv3.10
Diffstat (limited to 'proxy.c')
-rw-r--r--proxy.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/proxy.c b/proxy.c
index 5652e91..f3588ef 100644
--- a/proxy.c
+++ b/proxy.c
@@ -71,13 +71,33 @@ static struct string s_bogusfieldname42, s_bogusfieldname43;
static struct string str_ADUSER, str_ADUSERDN;
// HACK - we pefix usernames that start with something other than a-z_ with "_x_"
+// This is for requests - remove the prefix that the client added
static void fixUnNumeric(struct string *value)
{
- if (value == NULL || value->l < 4) return;
+ if (value == NULL) return;
+ if (value->s[0] >= '0' && value->s[0] <= '9') {
+ // This is a query from the client for an actually numeric ID - this should not
+ // happen, so let's break the request to make sure it doesn't yield anything
+ char *n = tmpbuffer_get();
+ size_t len = 0;
+ n[len++] = 'f';
+ n[len++] = 'a';
+ n[len++] = 'k';
+ n[len++] = 'e';
+ for (size_t i = 0; i < value->l && i < 30; ++i) {
+ n[len++] = value->s[i] + (value->s[i] < 64 ? 10 : -10);
+ }
+ value->s = n;
+ value->l = len;
+ return;
+ }
+ // Look for actual expected prefix and remove
+ if (value->l < 4) return;
if (value->s[0] != '_' || value->s[1] != 'x' || value->s[2] != '_') return;
value->s += 3;
value->l -= 3;
}
+// For server responses, if they're numeric, add the prefix
static void fixNumeric(struct string *value)
{
size_t i;
@@ -542,7 +562,7 @@ static BOOL request_replaceAttribute(server_t *server, struct string *attribute,
if (iequals(attribute, &s_uid)) {
*attribute = server->map.uid;
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 uid is of format _x_*, we assume that it's a numeric account name in AD, as a workaround
if (value == NULL) return TRUE;
if (server->fixNumeric) {
fixUnNumeric(value);
@@ -668,7 +688,6 @@ static struct PartialAttributeList* response_addPal(struct PartialAttributeList
static void response_replacePal(server_t *server, struct PartialAttributeList **pal, attr_t *attr)
{
struct string *username = NULL;
- BOOL wasNumeric = FALSE;
while (*pal != NULL) {
BOOL del = FALSE;
if (0) { } // Remove fields we don't want from AD/LDAP
@@ -715,7 +734,6 @@ static void response_replacePal(server_t *server, struct PartialAttributeList **
// Fetch user name so we can add our fake fields later
if (username == NULL && iequals(&(*pal)->type, &s_uid)) {
username = &(*pal)->values->a;
- if (server->fixNumeric && username->l > 1 && username->s[0] == 's' && isInt(username, 1)) wasNumeric = TRUE;
}
pal = &(*pal)->next;
}
@@ -740,11 +758,13 @@ static void response_replacePal(server_t *server, struct PartialAttributeList **
if (attr->bogusFieldName43) {
ADDATTR(bogusFieldName43, "%s", user);
}
- if (wasNumeric) user++; // From here on, user is the real AD/ldap username, no leading 's'
+ if (server->fixNumeric && strncmp(user, "_x_", 3) == 0) {
+ user += 3;
+ }
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
+ // Do this here so user += 3 will have been executed
ADDATTR(realAccount, "%s", user);
}
ADDATTR(loginShell, "/bin/bash");
@@ -1032,7 +1052,7 @@ static BOOL proxy_clientBindRequest(epoll_client_t *client, const unsigned long
server_t *server = server_getFromBase(&name);
if (server == NULL
|| (incorrect = (strncmp(password.s, "\x08\x0a\x0d\x7fINCORRECT", 13) == 0))
- || (server->fixNumeric && isInt(&name, 0))) {
+ || (server->fixNumeric && isdigit(name.s[0]))) {
// The INCORRECT part is some weird thing I saw pam_ldap do - probably to identify misconfigured
// LDAP servers/accounts that will accept any password - save the round trip to AD and deny
if (!incorrect) plog(DEBUG_WARNING, "[Client] Numeric account or invalid binddn for %.*s", (int)name.l, name.s);