فهرست منبع

Merge pull request #1170 from xicilion/cert

Add support for setting certificate on PeerConnection
Paul-Louis Ageneau 1 سال پیش
والد
کامیت
16c917f7bb
5فایلهای تغییر یافته به همراه86 افزوده شده و 2 حذف شده
  1. 5 0
      include/rtc/configuration.hpp
  2. 19 1
      src/impl/peerconnection.cpp
  3. 1 1
      src/impl/peerconnection.hpp
  4. 52 0
      test/connectivity.cpp
  5. 9 0
      test/main.cpp

+ 5 - 0
include/rtc/configuration.hpp

@@ -88,6 +88,11 @@ struct RTC_CPP_EXPORT Configuration {
 
 	// Local maximum message size for Data Channels
 	optional<size_t> maxMessageSize;
+
+	// Certificates and private keys
+	optional<string> certificatePemFile;
+	optional<string> keyPemFile;
+	optional<string> keyPemPass;
 };
 
 #ifdef RTC_ENABLE_WEBSOCKET

+ 19 - 1
src/impl/peerconnection.cpp

@@ -44,10 +44,28 @@ static LogCounter
     COUNTER_UNKNOWN_PACKET_TYPE(plog::warning,
                                 "Number of unknown RTCP packet types over past second");
 
+const string PemBeginCertificateTag = "-----BEGIN CERTIFICATE-----";
+
 PeerConnection::PeerConnection(Configuration config_)
-    : config(std::move(config_)), mCertificate(make_certificate(config.certificateType)) {
+    : config(std::move(config_)) {
 	PLOG_VERBOSE << "Creating PeerConnection";
 
+
+	if (config.certificatePemFile && config.keyPemFile) {
+		std::promise<certificate_ptr> cert;
+		cert.set_value(std::make_shared<Certificate>(
+			config.certificatePemFile->find(PemBeginCertificateTag) != string::npos
+				? Certificate::FromString(*config.certificatePemFile, *config.keyPemFile)
+				: Certificate::FromFile(*config.certificatePemFile, *config.keyPemFile,
+										config.keyPemPass.value_or(""))));
+		mCertificate = cert.get_future();
+	} else if (!config.certificatePemFile && !config.keyPemFile) {
+		mCertificate = make_certificate(config.certificateType);
+	} else {
+		throw std::invalid_argument(
+			"Either none or both certificate and key PEM files must be specified");
+	}
+
 	if (config.portRangeEnd && config.portRangeBegin > config.portRangeEnd)
 		throw std::invalid_argument("Invalid port range");
 

+ 1 - 1
src/impl/peerconnection.hpp

@@ -131,7 +131,7 @@ private:
 	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;

+ 52 - 0
test/connectivity.cpp

@@ -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.certificatePemFile = cert_pem;
+	config1.keyPemFile = 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 - 0
test/main.cpp

@@ -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();
@@ -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 {