Add content type check in the update service
The content type check is required in the update service. This may be a
security issue.
The correct content types to update service are multipart/form-data and
application/octet-stream. The multipart content type was missing from
the contentTypes array which is added in this drop.
Added couple of test cases.
Tested:
1) Make sure that update service content type
application/octet-stream are working correctly.
$ curl -k -H 'X-Auth-Token: THIbp1G0DiNVj3JrCZMf' -H 'Content-Type: \
application/octet-stream' -X POST \
-T ./obmc-phosphor-image-everest.ext4.mmc.tar \
https://${bmc}/redfish/v1/UpdateService/update
{
"@odata.id": "/redfish/v1/TaskService/Tasks/0",
"@odata.type": "#Task.v1_4_3.Task",
"Id": "0",
"TaskState": "Running",
"TaskStatus": "OK"
2) Make sure that update service content type
multipart/form-data are working correctly.
$ curl -k -H 'X-Auth-Token: Vc7KBgM6z3uMs1G7uVqu' \
-H Content-Type:multipart/form-data \
-F 'UpdateParameters={"Targets":["/redfish/v1/Managers/bmc"], \
"@Redfish.OperationApplyTime":"Immediate"};type=application/json'\
-F 'UpdateFile=@obmc-phosphor-image-p10bmc.ext4.mmc.tar; \
type=application/octet-stream' \
https://${bmc}/redfish/v1/UpdateService/update
{
"@Message.ExtendedInfo": [
{
"@odata.type": "#Message.v1_1_1.Message",
"Message": "The request completed successfully.",
"MessageArgs": [],
"MessageId": "Base.1.16.0.Success",
"MessageSeverity": "OK",
"Resolution": "None"
}
],
"@odata.id": "/redfish/v1/TaskService/Tasks/0",
"@odata.type": "#Task.v1_4_3.Task",
"Id": "0",
"TaskState": "Running",
"TaskStatus": "OK"
3) Make sure that command fails when content type is missing.
$ curl -k -H 'X-Auth-Token: vH3B88sh323sfy0YG8eN' -H Content-Type: \
-X POST -T ./obmc-phosphor-image-everest.ext4.mmc.tar \
https://${bmc}/redfish/v1/UpdateService/update
Bad Request
[INFO "http_connection.hpp":201] Request: 0x177f920 HTTP/1.1 POST \
/redfish/v1/UpdateService/update ::ffff:x.x.xx.xxx
|
[DEBUG "update_service.hpp":687] doPost: contentType=
[DEBUG "update_service.hpp":692] Bad content type specified:
4) Make sure that command fails when wrong cotent type specified.
$ curl -k -H 'X-Auth-Token: OQzODMaR0G29AjpD2YmT' -H 'Content-Type: \
application/octet-json' -X POST \
-T ./obmc-phosphor-image-everest.ext4.mmc.tar \
https://${bmc}/redfish/v1/UpdateService/update
Bad Request
[INFO "http_connection.hpp":201] Request: 0x17a69d0 HTTP/1.1 POST \
/redfish/v1/UpdateService/update ::ffff:x.x.xx.xxx
|
[DEBUG "update_service.hpp":687] doPost:
contentType=application/octet-json
[DEBUG "update_service.hpp":720] Bad content type specified:
application/octet-json
5) Make sure that command fails when header is not specified.
$ curl -k -H 'X-Auth-Token: Z1AEXg075qGKi0xISu6o' -X POST \
-T ./obmc-phosphor-image-everest.ext4.mmc.tar \
https://${bmc}/redfish/v1/UpdateService/update
Bad Request
[INFO "http_connection.hpp":201] Request: 0x17a69d0 HTTP/1.1 \
POST /redfish/v1/UpdateService/update ::ffff:x.x.xx.xxx
|
[DEBUG "update_service.hpp":687] doPost: contentType=
[DEBUG "update_service.hpp":692] Bad content type specified:
Change-Id: I48b709b6219debfed9ff60dd46ab87652e5a1fe5
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index 08af788..795010d 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -682,28 +682,44 @@
{
return;
}
- BMCWEB_LOG_DEBUG << "doPost...";
+ std::string_view contentType = req.getHeaderValue("Content-Type");
- // Setup callback for when new software detected
- monitorForSoftwareAvailable(asyncResp, req, "/redfish/v1/UpdateService");
+ BMCWEB_LOG_DEBUG << "doPost: contentType=" << contentType;
- MultipartParser parser;
- ParserError ec = parser.parse(req);
- if (ec == ParserError::ERROR_BOUNDARY_FORMAT)
+ // Make sure that content type is application/octet-stream or
+ // multipart/form-data
+ if (boost::iequals(contentType, "application/octet-stream"))
{
- // If the request didnt' contain boundary information, assume it was a
- // POST binary payload.
+ // Setup callback for when new software detected
+ monitorForSoftwareAvailable(asyncResp, req,
+ "/redfish/v1/UpdateService");
+
uploadImageFile(asyncResp->res, req.body());
- return;
}
- if (ec != ParserError::PARSER_SUCCESS)
+ else if (contentType.starts_with("multipart/form-data"))
{
- // handle error
- BMCWEB_LOG_ERROR << "MIME parse failed, ec : " << static_cast<int>(ec);
- messages::internalError(asyncResp->res);
- return;
+ MultipartParser parser;
+
+ // Setup callback for when new software detected
+ monitorForSoftwareAvailable(asyncResp, req,
+ "/redfish/v1/UpdateService");
+
+ ParserError ec = parser.parse(req);
+ if (ec != ParserError::PARSER_SUCCESS)
+ {
+ // handle error
+ BMCWEB_LOG_ERROR << "MIME parse failed, ec : "
+ << static_cast<int>(ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ updateMultipartContext(asyncResp, parser);
}
- updateMultipartContext(asyncResp, parser);
+ else
+ {
+ BMCWEB_LOG_DEBUG << "Bad content type specified:" << contentType;
+ asyncResp->res.result(boost::beast::http::status::bad_request);
+ }
}
inline void requestRoutesUpdateService(App& app)