X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fextra%2Fm_ssl_gnutls.cpp;h=c1ffdfb4c7b53e9f32fb0017aeef4d9236e64392;hb=bf66b6dedd226b9967d876a3869b1766af38d596;hp=716a736f87868f3304adfc7b79a8f697673fe5d2;hpb=a71f34e4b17420cacc4a50c5af64fe15811a8148;p=user%2Fhenk%2Fcode%2Finspircd.git
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index 716a736f8..c1ffdfb4c 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -20,6 +20,16 @@
* along with this program. If not, see .
*/
+/// $CompilerFlags: find_compiler_flags("gnutls")
+/// $CompilerFlags: require_version("gnutls" "1.0" "2.12") execute("libgcrypt-config --cflags" "LIBGCRYPT_CXXFLAGS")
+
+/// $LinkerFlags: find_linker_flags("gnutls" "-lgnutls")
+/// $LinkerFlags: require_version("gnutls" "1.0" "2.12") execute("libgcrypt-config --libs" "LIBGCRYPT_LDFLAGS")
+
+/// $PackageInfo: require_system("centos") gnutls-devel pkgconfig
+/// $PackageInfo: require_system("darwin") gnutls pkg-config
+/// $PackageInfo: require_system("ubuntu" "1.0" "13.10") libgcrypt11-dev
+/// $PackageInfo: require_system("ubuntu" "14.04") gnutls-bin libgnutls-dev pkg-config
#include "inspircd.h"
#include "modules/ssl.h"
@@ -29,7 +39,11 @@
#if defined __clang__
# pragma clang diagnostic ignored "-Wc++11-extensions"
#elif defined __GNUC__
-# pragma GCC diagnostic ignored "-pedantic"
+# if __GNUC__ < 6
+# pragma GCC diagnostic ignored "-pedantic"
+# else
+# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+# endif
#endif
#include
@@ -55,12 +69,9 @@
#endif
#ifdef _WIN32
-# pragma comment(lib, "libgnutls-28.lib")
+# pragma comment(lib, "libgnutls-30.lib")
#endif
-/* $CompileFlags: pkgconfincludes("gnutls","/gnutls/gnutls.h","") eval("print `libgcrypt-config --cflags | tr -d \r` if `pkg-config --modversion gnutls 2>/dev/null | tr -d \r` lt '2.12'") */
-/* $LinkerFlags: rpath("pkg-config --libs gnutls") pkgconflibs("gnutls","/libgnutls.so","-lgnutls") eval("print `libgcrypt-config --libs | tr -d \r` if `pkg-config --modversion gnutls 2>/dev/null | tr -d \r` lt '2.12'") */
-
// These don't exist in older GnuTLS versions
#if INSPIRCD_GNUTLS_HAS_VERSION(2, 1, 7)
#define GNUTLS_NEW_PRIO_API
@@ -97,6 +108,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
{
public:
@@ -577,16 +590,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& DH, unsigned int mindh, const std::string& hashstr,
const std::string& priostr, std::auto_ptr& CA, std::auto_ptr& 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);
@@ -657,7 +675,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
@@ -668,8 +689,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; }
@@ -913,7 +935,7 @@ info_done_dealloc:
{
StreamSocket* sock = reinterpret_cast(session_wrap);
#ifdef _WIN32
- GnuTLSIOHook* session = static_cast(sock->GetIOHook());
+ GnuTLSIOHook* session = static_cast(sock->GetModHook(thismod));
#endif
if (sock->GetEventMask() & FD_READ_WILL_BLOCK)
@@ -950,7 +972,7 @@ info_done_dealloc:
{
StreamSocket* sock = reinterpret_cast(transportptr);
#ifdef _WIN32
- GnuTLSIOHook* session = static_cast(sock->GetIOHook());
+ GnuTLSIOHook* session = static_cast(sock->GetModHook(thismod));
#endif
if (sock->GetEventMask() & FD_WRITE_WILL_BLOCK)
@@ -985,7 +1007,7 @@ info_done_dealloc:
{
StreamSocket* sock = reinterpret_cast(session_wrap);
#ifdef _WIN32
- GnuTLSIOHook* session = static_cast(sock->GetIOHook());
+ GnuTLSIOHook* session = static_cast(sock->GetModHook(thismod));
#endif
if (sock->GetEventMask() & FD_WRITE_WILL_BLOCK)
@@ -1061,6 +1083,9 @@ info_done_dealloc:
if (ret > 0)
{
reader.appendto(recvq);
+ // Schedule a read if there is still data in the GnuTLS buffer
+ if (gnutls_record_check_pending(sess) > 0)
+ SocketEngine::ChangeEventMask(user, FD_ADD_TRIAL_READ);
return 1;
}
else if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
@@ -1082,7 +1107,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);
@@ -1090,7 +1115,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)
@@ -1146,22 +1170,10 @@ info_done_dealloc:
return 1;
}
- void TellCiphersAndFingerprint(LocalUser* user)
- {
- if (sess)
- {
- std::string text = "*** You are connected using SSL cipher '";
- GetCiphersuite(text);
- text += '\'';
- if (!certificate->fingerprint.empty())
- text += " and your SSL certificate fingerprint is " + certificate->fingerprint;
-
- user->WriteNotice(text);
- }
- }
-
- void GetCiphersuite(std::string& out) const
+ void GetCiphersuite(std::string& out) const CXX11_OVERRIDE
{
+ if (!IsHandshakeDone())
+ return;
out.append(UnknownIfNULL(gnutls_protocol_get_name(gnutls_protocol_get_version(sess)))).push_back('-');
out.append(UnknownIfNULL(gnutls_kx_get_name(gnutls_kx_get(sess)))).push_back('-');
out.append(UnknownIfNULL(gnutls_cipher_get_name(gnutls_cipher_get(sess)))).push_back('-');
@@ -1181,7 +1193,7 @@ int GnuTLS::X509Credentials::cert_callback(gnutls_session_t sess, const gnutls_d
st->key_type = GNUTLS_PRIVKEY_X509;
#endif
StreamSocket* sock = reinterpret_cast(gnutls_transport_get_ptr(sess));
- GnuTLS::X509Credentials& cred = static_cast(sock->GetIOHook())->GetProfile()->GetX509Credentials();
+ GnuTLS::X509Credentials& cred = static_cast(sock->GetModHook(thismod))->GetProfile()->GetX509Credentials();
st->ncerts = cred.certs.size();
st->cert.x509 = cred.certs.raw();
@@ -1291,6 +1303,7 @@ class ModuleSSLGnuTLS : public Module
#ifndef GNUTLS_HAS_RND
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
#endif
+ thismod = this;
}
void init() CXX11_OVERRIDE
@@ -1326,7 +1339,7 @@ class ModuleSSLGnuTLS : public Module
{
LocalUser* user = IS_LOCAL(static_cast(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.
@@ -1340,22 +1353,11 @@ class ModuleSSLGnuTLS : public Module
return Version("Provides SSL support for clients", VF_VENDOR);
}
- void OnUserConnect(LocalUser* user) CXX11_OVERRIDE
- {
- IOHook* hook = user->eh.GetIOHook();
- if (hook && hook->prov->creator == this)
- static_cast(hook)->TellCiphersAndFingerprint(user);
- }
-
ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
{
- if ((user->eh.GetIOHook()) && (user->eh.GetIOHook()->prov->creator == this))
- {
- GnuTLSIOHook* iohook = static_cast(user->eh.GetIOHook());
- if (!iohook->IsHandshakeDone())
- return MOD_RES_DENY;
- }
-
+ const GnuTLSIOHook* const iohook = static_cast(user->eh.GetModHook(this));
+ if ((iohook) && (!iohook->IsHandshakeDone()))
+ return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
};