// Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef SRC_NODE_CRYPTO_CLIENTHELLO_H_ #define SRC_NODE_CRYPTO_CLIENTHELLO_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "node.h" #include // size_t #include // nullptr namespace node { namespace crypto { class ClientHelloParser { public: ClientHelloParser() : state_(kEnded), onhello_cb_(nullptr), onend_cb_(nullptr), cb_arg_(nullptr), session_size_(0), session_id_(nullptr), servername_size_(0), servername_(nullptr), ocsp_request_(0), tls_ticket_size_(0), tls_ticket_(nullptr) { Reset(); } class ClientHello { public: inline uint8_t session_size() const { return session_size_; } inline const uint8_t* session_id() const { return session_id_; } inline bool has_ticket() const { return has_ticket_; } inline uint8_t servername_size() const { return servername_size_; } inline const uint8_t* servername() const { return servername_; } inline int ocsp_request() const { return ocsp_request_; } private: uint8_t session_size_; const uint8_t* session_id_; bool has_ticket_; uint8_t servername_size_; const uint8_t* servername_; int ocsp_request_; friend class ClientHelloParser; }; typedef void (*OnHelloCb)(void* arg, const ClientHello& hello); typedef void (*OnEndCb)(void* arg); void Parse(const uint8_t* data, size_t avail); inline void Reset(); inline void Start(OnHelloCb onhello_cb, OnEndCb onend_cb, void* onend_arg); inline void End(); inline bool IsPaused() const; inline bool IsEnded() const; private: static const size_t kMaxTLSFrameLen = 16 * 1024 + 5; static const size_t kMaxSSLExFrameLen = 32 * 1024; static const uint8_t kServernameHostname = 0; static const uint8_t kStatusRequestOCSP = 1; static const size_t kMinStatusRequestSize = 5; enum ParseState { kWaiting, kTLSHeader, kPaused, kEnded }; enum FrameType { kChangeCipherSpec = 20, kAlert = 21, kHandshake = 22, kApplicationData = 23, kOther = 255 }; enum HandshakeType { kClientHello = 1 }; enum ExtensionType { kServerName = 0, kStatusRequest = 5, kTLSSessionTicket = 35 }; bool ParseRecordHeader(const uint8_t* data, size_t avail); void ParseHeader(const uint8_t* data, size_t avail); void ParseExtension(const uint16_t type, const uint8_t* data, size_t len); bool ParseTLSClientHello(const uint8_t* data, size_t avail); ParseState state_; OnHelloCb onhello_cb_; OnEndCb onend_cb_; void* cb_arg_; size_t frame_len_; size_t body_offset_; size_t extension_offset_; uint8_t session_size_; const uint8_t* session_id_; uint16_t servername_size_; const uint8_t* servername_; uint8_t ocsp_request_; uint16_t tls_ticket_size_; const uint8_t* tls_ticket_; }; } // namespace crypto } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_CRYPTO_CLIENTHELLO_H_