Skip to content

Commit 07edcd2

Browse files
committed
http: strict checks for RTSP methods
Disallow HTTP methods for RTSP, and vice versa PR-URL: #68 Reviewed-By: Fedor Indutny <[email protected]>
1 parent 0b0772c commit 07edcd2

File tree

4 files changed

+154
-9
lines changed

4 files changed

+154
-9
lines changed

src/llhttp/constants.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,69 @@ export enum METHODS {
113113
FLUSH = 45,
114114
}
115115

116+
export const METHODS_HTTP = [
117+
METHODS.DELETE,
118+
METHODS.GET,
119+
METHODS.HEAD,
120+
METHODS.POST,
121+
METHODS.PUT,
122+
METHODS.CONNECT,
123+
METHODS.OPTIONS,
124+
METHODS.TRACE,
125+
METHODS.COPY,
126+
METHODS.LOCK,
127+
METHODS.MKCOL,
128+
METHODS.MOVE,
129+
METHODS.PROPFIND,
130+
METHODS.PROPPATCH,
131+
METHODS.SEARCH,
132+
METHODS.UNLOCK,
133+
METHODS.BIND,
134+
METHODS.REBIND,
135+
METHODS.UNBIND,
136+
METHODS.ACL,
137+
METHODS.REPORT,
138+
METHODS.MKACTIVITY,
139+
METHODS.CHECKOUT,
140+
METHODS.MERGE,
141+
METHODS['M-SEARCH'],
142+
METHODS.NOTIFY,
143+
METHODS.SUBSCRIBE,
144+
METHODS.UNSUBSCRIBE,
145+
METHODS.PATCH,
146+
METHODS.PURGE,
147+
METHODS.MKCALENDAR,
148+
METHODS.LINK,
149+
METHODS.UNLINK,
150+
METHODS.PRI,
151+
152+
// TODO(indutny): should we allow it with HTTP?
153+
METHODS.SOURCE,
154+
];
155+
156+
export const METHODS_ICE = [
157+
METHODS.SOURCE,
158+
];
159+
160+
export const METHODS_RTSP = [
161+
METHODS.OPTIONS,
162+
METHODS.DESCRIBE,
163+
METHODS.ANNOUNCE,
164+
METHODS.SETUP,
165+
METHODS.PLAY,
166+
METHODS.PAUSE,
167+
METHODS.TEARDOWN,
168+
METHODS.GET_PARAMETER,
169+
METHODS.SET_PARAMETER,
170+
METHODS.REDIRECT,
171+
METHODS.RECORD,
172+
METHODS.FLUSH,
173+
174+
// For AirPlay
175+
METHODS.GET,
176+
METHODS.POST,
177+
];
178+
116179
export const METHOD_MAP = enumToMap(METHODS);
117180
export const H_METHOD_MAP: IEnumMap = {};
118181

src/llhttp/http.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import {
99
CONNECTION_TOKEN_CHARS, ERROR, FINISH, FLAGS, H_METHOD_MAP, HEADER_CHARS,
1010
HEADER_STATE, HEX_MAP,
1111
HTTPMode,
12-
MAJOR, METHOD_MAP, METHODS, MINOR, NUM_MAP, SPECIAL_HEADERS, STRICT_TOKEN,
12+
MAJOR, METHOD_MAP, METHODS, METHODS_HTTP, METHODS_ICE, METHODS_RTSP,
13+
MINOR, NUM_MAP, SPECIAL_HEADERS, STRICT_TOKEN,
1314
TOKEN, TYPE,
1415
} from './constants';
1516
import { URL } from './url';
@@ -309,16 +310,25 @@ export class HTTP {
309310
this.update('http_minor', 9, 'header_field_start')),
310311
);
311312

