*/
const bool allowrenego;
+ /** Rough max size of records to send
+ */
+ const unsigned int outrecsize;
+
static int error_callback(const char* str, size_t len, void* u)
{
Profile* profile = reinterpret_cast<Profile*>(u);
, ctx(SSL_CTX_new(SSLv23_server_method()))
, clictx(SSL_CTX_new(SSLv23_client_method()))
, allowrenego(tag->getBool("renegotiation", true))
+ , outrecsize(tag->getInt("outrecsize", 2048, 512, 16384))
{
if ((!ctx.SetDH(dh)) || (!clictx.SetDH(dh)))
throw Exception("Couldn't set DH parameters");
SSL* CreateClientSession() { return clictx.CreateClientSession(); }
const EVP_MD* GetDigest() { return digest; }
bool AllowRenegotiation() const { return allowrenego; }
+ unsigned int GetOutgoingRecordSize() const { return outrecsize; }
};
}
}
}
- int OnStreamSocketWrite(StreamSocket* user, std::string& buffer) CXX11_OVERRIDE
+ int OnStreamSocketWrite(StreamSocket* user) CXX11_OVERRIDE
{
// Finish handshake if needed
int prepret = PrepareIO(user);
data_to_write = true;
// Session is ready for transferring application data
+ StreamSocket::SendQueue& sendq = user->GetSendQ();
+ while (!sendq.empty())
{
ERR_clear_error();
+ FlattenSendQueue(sendq, profile->GetOutgoingRecordSize());
+ const StreamSocket::SendQueue::Element& buffer = sendq.front();
int ret = SSL_write(sess, buffer.data(), buffer.size());
#ifdef INSPIRCD_OPENSSL_ENABLE_RENEGO_DETECTION
if (ret == (int)buffer.length())
{
- data_to_write = false;
- SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE);
- return 1;
+ // Wrote entire record, continue sending
+ sendq.pop_front();
}
else if (ret > 0)
{
- buffer.erase(0, ret);
+ sendq.erase_front(ret);
SocketEngine::ChangeEventMask(user, FD_WANT_SINGLE_WRITE);
return 0;
}
}
}
}
+
+ data_to_write = false;
+ SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE);
+ return 1;
}
void TellCiphersAndFingerprint(LocalUser* user)
out.append(SSL_get_version(sess)).push_back('-');
out.append(SSL_get_cipher(sess));
}
+
+ bool IsHandshakeDone() const { return (status == ISSL_OPEN); }
};
static void StaticSSLInfoCallback(const SSL* ssl, int where, int rc)
void init() CXX11_OVERRIDE
{
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "OpenSSL lib version \"%s\" module was compiled for \"" OPENSSL_VERSION_TEXT "\"", SSLeay_version(SSLEAY_VERSION));
+
// Register application specific data
char exdatastr[] = "inspircd";
exdataindex = SSL_get_ex_new_index(0, exdatastr, NULL, NULL, NULL);
}
}
+ 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;
+ }
+
+ return MOD_RES_PASSTHRU;
+ }
+
Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides SSL support for clients", VF_VENDOR);