Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add documentation for form limits & improve configuration via context attributes #12560

Open
wants to merge 1 commit into
base: jetty-12.0.x
Choose a base branch
from
Open
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
@@ -0,0 +1,30 @@
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.docs.programming.security;

import org.eclipse.jetty.ee10.servlet.ServletContextHandler;

public class FormSizeDocs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rename it to FormDocs, as we may use it for something else than just "size".

{
public void example()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to limitFormContent(), like the paragraph that refers to this, and same for the tag.

{
ServletContextHandler servletContextHandler = new ServletContextHandler();
int maxSizeInBytes = 1024;
int formKeys = 100;
// tag::formSizeConfig[]
Comment on lines +23 to +25
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include the int values in the documentation.

servletContextHandler.setMaxFormContentSize(maxSizeInBytes);
servletContextHandler.setMaxFormKeys(formKeys);
// end::formSizeConfig[]
}
}
2 changes: 2 additions & 0 deletions documentation/jetty/modules/programming-guide/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
** xref:troubleshooting/state-tracking.adoc[]
** xref:troubleshooting/component-dump.adoc[]
** xref:troubleshooting/debugging.adoc[]
* Jetty Security
** xref:security/configuring-form-size.adoc[]
* Migration Guides
** xref:migration/94-to-10.adoc[]
** xref:migration/11-to-12.adoc[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

[[configuring-form-size]]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rename it to limit-form-content, like the title.

= Limiting Form Content

Form content sent to the server is processed by Jetty into a map of parameters to be used by the web application.
This can be vulnerable to denial of service (DOS) attacks since significant memory and CPU can be consumed if a malicious clients sends very large form content or large number of form keys.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This can be vulnerable to denial of service (DOS) attacks since significant memory and CPU can be consumed if a malicious clients sends very large form content or large number of form keys.
Forms can be a vector for denial-of-service attacks, since significant memory and CPU can be consumed if a malicious clients sends very large form content or a large number of form keys.

Thus, Jetty limits the amount of data and keys that can be in a form posted to Jetty.

The default maximum size Jetty permits is 200000 bytes and 1000 keys.
You can change this default for a particular webapp or for all webapps on a particular Server instance.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
You can change this default for a particular webapp or for all webapps on a particular Server instance.
You can change this default for a particular web application or for all web applications on a particular `Server` instance.


== Configuring Form Limits for a Webapp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
== Configuring Form Limits for a Webapp
== Configuring Form Limits for a Web Application


To configure the form limits for a single web application, the servlet context handler (or webappContext) instance must be configured using the following methods:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To configure the form limits for a single web application, the servlet context handler (or webappContext) instance must be configured using the following methods:
To configure the form limits for a single web application, the `ServletContextHandler` (or `WebappContext`) instance must be configured using the following methods:


[,java,indent=0]
----
include::code:example$src/main/java/org/eclipse/jetty/docs/programming/security/FormSizeDocs.java[tags=formSizeConfig]
----

These methods may be called directly when embedding Jetty, but more commonly are configured from a context XML file or WEB-INF/jetty-web.xml file:

[,xml,subs=attributes+]
----
<Configure class="org.eclipse.jetty.{ee-current}.webapp.WebAppContext">

...

<Set name="maxFormContentSize">200000</Set>
<Set name="maxFormKeys">200</Set>
</Configure>

----
Comment on lines +33 to +45
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be moved to the operations guide.


These settings can also be set via the following Context attributes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not clear what "Context" are you referring to here.

You mean context attributes in web.xml?
If so, better have an example, but should propably better be in the operations guide.


- `org.eclipse.jetty.server.Request.maxFormKeys`
- `org.eclipse.jetty.server.Request.maxFormContentSize`

== Configuring Default Form Limits for the Server

The default `maxFormKeys` is 1000 and the default `maxFormContentSize` is 200000.

However, the following system properties can be set to change the default values of this across every context; `org.eclipse.jetty.server.Request.maxFormKeys` and `org.eclipse.jetty.server.Request.maxFormContentSize`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put them in a bullet list like above.

I wonder why we don't look these up as Server attributes, before using system properties?

Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ public InvocationType getInvocationType()
public void dump(Appendable out, String indent) throws IOException
{
dumpObjects(out, indent,
Dumpable.named("maxFormKeys ", getMaxFormKeys()),
Dumpable.named("maxFormContentSize ", getMaxFormContentSize()),
Comment on lines +322 to +323
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move down in the dump to be after the attributes

new ClassLoaderDump(getClassLoader()),
Dumpable.named("context " + this, getContext()),
Dumpable.named("handler attributes " + this, getContext().getPersistentAttributes()),
Expand Down Expand Up @@ -2045,6 +2047,44 @@ public void setExtendedListenerTypes(boolean b)
{
_servletContext.setExtendedListenerTypes(b);
}

@Override
public Object getAttribute(String name)
{
return switch (name)
{
case FormFields.MAX_FIELDS_ATTRIBUTE -> getMaxFormKeys();
case FormFields.MAX_LENGTH_ATTRIBUTE -> getMaxFormContentSize();
default -> super.getAttribute(name);
};
}

@Override
public Object setAttribute(String name, Object attribute)
{
return switch (name)
{
case FormFields.MAX_FIELDS_ATTRIBUTE ->
{
int oldValue = getMaxFormKeys();
if (attribute == null)
setMaxFormKeys(DEFAULT_MAX_FORM_KEYS);
else
setMaxFormKeys(Integer.parseInt(attribute.toString()));
yield oldValue;
}
case FormFields.MAX_LENGTH_ATTRIBUTE ->
{
int oldValue = getMaxFormContentSize();
if (attribute == null)
setMaxFormContentSize(DEFAULT_MAX_FORM_CONTENT_SIZE);
else
setMaxFormContentSize(Integer.parseInt(attribute.toString()));
yield oldValue;
}
default -> super.setAttribute(name, attribute);
};
}
}

public class ServletContextApi implements jakarta.servlet.ServletContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ClassLoaderDump;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.DumpableCollection;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceFactory;
Expand Down Expand Up @@ -987,6 +988,8 @@ else if (getBaseResource() != null)
name = String.format("%s@%x", name, hashCode());

dumpObjects(out, indent,
Dumpable.named("maxFormKeys ", getMaxFormKeys()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this line, dump also the environment like in ee9?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than override dump and have to repeat the stuff from the base class, why don't we just add all these Dumpable collections as beans the the context and let the normal dump mechanism dump them?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or better yet, add one Dumpable webapp bean, that dumps all these extra details

Dumpable.named("maxFormContentSize ", getMaxFormContentSize()),
new ClassLoaderDump(getClassLoader()),
new DumpableCollection("Systemclasses " + name, systemClasses),
new DumpableCollection("Serverclasses " + name, serverClasses),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.DumpableCollection;
import org.eclipse.jetty.util.component.Environment;
import org.eclipse.jetty.util.component.LifeCycle;
Expand Down Expand Up @@ -302,7 +303,10 @@ public void insertHandler(org.eclipse.jetty.server.Handler.Singleton coreHandler
@Override
public void dump(Appendable out, String indent) throws IOException
{
dumpObjects(out, indent, new DumpableCollection("initparams " + this, getInitParams().entrySet()));
dumpObjects(out, indent,
Dumpable.named("maxFormKeys ", getMaxFormKeys()),
Dumpable.named("maxFormContentSize ", getMaxFormContentSize()),
new DumpableCollection("initparams " + this, getInitParams().entrySet()));
}

public APIContext getServletContext()
Expand Down Expand Up @@ -2861,6 +2865,44 @@ public APIContext getAPIContext()
{
return _apiContext;
}

@Override
public Object getAttribute(String name)
{
return switch (name)
{
case FormFields.MAX_FIELDS_ATTRIBUTE -> getMaxFormKeys();
case FormFields.MAX_LENGTH_ATTRIBUTE -> getMaxFormContentSize();
default -> super.getAttribute(name);
};
}

@Override
public Object setAttribute(String name, Object attribute)
{
return switch (name)
{
case FormFields.MAX_FIELDS_ATTRIBUTE ->
{
int oldValue = getMaxFormKeys();
if (attribute == null)
setMaxFormKeys(DEFAULT_MAX_FORM_KEYS);
else
setMaxFormKeys(Integer.parseInt(attribute.toString()));
yield oldValue;
}
case FormFields.MAX_LENGTH_ATTRIBUTE ->
{
int oldValue = getMaxFormContentSize();
if (attribute == null)
setMaxFormContentSize(DEFAULT_MAX_FORM_CONTENT_SIZE);
else
setMaxFormContentSize(Integer.parseInt(attribute.toString()));
yield oldValue;
}
default -> super.setAttribute(name, attribute);
};
}
}

private class CoreToNestedHandler extends Abstract
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ else if (getResourceBase() != null)

dumpObjects(out, indent,
Dumpable.named("environment", ContextHandler.ENVIRONMENT.getName()),
Dumpable.named("maxFormKeys ", getMaxFormKeys()),
Dumpable.named("maxFormContentSize ", getMaxFormContentSize()),
new ClassLoaderDump(getClassLoader()),
new DumpableCollection("Systemclasses " + name, systemClasses),
new DumpableCollection("Serverclasses " + name, serverClasses),
Expand Down
Loading