1*ff35df94SOliver Brewka // SPDX-License-Identifier: Apache-2.0 2*ff35df94SOliver Brewka // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3*ff35df94SOliver Brewka // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 4*ff35df94SOliver Brewka 5*ff35df94SOliver Brewka #pragma once 6*ff35df94SOliver Brewka 7*ff35df94SOliver Brewka #include "app.hpp" 8*ff35df94SOliver Brewka #include "async_resp.hpp" 9*ff35df94SOliver Brewka #include "error_messages.hpp" 10*ff35df94SOliver Brewka #include "http_body.hpp" 11*ff35df94SOliver Brewka #include "http_response.hpp" 12*ff35df94SOliver Brewka #include "logging.hpp" 13*ff35df94SOliver Brewka 14*ff35df94SOliver Brewka #include <asm-generic/errno.h> 15*ff35df94SOliver Brewka #include <systemd/sd-bus.h> 16*ff35df94SOliver Brewka #include <unistd.h> 17*ff35df94SOliver Brewka 18*ff35df94SOliver Brewka #include <boost/beast/http/field.hpp> 19*ff35df94SOliver Brewka #include <boost/beast/http/status.hpp> 20*ff35df94SOliver Brewka #include <boost/beast/http/verb.hpp> 21*ff35df94SOliver Brewka #include <boost/system/linux_error.hpp> 22*ff35df94SOliver Brewka #include <boost/url/format.hpp> 23*ff35df94SOliver Brewka #include <boost/url/url.hpp> 24*ff35df94SOliver Brewka #include <sdbusplus/message.hpp> 25*ff35df94SOliver Brewka #include <sdbusplus/message/native_types.hpp> 26*ff35df94SOliver Brewka #include <sdbusplus/unpack_properties.hpp> 27*ff35df94SOliver Brewka 28*ff35df94SOliver Brewka #include <cstdio> 29*ff35df94SOliver Brewka #include <format> 30*ff35df94SOliver Brewka #include <memory> 31*ff35df94SOliver Brewka #include <string> 32*ff35df94SOliver Brewka 33*ff35df94SOliver Brewka namespace redfish 34*ff35df94SOliver Brewka { 35*ff35df94SOliver Brewka namespace log_services_utils 36*ff35df94SOliver Brewka { 37*ff35df94SOliver Brewka 38*ff35df94SOliver Brewka inline bool checkSizeLimit(int fd, crow::Response& res) 39*ff35df94SOliver Brewka { 40*ff35df94SOliver Brewka long long int size = lseek(fd, 0, SEEK_END); 41*ff35df94SOliver Brewka if (size <= 0) 42*ff35df94SOliver Brewka { 43*ff35df94SOliver Brewka BMCWEB_LOG_ERROR("Failed to get size of file, lseek() returned {}", 44*ff35df94SOliver Brewka size); 45*ff35df94SOliver Brewka messages::internalError(res); 46*ff35df94SOliver Brewka return false; 47*ff35df94SOliver Brewka } 48*ff35df94SOliver Brewka 49*ff35df94SOliver Brewka // Arbitrary max size of 20MB to accommodate BMC dumps 50*ff35df94SOliver Brewka constexpr long long int maxFileSize = 20LL * 1024LL * 1024LL; 51*ff35df94SOliver Brewka if (size > maxFileSize) 52*ff35df94SOliver Brewka { 53*ff35df94SOliver Brewka BMCWEB_LOG_ERROR("File size {} exceeds maximum allowed size of {}", 54*ff35df94SOliver Brewka size, maxFileSize); 55*ff35df94SOliver Brewka messages::internalError(res); 56*ff35df94SOliver Brewka return false; 57*ff35df94SOliver Brewka } 58*ff35df94SOliver Brewka off_t rc = lseek(fd, 0, SEEK_SET); 59*ff35df94SOliver Brewka if (rc < 0) 60*ff35df94SOliver Brewka { 61*ff35df94SOliver Brewka BMCWEB_LOG_ERROR("Failed to reset file offset to 0"); 62*ff35df94SOliver Brewka messages::internalError(res); 63*ff35df94SOliver Brewka return false; 64*ff35df94SOliver Brewka } 65*ff35df94SOliver Brewka return true; 66*ff35df94SOliver Brewka } 67*ff35df94SOliver Brewka 68*ff35df94SOliver Brewka inline void downloadEntryCallback( 69*ff35df94SOliver Brewka const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 70*ff35df94SOliver Brewka const std::string& entryID, const std::string& downloadEntryType, 71*ff35df94SOliver Brewka const boost::system::error_code& ec, 72*ff35df94SOliver Brewka const sdbusplus::message::unix_fd& unixfd) 73*ff35df94SOliver Brewka { 74*ff35df94SOliver Brewka if (ec.value() == EBADR) 75*ff35df94SOliver Brewka { 76*ff35df94SOliver Brewka messages::resourceNotFound(asyncResp->res, "EntryAttachment", entryID); 77*ff35df94SOliver Brewka return; 78*ff35df94SOliver Brewka } 79*ff35df94SOliver Brewka if (ec) 80*ff35df94SOliver Brewka { 81*ff35df94SOliver Brewka BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 82*ff35df94SOliver Brewka messages::internalError(asyncResp->res); 83*ff35df94SOliver Brewka return; 84*ff35df94SOliver Brewka } 85*ff35df94SOliver Brewka 86*ff35df94SOliver Brewka // Make sure we know how to process the retrieved entry attachment 87*ff35df94SOliver Brewka if ((downloadEntryType != "BMC") && (downloadEntryType != "System")) 88*ff35df94SOliver Brewka { 89*ff35df94SOliver Brewka BMCWEB_LOG_ERROR("downloadEntryCallback() invalid entry type: {}", 90*ff35df94SOliver Brewka downloadEntryType); 91*ff35df94SOliver Brewka messages::internalError(asyncResp->res); 92*ff35df94SOliver Brewka } 93*ff35df94SOliver Brewka 94*ff35df94SOliver Brewka int fd = -1; 95*ff35df94SOliver Brewka fd = dup(unixfd); 96*ff35df94SOliver Brewka if (fd < 0) 97*ff35df94SOliver Brewka { 98*ff35df94SOliver Brewka BMCWEB_LOG_ERROR("Failed to open file"); 99*ff35df94SOliver Brewka messages::internalError(asyncResp->res); 100*ff35df94SOliver Brewka return; 101*ff35df94SOliver Brewka } 102*ff35df94SOliver Brewka if (!checkSizeLimit(fd, asyncResp->res)) 103*ff35df94SOliver Brewka { 104*ff35df94SOliver Brewka close(fd); 105*ff35df94SOliver Brewka return; 106*ff35df94SOliver Brewka } 107*ff35df94SOliver Brewka if (downloadEntryType == "System") 108*ff35df94SOliver Brewka { 109*ff35df94SOliver Brewka if (!asyncResp->res.openFd(fd, bmcweb::EncodingType::Base64)) 110*ff35df94SOliver Brewka { 111*ff35df94SOliver Brewka messages::internalError(asyncResp->res); 112*ff35df94SOliver Brewka close(fd); 113*ff35df94SOliver Brewka return; 114*ff35df94SOliver Brewka } 115*ff35df94SOliver Brewka asyncResp->res.addHeader( 116*ff35df94SOliver Brewka boost::beast::http::field::content_transfer_encoding, "Base64"); 117*ff35df94SOliver Brewka return; 118*ff35df94SOliver Brewka } 119*ff35df94SOliver Brewka if (!asyncResp->res.openFd(fd)) 120*ff35df94SOliver Brewka { 121*ff35df94SOliver Brewka messages::internalError(asyncResp->res); 122*ff35df94SOliver Brewka close(fd); 123*ff35df94SOliver Brewka return; 124*ff35df94SOliver Brewka } 125*ff35df94SOliver Brewka asyncResp->res.addHeader(boost::beast::http::field::content_type, 126*ff35df94SOliver Brewka "application/octet-stream"); 127*ff35df94SOliver Brewka } 128*ff35df94SOliver Brewka } // namespace log_services_utils 129*ff35df94SOliver Brewka } // namespace redfish 130