explicitly check against null, better x509 free, log timeout on connect and increase default to 5 secs, support wildcard subject
This commit is contained in:
@@ -149,11 +149,11 @@ SSLSocket* SSLSocket::connect(const string& host, const uint16_t& port, bool htt
|
|||||||
ostringstream ostr;
|
ostringstream ostr;
|
||||||
ostr << host << ':' << static_cast<unsigned>(port);
|
ostr << host << ':' << static_cast<unsigned>(port);
|
||||||
const string hostPort = ostr.str();
|
const string hostPort = ostr.str();
|
||||||
time_t until = time(nullptr) + (timeout <= 3 ? 3 : timeout); // at least 3 seconds
|
time_t until = time(nullptr) + 1 + (timeout <= 5 ? 5 : timeout); // at least 5 seconds, 1 extra for rounding
|
||||||
if (!https) {
|
if (!https) {
|
||||||
do {
|
do {
|
||||||
bio = BIO_new_connect(static_cast<const char*>(hostPort.c_str()));
|
bio = BIO_new_connect(static_cast<const char*>(hostPort.c_str()));
|
||||||
if (isError("connect", bio)) {
|
if (isError("connect", bio!=nullptr)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BIO_set_nbio(bio, 1); // set non-blocking
|
BIO_set_nbio(bio, 1); // set non-blocking
|
||||||
@@ -163,11 +163,11 @@ SSLSocket* SSLSocket::connect(const string& host, const uint16_t& port, bool htt
|
|||||||
SSL *ssl = nullptr;
|
SSL *ssl = nullptr;
|
||||||
do {
|
do {
|
||||||
const SSL_METHOD *method = SSLv23_method();
|
const SSL_METHOD *method = SSLv23_method();
|
||||||
if (isError("method", method)) {
|
if (isError("method", method!=nullptr)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ctx = SSL_CTX_new(method);
|
ctx = SSL_CTX_new(method);
|
||||||
if (isError("ctx_new", ctx)) {
|
if (isError("ctx_new", ctx!=nullptr)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bool verifyPeer = !caFile || strcmp(caFile, "#") != 0;
|
bool verifyPeer = !caFile || strcmp(caFile, "#") != 0;
|
||||||
@@ -191,7 +191,7 @@ SSLSocket* SSLSocket::connect(const string& host, const uint16_t& port, bool htt
|
|||||||
const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
|
const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
|
||||||
SSL_CTX_set_options(ctx, flags);
|
SSL_CTX_set_options(ctx, flags);
|
||||||
bio = BIO_new_ssl_connect(ctx);
|
bio = BIO_new_ssl_connect(ctx);
|
||||||
if (isError("new_ssl_conn", bio)) {
|
if (isError("new_ssl_conn", bio!=nullptr)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isError("conn_hostname", BIO_set_conn_hostname(bio, hostPort.c_str()), 1)) {
|
if (isError("conn_hostname", BIO_set_conn_hostname(bio, hostPort.c_str()), 1)) {
|
||||||
@@ -199,7 +199,7 @@ SSLSocket* SSLSocket::connect(const string& host, const uint16_t& port, bool htt
|
|||||||
}
|
}
|
||||||
BIO_set_nbio(bio, 1); // set non-blocking
|
BIO_set_nbio(bio, 1); // set non-blocking
|
||||||
BIO_get_ssl(bio, &ssl);
|
BIO_get_ssl(bio, &ssl);
|
||||||
if (isError("get_ssl", ssl)) {
|
if (isError("get_ssl", ssl!=nullptr)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
|
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
|
||||||
@@ -208,34 +208,45 @@ SSLSocket* SSLSocket::connect(const string& host, const uint16_t& port, bool htt
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
long res = BIO_do_connect(bio);
|
long res = BIO_do_connect(bio);
|
||||||
while (res <= 0 && BIO_should_retry(bio) && time(nullptr) < until) {
|
time_t now = 0;
|
||||||
|
while (res <= 0 && BIO_should_retry(bio)) {
|
||||||
|
if ((now=time(nullptr)) > until) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
usleep(SLEEP_NANOS);
|
usleep(SLEEP_NANOS);
|
||||||
res = BIO_do_connect(bio);
|
res = BIO_do_connect(bio);
|
||||||
}
|
}
|
||||||
|
if (res <= 0 && now > until) {
|
||||||
|
logError(lf_network, "HTTP connect: timed out after %d sec", now-until);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (isError("connect", res, 1)) {
|
if (isError("connect", res, 1)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
X509 *cert = SSL_get_peer_certificate(ssl);
|
X509 *cert = SSL_get_peer_certificate(ssl);
|
||||||
if (cert) {
|
if (isError("peer_cert", cert!=nullptr)) {
|
||||||
X509_free(cert);
|
|
||||||
}
|
|
||||||
if (isError("peer_cert", cert)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
X509_free(cert); // decrement reference count incremented by above call
|
||||||
if (verifyPeer && isError("verify", SSL_get_verify_result(ssl), X509_V_OK)) {
|
if (verifyPeer && isError("verify", SSL_get_verify_result(ssl), X509_V_OK)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// check hostname
|
// check hostname
|
||||||
X509_NAME *sname = X509_get_subject_name(cert);
|
X509_NAME *sname = X509_get_subject_name(cert);
|
||||||
if (isError("get_subject", sname)) {
|
if (isError("get_subject", sname!=nullptr)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
char peerName[64];
|
char peerName[64];
|
||||||
if (isError("subject name", X509_NAME_get_text_by_NID(sname, NID_commonName, peerName, sizeof(peerName)) > 0)) {
|
if (isError("subject name", X509_NAME_get_text_by_NID(sname, NID_commonName, peerName, sizeof(peerName)) > 0)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isError("subject", strcmp(peerName, hostname), 0)) {
|
if (strcmp(peerName, hostname)!=0) {
|
||||||
break;
|
char* dotpos = NULL;
|
||||||
|
if (peerName[0]=='*' && peerName[1]=='.' && (dotpos=strchr((char*)hostname, '.')) && strcmp(peerName+2, dotpos+1)==0) {
|
||||||
|
// wildcard matches
|
||||||
|
} else if (isError("subject", 1, 0)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return new SSLSocket(ctx, bio, until);
|
return new SSLSocket(ctx, bio, until);
|
||||||
} while (false);
|
} while (false);
|
||||||
|
|||||||
Reference in New Issue
Block a user