Compare commits

...

10 Commits

Author SHA1 Message Date
Ilia Ross
7231eedf20 Fix param name 2024-06-21 20:11:32 +03:00
Ilia Ross
d69609f49a Fix to consider unsafe params in index page referer check 2024-06-21 20:05:04 +03:00
Ilia Ross
fbee8f0588 Add logging for active FTP conns 2024-06-20 20:04:19 +03:00
Jamie Cameron
e077b4da94 Start of work on support for requesting only a subset of hostnames 2024-06-19 22:05:22 -07:00
Jamie Cameron
38efad8265 Escape some inputs 2024-06-19 20:37:25 -07:00
Jamie Cameron
4d2a1fa084 Add spam folder name 2024-06-19 17:19:51 -07:00
Jamie Cameron
13b2eca3b1 Follow webmin code standards 2024-06-19 16:48:41 -07:00
Ilia Ross
aa4c3b1de6 Fix embedded styles margin 2024-06-19 16:55:25 +03:00
Ilia Ross
edaab4fd6f Fix embedded styles 2024-06-19 16:52:04 +03:00
Jamie Cameron
6fded0862c Merge pull request #2201 from webmin/dev/fix-last-command-match-freebsd
Fix listing last logins in FreeBSD
2024-06-18 16:16:37 -07:00
9 changed files with 109 additions and 56 deletions

View File

@@ -21,7 +21,7 @@ if ($in{'source'} == 0) {
if (!$in{'local'})
{ &install_error($text{'download_elocal'}); }
if (!-r $in{'local'})
{ &install_error(&text('download_elocal2', $in{'local'})); }
{ &install_error(&text('download_elocal2', &html_escape($in{'local'}))); }
$source = $in{'local'};
@pfile = ( $in{'local'} );
$need_unlink = 0;
@@ -91,8 +91,9 @@ elsif ($in{'source'} == 3) {
$i = 0;
@fallback = ( );
foreach $yum (@cpanyum) {
print &text('download_yum', "<tt>$cpan[$i]</tt>",
"<tt>$yum->{'package'}</tt>"),"<br>\n";
print &text('download_yum',
"<tt>".&html_escape($cpan[$i])."</tt>",
"<tt>".&html_escape($yum->{'package'})."</tt>"),"<br>\n";
print "<ul>\n";
@got = &software::update_system_install(
$yum->{'package'});
@@ -154,7 +155,8 @@ elsif ($in{'source'} == 3) {
# Fail if any modules are missing from CPAN
for($i=0; $i<@cpan; $i++) {
push(@missing, "<tt>$cpan[$i]</tt>") if (!$source[$i]);
push(@missing, "<tt>".&html_escape($cpan[$i])."</tt>")
if (!$source[$i]);
}
if ($in{'missingok'}) {
@@ -167,11 +169,12 @@ elsif ($in{'source'} == 3) {
}
}
@cpan || &install_error(&text('download_ecpan',
join(" ", @missing)));
&html_escape(join(" ", @missing))));
}
elsif (@missing) {
# Fail due to missing modules
&install_error(&text('download_ecpan', join(" ", @missing)));
&install_error(&text('download_ecpan',
&html_escape(join(" ", @missing))));
}
$source = join("<br>", @source);
@@ -192,14 +195,16 @@ elsif ($in{'source'} == 3) {
&ftp_download($host, $file, $pfile, \$error,
\&progress_callback);
}
else { &install_error(&text('download_eurl', $m)); }
else {
&install_error(&text('download_eurl',&html_escape($m)));
}
&install_error($error) if ($error);
push(@pfile, $pfile);
}
$need_unlink = 1;
}
else {
&error("Unknown source mode $in{'source'}");
&error("Unknown source mode ".&html_escape($in{'source'}));
}
# Check if the file looks like a perl module
@@ -287,7 +292,7 @@ foreach $d (@dirs) {
close(MAKEFILE);
push(@allreqs, @prereqs);
}
system("rm -rf $mtemp");
&unlink_file($mtemp);
# Work out which pre-requesites are missing
@allreqs = &unique(@allreqs);

View File

