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