Skip to content

Commit cb7b4fe

Browse files
author
Will Toozs
committed
fixup: update for content-type checking
1 parent 2a41094 commit cb7b4fe

File tree

2 files changed

+967
-341
lines changed

2 files changed

+967
-341
lines changed

lib/api/apiUtils/apiCallers/callPostObject.js

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,47 @@ const os = require('os');
99
const MAX_FIELD_SIZE = 20 * 1024; // 20KB
1010
/** @see doc: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html */
1111
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+
];
1232

1333
async 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

2141
async 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

142179
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-
}
148180
try {
149181
const { userInfo, authorizationResults, streamingV4Params } =
150182
await parseFormData(request, response, requestContexts, log);

0 commit comments

Comments
 (0)