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
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
2015 Michał Słomkowski. The code is published under the terms of Lesser General Public License Version 3.
@ -42,4 +44,4 @@ to implement your own handlers.
The library contains code from following 3rd party projects:
* official Mumble Client: https://github.com/mumble-voip/mumble
* *libmumble*: https://github.com/cornejo/libmumble
* *libmumble*: https://github.com/cornejo/libmumble

View File

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

View File

@ -34,12 +34,26 @@ namespace mumlib {
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 {
public:
Transport(io_service &ioService,
ProcessControlMessageFunction processControlMessageFunc,
ProcessEncodedAudioPacketFunction processEncodedAudioPacketFunction,
bool noUdp = false);
bool noUdp = false,
std::string cert_file = "",
std::string privkey_file = "");
~Transport();
@ -48,6 +62,13 @@ namespace mumlib {
string user,
string password);
void connect(string host,
int port,
string user,
string password,
string cert_file,
string privkey_file);
void disconnect();
ConnectionState getConnectionState() {
@ -85,6 +106,7 @@ namespace mumlib {
CryptState cryptState;
ssl::context sslContext;
SslContextHelper sslContextHelper;
ssl::stream<tcp::socket> sslSocket;
uint8_t *sslIncomingBuffer;

View File

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

View File

@ -29,7 +29,9 @@ mumlib::Transport::Transport(
io_service &ioService,
mumlib::ProcessControlMessageFunction processMessageFunc,
ProcessEncodedAudioPacketFunction processEncodedAudioPacketFunction,
bool noUdp) :
bool noUdp,
std::string cert_file,
std::string privkey_file) :
logger(log4cpp::Category::getInstance("mumlib.Transport")),
ioService(ioService),
processMessageFunction(std::move(processMessageFunc)),
@ -38,6 +40,7 @@ mumlib::Transport::Transport(
state(ConnectionState::NOT_CONNECTED),
udpSocket(ioService),
sslContext(ssl::context::sslv23),
sslContextHelper(sslContext, cert_file, privkey_file),
sslSocket(ioService, sslContext),
pingTimer(ioService, PING_INTERVAL),
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);
//todo for now it accepts every certificate, move it to callback
sslSocket.set_verify_callback([](bool preverified, boost::asio::ssl::verify_context &ctx) {
return true;
@ -519,6 +523,16 @@ void mumlib::Transport::throwTransportException(string 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) {
if (state != ConnectionState::CONNECTED) {
logger.warn("Connection not established.");

View File

@ -43,12 +43,20 @@ namespace mumlib {
externalIoService = false;
}
_Mumlib_Private(Callback &callback, io_service &ioService, MumlibConfiguration &configuration)
_Mumlib_Private(
Callback &callback,
io_service &ioService,
MumlibConfiguration &configuration)
: callback(callback),
ioService(ioService),
externalIoService(true),
transport(ioService, boost::bind(&_Mumlib_Private::processIncomingTcpMessage, this, _1, _2, _3),
boost::bind(&_Mumlib_Private::processAudioPacket, this, _1, _2, _3)),
transport(
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.setOpusEncoderBitrate(configuration.opusEncoderBitrate);