312-
const isSource = this.isEqual('method', METHODS.SOURCE, {
313-
equal: n('req_http_major'),
314-
notEqual: p.error(ERROR.INVALID_CONSTANT,
315-
'Expected SOURCE method for ICE/x.x request'),
316-
});
313+
const checkMethod = (methods: METHODS[], error: string): Node => {
314+
const success = n('req_http_major');
315+
const failure = p.error(ERROR.INVALID_CONSTANT, error);
316+
317+
const map: { [key: number]: Node } = {};
318+
for (const method of methods) {
319+
map[method] = success;
320+
}
321+
322+
return this.load('method', map, failure);
323+
};
317324

318325
n('req_http_start')
319-
.match('HTTP/', n('req_http_major'))
320-
.match('RTSP/', n('req_http_major'))
321-
.match('ICE/', isSource)
326+
.match('HTTP/', checkMethod(METHODS_HTTP,
327+
'Invalid method for HTTP/x.x request'))
328+
.match('RTSP/', checkMethod(METHODS_RTSP,
329+
'Invalid method for RTSP/x.x request'))
330+
.match('ICE/', checkMethod(METHODS_ICE,
331+
'Expected SOURCE method for ICE/x.x request'))
322332
.match(' ', n('req_http_start'))
323333
.otherwise(p.error(ERROR.INVALID_CONSTANT, 'Expected HTTP/'));
324334

test/request/invalid.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,38 @@ off=4 len=18 span[url]="/music/sweet/music"
3333
off=24 error code=8 reason="Expected HTTP/"
3434
```
3535

36+
### RTSP protocol and PUT method
37+
38+
<!-- meta={"type": "request"} -->
39+
```http
40+
PUT /music/sweet/music RTSP/1.0
41+
Host: example.com
42+
43+
44+
```
45+
46+
```log
47+
off=0 message begin
48+
off=4 len=18 span[url]="/music/sweet/music"
49+
off=28 error code=8 reason="Invalid method for RTSP/x.x request"
50+
```
51+
52+
### HTTP protocol and ANNOUNCE method
53+
54+
<!-- meta={"type": "request"} -->
55+
```http
56+
ANNOUNCE /music/sweet/music HTTP/1.0
57+
Host: example.com
58+
59+
60+
```
61+
62+
```log
63+
off=0 message begin
64+
off=9 len=18 span[url]="/music/sweet/music"
65+
off=33 error code=8 reason="Invalid method for HTTP/x.x request"
66+
```
67+
3668
### Headers separated by CR
3769

3870
<!-- meta={"type": "request"} -->

test/request/method.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,46 @@ off=56 headers complete method=33 v=1/0 flags=0 content_length=0
267267
off=56 message complete
268268
```
269269

270+
### OPTIONS request with RTSP
271+
272+
NOTE: `OPTIONS` is a valid HTTP metho too.
273+
274+
<!-- meta={"type": "request"} -->
275+
```http
276+
OPTIONS /music/sweet/music RTSP/1.0
277+
Host: example.com
278+
279+
280+
```
281+
282+
```log
283+
off=0 message begin
284+
off=8 len=18 span[url]="/music/sweet/music"
285+
off=37 len=4 span[header_field]="Host"
286+
off=43 len=11 span[header_value]="example.com"
287+
off=58 headers complete method=6 v=1/0 flags=0 content_length=0
288+
off=58 message complete
289+
```
290+
291+
### ANNOUNCE request with RTSP
292+
293+
<!-- meta={"type": "request"} -->
294+
```http
295+
ANNOUNCE /music/sweet/music RTSP/1.0
296+
Host: example.com
297+
298+
299+
```
300+
301+
```log
302+
off=0 message begin
303+
off=9 len=18 span[url]="/music/sweet/music"
304+
off=38 len=4 span[header_field]="Host"
305+
off=44 len=11 span[header_value]="example.com"
306+
off=59 headers complete method=36 v=1/0 flags=0 content_length=0
307+
off=59 message complete
308+
```
309+
270310
### PRI request HTTP2
271311

272312
<!-- meta={"type": "request"} -->

0 commit comments

Comments
 (0)