| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1 | #pragma once | 
| Ed Tanous | 7531298 | 2021-02-11 14:26:02 -0800 | [diff] [blame] | 2 | #include "bmcweb_config.h" | 
| Adriana Kobylak | 0e1cf26 | 2019-12-05 13:57:57 -0600 | [diff] [blame] | 3 |  | 
| Nan Zhou | d055a34 | 2022-05-25 01:15:34 +0000 | [diff] [blame] | 4 | #include "authentication.hpp" | 
| Ed Tanous | 04e438c | 2020-10-03 08:06:26 -0700 | [diff] [blame] | 5 | #include "http_response.hpp" | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 6 | #include "http_utility.hpp" | 
| Ed Tanous | 04e438c | 2020-10-03 08:06:26 -0700 | [diff] [blame] | 7 | #include "logging.hpp" | 
| Ed Tanous | 04e438c | 2020-10-03 08:06:26 -0700 | [diff] [blame] | 8 | #include "utility.hpp" | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 9 |  | 
| Ed Tanous | e0d918b | 2018-03-27 17:41:04 -0700 | [diff] [blame] | 10 | #include <boost/algorithm/string.hpp> | 
| Ed Tanous | 257f579 | 2018-03-17 14:40:09 -0700 | [diff] [blame] | 11 | #include <boost/algorithm/string/predicate.hpp> | 
| Ed Tanous | 8f62635 | 2018-12-19 14:51:54 -0800 | [diff] [blame] | 12 | #include <boost/asio/io_context.hpp> | 
| Ed Tanous | 3112a14 | 2018-11-29 15:45:10 -0800 | [diff] [blame] | 13 | #include <boost/asio/ip/tcp.hpp> | 
| Ed Tanous | d43cd0c | 2020-09-30 20:46:53 -0700 | [diff] [blame] | 14 | #include <boost/asio/ssl/stream.hpp> | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 15 | #include <boost/asio/steady_timer.hpp> | 
| Ed Tanous | 3112a14 | 2018-11-29 15:45:10 -0800 | [diff] [blame] | 16 | #include <boost/beast/core/flat_static_buffer.hpp> | 
| Ed Tanous | 918ef25 | 2022-05-25 10:40:41 -0700 | [diff] [blame] | 17 | #include <boost/beast/http/parser.hpp> | 
 | 18 | #include <boost/beast/http/read.hpp> | 
 | 19 | #include <boost/beast/http/serializer.hpp> | 
 | 20 | #include <boost/beast/http/write.hpp> | 
| Manojkiran Eda | 4425044 | 2020-06-16 12:51:38 +0530 | [diff] [blame] | 21 | #include <boost/beast/ssl/ssl_stream.hpp> | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 22 | #include <boost/beast/websocket.hpp> | 
| Ed Tanous | d32c4fa | 2021-09-14 13:16:51 -0700 | [diff] [blame] | 23 | #include <boost/url/url_view.hpp> | 
| Ed Tanous | 57fce80 | 2019-05-21 13:00:34 -0700 | [diff] [blame] | 24 | #include <json_html_serializer.hpp> | 
| Ed Tanous | 52cc112 | 2020-07-18 13:51:21 -0700 | [diff] [blame] | 25 | #include <security_headers.hpp> | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 26 | #include <ssl_key_handler.hpp> | 
 | 27 |  | 
