From 52e48c02b61bcb9fb2fedc79b5d8b546d74d2b2c Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Fri, 21 Jan 2022 22:23:41 -0600 Subject: [PATCH] Add janus_path and janus_secret, allowing for more secure and flexible Janus installs --- .../lib/ZoneMinder/ConfigData.pm.in | 22 ++++++++++++++++ src/zm_monitor.cpp | 26 +++++++++++++++---- web/includes/functions.php | 2 +- web/js/MonitorStream.js | 4 ++- web/skins/classic/views/cycle.php | 1 + web/skins/classic/views/js/cycle.js | 9 ++++++- web/skins/classic/views/montage.php | 1 + web/skins/classic/views/watch.php | 1 + 8 files changed, 58 insertions(+), 8 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index 48d494614..9b8a4e61e 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -370,6 +370,28 @@ our @options = ( type => $types{boolean}, category => 'system', }, + { + name => 'ZM_JANUS_SECRET', + default => '', + description => 'Password for Janus streaming administration.', + help => q`This value should be set to a secure password, + and match the admin_key value in janus.plugin.streaming.config. + `, + type => $types{string}, + category => 'system', + }, + { + name => 'ZM_JANUS_PATH', + default => '', + description => 'URL for Janus HTTP/S port', + help => q`Janus requires HTTP/S communication to administer + and initiate h.264 streams. If left blank, this will default to + the ZM hostname, port 8088/janus. This setting is particularly + useful for putting janus behind a reverse proxy. + `, + type => $types{string}, + category => 'system', + }, { name => 'ZM_ENABLE_CSRF_MAGIC', default => 'yes', diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 2179197e8..9a1b747b6 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -3383,7 +3383,12 @@ size_t Monitor::WriteCallback(void *contents, size_t size, size_t nmemb, void *u int Monitor::add_to_janus() { //TODO clean this up, add error checking, etc std::string response; - std::string endpoint = "127.0.0.1:8088/janus/"; + std::string endpoint; + if ((config.janus_path != nullptr) && (config.janus_path[0] != '\0')) { + endpoint = config.janus_path; + } else { + endpoint = "127.0.0.1:8088/janus/"; + } std::string postData = "{\"janus\" : \"create\", \"transaction\" : \"randomString\"}"; std::string rtsp_username; std::string rtsp_password; @@ -3425,6 +3430,7 @@ int Monitor::add_to_janus() { if (pos == std::string::npos) return -1; janus_id = response.substr(pos + 6, 16); response = ""; + endpoint += "/"; endpoint += janus_id; postData = "{\"janus\" : \"attach\", \"plugin\" : \"janus.plugin.streaming\", \"transaction\" : \"randomString\"}"; curl_easy_setopt(curl, CURLOPT_URL,endpoint.c_str()); @@ -3445,8 +3451,10 @@ int Monitor::add_to_janus() { //Assemble our actual request postData = "{\"janus\" : \"message\", \"transaction\" : \"randomString\", \"body\" : {"; - postData += "\"request\" : \"create\", \"admin_key\" : \"supersecret\", \"type\" : \"rtsp\", "; - postData += "\"url\" : \""; + postData += "\"request\" : \"create\", \"admin_key\" : \""; + postData += config.janus_secret; + postData += "\", \"type\" : \"rtsp\", "; + postData += "\"url\" : \""; postData += rtsp_path; postData += "\", \"rtsp_user\" : \""; postData += rtsp_username; @@ -3474,7 +3482,12 @@ int Monitor::add_to_janus() { int Monitor::remove_from_janus() { //TODO clean this up, add error checking, etc std::string response; - std::string endpoint = "127.0.0.1:8088/janus/"; + std::string endpoint; + if ((config.janus_path != nullptr) && (config.janus_path[0] != '\0')) { + endpoint = config.janus_path; + } else { + endpoint = "127.0.0.1:8088/janus/"; + } std::string postData = "{\"janus\" : \"create\", \"transaction\" : \"randomString\"}"; std::size_t pos; CURLcode res; @@ -3495,6 +3508,7 @@ int Monitor::remove_from_janus() { if (pos == std::string::npos) return -1; std::string janus_id = response.substr(pos + 6, 16); response = ""; + endpoint += "/"; endpoint += janus_id; postData = "{\"janus\" : \"attach\", \"plugin\" : \"janus.plugin.streaming\", \"transaction\" : \"randomString\"}"; curl_easy_setopt(curl, CURLOPT_URL,endpoint.c_str()); @@ -3512,7 +3526,9 @@ int Monitor::remove_from_janus() { //Assemble our actual request postData = "{\"janus\" : \"message\", \"transaction\" : \"randomString\", \"body\" : {"; - postData += "\"request\" : \"destroy\", \"admin_key\" : \"supersecret\", \"id\" : "; + postData += "\"request\" : \"destroy\", \"admin_key\" : \""; + postData += config.janus_secret; + postData += "\", \"id\" : "; postData += std::to_string(id); postData += "}}"; diff --git a/web/includes/functions.php b/web/includes/functions.php index f9b8abf72..e346ceb34 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -2095,7 +2095,7 @@ function getStreamHTML($monitor, $options = array()) { ) ); return getVideoStreamHTML( 'liveStream'.$monitor->Id(), $streamSrc, $options['width'], $options['height'], ZM_MPEG_LIVE_FORMAT, $monitor->Name() ); } else if ( $monitor->JanusEnabled() ) { - return ''; + return ''; } else if ( $options['mode'] == 'stream' and canStream() ) { $options['mode'] = 'jpeg'; $streamSrc = $monitor->getStreamSrc($options); diff --git a/web/js/MonitorStream.js b/web/js/MonitorStream.js index 17f43c4b9..373902e1f 100644 --- a/web/js/MonitorStream.js +++ b/web/js/MonitorStream.js @@ -92,7 +92,9 @@ function MonitorStream(monitorData) { if (this.janusEnabled) { var id = parseInt(this.id); var server; - if (window.location.protocol=='https:') { + if (ZM_JANUS_PATH) { + server = ZM_JANUS_PATH; + } else if (window.location.protocol=='https:') { // Assume reverse proxy setup for now server = "https://" + window.location.hostname + "/janus"; } else { diff --git a/web/skins/classic/views/cycle.php b/web/skins/classic/views/cycle.php index ee9e03d4f..50bb42045 100644 --- a/web/skins/classic/views/cycle.php +++ b/web/skins/classic/views/cycle.php @@ -192,6 +192,7 @@ xhtmlHeaders(__FILE__, translate('CycleWatch')); + diff --git a/web/skins/classic/views/js/cycle.js b/web/skins/classic/views/js/cycle.js index 670671faa..9e128d0ab 100644 --- a/web/skins/classic/views/js/cycle.js +++ b/web/skins/classic/views/js/cycle.js @@ -51,7 +51,14 @@ function initCycle() { if ( scale == '0' || scale == 'auto' ) changeScale(); if (monitorData[monIdx].janusEnabled) { - server = "http://" + window.location.hostname + ":8088/janus"; + if (ZM_JANUS_PATH) { + server = ZM_JANUS_PATH; + } else if (window.location.protocol=='https:') { + // Assume reverse proxy setup for now + server = "https://" + window.location.hostname + "/janus"; + } else { + server = "http://" + window.location.hostname + ":8088/janus"; + } opaqueId = "streamingtest-"+Janus.randomString(12); Janus.init({debug: "all", callback: function() { janus = new Janus({ diff --git a/web/skins/classic/views/montage.php b/web/skins/classic/views/montage.php index a96e8a88e..c59ce9f66 100644 --- a/web/skins/classic/views/montage.php +++ b/web/skins/classic/views/montage.php @@ -318,6 +318,7 @@ foreach (array_reverse($zones) as $zone) { + diff --git a/web/skins/classic/views/watch.php b/web/skins/classic/views/watch.php index 340ee8e33..46ee11f90 100644 --- a/web/skins/classic/views/watch.php +++ b/web/skins/classic/views/watch.php @@ -396,6 +396,7 @@ if ( ZM_WEB_SOUND_ON_ALARM ) { ?> +