Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for setting certificate on PeerConnection #1170

Merged
merged 2 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/rtc/configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ struct RTC_CPP_EXPORT Configuration {

// Local maximum message size for Data Channels
optional<size_t> maxMessageSize;

// Certificates and private keys
optional<string> certPem;
optional<string> keyPem;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should make the configuration fields consistent with existing ones in WebSocketConfiguration and WebSocketServerConfiguration. The fields are called certificatePemFile, keyPemFile, and keyPemPass, they allow the user to pass certificate and key either as a file path or as a PEM string.

};

#ifdef RTC_ENABLE_WEBSOCKET
Expand Down
10 changes: 9 additions & 1 deletion src/impl/peerconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,17 @@ static LogCounter
"Number of unknown RTCP packet types over past second");

PeerConnection::PeerConnection(Configuration config_)
: config(std::move(config_)), mCertificate(make_certificate(config.certificateType)) {
: config(std::move(config_)) {
PLOG_VERBOSE << "Creating PeerConnection";

if( config.certPem.has_value() && config.keyPem.has_value() ) {
std::promise<certificate_ptr> cert;
cert.set_value(std::make_shared<Certificate>(Certificate::FromString(config.certPem.value(), config.keyPem.value())));
mCertificate = cert.get_future();
} else {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should create the certificate if both certificate and key are not specified, else throw an invalid_argument exception (like in WebSocketServer).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get it.

mCertificate = make_certificate(config.certificateType);
}

if (config.portRangeEnd && config.portRangeBegin > config.portRangeEnd)
throw std::invalid_argument("Invalid port range");

Expand Down
2 changes: 1 addition & 1 deletion src/impl/peerconnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {
void updateTrackSsrcCache(const Description &description);

const init_token mInitToken = Init::Instance().token();
const future_certificate_ptr mCertificate;
future_certificate_ptr mCertificate;

Processor mProcessor;
optional<Description> mLocalDescription, mRemoteDescription;
Expand Down
52 changes: 52 additions & 0 deletions test/connectivity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,55 @@ void test_connectivity(bool signal_wrong_fingerprint) {

cout << "Success" << endl;
}

const char* key_pem =
"-----BEGIN PRIVATE KEY-----\n"
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg3bbuT2SjSlMZH/J1\n"
"vHwmF0Blb/DBc/v7f1Za9GPUXHmhRANCAATDpmYxZozjVw6xlERNjJJGgfY3bEmj\n"
"xAKFRq3nbxbDHvMEs34u9HntMZWJ0hp3GUC+Ax7JHTv3cYqSaAg2SpR4\n"
"-----END PRIVATE KEY-----\n";

const char* cert_pem =
"-----BEGIN CERTIFICATE-----\n"
"MIIBgjCCASigAwIBAgIJAPMXEoZXOaDEMAoGCCqGSM49BAMCMEoxDzANBgNVBAMM\n"
"BmNhLmNvbTELMAkGA1UEBhMCVVMxCzAJBgNVBAcMAkNBMRAwDgYDVQQKDAdleGFt\n"
"cGxlMQswCQYDVQQIDAJDQTAeFw0yNDA1MDUxNjAzMjFaFw0yNDA4MTMxNjAzMjFa\n"
"MDExCzAJBgNVBAYTAkNOMRAwDgYDVQQKDAdiYW96LmNuMRAwDgYDVQQDDAdiYW96\n"
"Lm1lMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEw6ZmMWaM41cOsZRETYySRoH2\n"
"N2xJo8QChUat528Wwx7zBLN+LvR57TGVidIadxlAvgMeyR0793GKkmgINkqUeKMQ\n"
"MA4wDAYDVR0TAQH/BAIwADAKBggqhkjOPQQDAgNIADBFAiAPNldqGJHryfjPFyX3\n"
"zfHHWlO7xSDTzdyoxzroFdwy+gIhAKmZizEVvDlBiIe+3ptCArU3dbp+bzLynTcr\n"
"Ma9ayzQy\n"
"-----END CERTIFICATE-----\n";

void test_pem() {
InitLogger(LogLevel::Debug);

Configuration config1;

config1.certPem = cert_pem;
config1.keyPem = key_pem;

PeerConnection pc1(config1);
atomic_bool done;
string f;

pc1.onLocalDescription([&done, &f](Description sdp) {
f = sdp.fingerprint().value().value;
done = true;
});

auto dc1 = pc1.createDataChannel("test");

// Wait a bit
int attempts = 10;
while (!done && attempts--)
this_thread::sleep_for(1s);

cout << "Fingerprint: " << f << endl;

if (f != "07:E5:6F:2A:1A:0C:2C:32:0E:C1:C3:9C:34:5A:78:4E:A5:8B:32:05:D1:57:D6:F4:E7:02:41:12:E6:01:C6:8F")
throw runtime_error("The fingerprint of the specified certificate do not match");

cout << "Success" << endl;
}
9 changes: 9 additions & 0 deletions test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ using namespace std;
using namespace chrono_literals;

void test_connectivity(bool signal_wrong_fingerprint);
void test_pem();
void test_negotiated();
void test_reliability();
void test_turn_connectivity();
Expand Down Expand Up @@ -56,6 +57,14 @@ int main(int argc, char **argv) {
} catch (const exception &) {
}

try {
cout << endl << "*** Running pem test..." << endl;
test_pem();
} catch (const exception &e) {
cerr << "pem test failed: " << e.what() << endl;
return -1;
}

// TODO: Temporarily disabled as the Open Relay TURN server is unreliable
/*
try {
Expand Down
Loading