| Manojkiran Eda | 4425044 | 2020-06-16 12:51:38 +0530 | [diff] [blame] | 28 | #include <atomic> | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 29 | #include <chrono> | 
 | 30 | #include <vector> | 
 | 31 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 32 | namespace crow | 
 | 33 | { | 
| Ed Tanous | 257f579 | 2018-03-17 14:40:09 -0700 | [diff] [blame] | 34 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 35 | inline void prettyPrintJson(crow::Response& res) | 
 | 36 | { | 
| Ed Tanous | 57fce80 | 2019-05-21 13:00:34 -0700 | [diff] [blame] | 37 |     json_html_util::dumpHtml(res.body(), res.jsonValue); | 
 | 38 |  | 
| Ed Tanous | 93ef580 | 2019-01-03 10:15:41 -0800 | [diff] [blame] | 39 |     res.addHeader("Content-Type", "text/html;charset=UTF-8"); | 
| Ed Tanous | 257f579 | 2018-03-17 14:40:09 -0700 | [diff] [blame] | 40 | } | 
 | 41 |  | 
| Ed Tanous | 6fbdbca | 2021-12-06 14:36:06 -0800 | [diff] [blame] | 42 | static int connectionCount = 0; | 
| Jennifer Lee | acb7cfb | 2018-06-07 16:08:15 -0700 | [diff] [blame] | 43 |  | 
| Ed Tanous | 0260d9d | 2021-02-07 19:31:07 +0000 | [diff] [blame] | 44 | // request body limit size set by the bmcwebHttpReqBodyLimitMb option | 
| Ed Tanous | 6de264c | 2022-01-06 12:47:59 -0800 | [diff] [blame] | 45 | constexpr uint64_t httpReqBodyLimit = | 
 | 46 |     1024UL * 1024UL * bmcwebHttpReqBodyLimitMb; | 
| Jennifer Lee | acb7cfb | 2018-06-07 16:08:15 -0700 | [diff] [blame] | 47 |  | 
| James Feist | 3909dc8 | 2020-04-03 10:58:55 -0700 | [diff] [blame] | 48 | constexpr uint64_t loggedOutPostBodyLimit = 4096; | 
 | 49 |  | 
 | 50 | constexpr uint32_t httpHeaderLimit = 8192; | 
 | 51 |  | 
| Ed Tanous | 52cc112 | 2020-07-18 13:51:21 -0700 | [diff] [blame] | 52 | template <typename Adaptor, typename Handler> | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 53 | class Connection : | 
| Ed Tanous | 52cc112 | 2020-07-18 13:51:21 -0700 | [diff] [blame] | 54 |     public std::enable_shared_from_this<Connection<Adaptor, Handler>> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 55 | { | 
 | 56 |   public: | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 57 |     Connection(Handler* handlerIn, boost::asio::steady_timer&& timerIn, | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 58 |                std::function<std::string()>& getCachedDateStrF, | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 59 |                Adaptor adaptorIn) : | 
| Ed Tanous | ceac6f7 | 2018-12-02 11:58:47 -0800 | [diff] [blame] | 60 |         adaptor(std::move(adaptorIn)), | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 61 |         handler(handlerIn), timer(std::move(timerIn)), | 
 | 62 |         getCachedDateStr(getCachedDateStrF) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 63 |     { | 
 | 64 |         parser.emplace(std::piecewise_construct, std::make_tuple()); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 65 |         parser->body_limit(httpReqBodyLimit); | 
| James Feist | 3909dc8 | 2020-04-03 10:58:55 -0700 | [diff] [blame] | 66 |         parser->header_limit(httpHeaderLimit); | 
| Kowalski, Kamil | 55e43f6 | 2019-07-10 13:12:57 +0200 | [diff] [blame] | 67 |  | 
 | 68 | #ifdef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION | 
| Ed Tanous | 40aa058 | 2021-07-14 13:24:40 -0700 | [diff] [blame] | 69 |         prepareMutualTls(); | 
 | 70 | #endif // BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION | 
 | 71 |  | 
| Ed Tanous | 40aa058 | 2021-07-14 13:24:40 -0700 | [diff] [blame] | 72 |         connectionCount++; | 
| Ed Tanous | 6fbdbca | 2021-12-06 14:36:06 -0800 | [diff] [blame] | 73 |  | 
| Ed Tanous | 40aa058 | 2021-07-14 13:24:40 -0700 | [diff] [blame] | 74 |         BMCWEB_LOG_DEBUG << this << " Connection open, total " | 
 | 75 |                          << connectionCount; | 
| Ed Tanous | 40aa058 | 2021-07-14 13:24:40 -0700 | [diff] [blame] | 76 |     } | 
 | 77 |  | 
 | 78 |     ~Connection() | 
 | 79 |     { | 
| John Edward Broadbent | 4147b8a | 2021-07-19 16:52:24 -0700 | [diff] [blame] | 80 |         res.setCompleteRequestHandler(nullptr); | 
| Ed Tanous | 40aa058 | 2021-07-14 13:24:40 -0700 | [diff] [blame] | 81 |         cancelDeadlineTimer(); | 
| Ed Tanous | 6fbdbca | 2021-12-06 14:36:06 -0800 | [diff] [blame] | 82 |  | 
| Ed Tanous | 40aa058 | 2021-07-14 13:24:40 -0700 | [diff] [blame] | 83 |         connectionCount--; | 
 | 84 |         BMCWEB_LOG_DEBUG << this << " Connection closed, total " | 
 | 85 |                          << connectionCount; | 
| Ed Tanous | 40aa058 | 2021-07-14 13:24:40 -0700 | [diff] [blame] | 86 |     } | 
 | 87 |  | 
| Ed Tanous | ecd6a3a | 2022-01-07 09:18:40 -0800 | [diff] [blame] | 88 |     Connection(const Connection&) = delete; | 
 | 89 |     Connection(Connection&&) = delete; | 
 | 90 |     Connection& operator=(const Connection&) = delete; | 
 | 91 |     Connection& operator=(Connection&&) = delete; | 
 | 92 |  | 
| Ed Tanous | 40aa058 | 2021-07-14 13:24:40 -0700 | [diff] [blame] | 93 |     void prepareMutualTls() | 
 | 94 |     { | 
| Jonathan Doman | 83deb7d | 2020-11-16 17:00:22 -0800 | [diff] [blame] | 95 |         std::error_code error; | 
 | 96 |         std::filesystem::path caPath(ensuressl::trustStorePath); | 
 | 97 |         auto caAvailable = !std::filesystem::is_empty(caPath, error); | 
 | 98 |         caAvailable = caAvailable && !error; | 
| Ed Tanous | 2c70f80 | 2020-09-28 14:29:23 -0700 | [diff] [blame] | 99 |         if (caAvailable && persistent_data::SessionStore::getInstance() | 
 | 100 |                                .getAuthMethodsConfig() | 
 | 101 |                                .tls) | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 102 |         { | 
 | 103 |             adaptor.set_verify_mode(boost::asio::ssl::verify_peer); | 
| Ed Tanous | e7d1a1c | 2020-09-28 09:36:35 -0700 | [diff] [blame] | 104 |             std::string id = "bmcweb"; | 
| Ed Tanous | 46ff87b | 2022-01-07 09:25:51 -0800 | [diff] [blame] | 105 |  | 
| Ed Tanous | 9eb808c | 2022-01-25 10:19:23 -0800 | [diff] [blame] | 106 |             const char* cStr = id.c_str(); | 
| Ed Tanous | 46ff87b | 2022-01-07 09:25:51 -0800 | [diff] [blame] | 107 |             // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) | 
| Ed Tanous | 9eb808c | 2022-01-25 10:19:23 -0800 | [diff] [blame] | 108 |             const auto* idC = reinterpret_cast<const unsigned char*>(cStr); | 
| Ed Tanous | e7d1a1c | 2020-09-28 09:36:35 -0700 | [diff] [blame] | 109 |             int ret = SSL_set_session_id_context( | 
| Ed Tanous | 46ff87b | 2022-01-07 09:25:51 -0800 | [diff] [blame] | 110 |                 adaptor.native_handle(), idC, | 
| Ed Tanous | e7d1a1c | 2020-09-28 09:36:35 -0700 | [diff] [blame] | 111 |                 static_cast<unsigned int>(id.length())); | 
 | 112 |             if (ret == 0) | 
 | 113 |             { | 
 | 114 |                 BMCWEB_LOG_ERROR << this << " failed to set SSL id"; | 
 | 115 |             } | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 116 |         } | 
 | 117 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 118 |         adaptor.set_verify_callback( | 
 | 119 |             [this](bool preverified, boost::asio::ssl::verify_context& ctx) { | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 120 |             // do nothing if TLS is disabled | 
| Ed Tanous | 52cc112 | 2020-07-18 13:51:21 -0700 | [diff] [blame] | 121 |             if (!persistent_data::SessionStore::getInstance() | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 122 |                      .getAuthMethodsConfig() | 
 | 123 |                      .tls) | 
 | 124 |             { | 
 | 125 |                 BMCWEB_LOG_DEBUG << this << " TLS auth_config is disabled"; | 
| Kowalski, Kamil | 55e43f6 | 2019-07-10 13:12:57 +0200 | [diff] [blame] | 126 |                 return true; | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 127 |             } | 
 | 128 |  | 
 | 129 |             // We always return true to allow full auth flow | 
 | 130 |             if (!preverified) | 
 | 131 |             { | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 132 |                 BMCWEB_LOG_DEBUG << this << " TLS preverification failed."; | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 133 |                 return true; | 
 | 134 |             } | 
 | 135 |  | 
 | 136 |             X509_STORE_CTX* cts = ctx.native_handle(); | 
 | 137 |             if (cts == nullptr) | 
 | 138 |             { | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 139 |                 BMCWEB_LOG_DEBUG << this << " Cannot get native TLS handle."; | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 140 |                 return true; | 
 | 141 |             } | 
 | 142 |  | 
 | 143 |             // Get certificate | 
 | 144 |             X509* peerCert = | 
 | 145 |                 X509_STORE_CTX_get_current_cert(ctx.native_handle()); | 
 | 146 |             if (peerCert == nullptr) | 
 | 147 |             { | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 148 |                 BMCWEB_LOG_DEBUG << this | 
 | 149 |                                  << " Cannot get current TLS certificate."; | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 150 |                 return true; | 
 | 151 |             } | 
 | 152 |  | 
 | 153 |             // Check if certificate is OK | 
 | 154 |             int error = X509_STORE_CTX_get_error(cts); | 
 | 155 |             if (error != X509_V_OK) | 
 | 156 |             { | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 157 |                 BMCWEB_LOG_INFO << this << " Last TLS error is: " << error; | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 158 |                 return true; | 
 | 159 |             } | 
 | 160 |             // Check that we have reached final certificate in chain | 
 | 161 |             int32_t depth = X509_STORE_CTX_get_error_depth(cts); | 
 | 162 |             if (depth != 0) | 
 | 163 |  | 
 | 164 |             { | 
 | 165 |                 BMCWEB_LOG_DEBUG | 
 | 166 |                     << this << " Certificate verification in progress (depth " | 
 | 167 |                     << depth << "), waiting to reach final depth"; | 
 | 168 |                 return true; | 
 | 169 |             } | 
 | 170 |  | 
 | 171 |             BMCWEB_LOG_DEBUG << this | 
 | 172 |                              << " Certificate verification of final depth"; | 
 | 173 |  | 
 | 174 |             // Verify KeyUsage | 
 | 175 |             bool isKeyUsageDigitalSignature = false; | 
 | 176 |             bool isKeyUsageKeyAgreement = false; | 
 | 177 |  | 
 | 178 |             ASN1_BIT_STRING* usage = static_cast<ASN1_BIT_STRING*>( | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 179 |                 X509_get_ext_d2i(peerCert, NID_key_usage, nullptr, nullptr)); | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 180 |  | 
 | 181 |             if (usage == nullptr) | 
 | 182 |             { | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 183 |                 BMCWEB_LOG_DEBUG << this << " TLS usage is null"; | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 184 |                 return true; | 
 | 185 |             } | 
 | 186 |  | 
 | 187 |             for (int i = 0; i < usage->length; i++) | 
 | 188 |             { | 
| Ed Tanous | ca45aa3 | 2022-01-07 09:28:45 -0800 | [diff] [blame] | 189 |                 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) | 
 | 190 |                 unsigned char usageChar = usage->data[i]; | 
 | 191 |                 if (KU_DIGITAL_SIGNATURE & usageChar) | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 192 |                 { | 
 | 193 |                     isKeyUsageDigitalSignature = true; | 
 | 194 |                 } | 
| Ed Tanous | ca45aa3 | 2022-01-07 09:28:45 -0800 | [diff] [blame] | 195 |                 if (KU_KEY_AGREEMENT & usageChar) | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 196 |                 { | 
 | 197 |                     isKeyUsageKeyAgreement = true; | 
 | 198 |                 } | 
 | 199 |             } | 
| Vernon Mauery | b937830 | 2021-06-16 14:06:57 -0700 | [diff] [blame] | 200 |             ASN1_BIT_STRING_free(usage); | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 201 |  | 
 | 202 |             if (!isKeyUsageDigitalSignature || !isKeyUsageKeyAgreement) | 
 | 203 |             { | 
 | 204 |                 BMCWEB_LOG_DEBUG << this | 
 | 205 |                                  << " Certificate ExtendedKeyUsage does " | 
 | 206 |                                     "not allow provided certificate to " | 
 | 207 |                                     "be used for user authentication"; | 
 | 208 |                 return true; | 
 | 209 |             } | 
 | 210 |  | 
 | 211 |             // Determine that ExtendedKeyUsage includes Client Auth | 
 | 212 |  | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 213 |             stack_st_ASN1_OBJECT* extUsage = | 
 | 214 |                 static_cast<stack_st_ASN1_OBJECT*>(X509_get_ext_d2i( | 
 | 215 |                     peerCert, NID_ext_key_usage, nullptr, nullptr)); | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 216 |  | 
 | 217 |             if (extUsage == nullptr) | 
 | 218 |             { | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 219 |                 BMCWEB_LOG_DEBUG << this << " TLS extUsage is null"; | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 220 |                 return true; | 
 | 221 |             } | 
 | 222 |  | 
 | 223 |             bool isExKeyUsageClientAuth = false; | 
 | 224 |             for (int i = 0; i < sk_ASN1_OBJECT_num(extUsage); i++) | 
 | 225 |             { | 
| Ed Tanous | 4bac4a8 | 2022-01-07 09:37:55 -0800 | [diff] [blame] | 226 |                 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) | 
 | 227 |                 int nid = OBJ_obj2nid(sk_ASN1_OBJECT_value(extUsage, i)); | 
 | 228 |                 if (NID_client_auth == nid) | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 229 |                 { | 
 | 230 |                     isExKeyUsageClientAuth = true; | 
 | 231 |                     break; | 
 | 232 |                 } | 
 | 233 |             } | 
| Zbigniew Kurzynski | 09d02f8 | 2020-03-30 13:41:42 +0200 | [diff] [blame] | 234 |             sk_ASN1_OBJECT_free(extUsage); | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 235 |  | 
 | 236 |             // Certificate has to have proper key usages set | 
 | 237 |             if (!isExKeyUsageClientAuth) | 
 | 238 |             { | 
 | 239 |                 BMCWEB_LOG_DEBUG << this | 
 | 240 |                                  << " Certificate ExtendedKeyUsage does " | 
 | 241 |                                     "not allow provided certificate to " | 
 | 242 |                                     "be used for user authentication"; | 
 | 243 |                 return true; | 
 | 244 |             } | 
 | 245 |             std::string sslUser; | 
 | 246 |             // Extract username contained in CommonName | 
 | 247 |             sslUser.resize(256, '\0'); | 
 | 248 |  | 
 | 249 |             int status = X509_NAME_get_text_by_NID( | 
 | 250 |                 X509_get_subject_name(peerCert), NID_commonName, sslUser.data(), | 
 | 251 |                 static_cast<int>(sslUser.size())); | 
 | 252 |  | 
 | 253 |             if (status == -1) | 
 | 254 |             { | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 255 |                 BMCWEB_LOG_DEBUG | 
 | 256 |                     << this << " TLS cannot get username to create session"; | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 257 |                 return true; | 
 | 258 |             } | 
 | 259 |  | 
 | 260 |             size_t lastChar = sslUser.find('\0'); | 
 | 261 |             if (lastChar == std::string::npos || lastChar == 0) | 
 | 262 |             { | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 263 |                 BMCWEB_LOG_DEBUG << this << " Invalid TLS user name"; | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 264 |                 return true; | 
 | 265 |             } | 
 | 266 |             sslUser.resize(lastChar); | 
| Ed Tanous | e05aec5 | 2022-01-25 10:28:56 -0800 | [diff] [blame] | 267 |             std::string unsupportedClientId; | 
| Ed Tanous | 9a69d5a | 2021-09-13 10:23:51 -0700 | [diff] [blame] | 268 |             sessionIsFromTransport = true; | 
| John Edward Broadbent | 59b98b2 | 2021-07-13 15:36:32 -0700 | [diff] [blame] | 269 |             userSession = persistent_data::SessionStore::getInstance() | 
 | 270 |                               .generateUserSession( | 
| Jiaqing Zhao | 41d61c8 | 2021-12-07 13:21:47 +0800 | [diff] [blame] | 271 |                                   sslUser, req->ipAddress, unsupportedClientId, | 
| John Edward Broadbent | 59b98b2 | 2021-07-13 15:36:32 -0700 | [diff] [blame] | 272 |                                   persistent_data::PersistenceType::TIMEOUT); | 
 | 273 |             if (userSession != nullptr) | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 274 |             { | 
| John Edward Broadbent | 59b98b2 | 2021-07-13 15:36:32 -0700 | [diff] [blame] | 275 |                 BMCWEB_LOG_DEBUG | 
 | 276 |                     << this | 
 | 277 |                     << " Generating TLS session: " << userSession->uniqueId; | 
| Zbigniew Kurzynski | 009c2a4 | 2019-11-14 13:37:15 +0100 | [diff] [blame] | 278 |             } | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 279 |             return true; | 
 | 280 |         }); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 281 |     } | 
 | 282 |  | 
