if (cursor.totalLength() > 0) {
uint16_t extensionsLength = cursor.readBE<uint16_t>();
while (extensionsLength) {
+ TLSExtension extensionType = static_cast<TLSExtension>(
+ cursor.readBE<uint16_t>());
sock->clientHelloInfo_->
- clientHelloExtensions_.push_back(cursor.readBE<uint16_t>());
+ clientHelloExtensions_.push_back(extensionType);
extensionsLength -= 2;
uint16_t extensionDataLength = cursor.readBE<uint16_t>();
extensionsLength -= 2;
- cursor.skip(extensionDataLength);
- extensionsLength -= extensionDataLength;
+
+ if (extensionType == TLSExtension::SIGNATURE_ALGORITHMS) {
+ cursor.skip(2);
+ extensionDataLength -= 2;
+ while (extensionDataLength) {
+ HashAlgorithm hashAlg = static_cast<HashAlgorithm>(
+ cursor.readBE<uint8_t>());
+ SignatureAlgorithm sigAlg = static_cast<SignatureAlgorithm>(
+ cursor.readBE<uint8_t>());
+ extensionDataLength -= 2;
+ sock->clientHelloInfo_->
+ clientHelloSigAlgs_.emplace_back(hashAlg, sigAlg);
+ }
+ } else {
+ cursor.skip(extensionDataLength);
+ extensionsLength -= extensionDataLength;
+ }
}
}
} catch (std::out_of_range& e) {
return folly::join(":", clientHelloInfo_->clientHelloExtensions_);
}
+ std::string getSSLClientSigAlgs() {
+ if (!parseClientHello_) {
+ return "";
+ }
+
+ std::string sigAlgs;
+ sigAlgs.reserve(clientHelloInfo_->clientHelloSigAlgs_.size() * 4);
+ for (size_t i = 0; i < clientHelloInfo_->clientHelloSigAlgs_.size(); i++) {
+ if (i) {
+ sigAlgs.push_back(':');
+ }
+ sigAlgs.append(folly::to<std::string>(
+ clientHelloInfo_->clientHelloSigAlgs_[i].first));
+ sigAlgs.push_back(',');
+ sigAlgs.append(folly::to<std::string>(
+ clientHelloInfo_->clientHelloSigAlgs_[i].second));
+ }
+
+ return sigAlgs;
+ }
+
/**
* Get the list of shared ciphers between the server and the client.
* Works well for only SSLv2, not so good for SSLv3 or TLSv1.
static void clientHelloParsingCallback(int write_p, int version,
int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
+ // http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
+ enum class TLSExtension: uint16_t {
+ SERVER_NAME = 0,
+ MAX_FRAGMENT_LENGTH = 1,
+ CLIENT_CERTIFICATE_URL = 2,
+ TRUSTED_CA_KEYS = 3,
+ TRUNCATED_HMAC = 4,
+ STATUS_REQUEST = 5,
+ USER_MAPPING = 6,
+ CLIENT_AUTHZ = 7,
+ SERVER_AUTHZ = 8,
+ CERT_TYPE = 9,
+ SUPPORTED_GROUPS = 10,
+ EC_POINT_FORMATS = 11,
+ SRP = 12,
+ SIGNATURE_ALGORITHMS = 13,
+ USE_SRTP = 14,
+ HEARTBEAT = 15,
+ APPLICATION_LAYER_PROTOCOL_NEGOTIATION = 16,
+ STATUS_REQUEST_V2 = 17,
+ SIGNED_CERTIFICATE_TIMESTAMP = 18,
+ CLIENT_CERTIFICATE_TYPE = 19,
+ SERVER_CERTIFICATE_TYPE = 20,
+ PADDING = 21,
+ ENCRYPT_THEN_MAC = 22,
+ EXTENDED_MASTER_SECRET = 23,
+ SESSION_TICKET = 35,
+ RENEGOTIATION_INFO = 65281
+ };
+
+ // http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-18
+ enum class HashAlgorithm: uint8_t {
+ NONE = 0,
+ MD5 = 1,
+ SHA1 = 2,
+ SHA224 = 3,
+ SHA256 = 4,
+ SHA384 = 5,
+ SHA512 = 6
+ };
+
+ // http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16
+ enum class SignatureAlgorithm: uint8_t {
+ ANONYMOUS = 0,
+ RSA = 1,
+ DSA = 2,
+ ECDSA = 3
+ };
+
struct ClientHelloInfo {
folly::IOBufQueue clientHelloBuf_;
uint8_t clientHelloMajorVersion_;
uint8_t clientHelloMinorVersion_;
std::vector<uint16_t> clientHelloCipherSuites_;
std::vector<uint8_t> clientHelloCompressionMethods_;
- std::vector<uint16_t> clientHelloExtensions_;
+ std::vector<TLSExtension> clientHelloExtensions_;
+ std::vector<
+ std::pair<HashAlgorithm, SignatureAlgorithm>> clientHelloSigAlgs_;
};
// For unit-tests