This is an automated email from the ASF dual-hosted git repository.

enorman pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-jackrabbit-usermanager.git


The following commit(s) were added to refs/heads/master by this push:
     new cfdde23  SLING-10456 adjust HTTP status code for invalid :redirect 
value (#6)
cfdde23 is described below

commit cfdde23fbd2bc4b486084ba7e27d42b3187dd565
Author: Eric Norman <[email protected]>
AuthorDate: Thu Jun 3 14:31:16 2021 -0700

    SLING-10456 adjust HTTP status code for invalid :redirect value (#6)
    
    for usermanager post requests
---
 .../usermanager/impl/post/AbstractPostServlet.java | 33 +++++++------
 .../usermanager/it/post/CreateGroupIT.java         | 25 ++++++++++
 .../usermanager/it/post/CreateUserIT.java          | 26 ++++++++++
 .../usermanager/it/post/RemoveAuthorizablesIT.java | 27 ++++++++++
 .../usermanager/it/post/UpdateGroupIT.java         | 28 +++++++++++
 .../usermanager/it/post/UpdateUserIT.java          | 57 ++++++++++++++++++++++
 .../it/post/UserManagerClientTestSupport.java      |  2 +
 7 files changed, 183 insertions(+), 15 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractPostServlet.java
 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractPostServlet.java
index 33ad48c..542baa4 100644
--- 
a/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractPostServlet.java
+++ 
b/src/main/java/org/apache/sling/jackrabbit/usermanager/impl/post/AbstractPostServlet.java
@@ -157,9 +157,20 @@ public abstract class AbstractPostServlet extends
 
         // check for redirect URL if processing succeeded
         if (response.isSuccessful()) {
-            String redirect = getRedirectUrl(request, response);
+            String redirect = null;
+            try {
+                redirect = getRedirectUrl(request, response);
+            } catch (IOException e) {
+                if (log.isDebugEnabled()) {
+                    log.debug(String.format("Exception while handling redirect 
for POST %s with %s",
+                            request.getResource().getPath(), 
getClass().getName()), e);
+                }
+                // http status code for 422 Unprocessable Entity
+                response.setStatus(422, "invalid redirect");
+                response.setError(e);
+            }
             if (redirect != null) {
-                httpResponse.sendRedirect(redirect);
+                httpResponse.sendRedirect(redirect); // NOSONAR
                 return;
             }
         }
@@ -264,7 +275,7 @@ public abstract class AbstractPostServlet extends
      * @deprecated use {@link #getRedirectUrl(HttpServletRequest, 
PostResponse)} instead
      */
     @Deprecated
-    protected String getRedirectUrl(HttpServletRequest request, 
AbstractPostResponse ctx) {
+    protected String getRedirectUrl(HttpServletRequest request, 
AbstractPostResponse ctx) throws IOException {
         return getRedirectUrl(request, (PostResponse)ctx);
     }
     
@@ -273,8 +284,9 @@ public abstract class AbstractPostServlet extends
      * @param request the request
      * @param ctx the post processor
      * @return the redirect location or <code>null</code>
+     * @throws IOException if there is something invalid with the :redirect 
value
      */
-    protected String getRedirectUrl(HttpServletRequest request, PostResponse 
ctx) {
+    protected String getRedirectUrl(HttpServletRequest request, PostResponse 
ctx) throws IOException {
         // redirect param has priority (but see below, magic star)
         String result = 
request.getParameter(SlingPostConstants.RP_REDIRECT_TO);
         if (result != null) {
@@ -282,16 +294,11 @@ public abstract class AbstractPostServlet extends
                 URI redirectUri = new URI(result);
                 if (redirectUri.getAuthority() != null) {
                     // if it has a host information
-                    log.warn("redirect target includes host information ({}). 
This is not allowed for security reasons!", redirectUri.getAuthority());
-                    result = null;
+                    throw new IOException("The redirect target included host 
information. This is not allowed for security reasons!");
                 }
             } catch (URISyntaxException e) {
-                log.warn("given redirect target is not a valid uri: {}", 
e.getLocalizedMessage());
-                result = null;
+                throw new IOException("The redirect target was not a valid 
uri");
             }
-        }
-        if (result != null) {
-            log.debug("redirect requested as [{}] for path [{}]", result, 
ctx.getPath());
 
             if (ctx.getPath() != null) {
                 // redirect to created/modified Resource
@@ -320,10 +327,6 @@ public abstract class AbstractPostServlet extends
                     // name
                     result = 
result.concat(ResourceUtil.getName(ctx.getPath()));
                 }
-
-                if (log.isDebugEnabled()) {
-                    log.debug("Will redirect to {}", result);
-                }
             }
         }
         return result;
diff --git 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/CreateGroupIT.java
 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/CreateGroupIT.java
index 84e40fd..3c06703 100644
--- 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/CreateGroupIT.java
+++ 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/CreateGroupIT.java
@@ -182,4 +182,29 @@ public class CreateGroupIT extends 
UserManagerClientTestSupport {
         assertNotNull(jsonObj);
     }
 
+    private void testCreateGroupRedirect(String redirectTo, int 
expectedStatus) throws IOException {
+        String postUrl = 
String.format("%s/system/userManager/group.create.html", baseServerUri);
+
+        testGroupId = "testGroup" + getNextInt();
+        List<NameValuePair> postParams = new ArrayList<>();
+        postParams.add(new BasicNameValuePair(":name", testGroupId));
+        postParams.add(new BasicNameValuePair(":redirect", redirectTo));
+        assertAuthenticatedAdminPostStatus(postUrl, expectedStatus, 
postParams, null);
+    }
+
+    @Test
+    public void testCreateGroupValidRedirect() throws IOException, 
JsonException {
+        testCreateGroupRedirect("/*.html", 
HttpServletResponse.SC_MOVED_TEMPORARILY);
+    }
+
+    @Test
+    public void testCreateGroupInvalidRedirectWithAuthority() throws 
IOException, JsonException {
+        testCreateGroupRedirect("https://sling.apache.org";, 
SC_UNPROCESSABLE_ENTITY);
+    }
+
+    @Test
+    public void testCreateGroupInvalidRedirectWithInvalidURI() throws 
IOException, JsonException {
+        testCreateGroupRedirect("https://";, SC_UNPROCESSABLE_ENTITY);
+    }
+
 }
diff --git 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/CreateUserIT.java
 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/CreateUserIT.java
index cfe2e30..acf8e6e 100644
--- 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/CreateUserIT.java
+++ 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/CreateUserIT.java
@@ -277,4 +277,30 @@ public class CreateUserIT extends 
UserManagerClientTestSupport {
         assertEquals("Thanks!", content); //verify that the content matches 
the custom response
     }
 
+    private void testCreateUserRedirect(String redirectTo, int expectedStatus) 
throws IOException {
+        testUserId = "testUser" + getNextInt();
+        String postUrl = 
String.format("%s/system/userManager/user.create.html", baseServerUri);
+        final List<NameValuePair> postParams = new ArrayList<>();
+        postParams.add(new BasicNameValuePair(":name", testUserId));
+        postParams.add(new BasicNameValuePair("pwd", "testPwd"));
+        postParams.add(new BasicNameValuePair("pwdConfirm", "testPwd"));
+        postParams.add(new BasicNameValuePair(":redirect", redirectTo));
+        assertAuthenticatedAdminPostStatus(postUrl, expectedStatus, 
postParams, null);
+    }
+
+    @Test
+    public void testCreateUserValidRedirect() throws IOException, 
JsonException {
+        testCreateUserRedirect("/*.html", 
HttpServletResponse.SC_MOVED_TEMPORARILY);
+    }
+
+    @Test
+    public void testCreateUserInvalidRedirectWithAuthority() throws 
IOException, JsonException {
+        testCreateUserRedirect("https://sling.apache.org";, 
SC_UNPROCESSABLE_ENTITY);
+    }
+
+    @Test
+    public void testCreateUserInvalidRedirectWithInvalidURI() throws 
IOException, JsonException {
+        testCreateUserRedirect("https://";, SC_UNPROCESSABLE_ENTITY);
+    }
+
 }
diff --git 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/RemoveAuthorizablesIT.java
 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/RemoveAuthorizablesIT.java
index 6b615c3..bae6671 100644
--- 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/RemoveAuthorizablesIT.java
+++ 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/RemoveAuthorizablesIT.java
@@ -260,4 +260,31 @@ public class RemoveAuthorizablesIT extends 
UserManagerClientTestSupport {
         assertNotNull(jsonObj);
     }
 
+    private void testRemoveAuthorizablesRedirect(String redirectTo, int 
expectedStatus) throws IOException {
+        String userId = createTestUser();
+        String groupId = createTestGroup();
+
+        String postUrl = String.format("%s/system/userManager.delete.html", 
baseServerUri);
+        List<NameValuePair> postParams = new ArrayList<>();
+        postParams.add(new BasicNameValuePair(":applyTo", "group/" + groupId));
+        postParams.add(new BasicNameValuePair(":applyTo", "user/" + userId));
+        postParams.add(new BasicNameValuePair(":redirect", redirectTo));
+        assertAuthenticatedAdminPostStatus(postUrl, expectedStatus, 
postParams, null);
+    }
+
+    @Test
+    public void testRemoveAuthorizableValidRedirect() throws IOException, 
JsonException {
+        testRemoveAuthorizablesRedirect("/*.html", 
HttpServletResponse.SC_MOVED_TEMPORARILY);
+    }
+
+    @Test
+    public void testRemoveAuthorizableInvalidRedirectWithAuthority() throws 
IOException, JsonException {
+        testRemoveAuthorizablesRedirect("https://sling.apache.org";, 
SC_UNPROCESSABLE_ENTITY);
+    }
+
+    @Test
+    public void testRemoveAuthorizableInvalidRedirectWithInvalidURI() throws 
IOException, JsonException {
+        testRemoveAuthorizablesRedirect("https://";, SC_UNPROCESSABLE_ENTITY);
+    }
+
 }
diff --git 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UpdateGroupIT.java
 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UpdateGroupIT.java
index 0dcdab9..09f50cc 100644
--- 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UpdateGroupIT.java
+++ 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UpdateGroupIT.java
@@ -258,5 +258,33 @@ public class UpdateGroupIT extends 
UserManagerClientTestSupport {
         assertNotNull(jsonObj);
     }
 
+    private void testUpdateGroupRedirect(String redirectTo, int 
expectedStatus) throws IOException {
+        testGroupId = createTestGroup();
+
+        String postUrl = 
String.format("%s/system/userManager/group/%s.update.html", baseServerUri, 
testGroupId);
+
+        List<NameValuePair> postParams = new ArrayList<>();
+        postParams.add(new BasicNameValuePair("displayName", "My Updated Test 
Group"));
+        postParams.add(new BasicNameValuePair(":redirect", redirectTo));
+
+        Credentials creds = new UsernamePasswordCredentials("admin", "admin");
+        assertAuthenticatedPostStatus(creds, postUrl, expectedStatus, 
postParams, null);
+    }
+
+    @Test
+    public void testUpdateGroupValidRedirect() throws IOException, 
JsonException {
+        testUpdateGroupRedirect("/*.html", 
HttpServletResponse.SC_MOVED_TEMPORARILY);
+    }
+
+    @Test
+    public void testUpdateGroupInvalidRedirectWithAuthority() throws 
IOException, JsonException {
+        testUpdateGroupRedirect("https://sling.apache.org";, 
SC_UNPROCESSABLE_ENTITY);
+    }
+
+    @Test
+    public void testUpdateGroupInvalidRedirectWithInvalidURI() throws 
IOException, JsonException {
+        testUpdateGroupRedirect("https://";, SC_UNPROCESSABLE_ENTITY);
+    }
+
 }
 
diff --git 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UpdateUserIT.java
 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UpdateUserIT.java
index f44271a..b23dc7a 100644
--- 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UpdateUserIT.java
+++ 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UpdateUserIT.java
@@ -376,4 +376,61 @@ public class UpdateUserIT extends 
UserManagerClientTestSupport {
         httpContext.getCookieStore().clear();
     }
 
+    private void testChangeUserPasswordRedirect(String redirectTo, int 
expectedStatus) throws IOException {
+        testUserId = createTestUser();
+
+        String postUrl = 
String.format("%s/system/userManager/user/%s.changePassword.html", 
baseServerUri, testUserId);
+
+        List<NameValuePair> postParams = new ArrayList<>();
+        postParams.add(new BasicNameValuePair("oldPwd", "testPwd"));
+        postParams.add(new BasicNameValuePair("newPwd", "testNewPwd"));
+        postParams.add(new BasicNameValuePair("newPwdConfirm", "testNewPwd"));
+        postParams.add(new BasicNameValuePair(":redirect", redirectTo));
+
+        Credentials creds = new UsernamePasswordCredentials(testUserId, 
"testPwd");
+        assertAuthenticatedPostStatus(creds, postUrl, expectedStatus, 
postParams, null);
+    }
+
+    @Test
+    public void testChangeUserPasswordValidRedirect() throws IOException, 
JsonException {
+        testChangeUserPasswordRedirect("/*.html", 
HttpServletResponse.SC_MOVED_TEMPORARILY);
+    }
+
+    @Test
+    public void testChangeUserPasswordInvalidRedirectWithAuthority() throws 
IOException, JsonException {
+        testChangeUserPasswordRedirect("https://sling.apache.org";, 
SC_UNPROCESSABLE_ENTITY);
+    }
+
+    @Test
+    public void testChangeUserPasswordInvalidRedirectWithInvalidURI() throws 
IOException, JsonException {
+        testChangeUserPasswordRedirect("https://";, SC_UNPROCESSABLE_ENTITY);
+    }
+
+    private void testUpdateUserRedirect(String redirectTo, int expectedStatus) 
throws IOException {
+        testUserId = createTestUser();
+
+        String postUrl = 
String.format("%s/system/userManager/user/%s.update.html", baseServerUri, 
testUserId);
+
+        List<NameValuePair> postParams = new ArrayList<>();
+        postParams.add(new BasicNameValuePair("displayName", "My Updated Test 
User"));
+        postParams.add(new BasicNameValuePair(":redirect", redirectTo));
+        Credentials creds = new UsernamePasswordCredentials(testUserId, 
"testPwd");
+        assertAuthenticatedPostStatus(creds, postUrl, expectedStatus, 
postParams, null);
+    }
+
+    @Test
+    public void testUpdateUserValidRedirect() throws IOException, 
JsonException {
+        testUpdateUserRedirect("/*.html", 
HttpServletResponse.SC_MOVED_TEMPORARILY);
+    }
+
+    @Test
+    public void testUpdateUserInvalidRedirectWithAuthority() throws 
IOException, JsonException {
+        testUpdateUserRedirect("https://sling.apache.org";, 
SC_UNPROCESSABLE_ENTITY);
+    }
+
+    @Test
+    public void testUpdateUserInvalidRedirectWithInvalidURI() throws 
IOException, JsonException {
+        testUpdateUserRedirect("https://";, SC_UNPROCESSABLE_ENTITY);
+    }
+
 }
diff --git 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UserManagerClientTestSupport.java
 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UserManagerClientTestSupport.java
index 219b64f..64c96cc 100644
--- 
a/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UserManagerClientTestSupport.java
+++ 
b/src/test/java/org/apache/sling/jcr/jackrabbit/usermanager/it/post/UserManagerClientTestSupport.java
@@ -86,6 +86,8 @@ import org.osgi.service.cm.ConfigurationAdmin;
  * servlets
  */
 public abstract class UserManagerClientTestSupport extends 
UserManagerTestSupport {
+    protected static final int SC_UNPROCESSABLE_ENTITY = 422; // http status 
code for 422 Unprocessable Entity
+
     protected static final String TEST_FOLDER_JSON = "{'jcr:primaryType': 
'nt:unstructured'}";
 
     protected static final String CONTENT_TYPE_JSON = "application/json";

Reply via email to