| Ed Tanous | ceac6f7 | 2018-12-02 11:58:47 -0800 | [diff] [blame] | 283 |     Adaptor& socket() | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 284 |     { | 
| Ed Tanous | ceac6f7 | 2018-12-02 11:58:47 -0800 | [diff] [blame] | 285 |         return adaptor; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 286 |     } | 
 | 287 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 288 |     void start() | 
 | 289 |     { | 
| Ed Tanous | 6fbdbca | 2021-12-06 14:36:06 -0800 | [diff] [blame] | 290 |         if (connectionCount >= 100) | 
 | 291 |         { | 
 | 292 |             BMCWEB_LOG_CRITICAL << this << "Max connection count exceeded."; | 
 | 293 |             return; | 
 | 294 |         } | 
 | 295 |  | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 296 |         startDeadline(); | 
| Sunitha Harish | c0ea7ae | 2020-10-30 02:37:30 -0500 | [diff] [blame] | 297 |  | 
| Ed Tanous | ceac6f7 | 2018-12-02 11:58:47 -0800 | [diff] [blame] | 298 |         // TODO(ed) Abstract this to a more clever class with the idea of an | 
 | 299 |         // asynchronous "start" | 
 | 300 |         if constexpr (std::is_same_v<Adaptor, | 
 | 301 |                                      boost::beast::ssl_stream< | 
 | 302 |                                          boost::asio::ip::tcp::socket>>) | 
 | 303 |         { | 
| Jan Sowinski | ee52ae1 | 2020-01-09 16:28:32 +0000 | [diff] [blame] | 304 |             adaptor.async_handshake(boost::asio::ssl::stream_base::server, | 
 | 305 |                                     [this, self(shared_from_this())]( | 
 | 306 |                                         const boost::system::error_code& ec) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 307 |                 if (ec) | 
 | 308 |                 { | 
 | 309 |                     return; | 
 | 310 |                 } | 
 | 311 |                 doReadHeaders(); | 
 | 312 |             }); | 
| Ed Tanous | ceac6f7 | 2018-12-02 11:58:47 -0800 | [diff] [blame] | 313 |         } | 
 | 314 |         else | 
 | 315 |         { | 
 | 316 |             doReadHeaders(); | 
 | 317 |         } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 318 |     } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 319 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 320 |     void handle() | 
 | 321 |     { | 
| Ed Tanous | f79b7a5 | 2021-09-22 19:04:29 -0700 | [diff] [blame] | 322 |         std::error_code reqEc; | 
 | 323 |         crow::Request& thisReq = req.emplace(parser->release(), reqEc); | 
 | 324 |         if (reqEc) | 
 | 325 |         { | 
 | 326 |             BMCWEB_LOG_DEBUG << "Request failed to construct" << reqEc; | 
 | 327 |             return; | 
 | 328 |         } | 
| Ed Tanous | 596b203 | 2021-09-13 10:32:22 -0700 | [diff] [blame] | 329 |         thisReq.session = userSession; | 
 | 330 |  | 
| Ivan Mikhaylov | f65b0be | 2021-04-19 10:05:30 +0000 | [diff] [blame] | 331 |         // Fetch the client IP address | 
 | 332 |         readClientIp(); | 
 | 333 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 334 |         // Check for HTTP version 1.1. | 
| Ed Tanous | 596b203 | 2021-09-13 10:32:22 -0700 | [diff] [blame] | 335 |         if (thisReq.version() == 11) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 336 |         { | 
| Ed Tanous | 596b203 | 2021-09-13 10:32:22 -0700 | [diff] [blame] | 337 |             if (thisReq.getHeaderValue(boost::beast::http::field::host).empty()) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 338 |             { | 
| Ed Tanous | de5c9f3 | 2019-03-26 09:17:55 -0700 | [diff] [blame] | 339 |                 res.result(boost::beast::http::status::bad_request); | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 340 |                 completeRequest(res); | 
| Ed Tanous | 6c7f01d | 2021-08-25 13:42:35 -0700 | [diff] [blame] | 341 |                 return; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 342 |             } | 
 | 343 |         } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 344 |  | 
| Ed Tanous | e278c18 | 2019-03-13 16:23:37 -0700 | [diff] [blame] | 345 |         BMCWEB_LOG_INFO << "Request: " | 
| Ed Tanous | 596b203 | 2021-09-13 10:32:22 -0700 | [diff] [blame] | 346 |                         << " " << this << " HTTP/" << thisReq.version() / 10 | 
 | 347 |                         << "." << thisReq.version() % 10 << ' ' | 
 | 348 |                         << thisReq.methodString() << " " << thisReq.target() | 
| Ed Tanous | 8cc8ede | 2022-02-28 10:20:59 -0800 | [diff] [blame] | 349 |                         << " " << thisReq.ipAddress.to_string(); | 
| Ed Tanous | d32c4fa | 2021-09-14 13:16:51 -0700 | [diff] [blame] | 350 |  | 
| Ed Tanous | 6c7f01d | 2021-08-25 13:42:35 -0700 | [diff] [blame] | 351 |         res.isAliveHelper = [this]() -> bool { return isAlive(); }; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 352 |  | 
| Ed Tanous | 596b203 | 2021-09-13 10:32:22 -0700 | [diff] [blame] | 353 |         thisReq.ioService = static_cast<decltype(thisReq.ioService)>( | 
| Ed Tanous | 6c7f01d | 2021-08-25 13:42:35 -0700 | [diff] [blame] | 354 |             &adaptor.get_executor().context()); | 
| Kowalski, Kamil | 55e43f6 | 2019-07-10 13:12:57 +0200 | [diff] [blame] | 355 |  | 
| Ed Tanous | 6c7f01d | 2021-08-25 13:42:35 -0700 | [diff] [blame] | 356 |         if (res.completed) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 357 |         { | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 358 |             completeRequest(res); | 
| Ed Tanous | 6c7f01d | 2021-08-25 13:42:35 -0700 | [diff] [blame] | 359 |             return; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 360 |         } | 
| Nan Zhou | a43ea82 | 2022-05-27 00:42:44 +0000 | [diff] [blame] | 361 | #ifndef BMCWEB_INSECURE_DISABLE_AUTHX | 
| Nan Zhou | d055a34 | 2022-05-25 01:15:34 +0000 | [diff] [blame] | 362 |         if (!crow::authentication::isOnAllowlist(req->url, req->method()) && | 
| Ed Tanous | 1d3c14a | 2021-09-22 18:54:40 -0700 | [diff] [blame] | 363 |             thisReq.session == nullptr) | 
 | 364 |         { | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 365 |             BMCWEB_LOG_WARNING << "Authentication failed"; | 
| Ed Tanous | 1d3c14a | 2021-09-22 18:54:40 -0700 | [diff] [blame] | 366 |             forward_unauthorized::sendUnauthorized( | 
| Ed Tanous | c127a0f | 2022-05-11 15:23:59 -0700 | [diff] [blame^] | 367 |                 req->url, req->getHeaderValue("X-Requested-With"), | 
| Ed Tanous | 1d3c14a | 2021-09-22 18:54:40 -0700 | [diff] [blame] | 368 |                 req->getHeaderValue("Accept"), res); | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 369 |             completeRequest(res); | 
| Ed Tanous | 1d3c14a | 2021-09-22 18:54:40 -0700 | [diff] [blame] | 370 |             return; | 
 | 371 |         } | 
| Nan Zhou | a43ea82 | 2022-05-27 00:42:44 +0000 | [diff] [blame] | 372 | #endif // BMCWEB_INSECURE_DISABLE_AUTHX | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 373 |         auto asyncResp = std::make_shared<bmcweb::AsyncResp>(); | 
 | 374 |         BMCWEB_LOG_DEBUG << "Setting completion handler"; | 
 | 375 |         asyncResp->res.setCompleteRequestHandler( | 
 | 376 |             [self(shared_from_this())](crow::Response& thisRes) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 377 |             self->completeRequest(thisRes); | 
 | 378 |         }); | 
