Skip to content

Commit

Permalink
http: strict checks for RTSP methods
Browse files Browse the repository at this point in the history
Disallow HTTP methods for RTSP, and vice versa
  • Loading branch information
indutny committed Oct 16, 2020
1 parent ea81c55 commit 1e69a7e
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 9 deletions.
63 changes: 63 additions & 0 deletions src/llhttp/constants.ts
Expand Up @@ -113,6 +113,69 @@ export enum METHODS {
FLUSH = 45,
}

export const METHODS_HTTP = [
METHODS.DELETE,
METHODS.GET,
METHODS.HEAD,
METHODS.POST,
METHODS.PUT,
METHODS.CONNECT,
METHODS.OPTIONS,
METHODS.TRACE,
METHODS.COPY,
METHODS.LOCK,
METHODS.MKCOL,
METHODS.MOVE,
METHODS.PROPFIND,
METHODS.PROPPATCH,
METHODS.SEARCH,
METHODS.UNLOCK,
METHODS.BIND,
METHODS.REBIND,
METHODS.UNBIND,
METHODS.ACL,
METHODS.REPORT,
METHODS.MKACTIVITY,
METHODS.CHECKOUT,
METHODS.MERGE,
METHODS['M-SEARCH'],
METHODS.NOTIFY,
METHODS.SUBSCRIBE,
METHODS.UNSUBSCRIBE,
METHODS.PATCH,
METHODS.PURGE,
METHODS.MKCALENDAR,
METHODS.LINK,
METHODS.UNLINK,
METHODS.PRI,

// TODO(indutny): should we allow it with HTTP?
METHODS.SOURCE,
];

export const METHODS_ICE = [
METHODS.SOURCE,
];

export const METHODS_RTSP = [
METHODS.OPTIONS,
METHODS.DESCRIBE,
METHODS.ANNOUNCE,
METHODS.SETUP,
METHODS.PLAY,
METHODS.PAUSE,
METHODS.TEARDOWN,
METHODS.GET_PARAMETER,
METHODS.SET_PARAMETER,
METHODS.REDIRECT,
METHODS.RECORD,
METHODS.FLUSH,

// For AirPlay
METHODS.GET,
METHODS.POST,
];

export const METHOD_MAP = enumToMap(METHODS);
export const H_METHOD_MAP: IEnumMap = {};

Expand Down
28 changes: 19 additions & 9 deletions src/llhttp/http.ts
Expand Up @@ -9,7 +9,8 @@ import {
CONNECTION_TOKEN_CHARS, ERROR, FINISH, FLAGS, H_METHOD_MAP, HEADER_CHARS,
HEADER_STATE, HEX_MAP,
HTTPMode,
MAJOR, METHOD_MAP, METHODS, MINOR, NUM_MAP, SPECIAL_HEADERS, STRICT_TOKEN,
MAJOR, METHOD_MAP, METHODS, METHODS_HTTP, METHODS_ICE, METHODS_RTSP,
MINOR, NUM_MAP, SPECIAL_HEADERS, STRICT_TOKEN,
TOKEN, TYPE,
} from './constants';
import { URL } from './url';
Expand Down Expand Up @@ -309,16 +310,25 @@ export class HTTP {
this.update('http_minor', 9, 'header_field_start')),
);

const isSource = this.isEqual('method', METHODS.SOURCE, {
equal: n('req_http_major'),
notEqual: p.error(ERROR.INVALID_CONSTANT,
'Expected SOURCE method for ICE/x.x request'),
});
const checkMethod = (methods: METHODS[], error: string): Node => {
const success = n('req_http_major');
const failure = p.error(ERROR.INVALID_CONSTANT, error);

const map: { [key: number]: Node } = {};
for (const method of methods) {
map[method] = success;
}

return this.load('method', map, failure);
};

n('req_http_start')
.match('HTTP/', n('req_http_major'))
.match('RTSP/', n('req_http_major'))
.match('ICE/', isSource)
.match('HTTP/', checkMethod(METHODS_HTTP,
'Invalid method for HTTP/x.x request'))
.match('RTSP/', checkMethod(METHODS_RTSP,
'Invalid method for RTSP/x.x request'))
.match('ICE/', checkMethod(METHODS_ICE,
'Expected SOURCE method for ICE/x.x request'))
.match(' ', n('req_http_start'))
.otherwise(p.error(ERROR.INVALID_CONSTANT, 'Expected HTTP/'));

Expand Down
32 changes: 32 additions & 0 deletions test/request/invalid.md
Expand Up @@ -33,6 +33,38 @@ off=4 len=18 span[url]="/music/sweet/music"
off=24 error code=8 reason="Expected HTTP/"
```

### RTSP protocol and PUT method

<!-- meta={"type": "request"} -->
```http
PUT /music/sweet/music RTSP/1.0
Host: example.com
```

```log
off=0 message begin
off=4 len=18 span[url]="/music/sweet/music"
off=28 error code=8 reason="Invalid method for RTSP/x.x request"
```

### HTTP protocol and ANNOUNCE method

<!-- meta={"type": "request"} -->
```http
ANNOUNCE /music/sweet/music HTTP/1.0
Host: example.com
```

```log
off=0 message begin
off=9 len=18 span[url]="/music/sweet/music"
off=33 error code=8 reason="Invalid method for HTTP/x.x request"
```

### Headers separated by CR

<!-- meta={"type": "request"} -->
Expand Down
40 changes: 40 additions & 0 deletions test/request/method.md
Expand Up @@ -267,6 +267,46 @@ off=56 headers complete method=33 v=1/0 flags=0 content_length=0
off=56 message complete
```

### OPTIONS request with RTSP

NOTE: `OPTIONS` is a valid HTTP metho too.

<!-- meta={"type": "request"} -->
```http
OPTIONS /music/sweet/music RTSP/1.0
Host: example.com
```

```log
off=0 message begin
off=8 len=18 span[url]="/music/sweet/music"
off=37 len=4 span[header_field]="Host"
off=43 len=11 span[header_value]="example.com"
off=58 headers complete method=6 v=1/0 flags=0 content_length=0
off=58 message complete
```

### ANNOUNCE request with RTSP

<!-- meta={"type": "request"} -->
```http
ANNOUNCE /music/sweet/music RTSP/1.0
Host: example.com
```

```log
off=0 message begin
off=9 len=18 span[url]="/music/sweet/music"
off=38 len=4 span[header_field]="Host"
off=44 len=11 span[header_value]="example.com"
off=59 headers complete method=36 v=1/0 flags=0 content_length=0
off=59 message complete
```

### PRI request HTTP2

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

0 comments on commit 1e69a7e

Please sign in to comment.