diff options
author | Ed Tanous <edtanous@google.com> | 2023-08-25 19:34:07 +0300 |
---|---|---|
committer | Ed Tanous <ed@tanous.net> | 2024-01-19 22:43:50 +0300 |
commit | f86bcc875a496b3c321a4ed102579a4031617800 (patch) | |
tree | ea0ee25603c64a63a77edac9e4fe036e22916b96 /redfish-core | |
parent | 367b3dce0567c223f53ce1a4cc10d34241111774 (diff) | |
download | bmcweb-f86bcc875a496b3c321a4ed102579a4031617800.tar.xz |
Clean up tftp update to use URL
Similar to transforms we've done elsewhere, we shouldn't be parsing
urls using std::string::find, regex, or anything else, as they don't
handle URL % encoding properly.
Change-Id: I48bb30c0c737c4df2ae73f40fc49c63bac5b658f
Signed-off-by: Ed Tanous <edtanous@google.com>
Diffstat (limited to 'redfish-core')
-rw-r--r-- | redfish-core/lib/update_service.hpp | 120 |
1 files changed, 69 insertions, 51 deletions
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp index 9ab1a3b16b..9a07d3c334 100644 --- a/redfish-core/lib/update_service.hpp +++ b/redfish-core/lib/update_service.hpp @@ -433,6 +433,70 @@ static void monitorForSoftwareAvailable( std::bind_front(afterUpdateErrorMatcher, asyncResp, url)); } +struct TftpUrl +{ + std::string fwFile; + std::string tftpServer; +}; + +inline std::optional<TftpUrl> + parseTftpUrl(std::string imageURI, + std::optional<std::string> transferProtocol, + crow::Response& res) +{ + if (imageURI.find("://") == std::string::npos) + { + if (imageURI.starts_with("/")) + { + messages::actionParameterValueTypeError( + res, imageURI, "ImageURI", "UpdateService.SimpleUpdate"); + return std::nullopt; + } + if (!transferProtocol) + { + messages::actionParameterValueTypeError( + res, imageURI, "ImageURI", "UpdateService.SimpleUpdate"); + return std::nullopt; + } + // OpenBMC currently only supports TFTP + if (*transferProtocol != "TFTP") + { + messages::actionParameterNotSupported(res, "TransferProtocol", + *transferProtocol); + BMCWEB_LOG_ERROR("Request incorrect protocol parameter: {}", + *transferProtocol); + return std::nullopt; + } + imageURI = "tftp://" + imageURI; + } + + boost::system::result<boost::urls::url> url = + boost::urls::parse_absolute_uri(imageURI); + if (!url) + { + messages::actionParameterValueTypeError(res, imageURI, "ImageURI", + "UpdateService.SimpleUpdate"); + + return std::nullopt; + } + url->normalize(); + + if (url->scheme() != "tftp") + { + messages::actionParameterNotSupported(res, "ImageURI", imageURI); + return std::nullopt; + } + std::string path(url->encoded_path()); + if (path.size() < 2) + { + messages::actionParameterNotSupported(res, "ImageURI", imageURI); + return std::nullopt; + } + path.erase(0, 1); + std::string host(url->encoded_host_and_port()); + return TftpUrl{path, host}; +} + /** * UpdateServiceActionsSimpleUpdate class supports handle POST method for * SimpleUpdate action. @@ -467,60 +531,14 @@ inline void requestRoutesUpdateServiceActionsSimpleUpdate(App& app) BMCWEB_LOG_DEBUG("Missing TransferProtocol or ImageURI parameter"); return; } - if (!transferProtocol) - { - // Must be option 2 - // Verify ImageURI has transfer protocol in it - size_t separator = imageURI.find(':'); - if ((separator == std::string::npos) || - ((separator + 1) > imageURI.size())) - { - messages::actionParameterValueTypeError( - asyncResp->res, imageURI, "ImageURI", - "UpdateService.SimpleUpdate"); - BMCWEB_LOG_ERROR("ImageURI missing transfer protocol: {}", - imageURI); - return; - } - transferProtocol = imageURI.substr(0, separator); - // Ensure protocol is upper case for a common comparison path - // below - boost::to_upper(*transferProtocol); - BMCWEB_LOG_DEBUG("Encoded transfer protocol {}", *transferProtocol); - - // Adjust imageURI to not have the protocol on it for parsing - // below - // ex. tftp://1.1.1.1/myfile.bin -> 1.1.1.1/myfile.bin - imageURI = imageURI.substr(separator + 3); - BMCWEB_LOG_DEBUG("Adjusted imageUri {}", imageURI); - } - - // OpenBMC currently only supports TFTP - if (*transferProtocol != "TFTP") - { - messages::actionParameterNotSupported(asyncResp->res, - "TransferProtocol", - "UpdateService.SimpleUpdate"); - BMCWEB_LOG_ERROR("Request incorrect protocol parameter: {}", - *transferProtocol); - return; - } - - // Format should be <IP or Hostname>/<file> for imageURI - size_t separator = imageURI.find('/'); - if ((separator == std::string::npos) || - ((separator + 1) > imageURI.size())) + std::optional<TftpUrl> ret = parseTftpUrl(imageURI, transferProtocol, + asyncResp->res); + if (!ret) { - messages::actionParameterValueTypeError( - asyncResp->res, imageURI, "ImageURI", - "UpdateService.SimpleUpdate"); - BMCWEB_LOG_ERROR("Invalid ImageURI: {}", imageURI); return; } - std::string tftpServer = imageURI.substr(0, separator); - std::string fwFile = imageURI.substr(separator + 1); - BMCWEB_LOG_DEBUG("Server: {}{}", tftpServer + " File: ", fwFile); + BMCWEB_LOG_DEBUG("Server: {} File: {}", ret->tftpServer, ret->fwFile); // Setup callback for when new software detected // Give TFTP 10 minutes to complete @@ -552,7 +570,7 @@ inline void requestRoutesUpdateServiceActionsSimpleUpdate(App& app) }, "xyz.openbmc_project.Software.Download", "/xyz/openbmc_project/software", "xyz.openbmc_project.Common.TFTP", - "DownloadViaTFTP", fwFile, tftpServer); + "DownloadViaTFTP", ret->fwFile, ret->tftpServer); BMCWEB_LOG_DEBUG("Exit UpdateService.SimpleUpdate doPost"); }); |