Merge pull request #1910 from webmin/dev/safely-read-potentially-dangerous-files

Add ability to read potentially dangerous files safely or force download
This commit is contained in:
Jamie Cameron
2023-05-22 19:50:16 -07:00
committed by GitHub
7 changed files with 53 additions and 129 deletions

View File

@@ -245,16 +245,7 @@ sub main
talk('affected', \%opt, \%data);
# Run in overwrite mode
if ($opt{'mode'} eq 'clean') {
# # Execute clean
talk('clean-pre', \%opt, \%data);
if (prompt('next')) {
go(\%opt, \%data);
}
}
# Run in overwrite mode
elsif ($opt{'mode'} eq 'full') {
if ($opt{'mode'} eq 'full') {
# Execute force transcode/translate
talk('overwrite-pre', \%opt, \%data);
@@ -958,7 +949,6 @@ sub go
my $verbose = $opt->{'verbose'} || @{$keys_test};
my $mode_sync = $opt->{'mode'} ne 'full';
my $mode_transcode = $opt->{'mode'} eq 'transcode';
my $mode_clean = $opt->{'mode'} eq 'clean';
my $allow_symlinks = $opt->{'allow-symlinks'};
my $verbose_silent_mode = $mode_sync && $verbose != 2;
@@ -975,12 +965,6 @@ sub go
# Check if there has been something to process, if not print a message
my $output;
# If cleaning called in this mode, throw an error
if ($mode_clean) {
say RED, "Error: Cleaning can only be performed when the target type is unset!", RESET;
exit;
}
# Build targets first
talk_log(("Transcoding/translating " . CYAN BOLD, $module, RESET . " module's help .."), $data, 1);
@@ -1216,7 +1200,6 @@ sub go
# Set message type
my $message_type_s1 = 'Transcoding/translating';
$message_type_s1 = 'Searching/replacing in' if (@{$values_fix});
$message_type_s1 = 'Cleaning in' if ($mode_clean);
talk_log(("$message_type_s1 " . BLUE BOLD, $module, RESET . " module .."), $data, 1);
foreach $language (@{ $data->{'languages_source_list'} }) {
@@ -1240,51 +1223,6 @@ sub go
my %language;
my %language_auto;
# If in clean mode delete the file and go next
if ($mode_clean) {
# Language files
my $cfile = "$mpath/$code";
my $cfileauto = "$cfile.auto";
unlink($cfile);
unlink($cfileauto);
# Module files
foreach ('module', 'config', 'uconfig') {
my %mdata = %{$data};
$mdata{'type'} = $_;
my (undef, undef, $ffile) = source_data($module, \%mdata, $opt);
$ffile =~ s/\/$_\//\//;
my $cxfile = "$ffile.$code";
my $cxfileauto = "$cxfile.auto";
unlink($cxfile);
unlink($cxfileauto);
}
# Help files
my %hdata = %{$data};
$hdata{'type'} = 'help';
my (undef, $hpath) = source_data($module, \%hdata, $opt);
my @hdelete_targets;
if (-d $hpath) {
find(
{
wanted => sub {
my $found = $File::Find::name;
if ($found =~ /\.$code\./) {
push(@hdelete_targets, $found);
}
},
},
$hpath);
unlink(@hdelete_targets);
}
# Go next, don't translate
$output++;
next;
}
my $message_type_s2 = "Processing";
$message_type_s2 = "Testing translations for selected keys with" if (@{$keys_test});
@@ -1794,10 +1732,6 @@ sub talk
say GREEN, "Affected languages" . RESET, DARK . " [$languages_count]" . RESET . ": ", YELLOW BOLD,
"" . $languages . "", RESET;
}
if ($what eq 'clean-pre') {
say RED, "Danger! ", RESET, WHITE,
"The following operation will delete all files related to the affected lang-\nuage, including machine-translated files in all the mentioned modules listed above.",
}
if ($what eq 'overwrite-pre') {
say RED, "Warning! ", RESET, WHITE,
"The following operation will force-translate and overwrite mentioned\nlanguages in all mentioned modules listed above, using ",
@@ -1895,13 +1829,9 @@ Test translations for "index_stopmsg,trusted_warning" keys, in Russian and Germa
- webmin language-manager -m=bind8 -t=ru,de -kt=index_stopmsg,trusted_warning
Clean build directory by removing all kind of language files except English.
- webmin language-manager --mode=clean
=item --mode, -x <sync|full|transcode>
Mode can be either <sync> or <full> or <transcode> or <clean>. Default is set to "sync" and will only keep the keys found on template language file, while missing keys in target languages (translations), will be deleted, and newly added keys to template language file, will be translated. Mode "full" is meant to perform full translation, keeping human translated strings and overwriting all machine translations done in the past (not recommended to run). Mode "transcode" is useful to fix human translated language files, which stored in "utf-8" encoding already, while still having "&#195;&#173;" or "&#195;&#169;" HTML entities. Mode "clean" is useful to clean build package by removing all kind of language files except source language.
Mode can be either <sync> or <full> or <transcode>. Default is set to "sync" and will only keep the keys found on template language file, while missing keys in target languages (translations), will be deleted, and newly added keys to template language file, will be translated. Mode "full" is meant to perform full translation, keeping human translated strings and overwriting all machine translations done in the past (not recommended to run). Mode "transcode" is useful to fix human translated language files, which stored in "utf-8" encoding already, while still having "&#195;&#173;" or "&#195;&#169;" HTML entities.
=item --type, -w <lang|ulang|help|config|uconfig|module>
@@ -1987,4 +1917,4 @@ Verbosely print processed files and provide detailed output. By detault, verbose
=head1 LICENSE AND COPYRIGHT
Copyright 2020 Ilia Rostovtsev <ilia@virtualmin.com>
Copyright 2022 Ilia Rostovtsev <ilia@virtualmin.com>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 907 B

View File

@@ -307,7 +307,6 @@ ui_paging=Showing rows $1 to $2 of $3
ui_rowlabel=$2 in row $1 :
ui_filterbox=Type to filter..
ui_of=of
ui_jsblocked=JavaScript was removed to protect your privacy!
header_statusmsg=$1 logged into $2 $3 on $4 ($5)

View File

@@ -4,30 +4,17 @@
if ($0 =~ /^(.*)\//) {
chdir($1);
}
@ARGV == 1 || @ARGV == 2 || @ARGV == 3 || usage();
@ARGV == 1 || @ARGV == 2 || usage();
if ($ARGV[0] eq "-minimal" || $ARGV[0] eq "--minimal") {
$min++;
shift(@ARGV);
}
if ($ARGV[0] =~ /^--exclude-modules/) {
$exclude_modules = $ARGV[0];
shift(@ARGV);
}
if ($ARGV[0] =~ /^--product-type/) {
$product_type = $ARGV[0];
$product_type =~ s/--product-type=//;
if ($product_type =~ /^(minimal|essential)$/) {
$product_suff = "-$product_type";
$product_pref = "$product_type-";
}
shift(@ARGV);
}
$fullvers = $ARGV[0];
$fullvers =~ /^([0-9\.]+)(\-(\d+))?$/ || usage();
$vers = $1;
$release = $3;
$tardir = $min ? "minimal" : "tarballs";
$vfile = $product_pref ? "$product_pref$fullvers" : $min ? "$fullvers-minimal" : $fullvers;
$vfile = $min ? "$fullvers-minimal" : $fullvers;
$zipdir = "zips";
$vers || usage();
@@ -76,16 +63,10 @@ else {
$mod_def_list = do { local $/; <$fh> };
close($fh);
@mlist = split(/\s+/, $mod_def_list);
if ($exclude_modules) {
$exclude_modules =~ s/--exclude-modules=//;
my @mlist_excluded =
grep { my $f = $_; ! grep $_ eq $f, split(',', $exclude_modules) } @mlist;
@mlist = @mlist_excluded;
}
}
@dirlist = ( "vendor_perl" );
$dir = "webmin$product_suff-$vers";
$dir = "webmin-$vers";
if (!$release || !-d "$tardir/$dir") {
# Copy files into the directory for tarring up, unless this is a minor
# release or a new version

View File

@@ -20,14 +20,6 @@ if ($ARGV[0] eq "--nosign" || $ARGV[0] eq "-nosign") {
$nosign = 1;
shift(@ARGV);
}
if ($ARGV[0] =~ /^--product-type/) {
$product_type = $ARGV[0];
$product_type =~ s/--product-type=//;
if ($product_type =~ /^(minimal|essential)$/) {
$product_suff = "-$product_type";
}
shift(@ARGV);
}
$ver = $ARGV[0] || die "usage: makerpm.pl <version> [release]";
$rel = $ARGV[1] || "1";
@@ -75,25 +67,23 @@ else {
$makerel = "rm -f %{buildroot}/usr/libexec/webmin/release";
}
if ($rel > 1 && -r "tarballs/webmin$product_suff-$ver-$rel.tar.gz") {
$tarfile = "webmin$product_suff-$ver-$rel.tar.gz";
if ($rel > 1 && -r "tarballs/webmin-$ver-$rel.tar.gz") {
$tarfile = "webmin-$ver-$rel.tar.gz";
}
else {
$tarfile = "webmin$product_suff-$ver.tar.gz";
$tarfile = "webmin-$ver.tar.gz";
}
system("cp tarballs/$tarfile $source_dir");
open(SPEC, ">$spec_dir/webmin$product_suff-$ver.spec");
open(SPEC, ">$spec_dir/webmin-$ver.spec");
print SPEC <<EOF;
%global __perl_provides %{nil}
%define __spec_install_post %{nil}
Summary: A web-based administration interface for Unix systems.
Name: webmin$product_suff
Name: webmin
Version: $ver
Release: $rel
Provides: webmin = %{version}-%{release}
Provides: perl(WebminCore)
Provides: %{name}-%{version} perl(WebminCore)
Requires(pre): /usr/bin/perl
Requires: /bin/sh /usr/bin/perl /bin/rm perl(lib) perl(open) perl(Net::SSLeay) perl(Time::Local) perl(Encode::Detect) perl(Data::Dumper) perl(File::Path) perl(File::Basename) perl(Digest::SHA) perl(Digest::MD5) openssl unzip tar
Recommends: perl(DateTime) perl(DateTime::TimeZone) perl(DateTime::Locale) perl(Time::Piece)
@@ -341,21 +331,21 @@ EOF
close(SPEC);
$cmd = -x "/usr/bin/rpmbuild" ? "rpmbuild" : "rpm";
system("$cmd -ba --target=noarch $spec_dir/webmin$product_suff-$ver.spec") && exit;
system("$cmd -ba --target=noarch $spec_dir/webmin-$ver.spec") && exit;
if (-d "rpm") {
system("mv $rpms_dir/webmin$product_suff-$ver-$rel.noarch.rpm rpm/webmin$product_suff-$ver-$rel.noarch.rpm");
print "Moved to rpm/webmin$product_suff-$ver-$rel.noarch.rpm\n";
system("mv $srpms_dir/webmin$product_suff-$ver-$rel.src.rpm rpm/webmin$product_suff-$ver-$rel.src.rpm");
print "Moved to rpm/webmin$product_suff-$ver-$rel.src.rpm\n";
system("chown jcameron: rpm/webmin$product_suff-$ver-$rel.noarch.rpm rpm/webmin$product_suff-$ver-$rel.src.rpm");
system("mv $rpms_dir/webmin-$ver-$rel.noarch.rpm rpm/webmin-$ver-$rel.noarch.rpm");
print "Moved to rpm/webmin-$ver-$rel.noarch.rpm\n";
system("mv $srpms_dir/webmin-$ver-$rel.src.rpm rpm/webmin-$ver-$rel.src.rpm");
print "Moved to rpm/webmin-$ver-$rel.src.rpm\n";
system("chown jcameron: rpm/webmin-$ver-$rel.noarch.rpm rpm/webmin-$ver-$rel.src.rpm");
if (!$nosign) {
system("rpm --resign rpm/webmin$product_suff-$ver-$rel.noarch.rpm rpm/webmin$product_suff-$ver-$rel.src.rpm");
system("rpm --resign rpm/webmin-$ver-$rel.noarch.rpm rpm/webmin-$ver-$rel.src.rpm");
}
}
if (!$webmail && -d "/usr/local/webadmin/rpm/yum") {
# Add to our repository
system("cp rpm/webmin$product_suff-$ver-$rel.noarch.rpm /usr/local/webadmin/rpm/yum");
system("cp rpm/webmin-$ver-$rel.noarch.rpm /usr/local/webadmin/rpm/yum");
}

View File

@@ -154,9 +154,8 @@ elsif (!$config{'no_pam'}) {
$pam_conv_func_called = 0;
$pam_username = "test";
$pam_password = "test";
my $pam_ret = $pamh->pam_authenticate();
if ($pam_conv_func_called ||
$pam_ret == PAM_SUCCESS()) {
$pamh->pam_authenticate();
if ($pam_conv_func_called) {
push(@startup_msg,
"PAM authentication enabled");
$use_pam = 1;

View File

@@ -80,14 +80,38 @@ if ($ENV{'PATH_INFO'}) {
if (!$fetch_show) {
print "Content-Disposition: Attachment\n";
}
@st = stat($file);
print "Content-length: $st[7]\n";
print "X-Content-Type-Options: nosniff\n";
print "Content-type: $type\n\n";
while(read(FILE, $buffer, &get_buffer_size_binary())) {
print("$buffer");
# Stat file
my @st = stat($file);
my $fsize = $st[7];
# Get and analyze the file contents first
my $fdata = "";
my $dangertypes = $type =~ /html|xml|pdf/i;
my $htmltype = $type =~ /html/i ? 1 : 0;
my $pdftype = $type =~ /pdf/i ? 'pdf' : 0;
my $bsize =
$dangertypes ? $fsize : &get_buffer_size_binary();
while(read(FILE, $buffer, $bsize)) {
if ($dangertypes) {
my $buffer_filtered = &filter_javascript($buffer, $pdftype);
# If content was changed upon
# filtering force download it
if ($buffer_filtered ne $buffer) {
$type = "application/octet-stream";
print "Content-Disposition: Attachment\n";
}
$fdata = $buffer;
}
else {
$fdata .= $buffer;
}
}
close(FILE);
print "Content-length: $fsize\n";
print "X-Content-Type-Options: nosniff\n";
print "Content-type: $type\n\n";
print "$fdata";
}
# Switch back to root
@@ -119,3 +143,4 @@ else {
&redirect("fetch.cgi".$file);
}
}