@@ -9,18 +9,47 @@ const os = require('os');
99const MAX_FIELD_SIZE = 20 * 1024 ; // 20KB
1010/** @see doc: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html */
1111const 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+ ] ;
1232
1333async function authenticateRequest ( request , requestContexts , log ) {
1434 return new Promise ( resolve => {
15- // TODO RING-45960 remove ignore for POST object here
35+ // TODO RING-45960 remove ignore auth check for POST object here
1636 auth . server . doAuth ( request , log , ( err , userInfo , authorizationResults , streamingV4Params ) =>
1737 resolve ( { userInfo, authorizationResults, streamingV4Params } ) , 's3' , requestContexts ) ;
1838 } ) ;
1939}
2040
2141async function parseFormData ( request , response , requestContexts , log ) {
2242 /* eslint-disable no-param-reassign */
23- const formDataParser = busboy ( { headers : request . headers } ) ;
43+ let formDataParser ;
44+ try {
45+ formDataParser = busboy ( { headers : request . headers } ) ;
46+ } catch ( err ) {
47+ log . trace ( 'Error creating form data parser' , { error : err . toString ( ) } ) ;
48+ return Promise . reject ( errors . PreconditionFailed
49+ . customizeDescription ( 'Bucket POST must be of the enclosure-type multipart/form-data' ) ) ;
50+ }
51+
52+ // formDataParser = busboy({ headers: request.headers });
2453 writeContinue ( request , response ) ;
2554
2655 return new Promise ( ( resolve , reject ) => {
@@ -37,20 +66,28 @@ async function parseFormData(request, response, requestContexts, log) {
3766 const formParserFinishedPromise = new Promise ( ( res ) => { formParserFinishedPromiseResolve = res ; } ) ;
3867
3968 formDataParser . on ( 'field' , ( fieldname , val ) => {
69+ // Check if we have exceeded the max size allowed for all fields
4070 totalFieldSize += Buffer . byteLength ( val , 'utf8' ) ;
4171 if ( totalFieldSize > MAX_FIELD_SIZE ) {
4272 return reject ( errors . MaxPostPreDataLengthExceeded ) ;
4373 }
74+
75+ // validate the fieldname
4476 const lowerFieldname = fieldname . toLowerCase ( ) ;
77+ // special handling for key field
4578 if ( lowerFieldname === 'key' ) {
4679 if ( val . length > MAX_KEY_SIZE ) {
4780 return reject ( errors . KeyTooLong ) ;
4881 } else if ( val . length === 0 ) {
4982 return reject ( errors . InvalidArgument
5083 . customizeDescription ( 'User key must have a length greater than 0.' ) ) ;
5184 }
85+ request . formData [ lowerFieldname ] = val ;
86+ }
87+ // add only the recognized fields to the formData object
88+ if ( POST_OBJECT_OPTIONAL_FIELDS . some ( field => lowerFieldname . startsWith ( field ) ) ) {
89+ request . formData [ lowerFieldname ] = val ;
5290 }
53- request . formData [ lowerFieldname ] = val ;
5491 return undefined ;
5592 } ) ;
5693
@@ -140,11 +177,6 @@ function getFileStat(filePath, log) {
140177}
141178
142179async 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- }
148180 try {
149181 const { userInfo, authorizationResults, streamingV4Params } =
150182 await parseFormData ( request , response , requestContexts , log ) ;
0 commit comments