@@ -9,18 +9,56 @@ const os = require('os');
9
9
const MAX_FIELD_SIZE = 20 * 1024 ; // 20KB
10
10
/** @see doc: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html */
11
11
const MAX_KEY_SIZE = 1024 ;
12
+ const POST_OBJECT_OPTIONAL_FIELDS = [
13
+ 'acl' ,
14
+ 'awsaccesskeyid' ,
15
+ 'bucket' ,
16
+ 'cache-control' ,
17
+ 'content-disposition' ,
18
+ 'content-encoding' ,
19
+ 'content-type' ,
20
+ 'expires' ,
21
+ 'policy' ,
22
+ 'redirect' ,
23
+ 'tagging' ,
24
+ 'success_action_redirect' ,
25
+ 'success_action_status' ,
26
+ 'x-amz-meta-' ,
27
+ 'x-amz-storage-class' ,
28
+ 'x-amz-security-token' ,
29
+ 'x-amz-signgnature' ,
30
+ 'x-amz-website-redirect-location' ,
31
+ ] ;
12
32
13
33
async function authenticateRequest ( request , requestContexts , log ) {
14
34
return new Promise ( resolve => {
15
35
// TODO RING-45960 remove ignore for POST object here
36
+ // if (err) {
37
+ // log.trace('authentication error', { error: err });
38
+ // return reject(err);
39
+ // }
16
40
auth . server . doAuth ( request , log , ( err , userInfo , authorizationResults , streamingV4Params ) =>
17
41
resolve ( { userInfo, authorizationResults, streamingV4Params } ) , 's3' , requestContexts ) ;
18
42
} ) ;
19
43
}
20
44
21
45
async function parseFormData ( request , response , requestContexts , log ) {
22
46
/* eslint-disable no-param-reassign */
23
- const formDataParser = busboy ( { headers : request . headers } ) ;
47
+ let formDataParser ;
48
+ if ( ! request . headers
49
+ || ! request . headers [ 'content-type' ]
50
+ || ! request . headers [ 'content-type' ] . startsWith ( 'multipart/form-data' ) ) {
51
+ return Promise . reject ( errors . PreconditionFailed
52
+ . customizeDescription ( 'Bucket POST must be of the enclosure-type multipart/form-data' ) ) ;
53
+ }
54
+ try {
55
+ formDataParser = busboy ( { headers : request . headers } ) ;
56
+ } catch ( err ) {
57
+ log . trace ( 'Error creating form data parser' , { error : err . toString ( ) } ) ;
58
+ return Promise . reject ( errors . PreconditionFailed ) ;
59
+ }
60
+
61
+ // formDataParser = busboy({ headers: request.headers });
24
62
writeContinue ( request , response ) ;
25
63
26
64
return new Promise ( ( resolve , reject ) => {
@@ -37,20 +75,28 @@ async function parseFormData(request, response, requestContexts, log) {
37
75
const formParserFinishedPromise = new Promise ( ( res ) => { formParserFinishedPromiseResolve = res ; } ) ;
38
76
39
77
formDataParser . on ( 'field' , ( fieldname , val ) => {
78
+ // Check if we have exceeded the max size allowed for all fields
40
79
totalFieldSize += Buffer . byteLength ( val , 'utf8' ) ;
41
80
if ( totalFieldSize > MAX_FIELD_SIZE ) {
42
81
return reject ( errors . MaxPostPreDataLengthExceeded ) ;
43
82
}
83
+
84
+ // validate the fieldname
44
85
const lowerFieldname = fieldname . toLowerCase ( ) ;
86
+ // special handling for key field
45
87
if ( lowerFieldname === 'key' ) {
46
88
if ( val . length > MAX_KEY_SIZE ) {
47
89
return reject ( errors . KeyTooLong ) ;
48
90
} else if ( val . length === 0 ) {
49
91
return reject ( errors . InvalidArgument
50
92
. customizeDescription ( 'User key must have a length greater than 0.' ) ) ;
51
93
}
94
+ request . formData [ lowerFieldname ] = val ;
95
+ }
96
+ // add only the recognized fields to the formData object
97
+ if ( POST_OBJECT_OPTIONAL_FIELDS . some ( field => lowerFieldname . startsWith ( field ) ) ) {
98
+ request . formData [ lowerFieldname ] = val ;
52
99
}
53
- request . formData [ lowerFieldname ] = val ;
54
100
return undefined ;
55
101
} ) ;
56
102
@@ -140,11 +186,6 @@ function getFileStat(filePath, log) {
140
186
}
141
187
142
188
async function processPostForm ( request , response , requestContexts , log , callback ) {
143
- if ( ! request . headers || ! request . headers [ 'content-type' ] . includes ( 'multipart/form-data' ) ) {
144
- const contentTypeError = errors . PreconditionFailed
145
- . customizeDescription ( 'Bucket POST must be of the enclosure-type multipart/form-data' ) ;
146
- return process . nextTick ( callback , contentTypeError ) ;
147
- }
148
189
try {
149
190
const { userInfo, authorizationResults, streamingV4Params } =
150
191
await parseFormData ( request , response , requestContexts , log ) ;
0 commit comments