Skip to content

Commit

Permalink
[HOTFIX] Escape Ldap search filters
Browse files Browse the repository at this point in the history
  • Loading branch information
jongyoul committed Feb 17, 2024
1 parent 49e2740 commit 8a41f8e
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -773,15 +773,15 @@ public String getUserSearchFilter() {
}

public void setUserSearchFilter(final String filter) {
this.userSearchFilter = (filter == null ? null : filter.trim());
this.userSearchFilter = (filter == null ? null : escapeAttributeValue(filter.trim()));
}

public String getGroupSearchFilter() {
return groupSearchFilter;
}

public void setGroupSearchFilter(final String filter) {
this.groupSearchFilter = (filter == null ? null : filter.trim());
this.groupSearchFilter = (filter == null ? null : escapeAttributeValue(filter.trim()));
}

public boolean getUserLowerCase() {
Expand Down Expand Up @@ -941,6 +941,74 @@ userSearchAttributeName, expandTemplate(getUserSearchAttributeTemplate(),
}
}

// Implements the necessary escaping to represent an attribute value as a String as per RFC 4514.
protected String escapeAttributeValue(String input) {
if (input == null) {
return null;
}
int len = input.length();
StringBuilder result = new StringBuilder();

for (int i = 0; i < len; i++) {
char c = input.charAt(i);
switch (c) {
case ' ': {
if (i == 0 || i == (len - 1)) {
result.append("\\20");
} else {
result.append(c);
}
break;
}
case '#': {
if (i == 0) {
result.append("\\23");
} else {
result.append(c);
}
break;
}
case '\"': {
result.append("\\22");
break;
}
case '+': {
result.append("\\2B");
break;
}
case ',': {
result.append("\\2C");
break;
}
case ';': {
result.append("\\3B");
break;
}
case '<': {
result.append("\\3C");
break;
}
case '>': {
result.append("\\3E");
break;
}
case '\\': {
result.append("\\5C");
break;
}
case '\u0000': {
result.append("\\00");
break;
}
default:
result.append(c);
}
}

return result.toString();
}


@Override
protected AuthenticationInfo createAuthenticationInfo(AuthenticationToken token,
Object ldapPrincipal, Object ldapCredentials, LdapContext ldapContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,19 @@ void testRolesFor() throws NamingException {
assertEquals(new HashSet<>(Arrays.asList("group-one", "zeppelin-role")), roles);
}

@Test
void testFilterEscaping() {
LdapRealm realm = new LdapRealm();
assertEquals("foo", realm.escapeAttributeValue("foo"));
assertEquals("foo\\2B", realm.escapeAttributeValue("foo+"));
assertEquals("foo\\5C", realm.escapeAttributeValue("foo\\"));
assertEquals("foo\\00", realm.escapeAttributeValue("foo\u0000"));
realm.setUserSearchFilter("uid=<{0}>");
assertEquals("uid=\\3C{0}\\3E", realm.getUserSearchFilter());
realm.setUserSearchFilter("gid=\\{0}\\");
assertEquals("gid=\\5C{0}\\5C", realm.getUserSearchFilter());
}

private NamingEnumeration<SearchResult> enumerationOf(BasicAttributes... attrs) {
final Iterator<BasicAttributes> iterator = Arrays.asList(attrs).iterator();
return new NamingEnumeration<SearchResult>() {
Expand Down

0 comments on commit 8a41f8e

Please sign in to comment.