Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.shiro.lang.util.StringUtils;

import java.io.Serial;
import java.util.Locale;
import java.util.Set;

/**
Expand Down Expand Up @@ -95,7 +96,8 @@ protected void setParts(String domain, Set<String> actions, Set<String> targets)
}

protected String getDomain(Class<? extends DomainPermission> clazz) {
String domain = clazz.getSimpleName().toLowerCase();
// Locale.ROOT: under certain non-English default locales "InvoicePermission" would become "ınvoicepermission"
String domain = clazz.getSimpleName().toLowerCase(Locale.ROOT);
//strip any trailing 'permission' text from the name (as all subclasses should have been named):
int index = domain.lastIndexOf("permission");
if (index != -1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;

/**
Expand Down Expand Up @@ -155,7 +156,8 @@ protected void setParts(String wildcardString, boolean caseSensitive) {
}

if (!caseSensitive) {
wildcardString = wildcardString.toLowerCase();
// Locale.ROOT (as in SHIRO-415/SHIRO-483): under certain non-English default locales "ADMIN" would become "admın"
wildcardString = wildcardString.toLowerCase(Locale.ROOT);
}

List<String> parts = CollectionUtils.asList(wildcardString.split(PART_DIVIDER_TOKEN));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.shiro.authz.permission;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated;

import java.util.Locale;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Permission matching must not depend on the JVM default locale: under a Turkish default locale
* {@code "ADMIN".toLowerCase()} is {@code "admın"} (dotless i) while {@code "admin"} stays {@code "admin"}.
* The class changes the default locale, so it runs isolated from the (parallel) test execution.
*/
@Isolated
public class PermissionDefaultLocaleTest {

@Test
void wildcardPermissionIsCaseInsensitiveRegardlessOfDefaultLocale() {
Locale defaultLocale = Locale.getDefault();
Locale.setDefault(Locale.forLanguageTag("tr-TR"));
try {
assertThat(new WildcardPermission("ADMIN:*").implies(new WildcardPermission("admin:read"))).isTrue();
assertThat(new WildcardPermission("admin:*").implies(new WildcardPermission("ADMIN:read"))).isTrue();
} finally {
Locale.setDefault(defaultLocale);
}
}

@Test
void domainPermissionDerivesDomainRegardlessOfDefaultLocale() {
Locale defaultLocale = Locale.getDefault();
Locale.setDefault(Locale.forLanguageTag("tr-TR"));
try {
assertThat(new InvoicePermission().getDomain()).isEqualTo("invoice");
assertThat(new WildcardPermission("invoice:*").implies(new InvoicePermission())).isTrue();
} finally {
Locale.setDefault(defaultLocale);
}
}

private static final class InvoicePermission extends DomainPermission {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public static ProvidedHashFormat byId(final String id) {
try {
// Use English Locale, some Locales handle uppercase/lower differently. i.e. Turkish and upper case 'i'
// is not 'I'. And 'SHIRO1' would be 'SHİRO1'
return valueOf(id.toUpperCase(Locale.ENGLISH));
return valueOf(id.toUpperCase(Locale.ROOT));
} catch (final IllegalArgumentException ignored) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ public String formatToCryptString() {

private CharSequence formatParameters() {
return String.format(
Locale.ENGLISH,
Locale.ROOT,
"t=%d,m=%d,p=%d",
getIterations(),
getMemoryKiB(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;

Expand Down Expand Up @@ -130,8 +131,8 @@ public static boolean startsWithIgnoreCase(String str, String prefix) {
if (str.length() < prefix.length()) {
return false;
}
String lcStr = str.substring(0, prefix.length()).toLowerCase();
String lcPrefix = prefix.toLowerCase();
String lcStr = str.substring(0, prefix.length()).toLowerCase(Locale.ROOT);
String lcPrefix = prefix.toLowerCase(Locale.ROOT);
return lcStr.equals(lcPrefix);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ protected boolean isAccessAllowed(ServletRequest request, ServletResponse respon
boolean authcRequired = methods.isEmpty();
for (String m : methods) {
// list of methods is in upper case
if (httpMethod.toUpperCase(Locale.ENGLISH).equals(m)) {
if (httpMethod.toUpperCase(Locale.ROOT).equals(m)) {
authcRequired = true;
break;
}
Expand All @@ -229,7 +229,7 @@ private Set<String> httpMethodsFromOptions(String[] options) {
// to be backwards compatible with 1.3, we can ONLY check for known args
// ideally we would just validate HTTP methods, but someone could already be using this for webdav
if (!option.equalsIgnoreCase(PERMISSIVE)) {
methods.add(option.toUpperCase(Locale.ENGLISH));
methods.add(option.toUpperCase(Locale.ROOT));
}
}
}
Expand Down Expand Up @@ -314,8 +314,8 @@ protected String getAuthzHeader(ServletRequest request) {
*/
protected boolean isLoginAttempt(String authzHeader) {
//SHIRO-415: use English Locale:
String authzScheme = getAuthzScheme().toLowerCase(Locale.ENGLISH);
return authzHeader.toLowerCase(Locale.ENGLISH).startsWith(authzScheme);
String authzScheme = getAuthzScheme().toLowerCase(Locale.ROOT);
return authzHeader.toLowerCase(Locale.ROOT).startsWith(authzScheme);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ protected boolean preHandle(ServletRequest request, ServletResponse response) th
if (isPostOnlyLogout()) {

// check if the current request's method is a POST, if not redirect
if (!WebUtils.toHttp(request).getMethod().toUpperCase(Locale.ENGLISH).equals("POST")) {
if (!WebUtils.toHttp(request).getMethod().toUpperCase(Locale.ROOT).equals("POST")) {
return onLogoutRequestNotAPost(request, response);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
Expand Down Expand Up @@ -150,7 +151,7 @@ public String getAction() {
*/
public HttpMethodPermissionFilter() {
for (HttpMethodAction methodAction : HttpMethodAction.values()) {
httpMethodActions.put(methodAction.name().toLowerCase(), methodAction.getAction());
httpMethodActions.put(methodAction.name().toLowerCase(Locale.ROOT), methodAction.getAction());
}
}

Expand Down Expand Up @@ -187,7 +188,7 @@ protected String getHttpMethodAction(ServletRequest request) {
* @return The string equivalent verb of the method.
*/
protected String getHttpMethodAction(String method) {
String lc = method.toLowerCase();
String lc = method.toLowerCase(Locale.ROOT);
String resolved = getHttpMethodActions().get(lc);
return resolved != null ? resolved : method;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import jakarta.servlet.ServletResponse;
import java.io.Serializable;
import java.util.Collection;
import java.util.Locale;
import java.util.function.Supplier;


Expand Down Expand Up @@ -163,7 +164,7 @@ public void setSessionMode(String sessionMode) {
if (mode == null) {
throw new IllegalArgumentException("sessionMode argument cannot be null.");
}
mode = sessionMode.toLowerCase();
mode = sessionMode.toLowerCase(Locale.ROOT);
if (!HTTP_SESSION_MODE.equals(mode) && !NATIVE_SESSION_MODE.equals(mode)) {
String msg = "Invalid sessionMode [" + sessionMode + "]. Allowed values are "
+ "public static final String constants in the " + getClass().getName() + " class: '"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ private void appendSameSite(StringBuilder sb, SameSiteOptions sameSite) {
sb.append(ATTRIBUTE_DELIMITER);
sb.append(SAME_SITE_ATTRIBUTE_NAME)
.append(NAME_VALUE_DELIMITER)
.append(sameSite.toString().toLowerCase(Locale.ENGLISH));
.append(sameSite.toString().toLowerCase(Locale.ROOT));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.apache.shiro.web.session.mgt;

import org.apache.shiro.session.ExpiredSessionException;
import java.util.Locale;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionManager;
Expand Down Expand Up @@ -141,9 +142,9 @@ private Serializable getReferencedSessionId(ServletRequest request, ServletRespo
if (queryString != null && queryString.contains(name)) {
id = request.getParameter(name);
}
if (id == null && queryString != null && queryString.contains(name.toLowerCase())) {
if (id == null && queryString != null && queryString.contains(name.toLowerCase(Locale.ROOT))) {
//try lowercase:
id = request.getParameter(name.toLowerCase());
id = request.getParameter(name.toLowerCase(Locale.ROOT));
}
}
if (id != null) {
Expand Down
Loading