add initial support for client certs

This commit is contained in:
Scott Hardin 2017-05-28 21:02:45 +02:00 committed by Patrik Dahlström
parent d3bcced88d
commit e402d62f33
6 changed files with 61 additions and 9 deletions

View File

@ -35,6 +35,8 @@ make
Sample usage is covered in *mumlib_example.cpp* file. Basically, you should extend *mumlib::Callback* class Sample usage is covered in *mumlib_example.cpp* file. Basically, you should extend *mumlib::Callback* class
to implement your own handlers. to implement your own handlers.
To use a client certificate, you'll need a PEM certificate and private key without a passphrase. These are assed in the MumlibConfig struct to the Mumlib object constructor. Support for passphrase still needs to be added.
## Credits ## Credits
2015 Michał Słomkowski. The code is published under the terms of Lesser General Public License Version 3. 2015 Michał Słomkowski. The code is published under the terms of Lesser General Public License Version 3.

View File

@ -26,6 +26,8 @@ namespace mumlib {
int opusEncoderBitrate = DEFAULT_OPUS_ENCODER_BITRATE; int opusEncoderBitrate = DEFAULT_OPUS_ENCODER_BITRATE;
int opusSampleRate = DEFAULT_OPUS_SAMPLE_RATE; int opusSampleRate = DEFAULT_OPUS_SAMPLE_RATE;
int opusChannels = DEFAULT_OPUS_NUM_CHANNELS; int opusChannels = DEFAULT_OPUS_NUM_CHANNELS;
std::string cert_file = "";
std::string privkey_file = "";
// additional fields will be added in the future // additional fields will be added in the future
}; };

View File