| Ed Tanous | 6c7f01d | 2021-08-25 13:42:35 -0700 | [diff] [blame] | 379 |  | 
| Ed Tanous | 596b203 | 2021-09-13 10:32:22 -0700 | [diff] [blame] | 380 |         if (thisReq.isUpgrade() && | 
| Ed Tanous | 6c7f01d | 2021-08-25 13:42:35 -0700 | [diff] [blame] | 381 |             boost::iequals( | 
| Ed Tanous | 596b203 | 2021-09-13 10:32:22 -0700 | [diff] [blame] | 382 |                 thisReq.getHeaderValue(boost::beast::http::field::upgrade), | 
| Ed Tanous | 6c7f01d | 2021-08-25 13:42:35 -0700 | [diff] [blame] | 383 |                 "websocket")) | 
 | 384 |         { | 
| Ed Tanous | 596b203 | 2021-09-13 10:32:22 -0700 | [diff] [blame] | 385 |             handler->handleUpgrade(thisReq, res, std::move(adaptor)); | 
| Ed Tanous | 6c7f01d | 2021-08-25 13:42:35 -0700 | [diff] [blame] | 386 |             // delete lambda with self shared_ptr | 
 | 387 |             // to enable connection destruction | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 388 |             asyncResp->res.setCompleteRequestHandler(nullptr); | 
| Ed Tanous | 6c7f01d | 2021-08-25 13:42:35 -0700 | [diff] [blame] | 389 |             return; | 
 | 390 |         } | 
