From cfbf9ba0188eb3ac79dde1a960bbe2f0c2e32901 Mon Sep 17 00:00:00 2001
From: Andrej Shadura <andrew.shadura@collabora.co.uk>
Date: Mon, 2 Mar 2020 12:44:54 +0100
Subject: [PATCH] Make HTTPS communication between services possible
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When workers and services are located in different networks, we don’t
want to send traffic unencrypted and open to anyone to listen to.

Make it possible to easily opt in to HTTPS communication by changing
the service URLs in BSConfig.

Signed-off-by: Andrej Shadura <andrew.shadura@collabora.co.uk>
---
 src/backend/BSServer.pm         |  6 ++++++
 src/backend/BSStdServer.pm      |  1 +
 src/backend/bs_getbinariesproxy |  8 ++++++++
 src/backend/bs_repserver        | 11 +++++++++++
 src/backend/bs_service          | 10 +++++++++-
 src/backend/bs_srcserver        | 11 +++++++++++
 src/backend/bs_worker           |  2 +-
 src/backend/worker/BSSSL.pm     |  1 +
 8 files changed, 48 insertions(+), 2 deletions(-)
 create mode 120000 src/backend/worker/BSSSL.pm

diff --git a/src/backend/BSServer.pm b/src/backend/BSServer.pm
index 58bd8e6b44..74e30841c9 100644
--- a/src/backend/BSServer.pm
+++ b/src/backend/BSServer.pm
@@ -42,6 +42,9 @@ use BSUtil;
 
 use strict;
 
+require BSSSL;
+my $tossl = \&BSSSL::tossl;
+
 my $MS2;	# secondary server port
 
 our $request;		# FIXME: should not be global
@@ -319,6 +322,9 @@ sub server {
   };
 
   setsockopt(CLNT, SOL_SOCKET, SO_KEEPALIVE, pack("l",1)) if $conf->{'setkeepalive'};
