Bug 25672: Convert to restricting to listed repositories only

I think instead of a plain on/off switch we should use it in combination
with the plugin_repo's and set it to restrict to only those repos' (i.e.
disable uploads entirely if no repo's are listed, or just allow those
repo's when there are).

This patch achieves that, but only if plugins are installed via the
plugin browser method. We disable all direct upload avenues, so install
is blocked for other cases.

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
Martin Renvoize 2023-07-25 15:46:34 +01:00 committed by Tomas Cohen Arazi
parent aa8c26ae52
commit ea22082649
Signed by: tomascohen
GPG key ID: 0A272EA1B2F3C15F
8 changed files with 49 additions and 35 deletions

View file

@ -266,7 +266,6 @@ __END_SRU_PUBLICSERVER__
<authorityservershadow>1</authorityservershadow>
<pluginsdir>__PLUGINS_DIR__</pluginsdir> <!-- This entry can be repeated to use multiple directories -->
<enable_plugins>0</enable_plugins>
<enable_plugin_browser_upload>1</enable_plugin_browser_upload>
<upload_path>__UPLOAD_PATH__</upload_path>
<tmp_path>__TMP_PATH__</tmp_path>
<intranetdir>/usr/share/koha/intranet/cgi-bin</intranetdir>
@ -409,6 +408,7 @@ __END_SRU_PUBLICSERVER__
developers use it to catch bugs related to strict SQL modes -->
<dev_install>0</dev_install>
<strict_sql_modes>0</strict_sql_modes>
<plugins_restricted>1</plugins_restricted>
<plugin_repos>
<!--
<repo>
@ -423,7 +423,7 @@ __END_SRU_PUBLICSERVER__
</repo>
<repo>
<name>PTFS Europe</name>
<org_name>ptfs-europe</org_name>
<org_name>PTFS-Europe</org_name>
<service>github</service>
</repo>
<repo>

View file

@ -79,7 +79,6 @@
<authorityservershadow>1</authorityservershadow>
<pluginsdir>__PLUGINS_DIR__</pluginsdir> <!-- This entry can be repeated to use multiple directories -->
<enable_plugins>0</enable_plugins>
<enable_plugin_browser_upload>1</enable_plugin_browser_upload>
<upload_path></upload_path>
<tmp_path></tmp_path>
<intranetdir>__INTRANET_CGI_DIR__</intranetdir>
@ -226,8 +225,8 @@
developers use it to catch bugs related to strict SQL modes -->
<dev_install>0</dev_install>
<strict_sql_modes>0</strict_sql_modes>
<plugins_restricted>1</plugins_restricted>
<plugin_repos>
<!--
<repo>
<name>ByWater Solutions</name>
<org_name>bywatersolutions</org_name>
@ -240,10 +239,9 @@
</repo>
<repo>
<name>PTFS Europe</name>
<org_name>ptfs-europe</org_name>
<org_name>PTFS-Europe</org_name>
<service>github</service>
</repo>
-->
</plugin_repos>
<koha_xslt_security>

View file

@ -29,9 +29,9 @@
<div class="container-fluid">
<div class="row">
<div class="col-sm-6 col-sm-offset-3 col-md-6 col-md-offset-3">
[% IF ( browser_upload_enabled.defined ) && ( browser_upload_enabled == 0 ) %]
<h1>Plugin browser upload disabled</h1>
<p>To enable Koha plugin browser upload, the flag enable_plugin_browser_upload must be set in the Koha configuration file</p>
[% IF ( plugins_restricted.defined ) && ( plugins_restricted == 1 ) %]
<h1>Plugin upload is restricted to only those plugins listed by your server administrator</h1>
<p>To enable unrestricted plugin uploads, ask your administrator to unset plugins_restricted in the Koha configuration file</p>
[% ELSE %]
<h1>Plugins disabled</h1>
<p>To enable Koha plugins, the flag enable_plugins must be set in the Koha configuration file</p>

View file

@ -46,7 +46,7 @@
[% IF ( CAN_user_plugins_manage ) %]
<div class="btn-toolbar" id="toolbar">
[% IF ( enable_browser_upload ) %]
[% IF ( !plugins_restricted ) %]
<a href="/cgi-bin/koha/plugins/plugins-upload.pl" id="upload_plugin" class="btn btn-default"><i class="fa fa-upload"></i> Upload plugin</a>
[% END %]
@ -90,9 +90,7 @@
<th>Description</th>
<th>Organization</th>
<th>Latest version</th>
[% IF ( enable_browser_upload ) %]
<th>&nbsp;</th>
[% END %]
</tr>
</thead>
@ -102,9 +100,7 @@
<td>[% sr.result.description | html %]</td>
<td>[% sr.repo.name | html %]</td>
<td>[% sr.result.tag_name | html %]</td>
[% IF ( enable_browser_upload ) %]
<td><a class="btn btn-default btn-sm btn-install-plugin" href="/cgi-bin/koha/plugins/plugins-upload.pl?op=Upload&uploadfile=[% sr.result.install_name | uri %]&uploadlocation=[% sr.result.install_url | uri %]"><i class="fa fa-download"></i> Install</a></td>
[% END %]
</tr>
[% END %]
</table>
@ -220,9 +216,7 @@
[% END %]
[% END %]
[% IF ( CAN_user_plugins_manage ) %]
[% IF ( enable_browser_upload ) %]
<li><a class="uninstall_plugin" data-plugin-name="[% plugin.metadata.name | html %]" href="/cgi-bin/koha/plugins/plugins-uninstall.pl?class=[% plugin.class | html %]"><i class="fa fa-trash-can fa-fw"></i> Uninstall</a></li>
[% END %]
[% IF ( plugin.is_enabled ) %]
<li><a class="enable_plugin" data-plugin-name="[% plugin.metadata.name | html %]" href="/cgi-bin/koha/plugins/plugins-enable.pl?class=[% plugin.class | html %]&method=disable"><i class="fa fa-pause fa-fw"></i> Disable</a></li>
[% ELSE %]

View file

@ -39,6 +39,7 @@
[% ELSIF ( ERROR.EMPTYUPLOAD ) %]<li><strong>The upload file appears to be empty.</strong></li>
[% ELSIF ( ERROR.UZIPFAIL ) %]<li><strong>[% ERROR.UZIPFAIL | html %] failed to unpack.<br />Please verify the integrity of the zip file and retry.</strong></li>
[% ELSIF ( ERROR.NOWRITEPLUGINS ) %]<li><strong>Cannot unpack file to the plugins directory.<br />Please verify that the Apache user can write to the plugins directory.</strong></li>
[% ELSIF ( ERROR.RESTRICTED ) %]<li><strong>Cannot install plugin from unknown source whilst plugins_restricted is enabled.<br /></strong></li>
[% ELSE %]<li><strong>[% ERROR.CORERR | html %] An unknown error has occurred.<br />Please review the error log for more details.</strong></li>[% END %]
[% END %]
</div>

View file

@ -59,7 +59,7 @@ if ($plugins_enabled) {
);
$template->param( plugins => \@plugins, );
$template->param( enable_browser_upload => C4::Context->config('enable_plugin_browser_upload') );
$template->param( plugins_restricted => C4::Context->config('plugins_restricted') );
$template->param( can_search => C4::Context->config('plugin_repos') ? 1 : 0 );
my @results;

View file

@ -38,10 +38,9 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
}
);
my $browser_upload_enabled = C4::Context->config('enable_plugin_browser_upload');
my $class = $input->param('class');
if ( $browser_upload_enabled && $class ) {
if ( $class ) {
Koha::Plugins::Handler->delete( { class => $class } );
}

View file

@ -20,31 +20,36 @@ use Modern::Perl;
use Archive::Extract;
use CGI qw ( -utf8 );
use List::Util qw( any );
use Mojo::UserAgent;
use File::Temp;
use C4::Context;
use C4::Auth qw( get_template_and_user );
use C4::Auth qw( get_template_and_user );
use C4::Output qw( output_html_with_http_headers );
use C4::Members;
use Koha::Logger;
use Koha::Plugins;
my $plugins_enabled = C4::Context->config("enable_plugins");
my $browser_upload_enabled = C4::Context->config('enable_plugin_browser_upload');
my $plugins_enabled = C4::Context->config("enable_plugins");
my $plugins_restricted = C4::Context->config("plugins_restricted");
my $input = CGI->new;
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
{ template_name => ($plugins_enabled && $browser_upload_enabled) ? "plugins/plugins-upload.tt" : "plugins/plugins-disabled.tt",
{
template_name => $plugins_enabled ? "plugins/plugins-upload.tt" : "plugins/plugins-disabled.tt",
query => $input,
type => "intranet",
flagsrequired => { plugins => 'manage' },
flagsrequired => { plugins => 'manage' },
}
);
if ($plugins_enabled){
$template->param( browser_upload_enabled => $browser_upload_enabled );
if ($plugins_enabled) {
$template->param( plugins_restricted => $plugins_restricted );
} else {
# Exit early if uploads are not enabled
output_html_with_http_headers $input, $cookie, $template->output;
}
my $uploadfilename = $input->param('uploadfile');
@ -56,7 +61,7 @@ my ( $tempfile, $tfh );
my %errors;
if ($plugins_enabled && $browser_upload_enabled) {
if ($plugins_enabled) {
if ( ( $op eq 'Upload' ) && ( $uploadfile || $uploadlocation ) ) {
my $plugins_dir = C4::Context->config("pluginsdir");
$plugins_dir = ref($plugins_dir) eq 'ARRAY' ? $plugins_dir->[0] : $plugins_dir;
@ -67,22 +72,39 @@ if ($plugins_enabled && $browser_upload_enabled) {
$filesuffix = $1 if $uploadfilename =~ m/(\..+)$/i;
( $tfh, $tempfile ) = File::Temp::tempfile( SUFFIX => $filesuffix, UNLINK => 1 );
$errors{'NOTKPZ'} = 1 if ( $uploadfilename !~ /\.kpz$/i );
$errors{'NOTKPZ'} = 1 if ( $uploadfilename !~ /\.kpz$/i );
$errors{'NOWRITETEMP'} = 1 unless ( -w $dirname );
$errors{'NOWRITEPLUGINS'} = 1 unless ( -w $plugins_dir );
if ( $uploadlocation ) {
my $ua = Mojo::UserAgent->new(max_redirects => 5);
my $tx = $ua->get($uploadlocation);
$tx->result->content->asset->move_to($tempfile);
if ($uploadlocation) {
my $do_get = 1;
if ( $plugins_restricted ) {
my $repos = C4::Context->config('plugin_repos');
# Fix data structure if only one repo defined
if ( ref($repos->{repo}) eq 'HASH' ) {
$repos = { repo => [ $repos->{repo} ] };
}
$do_get = any { index($uploadlocation, $_->{org_name}) != -1 } @{ $repos->{repo} };
}
if ( $do_get ) {
my $ua = Mojo::UserAgent->new( max_redirects => 5 );
my $tx = $ua->get($uploadlocation);
$tx->result->content->asset->move_to($tempfile);
} else {
$errors{'RESTRICTED'} = 1;
}
} else {
$errors{'EMPTYUPLOAD'} = 1 unless ( length($uploadfile) > 0 );
$errors{'RESTRICTED'} = 1 unless ( !$plugins_restricted );
$errors{'EMPTYUPLOAD'} = 1 unless ( length($uploadfile) > 0 );
}
if (%errors) {
$template->param( ERRORS => [ \%errors ] );
} else {
if ( $uploadfile ) {
if ($uploadfile && !$plugins_restricted) {
while (<$uploadfile>) {
print $tfh $_;
}
@ -104,7 +126,7 @@ if ($plugins_enabled && $browser_upload_enabled) {
warn "Problem uploading file or no file uploaded.";
}
if ( ($uploadfile || $uploadlocation) && !%errors && !$template->param('ERRORS') ) {
if ( ( $uploadfile || $uploadlocation ) && !%errors && !$template->param('ERRORS') ) {
print $input->redirect("/cgi-bin/koha/plugins/plugins-home.pl");
} else {
output_html_with_http_headers $input, $cookie, $template->output;