1#lang scribble/doc
2@(require "web-server.rkt")
3
4@title[#:tag "safety-limits"]{Safety Limits}
5@defmodule[web-server/safety-limits]
6
7@(require (for-label web-server/private/dispatch-server-unit
8                     web-server/private/dispatch-server-sig
9                     web-server/private/util
10                     web-server/private/connection-manager
11                     web-server/web-server
12                     web-server/web-server-unit
13                     web-server/web-config-sig
14                     web-server/safety-limits
15                     web-server/lang/stuff-url
16                     web-server/http/request-structs
17                     net/tcp-sig
18                     racket/async-channel
19                     racket/tcp
20                     web-server/web-server-sig))
21
22@deftogether[
23 (@defproc[(safety-limits? [v any/c]) boolean?]
24   @defproc[(make-safety-limits
25             [#:max-waiting max-waiting exact-nonnegative-integer? 511]
26             [#:request-read-timeout request-read-timeout timeout/c 60]
27             [#:max-request-line-length max-request-line-length nonnegative-length/c
28              (code:line (* 8 1024) (code:comment #,(elem "8 KiB")))]
29             [#:max-request-headers max-request-headers nonnegative-length/c 100]
30             [#:max-request-header-length max-request-header-length nonnegative-length/c
31              (code:line (* 8 1024) (code:comment #,(elem "8 KiB")))]
32             [#:max-request-body-length max-request-body-length nonnegative-length/c
33              (code:line (* 1 1024 1024) (code:comment #,(elem "1 MiB")))]
34             [#:max-form-data-parts max-form-data-parts nonnegative-length/c
35              (+ max-form-data-fields max-form-data-files)]
36             [#:max-form-data-header-length max-form-data-header-length nonnegative-length/c
37              (code:line (* 8 1024) (code:comment #,(elem "8 KiB")))]
38             [#:max-form-data-files max-form-data-files nonnegative-length/c 100]
39             [#:max-form-data-file-length max-form-data-file-length nonnegative-length/c
40              (code:line (* 10 1024 1024) (code:comment #,(elem "10 MiB")))]
41             [#:form-data-file-memory-threshold form-data-file-memory-threshold nonnegative-length/c
42              (code:line (* 1 1024 1024) (code:comment #,(elem "1 MiB")))]
43             [#:max-form-data-fields max-form-data-fields nonnegative-length/c 100]
44             [#:max-form-data-field-length max-form-data-field-length nonnegative-length/c
45              (code:line (* 8 1024) (code:comment #,(elem "8 KiB")))]
46             [#:response-timeout response-timeout timeout/c 60]
47             [#:response-send-timeout response-send-timeout timeout/c 60])
48            safety-limits?]
49   @defthing[nonnegative-length/c flat-contract?
50             #:value (or/c exact-nonnegative-integer? +inf.0)]
51   @defthing[timeout/c flat-contract?
52             #:value (>=/c 0)])]{
53 The web server uses opaque @deftech{safety limits} values, recognized
54 by the predicate @racket[safety-limits?], to encapsulate
55 policies for protection against misbehaving or malicious clients and servlets.
56 Construct @tech{safety limits} values using @racket[make-safety-limits],
57 which supplies reasonably safe default policies that should work for most applications.
58 See the @elemref["safety-limits-porting"]{compatability note} and
59  @racket[make-unlimited-safety-limits] for further details.
60
61 The arguments to @racket[make-safety-limits] are used as follows:
62 @itemlist[
63 @item{The @racket[max-waiting] argument is passed to @racket[tcp-listen]
64   to specify the maximum number of client connections that can be waiting for acceptance.
65   When @racket[max-waiting] clients are waiting for acceptance, no new client connections can be made.
66   }
67 @item{The @racket[request-read-timeout] limits how long, in seconds,
68   the standard @sigelem[dispatch-server-config*^ read-request] implementation
69   (e.g. from @racket[serve] or @racket[web-server@])
70   will wait for request data to come in from the client
71   before it closes the connection.
72   If you need to support large file uploads over slow connections,
73   you may need to adjust this value.
74   }
75 @item{The @racket[max-request-line-length] limits the length (in bytes) of the
76   the first line of an HTTP request (the ``request line''),
77   which specifies the request method, path, and protocol version.
78   Requests with a first line longer than @racket[max-request-line-length]
79   are rejected by the standard @sigelem[dispatch-server-config*^ read-request]
80   implementation (e.g. from @racket[serve] or @racket[web-server@]).
81   Increase this if you have very long URLs, but see also @racket[is-url-too-big?].
82   }
83 @item{The @racket[max-request-headers] and @racket[max-request-header-length]
84   arguments limit the number of headers allowed per HTTP request
85   and the length, in bytes, of an individual request header, respectively.
86   Requests that exceed these limits are rejected by the standard
87   @sigelem[dispatch-server-config*^ read-request]
88   implementation (e.g. from @racket[serve] or @racket[web-server@]).
89   }
90 @item{The @racket[max-request-body-length] limits the size, in bytes,
91   of HTTP request bodies---but it does not apply to multipart (file upload)
92   requests: see @racket[max-form-data-files] and related limits, below.
93   Requests with bodies longer than @racket[max-request-body-length]
94   are rejected by the standard @sigelem[dispatch-server-config*^ read-request]
95   implementation (e.g. from @racket[serve] or @racket[web-server@]).
96   }
97 @item{The @racket[max-form-data-files], @racket[max-form-data-fields],
98   @racket[max-form-data-file-length], @racket[max-form-data-field-length],
99   @racket[max-form-data-parts], @racket[form-data-file-memory-threshold],
100   and @racket[max-form-data-header-length] arguments control the handling of
101   @tt{multipart/form-data} (file upload) requests by the standard
102   @sigelem[dispatch-server-config*^ read-request]
103   implementation (e.g. from @racket[serve] or @racket[web-server@]).
104
105   The number of files and non-file ``fields'' per request are limited by
106   @racket[max-form-data-files] and @racket[max-form-data-fields], respectively,
107   and @racket[max-form-data-file-length] and @racket[max-form-data-field-length]
108   limit the length, in bytes, of an individual file or non-file field.
109   Additionally, the total number of ``parts,'' which includes both files and fields,
110   must not exceed @racket[max-form-data-parts].
111   Requests that exceed these limits are rejected.
112
113   Files longer than @racket[request-file-memory-threshold], in bytes,
114   are automatically offloaded to disk as temporary files
115   to avoid running out of memory.
116
117   The @racket[max-form-data-header-length] argument limits the length of a header
118   for an individual part (file or field).
119   Since such headers are already tightly constrained by
120   @hyperlink["https://tools.ietf.org/html/rfc7578#section-4.8"]{RFC 7578 §4.8.},
121   it should be especially rare to need to increase this limit,
122   but doing so could allow for exceptionally long file or field names.
123   }
124 @item{The @racket[response-timeout] and @racket[response-send-timeout]
125   arguments limit the time for which individual request handlers
126   (as in @sigelem[dispatch-server-config*^ dispatch]) are allowed to run.
127
128   The @racket[response-timeout] specifies the maximum time, in seconds,
129   that a handler is allowed to run after the request has been read
130   before it writes its first byte of response data.
131   If no data is written within this time limit, the connection is killed.
132
133   The @racket[response-send-timeout] specifies the maximum time, in seconds,
134   that the server will wait for a chunk of response data.
135   Each time a chunk of data is sent to the client, this timeout resets.
136   If your application uses streaming responses or long polling,
137   either adjust this value or make sure that your request handler sends
138   data periodically, such as a no-op, to avoid hitting this limit.
139   }]
140
141
142 @elemtag["safety-limits-porting"]{@bold{Compatibility note:}}
143 The @tech{safety limits} type may be extended in the future to provide
144 additional protections.
145 Creating @tech{safety limits} values with @racket[make-safety-limits]
146 will allow applications to take advantage of reasonable default values
147 for any new limits that are added.
148 However, adding new limits does have the potential to break some existing
149 applications: as an alternative, the @racket[make-unlimited-safety-limits]
150 constructor uses default values that avoid imposing any limits that
151 aren't explicitly specified. (In most cases, this means a default of @racket[+inf.0].)
152 Of course, applications using @racket[make-unlimited-safety-limits]
153 may remain vulnerable to threats which the values from @racket[make-safety-limits]
154 would have protected against.
155
156 The @tech{safety limits} type was introduced in version 1.6 of the
157 @tt{web-server-lib} package.
158 Previous versions of this library only supported the @racket[max-waiting] limit
159 and (in some cases) an @racket[initial-connection-timeout] limit,
160 which was similar to @racket[request-read-timeout], but had
161 @hyperlink["https://github.com/racket/web-server/pull/77"]{some problems}.
162 These limits were specified through @racket[dispatch-server-config^], @racket[web-config^],
163 and optional arguments to functions like @racket[serve]:
164 if values weren't explicitly supplied, the default behavior was closest to using
165 @racket[(make-unlimited-safety-limits #:request-read-timeout 60)].
166
167 However, version 1.6 adopted @racket[(make-safety-limits)] as the default,
168 as most applications would benefit from using reasonable protections.
169 When porting from earlier versions of this library,
170 if you think your application may be especially resource-intensive,
171 you may prefer to use @racket[make-unlimited-safety-limits] while determining
172 limits that work for your application.
173
174 @history[#:added "1.6"]
175}
176
177@defproc[(make-unlimited-safety-limits
178          [#:max-waiting max-waiting exact-nonnegative-integer? 511]
179          [#:request-read-timeout request-read-timeout timeout/c +inf.0]
180          [#:max-request-line-length max-request-line-length nonnegative-length/c +inf.0]
181          [#:max-request-headers max-request-headers nonnegative-length/c +inf.0]
182          [#:max-request-header-length max-request-header-length nonnegative-length/c +inf.0]
183          [#:max-request-body-length max-request-body-length nonnegative-length/c +inf.0]
184          [#:max-request-files max-request-files nonnegative-length/c +inf.0]
185          [#:max-request-file-length max-request-file-length nonnegative-length/c +inf.0]
186          [#:request-file-memory-threshold request-file-memory-threshold nonnegative-length/c +inf.0]
187          [#:max-form-data-parts max-form-data-parts nonnegative-length/c +inf.0]
188          [#:max-form-data-header-length max-form-data-header-length nonnegative-length/c +inf.0]
189          [#:max-form-data-files max-form-data-files nonnegative-length/c +inf.0]
190          [#:max-form-data-file-length max-form-data-file-length nonnegative-length/c +inf.0]
191          [#:form-data-file-memory-threshold form-data-file-memory-threshold nonnegative-length/c +inf.0]
192          [#:max-form-data-fields max-form-data-fields nonnegative-length/c +inf.0]
193          [#:max-form-data-field-length max-form-data-field-length nonnegative-length/c +inf.0]
194          [#:response-timeout response-timeout timeout/c +inf.0]
195          [#:response-send-timeout response-send-timeout timeout/c +inf.0])
196         safety-limits?]{
197 Like @racket[make-safety-limits], but with default values that avoid
198 imposing any limits that aren't explicitly specified,
199 rather than the safer defaults of @racket[make-safety-limits].
200 Think carefully before using @racket[make-unlimited-safety-limits],
201 as it may leave your application vulnerable to denial of service attacks
202 or other threats that the default values from @racket[make-safety-limits] would mitigate.
203 See the @elemref["safety-limits-porting"]{compatability note} for more details.
204
205 Note that the default value for @racket[max-waiting] is @racket[511],
206 @italic{not} @racket[+inf.0], due to the contract of @racket[tcp-listen].
207
208 @history[#:added "1.6"]
209}
210