summaryrefslogtreecommitdiff
path: root/src/LibgnutlsTLSSession.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/LibgnutlsTLSSession.cc')
-rw-r--r--src/LibgnutlsTLSSession.cc189
1 files changed, 99 insertions, 90 deletions
diff --git a/src/LibgnutlsTLSSession.cc b/src/LibgnutlsTLSSession.cc
index 81f3720b..b59342c8 100644
--- a/src/LibgnutlsTLSSession.cc
+++ b/src/LibgnutlsTLSSession.cc
@@ -43,19 +43,20 @@
namespace {
using namespace aria2;
-TLSVersion getProtocolFromSession(gnutls_session_t& session) {
+TLSVersion getProtocolFromSession(gnutls_session_t& session)
+{
auto proto = gnutls_protocol_get_version(session);
- switch(proto) {
- case GNUTLS_SSL3:
- return TLS_PROTO_SSL3;
- case GNUTLS_TLS1_0:
- return TLS_PROTO_TLS10;
- case GNUTLS_TLS1_1:
- return TLS_PROTO_TLS11;
- case GNUTLS_TLS1_2:
- return TLS_PROTO_TLS12;
- default:
- return TLS_PROTO_NONE;
+ switch (proto) {
+ case GNUTLS_SSL3:
+ return TLS_PROTO_SSL3;
+ case GNUTLS_TLS1_0:
+ return TLS_PROTO_TLS10;
+ case GNUTLS_TLS1_1:
+ return TLS_PROTO_TLS11;
+ case GNUTLS_TLS1_2:
+ return TLS_PROTO_TLS12;
+ default:
+ return TLS_PROTO_NONE;
}
}
} // namespace
@@ -68,14 +69,13 @@ TLSSession* TLSSession::make(TLSContext* ctx)
}
GnuTLSSession::GnuTLSSession(GnuTLSContext* tlsContext)
- : sslSession_(nullptr),
- tlsContext_(tlsContext),
- rv_(0)
-{}
+ : sslSession_(nullptr), tlsContext_(tlsContext), rv_(0)
+{
+}
GnuTLSSession::~GnuTLSSession()
{
- if(sslSession_) {
+ if (sslSession_) {
gnutls_deinit(sslSession_);
}
}
@@ -88,37 +88,38 @@ GnuTLSSession::~GnuTLSSession()
// will fix this bug. See
// http://lists.gnutls.org/pipermail/gnutls-devel/2014-January/006679.html
// for details.
-#if (GNUTLS_VERSION_NUMBER >= 0x030103 && GNUTLS_VERSION_NUMBER <= 0x030112) \
- || (GNUTLS_VERSION_NUMBER >= 0x030200 && GNUTLS_VERSION_NUMBER <= 0x030208)
-# define A2_DISABLE_OCSP 1
+#if (GNUTLS_VERSION_NUMBER >= 0x030103 && \
+ GNUTLS_VERSION_NUMBER <= 0x030112) || \
+ (GNUTLS_VERSION_NUMBER >= 0x030200 && GNUTLS_VERSION_NUMBER <= 0x030208)
+#define A2_DISABLE_OCSP 1
#endif
int GnuTLSSession::init(sock_t sockfd)
{
#if GNUTLS_VERSION_NUMBER >= 0x030000
- unsigned int flags = tlsContext_->getSide() == TLS_CLIENT ?
- GNUTLS_CLIENT : GNUTLS_SERVER;
+ unsigned int flags =
+ tlsContext_->getSide() == TLS_CLIENT ? GNUTLS_CLIENT : GNUTLS_SERVER;
#ifdef A2_DISABLE_OCSP
- if(tlsContext_->getSide() == TLS_CLIENT) {
+ if (tlsContext_->getSide() == TLS_CLIENT) {
flags |= GNUTLS_NO_EXTENSIONS;
}
#endif // A2_DISABLE_OCSP
rv_ = gnutls_init(&sslSession_, flags);
-#else // GNUTLS_VERSION_NUMBER >= 0x030000
- rv_ = gnutls_init
- (&sslSession_,
- tlsContext_->getSide() == TLS_CLIENT ? GNUTLS_CLIENT : GNUTLS_SERVER);
+#else // GNUTLS_VERSION_NUMBER >= 0x030000
+ rv_ = gnutls_init(&sslSession_, tlsContext_->getSide() == TLS_CLIENT
+ ? GNUTLS_CLIENT
+ : GNUTLS_SERVER);
#endif // GNUTLS_VERSION_NUMBER >= 0x030000
- if(rv_ != GNUTLS_E_SUCCESS) {
+ if (rv_ != GNUTLS_E_SUCCESS) {
return TLS_ERR_ERROR;
}
#ifdef A2_DISABLE_OCSP
- if(tlsContext_->getSide() == TLS_CLIENT) {
+ if (tlsContext_->getSide() == TLS_CLIENT) {
// Enable session ticket extension manually because of
// GNUTLS_NO_EXTENSIONS.
rv_ = gnutls_session_ticket_enable_client(sslSession_);
- if(rv_ != GNUTLS_E_SUCCESS) {
+ if (rv_ != GNUTLS_E_SUCCESS) {
return TLS_ERR_ERROR;
}
}
@@ -127,27 +128,31 @@ int GnuTLSSession::init(sock_t sockfd)
// It seems err is not error message, but the argument string
// which causes syntax error.
const char* err;
+#ifdef USE_GNUTLS_SYSTEM_CRYPTO_POLICY
+ rv_ = gnutls_priority_set_direct(sslSession_, "@SYSTEM", &err);
+#else
std::string pri = "SECURE128:+SIGN-RSA-SHA1";
- switch(tlsContext_->getMinTLSVersion()) {
+ switch (tlsContext_->getMinTLSVersion()) {
case TLS_PROTO_TLS12:
pri += ":-VERS-TLS1.1";
- // fall through
+ // fall through
case TLS_PROTO_TLS11:
pri += ":-VERS-TLS1.0";
- // fall through
+ // fall through
case TLS_PROTO_TLS10:
pri += ":-VERS-SSL3.0";
default:
break;
};
rv_ = gnutls_priority_set_direct(sslSession_, pri.c_str(), &err);
- if(rv_ != GNUTLS_E_SUCCESS) {
+#endif
+ if (rv_ != GNUTLS_E_SUCCESS) {
return TLS_ERR_ERROR;
}
// put the x509 credentials to the current session
rv_ = gnutls_credentials_set(sslSession_, GNUTLS_CRD_CERTIFICATE,
tlsContext_->getCertCred());
- if(rv_ != GNUTLS_E_SUCCESS) {
+ if (rv_ != GNUTLS_E_SUCCESS) {
return TLS_ERR_ERROR;
}
// TODO Consider to use gnutls_transport_set_int() for GNUTLS 3.1.9
@@ -160,9 +165,9 @@ int GnuTLSSession::init(sock_t sockfd)
int GnuTLSSession::setSNIHostname(const std::string& hostname)
{
// TLS extensions: SNI
- rv_ = gnutls_server_name_set(sslSession_, GNUTLS_NAME_DNS,
- hostname.c_str(), hostname.size());
- if(rv_ != GNUTLS_E_SUCCESS) {
+ rv_ = gnutls_server_name_set(sslSession_, GNUTLS_NAME_DNS, hostname.c_str(),
+ hostname.size());
+ if (rv_ != GNUTLS_E_SUCCESS) {
return TLS_ERR_ERROR;
}
return TLS_ERR_OK;
@@ -171,11 +176,13 @@ int GnuTLSSession::setSNIHostname(const std::string& hostname)
int GnuTLSSession::closeConnection()
{
rv_ = gnutls_bye(sslSession_, GNUTLS_SHUT_WR);
- if(rv_ == GNUTLS_E_SUCCESS) {
+ if (rv_ == GNUTLS_E_SUCCESS) {
return TLS_ERR_OK;
- } else if(rv_ == GNUTLS_E_AGAIN || rv_ == GNUTLS_E_INTERRUPTED) {
+ }
+ else if (rv_ == GNUTLS_E_AGAIN || rv_ == GNUTLS_E_INTERRUPTED) {
return TLS_ERR_WOULDBLOCK;
- } else {
+ }
+ else {
return TLS_ERR_ERROR;
}
}
@@ -188,106 +195,111 @@ int GnuTLSSession::checkDirection()
ssize_t GnuTLSSession::writeData(const void* data, size_t len)
{
- while((rv_ = gnutls_record_send(sslSession_, data, len)) ==
- GNUTLS_E_INTERRUPTED);
- if(rv_ >= 0) {
+ while ((rv_ = gnutls_record_send(sslSession_, data, len)) ==
+ GNUTLS_E_INTERRUPTED)
+ ;
+ if (rv_ >= 0) {
ssize_t ret = rv_;
rv_ = 0;
return ret;
- } else if(rv_ == GNUTLS_E_AGAIN || rv_ == GNUTLS_E_INTERRUPTED) {
+ }
+ else if (rv_ == GNUTLS_E_AGAIN || rv_ == GNUTLS_E_INTERRUPTED) {
return TLS_ERR_WOULDBLOCK;
- } else {
+ }
+ else {
return TLS_ERR_ERROR;
}
}
ssize_t GnuTLSSession::readData(void* data, size_t len)
{
- while((rv_ = gnutls_record_recv(sslSession_, data, len)) ==
- GNUTLS_E_INTERRUPTED);
- if(rv_ >= 0) {
+ while ((rv_ = gnutls_record_recv(sslSession_, data, len)) ==
+ GNUTLS_E_INTERRUPTED)
+ ;
+ if (rv_ >= 0) {
ssize_t ret = rv_;
rv_ = 0;
return ret;
- } else if(rv_ == GNUTLS_E_AGAIN || rv_ == GNUTLS_E_INTERRUPTED) {
+ }
+ else if (rv_ == GNUTLS_E_AGAIN || rv_ == GNUTLS_E_INTERRUPTED) {
return TLS_ERR_WOULDBLOCK;
- } else {
+ }
+ else {
return TLS_ERR_ERROR;
}
}
-int GnuTLSSession::tlsConnect(const std::string& hostname,
- TLSVersion& version,
+int GnuTLSSession::tlsConnect(const std::string& hostname, TLSVersion& version,
std::string& handshakeErr)
{
handshakeErr = "";
- for(;;) {
+ for (;;) {
rv_ = gnutls_handshake(sslSession_);
- if(rv_ == GNUTLS_E_SUCCESS) {
+ if (rv_ == GNUTLS_E_SUCCESS) {
break;
}
- if(rv_ == GNUTLS_E_AGAIN || rv_ == GNUTLS_E_INTERRUPTED) {
+ if (rv_ == GNUTLS_E_AGAIN || rv_ == GNUTLS_E_INTERRUPTED) {
return TLS_ERR_WOULDBLOCK;
}
- if(gnutls_error_is_fatal(rv_)) {
+ if (gnutls_error_is_fatal(rv_)) {
return TLS_ERR_ERROR;
}
}
- if(tlsContext_->getVerifyPeer()) {
+ if (tlsContext_->getVerifyPeer()) {
// verify peer
unsigned int status;
rv_ = gnutls_certificate_verify_peers2(sslSession_, &status);
- if(rv_ != GNUTLS_E_SUCCESS) {
+ if (rv_ != GNUTLS_E_SUCCESS) {
return TLS_ERR_ERROR;
}
- if(status) {
+ if (status) {
handshakeErr = "";
- if(status & GNUTLS_CERT_INVALID) {
+ if (status & GNUTLS_CERT_INVALID) {
handshakeErr += " `not signed by known authorities or invalid'";
}
- if(status & GNUTLS_CERT_REVOKED) {
+ if (status & GNUTLS_CERT_REVOKED) {
handshakeErr += " `revoked by its CA'";
}
- if(status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
+ if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
handshakeErr += " `issuer is not known'";
}
// TODO should check GNUTLS_CERT_SIGNER_NOT_CA ?
- if(status & GNUTLS_CERT_INSECURE_ALGORITHM) {
+ if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
handshakeErr += " `insecure algorithm'";
}
- if(status & GNUTLS_CERT_NOT_ACTIVATED) {
+ if (status & GNUTLS_CERT_NOT_ACTIVATED) {
handshakeErr += " `not activated yet'";
}
- if(status & GNUTLS_CERT_EXPIRED) {
+ if (status & GNUTLS_CERT_EXPIRED) {
handshakeErr += " `expired'";
}
// TODO Add GNUTLS_CERT_SIGNATURE_FAILURE here
- if(!handshakeErr.empty()) {
+ if (!handshakeErr.empty()) {
return TLS_ERR_ERROR;
}
}
// certificate type: only X509 is allowed.
- if(gnutls_certificate_type_get(sslSession_) != GNUTLS_CRT_X509) {
+ if (gnutls_certificate_type_get(sslSession_) != GNUTLS_CRT_X509) {
handshakeErr = "certificate type must be X509";
return TLS_ERR_ERROR;
}
unsigned int peerCertsLength;
const gnutls_datum_t* peerCerts;
peerCerts = gnutls_certificate_get_peers(sslSession_, &peerCertsLength);
- if(!peerCerts || peerCertsLength == 0 ) {
+ if (!peerCerts || peerCertsLength == 0) {
handshakeErr = "certificate not found";
return TLS_ERR_ERROR;
}
gnutls_x509_crt_t cert;
rv_ = gnutls_x509_crt_init(&cert);
- if(rv_ != GNUTLS_E_SUCCESS) {
+ if (rv_ != GNUTLS_E_SUCCESS) {
return TLS_ERR_ERROR;
}
std::unique_ptr<std::remove_pointer<gnutls_x509_crt_t>::type,
- decltype(&gnutls_x509_crt_deinit)> certDeleter
- (cert, gnutls_x509_crt_deinit);
+ decltype(&gnutls_x509_crt_deinit)>
+ certDeleter(cert, gnutls_x509_crt_deinit);
rv_ = gnutls_x509_crt_import(cert, &peerCerts[0], GNUTLS_X509_FMT_DER);
- if(rv_ != GNUTLS_E_SUCCESS) {
+ if (rv_ != GNUTLS_E_SUCCESS) {
return TLS_ERR_ERROR;
}
std::string commonName;
@@ -296,24 +308,24 @@ int GnuTLSSession::tlsConnect(const std::string& hostname,
int ret = 0;
char altName[256];
size_t altNameLen;
- for(int i = 0; !(ret < 0); ++i) {
+ for (int i = 0; !(ret < 0); ++i) {
altNameLen = sizeof(altName);
- ret = gnutls_x509_crt_get_subject_alt_name(cert, i, altName,
- &altNameLen, nullptr);
- if(ret == GNUTLS_SAN_DNSNAME) {
+ ret = gnutls_x509_crt_get_subject_alt_name(cert, i, altName, &altNameLen,
+ nullptr);
+ if (ret == GNUTLS_SAN_DNSNAME) {
dnsNames.push_back(std::string(altName, altNameLen));
- } else if(ret == GNUTLS_SAN_IPADDRESS) {
+ }
+ else if (ret == GNUTLS_SAN_IPADDRESS) {
ipAddrs.push_back(std::string(altName, altNameLen));
}
}
altNameLen = sizeof(altName);
- ret = gnutls_x509_crt_get_dn_by_oid(cert,
- GNUTLS_OID_X520_COMMON_NAME, 0, 0,
+ ret = gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
altName, &altNameLen);
- if(ret == 0) {
+ if (ret == 0) {
commonName.assign(altName, altNameLen);
}
- if(!net::verifyHostname(hostname, dnsNames, ipAddrs, commonName)) {
+ if (!net::verifyHostname(hostname, dnsNames, ipAddrs, commonName)) {
handshakeErr = "hostname does not match";
return TLS_ERR_ERROR;
}
@@ -326,24 +338,21 @@ int GnuTLSSession::tlsConnect(const std::string& hostname,
int GnuTLSSession::tlsAccept(TLSVersion& version)
{
- for(;;) {
+ for (;;) {
rv_ = gnutls_handshake(sslSession_);
- if(rv_ == GNUTLS_E_SUCCESS) {
+ if (rv_ == GNUTLS_E_SUCCESS) {
version = getProtocolFromSession(sslSession_);
return TLS_ERR_OK;
}
- if(rv_ == GNUTLS_E_AGAIN || rv_ == GNUTLS_E_INTERRUPTED) {
+ if (rv_ == GNUTLS_E_AGAIN || rv_ == GNUTLS_E_INTERRUPTED) {
return TLS_ERR_WOULDBLOCK;
}
- if(gnutls_error_is_fatal(rv_)) {
+ if (gnutls_error_is_fatal(rv_)) {
return TLS_ERR_ERROR;
}
}
}
-std::string GnuTLSSession::getLastErrorString()
-{
- return gnutls_strerror(rv_);
-}
+std::string GnuTLSSession::getLastErrorString() { return gnutls_strerror(rv_); }
} // namespace aria2