+  if ($conf->{'proto'} eq 'https') {
+      $tossl->(\*CLNT, $conf->{'ssl_keyfile'}, $conf->{'ssl_certfile'}, 0);
+  }
   if ($conf->{'accept'}) {
     eval {
       $conf->{'accept'}->($conf, $req);
diff --git a/src/backend/BSStdServer.pm b/src/backend/BSStdServer.pm
index 30a416d767..7b86280c53 100644
--- a/src/backend/BSStdServer.pm
+++ b/src/backend/BSStdServer.pm
@@ -213,6 +213,7 @@ sub server {
     $conf->{'periodic_interval'} ||= 1;
     $conf->{'serverstatus'} ||= "$rundir/$name.status";
     $conf->{'setkeepalive'} = 1 unless defined $conf->{'setkeepalive'};
+    $conf->{'proto'} = 'http' unless defined $conf->{'proto'};
     $conf->{'name'} = $name;
     BSDispatch::compile($conf);
   }
diff --git a/src/backend/bs_getbinariesproxy b/src/backend/bs_getbinariesproxy
index 71c47e49ac..afb92d9338 100755
--- a/src/backend/bs_getbinariesproxy
+++ b/src/backend/bs_getbinariesproxy
@@ -52,6 +52,11 @@ my $gettimeout = 3600;
 
 my $port = 5254;        
 $port = $1 if $BSConfig::getbinariesproxyserver && $BSConfig::getbinariesproxyserver =~ /:(\d+)$/;
+my $proto = 'http';
+$proto = $1 if $BSConfig::getbinariesproxyserver =~ /^(https?):/;
+if ($proto eq 'https') {
+  die("need ssl_keyfile and ssl_certfile for HTTPS") unless defined $BSConfig::ssl_keyfile and defined $BSConfig::ssl_certfile;
+}
 
 my $cachedir = "$BSConfig::bsdir/getbinariesproxycache";
 my $cachesize = 1024 * 1024 * 1024;	# default: 1G
@@ -349,6 +354,9 @@ my $dispatches = [
 
 my $conf = {
   'port' => $port,
+  'ssl_keyfile' => $BSConfig::ssl_keyfile || '',
+  'ssl_certfile' => $BSConfig::ssl_certfile || '',
+  'proto' => $proto,
   'dispatches' => $dispatches,
   'setkeepalive' => 1,
   'maxchild' => 40,
diff --git a/src/backend/bs_repserver b/src/backend/bs_repserver
index e8de797b21..5b47cdbf7a 100755
--- a/src/backend/bs_repserver
+++ b/src/backend/bs_repserver
@@ -69,6 +69,11 @@ use strict;
 
 my $port = 5252;	#'RR'
 $port = $1 if $BSConfig::reposerver =~ /:(\d+)$/;
+my $proto = 'http';
+$proto = $1 if $BSConfig::reposerver =~ /^(https?):/;
+if ($proto eq 'https') {
+  die("need ssl_keyfile and ssl_certfile for HTTPS") unless defined $BSConfig::ssl_keyfile and defined $BSConfig::ssl_certfile;
+}
 my $proxy;
 $proxy = $BSConfig::proxy if defined($BSConfig::proxy);
 
@@ -4395,6 +4400,9 @@ my $dispatches_ajax = [
 
 my $conf = {
   'port' => $port,
+  'ssl_keyfile' => $BSConfig::ssl_keyfile || '',
+  'ssl_certfile' => $BSConfig::ssl_certfile || '',
+  'proto' => $proto,
   'dispatches' => $dispatches,
   'maxchild' => 20,
   'maxchild2' => 20,
@@ -4409,6 +4417,9 @@ if ($BSConfig::workerreposerver) {
   my $wport = $port;
   $wport = $1 if $BSConfig::workerreposerver =~ /:(\d+)$/;
   $conf->{'port2'} = $wport if $wport != $port;
+  my $wproto = $proto;
+  $wproto = $1 if $BSConfig::workerreposerver =~ /^(https?):/;
+  die("worker port on $wproto but normal port on $proto: both need to be the same\n") unless $wproto eq $proto;
 }
 
 # create bsdir before root privileges are dropped
diff --git a/src/backend/bs_service b/src/backend/bs_service
index 9e8da0aec9..a525b4ef76 100755
--- a/src/backend/bs_service
+++ b/src/backend/bs_service
@@ -36,7 +36,7 @@ use Data::Dumper;
 use POSIX;
 use Fcntl qw(:DEFAULT :flock);
 
-use BSRPC;
+use BSRPC ':https';
 use BSServer;
 use BSStdServer;
 use BSConfiguration;
@@ -55,6 +55,11 @@ BSUtil::set_fdatasync_before_rename() unless $BSConfig::disable_data_sync || $BS
 my $tempdir = $BSConfig::servicetempdir || $BSConfig::servicetempdir || "$BSConfig::bsdir/service";
 my $port = 5152;
 $port = $1 if $BSConfig::serviceserver =~ /:(\d+)$/;
+my $proto = 'http';
+$proto = $1 if $BSConfig::serviceserver =~ /^(https?):/;
+if ($proto eq 'https') {
+  die("need ssl_keyfile and ssl_certfile for HTTPS") unless defined $BSConfig::ssl_keyfile and defined $BSConfig::ssl_certfile;
+}
 
 my $servicedir = $BSConfig::servicedir || "/usr/lib/obs/service";
 my $rootservicedir = $BSConfig::serviceroot ? "$BSConfig::serviceroot/$servicedir" : $servicedir;
@@ -250,6 +255,9 @@ my $dispatches = [
 
 my $conf = {
   'port' => $port,
+  'ssl_keyfile' => $BSConfig::ssl_keyfile || '',
+  'ssl_certfile' => $BSConfig::ssl_certfile || '',
+  'proto' => $proto,
   'dispatches' => $dispatches,
   'setkeepalive' => 1,
   'maxchild' => $maxchild,
diff --git a/src/backend/bs_srcserver b/src/backend/bs_srcserver
index 383d600f54..54e3baa225 100755
--- a/src/backend/bs_srcserver
+++ b/src/backend/bs_srcserver
@@ -69,6 +69,11 @@ use strict;
 
 my $port = 5352;	#'SR'
 $port = $1 if $BSConfig::srcserver =~ /:(\d+)$/;
+my $proto = 'http';
+$proto = $1 if $BSConfig::srcserver =~ /^(https?):/;
+if ($proto eq 'https') {
+  die("need ssl_keyfile and ssl_certfile for HTTPS") unless defined $BSConfig::ssl_keyfile and defined $BSConfig::ssl_certfile;
+}
 my $proxy;
 $proxy = $BSConfig::proxy if defined($BSConfig::proxy);
 
@@ -8792,6 +8797,9 @@ my $dispatches_ajax = [
 
 my $conf = {
   'port' => $port,
+  'ssl_keyfile' => $BSConfig::ssl_keyfile || '',
+  'ssl_certfile' => $BSConfig::ssl_certfile || '',
+  'proto' => $proto,
   'dispatches' => $dispatches,
   'maxchild' => 20,
   'maxchild2' => 20,
@@ -8806,6 +8814,9 @@ if ($BSConfig::workersrcserver) {
   my $wport = $port;
   $wport = $1 if $BSConfig::workersrcserver =~ /:(\d+)$/;
   $conf->{'port2'} = $wport if $wport != $port;
+  my $wproto = $proto;
+  $wproto = $1 if $BSConfig::workersrcserver =~ /^(https?):/;
+  die("worker port on $wproto but normal port on $proto: both need to be the same\n") unless $wproto eq $proto;
 }
 
 # create bsdir before root privileges are dropped
diff --git a/src/backend/bs_worker b/src/backend/bs_worker
index fc038a1a1a..6e718ac41b 100755
--- a/src/backend/bs_worker
+++ b/src/backend/bs_worker
@@ -38,7 +38,7 @@ BEGIN { Fcntl->import(':seek') unless defined &SEEK_SET; }
 
 use Storable;
 
-use BSRPC;
+use BSRPC ':https';
 use BSServer;
 use BSDispatch;		# for parse_cgi
 use BSConfiguration;
diff --git a/src/backend/worker/BSSSL.pm b/src/backend/worker/BSSSL.pm
new file mode 120000
index 0000000000..2a67884296
--- /dev/null
+++ b/src/backend/worker/BSSSL.pm
@@ -0,0 +1 @@
+../BSSSL.pm
\ No newline at end of file
-- 
GitLab