mirror of
https://github.com/webmin/webmin.git
synced 2026-08-21 14:30:41 +01:00
Compare commits
15 Commits
2.650
...
dev/req-tr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
463fcea730 | ||
|
|
a94ff2c49a | ||
|
|
ec78452e7b | ||
|
|
a7325b9087 | ||
|
|
cc4bb35dee | ||
|
|
aa2282778e | ||
|
|
1c9d57f5dd | ||
|
|
4ffa02d636 | ||
|
|
57ad5fa535 | ||
|
|
a3f5ea3381 | ||
|
|
2579cf54d9 | ||
|
|
fa06c02be5 | ||
|
|
d02f0b6cb5 | ||
|
|
81d44f8491 | ||
|
|
6135c01d57 |
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,5 +1,16 @@
|
||||
## Changelog
|
||||
|
||||
#### 2.652 (July, 2026)
|
||||
* Fix to recognize hex numeric HTML entities to work in various elements
|
||||
|
||||
#### 2.651 (June 28, 2026)
|
||||
* Fix Certbot-backed certificate requests and renewals to correctly parse PEM paths after issuance
|
||||
* Fix live activation of Linux bond interfaces [#2777](https://github.com/webmin/webmin/pull/2777)
|
||||
* Update the Authentic theme to the latest version with various improvements and fixes:
|
||||
- Fix search-result all-items delete in File Manager
|
||||
- Fix search-result delete ordering in File Manager
|
||||
- Fix to speed up search-result deletion cleanup in File Manager
|
||||
|
||||
#### 2.650 (June 25, 2026)
|
||||
* Add new Systemd Services and Units module
|
||||
* Add new GRUB 2 Boot Loader module
|
||||
@@ -32,8 +43,9 @@
|
||||
* Fix PHP-FPM monitor on EL systems when using `/etc/php.ini` as the config file
|
||||
* Fix RPC-only accounts to block browser/module access before module ACL checks
|
||||
* Fix reflected XSS in Webmin status messages
|
||||
* Fix authentication state handling for SSL certificate logins and proxied keep-alive requests
|
||||
* Fix path validation in File Manager, package delete helpers, and Apache virtual host files
|
||||
* Fix authentication state handling for SSL certificate logins and proxied keep-alive requests
|
||||
* Update session handling to improve security, which will require users to re-authenticate after upgrading
|
||||
* Update the Authentic theme to the latest version with various improvements and fixes:
|
||||
- Add zooming to stats history graphs by holding shift and scrolling in the dashboard
|
||||
- Add support for saving live stats history for up to 24 hours without performance impact
|
||||
|
||||
2
custom/safeacl
Normal file
2
custom/safeacl
Normal file
@@ -0,0 +1,2 @@
|
||||
edit=0
|
||||
cmds=*
|
||||
BIN
gray-theme/grub2/images/icon.gif
Normal file
BIN
gray-theme/grub2/images/icon.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
BIN
gray-theme/kea-dhcp/images/icon.gif
Normal file
BIN
gray-theme/kea-dhcp/images/icon.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
BIN
grub2/images/icon.gif
Normal file
BIN
grub2/images/icon.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
kea-dhcp/images/icon.gif
Normal file
BIN
kea-dhcp/images/icon.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 311 B |
25
miniserv.pl
25
miniserv.pl
@@ -1542,16 +1542,25 @@ if ($headerhost) {
|
||||
$headerhost = undef if (!&check_ipaddress($headerhost) &&
|
||||
!&check_ip6address($headerhost));
|
||||
}
|
||||
# If trusted_proxies is configured, header-supplied client IP and SSL
|
||||
# client info are only honored when the direct TCP peer is in that list.
|
||||
# Otherwise drop them so an attacker reaching miniserv directly cannot
|
||||
# spoof X-Forwarded-For or X-SSL-Client-* to bypass auth.
|
||||
if ($config{'trust_real_ip'} && $config{'trusted_proxies'} ne '' &&
|
||||
!&ip_match($acptip, $localip,
|
||||
split(/\s+/, $config{'trusted_proxies'}))) {
|
||||
# If trusted_proxies is configured, header-supplied client IP is only
|
||||
# honored when the direct TCP peer is in that list. Proxied SSL client
|
||||
# cert headers carry authentication identity, so only honor those from
|
||||
# an explicitly trusted proxy.
|
||||
my @trusted_proxies = split(/\s+/, $config{'trusted_proxies'} || "");
|
||||
my $trusted_proxy = @trusted_proxies &&
|
||||
&ip_match($acptip, $localip, @trusted_proxies);
|
||||
my $trust_ssl_client_headers = $config{'trust_real_ip'} &&
|
||||
!$config{'no_trust_ssl'} && $trusted_proxy;
|
||||
if ($config{'trust_real_ip'} && @trusted_proxies && !$trusted_proxy) {
|
||||
print DEBUG "handle_request: peer $acptip not in trusted_proxies; ".
|
||||
"ignoring forwarding and SSL client headers\n";
|
||||
"ignoring forwarding headers\n";
|
||||
$headerhost = undef;
|
||||
}
|
||||
if (!$trust_ssl_client_headers) {
|
||||
print DEBUG "handle_request: ignoring SSL client headers from ".
|
||||
"peer $acptip\n"
|
||||
if ($header{'x-ssl-client-dn'} ||
|
||||
$header{'x-ssl-client-verify'});
|
||||
delete $header{'x-ssl-client-dn'};
|
||||
delete $header{'x-ssl-client-verify'};
|
||||
}
|
||||
|
||||
@@ -258,7 +258,44 @@ if (&has_command("ip") && $a->{'virtual'} ne '' && !$a->{'up'}) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!&has_command("ifconfig") && &has_command("ip")) {
|
||||
if (&has_command("ip") && $a->{'bond'} && $a->{'up'} && !$old) {
|
||||
# Create the bond before assigning addresses to it.
|
||||
my $bcmd = "ip link add ".quotemeta($a->{'name'})." type bond";
|
||||
if (defined($a->{'mode'}) && $a->{'mode'} ne '') {
|
||||
$bcmd .= " mode ".quotemeta(&bond_mode_name($a->{'mode'}));
|
||||
}
|
||||
if ($a->{'miimon'}) {
|
||||
$bcmd .= " miimon ".quotemeta($a->{'miimon'});
|
||||
}
|
||||
if ($a->{'updelay'}) {
|
||||
$bcmd .= " updelay ".quotemeta($a->{'updelay'});
|
||||
}
|
||||
if ($a->{'downdelay'}) {
|
||||
$bcmd .= " downdelay ".quotemeta($a->{'downdelay'});
|
||||
}
|
||||
my $out = &backquote_logged("$bcmd 2>&1");
|
||||
&error("Failed to create bond device : $out") if ($?);
|
||||
foreach my $slave (grep { $_ ne '' } split(/\s+/, $a->{'partner'})) {
|
||||
$bcmd = "ip link set dev ".quotemeta($slave)." down";
|
||||
$out = &backquote_logged("$bcmd 2>&1");
|
||||
&error("Failed to bring down bond slave : $out") if ($?);
|
||||
$bcmd = "ip link set dev ".quotemeta($slave)." master ".
|
||||
quotemeta($a->{'name'});
|
||||
$out = &backquote_logged("$bcmd 2>&1");
|
||||
&error("Failed to add bond slave : $out") if ($?);
|
||||
$bcmd = "ip link set dev ".quotemeta($slave)." up";
|
||||
$out = &backquote_logged("$bcmd 2>&1");
|
||||
&error("Failed to bring up bond slave : $out") if ($?);
|
||||
}
|
||||
if ($a->{'primary'}) {
|
||||
$bcmd = "ip link set dev ".quotemeta($a->{'name'}).
|
||||
" type bond primary ".quotemeta($a->{'primary'});
|
||||
$out = &backquote_logged("$bcmd 2>&1");
|
||||
&error("Failed to set bond primary interface : $out") if ($?);
|
||||
}
|
||||
}
|
||||
|
||||
if (($a->{'bond'} || !&has_command("ifconfig")) && &has_command("ip")) {
|
||||
# For a real interface, activate or de-activate the link
|
||||
if ($a->{'virtual'} eq '' && $a->{'up'} && (!$old || !$old->{'up'})) {
|
||||
# Bring up
|
||||
@@ -646,6 +683,19 @@ local $out = &backquote_logged("$cmd 2>&1");
|
||||
&error($out) if ($?);
|
||||
}
|
||||
|
||||
# bond_mode_name(mode)
|
||||
# Convert Webmin's numeric bonding mode to the name expected by ip(8).
|
||||
sub bond_mode_name
|
||||
{
|
||||
my ($mode) = @_;
|
||||
my @modes = ("balance-rr", "active-backup", "balance-xor", "broadcast",
|
||||
"802.3ad", "balance-tlb", "balance-alb");
|
||||
if ($mode =~ /^\d+$/ && defined($modes[$mode])) {
|
||||
return $modes[$mode];
|
||||
}
|
||||
return $mode eq "activebackup" ? "active-backup" : $mode;
|
||||
}
|
||||
|
||||
# Tries to unload the module
|
||||
# unload_module(name)
|
||||
sub unload_module
|
||||
|
||||
@@ -377,7 +377,7 @@ else {
|
||||
$err && &error("<pre>$err</pre>");
|
||||
}
|
||||
else {
|
||||
if ($in{'bond'}) {
|
||||
if ($in{'bond'} && !&has_command("ip")) {
|
||||
if (($gconfig{'os_type'} eq 'debian-linux') &&
|
||||
($gconfig{'os_version'} >= 5)) {}
|
||||
else {&load_module($b);}
|
||||
@@ -389,4 +389,3 @@ else {
|
||||
"bifc", $b->{'fullname'}, $b);
|
||||
}
|
||||
&redirect("list_ifcs.cgi?mode=boot");
|
||||
|
||||
|
||||
@@ -617,4 +617,47 @@ is_deeply(\@commands,
|
||||
[ "ip addr del 10\\.211\\.55\\.25\\/24 dev enp0s5 2>&1" ],
|
||||
"Linux active virtual interface is removed when saved down");
|
||||
|
||||
@commands = ( );
|
||||
{
|
||||
no warnings 'redefine';
|
||||
no warnings 'once';
|
||||
local *main::has_command = sub {
|
||||
return $_[0] eq "ip" ? "/sbin/ip" :
|
||||
$_[0] eq "ifconfig" ? "/sbin/ifconfig" : undef;
|
||||
};
|
||||
local *main::active_interfaces = sub {
|
||||
return ( );
|
||||
};
|
||||
local *main::backquote_command = sub {
|
||||
return "";
|
||||
};
|
||||
main::activate_interface({ 'name' => 'bond0',
|
||||
'fullname' => 'bond0',
|
||||
'virtual' => '',
|
||||
'bond' => 1,
|
||||
'partner' => 'eth0 eth1',
|
||||
'mode' => '1',
|
||||
'primary' => 'eth0',
|
||||
'miimon' => '100',
|
||||
'updelay' => '200',
|
||||
'downdelay' => '200',
|
||||
'address' => '10.0.0.2',
|
||||
'netmask' => '255.255.255.0',
|
||||
'address6' => [ ],
|
||||
'netmask6' => [ ],
|
||||
'up' => 1 });
|
||||
}
|
||||
is_deeply(\@commands,
|
||||
[ "ip link add bond0 type bond mode active\\-backup miimon 100 updelay 200 downdelay 200 2>&1",
|
||||
"ip link set dev eth0 down 2>&1",
|
||||
"ip link set dev eth0 master bond0 2>&1",
|
||||
"ip link set dev eth0 up 2>&1",
|
||||
"ip link set dev eth1 down 2>&1",
|
||||
"ip link set dev eth1 master bond0 2>&1",
|
||||
"ip link set dev eth1 up 2>&1",
|
||||
"ip link set dev bond0 type bond primary eth0 2>&1",
|
||||
"ip link set dev bond0 up 2>&1",
|
||||
"cd / ; ip addr add 10\\.0\\.0\\.2/24 dev bond0 2>&1" ],
|
||||
"Linux active bond interface is created before assigning an address");
|
||||
|
||||
done_testing();
|
||||
|
||||
@@ -38,6 +38,9 @@ subtest 'html_escape' => sub {
|
||||
is(main::html_escape('&'), '&amp;', 'default mode double-escapes &');
|
||||
is(main::html_escape('&', 1), '&', 'nodblamp preserves existing &');
|
||||
is(main::html_escape('A', 1), 'A', 'nodblamp preserves numeric entity');
|
||||
is(main::html_escape('◦', 1), '◦', 'nodblamp preserves hex numeric entity');
|
||||
is(main::html_escape('◦', 1), '◦', 'nodblamp preserves uppercase hex numeric entity');
|
||||
is(main::html_escape('&#xZZ;', 1), '&#xZZ;', 'nodblamp escapes invalid hex numeric entity');
|
||||
# Note: nodblamp's lookahead matches any &<letters>; as an entity, so
|
||||
# made-up names like &x; are treated as entities and not re-escaped.
|
||||
is(main::html_escape('&x;', 1), '&x;', 'nodblamp preserves arbitrary &word; shape');
|
||||
|
||||
50
t/webmin-letsencrypt-paths.t
Normal file
50
t/webmin-letsencrypt-paths.t
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/perl
|
||||
# Regression tests for Certbot output path parsing used by Webmin SSL.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More;
|
||||
use File::Basename qw(dirname);
|
||||
use File::Spec;
|
||||
|
||||
our %config;
|
||||
our $module_config_directory = "/etc/webmin/webmin";
|
||||
|
||||
sub has_command { return undef; }
|
||||
|
||||
my $script = File::Spec->rel2abs(
|
||||
File::Spec->catfile(dirname(__FILE__), '..',
|
||||
'webmin', 'letsencrypt-lib.pl'));
|
||||
do $script or die "failed to load $script: $@ $!";
|
||||
|
||||
my $certbot_out = <<'EOF';
|
||||
Successfully received certificate.
|
||||
Certificate is saved at: /etc/letsencrypt/live/test.example/fullchain.pem
|
||||
Key is saved at: /etc/letsencrypt/live/test.example/privkey.pem
|
||||
This certificate expires on 2026-09-25.
|
||||
EOF
|
||||
|
||||
is(main::get_letsencrypt_output_pem_path($certbot_out),
|
||||
'/etc/letsencrypt/live/test.example/fullchain.pem',
|
||||
'certbot output path stops at the first PEM path');
|
||||
|
||||
my $ipv6_out = <<'EOF';
|
||||
Successfully received certificate.
|
||||
Certificate is saved at: /etc/letsencrypt/live/2001:db8::1/fullchain.pem
|
||||
Key is saved at: /etc/letsencrypt/live/2001:db8::1/privkey.pem
|
||||
EOF
|
||||
|
||||
is(main::get_letsencrypt_output_pem_path($ipv6_out),
|
||||
'/etc/letsencrypt/live/2001:db8::1/fullchain.pem',
|
||||
'IPv6 certificate names can still contain colons');
|
||||
|
||||
my $wrapped_out = <<'EOF';
|
||||
Certificate is saved at: /etc/letsencrypt/live/wrapped.example/
|
||||
fullchain.pem
|
||||
EOF
|
||||
|
||||
is(main::get_letsencrypt_output_pem_path($wrapped_out),
|
||||
'/etc/letsencrypt/live/wrapped.example/fullchain.pem',
|
||||
'wrapped PEM paths are normalized');
|
||||
|
||||
done_testing();
|
||||
@@ -302,7 +302,7 @@ if (!defined $tmp) {
|
||||
};
|
||||
# Before escaping ampersand use negative lookahead to see if occurrence
|
||||
# is not an HTML entity already to prevent double escaping (optionally)
|
||||
$tmp =~ s/&(?!(([a-zA-Z]+)|(#|#x)\d+);)/&/g if ($nodblamp);
|
||||
$tmp =~ s/&(?!([a-zA-Z]+|#\d+|#[xX][0-9A-Fa-f]+);)/&/g if ($nodblamp);
|
||||
# Always escape all ampersands by default
|
||||
# to make sure they are displayed per se
|
||||
$tmp =~ s/&/&/g if (!$nodblamp);
|
||||
|
||||
@@ -3,13 +3,13 @@ standard_url=URL of standard modules list,3,On webmin.com
|
||||
third_url=URL of third party modules list,3,On webmin.com
|
||||
cron_mode=Show update times as,1,0-Simple interface,1-Cron time selector
|
||||
warn_days=Days before password expiry to warn users,0,5
|
||||
line2=Let's Encrypt configuration,11
|
||||
letsencrypt_cmd=Full path to Let's Encrypt client command,3,Find automatically
|
||||
letsencrypt_directory_url=Custom ACME directory URL,3,Use Let's Encrypt production
|
||||
line2=ACME provider configuration,11
|
||||
letsencrypt_cmd=Full path to ACME client command,3,Find automatically
|
||||
letsencrypt_directory_url=Custom ACME directory URL,3,Use default production server
|
||||
letsencrypt_eab_kid=External Account Binding key ID,3,None
|
||||
letsencrypt_eab_hmac=External Account Binding HMAC key,12
|
||||
letsencrypt_algo=Encryption algorithm for Let's Encrypt private key,1,rsa-RSA,ecdsa-ECC
|
||||
letsencrypt_dns_wait=Seconds to wait for Let's Encrypt DNS propagation,0,5
|
||||
letsencrypt_before=Command to run before Let's Encrypt request,0,60
|
||||
letsencrypt_after=Command to run after Let's Encrypt request,0,60
|
||||
letsencrypt_reuse=Re-use existing Let's Encrypt keys?,1,1-Yes,0-No
|
||||
letsencrypt_algo=Encryption algorithm for certificate private key,1,rsa-RSA,ecdsa-ECC
|
||||
letsencrypt_dns_wait=Seconds to wait for ACME DNS propagation,0,5
|
||||
letsencrypt_before=Command to run before ACME certificate request,0,60
|
||||
letsencrypt_after=Command to run after ACME certificate request,0,60
|
||||
letsencrypt_reuse=Re-use existing certificate keys?,1,1-Yes,0-No
|
||||
|
||||
@@ -2,4 +2,4 @@ standard_url=URL de la llista de mòduls estàndard,3,A webmin.com
|
||||
third_url=URL de la llista de mòduls de tercers,3,A webmin.com
|
||||
cron_mode=Mostra els temps d'actualització com,1,0-Interfície simple,1-Selector de temps cron
|
||||
warn_days=Dies abans de l'expiració de la contrasenya per avisar els usuaris,0,5
|
||||
letsencrypt_cmd=Camí complet de l'ordre client de Let's Encrypt,3,Troba'l automàticament
|
||||
letsencrypt_cmd=Camí complet de l'ordre client ACME,3,Troba'l automàticament
|
||||
|
||||
@@ -2,4 +2,4 @@ standard_url=URL der Standardmodul-Liste,3,Von webmin.com
|
||||
third_url=URL der Drittanbieter-Webmin-Modulliste,3,Von webmin.com
|
||||
cron_mode=Zeige Aktualisierungszeiten als,1,0-Einfache Anzeige,1-Cron-Zeit-Auswahl
|
||||
warn_days=Tage vor Ablauf des Passworts zu warnen an Benutzer,0,5
|
||||
letsencrypt_cmd=Voller Pfad zum Let's Encrypt Client-Befehl,0
|
||||
letsencrypt_cmd=Voller Pfad zum ACME-Client-Befehl,0
|
||||
|
||||
@@ -3,6 +3,6 @@ standard_url=URL de la liste des modules standard,3,webmin.com
|
||||
third_url=URL de la liste des modules non-standard,3,webmin.com
|
||||
cron_mode=Afficher les heures de mise à jour comme,1,0-Interface simple,1-Sélecteur de temps Cron
|
||||
warn_days=Jours avant l'expiration du mot de passe pour avertir les utilisateurs,0,5
|
||||
line2=Let's Encrypt configuration,11
|
||||
letsencrypt_cmd=Chemin complet de la commande client Let's Encrypt,3,Trouver automatiquement
|
||||
letsencrypt_dns_wait=Quelques secondes à attendre pour la propagation DNS de Let's Encrypt,0,5
|
||||
line2=Configuration du fournisseur ACME,11
|
||||
letsencrypt_cmd=Chemin complet de la commande client ACME,3,Trouver automatiquement
|
||||
letsencrypt_dns_wait=Quelques secondes à attendre pour la propagation DNS ACME,0,5
|
||||
|
||||
@@ -3,6 +3,6 @@ standard_url=標準モジュールリストに使用する URL,3,webmin.com
|
||||
third_url=サードパーティ製モジュールリストに使用する URL,3,webmin.com
|
||||
cron_mode=アップデート時刻の表示方法,1,0-シンプル,1-Cron 選択方式
|
||||
warn_days=ユーザのパスワード期限切れの通知(日前),0,5
|
||||
line2=Let's Encrypt の設定,11
|
||||
letsencrypt_cmd=Let's Encrypt クライアントのパス,3,自動設定
|
||||
letsencrypt_dns_wait=Let's Encrypt DNS の更新待機時間(秒),0,5
|
||||
line2=ACME プロバイダーの設定,11
|
||||
letsencrypt_cmd=ACME クライアントのパス,3,自動設定
|
||||
letsencrypt_dns_wait=ACME DNS の更新待機時間(秒),0,5
|
||||
|
||||
@@ -447,7 +447,7 @@ ssl_letsrenew_days=days
|
||||
ssl_letsnotrenew=Only renew manually
|
||||
ssl_staging=Provider server
|
||||
ssl_staging0=Production
|
||||
ssl_staging1=Staging (test only)
|
||||
ssl_staging1=Test endpoint
|
||||
ssl_acmeopts=Provider settings
|
||||
ssl_acmeextra=Show advanced settings
|
||||
ssl_acmedir=Custom ACME directory URL
|
||||
@@ -1262,13 +1262,13 @@ letsencrypt_doing=Requesting a new certificate for $1, using the website directo
|
||||
letsencrypt_doingdns=Requesting a new certificate for $1, using DNS validation ..
|
||||
letsencrypt_doingcertbot=Requesting a new certificate for $1, using the Certbot webserver ..
|
||||
letsencrypt_failed=.. request failed : $1
|
||||
letsencrypt_done=.. request succeeded!
|
||||
letsencrypt_show=The new certificate and private key were written to the following files :
|
||||
letsencrypt_done=.. done
|
||||
letsencrypt_show=The new certificate and private key were written to the following files:
|
||||
letsencrypt_cert=SSL certificate
|
||||
letsencrypt_key=SSL private key
|
||||
letsencrypt_chain=Chained CA certificate
|
||||
letsencrypt_webmin=Configuring Webmin to use new cert and key ..
|
||||
letsencrypt_wdone=.. done!
|
||||
letsencrypt_wdone=.. done
|
||||
letsencrypt_eaccountkey=Failed to generate account key : $1
|
||||
letsencrypt_etiny=Failed to request certificate : $1
|
||||
letsencrypt_echain=Failed to download chained certificate : $1
|
||||
|
||||
@@ -131,6 +131,20 @@ return &software::missing_install_link(
|
||||
"certbot", $text{'letsencrypt_certbot'}, $rlink, $rmsg);
|
||||
}
|
||||
|
||||
# get_letsencrypt_output_pem_path(output)
|
||||
# Returns the first certbot PEM path from command output, or undef
|
||||
sub get_letsencrypt_output_pem_path
|
||||
{
|
||||
my ($out) = @_;
|
||||
if ($out =~ /((?:\/usr\/local)?\/etc\/letsencrypt\/(?:live|archive)\/[a-zA-Z0-9\.\_\-:\/\*]+\.pem)/ ||
|
||||
$out =~ /((?:\/usr\/local)?\/etc\/letsencrypt\/(?:live|archive)\/[a-zA-Z0-9\.\_\-:\/\r\n\* ]*?\.pem)/) {
|
||||
my $full = $1;
|
||||
$full =~ s/\s//g;
|
||||
return $full;
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
# request_letsencrypt_cert(domain|&domains|&ips, webroot, [email], [keysize],
|
||||
# [request-mode], [use-staging], [account-email],
|
||||
# [key-type], [reuse-key],
|
||||
@@ -387,14 +401,15 @@ if ($letsencrypt_cmd) {
|
||||
goto FAILED;
|
||||
}
|
||||
my ($full, $cert, $key, $chain);
|
||||
if ($out =~ /((?:\/usr\/local)?\/etc\/letsencrypt\/(?:live|archive)\/[a-zA-Z0-9\.\_\-:\/\r\n\* ]*\.pem)/) {
|
||||
if ($full = &get_letsencrypt_output_pem_path($out)) {
|
||||
# Output contained the full path
|
||||
$full = $1;
|
||||
$full =~ s/\s//g;
|
||||
}
|
||||
else {
|
||||
# Try searching common paths
|
||||
my @fulls = (glob("/etc/letsencrypt/live/$certname-*/cert.pem"),
|
||||
my @fulls = grep { -r $_ } (
|
||||
"/etc/letsencrypt/live/$certname/cert.pem",
|
||||
glob("/etc/letsencrypt/live/$certname-*/cert.pem"),
|
||||
"/usr/local/etc/letsencrypt/live/$certname/cert.pem",
|
||||
glob("/usr/local/etc/letsencrypt/live/$certname-*/cert.pem"));
|
||||
if (@fulls) {
|
||||
my %stats = map { $_, [ stat($_) ] } @fulls;
|
||||
|
||||
@@ -132,7 +132,7 @@ else {
|
||||
$mode eq 'certbot' ? 'letsencrypt_doingcertbot' :
|
||||
'letsencrypt_doing',
|
||||
"<tt>".&html_escape(join(", ", @doms))."</tt>",
|
||||
"<tt>".&html_escape($webroot)."</tt>"),"<p>\n";
|
||||
"<tt>".&html_escape($webroot)."</tt>"),"<br>\n";
|
||||
my ($ok, $cert, $key, $chain) = &request_letsencrypt_cert(
|
||||
\@doms, $webroot, undef, $size, $mode, $in{'staging'},
|
||||
undef, undef, undef, $in{'directory_url'},
|
||||
@@ -142,7 +142,20 @@ else {
|
||||
}
|
||||
else {
|
||||
# Worked, now copy to Webmin
|
||||
print $text{'letsencrypt_done'},"<p>\n";
|
||||
my @grid = ( $text{'letsencrypt_cert'}, $cert,
|
||||
$text{'letsencrypt_key'}, $key );
|
||||
push(@grid, $text{'letsencrypt_chain'}, $chain) if ($chain);
|
||||
my $details = &html_escape($text{'letsencrypt_show'})."<p>\n".
|
||||
&ui_grid_table(\@grid, 2);
|
||||
print &ui_details({
|
||||
'html' => 1,
|
||||
'title' => &ui_tag('span',
|
||||
&html_escape($text{'letsencrypt_done'}),
|
||||
{ 'data-second-print' => undef }),
|
||||
'content' => $details,
|
||||
'class' => 'inline inlined',
|
||||
});
|
||||
print "<div data-x-br=\"\"></div>\n";
|
||||
|
||||
# Save the renewal schedule
|
||||
&save_renewal_only(\@doms, $webroot, $mode,
|
||||
@@ -183,15 +196,11 @@ else {
|
||||
|
||||
&webmin_log("letsencrypt");
|
||||
&restart_miniserv(1);
|
||||
print $text{'letsencrypt_wdone'},"<p>\n";
|
||||
print &ui_tag('span',
|
||||
&html_escape($text{'letsencrypt_wdone'}),
|
||||
{ 'data-second-print' => undef });
|
||||
print "<br><div data-x-br=\"\"></div>\n";
|
||||
}
|
||||
|
||||
# Tell the user what was done
|
||||
print $text{'letsencrypt_show'},"<p>\n";
|
||||
my @grid = ( $text{'letsencrypt_cert'}, $cert,
|
||||
$text{'letsencrypt_key'}, $key );
|
||||
push(@grid, $text{'letsencrypt_chain'}, $chain) if ($chain);
|
||||
print &ui_grid_table(\@grid, 2);
|
||||
}
|
||||
|
||||
&ui_print_footer("", $text{'index_return'});
|
||||
|
||||
@@ -60,8 +60,12 @@ if (!-r $first_install_file || $miniserv{'login_script'} eq $record_login_cmd) {
|
||||
$miniserv{'failed_script'} = $record_failed_cmd;
|
||||
}
|
||||
|
||||
# Disable trusting SSL certs unless already enabled
|
||||
if (!$miniserv{'trust_real_ip'} && !defined($miniserv{'no_trust_ssl'})) {
|
||||
# Disable trusting SSL certs unless already enabled. Legacy configs with
|
||||
# trust_real_ip but no trusted proxy cannot safely authenticate from
|
||||
# proxied SSL client cert headers.
|
||||
my @trusted_proxies = split(/\s+/, $miniserv{'trusted_proxies'} || "");
|
||||
if ((!$miniserv{'trust_real_ip'} || !@trusted_proxies) &&
|
||||
!defined($miniserv{'no_trust_ssl'})) {
|
||||
$miniserv{'no_trust_ssl'} = 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user