commit
e0c56b7522
4
MCServer/.gitignore
vendored
4
MCServer/.gitignore
vendored
@ -30,3 +30,7 @@ motd.txt
|
||||
*.xml
|
||||
mcserver_api.lua
|
||||
|
||||
# Ignore the webadmin certs / privkey, so that no-one commits theirs by accident:
|
||||
webadmin/httpscert.crt
|
||||
webadmin/httpskey.pem
|
||||
|
||||
|
@ -0,0 +1,11 @@
|
||||
echo This script generates the certificate and private key for the https webadmin
|
||||
echo Note that the generated certificate is self-signed, and therefore not trusted by browsers
|
||||
echo Note that this script requires openssl to be installed and in PATH
|
||||
echo.
|
||||
echo When OpenSSL asks you for Common Name, you need to enter the fully qualified domain name of the server, that is, e. g. gallery.xoft.cz
|
||||
echo.
|
||||
echo If OpenSSL fails with an error, "WARNING: can't open config file: /usr/local/ssl/openssl.cnf", you need to run this script as an administrator
|
||||
echo.
|
||||
|
||||
openssl req -x509 -newkey rsa:2048 -keyout httpskey.pem -out httpscert.crt -days 3650 -nodes
|
||||
pause
|
10
MCServer/webadmin/GenerateSelfSignedHTTPSCertUsingOpenssl.sh
Executable file
10
MCServer/webadmin/GenerateSelfSignedHTTPSCertUsingOpenssl.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "This script generates the certificate and private key for the https webadmin"
|
||||
echo "Note that the generated certificate is self-signed, and therefore not trusted by browsers"
|
||||
echo "Note that this script requires openssl to be installed and in PATH"
|
||||
echo ""
|
||||
echo "When OpenSSL asks you for Common Name, you need to enter the fully qualified domain name of the server, that is, e. g. gallery.xoft.cz"
|
||||
echo ""
|
||||
|
||||
openssl req -x509 -newkey rsa:2048 -keyout httpskey.pem -out httpscert.crt -days 3650 -nodes
|
@ -38,9 +38,9 @@ set(SHARED_SRC
|
||||
../../src/MCLogger.cpp
|
||||
../../src/PolarSSL++/AesCfb128Decryptor.cpp
|
||||
../../src/PolarSSL++/AesCfb128Encryptor.cpp
|
||||
../../src/PolarSSL++/CryptoKey.cpp
|
||||
../../src/PolarSSL++/CtrDrbgContext.cpp
|
||||
../../src/PolarSSL++/EntropyContext.cpp
|
||||
../../src/PolarSSL++/PublicKey.cpp
|
||||
../../src/PolarSSL++/RsaPrivateKey.cpp
|
||||
)
|
||||
set(SHARED_HDR
|
||||
@ -50,9 +50,9 @@ set(SHARED_HDR
|
||||
../../src/MCLogger.h
|
||||
../../src/PolarSSL++/AesCfb128Decryptor.h
|
||||
../../src/PolarSSL++/AesCfb128Encryptor.h
|
||||
../../src/PolarSSL++/CryptoKey.h
|
||||
../../src/PolarSSL++/CtrDrbgContext.h
|
||||
../../src/PolarSSL++/EntropyContext.h
|
||||
../../src/PolarSSL++/PublicKey.h
|
||||
../../src/PolarSSL++/RsaPrivateKey.h
|
||||
)
|
||||
set(SHARED_OSS_SRC
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "Connection.h"
|
||||
#include "Server.h"
|
||||
#include <iostream>
|
||||
#include "PolarSSL++/PublicKey.h"
|
||||
#include "PolarSSL++/CryptoKey.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h> // For _mkdir()
|
||||
@ -2900,7 +2900,7 @@ void cConnection::SendEncryptionKeyResponse(const AString & a_ServerPublicKey, c
|
||||
Byte SharedSecret[16];
|
||||
Byte EncryptedSecret[128];
|
||||
memset(SharedSecret, 0, sizeof(SharedSecret)); // Use all zeroes for the initial secret
|
||||
cPublicKey PubKey(a_ServerPublicKey);
|
||||
cCryptoKey PubKey(a_ServerPublicKey);
|
||||
int res = PubKey.Encrypt(SharedSecret, sizeof(SharedSecret), EncryptedSecret, sizeof(EncryptedSecret));
|
||||
if (res < 0)
|
||||
{
|
||||
|
@ -30,25 +30,25 @@ public:
|
||||
cByteBuffer(size_t a_BufferSize);
|
||||
~cByteBuffer();
|
||||
|
||||
/// Writes the bytes specified to the ringbuffer. Returns true if successful, false if not
|
||||
/** Writes the bytes specified to the ringbuffer. Returns true if successful, false if not */
|
||||
bool Write(const void * a_Bytes, size_t a_Count);
|
||||
|
||||
/// Returns the number of bytes that can be successfully written to the ringbuffer
|
||||
/** Returns the number of bytes that can be successfully written to the ringbuffer */
|
||||
size_t GetFreeSpace(void) const;
|
||||
|
||||
/// Returns the number of bytes that are currently in the ringbuffer. Note GetReadableBytes()
|
||||
/** Returns the number of bytes that are currently in the ringbuffer. Note GetReadableBytes() */
|
||||
size_t GetUsedSpace(void) const;
|
||||
|
||||
/// Returns the number of bytes that are currently available for reading (may be less than UsedSpace due to some data having been read already)
|
||||
/** Returns the number of bytes that are currently available for reading (may be less than UsedSpace due to some data having been read already) */
|
||||
size_t GetReadableSpace(void) const;
|
||||
|
||||
/// Returns the current data start index. For debugging purposes.
|
||||
/** Returns the current data start index. For debugging purposes. */
|
||||
size_t GetDataStart(void) const { return m_DataStart; }
|
||||
|
||||
/// Returns true if the specified amount of bytes are available for reading
|
||||
/** Returns true if the specified amount of bytes are available for reading */
|
||||
bool CanReadBytes(size_t a_Count) const;
|
||||
|
||||
/// Returns true if the specified amount of bytes are available for writing
|
||||
/** Returns true if the specified amount of bytes are available for writing */
|
||||
bool CanWriteBytes(size_t a_Count) const;
|
||||
|
||||
// Read the specified datatype and advance the read pointer; return true if successfully read:
|
||||
@ -65,7 +65,7 @@ public:
|
||||
bool ReadVarUTF8String (AString & a_Value); // string length as VarInt, then string as UTF-8
|
||||
bool ReadLEInt (int & a_Value);
|
||||
|
||||
/// Reads VarInt, assigns it to anything that can be assigned from an UInt32 (unsigned short, char, Byte, double, ...)
|
||||
/** Reads VarInt, assigns it to anything that can be assigned from an UInt32 (unsigned short, char, Byte, double, ...) */
|
||||
template <typename T> bool ReadVarInt(T & a_Value)
|
||||
{
|
||||
UInt32 v;
|
||||
@ -91,37 +91,37 @@ public:
|
||||
bool WriteVarUTF8String (const AString & a_Value); // string length as VarInt, then string as UTF-8
|
||||
bool WriteLEInt (int a_Value);
|
||||
|
||||
/// Reads a_Count bytes into a_Buffer; returns true if successful
|
||||
/** Reads a_Count bytes into a_Buffer; returns true if successful */
|
||||
bool ReadBuf(void * a_Buffer, size_t a_Count);
|
||||
|
||||
/// Writes a_Count bytes into a_Buffer; returns true if successful
|
||||
/** Writes a_Count bytes into a_Buffer; returns true if successful */
|
||||
bool WriteBuf(const void * a_Buffer, size_t a_Count);
|
||||
|
||||
/// Reads a_Count bytes into a_String; returns true if successful
|
||||
/** Reads a_Count bytes into a_String; returns true if successful */
|
||||
bool ReadString(AString & a_String, size_t a_Count);
|
||||
|
||||
/// Reads 2 * a_NumChars bytes and interprets it as a UTF16-BE string, converting it into UTF8 string a_String
|
||||
/** Reads 2 * a_NumChars bytes and interprets it as a UTF16-BE string, converting it into UTF8 string a_String */
|
||||
bool ReadUTF16String(AString & a_String, size_t a_NumChars);
|
||||
|
||||
/// Skips reading by a_Count bytes; returns false if not enough bytes in the ringbuffer
|
||||
/** Skips reading by a_Count bytes; returns false if not enough bytes in the ringbuffer */
|
||||
bool SkipRead(size_t a_Count);
|
||||
|
||||
/// Reads all available data into a_Data
|
||||
/** Reads all available data into a_Data */
|
||||
void ReadAll(AString & a_Data);
|
||||
|
||||
/// Reads the specified number of bytes and writes it into the destinatio bytebuffer. Returns true on success.
|
||||
/** Reads the specified number of bytes and writes it into the destinatio bytebuffer. Returns true on success. */
|
||||
bool ReadToByteBuffer(cByteBuffer & a_Dst, size_t a_NumBytes);
|
||||
|
||||
/// Removes the bytes that have been read from the ringbuffer
|
||||
/** Removes the bytes that have been read from the ringbuffer */
|
||||
void CommitRead(void);
|
||||
|
||||
/// Restarts next reading operation at the start of the ringbuffer
|
||||
/** Restarts next reading operation at the start of the ringbuffer */
|
||||
void ResetRead(void);
|
||||
|
||||
/// Re-reads the data that has been read since the last commit to the current readpos. Used by ProtoProxy to duplicate communication
|
||||
/** Re-reads the data that has been read since the last commit to the current readpos. Used by ProtoProxy to duplicate communication */
|
||||
void ReadAgain(AString & a_Out);
|
||||
|
||||
/// Checks if the internal state is valid (read and write positions in the correct bounds) using ASSERTs
|
||||
/** Checks if the internal state is valid (read and write positions in the correct bounds) using ASSERTs */
|
||||
void CheckValid(void) const;
|
||||
|
||||
protected:
|
||||
@ -136,7 +136,7 @@ protected:
|
||||
size_t m_WritePos; // Where the data ends in the ringbuffer
|
||||
size_t m_ReadPos; // Where the next read will start in the ringbuffer
|
||||
|
||||
/// Advances the m_ReadPos by a_Count bytes
|
||||
/** Advances the m_ReadPos by a_Count bytes */
|
||||
void AdvanceReadPos(size_t a_Count);
|
||||
} ;
|
||||
|
||||
|
@ -2676,12 +2676,13 @@ void cClientHandle::PacketError(unsigned char a_PacketType)
|
||||
|
||||
|
||||
|
||||
void cClientHandle::DataReceived(const char * a_Data, size_t a_Size)
|
||||
bool cClientHandle::DataReceived(const char * a_Data, size_t a_Size)
|
||||
{
|
||||
// Data is received from the client, store it in the buffer to be processed by the Tick thread:
|
||||
m_TimeSinceLastPacket = 0;
|
||||
cCSLock Lock(m_CSIncomingData);
|
||||
m_IncomingData.append(a_Data, a_Size);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -390,7 +390,7 @@ private:
|
||||
void HandleAnvilItemName(const char * a_Data, size_t a_Length);
|
||||
|
||||
// cSocketThreads::cCallback overrides:
|
||||
virtual void DataReceived (const char * a_Data, size_t a_Size) override; // Data is received from the client
|
||||
virtual bool 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
|
||||
virtual void SocketClosed (void) override; // The socket has been closed for any reason
|
||||
}; // tolua_export
|
||||
|
@ -26,6 +26,7 @@ cHTTPConnection::cHTTPConnection(cHTTPServer & a_HTTPServer) :
|
||||
|
||||
cHTTPConnection::~cHTTPConnection()
|
||||
{
|
||||
// LOGD("HTTP: Connection deleting: %p", this);
|
||||
delete m_CurrentRequest;
|
||||
}
|
||||
|
||||
@ -144,7 +145,7 @@ void cHTTPConnection::Terminate(void)
|
||||
|
||||
|
||||
|
||||
void cHTTPConnection::DataReceived(const char * a_Data, size_t a_Size)
|
||||
bool cHTTPConnection::DataReceived(const char * a_Data, size_t a_Size)
|
||||
{
|
||||
switch (m_State)
|
||||
{
|
||||
@ -162,12 +163,12 @@ void cHTTPConnection::DataReceived(const char * a_Data, size_t a_Size)
|
||||
m_CurrentRequest = NULL;
|
||||
m_State = wcsInvalid;
|
||||
m_HTTPServer.CloseConnection(*this);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (m_CurrentRequest->IsInHeaders())
|
||||
{
|
||||
// The request headers are not yet complete
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// The request has finished parsing its headers successfully, notify of it:
|
||||
@ -183,13 +184,12 @@ void cHTTPConnection::DataReceived(const char * a_Data, size_t a_Size)
|
||||
// Process the rest of the incoming data into the request body:
|
||||
if (a_Size > BytesConsumed)
|
||||
{
|
||||
DataReceived(a_Data + BytesConsumed, a_Size - BytesConsumed);
|
||||
return cHTTPConnection::DataReceived(a_Data + BytesConsumed, a_Size - BytesConsumed);
|
||||
}
|
||||
else
|
||||
{
|
||||
DataReceived("", 0); // If the request has zero body length, let it be processed right-away
|
||||
return cHTTPConnection::DataReceived("", 0); // If the request has zero body length, let it be processed right-away
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case wcsRecvBody:
|
||||
@ -209,7 +209,7 @@ void cHTTPConnection::DataReceived(const char * a_Data, size_t a_Size)
|
||||
{
|
||||
m_State = wcsInvalid;
|
||||
m_HTTPServer.CloseConnection(*this);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
delete m_CurrentRequest;
|
||||
m_CurrentRequest = NULL;
|
||||
@ -223,6 +223,7 @@ void cHTTPConnection::DataReceived(const char * a_Data, size_t a_Size)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -91,9 +91,15 @@ protected:
|
||||
|
||||
|
||||
// cSocketThreads::cCallback 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
|
||||
virtual void SocketClosed (void) override; // The socket has been closed for any reason
|
||||
/** Data is received from the client.
|
||||
Returns true if the connection has been closed as the result of parsing the data. */
|
||||
virtual bool DataReceived(const char * a_Data, size_t a_Size) override;
|
||||
|
||||
/** Data can be sent to client */
|
||||
virtual void GetOutgoingData(AString & a_Data) override;
|
||||
|
||||
/** The socket has been closed for any reason */
|
||||
virtual void SocketClosed(void) override;
|
||||
} ;
|
||||
|
||||
typedef std::vector<cHTTPConnection *> cHTTPConnections;
|
||||
|
@ -201,7 +201,7 @@ size_t cHTTPRequest::ParseRequestLine(const char * a_Data, size_t a_Size)
|
||||
return AString::npos;
|
||||
}
|
||||
// Check that there's HTTP/version at the end
|
||||
if (strncmp(a_Data + URLEnd + 1, "HTTP/1.", 7) != 0)
|
||||
if (strncmp(m_IncomingHeaderData.c_str() + URLEnd + 1, "HTTP/1.", 7) != 0)
|
||||
{
|
||||
m_IsValid = false;
|
||||
return AString::npos;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "HTTPMessage.h"
|
||||
#include "HTTPConnection.h"
|
||||
#include "HTTPFormParser.h"
|
||||
#include "SslHTTPConnection.h"
|
||||
|
||||
|
||||
|
||||
@ -142,6 +143,41 @@ cHTTPServer::~cHTTPServer()
|
||||
|
||||
bool cHTTPServer::Initialize(const AString & a_PortsIPv4, const AString & a_PortsIPv6)
|
||||
{
|
||||
// Read the HTTPS cert + key:
|
||||
AString CertFile = cFile::ReadWholeFile("webadmin/httpscert.crt");
|
||||
AString KeyFile = cFile::ReadWholeFile("webadmin/httpskey.pem");
|
||||
if (!CertFile.empty() && !KeyFile.empty())
|
||||
{
|
||||
m_Cert.reset(new cX509Cert);
|
||||
int res = m_Cert->Parse(CertFile.data(), CertFile.size());
|
||||
if (res == 0)
|
||||
{
|
||||
m_CertPrivKey.reset(new cCryptoKey);
|
||||
int res2 = m_CertPrivKey->ParsePrivate(KeyFile.data(), KeyFile.size(), "");
|
||||
if (res2 != 0)
|
||||
{
|
||||
// Reading the private key failed, reset the cert:
|
||||
LOGWARNING("WebServer: Cannot read HTTPS certificate private key: -0x%x", -res2);
|
||||
m_Cert.reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGWARNING("WebServer: Cannot read HTTPS certificate: -0x%x", -res);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify the admin about the HTTPS / HTTP status
|
||||
if (m_Cert.get() == NULL)
|
||||
{
|
||||
LOGWARNING("WebServer: The server is running in unsecure HTTP mode.");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGINFO("WebServer: The server is running in secure HTTPS mode.");
|
||||
}
|
||||
|
||||
// Open up requested ports:
|
||||
bool HasAnyPort;
|
||||
HasAnyPort = m_ListenThreadIPv4.Initialize(a_PortsIPv4);
|
||||
HasAnyPort = m_ListenThreadIPv6.Initialize(a_PortsIPv6) || HasAnyPort;
|
||||
@ -195,7 +231,15 @@ void cHTTPServer::Stop(void)
|
||||
|
||||
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);
|
||||
cCSLock Lock(m_CSConnections);
|
||||
m_Connections.push_back(Connection);
|
||||
|
@ -12,6 +12,9 @@
|
||||
#include "../OSSupport/ListenThread.h"
|
||||
#include "../OSSupport/SocketThreads.h"
|
||||
#include "inifile/iniFile.h"
|
||||
#include "PolarSSL++/RsaPrivateKey.h"
|
||||
#include "PolarSSL++/CryptoKey.h"
|
||||
#include "PolarSSL++/X509Cert.h"
|
||||
|
||||
|
||||
|
||||
@ -66,6 +69,7 @@ public:
|
||||
|
||||
protected:
|
||||
friend class cHTTPConnection;
|
||||
friend class cSslHTTPConnection;
|
||||
|
||||
cListenThread m_ListenThreadIPv4;
|
||||
cListenThread m_ListenThreadIPv6;
|
||||
@ -78,6 +82,12 @@ protected:
|
||||
/// The callbacks to call for various events
|
||||
cCallbacks * m_Callbacks;
|
||||
|
||||
/** The server certificate to use for the SSL connections */
|
||||
cX509CertPtr m_Cert;
|
||||
|
||||
/** The private key for m_Cert. */
|
||||
cCryptoKeyPtr m_CertPrivKey;
|
||||
|
||||
|
||||
// cListenThread::cCallback overrides:
|
||||
virtual void OnConnectionAccepted(cSocket & a_Socket) override;
|
||||
|
107
src/HTTPServer/SslHTTPConnection.cpp
Normal file
107
src/HTTPServer/SslHTTPConnection.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
|
||||
// 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 cCryptoKeyPtr & 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool 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)
|
||||
{
|
||||
if (super::DataReceived(Buffer, (size_t)NumRead))
|
||||
{
|
||||
// The socket has been closed, and the object is already deleted. Bail out.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If both failed, bail out:
|
||||
if ((BytesWritten == 0) && (NumRead <= 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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. */
|
||||
cSslHTTPConnection(cHTTPServer & a_HTTPServer, const cX509CertPtr & a_Cert, const cCryptoKeyPtr & a_PrivateKey);
|
||||
|
||||
protected:
|
||||
cBufferedSslContext m_Ssl;
|
||||
|
||||
/** The certificate to send to the client */
|
||||
cX509CertPtr m_Cert;
|
||||
|
||||
/** The private key used for the certificate */
|
||||
cCryptoKeyPtr m_PrivateKey;
|
||||
|
||||
// cHTTPConnection overrides:
|
||||
virtual bool 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
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
@ -63,8 +63,10 @@ public:
|
||||
// Force a virtual destructor in all subclasses:
|
||||
virtual ~cCallback() {}
|
||||
|
||||
/** Called when data is received from the remote party */
|
||||
virtual void DataReceived(const char * a_Data, size_t a_Size) = 0;
|
||||
/** Called when data is received from the remote party.
|
||||
SocketThreads does not care about the return value, others can use it for their specific purpose -
|
||||
for example HTTPServer uses it to signal if the connection was terminated as a result of the data received. */
|
||||
virtual bool DataReceived(const char * a_Data, size_t a_Size) = 0;
|
||||
|
||||
/** Called when data can be sent to remote party
|
||||
The function is supposed to *set* outgoing data to a_Data (overwrite) */
|
||||
|
@ -20,6 +20,37 @@ cBufferedSslContext::cBufferedSslContext(size_t a_BufferSize):
|
||||
|
||||
|
||||
|
||||
size_t cBufferedSslContext::WriteIncoming(const void * a_Data, size_t a_NumBytes)
|
||||
{
|
||||
size_t NumBytes = std::min(m_IncomingData.GetFreeSpace(), a_NumBytes);
|
||||
if (NumBytes > 0)
|
||||
{
|
||||
m_IncomingData.Write(a_Data, NumBytes);
|
||||
return NumBytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
size_t cBufferedSslContext::ReadOutgoing(void * a_Data, size_t a_DataMaxSize)
|
||||
{
|
||||
size_t NumBytes = std::min(m_OutgoingData.GetReadableSpace(), a_DataMaxSize);
|
||||
if (NumBytes > 0)
|
||||
{
|
||||
m_OutgoingData.ReadBuf(a_Data, NumBytes);
|
||||
m_OutgoingData.CommitRead();
|
||||
return NumBytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cBufferedSslContext::ReceiveEncrypted(unsigned char * a_Buffer, size_t a_NumBytes)
|
||||
{
|
||||
// Called when PolarSSL wants to read encrypted data from the SSL peer
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
project (MCServer)
|
||||
|
||||
@ -11,8 +10,8 @@ set(SOURCES
|
||||
BufferedSslContext.cpp
|
||||
CallbackSslContext.cpp
|
||||
CtrDrbgContext.cpp
|
||||
CryptoKey.cpp
|
||||
EntropyContext.cpp
|
||||
PublicKey.cpp
|
||||
RsaPrivateKey.cpp
|
||||
Sha1Checksum.cpp
|
||||
SslContext.cpp
|
||||
@ -26,8 +25,8 @@ set(HEADERS
|
||||
BufferedSslContext.h
|
||||
CallbackSslContext.h
|
||||
CtrDrbgContext.h
|
||||
CryptoKey.h
|
||||
EntropyContext.h
|
||||
PublicKey.h
|
||||
RsaPrivateKey.h
|
||||
SslContext.h
|
||||
Sha1Checksum.h
|
||||
|
149
src/PolarSSL++/CryptoKey.cpp
Normal file
149
src/PolarSSL++/CryptoKey.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
|
||||
// CryptoKey.cpp
|
||||
|
||||
// Implements the cCryptoKey class representing a RSA public key in PolarSSL
|
||||
|
||||
#include "Globals.h"
|
||||
#include "CryptoKey.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cCryptoKey::cCryptoKey(void)
|
||||
{
|
||||
pk_init(&m_Pk);
|
||||
m_CtrDrbg.Initialize("rsa_pubkey", 10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cCryptoKey::cCryptoKey(const AString & a_PublicKeyData)
|
||||
{
|
||||
pk_init(&m_Pk);
|
||||
m_CtrDrbg.Initialize("rsa_pubkey", 10);
|
||||
int res = ParsePublic(a_PublicKeyData.data(), a_PublicKeyData.size());
|
||||
if (res != 0)
|
||||
{
|
||||
LOGWARNING("Failed to parse public key: -0x%x", res);
|
||||
ASSERT(!"Cannot parse PubKey");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cCryptoKey::cCryptoKey(const AString & a_PrivateKeyData, const AString & a_Password)
|
||||
{
|
||||
pk_init(&m_Pk);
|
||||
m_CtrDrbg.Initialize("rsa_privkey", 11);
|
||||
int res = ParsePrivate(a_PrivateKeyData.data(), a_PrivateKeyData.size(), a_Password);
|
||||
if (res != 0)
|
||||
{
|
||||
LOGWARNING("Failed to parse private key: -0x%x", res);
|
||||
ASSERT(!"Cannot parse PubKey");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cCryptoKey::~cCryptoKey()
|
||||
{
|
||||
pk_free(&m_Pk);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cCryptoKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength)
|
||||
{
|
||||
ASSERT(IsValid());
|
||||
|
||||
size_t DecryptedLen = a_DecryptedMaxLength;
|
||||
int res = pk_decrypt(&m_Pk,
|
||||
a_EncryptedData, a_EncryptedLength,
|
||||
a_DecryptedData, &DecryptedLen, a_DecryptedMaxLength,
|
||||
ctr_drbg_random, m_CtrDrbg.GetInternal()
|
||||
);
|
||||
if (res != 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
return (int)DecryptedLen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cCryptoKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength)
|
||||
{
|
||||
ASSERT(IsValid());
|
||||
|
||||
size_t EncryptedLength = a_EncryptedMaxLength;
|
||||
int res = pk_encrypt(&m_Pk,
|
||||
a_PlainData, a_PlainLength, a_EncryptedData, &EncryptedLength, a_EncryptedMaxLength,
|
||||
ctr_drbg_random, m_CtrDrbg.GetInternal()
|
||||
);
|
||||
if (res != 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
return (int)EncryptedLength;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cCryptoKey::ParsePublic(const void * a_Data, size_t a_NumBytes)
|
||||
{
|
||||
ASSERT(!IsValid()); // Cannot parse a second key
|
||||
|
||||
return pk_parse_public_key(&m_Pk, (const unsigned char *)a_Data, a_NumBytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cCryptoKey::ParsePrivate(const void * a_Data, size_t a_NumBytes, const AString & a_Password)
|
||||
{
|
||||
ASSERT(!IsValid()); // Cannot parse a second key
|
||||
|
||||
if (a_Password.empty())
|
||||
{
|
||||
return pk_parse_key(&m_Pk, (const unsigned char *)a_Data, a_NumBytes, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return pk_parse_key(
|
||||
&m_Pk,
|
||||
(const unsigned char *)a_Data, a_NumBytes,
|
||||
(const unsigned char *)a_Password.c_str(), a_Password.size()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cCryptoKey::IsValid(void) const
|
||||
{
|
||||
return (pk_get_type(&m_Pk) != POLARSSL_PK_NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
76
src/PolarSSL++/CryptoKey.h
Normal file
76
src/PolarSSL++/CryptoKey.h
Normal file
@ -0,0 +1,76 @@
|
||||
|
||||
// CryptoKey.h
|
||||
|
||||
// Declares the cCryptoKey class representing a RSA public key in PolarSSL
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CtrDrbgContext.h"
|
||||
#include "polarssl/pk.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cCryptoKey
|
||||
{
|
||||
friend class cSslContext;
|
||||
|
||||
public:
|
||||
/** Constructs an empty key instance. Before use, it needs to be filled by ParsePublic() or ParsePrivate() */
|
||||
cCryptoKey(void);
|
||||
|
||||
/** Constructs the public key out of the DER- or PEM-encoded pubkey data */
|
||||
cCryptoKey(const AString & a_PublicKeyData);
|
||||
|
||||
/** Constructs the private key out of the DER- or PEM-encoded privkey data, with the specified password.
|
||||
If a_Password is empty, no password is assumed. */
|
||||
cCryptoKey(const AString & a_PrivateKeyData, const AString & a_Password);
|
||||
|
||||
~cCryptoKey();
|
||||
|
||||
/** Decrypts the data using the stored public key
|
||||
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
||||
Returns the number of bytes decrypted, or negative number for error. */
|
||||
int Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength);
|
||||
|
||||
/** Encrypts the data using the stored public key
|
||||
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
||||
Returns the number of bytes decrypted, or negative number for error. */
|
||||
int Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength);
|
||||
|
||||
/** Parses the specified data into a public key representation.
|
||||
The key can be DER- or PEM-encoded.
|
||||
Returns 0 on success, PolarSSL error code on failure. */
|
||||
int ParsePublic(const void * a_Data, size_t a_NumBytes);
|
||||
|
||||
/** Parses the specified data into a private key representation.
|
||||
If a_Password is empty, no password is assumed.
|
||||
The key can be DER- or PEM-encoded.
|
||||
Returns 0 on success, PolarSSL error code on failure. */
|
||||
int ParsePrivate(const void * a_Data, size_t a_NumBytes, const AString & a_Password);
|
||||
|
||||
/** Returns true if the contained key is valid. */
|
||||
bool IsValid(void) const;
|
||||
|
||||
protected:
|
||||
/** The PolarSSL representation of the key data */
|
||||
pk_context m_Pk;
|
||||
|
||||
/** The random generator used in encryption and decryption */
|
||||
cCtrDrbgContext m_CtrDrbg;
|
||||
|
||||
|
||||
/** Returns the internal context ptr. Only use in PolarSSL API calls. */
|
||||
pk_context * GetInternal(void) { return &m_Pk; }
|
||||
} ;
|
||||
|
||||
typedef SharedPtr<cCryptoKey> cCryptoKeyPtr;
|
||||
|
||||
|
||||
|
||||
|
@ -26,7 +26,7 @@ class cCtrDrbgContext
|
||||
{
|
||||
friend class cSslContext;
|
||||
friend class cRsaPrivateKey;
|
||||
friend class cPublicKey;
|
||||
friend class cCryptoKey;
|
||||
|
||||
public:
|
||||
/** Constructs the context with a new entropy context. */
|
||||
|
@ -1,73 +0,0 @@
|
||||
|
||||
// PublicKey.cpp
|
||||
|
||||
// Implements the cPublicKey class representing a RSA public key in PolarSSL
|
||||
|
||||
#include "Globals.h"
|
||||
#include "PublicKey.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPublicKey::cPublicKey(const AString & a_PublicKeyDER)
|
||||
{
|
||||
pk_init(&m_Pk);
|
||||
if (pk_parse_public_key(&m_Pk, (const Byte *)a_PublicKeyDER.data(), a_PublicKeyDER.size()) != 0)
|
||||
{
|
||||
ASSERT(!"Cannot parse PubKey");
|
||||
return;
|
||||
}
|
||||
m_CtrDrbg.Initialize("rsa_pubkey", 10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPublicKey::~cPublicKey()
|
||||
{
|
||||
pk_free(&m_Pk);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cPublicKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength)
|
||||
{
|
||||
size_t DecryptedLen = a_DecryptedMaxLength;
|
||||
int res = pk_decrypt(&m_Pk,
|
||||
a_EncryptedData, a_EncryptedLength,
|
||||
a_DecryptedData, &DecryptedLen, a_DecryptedMaxLength,
|
||||
ctr_drbg_random, m_CtrDrbg.GetInternal()
|
||||
);
|
||||
if (res != 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
return (int)DecryptedLen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cPublicKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength)
|
||||
{
|
||||
size_t EncryptedLength = a_EncryptedMaxLength;
|
||||
int res = pk_encrypt(&m_Pk,
|
||||
a_PlainData, a_PlainLength, a_EncryptedData, &EncryptedLength, a_EncryptedMaxLength,
|
||||
ctr_drbg_random, m_CtrDrbg.GetInternal()
|
||||
);
|
||||
if (res != 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
return (int)EncryptedLength;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
|
||||
// PublicKey.h
|
||||
|
||||
// Declares the cPublicKey class representing a RSA public key in PolarSSL
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CtrDrbgContext.h"
|
||||
#include "polarssl/pk.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cPublicKey
|
||||
{
|
||||
public:
|
||||
/** Constructs the public key out of the DER-encoded pubkey data */
|
||||
cPublicKey(const AString & a_PublicKeyDER);
|
||||
|
||||
~cPublicKey();
|
||||
|
||||
/** Decrypts the data using the stored public key
|
||||
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
||||
Returns the number of bytes decrypted, or negative number for error. */
|
||||
int Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength);
|
||||
|
||||
/** Encrypts the data using the stored public key
|
||||
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
||||
Returns the number of bytes decrypted, or negative number for error. */
|
||||
int Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength);
|
||||
|
||||
protected:
|
||||
/** The public key PolarSSL representation */
|
||||
pk_context m_Pk;
|
||||
|
||||
/** The random generator used in encryption and decryption */
|
||||
cCtrDrbgContext m_CtrDrbg;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
/** Encapsulates an RSA private key used in PKI cryptography */
|
||||
class cRsaPrivateKey
|
||||
{
|
||||
friend class cSslContext;
|
||||
|
||||
public:
|
||||
/** Creates a new empty object, the key is not assigned */
|
||||
cRsaPrivateKey(void);
|
||||
@ -51,8 +53,14 @@ protected:
|
||||
|
||||
/** The random generator used for generating the key and encryption / decryption */
|
||||
cCtrDrbgContext m_CtrDrbg;
|
||||
|
||||
|
||||
/** Returns the internal context ptr. Only use in PolarSSL API calls. */
|
||||
rsa_context * GetInternal(void) { return &m_Rsa; }
|
||||
} ;
|
||||
|
||||
typedef SharedPtr<cRsaPrivateKey> cRsaPrivateKeyPtr;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -40,7 +40,7 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr<cCtrDrbgContext> &
|
||||
if (m_IsValid)
|
||||
{
|
||||
LOGWARNING("SSL: Double initialization is not supported.");
|
||||
return POLARSSL_ERR_SSL_MALLOC_FAILED; // There is no return value well-suited for this, reuse this one.
|
||||
return POLARSSL_ERR_SSL_BAD_INPUT_DATA; // There is no return value well-suited for this, reuse this one.
|
||||
}
|
||||
|
||||
// Set the CtrDrbg context, create a new one if needed:
|
||||
@ -59,7 +59,7 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr<cCtrDrbgContext> &
|
||||
return res;
|
||||
}
|
||||
ssl_set_endpoint(&m_Ssl, a_IsClient ? SSL_IS_CLIENT : SSL_IS_SERVER);
|
||||
ssl_set_authmode(&m_Ssl, SSL_VERIFY_OPTIONAL);
|
||||
ssl_set_authmode(&m_Ssl, a_IsClient ? SSL_VERIFY_OPTIONAL : SSL_VERIFY_NONE); // Clients ask for server's cert but don't verify strictly; servers don't ask clients for certs by default
|
||||
ssl_set_rng(&m_Ssl, ctr_drbg_random, &m_CtrDrbg->m_CtrDrbg);
|
||||
ssl_set_bio(&m_Ssl, ReceiveEncrypted, this, SendEncrypted, this);
|
||||
|
||||
@ -70,6 +70,18 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr<cCtrDrbgContext> &
|
||||
ssl_set_dbg(&m_Ssl, &SSLDebugMessage, this);
|
||||
ssl_set_verify(&m_Ssl, &SSLVerifyCert, this);
|
||||
*/
|
||||
|
||||
/*
|
||||
// Set ciphersuite to the easiest one to decode, so that the connection can be wireshark-decoded:
|
||||
static const int CipherSuites[] =
|
||||
{
|
||||
TLS_RSA_WITH_RC4_128_MD5,
|
||||
TLS_RSA_WITH_RC4_128_SHA,
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
0, // Must be 0-terminated!
|
||||
};
|
||||
ssl_set_ciphersuites(&m_Ssl, CipherSuites);
|
||||
*/
|
||||
#endif
|
||||
|
||||
m_IsValid = true;
|
||||
@ -80,8 +92,56 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr<cCtrDrbgContext> &
|
||||
|
||||
|
||||
|
||||
void cSslContext::SetOwnCert(const cX509CertPtr & a_OwnCert, const cRsaPrivateKeyPtr & a_OwnCertPrivKey)
|
||||
{
|
||||
ASSERT(m_IsValid); // Call Initialize() first
|
||||
|
||||
// Check that both the cert and the key is valid:
|
||||
if ((a_OwnCert.get() == NULL) || (a_OwnCertPrivKey.get() == NULL))
|
||||
{
|
||||
LOGWARNING("SSL: Own certificate is not valid, skipping the set.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we have the cert stored for later, PolarSSL only uses the cert later on
|
||||
m_OwnCert = a_OwnCert;
|
||||
m_OwnCertPrivKey = a_OwnCertPrivKey;
|
||||
|
||||
// Set into the context:
|
||||
ssl_set_own_cert_rsa(&m_Ssl, m_OwnCert->GetInternal(), m_OwnCertPrivKey->GetInternal());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cSslContext::SetOwnCert(const cX509CertPtr & a_OwnCert, const cCryptoKeyPtr & a_OwnCertPrivKey)
|
||||
{
|
||||
ASSERT(m_IsValid); // Call Initialize() first
|
||||
|
||||
// Check that both the cert and the key is valid:
|
||||
if ((a_OwnCert.get() == NULL) || (a_OwnCertPrivKey.get() == NULL))
|
||||
{
|
||||
LOGWARNING("SSL: Own certificate is not valid, skipping the set.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we have the cert stored for later, PolarSSL only uses the cert later on
|
||||
m_OwnCert = a_OwnCert;
|
||||
m_OwnCertPrivKey2 = a_OwnCertPrivKey;
|
||||
|
||||
// Set into the context:
|
||||
ssl_set_own_cert(&m_Ssl, m_OwnCert->GetInternal(), m_OwnCertPrivKey2->GetInternal());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cSslContext::SetCACerts(const cX509CertPtr & a_CACert, const AString & a_ExpectedPeerName)
|
||||
{
|
||||
ASSERT(m_IsValid); // Call Initialize() first
|
||||
|
||||
// Store the data in our internal buffers, to avoid losing the pointers later on
|
||||
// PolarSSL will need these after this call returns, and the caller may move / delete the data before that:
|
||||
m_ExpectedPeerName = a_ExpectedPeerName;
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include "polarssl/ssl.h"
|
||||
#include "../ByteBuffer.h"
|
||||
#include "CryptoKey.h"
|
||||
#include "RsaPrivateKey.h"
|
||||
#include "X509Cert.h"
|
||||
|
||||
|
||||
@ -38,7 +40,7 @@ public:
|
||||
/** Creates a new uninitialized context */
|
||||
cSslContext(void);
|
||||
|
||||
~cSslContext();
|
||||
virtual ~cSslContext();
|
||||
|
||||
/** Initializes the context for use as a server or client.
|
||||
Returns 0 on success, PolarSSL error on failure. */
|
||||
@ -47,7 +49,15 @@ public:
|
||||
/** Returns true if the object has been initialized properly. */
|
||||
bool IsValid(void) const { return m_IsValid; }
|
||||
|
||||
/** Sets a cert chain as the trusted cert store for this context.
|
||||
/** Sets the certificate to use as our own. Must be used when representing a server, optional when client.
|
||||
Must be called after Initialize(). */
|
||||
void SetOwnCert(const cX509CertPtr & a_OwnCert, const cRsaPrivateKeyPtr & a_OwnCertPrivKey);
|
||||
|
||||
/** Sets the certificate to use as our own. Must be used when representing a server, optional when client.
|
||||
Must be called after Initialize(). */
|
||||
void SetOwnCert(const cX509CertPtr & a_OwnCert, const cCryptoKeyPtr & a_OwnCertPrivKey);
|
||||
|
||||
/** Sets a cert chain as the trusted cert store for this context. Must be called after Initialize().
|
||||
Calling this will switch the context into strict cert verification mode.
|
||||
a_ExpectedPeerName is the CommonName that we expect the SSL peer to have in its cert,
|
||||
if it is different, the verification will fail. An empty string will disable the CN check. */
|
||||
@ -93,6 +103,15 @@ protected:
|
||||
/** The SSL context that PolarSSL uses. */
|
||||
ssl_context m_Ssl;
|
||||
|
||||
/** The certificate that we present to the peer. */
|
||||
cX509CertPtr m_OwnCert;
|
||||
|
||||
/** Private key for m_OwnCert, if initialized from a cRsaPrivateKey. */
|
||||
cRsaPrivateKeyPtr m_OwnCertPrivKey;
|
||||
|
||||
/** Private key for m_OwnCert, if initialized from a cCryptoKey. */
|
||||
cCryptoKeyPtr m_OwnCertPrivKey2;
|
||||
|
||||
/** True if the SSL handshake has been completed. */
|
||||
bool m_HasHandshaken;
|
||||
|
||||
|
@ -169,7 +169,7 @@ cRCONServer::cConnection::cConnection(cRCONServer & a_RCONServer, cSocket & a_So
|
||||
|
||||
|
||||
|
||||
void cRCONServer::cConnection::DataReceived(const char * a_Data, size_t a_Size)
|
||||
bool cRCONServer::cConnection::DataReceived(const char * a_Data, size_t a_Size)
|
||||
{
|
||||
// Append data to the buffer:
|
||||
m_Buffer.append(a_Data, a_Size);
|
||||
@ -187,12 +187,12 @@ void cRCONServer::cConnection::DataReceived(const char * a_Data, size_t a_Size)
|
||||
m_RCONServer.m_SocketThreads.RemoveClient(this);
|
||||
m_Socket.CloseSocket();
|
||||
delete this;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (Length > (int)(m_Buffer.size() + 4))
|
||||
{
|
||||
// Incomplete packet yet, wait for more data to come
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
int RequestID = IntFromBuffer(m_Buffer.data() + 4);
|
||||
@ -202,10 +202,11 @@ void cRCONServer::cConnection::DataReceived(const char * a_Data, size_t a_Size)
|
||||
m_RCONServer.m_SocketThreads.RemoveClient(this);
|
||||
m_Socket.CloseSocket();
|
||||
delete this;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
m_Buffer.erase(0, Length + 4);
|
||||
} // while (m_Buffer.size() >= 14)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,7 +65,7 @@ protected:
|
||||
|
||||
|
||||
// cSocketThreads::cCallback overrides:
|
||||
virtual void DataReceived(const char * a_Data, size_t a_Size) override;
|
||||
virtual bool DataReceived(const char * a_Data, size_t a_Size) override;
|
||||
virtual void GetOutgoingData(AString & a_Data) override;
|
||||
virtual void SocketClosed(void) override;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user