Implemented SSL connection for WebAdmin.
Fixes FS-319.
This commit is contained in:
parent
a04cb6d146
commit
272c232efb
4
MCServer/.gitignore
vendored
4
MCServer/.gitignore
vendored
@ -30,3 +30,7 @@ motd.txt
|
|||||||
*.xml
|
*.xml
|
||||||
mcserver_api.lua
|
mcserver_api.lua
|
||||||
|
|
||||||
|
# Ignore the webadmin certs / privkey, so that no-one commits theirs by accident:
|
||||||
|
webadmin/httpscert.crt
|
||||||
|
webadmin/httpskey.pem
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "HTTPMessage.h"
|
#include "HTTPMessage.h"
|
||||||
#include "HTTPConnection.h"
|
#include "HTTPConnection.h"
|
||||||
#include "HTTPFormParser.h"
|
#include "HTTPFormParser.h"
|
||||||
|
#include "SslHTTPConnection.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -123,8 +124,30 @@ class cDebugCallbacks :
|
|||||||
cHTTPServer::cHTTPServer(void) :
|
cHTTPServer::cHTTPServer(void) :
|
||||||
m_ListenThreadIPv4(*this, cSocket::IPv4, "WebServer IPv4"),
|
m_ListenThreadIPv4(*this, cSocket::IPv4, "WebServer IPv4"),
|
||||||
m_ListenThreadIPv6(*this, cSocket::IPv6, "WebServer IPv6"),
|
m_ListenThreadIPv6(*this, cSocket::IPv6, "WebServer IPv6"),
|
||||||
m_Callbacks(NULL)
|
m_Callbacks(NULL),
|
||||||
|
m_Cert(new cX509Cert),
|
||||||
|
m_CertPrivKey(new cPublicKey)
|
||||||
{
|
{
|
||||||
|
AString CertFile = cFile::ReadWholeFile("webadmin/httpscert.crt");
|
||||||
|
AString KeyFile = cFile::ReadWholeFile("webadmin/httpskey.pem");
|
||||||
|
if (!CertFile.empty() && !KeyFile.empty())
|
||||||
|
{
|
||||||
|
int res = m_Cert->Parse(CertFile.data(), CertFile.size());
|
||||||
|
if (res == 0)
|
||||||
|
{
|
||||||
|
int res2 = m_CertPrivKey->ParsePrivate(KeyFile.data(), KeyFile.size(), "");
|
||||||
|
if (res2 != 0)
|
||||||
|
{
|
||||||
|
// Reading the private key failed, reset the cert:
|
||||||
|
LOGWARNING("WebAdmin: Cannot read HTTPS certificate private key: -0x%x", -res2);
|
||||||
|
m_Cert.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGWARNING("WebAdmin: Cannot read HTTPS certificate: -0x%x", -res);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -195,7 +218,15 @@ void cHTTPServer::Stop(void)
|
|||||||
|
|
||||||
void cHTTPServer::OnConnectionAccepted(cSocket & a_Socket)
|
void cHTTPServer::OnConnectionAccepted(cSocket & a_Socket)
|
||||||
{
|
{
|
||||||
cHTTPConnection * Connection = new cHTTPConnection(*this);
|
cHTTPConnection * Connection;
|
||||||
|
if (m_Cert.get() != NULL)
|
||||||
|
{
|
||||||
|
Connection = new cSslHTTPConnection(*this, m_Cert, m_CertPrivKey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Connection = new cHTTPConnection(*this);
|
||||||
|
}
|
||||||
m_SocketThreads.AddClient(a_Socket, Connection);
|
m_SocketThreads.AddClient(a_Socket, Connection);
|
||||||
cCSLock Lock(m_CSConnections);
|
cCSLock Lock(m_CSConnections);
|
||||||
m_Connections.push_back(Connection);
|
m_Connections.push_back(Connection);
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
#include "../OSSupport/ListenThread.h"
|
#include "../OSSupport/ListenThread.h"
|
||||||
#include "../OSSupport/SocketThreads.h"
|
#include "../OSSupport/SocketThreads.h"
|
||||||
#include "inifile/iniFile.h"
|
#include "inifile/iniFile.h"
|
||||||
|
#include "PolarSSL++/RsaPrivateKey.h"
|
||||||
|
#include "PolarSSL++/PublicKey.h"
|
||||||
|
#include "PolarSSL++/X509Cert.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -66,6 +69,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class cHTTPConnection;
|
friend class cHTTPConnection;
|
||||||
|
friend class cSslHTTPConnection;
|
||||||
|
|
||||||
cListenThread m_ListenThreadIPv4;
|
cListenThread m_ListenThreadIPv4;
|
||||||
cListenThread m_ListenThreadIPv6;
|
cListenThread m_ListenThreadIPv6;
|
||||||
@ -78,6 +82,12 @@ protected:
|
|||||||
/// The callbacks to call for various events
|
/// The callbacks to call for various events
|
||||||
cCallbacks * m_Callbacks;
|
cCallbacks * m_Callbacks;
|
||||||
|
|
||||||
|
/** The server certificate to use for the SSL connections */
|
||||||
|
cX509CertPtr m_Cert;
|
||||||
|
|
||||||
|
/** The private key for m_Cert. Despite the class name, this is the PRIVATE key. */
|
||||||
|
cPublicKeyPtr m_CertPrivKey;
|
||||||
|
|
||||||
|
|
||||||
// cListenThread::cCallback overrides:
|
// cListenThread::cCallback overrides:
|
||||||
virtual void OnConnectionAccepted(cSocket & a_Socket) override;
|
virtual void OnConnectionAccepted(cSocket & a_Socket) override;
|
||||||
|
103
src/HTTPServer/SslHTTPConnection.cpp
Normal file
103
src/HTTPServer/SslHTTPConnection.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
|
||||||
|
// SslHTTPConnection.cpp
|
||||||
|
|
||||||
|
// Implements the cSslHTTPConnection class representing a HTTP connection made over a SSL link
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "SslHTTPConnection.h"
|
||||||
|
#include "HTTPServer.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cSslHTTPConnection::cSslHTTPConnection(cHTTPServer & a_HTTPServer, const cX509CertPtr & a_Cert, const cPublicKeyPtr & a_PrivateKey) :
|
||||||
|
super(a_HTTPServer),
|
||||||
|
m_Ssl(64000),
|
||||||
|
m_Cert(a_Cert),
|
||||||
|
m_PrivateKey(a_PrivateKey)
|
||||||
|
{
|
||||||
|
m_Ssl.Initialize(false);
|
||||||
|
m_Ssl.SetOwnCert(a_Cert, a_PrivateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSslHTTPConnection::DataReceived(const char * a_Data, size_t a_Size)
|
||||||
|
{
|
||||||
|
// If there is outgoing data in the queue, notify the server that it should write it out:
|
||||||
|
if (!m_OutgoingData.empty())
|
||||||
|
{
|
||||||
|
m_HTTPServer.NotifyConnectionWrite(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the received data:
|
||||||
|
const char * Data = a_Data;
|
||||||
|
size_t Size = a_Size;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
// Try to write as many bytes into Ssl's "incoming" buffer as possible:
|
||||||
|
size_t BytesWritten = 0;
|
||||||
|
if (Size > 0)
|
||||||
|
{
|
||||||
|
BytesWritten = m_Ssl.WriteIncoming(Data, Size);
|
||||||
|
Data += BytesWritten;
|
||||||
|
Size -= BytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to read as many bytes from SSL's decryption as possible:
|
||||||
|
char Buffer[32000];
|
||||||
|
int NumRead = m_Ssl.ReadPlain(Buffer, sizeof(Buffer));
|
||||||
|
if (NumRead > 0)
|
||||||
|
{
|
||||||
|
super::DataReceived(Buffer, (size_t)NumRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If both failed, bail out:
|
||||||
|
if ((BytesWritten == 0) && (NumRead <= 0))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSslHTTPConnection::GetOutgoingData(AString & a_Data)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
// Write as many bytes from our buffer to SSL's encryption as possible:
|
||||||
|
int NumWritten = 0;
|
||||||
|
if (!m_OutgoingData.empty())
|
||||||
|
{
|
||||||
|
NumWritten = m_Ssl.WritePlain(m_OutgoingData.data(), m_OutgoingData.size());
|
||||||
|
if (NumWritten > 0)
|
||||||
|
{
|
||||||
|
m_OutgoingData.erase(0, (size_t)NumWritten);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read as many bytes from SSL's "outgoing" buffer as possible:
|
||||||
|
char Buffer[32000];
|
||||||
|
size_t NumBytes = m_Ssl.ReadOutgoing(Buffer, sizeof(Buffer));
|
||||||
|
if (NumBytes > 0)
|
||||||
|
{
|
||||||
|
a_Data.append(Buffer, NumBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If both failed, bail out:
|
||||||
|
if ((NumWritten <= 0) && (NumBytes == 0))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
45
src/HTTPServer/SslHTTPConnection.h
Normal file
45
src/HTTPServer/SslHTTPConnection.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
// SslHTTPConnection.h
|
||||||
|
|
||||||
|
// Declared the cSslHTTPConnection class representing a HTTP connection made over a SSL link
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "HTTPConnection.h"
|
||||||
|
#include "PolarSSL++/BufferedSslContext.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cSslHTTPConnection :
|
||||||
|
public cHTTPConnection
|
||||||
|
{
|
||||||
|
typedef cHTTPConnection super;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Creates a new connection on the specified server; sends the specified cert as the server certificate,
|
||||||
|
uses the private key for decryption. a_Private key is, despite the class name, a PRIVATE key for the cert. */
|
||||||
|
cSslHTTPConnection(cHTTPServer & a_HTTPServer, const cX509CertPtr & a_Cert, const cPublicKeyPtr & a_PrivateKey);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cBufferedSslContext m_Ssl;
|
||||||
|
|
||||||
|
/** The certificate to send to the client */
|
||||||
|
cX509CertPtr m_Cert;
|
||||||
|
|
||||||
|
/** The private key used for the certificate */
|
||||||
|
cPublicKeyPtr m_PrivateKey;
|
||||||
|
|
||||||
|
// cHTTPConnection overrides:
|
||||||
|
virtual void DataReceived (const char * a_Data, size_t a_Size) override; // Data is received from the client
|
||||||
|
virtual void GetOutgoingData(AString & a_Data) override; // Data can be sent to client
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user