aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/extra
diff options
context:
space:
mode:
authorGravatar Attila Molnar2016-08-10 15:57:04 +0200
committerGravatar Attila Molnar2016-08-10 15:57:04 +0200
commit7770cd985405c7630e9149fc08c314ec824a9c75 (patch)
tree717c8ed61ec462196d206471899fc47e25c05c59 /src/modules/extra
parentAdd a method which calculates the maximum mask length. (#1171) (diff)
parentm_ssl_* Add option to sslprofile controlling whether to request client certif... (diff)
Merge branch 'master+websocket'
Diffstat (limited to 'src/modules/extra')
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp43
-rw-r--r--src/modules/extra/m_ssl_mbedtls.cpp35
-rw-r--r--src/modules/extra/m_ssl_openssl.cpp26
3 files changed, 61 insertions, 43 deletions
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index a1c989163..bda4e6a48 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -101,6 +101,8 @@ typedef gnutls_connection_end_t inspircd_gnutls_session_init_flags_t;
#define INSPIRCD_GNUTLS_HAS_CORK
#endif
+static Module* thismod;
+
class RandGen : public HandlerBase2<void, char*, size_t>
{
public:
@@ -581,16 +583,21 @@ namespace GnuTLS
*/
const unsigned int outrecsize;
+ /** True to request a client certificate as a server
+ */
+ const bool requestclientcert;
+
Profile(const std::string& profilename, const std::string& certstr, const std::string& keystr,
std::auto_ptr<DHParams>& DH, unsigned int mindh, const std::string& hashstr,
const std::string& priostr, std::auto_ptr<X509CertList>& CA, std::auto_ptr<X509CRL>& CRL,
- unsigned int recsize)
+ unsigned int recsize, bool Requestclientcert)
: name(profilename)
, x509cred(certstr, keystr)
, min_dh_bits(mindh)
, hash(hashstr)
, priority(priostr)
, outrecsize(recsize)
+ , requestclientcert(Requestclientcert)
{
x509cred.SetDH(DH);
x509cred.SetCA(CA, CRL);
@@ -661,7 +668,10 @@ namespace GnuTLS
#else
unsigned int outrecsize = tag->getInt("outrecsize", 2048, 512, 16384);
#endif
- return new Profile(profilename, certstr, keystr, dh, mindh, hashstr, priostr, ca, crl, outrecsize);
+
+ const bool requestclientcert = tag->getBool("requestclientcert", true);
+
+ return new Profile(profilename, certstr, keystr, dh, mindh, hashstr, priostr, ca, crl, outrecsize, requestclientcert);
}
/** Set up the given session with the settings in this profile
@@ -672,8 +682,9 @@ namespace GnuTLS
x509cred.SetupSession(sess);
gnutls_dh_set_prime_bits(sess, min_dh_bits);
- // Request client certificate if we are a server, no-op if we're a client
- gnutls_certificate_server_set_request(sess, GNUTLS_CERT_REQUEST);
+ // Request client certificate if enabled and we are a server, no-op if we're a client
+ if (requestclientcert)
+ gnutls_certificate_server_set_request(sess, GNUTLS_CERT_REQUEST);
}
const std::string& GetName() const { return name; }
@@ -917,7 +928,7 @@ info_done_dealloc:
{
StreamSocket* sock = reinterpret_cast<StreamSocket*>(session_wrap);
#ifdef _WIN32
- GnuTLSIOHook* session = static_cast<GnuTLSIOHook*>(sock->GetIOHook());
+ GnuTLSIOHook* session = static_cast<GnuTLSIOHook*>(sock->GetModHook(thismod));
#endif
if (sock->GetEventMask() & FD_READ_WILL_BLOCK)
@@ -954,7 +965,7 @@ info_done_dealloc:
{
StreamSocket* sock = reinterpret_cast<StreamSocket*>(transportptr);
#ifdef _WIN32
- GnuTLSIOHook* session = static_cast<GnuTLSIOHook*>(sock->GetIOHook());
+ GnuTLSIOHook* session = static_cast<GnuTLSIOHook*>(sock->GetModHook(thismod));
#endif
if (sock->GetEventMask() & FD_WRITE_WILL_BLOCK)
@@ -989,7 +1000,7 @@ info_done_dealloc:
{
StreamSocket* sock = reinterpret_cast<StreamSocket*>(session_wrap);
#ifdef _WIN32
- GnuTLSIOHook* session = static_cast<GnuTLSIOHook*>(sock->GetIOHook());
+ GnuTLSIOHook* session = static_cast<GnuTLSIOHook*>(sock->GetModHook(thismod));
#endif
if (sock->GetEventMask() & FD_WRITE_WILL_BLOCK)
@@ -1086,7 +1097,7 @@ info_done_dealloc:
}
}
- int OnStreamSocketWrite(StreamSocket* user) CXX11_OVERRIDE
+ int OnStreamSocketWrite(StreamSocket* user, StreamSocket::SendQueue& sendq) CXX11_OVERRIDE
{
// Finish handshake if needed
int prepret = PrepareIO(user);
@@ -1094,7 +1105,6 @@ info_done_dealloc:
return prepret;
// Session is ready for transferring application data
- StreamSocket::SendQueue& sendq = user->GetSendQ();
#ifdef INSPIRCD_GNUTLS_HAS_CORK
while (true)
@@ -1173,7 +1183,7 @@ int GnuTLS::X509Credentials::cert_callback(gnutls_session_t sess, const gnutls_d
st->key_type = GNUTLS_PRIVKEY_X509;
#endif
StreamSocket* sock = reinterpret_cast<StreamSocket*>(gnutls_transport_get_ptr(sess));
- GnuTLS::X509Credentials& cred = static_cast<GnuTLSIOHook*>(sock->GetIOHook())->GetProfile()->GetX509Credentials();
+ GnuTLS::X509Credentials& cred = static_cast<GnuTLSIOHook*>(sock->GetModHook(thismod))->GetProfile()->GetX509Credentials();
st->ncerts = cred.certs.size();
st->cert.x509 = cred.certs.raw();
@@ -1283,6 +1293,7 @@ class ModuleSSLGnuTLS : public Module
#ifndef GNUTLS_HAS_RND
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
#endif
+ thismod = this;
}
void init() CXX11_OVERRIDE
@@ -1318,7 +1329,7 @@ class ModuleSSLGnuTLS : public Module
{
LocalUser* user = IS_LOCAL(static_cast<User*>(item));
- if (user && user->eh.GetIOHook() && user->eh.GetIOHook()->prov->creator == this)
+ if ((user) && (user->eh.GetModHook(this)))
{
// User is using SSL, they're a local user, and they're using one of *our* SSL ports.
// Potentially there could be multiple SSL modules loaded at once on different ports.
@@ -1334,13 +1345,9 @@ class ModuleSSLGnuTLS : public Module
ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
{
- if ((user->eh.GetIOHook()) && (user->eh.GetIOHook()->prov->creator == this))
- {
- GnuTLSIOHook* iohook = static_cast<GnuTLSIOHook*>(user->eh.GetIOHook());
- if (!iohook->IsHandshakeDone())
- return MOD_RES_DENY;
- }
-
+ const GnuTLSIOHook* const iohook = static_cast<GnuTLSIOHook*>(user->eh.GetModHook(this));
+ if ((iohook) && (!iohook->IsHandshakeDone()))
+ return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
};
diff --git a/src/modules/extra/m_ssl_mbedtls.cpp b/src/modules/extra/m_ssl_mbedtls.cpp
index 8578b8196..a465d06ee 100644
--- a/src/modules/extra/m_ssl_mbedtls.cpp
+++ b/src/modules/extra/m_ssl_mbedtls.cpp
@@ -257,7 +257,6 @@ namespace mbedTLS
mbedtls_debug_set_threshold(INT_MAX);
mbedtls_ssl_conf_dbg(&conf, DebugLogFunc, NULL);
#endif
- mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
// TODO: check ret of mbedtls_ssl_config_defaults
mbedtls_ssl_config_defaults(&conf, endpoint, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
@@ -308,6 +307,11 @@ namespace mbedTLS
mbedtls_ssl_conf_ca_chain(&conf, certs.get(), crl.get());
}
+ void SetOptionalVerifyCert()
+ {
+ mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
+ }
+
const mbedtls_ssl_config* GetConf() const { return &conf; }
};
@@ -376,7 +380,8 @@ namespace mbedTLS
const std::string& castr, const std::string& crlstr,
unsigned int recsize,
CTRDRBG& ctrdrbg,
- int minver, int maxver
+ int minver, int maxver,
+ bool requestclientcert
)
: name(profilename)
, x509cred(certstr, keystr)
@@ -414,7 +419,13 @@ namespace mbedTLS
serverctx.SetDHParams(dhparams);
}
- serverctx.SetCA(cacerts, crl);
+ clientctx.SetOptionalVerifyCert();
+ // The default for servers is to not request a client certificate from the peer
+ if (requestclientcert)
+ {
+ serverctx.SetOptionalVerifyCert();
+ serverctx.SetCA(cacerts, crl);
+ }
}
static std::string ReadFile(const std::string& filename)
@@ -451,7 +462,8 @@ namespace mbedTLS
int minver = tag->getInt("minver");
int maxver = tag->getInt("maxver");
unsigned int outrecsize = tag->getInt("outrecsize", 2048, 512, 16384);
- return new Profile(profilename, certstr, keystr, dhstr, mindh, hashstr, ciphersuitestr, curvestr, castr, crlstr, outrecsize, ctr_drbg, minver, maxver);
+ const bool requestclientcert = tag->getBool("requestclientcert", true);
+ return new Profile(profilename, certstr, keystr, dhstr, mindh, hashstr, ciphersuitestr, curvestr, castr, crlstr, outrecsize, ctr_drbg, minver, maxver, requestclientcert);
}
/** Set up the given session with the settings in this profile
@@ -698,7 +710,7 @@ class mbedTLSIOHook : public SSLIOHook
}
}
- int OnStreamSocketWrite(StreamSocket* sock) CXX11_OVERRIDE
+ int OnStreamSocketWrite(StreamSocket* sock, StreamSocket::SendQueue& sendq) CXX11_OVERRIDE
{
// Finish handshake if needed
int prepret = PrepareIO(sock);
@@ -706,7 +718,6 @@ class mbedTLSIOHook : public SSLIOHook
return prepret;
// Session is ready for transferring application data
- StreamSocket::SendQueue& sendq = sock->GetSendQ();
while (!sendq.empty())
{
FlattenSendQueue(sendq, profile->GetOutgoingRecordSize());
@@ -895,7 +906,7 @@ class ModuleSSLmbedTLS : public Module
return;
LocalUser* user = IS_LOCAL(static_cast<User*>(item));
- if ((user) && (user->eh.GetIOHook()) && (user->eh.GetIOHook()->prov->creator == this))
+ if ((user) && (user->eh.GetModHook(this)))
{
// User is using SSL, they're a local user, and they're using our IOHook.
// Potentially there could be multiple SSL modules loaded at once on different ports.
@@ -905,13 +916,9 @@ class ModuleSSLmbedTLS : public Module
ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
{
- if ((user->eh.GetIOHook()) && (user->eh.GetIOHook()->prov->creator == this))
- {
- mbedTLSIOHook* iohook = static_cast<mbedTLSIOHook*>(user->eh.GetIOHook());
- if (!iohook->IsHandshakeDone())
- return MOD_RES_DENY;
- }
-
+ const mbedTLSIOHook* const iohook = static_cast<mbedTLSIOHook*>(user->eh.GetModHook(this));
+ if ((iohook) && (!iohook->IsHandshakeDone()))
+ return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp
index 80c9d9395..4df0d8962 100644
--- a/src/modules/extra/m_ssl_openssl.cpp
+++ b/src/modules/extra/m_ssl_openssl.cpp
@@ -132,7 +132,7 @@ namespace OpenSSL
mode |= SSL_MODE_RELEASE_BUFFERS;
#endif
SSL_CTX_set_mode(ctx, mode);
- SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, OnVerify);
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
SSL_CTX_set_info_callback(ctx, StaticSSLInfoCallback);
}
@@ -206,6 +206,11 @@ namespace OpenSSL
return SSL_CTX_clear_options(ctx, clearoptions);
}
+ void SetVerifyCert()
+ {
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, OnVerify);
+ }
+
SSL* CreateServerSession()
{
SSL* sess = SSL_new(ctx);
@@ -345,6 +350,10 @@ namespace OpenSSL
ERR_print_errors_cb(error_callback, this);
ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Can't read CA list from %s. This is only a problem if you want to verify client certificates, otherwise it's safe to ignore this message. Error: %s", filename.c_str(), lasterr.c_str());
}
+
+ clictx.SetVerifyCert();
+ if (tag->getBool("requestclientcert", true))
+ ctx.SetVerifyCert();
}
const std::string& GetName() const { return name; }
@@ -656,7 +665,7 @@ class OpenSSLIOHook : public SSLIOHook
}
}
- int OnStreamSocketWrite(StreamSocket* user) CXX11_OVERRIDE
+ int OnStreamSocketWrite(StreamSocket* user, StreamSocket::SendQueue& sendq) CXX11_OVERRIDE
{
// Finish handshake if needed
int prepret = PrepareIO(user);
@@ -666,7 +675,6 @@ class OpenSSLIOHook : public SSLIOHook
data_to_write = true;
// Session is ready for transferring application data
- StreamSocket::SendQueue& sendq = user->GetSendQ();
while (!sendq.empty())
{
ERR_clear_error();
@@ -910,7 +918,7 @@ class ModuleSSLOpenSSL : public Module
{
LocalUser* user = IS_LOCAL((User*)item);
- if (user && user->eh.GetIOHook() && user->eh.GetIOHook()->prov->creator == this)
+ if ((user) && (user->eh.GetModHook(this)))
{
// User is using SSL, they're a local user, and they're using one of *our* SSL ports.
// Potentially there could be multiple SSL modules loaded at once on different ports.
@@ -921,13 +929,9 @@ class ModuleSSLOpenSSL : public Module
ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
{
- if ((user->eh.GetIOHook()) && (user->eh.GetIOHook()->prov->creator == this))
- {
- OpenSSLIOHook* iohook = static_cast<OpenSSLIOHook*>(user->eh.GetIOHook());
- if (!iohook->IsHandshakeDone())
- return MOD_RES_DENY;
- }
-
+ const OpenSSLIOHook* const iohook = static_cast<OpenSSLIOHook*>(user->eh.GetModHook(this));
+ if ((iohook) && (!iohook->IsHandshakeDone()))
+ return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}