mirror of
https://github.com/webmin/webmin.git
synced 2026-06-23 20:40:32 +01:00
Merge branch 'master' into systemd
This commit is contained in:
143
acl/acl-lib.pl
143
acl/acl-lib.pl
@@ -1433,6 +1433,148 @@ dbmclose(%sessiondb);
|
||||
return $sid;
|
||||
}
|
||||
|
||||
=head2 set_module_access(&modules, enabled, [&users-groups])
|
||||
|
||||
Grants or revokes Webmin module access for users and groups. The modules
|
||||
parameter must be an array ref of module names. The enabled flag should be
|
||||
1 to grant access, or 0 to revoke access. If the users-groups parameter is
|
||||
not given, all users and groups are updated. Otherwise, it must be an array
|
||||
ref of usernames and group names. Group names may be prefixed with @ to
|
||||
target only a group.
|
||||
|
||||
Returns the number of directly updated user and group records.
|
||||
|
||||
=cut
|
||||
sub set_module_access
|
||||
{
|
||||
my ($mods, $enabled, $usersgroups) = @_;
|
||||
$mods ||= [];
|
||||
return 0 if (!@$mods);
|
||||
my $set_module_access_list = sub {
|
||||
my ($obj, $key, $addmods) = @_;
|
||||
$addmods ||= $mods;
|
||||
my @old = @{$obj->{$key} || []};
|
||||
my @new;
|
||||
if ($enabled) {
|
||||
@new = &unique(@old, @$addmods);
|
||||
}
|
||||
else {
|
||||
my %remove = map { $_, 1 } @$mods;
|
||||
@new = grep { !$remove{$_} } @old;
|
||||
}
|
||||
return 0 if (join("\0", @old) eq join("\0", @new));
|
||||
$obj->{$key} = \@new;
|
||||
return 1;
|
||||
};
|
||||
my $own_module_updates = sub {
|
||||
my ($obj, $inherited) = @_;
|
||||
return $mods if (!$enabled);
|
||||
return [] if (!@{$obj->{'ownmods'} || []} && !@$inherited);
|
||||
return [ grep { &indexof($_, @$inherited) < 0 } @$mods ];
|
||||
};
|
||||
my @users = &list_users();
|
||||
my @groups = &list_groups();
|
||||
my $all = !defined($usersgroups);
|
||||
my (%target_user, %target_group);
|
||||
if (!$all) {
|
||||
foreach my $ug (@$usersgroups) {
|
||||
if ($ug =~ /^\@(.*)$/) {
|
||||
$target_group{$1} = 1;
|
||||
}
|
||||
else {
|
||||
$target_user{$ug} = 1;
|
||||
$target_group{$ug} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
my $changed = 0;
|
||||
my (%user_group, %group_parent);
|
||||
foreach my $g (@groups) {
|
||||
foreach my $m (@{$g->{'members'} || []}) {
|
||||
if ($m =~ /^\@(.*)$/) {
|
||||
$group_parent{$1} = $g;
|
||||
}
|
||||
else {
|
||||
$user_group{$m} = $g;
|
||||
}
|
||||
}
|
||||
}
|
||||
my (@ordered_groups, %ordered_group, %ordering_group);
|
||||
my $add_ordered_group;
|
||||
$add_ordered_group = sub {
|
||||
my ($g) = @_;
|
||||
return if (!$g || $ordered_group{$g->{'name'}});
|
||||
return if ($ordering_group{$g->{'name'}}++);
|
||||
$add_ordered_group->($group_parent{$g->{'name'}});
|
||||
delete($ordering_group{$g->{'name'}});
|
||||
push(@ordered_groups, $g);
|
||||
$ordered_group{$g->{'name'}}++;
|
||||
};
|
||||
foreach my $g (@groups) {
|
||||
$add_ordered_group->($g);
|
||||
}
|
||||
|
||||
# Update groups first, so member users and sub-groups inherit the new set
|
||||
foreach my $g (@ordered_groups) {
|
||||
next if (!$all && !$target_group{$g->{'name'}});
|
||||
my $gchanged = 0;
|
||||
my $parent = $group_parent{$g->{'name'}};
|
||||
my $ownmods = $own_module_updates->(
|
||||
$g, [ @{$parent ? $parent->{'modules'} || [] : []} ]);
|
||||
$gchanged += $set_module_access_list->($g, "modules");
|
||||
$gchanged += $set_module_access_list->($g, "ownmods", $ownmods);
|
||||
if ($gchanged) {
|
||||
&modify_group($g->{'name'}, $g);
|
||||
&update_members(\@users, \@groups, $g->{'modules'},
|
||||
$g->{'members'});
|
||||
$changed++;
|
||||
}
|
||||
}
|
||||
|
||||
# Update directly targeted users
|
||||
foreach my $u (@users) {
|
||||
next if (!$all && !$target_user{$u->{'name'}});
|
||||
my $uchanged = 0;
|
||||
my $group = $user_group{$u->{'name'}};
|
||||
my $ownmods = $own_module_updates->(
|
||||
$u, [ @{$group ? $group->{'modules'} || [] : []} ]);
|
||||
$uchanged += $set_module_access_list->($u, "modules");
|
||||
$uchanged += $set_module_access_list->($u, "ownmods", $ownmods);
|
||||
if ($uchanged) {
|
||||
&modify_user($u->{'name'}, $u);
|
||||
$changed++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($changed) {
|
||||
undef(%main::acl_hash_cache);
|
||||
undef(%main::acl_array_cache);
|
||||
}
|
||||
return $changed;
|
||||
}
|
||||
|
||||
=head2 enable_module_access(&modules, [&users-groups])
|
||||
|
||||
Grants users and groups access to one or more modules. This is a wrapper
|
||||
around set_module_access.
|
||||
|
||||
=cut
|
||||
sub enable_module_access
|
||||
{
|
||||
return &set_module_access($_[0], 1, $_[1]);
|
||||
}
|
||||
|
||||
=head2 disable_module_access(&modules, [&users-groups])
|
||||
|
||||
Revokes users and groups access to one or more modules. This is a wrapper
|
||||
around set_module_access.
|
||||
|
||||
=cut
|
||||
sub disable_module_access
|
||||
{
|
||||
return &set_module_access($_[0], 0, $_[1]);
|
||||
}
|
||||
|
||||
=head2 update_members(&allusers, &allgroups, &modules, &members)
|
||||
|
||||
Update the modules for members users and groups of some group. The parameters
|
||||
@@ -2368,4 +2510,3 @@ return $mailbox."\@".join(".", @doms);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
@@ -701,6 +701,152 @@ is(group_line({ name => 'empty' }),
|
||||
'delete_group removes the only group');
|
||||
}
|
||||
|
||||
# set_module_access and wrappers: batch enable/disable module visibility for
|
||||
# users and groups, while keeping ownmods in sync for future group refreshes.
|
||||
{
|
||||
_reset_fixture();
|
||||
create_user({ name => 'alice',
|
||||
pass => 'x',
|
||||
modules => [ 'useradmin', 'apache' ],
|
||||
ownmods => [ 'apache' ] });
|
||||
create_group({ name => 'wheel',
|
||||
members => [ 'alice' ],
|
||||
modules => [ 'useradmin', 'apache' ],
|
||||
desc => 'Sysadmins',
|
||||
ownmods => [ 'apache' ] });
|
||||
_clear_caches();
|
||||
|
||||
is(disable_module_access([ 'apache' ]), 2,
|
||||
'disable_module_access without targets updates all users and groups');
|
||||
|
||||
my $alice = get_user('alice');
|
||||
my $wheel = get_group('wheel');
|
||||
is_deeply($alice->{'modules'}, [ 'useradmin' ],
|
||||
'global disable removes module from user modules');
|
||||
is_deeply($alice->{'ownmods'}, [],
|
||||
'global disable removes module from user ownmods');
|
||||
is_deeply($wheel->{'modules'}, [ 'useradmin' ],
|
||||
'global disable removes module from group modules');
|
||||
is_deeply($wheel->{'ownmods'}, [],
|
||||
'global disable removes module from group ownmods');
|
||||
}
|
||||
|
||||
{
|
||||
_reset_fixture();
|
||||
create_user({ name => 'alice',
|
||||
pass => 'x',
|
||||
modules => [ 'useradmin' ] });
|
||||
create_group({ name => 'wheel',
|
||||
members => [ 'alice' ],
|
||||
modules => [ 'useradmin' ],
|
||||
desc => 'Sysadmins' });
|
||||
_clear_caches();
|
||||
|
||||
is(enable_module_access([ 'apache' ], [ '@wheel' ]), 1,
|
||||
'enable_module_access can target one group by @name');
|
||||
|
||||
my $alice = get_user('alice');
|
||||
my $wheel = get_group('wheel');
|
||||
is_deeply($wheel->{'modules'}, [ 'useradmin', 'apache' ],
|
||||
'targeted group enable adds module to group modules');
|
||||
is_deeply($wheel->{'ownmods'}, [],
|
||||
'targeted group enable leaves top-level group ownmods unchanged');
|
||||
is_deeply($alice->{'modules'}, [ 'useradmin', 'apache' ],
|
||||
'targeted group enable propagates to member user modules');
|
||||
is_deeply($alice->{'ownmods'}, [],
|
||||
'targeted group enable leaves member user ownmods unchanged');
|
||||
|
||||
is(disable_module_access([ 'apache' ], [ '@wheel' ]), 1,
|
||||
'disable_module_access can target one group by @name');
|
||||
|
||||
$alice = get_user('alice');
|
||||
$wheel = get_group('wheel');
|
||||
is_deeply($wheel->{'modules'}, [ 'useradmin' ],
|
||||
'targeted group disable removes module from group modules');
|
||||
is_deeply($wheel->{'ownmods'}, [],
|
||||
'targeted group disable removes module from group ownmods');
|
||||
is_deeply($alice->{'modules'}, [ 'useradmin' ],
|
||||
'targeted group disable propagates to member user modules');
|
||||
}
|
||||
|
||||
{
|
||||
_reset_fixture();
|
||||
create_user({ name => 'carol',
|
||||
pass => 'x',
|
||||
modules => [ 'useradmin' ] });
|
||||
create_group({ name => 'child',
|
||||
members => [ 'carol' ],
|
||||
modules => [ 'useradmin' ],
|
||||
desc => 'Child group' });
|
||||
create_group({ name => 'parent',
|
||||
members => [ '@child' ],
|
||||
modules => [ 'useradmin' ],
|
||||
desc => 'Parent group' });
|
||||
_clear_caches();
|
||||
|
||||
is(enable_module_access([ 'apache' ]), 1,
|
||||
'enable_module_access handles all nested groups');
|
||||
|
||||
my $child = get_group('child');
|
||||
my $carol = get_user('carol');
|
||||
is_deeply($child->{'modules'}, [ 'useradmin', 'apache' ],
|
||||
'child group inherits module from parent enabled later in file');
|
||||
is_deeply($child->{'ownmods'}, [],
|
||||
'child group does not record inherited module as ownmod');
|
||||
is_deeply($carol->{'modules'}, [ 'useradmin', 'apache' ],
|
||||
'child group member inherits module through nested groups');
|
||||
is_deeply($carol->{'ownmods'}, [],
|
||||
'child group member does not record inherited module as ownmod');
|
||||
}
|
||||
|
||||
{
|
||||
_reset_fixture();
|
||||
create_user({ name => 'root',
|
||||
pass => 'x',
|
||||
modules => [ 'useradmin' ] });
|
||||
_clear_caches();
|
||||
|
||||
is(enable_module_access([ 'apache' ], [ 'root' ]), 1,
|
||||
'enable_module_access can target a standalone user');
|
||||
my $root = get_user('root');
|
||||
is_deeply($root->{'modules'}, [ 'useradmin', 'apache' ],
|
||||
'standalone user enable adds module to user modules');
|
||||
is_deeply($root->{'ownmods'}, [],
|
||||
'standalone user enable does not create ownmods');
|
||||
}
|
||||
|
||||
{
|
||||
_reset_fixture();
|
||||
create_user({ name => 'bob',
|
||||
pass => 'x',
|
||||
modules => [ 'useradmin' ] });
|
||||
create_group({ name => 'wheel',
|
||||
members => [ 'bob' ],
|
||||
modules => [ 'useradmin' ],
|
||||
desc => 'Sysadmins' });
|
||||
_clear_caches();
|
||||
|
||||
is(enable_module_access([ 'apache' ], [ 'bob' ]), 1,
|
||||
'enable_module_access can target one user by name');
|
||||
|
||||
my $bob = get_user('bob');
|
||||
is_deeply($bob->{'modules'}, [ 'useradmin', 'apache' ],
|
||||
'targeted user enable adds module to user modules');
|
||||
is_deeply($bob->{'ownmods'}, [ 'apache' ],
|
||||
'targeted user enable records explicit user ownmod');
|
||||
|
||||
# A later group refresh must not erase a directly granted user module.
|
||||
my @users = list_users();
|
||||
my @groups = list_groups();
|
||||
my ($wheel) = grep { $_->{'name'} eq 'wheel' } @groups;
|
||||
update_members(\@users, \@groups, $wheel->{'modules'},
|
||||
$wheel->{'members'});
|
||||
_clear_caches();
|
||||
$bob = get_user('bob');
|
||||
is_deeply($bob->{'modules'}, [ 'useradmin', 'apache' ],
|
||||
'targeted user enable survives later group refresh');
|
||||
}
|
||||
|
||||
# copy_acl_files (file mode): copy a module ACL file from one name to another.
|
||||
{
|
||||
_reset_fixture();
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
line1=Configurable options,11
|
||||
expert=Allow selection of individual runlevels?,1,1-Yes,0-No
|
||||
desc=Display actions with descriptions,1,2-Yes, and show all runlevels,1-Yes,0-No
|
||||
systemd_dedicated=Hide systemd services table?,1,-No,1-Yes
|
||||
order=Show boot order of actions?,1,1-Yes,0-No
|
||||
status_check=Show current status of actions,1,2-On index and action pages,1-On action page only,0-No
|
||||
sort_mode=Sort actions by,1,1-Boot order,0-Name
|
||||
line2=System configuration,11
|
||||
init_mode=Boot system,4,-Detect automatically,init-SysV init,upstart-Upstart,systemd-Systemd,osx-MacOS,rc-FreeBSD RC scripts,win32-Windows services,local-Single boot script
|
||||
init_mode=Boot system,4,-Detect automatically,systemd-Systemd,init-SysV init,openrc-OpenRC,upstart-Upstart,local-Single boot script,rc-FreeBSD RC scripts,launchd-macOS launchd,osx-Legacy macOS StartupItems,win32-Windows services
|
||||
init_base=Directory in which runlevel directories are located,0
|
||||
init_dir=Directory containing master init scripts,0
|
||||
order_digits=Number of digits in action order,0
|
||||
@@ -17,8 +18,8 @@ shutdown_command=Command to shutdown the system,0
|
||||
inittab_id=inittab ID for bootup runlevel,0
|
||||
rc_dir=FreeBSD rc scripts directories,3,None
|
||||
rc_conf=FreeBSD configuration files,3,None
|
||||
line3=OSX system configuration,11
|
||||
startup_dirs=Darwin StartupItems directories,0
|
||||
line3=macOS StartupItems configuration,11
|
||||
startup_dirs=macOS StartupItems directories,0
|
||||
darwin_setup=Directory for custom StartupItems,0
|
||||
hostconfig=Darwin hostconfig file,0
|
||||
hostconfig=Legacy hostconfig file,0
|
||||
plist=Name of plist in a StartupItems directory,0
|
||||
|
||||
@@ -5,7 +5,7 @@ order=Mostra l'ordre d'engegada de les accions,1,1-Sí,0-No
|
||||
status_check=Mostra l'estat actual de les accions,1,2-A les pàgines d'índex i de l'acció,1-Només a la pàgina de l'acció,0-No
|
||||
sort_mode=Ordena les accions per,1,1-Ordre d'engegada,0-Nom
|
||||
line2=Configuració del sistema,11
|
||||
init_mode=Engegada del sistema,4,-Detecta-ho automàticament,init-Init de SysV,upstart-Upstart,systemd-Systemd,osx-MacOS,rc-Scripts RC de FreeBSD,win32-Serveis Windows,local-Script únic d'engegada
|
||||
init_mode=Engegada del sistema,4,-Detecta-ho automàticament,systemd-Systemd,init-Init de SysV,openrc-OpenRC,upstart-Upstart,local-Script únic d'engegada,rc-Scripts RC de FreeBSD,launchd-macOS launchd,osx-Legacy macOS StartupItems,win32-Serveis Windows
|
||||
init_base=Directori on s'allotgen els directoris de nivells d'execució,0
|
||||
init_dir=Directori que conté els scripts init mestres,0
|
||||
order_digits=Nombre de dígits de l'ordre de l'acció,0
|
||||
|
||||
@@ -5,7 +5,7 @@ order=Zeige die Aktionen in Reihenfolge des Starts an?,1,1-Ja,0-Nein
|
||||
status_check=Zeige aktuellen Status der Aktionen,1,2-Auf Index- und Aktionen-Seite,1-Nur auf der Aktionen-Seite,0-Nein
|
||||
sort_mode=Sortiere Aktionen nach,1,1-Boot-Reihenfolge,0-Name
|
||||
line2=Systemkonfiguration,11
|
||||
init_mode=Boot-System,4,-automatisch erkennen,init-SysV init,upstart-Upstart,systemd-Systemd,osx-MacOS,rc-FreeBSD RC Script,win32-Windows-Dienste,local-Single Bootskript
|
||||
init_mode=Boot-System,4,-automatisch erkennen,systemd-Systemd,init-SysV init,openrc-OpenRC,upstart-Upstart,local-Single Bootskript,rc-FreeBSD RC Script,launchd-macOS launchd,osx-Legacy macOS StartupItems,win32-Windows-Dienste
|
||||
init_base=Verzeichnis, in dem die Runlevel-Verzeichnisse liegen,0
|
||||
init_dir=Verzeichnis, in dem das Haupt-Skript liegt,0
|
||||
order_digits=Anzahl Ziffern in Aktionsreihenfolge,0
|
||||
|
||||
@@ -5,7 +5,7 @@ order=Vis handlingenes oppstartsrekkefølge?1,1-Ja,0-Nei
|
||||
status_check=Vis handlingenes gjeldende status,1,2-På indeks- og handlingssider,1-Bare på handlingssider,0-Nei
|
||||
sort_mode=Sorter handlinger etter,1,1-Oppstartrekkefølge,0-Navn
|
||||
line2=System konfigurasjon,11
|
||||
init_mode=Oppstartssystem,4,-Oppdag automatisk,init-SysV init,upstart-Upstart,systemd-Systemd,osx-MacOS,rc-FreeBSD RC scripts,win32-Windows tjenester,local-Enkelt oppstartsscript
|
||||
init_mode=Oppstartssystem,4,-Oppdag automatisk,systemd-Systemd,init-SysV init,openrc-OpenRC,upstart-Upstart,local-Enkelt oppstartsscript,rc-FreeBSD RC scripts,launchd-macOS launchd,osx-Legacy macOS StartupItems,win32-Windows tjenester
|
||||
init_base=Katalog hvor kjøretids-kataloger finnes,0
|
||||
init_dir=Katalog som inneholder master init scripts,0
|
||||
order_digits=Antall sifre i handlingssortering,0
|
||||
|
||||
129
init/index.cgi
129
init/index.cgi
@@ -329,70 +329,74 @@ elsif ($init_mode eq "upstart" && $access{'bootup'}) {
|
||||
|
||||
}
|
||||
elsif ($init_mode eq "systemd" && $access{'bootup'}) {
|
||||
# Show systemd actions
|
||||
print &ui_form_start("mass_systemd.cgi", "post");
|
||||
@links = ( &select_all_link("d"),
|
||||
&select_invert_link("d"),
|
||||
&ui_link("edit_systemd.cgi?new=1", $text{'index_sadd'}) );
|
||||
print &ui_links_row(\@links);
|
||||
print &ui_columns_start([ "", $text{'systemd_name'},
|
||||
$config{'desc'} ? $text{'systemd_desc'} : (),
|
||||
$text{'systemd_type'},
|
||||
$text{'systemd_status'},
|
||||
$text{'systemd_boot'},
|
||||
$text{'index_ustatus'} ]);
|
||||
my $units_piped = join('|', map { quotemeta } &get_systemd_unit_types());
|
||||
foreach $u (&list_systemd_services()) {
|
||||
if ($u->{'legacy'}) {
|
||||
$l = "edit_action.cgi?0+".&urlize($u->{'name'});
|
||||
}
|
||||
else {
|
||||
$l = "edit_systemd.cgi?name=".&urlize($u->{'name'});
|
||||
}
|
||||
my $sname = $u->{'name'};
|
||||
my ($type) = $sname =~ /\.([^.]+)$/;
|
||||
if (defined($type) && $type =~ /^(?:$units_piped)$/) {
|
||||
$sname =~ s/\.$type$//;
|
||||
}
|
||||
else {
|
||||
$type = '';
|
||||
}
|
||||
my $title = ($u->{'boot'} == -1 ?
|
||||
&html_escape($sname) :
|
||||
&ui_link($l, &html_escape($sname)));
|
||||
my $desc = $config{'desc'} ? &html_escape($u->{'desc'}) : undef;
|
||||
print &ui_columns_row([
|
||||
&ui_checkbox("d", $u->{'name'}, undef),
|
||||
$title,
|
||||
$desc // (),
|
||||
$type,
|
||||
$u->{'fullstatus'} || "<i>$text{'index_unknown'}</i>",
|
||||
$u->{'boot'} == 1 ?
|
||||
&ui_text_color("$text{'yes'}", 'success') :
|
||||
$u->{'boot'} == 2 ?
|
||||
&ui_text_color("$text{'index_sboot6'}", 'success') :
|
||||
$u->{'boot'} == -1 ?
|
||||
&ui_text_color("$text{'index_sboot5'}", 'warn') :
|
||||
&ui_text_color("$text{'no'}", 'warn'),
|
||||
$u->{'status'} == 1 ? &ui_text_color("$text{'yes'}", 'success') :
|
||||
$u->{'status'} == 0 ?
|
||||
&ui_text_color("$text{'no'}", 'warn') :
|
||||
"<i>$text{'index_unknown'}</i>",
|
||||
]);
|
||||
if (!&init_show_systemd_services()) {
|
||||
my $systemd_link = &ui_tag('a',
|
||||
$text{'index_systemd_module'},
|
||||
{ 'href' => '../systemd/' });
|
||||
print &ui_alert_box(
|
||||
&text('index_systemd_dedicated', $systemd_link),
|
||||
'info', undef, undef, ""),"\n";
|
||||
}
|
||||
print &ui_columns_end();
|
||||
print &ui_links_row(\@links);
|
||||
print &ui_form_end([ [ "start", $text{'index_start'} ],
|
||||
[ "stop", $text{'index_stop'} ],
|
||||
[ "restart", $text{'index_restart'} ],
|
||||
undef,
|
||||
[ "addboot", $text{'index_addboot'} ],
|
||||
[ "delboot", $text{'index_delboot'} ],
|
||||
undef,
|
||||
[ "addboot_start", $text{'index_addboot_start'} ],
|
||||
[ "delboot_stop", $text{'index_delboot_stop'} ],
|
||||
]);
|
||||
else {
|
||||
# Show systemd actions
|
||||
print &ui_form_start("mass_systemd.cgi", "post");
|
||||
@links = ( &select_all_link("d"),
|
||||
&select_invert_link("d"),
|
||||
&ui_link("edit_systemd.cgi?new=1",
|
||||
$text{'index_sadd'}) );
|
||||
print &ui_links_row(\@links);
|
||||
print &ui_columns_start([ "", $text{'systemd_name'},
|
||||
$config{'desc'} ?
|
||||
$text{'systemd_desc'} : (),
|
||||
$text{'systemd_status'},
|
||||
$text{'systemd_boot'},
|
||||
$text{'index_ustatus'} ]);
|
||||
foreach $u (&list_systemd_services()) {
|
||||
if ($u->{'legacy'}) {
|
||||
$l = "edit_action.cgi?0+".&urlize($u->{'name'});
|
||||
}
|
||||
else {
|
||||
$l = "edit_systemd.cgi?name=".&urlize($u->{'name'});
|
||||
}
|
||||
my $sname = $u->{'name'};
|
||||
$sname =~ s/\.service$//;
|
||||
my $title = ($u->{'boot'} == -1 ?
|
||||
&html_escape($sname) :
|
||||
&ui_link($l, &html_escape($sname)));
|
||||
my $desc = $config{'desc'} ?
|
||||
&html_escape($u->{'desc'}) : undef;
|
||||
print &ui_columns_row([
|
||||
&ui_checkbox("d", $u->{'name'}, undef),
|
||||
$title,
|
||||
$desc // (),
|
||||
$u->{'fullstatus'} || "<i>$text{'index_unknown'}</i>",
|
||||
$u->{'boot'} == 1 ?
|
||||
&ui_text_color("$text{'yes'}", 'success') :
|
||||
$u->{'boot'} == 2 ?
|
||||
&ui_text_color("$text{'index_sboot6'}", 'success') :
|
||||
$u->{'boot'} == -1 ?
|
||||
&ui_text_color("$text{'index_sboot5'}", 'warn') :
|
||||
&ui_text_color("$text{'no'}", 'warn'),
|
||||
$u->{'status'} == 1 ? &ui_text_color("$text{'yes'}", 'success') :
|
||||
$u->{'status'} == 0 ?
|
||||
&ui_text_color("$text{'no'}", 'warn') :
|
||||
"<i>$text{'index_unknown'}</i>",
|
||||
]);
|
||||
}
|
||||
print &ui_columns_end();
|
||||
print &ui_links_row(\@links);
|
||||
print &ui_form_end([ [ "start", $text{'index_start'} ],
|
||||
[ "stop", $text{'index_stop'} ],
|
||||
[ "restart", $text{'index_restart'} ],
|
||||
undef,
|
||||
[ "addboot", $text{'index_addboot'} ],
|
||||
[ "delboot", $text{'index_delboot'} ],
|
||||
undef,
|
||||
[ "addboot_start", $text{'index_addboot_start'} ],
|
||||
[ "delboot_stop", $text{'index_delboot_stop'} ],
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
elsif ($init_mode eq "launchd" && $access{'bootup'}) {
|
||||
# Show launchd agents
|
||||
@@ -449,4 +453,3 @@ if ($access{'shutdown'}) {
|
||||
print &ui_buttons_end();
|
||||
|
||||
&ui_print_footer("/", $text{'index'});
|
||||
|
||||
|
||||
103
init/init-lib.pl
103
init/init-lib.pl
@@ -28,9 +28,9 @@ use WebminCore;
|
||||
|
||||
This variable is set based on the bootup system in use. Possible values are :
|
||||
|
||||
=item osx - MacOSX hostconfig files, for older versions
|
||||
=item osx - Legacy macOS StartupItems and hostconfig files
|
||||
|
||||
=item launchd - MacOS Launchd, for newer versions
|
||||
=item launchd - macOS launchd, for newer versions
|
||||
|
||||
=item rc - FreeBSD 6+ RC files
|
||||
|
||||
@@ -2311,16 +2311,15 @@ if (@list_systemd_services_cache && !$noinit) {
|
||||
return @list_systemd_services_cache;
|
||||
}
|
||||
|
||||
my $units_piped = join('|', &get_systemd_unit_types());
|
||||
|
||||
# Get all systemd unit names
|
||||
my $out = &backquote_command("systemctl list-units --full --all -t service --no-legend");
|
||||
my $ex = $?;
|
||||
foreach my $l (split(/\r?\n/, $out)) {
|
||||
$l =~ s/^[^a-z0-9\-\_\.]+//i;
|
||||
my ($unit, $loaded, $active, $sub, $desc) = split(/\s+/, $l, 5);
|
||||
next if ($unit !~ /\.service$/);
|
||||
my $a = $unit;
|
||||
$a =~ s/\.($units_piped)$//;
|
||||
$a =~ s/\.service$//;
|
||||
my $f = &action_filename($a);
|
||||
if ($unit ne "UNIT" && $loaded eq "loaded" && !-r $f) {
|
||||
push(@units, $unit);
|
||||
@@ -2332,29 +2331,26 @@ foreach my $l (split(/\r?\n/, $out)) {
|
||||
# and so don't show up in systemctl list-units
|
||||
my $root = &get_systemd_root(undef, 1);
|
||||
opendir(UNITS, $root);
|
||||
push(@units, grep { !/\.wants$/ && !/^\./ && !-d "$root/$_" } readdir(UNITS));
|
||||
push(@units, grep { /\.service$/ && !-d "$root/$_" } readdir(UNITS));
|
||||
closedir(UNITS);
|
||||
|
||||
# Also add units from list-unit-files that also don't show up
|
||||
$out = &backquote_command("systemctl list-unit-files -t service --no-legend");
|
||||
foreach my $l (split(/\r?\n/, $out)) {
|
||||
if ($l =~ /^(\S+\.($units_piped))\s+disabled/ ||
|
||||
$l =~ /^(\S+)\s+disabled/) {
|
||||
if ($l =~ /^(\S+\.service)\s+disabled/) {
|
||||
push(@units, $1);
|
||||
}
|
||||
}
|
||||
|
||||
# Skip useless units
|
||||
@units = grep { !/^sys-devices-/ &&
|
||||
!/^\-\.mount/ &&
|
||||
!/^\-\.slice/ &&
|
||||
!/^dev-/ &&
|
||||
!/^systemd-/ } @units;
|
||||
@units = &unique(@units);
|
||||
|
||||
# Filter out templates
|
||||
my @templates = grep { /\@$/ || /\@\.($units_piped)$/ } @units;
|
||||
@units = grep { !/\@$/ && !/\@\.($units_piped)$/ } @units;
|
||||
my @templates = grep { /\@$/ || /\@\.service$/ } @units;
|
||||
@units = grep { !/\@$/ && !/\@\.service$/ } @units;
|
||||
|
||||
# Dump state of all of them, 100 at a time
|
||||
my %info;
|
||||
@@ -3142,11 +3138,90 @@ return $name =~ /\./ ? $name : "com.webmin.".$name;
|
||||
}
|
||||
|
||||
# config_pre_load(mod-info, [mod-order])
|
||||
# Check if some config options are conditional
|
||||
# Hides config options that do not apply to the detected boot system.
|
||||
sub config_pre_load
|
||||
{
|
||||
my ($modconf_info, $modconf_order) = @_;
|
||||
$modconf_info->{'desc'} =~ s/2-[^,]+,// if ($init_mode eq "systemd");
|
||||
return if (ref($modconf_info) ne 'HASH');
|
||||
|
||||
if ($init_mode eq "systemd" && $modconf_info->{'desc'}) {
|
||||
# Systemd has no runlevels, so keep only the plain yes/no choices.
|
||||
$modconf_info->{'desc'} =~ s/2-[^,]+,//;
|
||||
}
|
||||
|
||||
my %keep = map { $_, 1 } &init_config_options_for_mode($init_mode);
|
||||
foreach my $key (keys %$modconf_info) {
|
||||
delete($modconf_info->{$key}) if (!$keep{$key});
|
||||
}
|
||||
if (ref($modconf_order) eq 'ARRAY') {
|
||||
@$modconf_order = grep { $keep{$_} } @$modconf_order;
|
||||
}
|
||||
&hide_single_init_config_section($modconf_info, $modconf_order);
|
||||
}
|
||||
|
||||
# init_config_options_for_mode(mode)
|
||||
# Returns config.info keys that should be visible for a boot system.
|
||||
sub init_config_options_for_mode
|
||||
{
|
||||
my ($mode) = @_;
|
||||
my @display = ( 'expert', 'desc', 'order', 'status_check', 'sort_mode' );
|
||||
my @common = ( 'init_mode', 'reboot_command', 'shutdown_command' );
|
||||
my @sysv = ( @common, 'init_base', 'init_dir', 'order_digits',
|
||||
'boot_levels', 'local_script', 'local_down', 'inittab_id' );
|
||||
my @systemd_display = ( 'desc' );
|
||||
push(@systemd_display, 'systemd_dedicated')
|
||||
if (&init_dedicated_systemd_module_available());
|
||||
|
||||
return ( 'line1', @systemd_display, 'line2', @common )
|
||||
if ($mode eq 'systemd');
|
||||
return ( 'line1', @display, 'line2', @sysv )
|
||||
if ($mode eq 'init' || $mode eq 'upstart' || $mode eq 'openrc');
|
||||
return ( 'line2', @common, 'local_script', 'local_down',
|
||||
'rc_dir', 'rc_conf' )
|
||||
if ($mode eq 'rc');
|
||||
return ( 'line2', @common, 'local_script', 'local_down' )
|
||||
if ($mode eq 'local');
|
||||
return ( 'line2', @common, 'line3', 'startup_dirs', 'darwin_setup',
|
||||
'hostconfig', 'plist' )
|
||||
if ($mode eq 'osx');
|
||||
return ( 'line2', @common )
|
||||
if ($mode eq 'launchd' || $mode eq 'win32');
|
||||
return ( 'line1', @display, 'line2', @sysv, 'rc_dir', 'rc_conf',
|
||||
'line3', 'startup_dirs', 'darwin_setup', 'hostconfig', 'plist' );
|
||||
}
|
||||
|
||||
# hide_single_init_config_section(&config-info, [&config-order])
|
||||
# Removes the lone section header when filtering leaves only one group.
|
||||
sub hide_single_init_config_section
|
||||
{
|
||||
my ($modconf_info, $modconf_order) = @_;
|
||||
my @sections = grep {
|
||||
exists($modconf_info->{$_}) &&
|
||||
(split(/,/, $modconf_info->{$_}))[1] == 11
|
||||
} keys %$modconf_info;
|
||||
return if (@sections != 1);
|
||||
|
||||
delete($modconf_info->{$sections[0]});
|
||||
if (ref($modconf_order) eq 'ARRAY') {
|
||||
@$modconf_order = grep { $_ ne $sections[0] } @$modconf_order;
|
||||
}
|
||||
}
|
||||
|
||||
# init_dedicated_systemd_module_available()
|
||||
# Returns 1 if the standalone Systemd module can be used by this Webmin user.
|
||||
sub init_dedicated_systemd_module_available
|
||||
{
|
||||
return &foreign_available("systemd") && &foreign_installed("systemd");
|
||||
}
|
||||
|
||||
# init_show_systemd_services()
|
||||
# Returns 1 if this module should show its legacy systemd service table.
|
||||
sub init_show_systemd_services
|
||||
{
|
||||
return 1 if (!&init_dedicated_systemd_module_available());
|
||||
return 0 if ($config{'systemd_dedicated'} &&
|
||||
$config{'systemd_dedicated'} eq '1');
|
||||
return 1;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@@ -188,13 +188,14 @@ change_title=Switch Runlevel
|
||||
change_cmd=Switching to runlevel $1 with command $2. This may take some time, and Webmin might not be available anymore after switching.
|
||||
|
||||
mode_init=SysV init
|
||||
mode_osx=MacOS
|
||||
mode_osx=Legacy macOS StartupItems
|
||||
mode_local=Single boot script
|
||||
mode_win32=Windows services
|
||||
mode_rc=FreeBSD RC scripts
|
||||
mode_upstart=Upstart
|
||||
mode_systemd=Systemd
|
||||
mode_launchd=LaunchD
|
||||
mode_launchd=macOS launchd
|
||||
mode_openrc=OpenRC
|
||||
|
||||
upstart_title1=Create Upstart Service
|
||||
upstart_title2=Edit Upstart Service
|
||||
@@ -246,6 +247,8 @@ systemd_edesc=Missing unit description
|
||||
systemd_return=systemd unit
|
||||
systemd_econf=No systemd unit configuration entered
|
||||
systemd_estart=Missing commands to run on startup
|
||||
index_systemd_module=Systemd Services and Units
|
||||
index_systemd_dedicated=Use the dedicated $1 module to manage systemd services and units. This page now shows only system reboot and shutdown controls.
|
||||
|
||||
launchd_title1=Create Launchd Agent
|
||||
launchd_title2=Edit Launchd Agent
|
||||
|
||||
@@ -127,7 +127,7 @@ Provides: $baseproduct
|
||||
EOF
|
||||
if ($product eq "webmin") {
|
||||
print CONTROL <<EOF;
|
||||
Replaces: webmin-adsl, webmin-apache, webmin-bandwidth, webmin-bind, webmin-burner, webmin-cfengine, webmin-cluster, webmin-core, webmin-cpan, webmin-dhcpd, webmin-exim, webmin-exports, webmin-fetchmail, webmin-firewall, webmin-freeswan, webmin-frox, webmin-fsdump, webmin-grub, webmin-heartbeat, webmin-htaccess, webmin-inetd, webmin-jabber, webmin-ldap-netgroups, webmin-ldap-user-simple, webmin-ldap-useradmin, webmin-lilo, webmin-logrotate, webmin-lpadmin, webmin-lvm, webmin-mailboxes, webmin-mon, webmin-mysql, webmin-nis, webmin-openslp, webmin-postfix, webmin-postgresql, webmin-ppp, webmin-pptp-client, webmin-pptp-server, webmin-procmail, webmin-proftpd, webmin-pserver, webmin-quota, webmin-samba, webmin-sarg, webmin-sendmail, webmin-shorewall, webmin-slbackup, webmin-smart-status, webmin-snort, webmin-software, webmin-spamassassin, webmin-squid, webmin-sshd, webmin-status, webmin-stunnel, webmin-updown, webmin-usermin, webmin-vgetty, webmin-webalizer, webmin-wuftpd, webmin-wvdial, webmin-xinetd, webmin-filemin, webmin-authentic-theme
|
||||
Replaces: webmin-adsl, webmin-apache, webmin-bandwidth, webmin-bind, webmin-burner, webmin-cfengine, webmin-cluster, webmin-core, webmin-cpan, webmin-custom, webmin-dhcpd, webmin-exim, webmin-exports, webmin-fetchmail, webmin-firewall, webmin-freeswan, webmin-frox, webmin-fsdump, webmin-grub, webmin-heartbeat, webmin-htaccess, webmin-inetd, webmin-jabber, webmin-ldap-netgroups, webmin-ldap-user-simple, webmin-ldap-useradmin, webmin-lilo, webmin-logrotate, webmin-lpadmin, webmin-lvm, webmin-mailboxes, webmin-mon, webmin-mysql, webmin-nftables, webmin-nis, webmin-openslp, webmin-postfix, webmin-postgresql, webmin-ppp, webmin-pptp-client, webmin-pptp-server, webmin-procmail, webmin-proftpd, webmin-pserver, webmin-quota, webmin-samba, webmin-sarg, webmin-sendmail, webmin-shorewall, webmin-slbackup, webmin-smart-status, webmin-snort, webmin-software, webmin-spamassassin, webmin-squid, webmin-sshd, webmin-status, webmin-stunnel, webmin-updown, webmin-usermin, webmin-vgetty, webmin-webalizer, webmin-wuftpd, webmin-wvdial, webmin-xinetd, webmin-filemin, webmin-authentic-theme
|
||||
Description: web-based administration interface for Unix systems
|
||||
Using Webmin you can configure DNS, Samba, NFS, local/remote filesystems
|
||||
and more using your web browser. After installation, enter the URL
|
||||
|
||||
@@ -86,6 +86,8 @@ Name: webmin
|
||||
Version: $ver
|
||||
Release: $rel
|
||||
Provides: %{name}-%{version} perl(WebminCore)
|
||||
Provides: webmin-custom webmin-nftables webmin-postgresql
|
||||
Obsoletes: webmin-custom webmin-nftables webmin-postgresql
|
||||
Requires(pre): /usr/bin/perl
|
||||
Requires: /bin/sh /usr/bin/perl perl(lib) perl(open) perl(Net::SSLeay) perl(Time::Local) perl(Data::Dumper) perl(File::Path) perl(File::Basename) perl(Digest::SHA) perl(Digest::MD5) openssl unzip tar gzip
|
||||
Recommends: perl(DateTime) perl(DateTime::TimeZone) perl(DateTime::Locale) perl(Time::Piece) perl(Encode::Detect) perl(Time::HiRes) perl(Socket6) perl(Sys::Syslog) html2text shared-mime-info lsof perl-File-Basename perl-File-Path perl-JSON-XS perl(DBI) perl(DBD::mysql) perl(DBD::MariaDB)
|
||||
|
||||
@@ -1 +1 @@
|
||||
acl apache authentic-theme backup-config bind8 change-user cron dovecot fail2ban fdisk filemin firewalld fsdump gray-theme htaccess-htpasswd init systemd logrotate logviewer lvm mailboxes mailcap mount mysql net package-updates passwd phpini postfix proc procmail proftpd quota servers software spam sshd status system-status time updown useradmin usermin webmin webmincron webminlog xterm
|
||||
acl apache authentic-theme backup-config bind8 change-user cron custom dovecot fail2ban fdisk filemin firewalld fsdump gray-theme htaccess-htpasswd init logrotate logviewer lvm mailboxes mailcap mount mysql net nftables package-updates passwd phpini postfix postgresql proc procmail proftpd quota servers software spam sshd status systemd system-status time updown useradmin usermin webmin webmincron webminlog xterm
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
---- Changes since 2.641 ----
|
||||
Added defaults for alpine linux and fix package installs
|
||||
---- Changes since 1.140 ----
|
||||
The not null flag and a default value can be specified for fields in new tables.
|
||||
The form for creating an initial table in a new database is now the same as the one for adding a table to an existing database.
|
||||
|
||||
25
mysql/config-alpine-linux
Normal file
25
mysql/config-alpine-linux
Normal file
@@ -0,0 +1,25 @@
|
||||
start_cmd=rc-service mariadb start
|
||||
mysql=/usr/bin/mariadb
|
||||
mysqld=/usr/bin/mariadbd
|
||||
mysqldump=/usr/bin/mysqldump
|
||||
mysqlimport=/usr/bin/mariadb-import
|
||||
mysql_libs=/usr/lib/mariadb/plugin
|
||||
mysqladmin=/usr/bin/mariadb-admin
|
||||
mysqlshow=/usr/bin/mariadb-show
|
||||
perpage=25
|
||||
style=1
|
||||
add_mode=1
|
||||
nodbi=0
|
||||
access=*: *
|
||||
blob_mode=0
|
||||
date_subs=0
|
||||
passwd_mode=0
|
||||
mysql_data=/var/lib/mysql
|
||||
max_dbs=50
|
||||
my_cnf=/etc/my.cnf
|
||||
max_text=1000
|
||||
nopwd=0
|
||||
webmin_subs=0
|
||||
ssl=0
|
||||
stop_cmd=rc-service mariadb stop
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
---- Changes since 2.641 ----
|
||||
Fix Alpine Linux mysql/mariadb package installs names due missing server utils (means at least Alpine Linux package installation is supported since Alpine linux v 3.16 up to edge)
|
||||
---- Changes since 1.130 ----
|
||||
Packages can now be installed directly from yum, if installed.
|
||||
The entire system can also be upgraded from yum.
|
||||
|
||||
@@ -364,7 +364,7 @@ sub update_system_resolve
|
||||
my ($name) = @_;
|
||||
return $name eq "apache" ? "apache2" :
|
||||
$name eq "dhcpd" ? "dhcp" :
|
||||
$name eq "mysql" ? "mariadb mariadb-client" :
|
||||
$name eq "mysql" ? "mariadb mariadb-client mariadb-server-utils" :
|
||||
$name eq "postgresql" ? "postgresql postgresql-client" :
|
||||
$name eq "openldap" ? "openldap openldap-clients" :
|
||||
$name eq "ldap" ? "openldap openldap-clients" :
|
||||
|
||||
@@ -4,15 +4,12 @@ Wants=network-online.target
|
||||
After=network.target network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Environment="PERLLIB=WEBMIN_LIBDIR"
|
||||
ExecStart=WEBMIN_LIBDIR/miniserv.pl WEBMIN_CONFIG/miniserv.conf
|
||||
ExecStop=WEBMIN_KILLCMD $MAINPID
|
||||
ExecStart=WEBMIN_LIBDIR/miniserv.pl --nofork WEBMIN_CONFIG/miniserv.conf
|
||||
ExecReload=WEBMIN_KILLCMD -HUP $MAINPID
|
||||
PIDFile=WEBMIN_VAR/miniserv.pid
|
||||
Type=forking
|
||||
Restart=always
|
||||
Restart=on-failure
|
||||
RestartSec=2s
|
||||
TimeoutSec=15s
|
||||
TimeoutStopSec=300s
|
||||
|
||||
[Install]
|
||||
|
||||
@@ -111,7 +111,7 @@ return &software::missing_install_link(
|
||||
"certbot", $text{'letsencrypt_certbot'}, $rlink, $rmsg);
|
||||
}
|
||||
|
||||
# request_letsencrypt_cert(domain|&domains, webroot, [email], [keysize],
|
||||
# request_letsencrypt_cert(domain|&domains|&ips, webroot, [email], [keysize],
|
||||
# [request-mode], [use-staging], [account-email],
|
||||
# [key-type], [reuse-key],
|
||||
# [directory-url, server-key, server-hmac],
|
||||
@@ -125,11 +125,15 @@ my ($dom, $webroot, $email, $size, $mode, $staging, $account_email,
|
||||
$key_type, $reuse_key, $directory_url, $server_key, $server_hmac,
|
||||
$subset) = @_;
|
||||
my @doms = ref($dom) ? @$dom : ($dom);
|
||||
$email ||= "root\@$doms[0]";
|
||||
$mode ||= "web";
|
||||
@doms = &unique(@doms);
|
||||
my @ips = grep { &check_ipaddress($_) } @doms;
|
||||
@doms = grep { !&check_ipaddress($_) } @doms;
|
||||
$email ||= (@doms ? "root\@$doms[0]" : "root\@".&get_system_hostname());
|
||||
$mode ||= "web";
|
||||
$reuse_key = $config{'letsencrypt_reuse'} if (!defined($reuse_key));
|
||||
my ($challenge, $wellknown, $challenge_new, $wellknown_new, $wildcard);
|
||||
my $cmd_ver = $letsencrypt_cmd ? &get_certbot_major_version($letsencrypt_cmd)
|
||||
: undef;
|
||||
|
||||
# Wildcard mode?
|
||||
foreach my $d (@doms) {
|
||||
@@ -142,6 +146,17 @@ if (($server_key || $server_hmac) && !$letsencrypt_cmd) {
|
||||
return (0, $text{'letsencrypt_eeabnative'});
|
||||
}
|
||||
|
||||
# Check if IP addresses are supported
|
||||
if (@ips) {
|
||||
$mode eq "dns" && return (0, "DNS-based validation cannot be used ".
|
||||
"for IP addresses");
|
||||
$letsencrypt_cmd || return (0, "The certbot command is required for ".
|
||||
"IP address certificates");
|
||||
&compare_version_numbers($cmd_ver, "5.3") >= 0 ||
|
||||
return (0, "Certbot version 5.3 or later is required for ".
|
||||
"IP address certificates");
|
||||
}
|
||||
|
||||
if ($mode eq "web") {
|
||||
# Create a challenges directory under the web root
|
||||
if ($wildcard) {
|
||||
@@ -232,7 +247,6 @@ if ($letsencrypt_cmd) {
|
||||
&print_tempfile(TEMP, "text = True\n");
|
||||
&close_tempfile(TEMP);
|
||||
my $dir = $letsencrypt_cmd;
|
||||
my $cmd_ver = &get_certbot_major_version($letsencrypt_cmd);
|
||||
my $old_flags = "";
|
||||
my $new_flags = "";
|
||||
my $reuse_flags = "";
|
||||
@@ -271,13 +285,14 @@ if ($letsencrypt_cmd) {
|
||||
$dir =~ s/\/[^\/]+$//;
|
||||
$size ||= 4096;
|
||||
my $out;
|
||||
my $certname = @doms ? $doms[0] : $ips[0];
|
||||
my $common_flags = " --duplicate".
|
||||
" --force-renewal".
|
||||
" --non-interactive".
|
||||
" --agree-tos".
|
||||
" --config ".quotemeta($temp)."".
|
||||
" --rsa-key-size ".quotemeta($size).
|
||||
" --cert-name ".quotemeta($doms[0]).
|
||||
" --cert-name ".quotemeta($certname).
|
||||
" --no-autorenew".
|
||||
(!$directory_url && $staging ? " --test-cert" : "");
|
||||
if ($mode eq "web") {
|
||||
@@ -287,7 +302,9 @@ if ($letsencrypt_cmd) {
|
||||
"cd $dir && (echo A | $letsencrypt_cmd certonly".
|
||||
" -a webroot ".
|
||||
join("", map { " -d ".quotemeta($_) } @doms).
|
||||
join("", map { " --ip-address ".quotemeta($_) } @ips).
|
||||
" --webroot-path ".quotemeta($webroot).
|
||||
(@ips ? " --preferred-profile shortlived" : "").
|
||||
$common_flags.
|
||||
$reuse_flags.
|
||||
$old_flags.
|
||||
@@ -328,6 +345,8 @@ if ($letsencrypt_cmd) {
|
||||
"cd $dir && (echo A | $letsencrypt_cmd certonly".
|
||||
" --standalone".
|
||||
join("", map { " -d ".quotemeta($_) } @doms).
|
||||
join("", map { " --ip-address ".quotemeta($_) } @ips).
|
||||
(@ips ? " --preferred-profile shortlived" : "").
|
||||
$common_flags.
|
||||
$reuse_flags.
|
||||
$old_flags.
|
||||
@@ -353,8 +372,8 @@ if ($letsencrypt_cmd) {
|
||||
}
|
||||
else {
|
||||
# Try searching common paths
|
||||
my @fulls = (glob("/etc/letsencrypt/live/$doms[0]-*/cert.pem"),
|
||||
glob("/usr/local/etc/letsencrypt/live/$doms[0]-*/cert.pem"));
|
||||
my @fulls = (glob("/etc/letsencrypt/live/$certname-*/cert.pem"),
|
||||
glob("/usr/local/etc/letsencrypt/live/$certname-*/cert.pem"));
|
||||
if (@fulls) {
|
||||
my %stats = map { $_, [ stat($_) ] } @fulls;
|
||||
@fulls = sort { $stats{$a}->[9] <=> $stats{$b}->[9] }
|
||||
|
||||
Reference in New Issue
Block a user