| Ed Tanous | 596b203 | 2021-09-13 10:32:22 -0700 | [diff] [blame] | 391 |         handler->handle(thisReq, asyncResp); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 392 |     } | 
| Ed Tanous | e0d918b | 2018-03-27 17:41:04 -0700 | [diff] [blame] | 393 |  | 
| Ed Tanous | e278c18 | 2019-03-13 16:23:37 -0700 | [diff] [blame] | 394 |     bool isAlive() | 
 | 395 |     { | 
| Ed Tanous | e278c18 | 2019-03-13 16:23:37 -0700 | [diff] [blame] | 396 |         if constexpr (std::is_same_v<Adaptor, | 
 | 397 |                                      boost::beast::ssl_stream< | 
 | 398 |                                          boost::asio::ip::tcp::socket>>) | 
 | 399 |         { | 
 | 400 |             return adaptor.next_layer().is_open(); | 
 | 401 |         } | 
 | 402 |         else | 
 | 403 |         { | 
 | 404 |             return adaptor.is_open(); | 
 | 405 |         } | 
 | 406 |     } | 
 | 407 |     void close() | 
 | 408 |     { | 
| Ed Tanous | e278c18 | 2019-03-13 16:23:37 -0700 | [diff] [blame] | 409 |         if constexpr (std::is_same_v<Adaptor, | 
 | 410 |                                      boost::beast::ssl_stream< | 
 | 411 |                                          boost::asio::ip::tcp::socket>>) | 
 | 412 |         { | 
 | 413 |             adaptor.next_layer().close(); | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 414 |             if (sessionIsFromTransport && userSession != nullptr) | 
| Kowalski, Kamil | 55e43f6 | 2019-07-10 13:12:57 +0200 | [diff] [blame] | 415 |             { | 
| John Edward Broadbent | 59b98b2 | 2021-07-13 15:36:32 -0700 | [diff] [blame] | 416 |                 BMCWEB_LOG_DEBUG | 
 | 417 |                     << this | 
 | 418 |                     << " Removing TLS session: " << userSession->uniqueId; | 
 | 419 |                 persistent_data::SessionStore::getInstance().removeSession( | 
 | 420 |                     userSession); | 
| Kowalski, Kamil | 55e43f6 | 2019-07-10 13:12:57 +0200 | [diff] [blame] | 421 |             } | 
| Ed Tanous | e278c18 | 2019-03-13 16:23:37 -0700 | [diff] [blame] | 422 |         } | 
 | 423 |         else | 
 | 424 |         { | 
 | 425 |             adaptor.close(); | 
 | 426 |         } | 
 | 427 |     } | 
 | 428 |  | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 429 |     void completeRequest(crow::Response& thisRes) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 430 |     { | 
| Ed Tanous | f79b7a5 | 2021-09-22 19:04:29 -0700 | [diff] [blame] | 431 |         if (!req) | 
 | 432 |         { | 
 | 433 |             return; | 
 | 434 |         } | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 435 |         res = std::move(thisRes); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 436 |         BMCWEB_LOG_INFO << "Response: " << this << ' ' << req->url << ' ' | 
 | 437 |                         << res.resultInt() << " keepalive=" << req->keepAlive(); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 438 |  | 
| Ed Tanous | 0260d9d | 2021-02-07 19:31:07 +0000 | [diff] [blame] | 439 |         addSecurityHeaders(*req, res); | 
| Ed Tanous | 52cc112 | 2020-07-18 13:51:21 -0700 | [diff] [blame] | 440 |  | 
| Nan Zhou | d055a34 | 2022-05-25 01:15:34 +0000 | [diff] [blame] | 441 |         crow::authentication::cleanupTempSession(*req); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 442 |  | 
| Ed Tanous | e278c18 | 2019-03-13 16:23:37 -0700 | [diff] [blame] | 443 |         if (!isAlive()) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 444 |         { | 
 | 445 |             // BMCWEB_LOG_DEBUG << this << " delete (socket is closed) " << | 
 | 446 |             // isReading | 
 | 447 |             // << ' ' << isWriting; | 
 | 448 |             // delete this; | 
| Jan Sowinski | ee52ae1 | 2020-01-09 16:28:32 +0000 | [diff] [blame] | 449 |  | 
 | 450 |             // delete lambda with self shared_ptr | 
 | 451 |             // to enable connection destruction | 
| John Edward Broadbent | 4147b8a | 2021-07-19 16:52:24 -0700 | [diff] [blame] | 452 |             res.setCompleteRequestHandler(nullptr); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 453 |             return; | 
 | 454 |         } | 
 | 455 |         if (res.body().empty() && !res.jsonValue.empty()) | 
 | 456 |         { | 
| John Edward Broadbent | 59b98b2 | 2021-07-13 15:36:32 -0700 | [diff] [blame] | 457 |             if (http_helpers::requestPrefersHtml(req->getHeaderValue("Accept"))) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 458 |             { | 
 | 459 |                 prettyPrintJson(res); | 
 | 460 |             } | 
 | 461 |             else | 
 | 462 |             { | 
 | 463 |                 res.jsonMode(); | 
| Ed Tanous | 71f52d9 | 2021-02-19 08:51:17 -0800 | [diff] [blame] | 464 |                 res.body() = res.jsonValue.dump( | 
 | 465 |                     2, ' ', true, nlohmann::json::error_handler_t::replace); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 466 |             } | 
 | 467 |         } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 468 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 469 |         if (res.resultInt() >= 400 && res.body().empty()) | 
 | 470 |         { | 
 | 471 |             res.body() = std::string(res.reason()); | 
 | 472 |         } | 
| Ed Tanous | 6295bec | 2019-09-03 10:11:01 -0700 | [diff] [blame] | 473 |  | 
 | 474 |         if (res.result() == boost::beast::http::status::no_content) | 
 | 475 |         { | 
 | 476 |             // Boost beast throws if content is provided on a no-content | 
 | 477 |             // response.  Ideally, this would never happen, but in the case that | 
 | 478 |             // it does, we don't want to throw. | 
 | 479 |             BMCWEB_LOG_CRITICAL | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 480 |                 << this << " Response content provided but code was no-content"; | 
| Ed Tanous | 6295bec | 2019-09-03 10:11:01 -0700 | [diff] [blame] | 481 |             res.body().clear(); | 
 | 482 |         } | 
 | 483 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 484 |         res.addHeader(boost::beast::http::field::date, getCachedDateStr()); | 
 | 485 |  | 
 | 486 |         res.keepAlive(req->keepAlive()); | 
 | 487 |  | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 488 |         doWrite(res); | 
| Jan Sowinski | ee52ae1 | 2020-01-09 16:28:32 +0000 | [diff] [blame] | 489 |  | 
 | 490 |         // delete lambda with self shared_ptr | 
 | 491 |         // to enable connection destruction | 
| John Edward Broadbent | 4147b8a | 2021-07-19 16:52:24 -0700 | [diff] [blame] | 492 |         res.setCompleteRequestHandler(nullptr); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 493 |     } | 
 | 494 |  | 
