state == SSL23_ST_SR_CLNT_HELLO_B ||
state == SSL3_ST_SR_CLNT_HELLO_B ||
state == SSL3_ST_SR_CLNT_HELLO_C
- );
+ );
}
-void
+void
Ssl::ClientBio::stateChanged(const SSL *ssl, int where, int ret)
{
Ssl::Bio::stateChanged(ssl, where, ret);
{
static std::string buf;
buf.clear();
- for(int i = 0; i < len; i++ ) {
+ for (int i = 0; i < len; i++ ) {
char tmp[3];
snprintf(tmp, sizeof(tmp), "%.2x", bytes[i]);
buf.append(tmp);
debugs(83, 7, "SSL Header Size: " << helloSize);
helloSize +=5;
#ifdef DO_SSLV23
- } else if ((head[0] & 0x80) && head[2] == 0x01 && head[3] == 0x03) {
+ } else if ((head[0] & 0x80) && head[2] == 0x01 && head[3] == 0x03) {
debugs(83, 7, "SSL version 2 handshake message with v3 support");
helloSize = head[1];
helloSize +=5;
#endif
- }else {
+ } else {
debugs(83, 7, "Not an SSL acceptable handshake message (SSLv2 message?)");
return -1;
}
size_t token = 0;
size_t end = 0;
while (token != std::string::npos) {
- end = features.clientRequestedCiphers.find(':',token);
- std::string cipher;
- cipher.assign(features.clientRequestedCiphers, token, end - token);
- token = (end != std::string::npos ? end + 1 : std::string::npos);
- bool found = false;
- STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(ssl);
- for (int i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) {
- SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
- const char *cname = SSL_CIPHER_get_name(c);
- if (cipher.compare(cname)) {
- found = true;
- break;
- }
- }
- if (!found) {
- debugs(83, 5, "Client Hello Data supports cipher '"<< cipher <<"' but we do not support it!");
- return false;
- }
+ end = features.clientRequestedCiphers.find(':',token);
+ std::string cipher;
+ cipher.assign(features.clientRequestedCiphers, token, end - token);
+ token = (end != std::string::npos ? end + 1 : std::string::npos);
+ bool found = false;
+ STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(ssl);
+ for (int i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) {
+ SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
+ const char *cname = SSL_CIPHER_get_name(c);
+ if (cipher.compare(cname)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ debugs(83, 5, "Client Hello Data supports cipher '"<< cipher <<"' but we do not support it!");
+ return false;
+ }
}
#if !defined(SSL_TLSEXT_HB_ENABLED)
if (
buf[1] >= 3 //it is an SSL Version3 message
&& buf[0] == 0x16 // and it is a Handshake/Hello message
- ) {
+ ) {
//Hello message is the first message we write to server
assert(!helloMsg.hasContent());
//allowBump = true;
if (allowSplice) {
- // Do not write yet.....
+ // Do not write yet.....
BIO_set_retry_write(table);
return -1;
}
return -1;
case BIO_CTRL_DUP:
- // Should implemented if the SSL_dup openSSL API function
+ // Should implemented if the SSL_dup openSSL API function
// used anywhere in squid.
return 0;
}
return 0;
-/* we may also need to implement these:
- case BIO_CTRL_RESET:
- case BIO_C_FILE_SEEK:
- case BIO_C_FILE_TELL:
- case BIO_CTRL_INFO:
- case BIO_CTRL_GET_CLOSE:
- case BIO_CTRL_SET_CLOSE:
- case BIO_CTRL_PENDING:
- case BIO_CTRL_WPENDING:
-*/
+ /* we may also need to implement these:
+ case BIO_CTRL_RESET:
+ case BIO_C_FILE_SEEK:
+ case BIO_C_FILE_TELL:
+ case BIO_CTRL_INFO:
+ case BIO_CTRL_GET_CLOSE:
+ case BIO_CTRL_SET_CLOSE:
+ case BIO_CTRL_PENDING:
+ case BIO_CTRL_WPENDING:
+ */
default:
return 0;
int Ssl::Bio::sslFeatures::toSquidSSLVersion() const
{
- if(sslVersion == SSL2_VERSION)
+ if (sslVersion == SSL2_VERSION)
return 2;
- else if(sslVersion == SSL3_VERSION)
+ else if (sslVersion == SSL3_VERSION)
return 3;
- else if(sslVersion == TLS1_VERSION)
+ else if (sslVersion == TLS1_VERSION)
return 4;
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
- else if(sslVersion == TLS1_1_VERSION)
+ else if (sslVersion == TLS1_1_VERSION)
return 5;
- else if(sslVersion == TLS1_2_VERSION)
+ else if (sslVersion == TLS1_2_VERSION)
return 6;
#endif
else
sslVersion = SSL_version(ssl);
debugs(83, 7, "SSL version: " << SSL_get_version(ssl) << " (" << sslVersion << ")");
-#if defined(TLSEXT_NAMETYPE_host_name)
- if(const char *server = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))
+#if defined(TLSEXT_NAMETYPE_host_name)
+ if (const char *server = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))
serverName = server;
debugs(83, 7, "SNI server name: " << serverName);
#endif
if (ssl->session->compress_meth)
- compressMethod = ssl->session->compress_meth;
- else if(sslVersion >= 3) //if it is 3 or newer version then compression is disabled
+ compressMethod = ssl->session->compress_meth;
+ else if (sslVersion >= 3) //if it is 3 or newer version then compression is disabled
compressMethod = 0;
debugs(83, 7, "SSL compression: " << compressMethod);
for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) {
SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i);
if (c != NULL) {
- if(!clientRequestedCiphers.empty())
+ if (!clientRequestedCiphers.empty())
clientRequestedCiphers.append(":");
clientRequestedCiphers.append(c->name);
}
return parseV23Hello(hello);
#endif
}
-
+
debugs(83, 7, "Not a known SSL handshake message");
return false;
}
for (int i = 0; i < ciphersLen; i += cs) {
const SSL_CIPHER *c = method->get_cipher_by_char((ciphers + i));
if (c != NULL) {
- if(!clientRequestedCiphers.empty())
+ if (!clientRequestedCiphers.empty())
clientRequestedCiphers.append(":");
clientRequestedCiphers.append(c->name);
} else
debugs(83, 7, "SSL compression methods number: " << (int)compression[0]);
const unsigned char *pToExtensions = compression + 1 + (int)compression[0];
- if (pToExtensions < hello + helloSize) {
+ if (pToExtensions < hello + helloSize) {
int extensionsLen = (pToExtensions[0] << 8) | pToExtensions[1];
const unsigned char *ext = pToExtensions + 2;
- while (ext < pToExtensions + extensionsLen){
+ while (ext < pToExtensions + extensionsLen) {
short extType = (ext[0] << 8) | ext[1];
ext += 2;
short extLen = (ext[0] << 8) | ext[1];
doHeartBeats = true;
} else
extensions.push_back(extType);
-
+
ext += extLen;
}
}
for (int i = 0; i < ciphersLen; i += cs) {
// The v2 hello messages cipher has 3 bytes.
// The v2 cipher has the first byte not null
- // Because we are going to sent only v3 message we
+ // Because we are going to sent only v3 message we
// are ignoring these ciphers
if (ciphers[i] != 0)
continue;
const SSL_CIPHER *c = method->get_cipher_by_char((ciphers + i + 1));
if (c != NULL) {
- if(!clientRequestedCiphers.empty())
+ if (!clientRequestedCiphers.empty())
clientRequestedCiphers.append(":");
clientRequestedCiphers.append(c->name);
}
}
}
- debugs(83, 7, "Ciphers requested by client: " << clientRequestedCiphers);
+ debugs(83, 7, "Ciphers requested by client: " << clientRequestedCiphers);
//Get Client Random number. It starts on the position 11 of hello message
memcpy(client_random, ciphers + ciphersLen, SSL3_RANDOM_SIZE);
Ssl::Bio::sslFeatures::applyToSSL(SSL *ssl) const
{
// To increase the possibility for bumping after peek mode selection or
- // splicing after stare mode selection it is good to set the
+ // splicing after stare mode selection it is good to set the
// SSL protocol version.
// The SSL_set_ssl_method is not the correct method because it will strict
// SSL version which can be used to the SSL version used for client hello message.
- // For example will prevent comunnicating with a tls1.0 server if the
+ // For example will prevent comunnicating with a tls1.0 server if the
// client sent and tlsv1.2 Hello message.
//SSL_set_ssl_method(ssl, Ssl::method(features.toSquidSSLVersion()));
#ifdef TLSEXT_NAMETYPE_host_name
Ssl::Bio::sslFeatures::print(std::ostream &os) const
{
static std::string buf;
- return os << "v" << sslVersion <<
- " SNI:" << (serverName.empty() ? "-" : serverName) <<
- " comp:" << compressMethod <<
- " Ciphers:" << clientRequestedCiphers <<
- " Random:" << objToString(client_random, SSL3_RANDOM_SIZE) <<
- " ecPointFormats:" << ecPointFormatList <<
- " ec:" << ellipticCurves <<
- " opaquePrf:" << opaquePrf;
+ return os << "v" << sslVersion <<
+ " SNI:" << (serverName.empty() ? "-" : serverName) <<
+ " comp:" << compressMethod <<
+ " Ciphers:" << clientRequestedCiphers <<
+ " Random:" << objToString(client_random, SSL3_RANDOM_SIZE) <<
+ " ecPointFormats:" << ecPointFormatList <<
+ " ec:" << ellipticCurves <<
+ " opaquePrf:" << opaquePrf;
}
#endif /* USE_SSL */
#include <string>
#endif
-namespace Ssl {
+namespace Ssl
+{
/// BIO source and sink node, handling socket I/O and monitoring SSL state
-class Bio {
+class Bio
+{
public:
enum Type {
BIO_TO_CLIENT = 6000,
};
/// Class to store SSL connection features
- class sslFeatures {
+ class sslFeatures
+ {
public:
sslFeatures();
bool get(const SSL *ssl); ///< Retrieves the features from SSL object
/// BIO node to handle socket IO for squid client side
/// If bumping is enabled this Bio detects and analyses client hello message
/// to retrieve the SSL features supported by the client
-class ClientBio: public Bio {
+class ClientBio: public Bio
+{
public:
/// The ssl hello message read states
typedef enum {atHelloNone = 0, atHelloStarted, atHelloReceived} HelloReadState;
explicit ClientBio(const int anFd): Bio(anFd), holdRead_(false), holdWrite_(false), helloState(atHelloNone), helloSize(0) {}
/// The ClientBio version of the Ssl::Bio::stateChanged method
- /// When the client hello message retrieved, fill the
+ /// When the client hello message retrieved, fill the
/// "features" member with the client provided informations.
virtual void stateChanged(const SSL *ssl, int where, int ret);
/// The ClientBio version of the Ssl::Bio::write method
/// If bumping is enabled, analyses the SSL hello message sent by squid OpenSSL
/// subsystem (step3 bumping step) against bumping mode:
/// * Peek mode: Send client hello message instead of the openSSL generated
-/// hello message and normaly denies bumping and allow only
+/// hello message and normaly denies bumping and allow only
/// splice or terminate the SSL connection
/// * Stare mode: Sends the openSSL generated hello message and normaly
/// denies splicing and allow bump or terminate the SSL
/// object members to replace hello message with web client hello message.
/// This is may allow bumping in peek mode and splicing in stare mode after
/// the server hello message received.
-class ServerBio: public Bio {
+class ServerBio: public Bio
+{
public:
explicit ServerBio(const int anFd): Bio(anFd), featuresSet(false), helloMsgSize(0), helloBuild(false), allowSplice(false), allowBump(false), holdWrite_(false), record_(false), bumpMode_(bumpNone) {}
/// The ServerBio version of the Ssl::Bio::stateChanged method
bool holdWrite() const {return holdWrite_;}
/// Enables or disables the write hold state
void holdWrite(bool h) {holdWrite_ = h;}
- /// Enables or disables the input data recording, for internal analysis.
+ /// Enables or disables the input data recording, for internal analysis.
void recordInput(bool r) {record_ = r;}
/// Whether we can splice or not the SSL stream
bool canSplice() {return allowSplice;}