@@ -1,7 +1 @@
body blockquote:not([style*="border-left"]) {
border-left: 1px solid #ccc;
margin-left: 6px;
margin-top: 0;
margin-bottom: 0;
padding-left: 12px;
}
body blockquote:not([style*="border-left"]){border-left:1px solid #ccc;margin-left:6px;margin-top:0;margin-bottom:0;padding-left:12px;}pre{white-space:break-spaces;margin:0 0 4px 0}

View File

@@ -332,6 +332,7 @@ folder_inbox=Inbox
folder_sent=Sent
folder_drafts=Drafts
folder_trash=Trash
folder_spam=Spam
detach_err=Failed to detach file
detach_edir=No file or directory to save to entered

View File

@@ -44,9 +44,10 @@ while(1) {
# jcameron pts/0 fudu Sun Feb 4 02:26:28 2024 - Wed Feb 7 18:25:09 2024 (3+15:58)
return ($1, $2, $3, $4, $5 eq "down" ? "Shutdown" : $5, $6);
}
elsif ($line =~ /^(\S+)\s+(\S+)\s+(\S+)?\s+(\S+\s+\S+\s+\d+\s+\d+:\d+)\s+still/ ||
$line =~ /^(\S+)\s+(\S+)\s+(\S+)?\s+(\S+\s+\S+\s+\d+\s+\d+:\d+:\d+\s+\d+)\s+still/) {
elsif ($line =~ /^(\S+)\s+(\S+)\s+(\S+)?\s+(\S+\s+\S+\s+\d+\s+\d+:\d+)\s+(still|gone)/ ||
$line =~ /^(\S+)\s+(\S+)\s+(\S+)?\s+(\S+\s+\S+\s+\d+\s+\d+:\d+:\d+\s+\d+)\s+(still|gone)/) {
# root pts/0 fudu Fri Feb 23 18:46 still logged in
# root ftpd10 fudu Thu Jun 20 11:19 gone - no logout
# root pts/0 fudu Tue Jun 18 23:10:30 2024 still logged in
return ($1, $2, $3, $4);
}

View File

@@ -2098,10 +2098,10 @@ formatted like dd/mmm/yyyy hh:mm:ss. Parameters are :
=item seconds - Unix time is seconds to convert.
=item date-only-or-opts - If set to 1, exclude the time from the returned string.
=item date-only-or-opts - If set to 1 exclude the time from the returned string.
In case this param is a hash reference use it for options in a new DateTime::Locale
code or preserve the original, old logic
In case this param is a hash reference use it for options in a new
DateTime::Locale code or preserve the original, old logic
=item fmt - Optional, one of dd/mon/yyyy, dd/mm/yyyy, mm/dd/yyyy or yyyy/mm/dd
@@ -2116,27 +2116,31 @@ if (!$@ && $] > 5.011) {
my $opts = ref($only) ? $only : {};
my $locale_default = &get_default_system_locale();
my $locale_auto = &parse_accepted_language();
my $locale_name = $opts->{'locale'} || $gconfig{'locale_'.$base_remote_user} ||
my $locale_name = $opts->{'locale'} ||
$gconfig{'locale_'.$base_remote_user} ||
$gconfig{'locale_'.$remote_user} || $locale_auto ||
$gconfig{'locale'} || &get_default_system_locale();
my $tz = $opts->{'tz'};
if (!$tz) {
eval {
$tz =
DateTime::TimeZone->new(name => strftime("%z", localtime()))->name(); # +0200
$tz = DateTime::TimeZone->new(
name => strftime("%z", localtime()))->name(); # +0200
};
if ($@) {
eval {
$tz = DateTime::TimeZone->new(name => 'local')->name(); # Asia/Nicosia
$tz = DateTime::TimeZone->new(
name => 'local')->name(); # Asia/Nicosia
};
if ($@) {
$tz = DateTime::TimeZone->new(name => 'UTC')->name(); # UTC
$tz = DateTime::TimeZone->new(
name => 'UTC')->name(); # UTC
}
}
}
# Pre-process time locale
my $locale_military_status = sub {
return ($locale_military_name && $locale_military_name =~ /[a-z]/i) ? 2 :
return ($locale_military_name &&
$locale_military_name =~ /[a-z]/i) ? 2 :
($locale_military_name == 1) ? 1 : 0;
};
# Allow locales with military time (in 24h format)
@@ -2152,15 +2156,18 @@ if (!$@ && $] > 5.011) {
my $locale = DateTime::Locale->load($locale_name_loaded);
# Create a new locale out of base locale
if (&$locale_military_status() == 1) {
my %locale_data = $locale->locale_data;
$locale_data{'code'} = $locale_name_initial;
my %locale_data = $locale->locale_data;
$locale_data{'code'} = $locale_name_initial;
# Force 24h time
$locale_data{'glibc_date_1_format'} = '%a %b %e %H:%M:%S %Z %Y';
$locale_data{'glibc_date_1_format'} = '%a %b %e %H:%M:%S %Z %Y';
$locale_data{'glibc_datetime_format'} = '%a %d %b %Y %T %Z';
$locale_data{'glibc_time_format'} = '%T';
$locale_data{'glibc_time_format'} = '%T';
DateTime::Locale->register_from_data(%locale_data);
# Load newly cloned locale in 24h time format
$locale_military_name = $locale_name_loaded = $locale_name_initial;
$locale_military_name = $locale_name_loaded =
$locale_name_initial;
$locale = DateTime::Locale->load($locale_name_loaded);
}
my $locale_format_full_tz = $locale->glibc_date_1_format; # Sat 20 Nov 2286 17:46:39 UTC
@@ -2194,18 +2201,31 @@ if (!$@ && $] > 5.011) {
"pretty" => $ago_obj->pretty
};
}
# my $xxxx = $locale->full_date_format;
my $data = {
# Wed Feb 8 05:09:39 PM UTC 2023
'full-tz-utc' => DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs)->strftime($locale_format_full_tz),
'full-tz-utc' => DateTime->from_epoch(
locale => $locale_name_loaded,
epoch => $secs)->strftime($locale_format_full_tz),
# Wed Feb 8 07:10:01 PM EET 2023
'full-tz' => DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime($locale_format_full_tz),
'full-tz' => DateTime->from_epoch(
locale => $locale_name_loaded,
epoch => $secs,
time_zone => $tz)->strftime($locale_format_full_tz),
# Wed 08 Feb 2023 07:11:26 PM EET
'full' => DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime($locale_format_full),
'full' => DateTime->from_epoch(
locale => $locale_name_loaded,
epoch => $secs,
time_zone => $tz)->strftime($locale_format_full),
# 02/08/2023
'short' => DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime($locale_format_short),
'short' => DateTime->from_epoch(
locale => $locale_name_loaded,
epoch => $secs,
time_zone => $tz)->strftime($locale_format_short),
# 07:12:07 PM
'time' => DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime($locale_format_time),
'time' => DateTime->from_epoch(
locale => $locale_name_loaded,
epoch => $secs,
time_zone => $tz)->strftime($locale_format_time),
'ago' => $ago,
'tz' => $tz,
'delimiter' => $locale_format_delimiter,
@@ -2216,10 +2236,16 @@ if (!$@ && $] > 5.011) {
$data->{'timeshort'} = $data->{'time'};
$data->{'timeshort'} =~ s/(\d+):(\d+):(\d+)(.*?)/$1:$2$4/;
# %c alternative with full week and month and no seconds in time (complete)
# Wednesday, February 8, 2023, 8:18 PM or 星期三, 2023年2月8日 20:18 or miércoles, 8 febrero 2023, 20:28
$data->{'monthfull'} = DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%B");
foreach (split(/\s+/, DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%A, %c"))) {
# %c alternative with full week and month and no seconds
# in time (complete)
# Wednesday, February 8, 2023, 8:18 PM or 星期三,
# 2023年2月8日 20:18 or miércoles, 8 febrero 2023, 20:28
$data->{'monthfull'} = DateTime->from_epoch(
locale => $locale_name_loaded, epoch => $secs,
time_zone => $tz)->strftime("%B");
foreach (split(/\s+/, DateTime->from_epoch(
locale => $locale_name_loaded, epoch => $secs,
time_zone => $tz)->strftime("%A, %c"))) {
if ($data->{'monthfull'} =~ /^$_/) {
$data->{'complete'} .= "$data->{'monthfull'} "
}
@@ -2227,13 +2253,24 @@ if (!$@ && $] > 5.011) {
$data->{'complete'} .= "$_ "
}
};
$data->{'year'} = DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%Y");
$data->{'day'} = DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%d");
$data->{'week'} = DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%a");
$data->{'weekfull'} = DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%A");
$data->{'month'} = DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%b");
$data->{'year'} = DateTime->from_epoch(
locale => $locale_name_loaded, epoch => $secs,
time_zone => $tz)->strftime("%Y");
$data->{'day'} = DateTime->from_epoch(
locale => $locale_name_loaded, epoch => $secs,
time_zone => $tz)->strftime("%d");
$data->{'week'} = DateTime->from_epoch(
locale => $locale_name_loaded, epoch => $secs,
time_zone => $tz)->strftime("%a");
$data->{'weekfull'} = DateTime->from_epoch(
locale => $locale_name_loaded, epoch => $secs,
time_zone => $tz)->strftime("%A");
$data->{'month'} = DateTime->from_epoch(
locale => $locale_name_loaded, epoch => $secs,
time_zone => $tz)->strftime("%b");
$data->{'complete'} =~ s/(\d+):(\d+):(\d+)(.*?)/$1:$2$4/;
($data->{'complete_short'} = $data->{'complete'}) =~ s/(.*?)([\s\,]*\Q$data->{'year'}\E.*)/$1/;
($data->{'complete_short'} = $data->{'complete'}) =~
s/(.*?)([\s\,]*\Q$data->{'year'}\E.*)/$1/;
if ($opts->{'get'}) {
return $data->{$opts->{'get'}};
@@ -5503,6 +5540,7 @@ my $unsafe_index = $unsafe_index_cgi ||
&get_module_variable('$unsafe_index_cgi');
my $trustvar = $trust_unknown_referers ||
&get_module_variable('$trust_unknown_referers');
my $unsafe_params = $ENV{'REQUEST_URI'} =~ /xhr/i;
my $trust = 0;
if (!$0) {
# Script name not known
@@ -5518,7 +5556,7 @@ elsif ($ENV{'DISABLE_REFERERS_CHECK'}) {
}
elsif (($ENV{'SCRIPT_NAME'} =~ /^\/(index.cgi)?$/ ||
$ENV{'SCRIPT_NAME'} =~ /^\/([a-z0-9\_\-]+)\/(index.cgi)?$/i) &&
!$unsafe_index) {
!$unsafe_index && !$unsafe_params) {
# Script is a module's index.cgi, which is normally safe
$trust = 1;
}

View File

@@ -277,7 +277,9 @@ else {
my @doms = $config{'letsencrypt_doms'} ?
split(/\s+/, $config{'letsencrypt_doms'}) : ( $host );
print &ui_table_row($text{'ssl_letsdoms'},
&ui_textarea("dom", join("\n", @doms), 5, 40));
&ui_textarea("dom", join("\n", @doms), 5, 40)."<br>\n".
&ui_checkbox("subset", 1, $text{'ssl_subset'},
$config{'letsencrypt_subset'}));
# Apache vhost or other path
my @opts;

View File

@@ -424,6 +424,7 @@ ssl_letserr2=Alternately, check the <a href='$1'>module configuration</a> page t
ssl_letsdesc2=This page can be used to request a new certificate, which will overwrite any other currently have configured in Webmin. However, the Let's Encrypt service requires that your ownership of the certificate domain be validated by checking that this system hosts the website for the domain. This is done by placing a small temporary file in the website's document directory.
ssl_letsheader=Options for new SSL certificate
ssl_letsdoms=Hostnames for certificate
ssl_subset=Skip unverifiable hostnames?
ssl_letsmode=Let's Encrypt validation method
ssl_letsmode0=Apache virtual host matching hostname
ssl_letsmode1=Selected Apache virtual host

View File

@@ -58,14 +58,15 @@ return &software::missing_install_link(
# request_letsencrypt_cert(domain|&domains, webroot, [email], [keysize],
# [request-mode], [use-staging], [account-email],
# [reuse-key], [server-url, server-key, server-hmac])
# [reuse-key], [server-url, server-key, server-hmac],
# [allow-subset])
# Attempt to request a cert using a generated key with the Let's Encrypt client
# command, and write it to the given path. Returns a status flag, and either
# an error message or the paths to cert, key and chain files.
sub request_letsencrypt_cert
{
my ($dom, $webroot, $email, $size, $mode, $staging, $account_email,
$key_type, $reuse_key, $server, $server_key, $server_hmac) = @_;
$key_type, $reuse_key, $server, $server_key, $server_hmac, $subset) = @_;
my @doms = ref($dom) ? @$dom : ($dom);
$email ||= "root\@$doms[0]";
$mode ||= "web";
@@ -179,6 +180,7 @@ if ($letsencrypt_cmd) {
my $new_flags = "";
my $reuse_flags = "";
my $server_flags = "";
my $subset_flags = "";
$key_type ||= $config{'letsencrypt_algo'} || 'rsa';
if (&compare_version_numbers($cmd_ver, 1.11) < 0) {
$old_flags = " --manual-public-ip-logging-ok";
@@ -192,6 +194,9 @@ if ($letsencrypt_cmd) {
else {
$reuse_flags = " --no-reuse-key";
}
if ($subset) {
$subset_flags = " --allow-subset-of-names";
}
$reuse_flags = "" if ($reuse_key && $reuse_key == -1);
if ($server) {
$server_flags = " --server ".quotemeta($server);
@@ -227,6 +232,7 @@ if ($letsencrypt_cmd) {
$old_flags.
$server_flags.
$new_flags.
$subset_flags.
" 2>&1)");
&reset_environment();
}
@@ -245,6 +251,7 @@ if ($letsencrypt_cmd) {
$old_flags.
$server_flags.
$new_flags.
$subset_flags.
" 2>&1)");
&reset_environment();
}
@@ -260,6 +267,7 @@ if ($letsencrypt_cmd) {
$old_flags.
$server_flags.
$new_flags.
$subset_flags.
" 2>&1)");
&reset_environment();
}

View File

@@ -76,7 +76,7 @@ else {
if ($in{'save'}) {
# Just update renewal
&save_renewal_only(\@doms, $webroot, $mode);
&save_renewal_only(\@doms, $webroot, $mode, $size, $in{'subset'});
&redirect("edit_ssl.cgi");
}
else {
@@ -88,7 +88,9 @@ else {
'letsencrypt_doing',
"<tt>".&html_escape(join(", ", @doms))."</tt>",
"<tt>".&html_escape($webroot)."</tt>"),"<p>\n";
my ($ok, $cert, $key, $chain) = &request_letsencrypt_cert(\@doms, $webroot, undef, $size, $mode, $in{'staging'});
my ($ok, $cert, $key, $chain) = &request_letsencrypt_cert(
\@doms, $webroot, undef, $size, $mode, $in{'staging'},
undef, 0, undef, undef, undef, $in{'subset'});
if (!$ok) {
print &text('letsencrypt_failed', $cert),"<p>\n";
}
@@ -148,15 +150,16 @@ else {
&ui_print_footer("", $text{'index_return'});
}
# save_renewal_only(&doms, webroot, mode)
# save_renewal_only(&doms, webroot, mode, size, subset-mode)
# Save for future renewals
sub save_renewal_only
{
my ($doms, $webroot, $mode) = @_;
my ($doms, $webroot, $mode, $size, $subset) = @_;
$config{'letsencrypt_doms'} = join(" ", @$doms);
$config{'letsencrypt_webroot'} = $webroot;
$config{'letsencrypt_mode'} = $mode;
$config{'letsencrypt_size'} = $size;
$config{'letsencrypt_subset'} = $subset;
&save_module_config();
if (&foreign_check("webmincron")) {
my $job = &find_letsencrypt_cron_job();