| Sunitha Harish | c0ea7ae | 2020-10-30 02:37:30 -0500 | [diff] [blame] | 495 |     void readClientIp() | 
 | 496 |     { | 
| John Edward Broadbent | 59b98b2 | 2021-07-13 15:36:32 -0700 | [diff] [blame] | 497 |         boost::asio::ip::address ip; | 
 | 498 |         boost::system::error_code ec = getClientIp(ip); | 
 | 499 |         if (ec) | 
 | 500 |         { | 
 | 501 |             return; | 
 | 502 |         } | 
 | 503 |         req->ipAddress = ip; | 
 | 504 |     } | 
 | 505 |  | 
 | 506 |     boost::system::error_code getClientIp(boost::asio::ip::address& ip) | 
 | 507 |     { | 
| Sunitha Harish | c0ea7ae | 2020-10-30 02:37:30 -0500 | [diff] [blame] | 508 |         boost::system::error_code ec; | 
 | 509 |         BMCWEB_LOG_DEBUG << "Fetch the client IP address"; | 
 | 510 |         boost::asio::ip::tcp::endpoint endpoint = | 
 | 511 |             boost::beast::get_lowest_layer(adaptor).remote_endpoint(ec); | 
 | 512 |  | 
 | 513 |         if (ec) | 
 | 514 |         { | 
 | 515 |             // If remote endpoint fails keep going. "ClientOriginIPAddress" | 
 | 516 |             // will be empty. | 
 | 517 |             BMCWEB_LOG_ERROR << "Failed to get the client's IP Address. ec : " | 
 | 518 |                              << ec; | 
| John Edward Broadbent | 59b98b2 | 2021-07-13 15:36:32 -0700 | [diff] [blame] | 519 |             return ec; | 
| Sunitha Harish | c0ea7ae | 2020-10-30 02:37:30 -0500 | [diff] [blame] | 520 |         } | 
| John Edward Broadbent | 59b98b2 | 2021-07-13 15:36:32 -0700 | [diff] [blame] | 521 |         ip = endpoint.address(); | 
 | 522 |         return ec; | 
| Sunitha Harish | c0ea7ae | 2020-10-30 02:37:30 -0500 | [diff] [blame] | 523 |     } | 
 | 524 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 525 |   private: | 
 | 526 |     void doReadHeaders() | 
 | 527 |     { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 528 |         BMCWEB_LOG_DEBUG << this << " doReadHeaders"; | 
 | 529 |  | 
 | 530 |         // Clean up any previous Connection. | 
 | 531 |         boost::beast::http::async_read_header( | 
| Ed Tanous | ceac6f7 | 2018-12-02 11:58:47 -0800 | [diff] [blame] | 532 |             adaptor, buffer, *parser, | 
| Jan Sowinski | ee52ae1 | 2020-01-09 16:28:32 +0000 | [diff] [blame] | 533 |             [this, | 
 | 534 |              self(shared_from_this())](const boost::system::error_code& ec, | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 535 |                                        std::size_t bytesTransferred) { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 536 |             BMCWEB_LOG_DEBUG << this << " async_read_header " | 
 | 537 |                              << bytesTransferred << " Bytes"; | 
 | 538 |             bool errorWhileReading = false; | 
 | 539 |             if (ec) | 
 | 540 |             { | 
 | 541 |                 errorWhileReading = true; | 
 | 542 |                 if (ec == boost::asio::error::eof) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 543 |                 { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 544 |                     BMCWEB_LOG_WARNING | 
 | 545 |                         << this << " Error while reading: " << ec.message(); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 546 |                 } | 
 | 547 |                 else | 
 | 548 |                 { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 549 |                     BMCWEB_LOG_ERROR | 
 | 550 |                         << this << " Error while reading: " << ec.message(); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 551 |                 } | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 552 |             } | 
 | 553 |             else | 
 | 554 |             { | 
 | 555 |                 // if the adaptor isn't open anymore, and wasn't handed to a | 
 | 556 |                 // websocket, treat as an error | 
 | 557 |                 if (!isAlive() && | 
 | 558 |                     !boost::beast::websocket::is_upgrade(parser->get())) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 559 |                 { | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 560 |                     errorWhileReading = true; | 
 | 561 |                 } | 
 | 562 |             } | 
 | 563 |  | 
 | 564 |             cancelDeadlineTimer(); | 
 | 565 |  | 
 | 566 |             if (errorWhileReading) | 
 | 567 |             { | 
 | 568 |                 close(); | 
 | 569 |                 BMCWEB_LOG_DEBUG << this << " from read(1)"; | 
 | 570 |                 return; | 
 | 571 |             } | 
 | 572 |  | 
 | 573 |             readClientIp(); | 
 | 574 |  | 
 | 575 |             boost::asio::ip::address ip; | 
 | 576 |             if (getClientIp(ip)) | 
 | 577 |             { | 
 | 578 |                 BMCWEB_LOG_DEBUG << "Unable to get client IP"; | 
 | 579 |             } | 
 | 580 |             sessionIsFromTransport = false; | 
 | 581 | #ifndef BMCWEB_INSECURE_DISABLE_AUTHX | 
 | 582 |             boost::beast::http::verb method = parser->get().method(); | 
 | 583 |             userSession = crow::authentication::authenticate( | 
 | 584 |                 ip, res, method, parser->get().base(), userSession); | 
 | 585 |  | 
 | 586 |             bool loggedIn = userSession != nullptr; | 
 | 587 |             if (!loggedIn) | 
 | 588 |             { | 
 | 589 |                 const boost::optional<uint64_t> contentLength = | 
 | 590 |                     parser->content_length(); | 
 | 591 |                 if (contentLength && *contentLength > loggedOutPostBodyLimit) | 
 | 592 |                 { | 
 | 593 |                     BMCWEB_LOG_DEBUG << "Content length greater than limit " | 
 | 594 |                                      << *contentLength; | 
| Ed Tanous | e278c18 | 2019-03-13 16:23:37 -0700 | [diff] [blame] | 595 |                     close(); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 596 |                     return; | 
 | 597 |                 } | 
 | 598 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 599 |                 BMCWEB_LOG_DEBUG << "Starting quick deadline"; | 
 | 600 |             } | 
| Nan Zhou | a43ea82 | 2022-05-27 00:42:44 +0000 | [diff] [blame] | 601 | #endif // BMCWEB_INSECURE_DISABLE_AUTHX | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 602 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 603 |             doRead(); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 604 |             }); | 
 | 605 |     } | 
 | 606 |  | 
 | 607 |     void doRead() | 
 | 608 |     { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 609 |         BMCWEB_LOG_DEBUG << this << " doRead"; | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 610 |         startDeadline(); | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 611 |         boost::beast::http::async_read(adaptor, buffer, *parser, | 
 | 612 |                                        [this, self(shared_from_this())]( | 
 | 613 |                                            const boost::system::error_code& ec, | 
 | 614 |                                            std::size_t bytesTransferred) { | 
 | 615 |             BMCWEB_LOG_DEBUG << this << " async_read " << bytesTransferred | 
 | 616 |                              << " Bytes"; | 
 | 617 |             cancelDeadlineTimer(); | 
 | 618 |             if (ec) | 
 | 619 |             { | 
 | 620 |                 BMCWEB_LOG_ERROR << this | 
 | 621 |                                  << " Error while reading: " << ec.message(); | 
 | 622 |                 close(); | 
 | 623 |                 BMCWEB_LOG_DEBUG << this << " from read(1)"; | 
 | 624 |                 return; | 
 | 625 |             } | 
 | 626 |             handle(); | 
 | 627 |         }); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 628 |     } | 
 | 629 |  | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 630 |     void doWrite(crow::Response& thisRes) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 631 |     { | 
| Zbigniew Kurzynski | 2658d98 | 2019-11-19 18:01:08 +0100 | [diff] [blame] | 632 |         BMCWEB_LOG_DEBUG << this << " doWrite"; | 
| Nan Zhou | 72374eb | 2022-01-27 17:06:51 -0800 | [diff] [blame] | 633 |         thisRes.preparePayload(); | 
 | 634 |         serializer.emplace(*thisRes.stringResponse); | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 635 |         startDeadline(); | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 636 |         boost::beast::http::async_write(adaptor, *serializer, | 
 | 637 |                                         [this, self(shared_from_this())]( | 
 | 638 |                                             const boost::system::error_code& ec, | 
 | 639 |                                             std::size_t bytesTransferred) { | 
 | 640 |             BMCWEB_LOG_DEBUG << this << " async_write " << bytesTransferred | 
 | 641 |                              << " bytes"; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 642 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 643 |             cancelDeadlineTimer(); | 
| James Feist | 54d8bb1 | 2020-07-20 13:28:59 -0700 | [diff] [blame] | 644 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 645 |             if (ec) | 
 | 646 |             { | 
 | 647 |                 BMCWEB_LOG_DEBUG << this << " from write(2)"; | 
 | 648 |                 return; | 
 | 649 |             } | 
 | 650 |             if (!res.keepAlive()) | 
 | 651 |             { | 
 | 652 |                 close(); | 
 | 653 |                 BMCWEB_LOG_DEBUG << this << " from write(1)"; | 
 | 654 |                 return; | 
 | 655 |             } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 656 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 657 |             serializer.reset(); | 
 | 658 |             BMCWEB_LOG_DEBUG << this << " Clearing response"; | 
 | 659 |             res.clear(); | 
 | 660 |             parser.emplace(std::piecewise_construct, std::make_tuple()); | 
 | 661 |             parser->body_limit(httpReqBodyLimit); // reset body limit for | 
 | 662 |                                                   // newly created parser | 
 | 663 |             buffer.consume(buffer.size()); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 664 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 665 |             // If the session was built from the transport, we don't need to | 
 | 666 |             // clear it.  All other sessions are generated per request. | 
 | 667 |             if (!sessionIsFromTransport) | 
 | 668 |             { | 
 | 669 |                 userSession = nullptr; | 
 | 670 |             } | 
| Ed Tanous | 9a69d5a | 2021-09-13 10:23:51 -0700 | [diff] [blame] | 671 |  | 
| Ed Tanous | 002d39b | 2022-05-31 08:59:27 -0700 | [diff] [blame] | 672 |             // Destroy the Request via the std::optional | 
 | 673 |             req.reset(); | 
 | 674 |             doReadHeaders(); | 
 | 675 |         }); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 676 |     } | 
 | 677 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 678 |     void cancelDeadlineTimer() | 
 | 679 |     { | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 680 |         timer.cancel(); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 681 |     } | 
 | 682 |  | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 683 |     void startDeadline() | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 684 |     { | 
 | 685 |         cancelDeadlineTimer(); | 
 | 686 |  | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 687 |         std::chrono::seconds timeout(15); | 
 | 688 |         // allow slow uploads for logged in users | 
| Lei YU | 638e239 | 2021-12-28 18:14:13 +0800 | [diff] [blame] | 689 |         bool loggedIn = userSession != nullptr; | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 690 |         if (loggedIn) | 
| James Feist | 3909dc8 | 2020-04-03 10:58:55 -0700 | [diff] [blame] | 691 |         { | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 692 |             timeout = std::chrono::seconds(60); | 
| James Feist | cb6cb49 | 2020-04-03 13:36:17 -0700 | [diff] [blame] | 693 |             return; | 
 | 694 |         } | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 695 |  | 
 | 696 |         std::weak_ptr<Connection<Adaptor, Handler>> weakSelf = weak_from_this(); | 
 | 697 |         timer.expires_after(timeout); | 
 | 698 |         timer.async_wait([weakSelf](const boost::system::error_code ec) { | 
 | 699 |             // Note, we are ignoring other types of errors here;  If the timer | 
 | 700 |             // failed for any reason, we should still close the connection | 
 | 701 |  | 
 | 702 |             std::shared_ptr<Connection<Adaptor, Handler>> self = | 
 | 703 |                 weakSelf.lock(); | 
 | 704 |             if (!self) | 
 | 705 |             { | 
 | 706 |                 BMCWEB_LOG_CRITICAL << self << " Failed to capture connection"; | 
 | 707 |                 return; | 
 | 708 |             } | 
 | 709 |             if (ec == boost::asio::error::operation_aborted) | 
 | 710 |             { | 
 | 711 |                 // Canceled wait means the path succeeeded. | 
 | 712 |                 return; | 
 | 713 |             } | 
 | 714 |             if (ec) | 
 | 715 |             { | 
 | 716 |                 BMCWEB_LOG_CRITICAL << self << " timer failed " << ec; | 
 | 717 |             } | 
 | 718 |  | 
 | 719 |             BMCWEB_LOG_WARNING << self << "Connection timed out, closing"; | 
 | 720 |  | 
 | 721 |             self->close(); | 
 | 722 |         }); | 
 | 723 |  | 
 | 724 |         BMCWEB_LOG_DEBUG << this << " timer started"; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 725 |     } | 
 | 726 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 727 |     Adaptor adaptor; | 
 | 728 |     Handler* handler; | 
| Ed Tanous | a24526d | 2018-12-10 15:17:59 -0800 | [diff] [blame] | 729 |     // Making this a std::optional allows it to be efficiently destroyed and | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 730 |     // re-created on Connection reset | 
| Ed Tanous | a24526d | 2018-12-10 15:17:59 -0800 | [diff] [blame] | 731 |     std::optional< | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 732 |         boost::beast::http::request_parser<boost::beast::http::string_body>> | 
 | 733 |         parser; | 
 | 734 |  | 
| Ed Tanous | 3112a14 | 2018-11-29 15:45:10 -0800 | [diff] [blame] | 735 |     boost::beast::flat_static_buffer<8192> buffer; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 736 |  | 
| Ed Tanous | a24526d | 2018-12-10 15:17:59 -0800 | [diff] [blame] | 737 |     std::optional<boost::beast::http::response_serializer< | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 738 |         boost::beast::http::string_body>> | 
 | 739 |         serializer; | 
 | 740 |  | 
| Ed Tanous | a24526d | 2018-12-10 15:17:59 -0800 | [diff] [blame] | 741 |     std::optional<crow::Request> req; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 742 |     crow::Response res; | 
| Ed Tanous | 52cc112 | 2020-07-18 13:51:21 -0700 | [diff] [blame] | 743 |  | 
| Ed Tanous | 9a69d5a | 2021-09-13 10:23:51 -0700 | [diff] [blame] | 744 |     bool sessionIsFromTransport = false; | 
| John Edward Broadbent | 59b98b2 | 2021-07-13 15:36:32 -0700 | [diff] [blame] | 745 |     std::shared_ptr<persistent_data::UserSession> userSession; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 746 |  | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 747 |     boost::asio::steady_timer timer; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 748 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 749 |     std::function<std::string()>& getCachedDateStr; | 
| Jan Sowinski | ee52ae1 | 2020-01-09 16:28:32 +0000 | [diff] [blame] | 750 |  | 
 | 751 |     using std::enable_shared_from_this< | 
| Ed Tanous | 52cc112 | 2020-07-18 13:51:21 -0700 | [diff] [blame] | 752 |         Connection<Adaptor, Handler>>::shared_from_this; | 
| Ed Tanous | 5dfb5b2 | 2021-12-03 11:24:53 -0800 | [diff] [blame] | 753 |  | 
 | 754 |     using std::enable_shared_from_this< | 
 | 755 |         Connection<Adaptor, Handler>>::weak_from_this; | 
| Ed Tanous | 3112a14 | 2018-11-29 15:45:10 -0800 | [diff] [blame] | 756 | }; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 757 | } // namespace crow |