@ -34,12 +34,26 @@ namespace mumlib {
TransportException(string message) : MumlibException(std::move(message)) { } TransportException(string message) : MumlibException(std::move(message)) { }
}; };
/* This helper is needed because the sslContext and sslSocket are initialized in
* the Transport constructor and there wasn't an easier way of passing these two
* arguments.
* TODO: add support for password callback.
*/
class SslContextHelper : boost::noncopyable {
public:
SslContextHelper(boost::asio::ssl::context &ctx,
std::string cert_file, std::string privkey_file);
~SslContextHelper() { };
};
class Transport : boost::noncopyable { class Transport : boost::noncopyable {
public: public:
Transport(io_service &ioService, Transport(io_service &ioService,
ProcessControlMessageFunction processControlMessageFunc, ProcessControlMessageFunction processControlMessageFunc,
ProcessEncodedAudioPacketFunction processEncodedAudioPacketFunction, ProcessEncodedAudioPacketFunction processEncodedAudioPacketFunction,
bool noUdp = false); bool noUdp = false,
std::string cert_file = "",
std::string privkey_file = "");
~Transport(); ~Transport();
@ -48,6 +62,13 @@ namespace mumlib {
string user, string user,
string password); string password);
void connect(string host,
int port,
string user,
string password,
string cert_file,
string privkey_file);
void disconnect(); void disconnect();
ConnectionState getConnectionState() { ConnectionState getConnectionState() {
@ -85,6 +106,7 @@ namespace mumlib {
CryptState cryptState; CryptState cryptState;
ssl::context sslContext; ssl::context sslContext;
SslContextHelper sslContextHelper;
ssl::stream<tcp::socket> sslSocket; ssl::stream<tcp::socket> sslSocket;
uint8_t *sslIncomingBuffer; uint8_t *sslIncomingBuffer;

View File

@ -39,8 +39,8 @@ int main(int argc, char *argv[]) {
logger.setPriority(log4cpp::Priority::NOTICE); logger.setPriority(log4cpp::Priority::NOTICE);
logger.addAppender(appender1); logger.addAppender(appender1);
if (argc < 3) { if (argc < 3 || argc == 4 || argc > 5) {
logger.crit("Usage: %s {server} {password}", argv[0]); logger.crit("Usage: %s {server} {password} [{certfile} {keyfile}]", argv[0]);
return 1; return 1;
} }
@ -50,6 +50,10 @@ int main(int argc, char *argv[]) {
try { try {
mumlib::MumlibConfiguration conf; mumlib::MumlibConfiguration conf;
conf.opusEncoderBitrate = 32000; conf.opusEncoderBitrate = 32000;
if ( argc > 3 && argc <= 5 ) {
conf.cert_file = argv[3];
conf.privkey_file = argv[4];
}
mumlib::Mumlib mum(myCallback, conf); mumlib::Mumlib mum(myCallback, conf);
myCallback.mum = &mum; myCallback.mum = &mum;
mum.connect(argv[1], 64738, "mumlib_example", argv[2]); mum.connect(argv[1], 64738, "mumlib_example", argv[2]);

View File

@ -29,7 +29,9 @@ mumlib::Transport::Transport(
io_service &ioService, io_service &ioService,
mumlib::ProcessControlMessageFunction processMessageFunc, mumlib::ProcessControlMessageFunction processMessageFunc,
ProcessEncodedAudioPacketFunction processEncodedAudioPacketFunction, ProcessEncodedAudioPacketFunction processEncodedAudioPacketFunction,
bool noUdp) : bool noUdp,
std::string cert_file,
std::string privkey_file) :
logger(log4cpp::Category::getInstance("mumlib.Transport")), logger(log4cpp::Category::getInstance("mumlib.Transport")),
ioService(ioService), ioService(ioService),
processMessageFunction(std::move(processMessageFunc)), processMessageFunction(std::move(processMessageFunc)),
@ -38,6 +40,7 @@ mumlib::Transport::Transport(
state(ConnectionState::NOT_CONNECTED), state(ConnectionState::NOT_CONNECTED),
udpSocket(ioService), udpSocket(ioService),
sslContext(ssl::context::sslv23), sslContext(ssl::context::sslv23),
sslContextHelper(sslContext, cert_file, privkey_file),
sslSocket(ioService, sslContext), sslSocket(ioService, sslContext),
pingTimer(ioService, PING_INTERVAL), pingTimer(ioService, PING_INTERVAL),
asyncBufferPool(static_cast<const unsigned long>(max(MAX_UDP_LENGTH, MAX_TCP_LENGTH))) { asyncBufferPool(static_cast<const unsigned long>(max(MAX_UDP_LENGTH, MAX_TCP_LENGTH))) {
@ -67,6 +70,7 @@ void mumlib::Transport::connect(
sslSocket.set_verify_mode(boost::asio::ssl::verify_peer); sslSocket.set_verify_mode(boost::asio::ssl::verify_peer);
//todo for now it accepts every certificate, move it to callback //todo for now it accepts every certificate, move it to callback
sslSocket.set_verify_callback([](bool preverified, boost::asio::ssl::verify_context &ctx) { sslSocket.set_verify_callback([](bool preverified, boost::asio::ssl::verify_context &ctx) {
return true; return true;
@ -519,6 +523,16 @@ void mumlib::Transport::throwTransportException(string message) {
throw TransportException(std::move(message)); throw TransportException(std::move(message));
} }
mumlib::SslContextHelper::SslContextHelper(ssl::context &ctx, std::string cert_file, std::string privkey_file) {
if ( cert_file.size() > 0 ) {
ctx.use_certificate_file(cert_file, ssl::context::file_format::pem);
}
if ( privkey_file.size() > 0 ) {
ctx.use_private_key_file(privkey_file, ssl::context::file_format::pem);
}
}
void mumlib::Transport::sendEncodedAudioPacket(uint8_t *buffer, int length) { void mumlib::Transport::sendEncodedAudioPacket(uint8_t *buffer, int length) {
if (state != ConnectionState::CONNECTED) { if (state != ConnectionState::CONNECTED) {
logger.warn("Connection not established."); logger.warn("Connection not established.");

View File

@ -43,12 +43,20 @@ namespace mumlib {
externalIoService = false; externalIoService = false;
} }
_Mumlib_Private(Callback &callback, io_service &ioService, MumlibConfiguration &configuration) _Mumlib_Private(
Callback &callback,
io_service &ioService,
MumlibConfiguration &configuration)
: callback(callback), : callback(callback),
ioService(ioService), ioService(ioService),
externalIoService(true), externalIoService(true),
transport(ioService, boost::bind(&_Mumlib_Private::processIncomingTcpMessage, this, _1, _2, _3), transport(
boost::bind(&_Mumlib_Private::processAudioPacket, this, _1, _2, _3)), ioService,
boost::bind(&_Mumlib_Private::processIncomingTcpMessage, this, _1, _2, _3),
boost::bind(&_Mumlib_Private::processAudioPacket, this, _1, _2, _3),
false,
configuration.cert_file,
configuration.privkey_file),
audio(configuration.opusSampleRate, configuration.opusEncoderBitrate, configuration.opusChannels) { audio(configuration.opusSampleRate, configuration.opusEncoderBitrate, configuration.opusChannels) {
audio.setOpusEncoderBitrate(configuration.opusEncoderBitrate); audio.setOpusEncoderBitrate(configuration.opusEncoderBitrate);