chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:12:17 +08:00
commit cf8edb9f21
44281 changed files with 1655134 additions and 0 deletions
+151
View File
@@ -0,0 +1,151 @@
---- Changes since 1.140 ----
Module update emails are now sent using the Read User Mail module.
Added a new option to the Webmin Modules page for installing a third-party module from thirdpartymodules.webmin.com.
Added a field to the Index Page Options page for specifying a module to redirect users to immediately after logging in.
---- Changes since 1.150 ----
Added an option to the Authentication page for enabling the use of MD5 encrypted passwords for Webmin users. These are more secure, and allow longer usable passwords.
Added an option to the Proxy Servers page for specifying a source IP address for all network connections.
---- Changes since 1.170 ----
Create the File Locking page, which can be used to limit Webmin's .lock file creation to certain directories or disable it altogether.
---- Changes since 1.180 ----
Added a new option on the logging page for recording the full contents of changed files.
Scheduled updates can now be downloaded at any time configurable using Cron, by enabling a new option on the Module Config page.
---- Changes since 1.190 ----
Added an option to the Authentication page for enabling full PAM conversations at login, which may be necessary on systems that request more than just a username and password.
---- Changes since 1.200 ----
Additional SSL certificates can now be defined for different local IP addresses. This can be useful for sites doing SSL virtual hosting that want to share the same certificate between Apache and Webmin for the same address.
Added a checkbox to the upgrade form to terminate other Webmin sessions, to prevent mismatches between forms and programs in the old and new versions.
---- Changes since 1.210 ----
Added a new field to the proxy page, for selecting a preferred OSDN mirror site. This is used when updating Webmin and Usermin, and so should be set to whichever mirror is closest to you.
---- Changes since 1.220 ----
Added an option to enable Utmp logging where users login to or logout from Webmin. Requires the User::Utmp Perl module.
Added a form on the Modules page for exporting one or more installed modules as a .wbm.gz file.
Put a button on the main page for submitting information about the OS on this Webmin system to the developers, for tracking how many people use each OS.
Fixed up the proxy servers and downloads page, to prevent problems when the OSDN servers cannot be reached.
---- Changes since 1.230 ----
CIDR-format network addresses can now be used on the IP Access Control page.
Added the Advanced Options icon, for managing some rarely-used internal Webmin settings.
The size of the popup help window used by Webmin can now be configured on the User Interface page.
---- Changes since 1.240 ----
When adjusting the operating system manually, the internal version code can and must be changed too.
Added an option when cloning a module to use the default configuration instead of copying from the original.
---- Changes since 1.250 ----
The Export Modules form can now write to a file on the server.
---- Changes since 1.260 ----
The sizes of user, file, date and module chooser windows opened by Webmin can be configured on the User Interface page.
Added an option on the SSL Encryption page to prevent the use of SSL version 2.
Added an option on the User Interface page to have the current username prepended to all page titles.
Added a section to the Advanced Options page for setting the Webmin temporary files directory on a per-module basis.
Added options on the Proxy Servers and Downloads page to enable caching of HTTP and FTP downloads by Webmin. This is useful if your network does not have a proxy (like Squid), and you often download the same files multiple times.
Added a form to the Webmin Themes page for exporting a theme to a file.
---- Changes since 1.270 ----
Custom category names can be defined on a per-language basis.
Added a button on the Proxy Servers and Downloads page for clearing the cache.
---- Changes since 1.290 ----
Added support for installing and upgrading the Debian package version of Webmin.
Updates to a module that has already been updated and are not needed are not displayed.
Added an setting to the Advanced Options page for showing full stack traces when Webmin's common error function is displayed. This is useful for tracking down bugs.
Added a field on the Advanced Options page for setting the Umask, which determines default permissions for new files created by Webmin.
---- Changes since 1.300 ----
Added a section to the SSL Encryption page for uploading an existing PEM format SSL key and certificate.
Added buttons on the Proxy Servers and Downloads page for viewing and deleting cached files, and clearing the entire cache.
Fixed a bug that prevents module installs from RPMs from working.
---- Changes since 1.320 ----
Added an option to the Advanced page for suppressing the display of Perl errors.
Added a new Mobile Device Options page for defining a custom theme and login process for mobile browsers.
---- Changes since 1.330 ----
Added an option to the Logging page to write Webmin actions to syslog.
Converted many pages to use new ui-lib.pl functions, and broke down long forms using tabs.
When Webmin's detected OS is automatically updated, Usermin's will be too (if it is an equivalent version).
---- Changes since 1.340 ----
Added an option to the Proxy Servers form to fallback to a direct connection if the proxy is down.
Added a tab showing details of the current cert, with a link to download in PEM or PKCS12 format.
---- Changes since 1.350 ----
Added an option to the Authentication page to block users with too many failed logins, as well as hosts.
Created the new Blocked Hosts and Users page to show blocks currently in force, and allow them to be cleared.
Added an option to the Ports and Addresses page to control if Webmin attempts to to reverse-resolve the connected-to IP address when issuing redirects, such as from non-SSL to SSL mode.
---- Changes since 1.360 ----
Added a field to the Advanced Options page to control the number of days that files in /tmp/.webmin are kept before automatic deletion.
---- Changes since 1.370 ----
The format for dates displayed by Webmin can be changed by a new option on the User Interface page.
---- Changes since 1.380 ----
Inheritance of the system path into Webmin's search path can be set on the Operating System and Environment page.
The nice level (CPU priority) of all cron and other background jobs run by Webmin can now be set on the Advanced Options page.
---- Changes since 1.400 ----
Use the gzip -d command to extract Webmin modules, if gunzip is missing (such as on Windows).
Users with too many failed logins can be locked until the administrator unlocks them.
The default scheduled update time is now randomly selected.
---- Changes since 1.410 ----
Refresh the left-side frame when installing, removing or re-categorizing modules.
---- Changes since 1.420 ----
On Linux systems, the IO scheduling class and priority for Webmin Cron jobs can be set on the Advanced Options page.
Added a field to the SSL Encryption page for setting allowed ciphers.
---- Changes since 1.440 ----
Added an advanced option to have Webmin turn off the immutable bit on files before writing to them, and turn it back on when done.
Re-designed the Webmin Themes page to use tabs.
Added support for overlay themes, which can be selected in addition to a regular theme. An overlay typically just modifies the CSS or images in the real theme, making simple design changes easier.
Converted commands in the module's API file to POD format, and added more details about each function.
---- Changes since 1.450 ----
Added GPG verification of the updates list and modules from the Webmin update repository, when the gpg command is installed.
Expired Unix passwords can now be changed using an external command, instead of PAM or directly updating /etc/shadow. This is set on the Authentication page.
---- Changes since 1.460 ----
Detect and ignore failures when checking if other modules are installed.
---- Changes since 1.470 ----
Added a field to the Operating System and Environment page for additional Perl module directories.
---- Changes since 1.480 ----
Removed the option to select an OSDN mirror, as Sourceforge now does sensible location-based redirects automatically.
Added an option on the Logging page to record logins and logouts from Webmin, for display in the Webmin Actions Log module.
---- Changes since 1.490 ----
Added a field to the Debugging Log File page to select modules to debug for.
---- Changes since 1.500 ----
Added an option to the User Interface page to always put the hostname before the page title.
---- Changes since 1.510 ----
Strong PCI-compliant ciphers can now be selected on the SSL Encryption page.
---- Changes since 1.540 ----
Added the Sending Email page which controls how Webmin itself sends messages.
---- Changes since 1.550 ----
Added fields to the Index Page Options page to control the display of Webmin and module updates.
Moved settings related to Webmin's built-in webserver to the new Web Server Options page.
The client-side expiry time for static files served by Webmin can now be configured on the Web Server Options page, and can be customized on a per-file basis.
A chained certificate file supplied by a CA can now be easily uploaded using the Upload certificate tab on the SSL Encryption page.
Chained certificate files can now be set for per-IP address SSL keys, rather than the global chained list always being used.
---- Changes since 1.580 ----
Added a tab to the SSL Encryption page for generating a certificate signing request.
---- Changes since 1.590 ----
The titles for existing clone modules can now be changed on the Module Titles page.
---- Changes since 1.610 ----
Added a page for viewing and running Webmin scheduled functions.
Added a section to the Sending Email page to verify that the configured mail server settings work.
---- Changes since 1.620 ----
Added a setting to the Web Server Options page to control if redirects use just a path, or the full URL.
---- Changes since 1.640 ----
Actions on the Webmin Scheduled Functions page can now be clicked on to change the time the function runs at.
---- Changes since 1.650 ----
Added an SSL option to use only ciphers with perfect forward secrecy.
Added support for two-factor authentication using Authy or Google Authenticator.
---- Changes since 1.660 ----
Updated the UI on several pages to use the standard Webmin library, for a more consistent look.
---- Changes since 1.730 ----
Added an option to use an SSL connection when Webmin sends email, for connecting to remote mail servers like Gmail that don't allow unencrypted SMTP.
---- Changes since 1.770 ----
An SSL certificate can now be requested from Let's Encrypt using a new tab on the SSL Encryption page.
---- Changes since 1.780 ----
Added an option for automatically renewing Let's Encrypt certificates.
If the Let's Encrypt client is not installed, Webmin will use its own built-in client code to request a certificate.
---- Changes since 1.800 ----
Added an option to the logging page for sending Webmin action log messages via email.
---- Changes since 1.810 ----
The Let's Encrypt key size can now be customized.
When Perfect Forward Secrecy ciphers are selected, the required DH params file is now created and used by Webmin.
---- Changes since 1.830 ----
Added DNS validation support for Let's Encrypt certificate requests, for use when a system is hosting the DNS zone that you want to request a cert for.
Per-domain-name SSL certificates can now be created as well as per-IP, allowing for multiple certs to exist on the same IP address.
---- Changes since 1.890 ----
Wildcard SSL certs can now be requested via Let's Encrypt in DNS mode, if the native client is installed.
Announcements to all Webmin users can now be displayed on the System Information page.
---- Changes since 1.940 ----
The host, port and SSL mode for redirects can now be customized via miniserv.conf options.
---- Changes since 1.960 ----
Added options on the Ports and Addresses page to control the number of concurrent connections per IP, network and in total.
---- Changes since 1.970 ----
Added an option on the Authentication Options page to enable a password change API for use by other programs.
+199
View File
@@ -0,0 +1,199 @@
#!/usr/bin/env python
# Copyright Daniel Roesler, under MIT license, see LICENSE at github.com/diafygi/acme-tiny
import argparse, subprocess, json, os, sys, base64, binascii, time, hashlib, re, copy, textwrap, logging
try:
from urllib.request import urlopen, Request # Python 3
except ImportError: # pragma: no cover
from urllib2 import urlopen, Request # Python 2
DEFAULT_CA = "https://acme-v02.api.letsencrypt.org" # DEPRECATED! USE DEFAULT_DIRECTORY_URL INSTEAD
DEFAULT_DIRECTORY_URL = "https://acme-v02.api.letsencrypt.org/directory"
LOGGER = logging.getLogger(__name__)
LOGGER.addHandler(logging.StreamHandler())
LOGGER.setLevel(logging.INFO)
def get_crt(account_key, csr, acme_dir, log=LOGGER, CA=DEFAULT_CA, disable_check=False, directory_url=DEFAULT_DIRECTORY_URL, contact=None, check_port=None):
directory, acct_headers, alg, jwk = None, None, None, None # global variables
# helper functions - base64 encode for jose spec
def _b64(b):
return base64.urlsafe_b64encode(b).decode('utf8').replace("=", "")
# helper function - run external commands
def _cmd(cmd_list, stdin=None, cmd_input=None, err_msg="Command Line Error"):
proc = subprocess.Popen(cmd_list, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate(cmd_input)
if proc.returncode != 0:
raise IOError("{0}\n{1}".format(err_msg, err))
return out
# helper function - make request and automatically parse json response
def _do_request(url, data=None, err_msg="Error", depth=0):
try:
resp = urlopen(Request(url, data=data, headers={"Content-Type": "application/jose+json", "User-Agent": "acme-tiny"}))
resp_data, code, headers = resp.read().decode("utf8"), resp.getcode(), resp.headers
except IOError as e:
resp_data = e.read().decode("utf8") if hasattr(e, "read") else str(e)
code, headers = getattr(e, "code", None), {}
try:
resp_data = json.loads(resp_data) # try to parse json results
except ValueError:
pass # ignore json parsing errors
if depth < 100 and code == 400 and resp_data['type'] == "urn:ietf:params:acme:error:badNonce":
raise IndexError(resp_data) # allow 100 retrys for bad nonces
if code not in [200, 201, 204]:
raise ValueError("{0}:\nUrl: {1}\nData: {2}\nResponse Code: {3}\nResponse: {4}".format(err_msg, url, data, code, resp_data))
return resp_data, code, headers
# helper function - make signed requests
def _send_signed_request(url, payload, err_msg, depth=0):
payload64 = "" if payload is None else _b64(json.dumps(payload).encode('utf8'))
new_nonce = _do_request(directory['newNonce'])[2]['Replay-Nonce']
protected = {"url": url, "alg": alg, "nonce": new_nonce}
protected.update({"jwk": jwk} if acct_headers is None else {"kid": acct_headers['Location']})
protected64 = _b64(json.dumps(protected).encode('utf8'))
protected_input = "{0}.{1}".format(protected64, payload64).encode('utf8')
out = _cmd(["openssl", "dgst", "-sha256", "-sign", account_key], stdin=subprocess.PIPE, cmd_input=protected_input, err_msg="OpenSSL Error")
data = json.dumps({"protected": protected64, "payload": payload64, "signature": _b64(out)})
try:
return _do_request(url, data=data.encode('utf8'), err_msg=err_msg, depth=depth)
except IndexError: # retry bad nonces (they raise IndexError)
return _send_signed_request(url, payload, err_msg, depth=(depth + 1))
# helper function - poll until complete
def _poll_until_not(url, pending_statuses, err_msg):
result, t0 = None, time.time()
while result is None or result['status'] in pending_statuses:
assert (time.time() - t0 < 3600), "Polling timeout" # 1 hour timeout
time.sleep(0 if result is None else 2)
result, _, _ = _send_signed_request(url, None, err_msg)
return result
# parse account key to get public key
log.info("Parsing account key...")
out = _cmd(["openssl", "rsa", "-in", account_key, "-noout", "-text"], err_msg="OpenSSL Error")
pub_pattern = r"modulus:[\s]+?00:([a-f0-9\:\s]+?)\npublicExponent: ([0-9]+)"
pub_hex, pub_exp = re.search(pub_pattern, out.decode('utf8'), re.MULTILINE|re.DOTALL).groups()
pub_exp = "{0:x}".format(int(pub_exp))
pub_exp = "0{0}".format(pub_exp) if len(pub_exp) % 2 else pub_exp
alg, jwk = "RS256", {
"e": _b64(binascii.unhexlify(pub_exp.encode("utf-8"))),
"kty": "RSA",
"n": _b64(binascii.unhexlify(re.sub(r"(\s|:)", "", pub_hex).encode("utf-8"))),
}
accountkey_json = json.dumps(jwk, sort_keys=True, separators=(',', ':'))
thumbprint = _b64(hashlib.sha256(accountkey_json.encode('utf8')).digest())
# find domains
log.info("Parsing CSR...")
out = _cmd(["openssl", "req", "-in", csr, "-noout", "-text"], err_msg="Error loading {0}".format(csr))
domains = set([])
common_name = re.search(r"Subject:.*? CN\s?=\s?([^\s,;/]+)", out.decode('utf8'))
if common_name is not None:
domains.add(common_name.group(1))
subject_alt_names = re.search(r"X509v3 Subject Alternative Name: (?:critical)?\n +([^\n]+)\n", out.decode('utf8'), re.MULTILINE|re.DOTALL)
if subject_alt_names is not None:
for san in subject_alt_names.group(1).split(", "):
if san.startswith("DNS:"):
domains.add(san[4:])
log.info(u"Found domains: {0}".format(", ".join(domains)))
# get the ACME directory of urls
log.info("Getting directory...")
directory_url = CA + "/directory" if CA != DEFAULT_CA else directory_url # backwards compatibility with deprecated CA kwarg
directory, _, _ = _do_request(directory_url, err_msg="Error getting directory")
log.info("Directory found!")
# create account, update contact details (if any), and set the global key identifier
log.info("Registering account...")
reg_payload = {"termsOfServiceAgreed": True} if contact is None else {"termsOfServiceAgreed": True, "contact": contact}
account, code, acct_headers = _send_signed_request(directory['newAccount'], reg_payload, "Error registering")
log.info("{0} Account ID: {1}".format("Registered!" if code == 201 else "Already registered!", acct_headers['Location']))
if contact is not None:
account, _, _ = _send_signed_request(acct_headers['Location'], {"contact": contact}, "Error updating contact details")
log.info("Updated contact details:\n{0}".format("\n".join(account.get('contact') or [])))
# create a new order
log.info("Creating new order...")
order_payload = {"identifiers": [{"type": "dns", "value": d} for d in domains]}
order, _, order_headers = _send_signed_request(directory['newOrder'], order_payload, "Error creating new order")
log.info("Order created!")
# get the authorizations that need to be completed
for auth_url in order['authorizations']:
authorization, _, _ = _send_signed_request(auth_url, None, "Error getting challenges")
domain = authorization['identifier']['value']
# skip if already valid
if authorization['status'] == "valid":
log.info("Already verified: {0}, skipping...".format(domain))
continue
log.info("Verifying {0}...".format(domain))
# find the http-01 challenge and write the challenge file
challenge = [c for c in authorization['challenges'] if c['type'] == "http-01"][0]
token = re.sub(r"[^A-Za-z0-9_\-]", "_", challenge['token'])
keyauthorization = "{0}.{1}".format(token, thumbprint)
wellknown_path = os.path.join(acme_dir, token)
with open(wellknown_path, "w") as wellknown_file:
wellknown_file.write(keyauthorization)
# check that the file is in place
try:
wellknown_url = "http://{0}{1}/.well-known/acme-challenge/{2}".format(domain, "" if check_port is None else ":{0}".format(check_port), token)
assert (disable_check or _do_request(wellknown_url)[0] == keyauthorization)
except (AssertionError, ValueError) as e:
raise ValueError("Wrote file to {0}, but couldn't download {1}: {2}".format(wellknown_path, wellknown_url, e))
# say the challenge is done
_send_signed_request(challenge['url'], {}, "Error submitting challenges: {0}".format(domain))
authorization = _poll_until_not(auth_url, ["pending"], "Error checking challenge status for {0}".format(domain))
if authorization['status'] != "valid":
raise ValueError("Challenge did not pass for {0}: {1}".format(domain, authorization))
os.remove(wellknown_path)
log.info("{0} verified!".format(domain))
# finalize the order with the csr
log.info("Signing certificate...")
csr_der = _cmd(["openssl", "req", "-in", csr, "-outform", "DER"], err_msg="DER Export Error")
_send_signed_request(order['finalize'], {"csr": _b64(csr_der)}, "Error finalizing order")
# poll the order to monitor when it's done
order = _poll_until_not(order_headers['Location'], ["pending", "processing"], "Error checking order status")
if order['status'] != "valid":
raise ValueError("Order failed: {0}".format(order))
# download the certificate
certificate_pem, _, _ = _send_signed_request(order['certificate'], None, "Certificate download failed")
log.info("Certificate signed!")
return certificate_pem
def main(argv=None):
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent("""\
This script automates the process of getting a signed TLS certificate from Let's Encrypt using the ACME protocol.
It will need to be run on your server and have access to your private account key, so PLEASE READ THROUGH IT!
It's only ~200 lines, so it won't take long.
Example Usage: python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /usr/share/nginx/html/.well-known/acme-challenge/ > signed_chain.crt
""")
)
parser.add_argument("--account-key", required=True, help="path to your Let's Encrypt account private key")
parser.add_argument("--csr", required=True, help="path to your certificate signing request")
parser.add_argument("--acme-dir", required=True, help="path to the .well-known/acme-challenge/ directory")
parser.add_argument("--quiet", action="store_const", const=logging.ERROR, help="suppress output except for errors")
parser.add_argument("--disable-check", default=False, action="store_true", help="disable checking if the challenge file is hosted correctly before telling the CA")
parser.add_argument("--directory-url", default=DEFAULT_DIRECTORY_URL, help="certificate authority directory url, default is Let's Encrypt")
parser.add_argument("--ca", default=DEFAULT_CA, help="DEPRECATED! USE --directory-url INSTEAD!")
parser.add_argument("--contact", metavar="CONTACT", default=None, nargs="*", help="Contact details (e.g. mailto:aaa@bbb.com) for your account-key")
parser.add_argument("--check-port", metavar="PORT", default=None, help="what port to use when self-checking the challenge file, default is port 80")
args = parser.parse_args(argv)
LOGGER.setLevel(args.quiet or LOGGER.level)
signed_crt = get_crt(args.account_key, args.csr, args.acme_dir, log=LOGGER, CA=args.ca, disable_check=args.disable_check, directory_url=args.directory_url, contact=args.contact, check_port=args.check_port)
sys.stdout.write(signed_crt)
if __name__ == "__main__": # pragma: no cover
main(sys.argv[1:])
+19
View File
@@ -0,0 +1,19 @@
#
# Admin script for Webmin pkgadd upgrade
#
mail=
instance=overwrite
partial=nocheck
runlevel=nocheck
idepend=nocheck
rdepend=quit
space=nocheck
setuid=nocheck
conflict=nocheck
action=nocheck
networktimeout=60
networkretries=3
authentication=quit
keystore=/var/sadm/security
proxy=
basedir=default
+85
View File
@@ -0,0 +1,85 @@
do 'webmin-lib.pl';
# backup_config_files()
# Returns files and directories that can be backed up
sub backup_config_files
{
&get_miniserv_config(\%miniserv);
my @rv = ( "$config_directory/config",
"$config_directory/miniserv.conf",
"$config_directory/webmin.cats",
"$config_directory/webmin.catnames",
"$config_directory/webmin.desc",
$miniserv{'keyfile'},
$miniserv{'certfile'},
$miniserv{'ca'},
$newmodule_users_file,
"$config_directory/custom-lang",
glob("$config_directory/*/custom-lang"),
);
return @rv;
}
# pre_backup(&files)
# Called before the files are actually read
sub pre_backup
{
return undef;
}
# post_backup(&files)
# Called after the files are actually read
sub post_backup
{
return undef;
}
# pre_restore(&files)
# Called before the files are restored from a backup
sub pre_restore
{
# Get current configs, for later merging
&get_miniserv_config(\%oldminiserv);
&read_file("$config_directory/config", \%oldconfig);
return undef;
}
# post_restore(&files)
# Called after the files are restored from a backup
sub post_restore
{
# Merge in local settings that cannot be copied
my %miniserv;
&get_miniserv_config(\%miniserv);
foreach my $k (keys %oldminiserv) {
my $copy = 0;
foreach my $keep ("root", "mimetypes", "logfile", "pidfile",
"env_WEBMIN_CONFIG", "env_WEBMIN_VAR", "logout",
"userfile", "passwd_.*") {
$copy = 1 if ($k =~ /^$keep$/);
}
$miniserv{$k} = $oldminiserv{$k} if ($copy);
}
&put_miniserv_config(\%miniserv);
my %gconfig;
&read_file("$config_directory/config", \%gconfig);
foreach my $k (keys %oldconfig) {
my $copy = 0;
foreach my $nocopy ("os_type", "os_version",
"real_os_type", "real_os_version",
"find_pid_command", "ld_env", "passwd_.*") {
$copy = 1 if ($k =~ /^$keep$/);
}
$config{$k} = $oldconfig{$k} if ($copy);
}
&write_file("$config_directory/config", \%gconfig);
unlink("$config_directory/module.infos.cache");
&restart_miniserv();
return undef;
}
1;
+50
View File
@@ -0,0 +1,50 @@
#!/usr/local/bin/perl
# bootup.cgi
# Create, enable or disable webmin startup at boot time
require './webmin-lib.pl';
&foreign_require("init");
&ReadParse();
my %miniserv;
&get_miniserv_config(\%miniserv);
if ($in{'boot'}) {
# Enable starting at boot
$start = "$config_directory/start";
if ($init::init_mode eq "launchd") {
# Launchd forks automatically
$start .= " --nofork";
$fork = 0;
}
else {
$fork = 1;
}
$stop = "$config_directory/stop";
$status = <<EOF;
pidfile=`grep "^pidfile=" $config_directory/miniserv.conf | sed -e 's/pidfile=//g'`
if [ -s \$pidfile ]; then
pid=`cat \$pidfile`
kill -0 \$pid >/dev/null 2>&1
if [ "\$?" = "0" ]; then
echo "webmin (pid \$pid) is running"
RETVAL=0
else
echo "webmin is stopped"
RETVAL=1
fi
else
echo "webmin is stopped"
RETVAL=1
fi
EOF
&init::enable_at_boot("webmin", "Start or stop Webmin",
$start, $stop, $status,
{ 'fork' => $fork,
'pidfile' => $miniserv{'pidfile'} });
}
else {
# Disable starting at boot
&init::disable_at_boot("webmin");
}
&redirect("");
+54
View File
@@ -0,0 +1,54 @@
#!/usr/local/bin/perl
# Show a form for finding cached URLs, with the ability to flush
require './webmin-lib.pl';
&ui_print_header(undef, $text{'cache_title'}, "");
&ReadParse();
# Search form
print &ui_form_start("cache.cgi");
print "<b>$text{'cache_search'}</b>\n",
&ui_textbox("search", $in{'search'}, 40),"\n",
&ui_submit($text{'cache_ok'}),"\n";
print &ui_form_end();
if ($in{'search'}) {
# Find results
$surl = $in{'search'};
$surl =~ s/\//_/g;
foreach $c (&list_cached_files()) {
if ($c->[0] =~ /\Q$surl\E/i) {
my @st = stat($c->[1]);
push(@urls, [ $c->[0], $c->[2], $st[7], $st[9] ]);
}
}
if (@urls) {
# Show the results
print &text('cache_matches', scalar(@urls)),"<br>\n";
@tds = ( "width=5" );
print &ui_form_start("delete_cache.cgi", "post");
print &ui_hidden("search", $in{'search'}),"\n";
@links = ( &select_all_link("d", 1),
&select_invert_link("d", 1) );
print &ui_links_row(\@links);
print &ui_columns_start([ "", $text{'cache_url'},
$text{'cache_size'}, $text{'cache_date'} ],
100, 0, \@tds);
foreach $url (@urls) {
print &ui_checked_columns_row(
[ $url->[1], &nice_size($url->[2]), &make_date($url->[3], 1) ],
\@tds, "d", $url->[0]);
}
print &ui_columns_end();
print &ui_links_row(\@links);
print &ui_form_end([ [ "delete", $text{'cache_delete'} ] ]);
}
else {
print "<b>$text{'cache_none'}</b><p>\n";
}
}
&ui_print_footer("edit_proxy.cgi", $text{'proxy_return'},
"", $text{'index_return'});
+12
View File
@@ -0,0 +1,12 @@
do 'webmin-lib.pl';
sub cgi_args
{
my ($cgi) = @_;
if ($cgi =~ /^edit_/ || $cgi eq 'index.cgi') {
# No args needed for sure
return '';
}
return 'none';
}
+69
View File
@@ -0,0 +1,69 @@
#!/usr/local/bin/perl
# change_access.cgi
# Update IP allow and deny parameters
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'access_err'});
$raddr = $ENV{'REMOTE_ADDR'};
@hosts = split(/\s+/, $in{"ip"});
if ($in{"access"}) {
push(@hosts, "LOCAL") if ($in{'local'});
if (!@hosts) { &error($text{'access_enone'}); }
foreach $h (@hosts) {
$err = &valid_allow($h);
&error($err) if ($err);
push(@ip, $h);
}
if ($in{"access"} == 1 && !&ip_match($raddr, @ip) ||
$in{"access"} == 2 && &ip_match($raddr, @ip)) {
&error(&text('access_eself', $raddr));
}
}
eval "use Authen::Libwrap qw(hosts_ctl STRING_UNKNOWN)";
if (!$@ && $in{'libwrap'}) {
# Check if the current address would be denied
if (!hosts_ctl("webmin", STRING_UNKNOWN, $raddr, STRING_UNKNOWN)) {
&error(&text('access_eself', $raddr));
}
}
@tprox = split(/\s+/, $in{'trusted_proxies'});
foreach $h (@tprox) {
$err = &valid_allow($h);
&error($err) if ($err);
}
if ($in{'trust'} == 2 && !@tprox) {
&error($text{'access_etproxies'});
}
&lock_file($ENV{'MINISERV_CONFIG'});
&get_miniserv_config(\%miniserv);
delete($miniserv{"allow"});
delete($miniserv{"deny"});
if ($in{"access"} == 1) { $miniserv{"allow"} = join(' ', @hosts); }
elsif ($in{"access"} == 2) { $miniserv{"deny"} = join(' ', @hosts); }
$miniserv{"known_ips"} = $miniserv{"allow"} || $miniserv{"deny"} ||
(!@hosts && $in{"access"} == 0 ? "" : $miniserv{"known_ips"});
$miniserv{'libwrap'} = $in{'libwrap'};
$miniserv{'alwaysresolve'} = $in{'alwaysresolve'};
if ($in{'trust'} == 2) {
$miniserv{'trust_real_ip'} = 1;
$miniserv{'no_trust_ssl'} = 0;
}
elsif ($in{'trust'} == 1) {
$miniserv{'trust_real_ip'} = 1;
$miniserv{'no_trust_ssl'} = 1;
}
else {
$miniserv{'trust_real_ip'} = 0;
$miniserv{'no_trust_ssl'} = 1;
}
$miniserv{'trusted_proxies'} = join(' ', @tprox);
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
&show_restart_page();
&webmin_log("access", undef, undef, \%in);
+284
View File
@@ -0,0 +1,284 @@
#!/usr/local/bin/perl
# Save advanced options
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'advanced_err'});
&get_miniserv_config(\%miniserv);
# Permissions used for newly created Webmin temp directories.
my $advanced_temp_dir_perms = 0755;
my $advanced_temp_dir_perms_text = sprintf("%04o", $advanced_temp_dir_perms);
my @advanced_temp_dirs_to_create;
# Save global temp dir setting
if ($in{'tempdir_def'}) {
delete($gconfig{'tempdir'});
}
else {
$in{'tempdir'} = &validate_advanced_temp_dir(
$in{'tempdir'}, $text{'advanced_etemp'},
\@advanced_temp_dirs_to_create);
$gconfig{'tempdir'} = $in{'tempdir'};
}
# Save temp clearing options
$gconfig{'tempdirdelete'} = $in{'tempdirdelete'};
if ($in{'tempdelete_def'}) {
$gconfig{'tempdelete_days'} = '';
}
else {
$in{'tempdelete'} =~ /^[0-9\.]+$/ ||
&error($text{'advanced_etempdelete'});
$gconfig{'tempdelete_days'} = $in{'tempdelete'};
}
# Save per-module temp dirs
for($i=0; defined($tmod = $in{'tmod_'.$i}); $i++) {
next if (!$tmod);
$tdir = $in{'tdir_'.$i};
%minfo = &get_module_info($tmod);
$tdir = &validate_advanced_temp_dir(
$tdir, &text('advanced_etdir', $minfo{'desc'}),
\@advanced_temp_dirs_to_create);
push(@tdirs, [ $tmod, $tdir ]);
}
&save_tempdirs(\%gconfig, \@tdirs);
# Save umask
if ($in{'umask_def'}) {
delete($gconfig{'umask'});
}
else {
$in{'umask'} =~ /^[0-7]{3}$/ || &error($text{'advanced_eumask'});
$gconfig{'umask'} = $in{'umask'};
}
# Save chattr
if (defined($in{'chattr'})) {
$gconfig{'chattr'} = $in{'chattr'};
}
# Save nice level
if ($in{'nice_def'}) {
delete($gconfig{'nice'});
}
else {
$gconfig{'nice'} = $in{'nice'};
}
# Save scheduling class
if (defined($in{'sclass'})) {
$gconfig{'sclass'} = $in{'sclass'};
$gconfig{'sprio'} = $in{'sprio'};
}
# Save HTTP headers
@hl = ( );
foreach my $l (split(/\r?\n/, $in{'headers'})) {
$l =~ /^\S+:\s+\S.*$/ || &error($text{'advanced_eheader'});
push(@hl, $l);
}
$gconfig{'extra_headers'} = join("\t", @hl);
if (defined($in{'preload'})) {
# Save preload option, forcing new mode
if ($in{'preload'}) {
$miniserv{'premodules'} = 'WebminCore';
}
else {
delete($miniserv{'premodules'});
}
&save_preloads(\%miniserv, [ ]);
}
# Save pre-cache option
if ($in{'precache_mode'} == 0) {
$miniserv{'precache'} = 'none';
}
elsif ($in{'precache_mode'} == 1) {
$miniserv{'precache'} = '';
}
else {
$in{'precache'} =~ /\S/ || &error($text{'advanced_eprecache'});
$miniserv{'precache'} = $in{'precache'};
}
# Save buffer size
if ($in{'bufsize_def'}) {
delete($miniserv{'bufsize'});
}
else {
$in{'bufsize'} =~ /^\d+$/ && $in{'bufsize'} > 0 ||
&error($text{'advanced_ebufsize'});
$miniserv{'bufsize'} = $in{'bufsize'};
}
# Save buffer size
if ($in{'bufsize_binary_def'}) {
delete($miniserv{'bufsize_binary'});
}
else {
$in{'bufsize_binary'} =~ /^\d+$/ && $in{'bufsize_binary'} > 0 ||
&error($text{'advanced_ebufsize_binary'});
$miniserv{'bufsize_binary'} = $in{'bufsize_binary'};
}
# Sort config file's keys alphabetically
if (defined($in{'sortconfigs'})) {
$gconfig{'sortconfigs'} = $in{'sortconfigs'};
}
&setup_advanced_temp_dirs(\@advanced_temp_dirs_to_create);
&lock_file("$config_directory/config");
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&lock_file($ENV{'MINISERV_CONFIG'});
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
&show_restart_page();
&webmin_log("advanced");
# Validate a configured Webmin temp directory without creating or changing it.
# Missing components are queued and created after all form validation passes.
sub validate_advanced_temp_dir
{
my ($dir, $missing_error, $create_dirs) = @_;
$dir =~ /\S/ || &error($missing_error);
$dir =~ s/\/+$// if ($dir ne "/");
$dir =~ /\S/ || &error($missing_error);
if (&advanced_temp_dir_is_windows($dir)) {
$dir = &webmin_temp_dir_path($dir);
if (-e $dir || -l $dir) {
-d $dir ||
&error(&text('advanced_etempparent', $dir));
}
else {
push(@$create_dirs, $dir);
}
return $dir;
}
if ($dir =~ /^\//) {
my $sdir = &simplify_path($dir);
defined($sdir) || &error($missing_error);
$dir = $sdir;
}
# Treat the entered directory as a base path. The final Webmin-private
# component is always the hidden tempdirname setting, or .webmin by default.
$dir = &webmin_temp_dir_path($dir);
# Walk the path so existing components are checked, while missing components
# can be created after all form validation has passed.
my $path = $dir =~ /^\// ? "/" : "";
foreach my $part (split(/\/+/, $dir)) {
next if ($part eq "");
$path = $path eq "/" ? "/$part" :
$path eq "" ? $part : "$path/$part";
my $final = $path eq $dir;
my @st = lstat($path);
if (!@st) {
push(@$create_dirs, $path);
next;
}
-d _ || &error(&text('advanced_etempparent', $path));
if ($final) {
&advanced_temp_dir_perms_ok($path) ||
&error(&text('advanced_etempperms', $path,
$advanced_temp_dir_perms_text));
}
else {
&advanced_temp_parent_dir_perms_ok($path) ||
&error(&text('advanced_etempparentperms',
$path));
}
}
return $dir;
}
# Create missing temp directory components after all form validation passes.
sub setup_advanced_temp_dirs
{
my ($dirs) = @_;
my %done;
my @created;
foreach my $dir (@$dirs) {
next if ($done{$dir}++);
if (&advanced_temp_dir_is_windows($dir)) {
if (!-d $dir) {
&make_dir($dir, $advanced_temp_dir_perms, 1) ||
&advanced_temp_dirs_error(
\@created,
&text('advanced_etempmkdir',
$dir, "$!"));
push(@created, $dir);
}
-d $dir ||
&advanced_temp_dirs_error(
\@created,
&text('advanced_etempmkdir', $dir, "$!"));
next;
}
if (-e $dir || -l $dir) {
&advanced_temp_dir_perms_ok($dir) ||
&advanced_temp_dirs_error(
\@created,
&text('advanced_etempperms', $dir,
$advanced_temp_dir_perms_text));
next;
}
&make_dir($dir, $advanced_temp_dir_perms) ||
&advanced_temp_dirs_error(
\@created,
&text('advanced_etempmkdir', $dir, "$!"));
push(@created, $dir);
&advanced_temp_dir_perms_ok($dir) ||
&advanced_temp_dirs_error(
\@created,
&text('advanced_etempchmod', $dir,
$advanced_temp_dir_perms_text, "$!"));
}
}
# Roll back only directories created by this save attempt, and only if empty.
sub advanced_temp_dirs_error
{
my ($created, $msg) = @_;
foreach my $dir (reverse(@$created)) {
rmdir($dir);
}
&error($msg);
}
# Check the final configured temp directory. It must be Webmin-private.
sub advanced_temp_dir_perms_ok
{
my ($dir) = @_;
my @st = lstat($dir);
return 0 if (!@st || !-d _);
return 0 if ($st[4] != $<);
my $mode = $st[2] & 07777;
return $mode == $advanced_temp_dir_perms;
}
# Existing parents only need to be searchable by group and others. The final
# temp directory itself is checked more strictly above.
sub advanced_temp_parent_dir_perms_ok
{
my ($dir) = @_;
my @st = lstat($dir);
return 0 if (!@st || !-d _);
my $mode = $st[2] & 07777;
return 0 if (($mode & 0011) != 0011);
return 1;
}
# Windows temp directories are only checked when they already exist.
sub advanced_temp_dir_is_windows
{
my ($dir) = @_;
return $gconfig{'os_type'} eq 'windows' || $dir =~ /^[a-z]:/i;
}
+24
View File
@@ -0,0 +1,24 @@
#!/usr/local/bin/perl
# change_anon.cgi
# Update list of anonymously accessible modules
require './webmin-lib.pl';
&ReadParse();
&get_miniserv_config(\%miniserv);
&error_setup($text{'anon_err'});
# Check inputs
&read_acl(undef, \%acl);
for($i=0; defined($in{"url_$i"}); $i++) {
next if (!$in{"url_$i"});
$in{"url_$i"} =~ /^\/\S+$/ || &error(&text('anon_eurl', $in{"url_$i"}));
$acl{$in{"user_$i"}} || &error(&text('anon_euser', $in{"url_$i"}));
push(@anon, $in{"url_$i"}."=".$in{"user_$i"});
}
&lock_file($ENV{'MINISERV_CONFIG'});
$miniserv{'anonymous'} = join(" ", @anon);
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
&show_restart_page();
&webmin_log("anon", undef, undef, \%in);
+193
View File
@@ -0,0 +1,193 @@
#!/usr/local/bin/perl
# change_bind.cgi
# Update the binding IP address and port for miniserv
require './webmin-lib.pl';
&ReadParse();
&get_miniserv_config(\%miniserv);
%oldminiserv = %miniserv;
&error_setup($text{'bind_err'});
# Validate inputs
for($i=0; defined($in{"ip_def_$i"}); $i++) {
next if (!$in{"ip_def_$i"});
if ($in{"ip_def_$i"} == 1) {
$ip = "*";
}
else {
$ip = $in{"ip_$i"};
&check_ipaddress($ip) ||
$in{'ipv6'} && &check_ip6address($ip) ||
&error(&text('bind_eip2', $ip));
}
if ($in{"port_def_$i"} == 1) {
$port = $in{"port_$i"};
$port =~ /^\d+$/ && $port < 65536 ||
&error(&text('bind_eport2', $port));
}
else {
$port = "*";
}
push(@sockets, [ $ip, $port ]);
push(@ports, $port) if ($port && $port ne "*");
}
@sockets || &error($text{'bind_enone'});
$in{'listen_def'} || $in{'listen'} =~ /^\d+$/ || &error($text{'bind_elisten'});
$in{'hostname_def'} || $in{'hostname'} =~ /^[a-z0-9\.\-]+$/i ||
&error($text{'bind_ehostname'});
if ($in{'ipv6'}) {
eval "use Socket6";
$@ && &error(&text('bind_eipv6', "<tt>Socket6</tt>"));
}
# For any new ports, check if they are already in use
@oldports = split(/\s+/, $in{'oldports'});
@newports = &unique(grep { &indexof($_, @oldports) < 0 } @ports);
if (&has_command("lsof")) {
foreach my $p (@newports) {
$out = &backquote_command("lsof -t -i tcp:$p 2>/dev/null");
if ($out =~ /\d+/) {
&error(&text('bind_elsof', $p));
}
}
}
# Make sure each IP is actually active on the system
@ips = grep { $_ ne "*" } map { $_->[0] } @sockets;
if (@ips && &foreign_installed("net")) {
%onsystem = ( );
&foreign_require("net");
if (defined(&net::active_interfaces)) {
foreach $a (&net::active_interfaces()) {
$onsystem{$a->{'address'}} = $a;
foreach $ip6 (@{$a->{'address6'}}) {
$onsystem{&canonicalize_ip6($ip6)} = $a;
}
}
}
if (%onsystem) {
foreach $ip (@ips) {
$onsystem{&canonicalize_ip6($ip)} ||
&error(&text('bind_eonsystem', $ip));
}
}
}
# Update config file
&lock_file($ENV{'MINISERV_CONFIG'});
$first = shift(@sockets);
$miniserv{'port'} = $first->[1];
if ($first->[0] eq "*") {
delete($miniserv{'bind'});
}
else {
$miniserv{'bind'} = $first->[0];
}
$miniserv{'sockets'} = join(" ", map { "$_->[0]:$_->[1]" } @sockets);
if ($in{'websocket_base_port_def'}) {
delete($miniserv{'websocket_base_port'});
}
else {
$miniserv{'websocket_base_port'} = $in{'websocket_base_port'};
}
if ($in{'websocket_host_def'}) {
delete($miniserv{'websocket_host'});
}
else {
$miniserv{'websocket_host'} = $in{'websocket_host'};
}
$miniserv{'ipv6'} = $in{'ipv6'};
if ($in{'listen_def'}) {
delete($miniserv{'listen'});
}
else {
$miniserv{'listen'} = $in{'listen'};
}
if ($in{'hostname_def'}) {
delete($miniserv{'host'});
}
else {
$miniserv{'host'} = $in{'hostname'};
}
$miniserv{'no_resolv_myname'} = $in{'no_resolv_myname'};
if ($in{'maxconns_def'}) {
delete($miniserv{'maxconns'});
}
else {
$in{'maxconns'} =~ /^\d+$/ && $in{'maxconns'} > 1 ||
&error($text{'bind_emaxconns'});
$miniserv{'maxconns'} = $in{'maxconns'};
}
if ($in{'maxconns_per_ip_def'}) {
delete($miniserv{'maxconns_per_ip'});
}
else {
$in{'maxconns_per_ip'} =~ /^\d+$/ && $in{'maxconns_per_ip'} > 1 ||
&error($text{'bind_emaxconns_per_ip'});
$miniserv{'maxconns_per_ip'} = $in{'maxconns_per_ip'};
}
if ($in{'maxconns_per_net_def'}) {
delete($miniserv{'maxconns_per_net'});
}
else {
$in{'maxconns_per_net'} =~ /^\d+$/ && $in{'maxconns_per_net'} > 1 ||
&error($text{'bind_emaxconns_per_net'});
$miniserv{'maxconns_per_net'} = $in{'maxconns_per_net'};
}
if ($in{'maxlifetime_def'}) {
delete($miniserv{'maxlifetime'});
}
else {
$in{'maxlifetime'} =~ /^\d+$/ && $in{'maxlifetime'} > 60 ||
&error($text{'bind_emaxlifetime'});
$miniserv{'maxlifetime'} = $in{'maxlifetime'};
}
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
# Re-start miniserv
&restart_miniserv(1);
# If possible, open the new ports
foreach my $mod ("firewall", "firewalld") {
if (&foreign_check($mod) && $in{'firewall'}) {
if (@newports) {
&clean_environment();
$ENV{'WEBMIN_CONFIG'} = $config_directory;
&system_logged(
&module_root_directory($mod)."/open-ports.pl ".
join(" ", map { $_.":".($_+10) } @newports).
" >/dev/null 2>&1");
&reset_environment();
}
}
}
&webmin_log("bind", undef, undef, \%in);
# Work out redirect URL
if ($miniserv{'musthost'}) { $miniserv{'musthost'}; }
elsif ($miniserv{'bind'}) { $url = $miniserv{'bind'}; }
else { $url = $ENV{'SERVER_NAME'}; }
if ($ENV{'HTTPS'} eq "ON") { $url = "https://$url"; }
else { $url = "http://$url"; }
# Theme redirect if port changed
if ($miniserv{'port'} != $oldminiserv{'port'}) {
$url .= ":$miniserv{'port'}";
my %tinfo = &get_theme_info($current_theme);
if ($tinfo{'spa'} && $tinfo{'nomodcall'}) {
$url .= "@{[&get_webprefix()]}/webmin/?$tinfo{'nomodcall'}";
}
&ui_print_header(undef, $text{'bind_title'}, "", undef, undef, 1);
print $text{'bind_redirecting'},"<br>\n";
print "<script>\n";
print "top.location = '$url';\n";
print "</script>\n";
&ui_print_footer();
}
else {
$url .= ":$miniserv{'port'}@{[&get_webprefix()]}/webmin/";
&redirect($url);
}
+28
View File
@@ -0,0 +1,28 @@
#!/usr/local/bin/perl
# change_ca.cgi
# Update the CA cert manually
require './webmin-lib.pl';
&ReadParseMime();
&lock_file($ENV{'MINISERV_CONFIG'});
&get_miniserv_config(\%miniserv);
if (!$miniserv{'ca'}) {
&setup_ca(\%miniserv);
}
&lock_file($miniserv{'ca'});
&open_tempfile(CA, ">$miniserv{'ca'}");
$in{'cert'} =~ s/\r//g;
$in{'cert'} =~ s/\n*$/\n/;
&print_tempfile(CA, $in{'cert'});
&close_tempfile(CA);
chmod(0700, $miniserv{'ca'});
&unlock_file($miniserv{'ca'});
unlink("$config_directory/acl/crl.pem");
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
&redirect("");
sleep(1);
&show_restart_page();
&webmin_log("changeca", undef, undef, \%in);
+60
View File
@@ -0,0 +1,60 @@
#!/usr/local/bin/perl
# Save debug mode options
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'debug_err'});
# Validate and store inputs
&lock_file("$config_directory/config");
$gconfig{'debug_enabled'} = $in{'debug_enabled'};
# What to log
$count = 0;
foreach $w (@debug_what_events) {
$gconfig{'debug_what_'.$w} = $in{'debug_what_'.$w};
$count++ if ($in{'debug_what_'.$w});
}
$count || &error($text{'debug_ewhat'});
# Log file
if ($in{'debug_file_def'}) {
delete($gconfig{'debug_file'});
}
else {
$in{'debug_file'} =~ /^(.*\/)([^\/]+)$/ ||
&error($text{'debug_efile'});
-d $1 || &error(&text('debug_edir', "$1"));
$gconfig{'debug_file'} = $in{'debug_file'};
}
# Size before clearing
if ($in{'debug_size_def'}) {
delete($gconfig{'debug_size'});
}
else {
$in{'debug_size'} =~ /^\d+$/ || &error($text{'debug_esize'});
$gconfig{'debug_size'} = $in{'debug_size'}*$in{'debug_size_units'};
}
# What to debug
$gconfig{'debug_noweb'} = !$in{'debug_web'};
$gconfig{'debug_nocmd'} = !$in{'debug_cmd'};
$gconfig{'debug_nocron'} = !$in{'debug_cron'};
# Modules
if ($in{'mall'}) {
delete($gconfig{'debug_modules'});
}
else {
$in{'modules'} || &error($text{'debug_emodules'});
$gconfig{'debug_modules'} = join(' ', split(/\0/, $in{'modules'}));
}
# Write out
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&webmin_log("debug");
&redirect("");
+19
View File
@@ -0,0 +1,19 @@
#!/usr/local/bin/perl
# change_lang.cgi
# Change language setting
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'lang_err'});
&lock_file("$config_directory/config");
$gconfig{'lang'} = $in{'lang'};
$gconfig{'langauto'} = int($in{'langauto'});
$gconfig{'acceptlang'} = $in{'acceptlang'};
$gconfig{'dateformat'} = $in{'dateformat'};
$gconfig{'locale'} = $in{'locale'};
$gconfig{'charset'} = 'UTF-8';
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&webmin_log("lang", undef, undef, \%in);
&redirect("");
+26
View File
@@ -0,0 +1,26 @@
#!/usr/local/bin/perl
# Save file locking settings
require './webmin-lib.pl';
&ReadParse();
# Validate inputs
&error_setup($text{'lock_err'});
if ($in{'lockmode'} >= 2) {
@dirs = split(/\n+/, $in{'lockdirs'});
foreach $d (@dirs) {
$d =~ /^\// || &error(&text('lock_edir', $d));
}
@dirs || &error($text{'lock_edirs'});
}
# Write out config
&lock_file($config_file);
$gconfig{'lockmode'} = $in{'lockmode'};
$gconfig{'lockdirs'} = join("\t", @dirs);
&save_module_config(\%gconfig, "");
&unlock_file($config_file);
&webmin_log("lock");
&redirect("");
+76
View File
@@ -0,0 +1,76 @@
#!/usr/local/bin/perl
# change_log.cgi
# Enable or disable logging
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'log_err'});
&lock_file($ENV{'MINISERV_CONFIG'});
&get_miniserv_config(\%miniserv);
my ($miniserv_log, $in_log) = ($miniserv{'log'}, $in{'log'});
$miniserv{'log'} = $in{'log'};
$miniserv{'loghost'} = $in{'loghost'};
$miniserv{'logtrust'} = $in{'logtrust'};
$miniserv{'logclf'} = $in{'logclf'};
$miniserv{'logclear'} = $in{'logclear'};
!$in{'logclear'} || $in{'logtime'} =~ /^[1-9][0-9]*$/ ||
&error(&text('log_ehours', $in{'logtime'}));
$miniserv{'logtime'} = $in{'logtime'};
if ($in{'perms_def'}) {
delete($miniserv{'logperms'});
}
else {
$in{'perms'} =~ /^[0-7]{3,4}$/ || &error($text{'log_eperms'});
$miniserv{'logperms'} = $in{'perms'};
}
if (defined($in{'login'})) {
if ($in{'login'}) {
# Create and user login wrapper scripts
&foreign_require("cron");
&cron::create_wrapper($record_login_cmd,"","record-login.pl");
&cron::create_wrapper($record_logout_cmd,"","record-logout.pl");
&cron::create_wrapper($record_failed_cmd,"","record-failed.pl");
$miniserv{'login_script'} = $record_login_cmd;
$miniserv{'logout_script'} = $record_logout_cmd;
$miniserv{'failed_script'} = $record_failed_cmd;
}
else {
# Stop using
delete($miniserv{'login_script'});
delete($miniserv{'logout_script'});
delete($miniserv{'failed_script'});
}
}
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
$gconfig{'log'} = $in{'log'};
$gconfig{'logtime'} = $in{'logtime'};
$gconfig{'logclear'} = $in{'logclear'};
$gconfig{'logusers'} =
$in{'uall'} ? '' : join(" ", split(/\0/, $in{'users'}));
$gconfig{'logmodules'} =
$in{'mall'} ? '' : join(" ", split(/\0/, $in{'modules'}));
$gconfig{'logsched'} = $in{'logsched'};
$gconfig{'logfiles'} = $in{'logfiles'};
$gconfig{'logfullfiles'} = $in{'logfullfiles'};
$gconfig{'logperms'} = $miniserv{'logperms'};
!$in{'logfiles'} || &has_command("diff") ||
&error(&text('log_ediff', "diff"));
$gconfig{'logsyslog'} = $in{'logsyslog'} if (defined($in{'logsyslog'}));
&lock_file("$config_directory/config");
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
# Clear links in Virtualmin module if installed
if ($miniserv_log != $in_log) {
if (&foreign_available('virtual-server')) {
&foreign_require("virtual-server");
&virtual_server::clear_links_cache();
}
}
&show_restart_page();
&webmin_log("log", undef, undef, \%in);
+36
View File
@@ -0,0 +1,36 @@
#!/usr/local/bin/perl
# Display options specific to mobile devices
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'mobile_err'});
&lock_file($ENV{'MINISERV_CONFIG'});
&lock_file("$config_directory/config");
&get_miniserv_config(\%miniserv);
# Validate and store inputs
if ($in{'theme'} eq '*') {
delete($miniserv{'mobile_preroot'});
delete($gconfig{'mobile_theme'});
}
else {
$miniserv{'mobile_preroot'} = $in{'theme'};
$gconfig{'mobile_theme'} = $in{'theme'};
}
$miniserv{'mobile_nosession'} = $in{'nosession'};
$in{'agents'} =~ s/\r//g;
$miniserv{'mobile_agents'} = join("\t", split(/\n+/, $in{'agents'}));
$miniserv{'mobile_prefixes'} = $in{'prefixes'};
# Write out files
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&reload_miniserv();
&webmin_log('mobile', undef, undef, \%in);
&redirect("");
+68
View File
@@ -0,0 +1,68 @@
#!/usr/local/bin/perl
# change_os.cgi
# Change OS settings
require './webmin-lib.pl';
&ReadParse();
&lock_file("$config_directory/config");
if ($in{'update'}) {
# Automatically detect
%osinfo = &detect_operating_system();
$gconfig{'real_os_type'} = $osinfo{'real_os_type'};
$gconfig{'real_os_version'} = $osinfo{'real_os_version'};
$gconfig{'os_type'} = $osinfo{'os_type'};
$gconfig{'os_version'} = $osinfo{'os_version'};
}
elsif ($in{'type'} ne $gconfig{'real_os_type'} ||
$in{'version'} ne $gconfig{'real_os_version'} ||
$in{'itype'} ne $gconfig{'os_type'} ||
$in{'iversion'} ne $gconfig{'os_version'}) {
# Manually change
$gconfig{'real_os_type'} = $in{'type'};
$in{'version'} || &error($text{'os_eversion'});
$gconfig{'real_os_version'} = $in{'version'};
($os) = grep { $_->{'realtype'} eq $in{'type'} }
&list_operating_systems();
$gconfig{'os_type'} = $in{'itype'};
$in{'iversion'} || &error($text{'os_eiversion'});
$gconfig{'os_version'} = $in{'iversion'};
}
# EOL data
if (defined($in{'os_eol_before'}) &&
$in{'os_eol_before'} ne $gconfig{'os_eol_before'}) {
$in{'os_eol_before'} =~ /^\d+$/ || &error($text{'os_eol_ecountdown'});
$gconfig{'os_eol_before'} = $in{'os_eol_before'};
# Invalidate EOL cache
foreach my $key ('os_eol_db', 'os_eol_expired',
'os_eol_expiring') {
delete($gconfig{$key});
}
}
# Path
$gconfig{'path'} = join($path_separator, split(/[\r\n]+/, $in{'path'}));
$gconfig{'syspath'} = !$in{'syspath'};
if ($gconfig{'ld_env'}) {
$gconfig{'ld_path'} = join($path_separator,
split(/[\r\n]+/, $in{'ld_path'}));
}
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&lock_file($ENV{'MINISERV_CONFIG'});
&get_miniserv_config(\%miniserv);
foreach $e (keys %miniserv) {
delete($miniserv{$e}) if ($e =~ /^env_(\S+)$/ &&
$1 ne "WEBMIN_CONFIG" && $1 ne "WEBMIN_VAR");
}
for($i=0; defined($n = $in{"name_$i"}); $i++) {
next if (!$n);
$miniserv{'env_'.$n} = $in{"value_$i"}
if ($n ne "WEBMIN_CONFIG" && $n ne "WEBMIN_VAR");
}
$miniserv{'perllib'} = join(':', split(/\r?\n/, $in{'perllib'}));
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
&show_restart_page();
&webmin_log("os", undef, undef, \%in);
+71
View File
@@ -0,0 +1,71 @@
#!/usr/local/bin/perl
# Change OSDN download settings
require './webmin-lib.pl';
&error_setup($text{'proxy_err'});
&ReadParse();
if ($in{'clear'}) {
# Just clearing Webmin's cache
&ui_print_header(undef, $text{'clear_title'}, "");
$sz = &disk_usage_kb($main::http_cache_directory)*1024;
if ($sz > 0) {
opendir(DIR, $main::http_cache_directory);
@files = readdir(DIR);
closedir(DIR);
&system_logged("rm -rf ".
quotemeta($main::http_cache_directory));
print &text('clear_done', &nice_size($sz), @files-2),"<p>\n";
&webmin_log("osdnclear");
}
else {
print &text('clear_none'),"<p>\n";
}
&ui_print_footer("", $text{'index_return'});
exit;
}
&lock_file("$config_directory/config");
# Save cache size
if ($in{'cache_def'}) {
delete($gconfig{'cache_size'});
}
else {
$in{'cache'} =~ /^\d+$/ || &error($text{'proxy_ecache'});
$gconfig{'cache_size'} = $in{'cache_units'}*$in{'cache'};
}
# Save cache days
if ($in{'days_def'}) {
delete($gconfig{'cache_days'});
}
else {
$in{'days'} =~ /^\d+$/ || &error($text{'proxy_edays'});
$gconfig{'cache_days'} = $in{'days'};
}
# Save modules
if ($in{'mods_def'} == 0) {
delete($gconfig{'cache_mods'});
}
else {
@mods = split(/\0/, $in{'mods'});
@mods || &error($text{'proxy_emods'});
if ($in{'mods_def'} == 1) {
$gconfig{'cache_mods'} = join(" ", @mods);
}
else {
$gconfig{'cache_mods'} = "!".join(" ", @mods);
}
}
# Write out the file
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&webmin_log('osdn', undef, undef, \%in);
&redirect("");
+45
View File
@@ -0,0 +1,45 @@
#!/usr/local/bin/perl
# Change the current webmin theme overlay
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'themes_err4'});
# Get the overlay and make sure it is compatible
($gtheme) = split(/\s+/, $gconfig{'theme'});
if ($in{'overlay'}) {
%oinfo = &get_theme_info($in{'overlay'});
if ($oinfo{'overlays'} &&
&indexof($gtheme, split(/\s+/, $oinfo{'overlays'})) < 0) {
&error($text{'themes_eoverlay'});
}
}
&lock_file("$config_directory/config");
if ($in{'overlay'}) {
$gconfig{'theme'} = join(" ", $gtheme, $in{'overlay'});
}
else {
$gconfig{'theme'} = $gtheme;
}
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&lock_file($ENV{'MINISERV_CONFIG'});
&get_miniserv_config(\%miniserv);
if ($in{'overlay'}) {
$miniserv{'preroot'} = join(" ", $gtheme, $in{'overlay'});
}
else {
$miniserv{'preroot'} = $gtheme;
}
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
&reload_miniserv();
&webmin_log('theme', undef, undef, \%in);
&ui_print_header(undef, $text{'themes_title'}, "");
print "$text{'themes_ok2'}<p>\n";
print &js_redirect("/", "top", 1500);
&ui_print_footer("", $text{'index_return'});
+41
View File
@@ -0,0 +1,41 @@
#!/usr/local/bin/perl
# change_proxy.cgi
# Change proxy settings
require './webmin-lib.pl';
&error_setup($text{'proxy_err'});
&ReadParse();
&lock_file("$config_directory/config");
if ($in{'http_def'}) { delete($gconfig{'http_proxy'}); }
elsif ($in{'http'} !~ /^http:\/\/(\S+):(\d+)/) {
&error(&text('proxy_ehttp2', "http://proxy.foo.com:8080/"));
}
else { $gconfig{'http_proxy'} = $in{'http'}; }
if ($in{'ftp_def'}) { delete($gconfig{'ftp_proxy'}); }
elsif ($in{'ftp'} !~ /^http:\/\/(\S+):(\d+)/) {
&error(&text('proxy_eftp2', "http://proxy.foo.com:8080/"));
}
else { $gconfig{'ftp_proxy'} = $in{'ftp'}; }
if ($in{'bind_def'}) {
delete($gconfig{'bind_proxy'});
}
else {
&check_ipaddress($in{'bind'}) || &error($text{'proxy_ebind'});
$gconfig{'bind_proxy'} = $in{'bind'};
}
$gconfig{'proxy_fallback'} = $in{'fallback'};
$gconfig{'proxy_user'} = $in{'puser'};
$gconfig{'proxy_pass'} = $in{'ppass'};
$gconfig{'noproxy'} = $in{'noproxy'};
# Write out the config
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&webmin_log('proxy', undef, undef, \%in);
&redirect("");
+23
View File
@@ -0,0 +1,23 @@
#!/usr/local/bin/perl
# change_referers.cgi
# Change referer checking settings
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'referers_err'});
&lock_file("$config_directory/config");
$gconfig{'referer'} = $in{'referer'};
@refs = split(/\s+/, $in{'referers'});
foreach my $r (@refs) {
$r =~ /^[a-z0-9\.\-\_]+$/ ||
&error(&text('referers_ehost', &html_escape($r)));
}
$gconfig{'referers'} = join(" ", @refs);
$gconfig{'referers_none'} = int(!$in{'referers_none'});
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&webmin_log('referers', undef, undef, \%in);
&redirect("");
+193
View File
@@ -0,0 +1,193 @@
#!/usr/local/bin/perl
# change_session.cgi
# Enable or disable session authentication
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'session_err'});
&foreign_require("acl");
&lock_file($ENV{'MINISERV_CONFIG'});
&get_miniserv_config(\%miniserv);
$miniserv{'passdelay'} = $in{'passdelay'};
# Save blocked hosts
if ($in{'blockhost_on'}) {
$in{'blockhost_time'} =~ /^\d+$/ && $in{'blockhost_time'} > 0 ||
&error($text{'session_eblockhost_time'});
$in{'blockhost_failures'} =~ /^\d+$/ && $in{'blockhost_failures'} > 0 ||
&error($text{'session_eblockhost_failures'});
$miniserv{'blockhost_time'} = $in{'blockhost_time'};
$miniserv{'blockhost_failures'} = $in{'blockhost_failures'};
}
else {
$miniserv{'blockhost_time'} = $miniserv{'blockhost_failures'} = undef;
}
# Save blocked users
if ($in{'blockuser_on'}) {
$in{'blockuser_time'} =~ /^\d+$/ && $in{'blockuser_time'} > 0 ||
&error($text{'session_eblockuser_time'});
$in{'blockuser_failures'} =~ /^\d+$/ && $in{'blockuser_failures'} > 0 ||
&error($text{'session_eblockuser_failures'});
$miniserv{'blockuser_time'} = $in{'blockuser_time'};
$miniserv{'blockuser_failures'} = $in{'blockuser_failures'};
}
else {
$miniserv{'blockuser_time'} = $miniserv{'blockuser_failures'} = undef;
}
$miniserv{'blocklock'} = $in{'blocklock'};
$miniserv{'syslog'} = $in{'syslog'};
if ($in{'session'} && $ENV{'HTTP_COOKIE'} !~ /sessiontest=1/i &&
!$ENV{'HTTP_WEBMIN_SERVERS'}) {
&error($text{'session_ecookie'});
}
if (defined($in{'session'})) {
$miniserv{'session'} = $in{'session'};
}
if ($in{'logouttime_on'}) {
$in{'logouttime'} =~ /^\d+$/ && $in{'logouttime'} > 0 ||
&error($text{'session_elogouttime'});
}
$miniserv{'logouttime'} = $in{'logouttime_on'} ? $in{'logouttime'} : undef;
if (defined($in{'localauth'})) {
if ($in{'localauth'}) {
$lsof = &has_command("lsof");
&error($text{'session_elsof'}) if (!$lsof);
$miniserv{'localauth'} = $lsof;
}
else {
delete($miniserv{'localauth'});
}
}
$miniserv{'no_pam'} = $in{'no_pam'};
if ($in{'passwd_file'}) {
$in{'passwd_file'} =~ /\|$/ || -r $in{'passwd_file'} ||
&error($text{'session_epasswd_file'});
$in{'passwd_uindex'} =~ /^\d+$/ ||
&error($text{'session_epasswd_uindex'});
$in{'passwd_pindex'} =~ /^\d+$/ ||
&error($text{'session_epasswd_pindex'});
$miniserv{'passwd_file'} = $in{'passwd_file'};
$miniserv{'passwd_uindex'} = $in{'passwd_uindex'};
$miniserv{'passwd_pindex'} = $in{'passwd_pindex'};
}
else {
delete($miniserv{'passwd_file'});
delete($miniserv{'passwd_uindex'});
delete($miniserv{'passwd_pindex'});
}
$miniserv{'pam_conv'} = $in{'pam_conv'};
$miniserv{'pam_end'} = $in{'pam_end'};
if ($in{'cmd_def'}) {
delete($gconfig{'passwd_cmd'});
}
else {
$in{'cmd'} =~ /\S/ && &has_command($in{'cmd'}) ||
&error($text{'session_ecmd'});
$gconfig{'passwd_cmd'} = $in{'cmd'};
}
if (defined($in{'extauth'})) {
if ($in{'extauth'}) {
$in{'extauth'} =~ /^(\S+)/ && -x $1 ||
&error($text{'session_eextauth'});
$miniserv{'extauth'} = $in{'extauth'};
}
else {
delete($miniserv{'extauth'});
}
}
if (defined($in{'passwd_mode'})) {
$miniserv{'passwd_mode'} = $in{'passwd_mode'};
}
$miniserv{'utmp'} = $in{'utmp'};
$miniserv{'session_ip'} = $in{'session_ip'};
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
if ($in{'passapi'}) {
&acl::setup_anonymous_access($password_change_path,
$password_change_mod);
}
else {
&acl::remove_anonymous_access($password_change_path,
$password_change_mod);
}
$gconfig{'passapi'} = $in{'passapi'};
&lock_file("$config_directory/config");
#$gconfig{'locking'} = $in{'locking'};
$gconfig{'noremember'} = !$in{'remember'};
$gconfig{'realname'} = $in{'realname'};
if ($in{'passwd_file'}) {
$gconfig{'passwd_file'} = $in{'passwd_file'};
$gconfig{'passwd_uindex'} = $in{'passwd_uindex'};
$gconfig{'passwd_pindex'} = $in{'passwd_pindex'};
}
else {
delete($gconfig{'passwd_file'});
delete($gconfig{'passwd_uindex'});
delete($gconfig{'passwd_pindex'});
}
if ($in{'banner_def'}) {
delete($gconfig{'loginbanner'});
}
else {
-r $in{'banner'} || &error($text{'session_ebanner'});
$gconfig{'loginbanner'} = $in{'banner'};
}
if ($in{'md5pass'} == 1) {
# MD5 enabled .. but is it supported by this system?
$need = &acl::check_md5();
$need && &error(&text('session_emd5mod', "<tt>$need</tt>"));
}
elsif ($in{'md5pass'} == 2) {
# SHA512 enabled .. check support
$need = &acl::check_sha512();
$need && &error(&text('session_edigestcrypt', 'SHA512'));
}
elsif ($in{'md5pass'} == 3) {
# yescrypt enabled .. check support
$need = &acl::check_yescrypt();
$need && &error(&text('session_edigestcrypt', 'yescrypt'));
}
$gconfig{'md5pass'} = $in{'md5pass'};
# Save forgotten password mode
if ($in{'forgot'} && &foreign_installed("virtualmin-password-recovery") &&
$text{'session_postfix'} =~ /virtualmin-password-recovery/) {
&error(&text('session_eforgot', 'edit_mods.cgi?tab=delete'));
}
$gconfig{'forgot_pass'} = $in{'forgot'};
# Save bad password requests
if ($in{'blockpass_on'}) {
$in{'passreset_time'} =~ /^\d+$/ && $in{'passreset_time'} > 0 ||
&error($text{'session_eblockhost_time'});
$in{'passreset_failures'} =~ /^\d+$/ && $in{'passreset_failures'} > 0 ||
&error($text{'session_epassreset_failures'});
$gconfig{'passreset_time'} = $in{'passreset_time'};
$gconfig{'passreset_failures'} = $in{'passreset_failures'};
}
else {
$gconfig{'passreset_time'} = $gconfig{'passreset_failures'} = undef;
}
# Password expiry
$in{'passreset_timeout'} =~ /^\d+$/ && $in{'passreset_timeout'} > 0 ||
&error($text{'session_epassreset_timeout'});
$gconfig{'passreset_timeout'} = $in{'passreset_timeout'};
# RPC timeout
my $rpc_timeout = $in{'rpc_timeout'};
$rpc_timeout =~ /^\d+$/ && $rpc_timeout > 0 ||
&error($text{'session_erpc_timeout'});
$gconfig{'rpc_timeout'} = $rpc_timeout;
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&show_restart_page();
&webmin_log("session", undef, undef, \%in);
+97
View File
@@ -0,0 +1,97 @@
#!/usr/local/bin/perl
# change_ssl.cgi
# Enable or disable SSL support
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'ssl_err'});
&lock_file($ENV{'MINISERV_CONFIG'});
&get_miniserv_config(\%miniserv);
$sslcurr = $miniserv{'ssl'};
$miniserv{'ssl'} = $in{'ssl'};
$miniserv{'ssl_enforce'} = int($in{'ssl_enforce'});
$miniserv{'ssl_hsts'} = $miniserv{'ssl_enforce'} == 2 ? 1 : 0;
&validate_key_cert($in{'key'}, $in{'cert_def'} ? undef : $in{'cert'});
$miniserv{'keyfile'} = $in{'key'};
$miniserv{'certfile'} = $in{'cert_def'} ? undef : $in{'cert'};
$miniserv{'no_sslcompression'} = !$in{'ssl_compression'};
$miniserv{'ssl_honorcipherorder'} = $in{'ssl_honorcipherorder'};
if ($in{'version_def'}) {
delete($miniserv{'ssl_version'});
}
else {
$in{'version'} =~ /^\d+$/ || &error($text{'ssl_eversion'});
$miniserv{'ssl_version'} = $in{'version'};
}
$miniserv{'no_ssl2'} = $in{'no_ssl2'};
$miniserv{'no_ssl3'} = $in{'no_ssl3'};
$miniserv{'no_tls1'} = $in{'no_tls1'};
$miniserv{'no_tls1_1'} = $in{'no_tls1_1'};
$miniserv{'no_tls1_2'} = $in{'no_tls1_2'};
if ($in{'cipher_list_def'} == 1) {
delete($miniserv{'ssl_cipher_list'});
}
elsif ($in{'cipher_list_def'} == 2) {
$miniserv{'ssl_cipher_list'} = $strong_ssl_ciphers;
}
elsif ($in{'cipher_list_def'} == 3) {
# Check for PFS support
eval "use Net::SSLeay";
$Net::SSLeay::VERSION >= 1.57 ||
&error(&text('ssl_epfsversion', $Net::SSLeay::VERSION, 1.57));
$miniserv{'ssl_cipher_list'} = $pfs_ssl_ciphers;
$miniserv{'dhparams_file'} ||= "$config_directory/dhparams.pem";
if (!-r $miniserv{'dhparams_file'}) {
# Generate file needed for PFS
my $out = &backquote_command(
"openssl dhparam -out ".
quotemeta($miniserv{'dhparams_file'})." 4096 2>&1");
if ($?) {
&error(&text('ssl_edhparams',
"<pre>".&html_escape($out)."</pre>"));
}
&set_ownership_permissions(
undef, undef, 700, $miniserv{'dhparams_file'});
}
}
else {
$in{'cipher_list'} =~ /^\S+$/ || &error($text{'ssl_ecipher_list'});
$miniserv{'ssl_cipher_list'} = $in{'cipher_list'};
}
$miniserv{'cipher_list_def'} = $in{'cipher_list_def'};
foreach $ec (split(/[\r\n]+/, $in{'extracas'})) {
-r $ec && !-d $ec || &error(&text('ssl_eextraca', $ec));
push(@extracas, $ec);
}
$miniserv{'extracas'} = join("\t", @extracas);
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
$SIG{'TERM'} = 'IGNORE'; # stop process from being killed by restart
&restart_miniserv();
&webmin_log("ssl", undef, undef, \%in);
if (!$miniserv{'ssl_hsts'}) {
# Tell browser to unset HSTS policy to make non-SSL URL work
print "Strict-Transport-Security: max-age=0;\n";
}
$url = ($in{'ssl'} ? "https://" : "http://") .
"$ENV{'SERVER_NAME'}:$miniserv{'port'}";
if ($sslcurr != $miniserv{'ssl'}) {
%tinfo = &get_theme_info($current_theme);
if ($tinfo{'spa'} && $tinfo{'nomodcall'}) {
$url .= "@{[&get_webprefix()]}/webmin/?$tinfo{'nomodcall'}";
}
&ui_print_header(undef, $text{'ssl_title'}, "", undef, undef, 1);
print $text{'ssl_redirect'},"<br>\n";
print "<script>\n";
print "top.location = '$url';\n";
print "</script>\n";
&ui_print_footer();
}
else {
&redirect("");
}
+25
View File
@@ -0,0 +1,25 @@
#!/usr/local/bin/perl
# change_startpage.cgi
# Change startpage settings
require './webmin-lib.pl';
&ReadParse();
&lock_file("$config_directory/config");
if ($in{'nocols_def'}) {
delete($gconfig{'nocols'});
}
else {
$in{'nocols'} =~ /^\d+$/ ||
&error(&text('startpage_ecols', $in{'nocols'}));
$gconfig{'nocols'} = $in{'nocols'};
}
$gconfig{'notabs'} = $in{'notabs'};
$gconfig{'gotoone'} = $in{'gotoone'};
$gconfig{'deftab'} = $in{'deftab'};
$gconfig{'nohostname'} = $in{'nohostname'};
$gconfig{'gotomodule'} = $in{'gotomodule'};
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&webmin_log("startpage", undef, undef, \%in);
&redirect("");
+38
View File
@@ -0,0 +1,38 @@
#!/usr/local/bin/perl
# Save status collection options
require './webmin-lib.pl';
&ReadParse();
&foreign_require("system-status");
&error_setup($text{'status_err'});
# Save collection interval
if ($in{'interval_def'}) {
$system_status::config{'collect_interval'} = 'none';
}
else {
$in{'interval'} =~ /^\d+$/ && $in{'interval'} > 0 &&
$in{'interval'} <= 60 || &error($text{'status_einterval'});
$system_status::config{'collect_interval'} = $in{'interval'};
}
# Save collection options
$system_status::config{'collect_pkgs'} = $in{'pkgs'};
$system_status::config{'collect_notemp2'} = !$in{'temp2'};
$system_status::config{'collect_notemp'} = !$in{'temp'};
$system_status::config{'collect_units'} = $in{'units'};
&lock_file($system_status::module_config_file);
&save_module_config(\%system_status::config, 'system-status');
&unlock_file($system_status::module_config_file);
&system_status::setup_collectinfo_job();
if ($in{'interval_def'}) {
&unlink_file($system_status::collected_info_file);
}
else {
&system_status::scheduled_collect_system_info();
}
&webmin_log("status");
&redirect("");
+54
View File
@@ -0,0 +1,54 @@
#!/usr/local/bin/perl
# change_theme.cgi
# Change the current webmin theme
require './webmin-lib.pl';
&ReadParse();
&ui_print_header(undef, $text{'themes_title'}, "");
($gtheme, @others) = split(/\s+/, $gconfig{'theme'});
# Call pre-change function
if ($in{'theme'} ne $gtheme) {
if (defined(&theme_pre_change_theme)) {
&theme_pre_change_theme();
}
}
&lock_file("$config_directory/config");
if ($in{'theme'}) {
$gconfig{'theme'} = join(" ", $in{'theme'}, @others);
}
else {
delete($gconfig{'theme'});
}
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&lock_file($ENV{'MINISERV_CONFIG'});
&get_miniserv_config(\%miniserv);
if ($in{'theme'}) {
$miniserv{'preroot'} = join(" ", $in{'theme'}, @others);
}
else {
delete($miniserv{'preroot'});
}
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
&reload_miniserv();
print "$text{'themes_ok'}<p>\n";
# Call post-change function
if ($in{'theme'} ne $gtheme) {
if (defined(&theme_post_change_theme)) {
&theme_post_change_theme();
}
}
print &js_redirect("/", "top", 1500);
&webmin_log('theme', undef, undef, \%in);
&ui_print_footer("", $text{'index_return'});
+50
View File
@@ -0,0 +1,50 @@
#!/usr/local/bin/perl
# Enable two-factor authentication
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'twofactor_err'});
&get_miniserv_config(\%miniserv);
# Validate inputs
if ($in{'twofactor_provider'}) {
($prov) = grep { $_->[0] eq $in{'twofactor_provider'} }
&list_twofactor_providers();
$prov || &error($text{'twofactor_eprovider'});
$vfunc = "validate_twofactor_apikey_".$in{'twofactor_provider'};
$err = defined(&$vfunc) && &$vfunc(\%in, \%miniserv);
&error($err) if ($err);
}
else {
# Don't disable if any users have twofactor enabled
&foreign_require("acl");
@twos = grep { $_->{'twofactor_provider'} && $_->{'twofactor_id'} }
&acl::list_users();
if (@twos) {
&error(&text('twofactor_eusers',
join(" ", map { $_->{'name'} } @twos)));
}
}
# Save settings
&lock_file($ENV{'MINISERV_CONFIG'});
$miniserv{'twofactor_provider'} = $in{'twofactor_provider'};
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
$msg = "";
$msg .= $text{'restart_done'}."<p>\n" if ($gconfig{'restart_async'});
if ($in{'twofactor_provider'}) {
$msg .= &text('twofactor_enrolllink',
"../acl/twofactor_form.cgi")."<p>\n";
$mfunc = "message_twofactor_apikey_".$in{'twofactor_provider'};
if (defined(&$mfunc)) {
$msg .= &$mfunc(\%miniserv)."<p>\n";
}
elsif ($prov->[2]) {
$msg .= &text('twofactor_url', $prov->[1], $prov->[2])."<p>\n";
}
}
&show_restart_page($text{'twofactor_title'}, $msg);
&webmin_log("twofactor", undef, undef, \%in);
+53
View File
@@ -0,0 +1,53 @@
#!/usr/local/bin/perl
# change_ui.cgi
# Change colour scheme
require './webmin-lib.pl';
&error_setup($text{'ui_err'});
&ReadParse();
&lock_file("$config_directory/config");
for($i=0; $i<@cs_names; $i++) {
$cd = $cs_codes[$i];
if ($in{"${cd}_def"}) { delete($gconfig{$cd}); }
elsif ($in{$cd} !~ /^[0-9a-fA-F]{6}$/) {
&error(&text('ui_ergb', $cs_names[$i]));
}
else { $gconfig{$cd} = $in{$cd}; }
}
$gconfig{'sysinfo'} = $in{'sysinfo'};
$gconfig{'showlogin'} = $in{'showlogin'};
$gconfig{'showhost'} = $in{'showhost'};
$gconfig{'hostnamemode'} = $in{'hostnamemode'};
$in{'hostnamemode'} != 3 || $in{'hostnamedisplay'} =~ /^[a-z0-9\.\_\-]+$/i ||
&error($text{'ui_ehostnamedisplay'});
$gconfig{'hostnamedisplay'} = $in{'hostnamedisplay'};
$gconfig{'feedback_to'} = $in{'feedback_def'} ? undef : $in{'feedback'};
$gconfig{'nofeedbackcc'} = $in{'nofeedbackcc'};
$in{'width_def'} || $in{'width'} =~ /^\d+$/ || &error($text{'ui_ewidth'});
$gconfig{'help_width'} = $in{'width'};
$in{'height_def'} || $in{'height'} =~ /^\d+$/ || &error($text{'ui_eheight'});
$gconfig{'help_height'} = $in{'height'};
# Save dialog box sizes
foreach $db ("file", "user", "users", "date", "module", "modules") {
if ($in{"size".$db."_def"}) {
delete($gconfig{"db_size".$db});
}
else {
$in{"size".$db."_w"} =~ /^\d+$/ ||
&error($text{'ui_edbwidth'});
$in{"size".$db."_h"} =~ /^\d+$/ ||
&error($text{'ui_edbheight'});
$gconfig{"db_size".$db} = $in{"size".$db."_w"}."x".
$in{"size".$db."_h"};
}
}
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
&webmin_log('ui', undef, undef, \%in);
&redirect("");
+90
View File
@@ -0,0 +1,90 @@
#!/usr/local/bin/perl
# Save webserver options
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'web_err'});
&get_miniserv_config(\%miniserv);
# Save expires
if ($in{'expires_def'}) {
delete($miniserv{'expires'});
}
else {
$in{'expires'} =~ /^\d+$/ ||
&error($text{'web_eexpires'});
$miniserv{'expires'} = $in{'expires'};
}
# Save per-path expires
for(my $i=0; defined($p = $in{"expirespath_$i"}); $i++) {
$t = $in{"expirestime_$i"};
next if ($p !~ /\S/);
$t =~ /^\d+$/ || &error(&text('web_eexpires2', $i+1));
push(@expires_paths, [ $p, $t ]);
}
$miniserv{'expires_paths'} = join("\t", map { $_->[0]."=".$_->[1] }
@expires_paths);
# Save redirects
delete($miniserv{'redirect_host'});
delete($miniserv{'redirect_port'});
delete($miniserv{'redirect_prefix'});
delete($miniserv{'redirect_ssl'});
my $redir_host = $in{'redirect_host'};
$redir_host =~ /^[A-z0-9\-\.\:]+$/ ||
$redir_host =~ /^\s*$/ ||
&error(&text('web_eredirhost', &html_escape($redir_host)));
$miniserv{'redirect_host'} = $redir_host
if ($redir_host);
my $redir_port = &trim($in{'redirect_port'});
($redir_port =~ /^\d+$/ && $redir_port < 65536) ||
$redir_port =~ /^\s*$/ ||
&error(&text('bind_eport2', &html_escape($redir_port)));
$miniserv{'redirect_port'} = $redir_port
if ($redir_port);
my $redir_pref = &trim($in{'redirect_prefix'});
$redir_pref =~ /^\// || $redir_pref =~ /^\s*$/ ||
&error($text{'web_eredirpref'});
$redir_pref !~ /\s/ || &error($text{'web_eredirpref2'});
$miniserv{'redirect_prefix'} = $redir_pref
if ($redir_pref);
my $redir_ssl = $in{'redirect_ssl'};
$miniserv{'redirect_ssl'} = 1 if ($redir_ssl == 1);
# Save stack trace option
$gconfig{'error_stack'} = $in{'stack'};
# Save showing of stderr
$miniserv{'noshowstderr'} = !$in{'showstderr'};
if (!$miniserv{'session'}) {
# Save password pass option
$miniserv{'pass_password'} = $in{'pass'};
}
# Save gzip option
if ($in{'gzip'} == 1) {
eval "use Compress::Zlib";
$@ && &error(&text('advanced_egzip', '<tt>Compress::Zlib</tt>'));
}
$miniserv{'gzip'} = $in{'gzip'};
# Save redirect type
$gconfig{'relative_redir'} = $in{'redir'};
# Save directory list option
$miniserv{'nolistdir'} = !$in{'listdir'};
# Save global config
&lock_file("$config_directory/config");
&write_file("$config_directory/config", \%gconfig);
&unlock_file("$config_directory/config");
# Save miniserv config
&lock_file($ENV{'MINISERV_CONFIG'});
&put_miniserv_config(\%miniserv);
&unlock_file($ENV{'MINISERV_CONFIG'});
&show_restart_page();
&webmin_log("web");
+11
View File
@@ -0,0 +1,11 @@
#!/usr/local/bin/perl
# Re-start Webmin to clear blocks
require './webmin-lib.pl';
&show_restart_page($text{'blocked_title'},
$gconfig{'restart_async'}
? $text{'blocked_restarting'}
: undef);
+9
View File
@@ -0,0 +1,9 @@
#!/usr/local/bin/perl
# Delete all URLs from the cache
require './webmin-lib.pl';
&system_logged("rm -f ".quotemeta($main::http_cache_directory)."/*");
&webmin_log("clearcache");
&redirect("edit_proxy.cgi");
+75
View File
@@ -0,0 +1,75 @@
#!/usr/local/bin/perl
# clone_mod.cgi
# Clones an existing module under a new name
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'clone_err'});
# Filter out potentially dangerous strings
$in{'desc'} = &filter_javascript($in{'desc'});
# Symlink the code directory
$src = $in{'mod'};
%minfo = &get_module_info($src);
$count = 2;
do {
$dst = $src.$count;
$count++;
} while(-d "../$dst");
symlink($src, "../$dst") || &error(&text('clone_elink', $!));
# Symlink in the theme directory
if ($gconfig{'theme'}) {
unlink("../$gconfig{'theme'}/$dst");
symlink($src, "../$gconfig{'theme'}/$dst");
}
mkdir("$config_directory/$dst", 0700);
if ($in{'reset'}) {
# Setup config directory from scratch
$perl = &get_perl_path();
system("cd $root_directory ; $perl $root_directory/copyconfig.pl '$gconfig{'os_type'}' '$gconfig{'os_version'}' '$root_directory' '$config_directory' '$dst'");
}
else {
# Copy the config directory
$out = `( (cd $config_directory/$src ; tar cf - .) | (cd $config_directory/$dst ; tar xpf -) ) 2>&1`;
if ($?) {
&error(&text('clone_ecopy', $out));
}
$in{'desc'} = &text('clone_desc', $minfo{'desc'}) if (!$in{'desc'});
}
&open_tempfile(CLONE, ">$config_directory/$dst/clone");
&print_tempfile(CLONE, "desc=$in{'desc'}\n");
&close_tempfile(CLONE);
# Delete .lock files from the config directory
system("(find '$config_directory/$dst' -name '*.lock' | xargs rm -f) >/dev/null 2>&1");
# Grant access to the clone to this user
&read_acl(undef, \%acl);
&open_lock_tempfile(ACL, "> ".&acl_filename());
foreach $u (keys %acl) {
my @mods = @{$acl{$u}};
if ($u eq $base_remote_user) {
@mods = &unique(@mods, $dst);
}
&print_tempfile(ACL, "$u: ",join(' ', @mods),"\n");
}
&close_tempfile(ACL);
if ($in{'cat'} ne '*') {
# Assign to category
&lock_file("$config_directory/webmin.cats");
&read_file("$config_directory/webmin.cats", \%cats);
$cats{$dst} = $in{'cat'};
&write_file("$config_directory/webmin.cats", \%cats);
&unlock_file("$config_directory/webmin.cats");
}
&webmin_log("clone", undef, $in{'mod'}, { 'desc' => $minfo{'desc'},
'dst' => $dst,
'dstdesc' => $in{'desc'} });
&flush_webmin_caches();
&redirect("index.cgi?refresh=1");
+11
View File
@@ -0,0 +1,11 @@
update=0
upmissing=0
upshow=1
updays=1
cron_mode=0
osdn=1
warn_days=7
letsencrypt_dns_wait=10
letsencrypt_algo=rsa
letsencrypt_reuse=1
letsencrypt_nouse=0
+15
View File
@@ -0,0 +1,15 @@
line1=Configurable options,11
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=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 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
+5
View File
@@ -0,0 +1,5 @@
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=عرض أوقات التحديث كـ,1,0-واجهة بسيطة,1-اختيار وقت Cron
warn_days=أيام قبل انتهاء صلاحية كلمة المرور لتحذير المستخدمين,0,5
letsencrypt_cmd=المسار الكامل لأمر تشفير العميل,0
+5
View File
@@ -0,0 +1,5 @@
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 ACME,3,Troba'l automàticament
+3
View File
@@ -0,0 +1,3 @@
standard_url=URL seznamu standardních modulů,3,Na webmin.com
third_url=URL seznamu modulů třetích stran,3,Na webmin.com
cron_mode=Zobrazit aktualizační časy jako,1,0-Jednoduché rozhraní,1-Výběr šasu jako u Cronu
+5
View File
@@ -0,0 +1,5 @@
standard_url=URL der Standardmodul&#45;Liste,3,Von webmin.com
third_url=URL der Drittanbieter&#45;Webmin&#45;Modulliste,3,Von webmin.com
cron_mode=Zeige Aktualisierungszeiten als,1,0-Einfache Anzeige,1-Cron&#45;Zeit&#45;Auswahl
warn_days=Tage vor Ablauf des Passworts zu warnen an Benutzer,0,5
letsencrypt_cmd=Voller Pfad zum ACME-Client&#45;Befehl,0
+3
View File
@@ -0,0 +1,3 @@
standard_url=URL de lista de módulos estándar,3,En webmin.com
third_url=URL de lista de módulos de terceros,3,En webmin.com
cron_mode=Mostrar horas de actualización como,1,0-Interfaz simple,1-Selector horario de Cron
+3
View File
@@ -0,0 +1,3 @@
standard_url=URL ليست پيمانه‌هاي استاندارد,3,در webmin.com
third_url=URL ليست پيمانه‌هاي بخش سوم,3,در webmin.com
cron_mode=نمايش زمانهاي به‌روزرساني در,1,0-واسط ساده,1-انتخاب کننده زمان cron
+8
View File
@@ -0,0 +1,8 @@
line1=Options configurables,11
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=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
View File
View File
+3
View File
@@ -0,0 +1,3 @@
standard_url=URL per la lista dei moduli standard,3,Su webmin.com
third_url=URL per la lista dei moduli di terze parti,3,Su webmin.com
cron_mode=Mostra i tempi di aggiornamento come,1,0-Interfaccia semplice,1-Selettore del tempo di Cron
+8
View File
@@ -0,0 +1,8 @@
line1=基本設定,11
standard_url=標準モジュールリストに使用する URL,3,webmin.com
third_url=サードパーティ製モジュールリストに使用する URL,3,webmin.com
cron_mode=アップデート時刻の表示方法,1,0-シンプル,1-Cron 選択方式
warn_days=ユーザのパスワード期限切れの通知(日前),0,5
line2=ACME プロバイダーの設定,11
letsencrypt_cmd=ACME クライアントのパス,3,自動設定
letsencrypt_dns_wait=ACME DNS の更新待機時間(秒),0,5
+3
View File
@@ -0,0 +1,3 @@
standard_url=표준 모듈 리스트 URL,3,webmin.com
third_url=third party 모듈 리스트 URL,3,webmin.com
cron_mode=업데이트 시간 보기,1,0-간단한 인터페이스,1-Cron 시간 선택
+4
View File
@@ -0,0 +1,4 @@
standard_url=URL senarai modul piawai,3,di webmin.com
third_url=URL senarai modul pihak ketiga,3,di webmin.com
cron_mode=Paparkan masa kemaskini sebagai,1,0-Antaramuka Mudah,1-masa terpilih Cron
warn_days=Hari sebelum tamat kata laluan untuk memberi amaran kepada pengguna, 0,5
+4
View File
@@ -0,0 +1,4 @@
standard_url=URL voor lijst van standaard modules,3,Op webmin.com
third_url=URL voor lijst van 3e partij modules,3,Op webmin.com
cron_mode=Update tijden weergeven als,1,0-Simpele interface,1-Cron tijd selectie
warn_days=Dagen voordat het wachtwoord verloopt om gebruikers te waarschuwen,0,5
+4
View File
@@ -0,0 +1,4 @@
standard_url=URL til standard modulliste,3,På webmin.com
third_url=URL til liste over tredjeparts moduler,3,På webmin.com
cron_mode=Vis oppdateringstidspunkt som,1,0-Enkelt grensesnitt,1-Cron tidsvelger
warn_days=Dager før passord utløper at brukere skal gis melding,0,5
+4
View File
@@ -0,0 +1,4 @@
standard_url=URL listy modułów standardowych,3,webmin.com
third_url=URL listy modułów osób trzecich,3,webmin.com
cron_mode=Pokazuj czasy aktualizacji jako,1,0-Prosty,1-Ustawienia czasu Crona
warn_days=Na ile dni przed wygaśnięciem hasła ostrzegać użytkowników?,0,5
+4
View File
@@ -0,0 +1,4 @@
standard_url=URL da lista de módulos padrões,3,No webmin.com
third_url=URL da lista de módulos de terceiros,3,No webmin.com
cron_mode=Exibir horas das atualizações como,1,0-Interface Simples,1-Seletor de hora do Cron
warn_days=Dias antes de avisar usuários da expiração da senha,0,5
+4
View File
@@ -0,0 +1,4 @@
standard_url=URL списка стандартных модулей,3,На webmin.com
third_url=URL списка сторонних модулей,3,На webmin.com
cron_mode=Задавать время в "Обновлении по расписанию" как,1,0-Простой интерфейс,1-Cron time selector
warn_days=За сколько дней предупреждать пользователей об истечении срока действия пароля,0,5
+2
View File
@@ -0,0 +1,2 @@
standard_url=URL adresa štandardných modulov,3,na webmin.com
third_url=URL adresa modulov tretích strán,3,na webmin.com
+3
View File
@@ -0,0 +1,3 @@
standard_url=URL för standardmodul-listan,3, webmin.com
third_url=URL för tredje parts moduler-lista,3, webmin.com
warn_days=Dagar före lösenord gått ut för att varna användare,0,5
+2
View File
@@ -0,0 +1,2 @@
standard_url=Standart modüllerin listesinin URL'si,3,webmin.com adresinde
third_url=Üçüncü parti modül listesi URL'si,3,webmin.com adresinde
+16
View File
@@ -0,0 +1,16 @@
require 'webmin-lib.pl';
sub cpan_recommended
{
local @rv = ( "Sys::Syslog" );
if (&has_command("openssl")) {
push(@rv, "Net::SSLeay");
}
eval "crypt('foo', 'xx')";
if ($@) {
push(@rv, "Crypt::UnixCrypt");
}
return @rv;
}
+2
View File
@@ -0,0 +1,2 @@
allow=
disallow=
+18
View File
@@ -0,0 +1,18 @@
#!/usr/local/bin/perl
# Delete selected URLs from the cache
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'cache_err'});
@d = split(/\0/, $in{'d'});
@d || &error($text{'cache_enone'});
# Remove the files
foreach $d (@d) {
$d !~ /\.\./ && $d !~ /\0/ || &error($text{'cache_efile'});
&system_logged("rm -f ".quotemeta("$main::http_cache_directory/$d"));
}
&webmin_log("deletecache", undef, scalar(@d));
&redirect("cache.cgi?search=".&urlize($in{'search'}));
+83
View File
@@ -0,0 +1,83 @@
#!/usr/local/bin/perl
# delete_mod.cgi
# Delete selected modules from webmin, after asking first
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'delete_err'});
@mods = split(/\0/, $in{'mod'});
@mods || &error($text{'delete_enone'});
# check if any other module depends on those to be deleted
foreach $minfo (&get_all_module_infos()) {
if (&check_os_support($minfo) && &indexof($minfo->{'dir'}, @mods) < 0) {
foreach $d (split(/\s+/, $minfo->{'depends'})) {
if (&indexof($minfo->{'dir'}, @mods) < 0) {
$depends{$d} = $minfo->{'desc'};
}
}
}
}
foreach $m (@mods) {
%minfo = &get_module_info($m);
%minfo = &get_theme_info($m) if (!%minfo);
if (!$in{'nodeps'} && !-l &module_root_directory($m) && $depends{$m}) {
&error(&text('delete_edep', "<tt>$minfo{'desc'}</tt>",
"<tt>$depends{$m}</tt>"));
}
}
# ask the user if he is sure
if (!$in{'confirm'}) {
&ui_print_header(undef, $text{'delete_title'}, "");
print &ui_form_start("delete_mod.cgi", "post");
foreach $m (@mods) {
my %minfo = &get_module_info($m);
if (%minfo) {
$module++;
}
else {
$theme++;
%minfo = &get_theme_info($m);
}
print &ui_hidden("mod", $m);
$total += &disk_usage_kb(&module_root_directory($m))
if (!-l &module_root_directory($m));
$descs .= " , " if ($descs);
$descs .= "<b>$minfo{'desc'}</b>";
}
print "<center>",&text($theme ? 'delete_rusure2' :
$total ? 'delete_rusure' : 'delete_rusure3',
int($total), $descs),"<p>",
&ui_submit($text{'delete'}, "confirm"),"<br>\n";
if ($module) {
print &ui_checkbox("acls", 1, $text{'delete_acls'}, 0);
}
print &ui_hidden("nodeps", $in{'nodeps'}),"\n";
print "</center>\n";
print &ui_form_end();
&ui_print_footer("", $text{'index_return'});
exit;
}
# delete the selected modules or themes
foreach $m (split(/\0/, $in{'mod'})) {
next if (!$m || !-d &module_root_directory($m));
push(@mdesc, &delete_webmin_module($m, $in{'acls'}));
}
&flush_webmin_caches();
&ui_print_header(undef, $text{'delete_title'}, "");
print $text{'delete_msg'},"<p>\n";
print "<ul>\n";
for($i=0; $i<@mdesc; $i++) {
print $mdesc[$i],"<p>\n";
}
print "</ul><p>\n";
if (defined(&theme_post_change_modules)) {
&theme_post_change_modules();
}
&ui_print_footer("", $text{'index_return'});
+61
View File
@@ -0,0 +1,61 @@
#!/usr/local/bin/perl
# Delete or run some Webmin cron jobs
require './webmin-lib.pl';
&foreign_require("webmincron");
&ReadParse();
# Get jobs
@d = split(/\0/, $in{'d'});
@wcrons = grep { &indexof($_->{'id'}, @d) >= 0 }
&webmincron::list_webmin_crons();
if ($in{'delete'}) {
# Deleting some jobs
&error_setup($text{'webmincron_derr'});
@wcrons || &error($text{'webmincron_enone'});
foreach my $w (@wcrons) {
&webmincron::delete_webmin_cron($w);
}
&webmin_log("delete", "webmincron", scalar(@wcrons));
&redirect("edit_webmincron.cgi");
}
elsif ($in{'run'}) {
# Running some jobs
&error_setup($text{'webmincron_rerr'});
@wcrons || &error($text{'webmincron_enone'});
&ui_print_unbuffered_header(undef, $text{'webmincron_title'}, "");
foreach my $w (@wcrons) {
%minfo = &get_module_info($w->{'module'});
print &text('webmincron_running',
$minfo{'desc'} || $w->{'module'},
"<tt>$w->{'func'}</tt>"),"<br>\n";
print "<pre>\n";
eval {
local $main::error_must_die = 1;
&foreign_require($w->{'module'}, $w->{'file'});
if ($w->{'args'}) {
&foreign_call($w->{'module'}, $w->{'func'},
@{$w->{'args'}});
}
else {
&foreign_call($w->{'module'}, $w->{'func'});
}
};
print "</pre>\n";
if ($@) {
print &text('webmincron_failed',
&html_escape($@)),"<p>\n";
}
else {
print $text{'webmincron_done'},"<p>\n";
}
}
&webmin_log("run", "webmincron", scalar(@wcrons));
&ui_print_footer("", $text{'index_return'});
}
else {
&error($text{'webmincron_ebutton'});
}
+52
View File
@@ -0,0 +1,52 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGSuZVABEAC5H1bzk4TYlpu8gcEwWGD7eVxtBagEYRCrG9WLkJ1TohfGumUd
za5H0KU/sfI1VkLFkMJ/UE8PblCE4l9qePDfo0Cf35PU9Y5D5/KvbatR2lVM9C2k
qtBVFEFuwtBAuyJaS2ofstKk4AJMZHHn+Q1fSHdc9UgdzRs0cQqbHpKaVYp8tkL5
Qhf6n8be5HhbzJQ0RV9tzRxV/hjSaUPtWU6UmhpKgD5SmHj+R6Ft/waGiQAOlw+5
kevpzP5poEBH0cjt2Hi4i96Eir6b5fBBq/Jgh/Fztsk53DXVjiluNfQwnlhG4TfB
muf5KIr0aKo8R+r1OO+5sML0koBLWNCZu5p5/wik/ug4MCXm/B0jfy3JNmn5bwKK
MDnUVyQ9HumXMyTLx/zWf6TzQyU9jqQxNS+qM2UipVyQdfzslRn40jwTcgO+oL8F
MdEkFGVxPmfXDmmykeX/KgcmqIs7qHQ1+RNPJrcPiOgDc0Em1JPbSZoBxPQw8JTm
flQ6M/AVWRawaHvInSld7N/rD9QAO5JvZ3q/3wYW0X1j4mgoSWQSe7oTblOuNcc+
yJp5Jj6dyR17mVj+W8TLCN+x1b0F3eWB61a8mSBSQFcE2jt2RwOnSSolFnzhLhR9
Twd/jD3CgpZuC3/CPODDrr5iI6KlVlvCQFRx4EGrpqa/C6IeFtt5w1ypEQARAQAB
tClXZWJtaW4gRGV2ZWxvcGVycyA8ZGV2ZWxvcGVyc0B3ZWJtaW4uY29tPokCTgQT
AQgAOBYhBH0a6RXz3PraNEpPyy0iO5GJFvKiBQJkrmVQAhsDBQsJCAcCBhUKCQgL
AgQWAgMBAh4BAheAAAoJEC0iO5GJFvKiPc8P/0lrZ2540PcvLSuou4B05cSLrRMK
c+6JrM6xPR0p3ellVI3JCh5A+u9iXeUKIfLpooaT/adPsHoTrcBGzccmKg11UC9H
a43q2LT4nKIiv7Gof+PkYZLfKpdYWI3EEcJ0zap3AkNrX7LuKudun5AJjQq3Fpbc
pNsy1UwEqfg5iaw0D+TBlzkkn3UrZytLyl6p0euolr87twuXhTVcYDcB9Gt54zmH
+nuyQbIQb8BjZg1nBl613/iweadU0BqpH/uZ4GJTBezz3qrbnO4QRT9nfJVd9FCR
Y28XNuga9Mt2ZtRr5LTW8JiFQVdfMc6viAPD1xmLRcCgvg4pajiuR+Nxu7tDlwqX
k/DujnNOXYm/nC/9f4Uoq4dxKlYSudLMu074m+8brRWKM8KoYnlLTHLgnJUDXwSM
k7PW8N7oKcjvDJGj23AKC2kMrtuPPrIOhhi3Hoc9os8btukM68tFKT58+Z3Pmmgo
752Ivgs86ggrxft3JlUy0ZihxH96C/MWhT4SJgqi0I4CUCwjPVDQ2Qz5T+1i1Tyf
AJlKXQLXVW4thIEj3ffNHcGx1xi5WKy9Ft8+znKHHrJhfMpN0MOlM4LaG1TiUb0H
YjVMt/yNjobiAcUcWMcKDPvuJdTCiGJ9CiFTf/G0NlXVog8+9hCmz/hh9Io4NWLv
GoBjT9q765jol9n1uQINBGSuZVABEADLbVETrd5xdIRz1pukKGZQsbKczPp6QTAL
p1OJ+9P7ZYuadQoBSOUyO+3cofNTXB8DFIMb9Q6WiY16/EQf34TUZporPKzpk7y2
JlkJeEfAj9UZVUWAfF/yekypB9u5cN+eP6204U90uI7IBZTKN7qKjTs533x/f670
IkwPpJUkmaAzkhzyxUCtAk5B0fV5k8VIO/QiR75Ag7K1OfjuwCMQRhH9SYozYGAX
sKSR0MasoIu+of19Addkfo3Xhyooh8f2NyUoxdbQgmERV/4m0NIyIDHFPUexO/Ux
rwrQDlQ7wxxUNbdYyvmIZVtngjBDbIuwbA7ODQClFr9x7mWdQ9ytCLSvPNTE3n03
1GTjS5DVxc6W4DQpLxzBnq7iIBlxjPY6q2JnQANT3I3ettGvo1aZGvIlX2XWhSO/
wSSCeyyBsyXc/w79o19vPITLnhIiaVCDk9Ar3GM9bzbro/IyXhn2qjNi6l7YMCsR
K5qyg8UUc2vMfDjedHidrx2nkte2+VQ/q81KaGu5GDaDfJOHMZK9mTSW7TDvgziX
vbCsp6/Ae1PDzuTBJbStGbPyereQky73lco9zv192sMFKakFPzZsFVm6tv1024wI
MacOsSxOiFgRmMnSJTgv49HwcqaPCR3Ow3gAiG/hTTq6+9HrE/H2mVpWryNITky3
3f8F/EB2TwARAQABiQI2BBgBCAAgFiEEfRrpFfPc+to0Sk/LLSI7kYkW8qIFAmSu
ZVACGwwACgkQLSI7kYkW8qIHbg//Ua30xqv1N88S1NtjAQFegOSGpSoWcBPCibgy
VEabG6ajlPo7PNdqFqk7QVg4epFD+jSOUaafb8OuiA77DcuW1dKJcxQtOrIhBppc
RyBp9IhUKlbywCNgL28sHl1Ve5PTgCsqurAl2ObtQID9eSaDvrxGacYekQ6j+KIy
m+4QSlt4PTgUIthMaTl2A8apk/Sh2+GEi/ZEMTKSHwM+H3P96XTjJ/2nL3kxB2wb
rU5JLncVKyBfJ4cNE1QBWLwEaj3BnmDORsgAJy0JpR+B9+hiWahMfOTGO/z0JW9U
dXooLE9DJZw5h308S5dAvQZe0cwwnvldh4rRoEQv0Zw3NFORwq1YggP/pN5FRmVC
Pu0sezIA4lt3/kI3qihGO3UogqsPqjO7JD5pua/Tarlf6UBZZCyh3uJA4aPvDYOb
9MTmPinqfQUzk6W892OBkk2HqRZwCxYuRLmOfTy2KFmN09z0M3EpZijz6iCp3ARV
5lKYcGuNS5I0LNgWesoFrbJdW3V+C7YyNevtolJFISTfEGXE4PO5MpiUGBbya7tW
gtVP/edU/JbeCEnjsCsdeWAgLaByp5yTS0u3i9Jn3rPU+cekNTfEprM61SutrIfV
NwLr+Y0i9j34kj2CjamfZrYtCjOVytsfVGGogSd5GBumqfYt2bmJywuom1Wkpvkv
eMAhu3k=
=ha4Q
-----END PGP PUBLIC KEY BLOCK-----
+25
View File
@@ -0,0 +1,25 @@
#!/usr/local/bin/perl
# Output the certificate in PEM or PKCS12 format
require './webmin-lib.pl';
&ReadParse();
&get_miniserv_config(\%miniserv);
if ($ENV{'PATH_INFO'} =~ /\.p12$/) {
# PKCS12 format
$data = &cert_pkcs12_data($miniserv{'keyfile'}, $miniserv{'certfile'});
$type = "application/x-pkcs12";
}
else {
# PEM format
$data = &cert_pem_data($miniserv{'certfile'} || $miniserv{'keyfile'});
$type = "text/plain";
}
if ($data) {
print "Content-type: $type\n\n";
print $data;
}
else {
&error($text{'ssl_edownload'});
}
+55
View File
@@ -0,0 +1,55 @@
#!/usr/local/bin/perl
# edit_access.cgi
# Display IP access control form
require './webmin-lib.pl';
&ui_print_header(undef, $text{'access_title'}, "");
&get_miniserv_config(\%miniserv);
print $text{'access_desc'},"<p>\n";
print &ui_form_start("change_access.cgi", "post");
print &ui_table_start($text{'access_header'}, undef, 2, [ "width=30%" ]);
$access = $miniserv{"allow"} ? 1 : $miniserv{"deny"} ? 2 : 0;
@list = $access == 1 ? split(/\s+/, $miniserv{"allow"}) :
$access == 2 ? split(/\s+/, $miniserv{"deny"}) : ( );
if (!@list && $miniserv{"known_ips"}) {
@list = split(/\s+/, $miniserv{"known_ips"});
}
$idx = &indexof("LOCAL", @list);
splice(@list, $idx, 1) if ($idx >= 0);
print &ui_table_row($text{'access_ip'},
&ui_radio("access", $access,
[ [ 0, $text{'access_all'} ],
[ 1, $text{'access_allow'} ],
[ 2, $text{'access_deny'} ] ])."<br>\n".
&ui_textarea("ip", join("\n", @list), 6, 30)."<br>\n".
&ui_checkbox("local", 1, $text{'access_local'}, $idx >= 0));
print &ui_table_row($text{'access_always'},
&ui_yesno_radio("alwaysresolve", int($miniserv{'alwaysresolve'})));
$mode = $miniserv{'trust_real_ip'} && !$miniserv{'no_trust_ssl'} ? 2 :
$miniserv{'trust_real_ip'} ? 1 : 0;
print &ui_table_row(&hlink($text{'access_trust_lvl'}, "access_trust_lvl"),
&ui_radio("trust", $mode,
[ [ 0, $text{'access_trust_lvl0'} ],
[ 1, $text{'access_trust_lvl1'} ],
[ 2, $text{'access_trust_lvl2'} ] ]));
@tprox = split(/\s+/, $miniserv{'trusted_proxies'});
print &ui_table_row(&hlink($text{'access_tproxies'}, "access_tproxies"),
&ui_textarea("trusted_proxies", join("\n", @tprox), 4, 30));
eval "use Authen::Libwrap qw(hosts_ctl STRING_UNKNOWN)";
if (!$@) {
print &ui_table_row($text{'access_libwrap'},
&ui_yesno_radio("libwrap", int($miniserv{'libwrap'})));
}
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+128
View File
@@ -0,0 +1,128 @@
#!/usr/local/bin/perl
# Display the advanced options form
require './webmin-lib.pl';
&ui_print_header(undef, $text{'advanced_title'}, "");
&get_miniserv_config(\%miniserv);
print &ui_form_start("change_advanced.cgi", "post");
print &ui_table_start($text{'advanced_header'}, undef, 2);
# Global temp directory
my $tempdir_placeholder = &webmin_temp_dir_path("/var/tmp");
print &ui_table_row($text{'advanced_temp'},
&ui_opt_textbox("tempdir", $gconfig{'tempdir'}, 30,
&text('advanced_tempdef', &default_webmin_temp_dir()),
undef, undef, undef, undef,
"placeholder='".&quote_escape($tempdir_placeholder)."'").
"<br>".
&ui_checkbox("tempdirdelete", 1, $text{'advanced_tdd'},
$gconfig{'tempdirdelete'}));
# Temp files clearing period
print &ui_table_row($text{'advanced_tempdelete'},
&ui_opt_textbox("tempdelete", $gconfig{'tempdelete_days'},
5, $text{'advanced_nodelete'})." ".
$text{'advanced_days'});
# Per-module temp directories
@mods = sort { $a->{'desc'} cmp $b->{'desc'} } &get_all_module_infos();
$ttable = &ui_columns_start([ $text{'advanced_tmod'},
$text{'advanced_tdir'} ]);
$i = 0;
foreach $d (&get_tempdirs(\%gconfig), [ ]) {
$ttable .= &ui_columns_row([
&ui_select("tmod_$i", $d->[0],
[ [ "", "&nbsp;" ],
map { [ $_->{'dir'}, $_->{'desc'} ] } @mods ]),
&ui_textbox("tdir_$i", $d->[1], 30)
]);
$i++;
}
$ttable .= &ui_columns_end();
print &ui_table_row($text{'advanced_tempmods'}, $ttable);
@preloads = &get_preloads(\%miniserv);
if (!@preloads && (!$miniserv{'premodules'} ||
$miniserv{'premodules'} eq 'WebminCore')) {
# New-style preload possible or enabled
print &ui_table_row($text{'advanced_preload'},
&ui_yesno_radio("preload",
$miniserv{'premodules'} eq 'WebminCore'));
}
elsif ($preloads[0]->[0] eq "main" && $preloads[0]->[1] eq "web-lib-funcs.pl") {
# Old-style preloads enabled
print &ui_table_row($text{'advanced_preload'},
&ui_yesno_radio("preload", 1));
}
# Files to pre-cache
$mode = $miniserv{'precache'} eq 'none' ? 0 :
$miniserv{'precache'} eq '' ? 1 : 2;
print &ui_table_row($text{'advanced_precache'},
&ui_radio("precache_mode", $mode,
[ [ 0, $text{'advanced_precache0'}."<br>" ],
[ 1, $text{'advanced_precache1'}."<br>" ],
[ 2, &text('advanced_precache2',
&ui_textbox("precache",
$mode == 2 ? $miniserv{'precache'} : "", 40)) ] ]));
# Umask for created files
print &ui_table_row($text{'advanced_umask'},
&ui_opt_textbox("umask", $gconfig{'umask'}, 5, $text{'default'}));
# Overwrite immutable files
if (&has_command("chattr")) {
print &ui_table_row($text{'advanced_chattr'},
&ui_yesno_radio("chattr", $gconfig{'chattr'}));
}
# Network buffer size
print &ui_table_row($text{'advanced_bufsize'},
&ui_opt_textbox("bufsize", $miniserv{'bufsize'}, 6,
$text{'default'}." (32768)"));
# Network download buffer size
print &ui_table_row($text{'advanced_bufsize_binary'},
&ui_opt_textbox("bufsize_binary", $miniserv{'bufsize_binary'}, 6,
$text{'default'}." (1048576)"));
# Nice level for cron jobs
if (&foreign_check("proc")) {
&foreign_require("proc", "proc-lib.pl");
print &ui_table_row($text{'advanced_nice'},
&ui_radio("nice_def", $gconfig{'nice'} eq '' ? 1 : 0,
[ [ 1, $text{'default'} ],
[ 0, $text{'advanced_pri'}." ".
&proc::nice_selector("nice", $gconfig{'nice'} || 0) ] ]));
# IO scheduling class and priority
if (defined(&proc::os_list_scheduling_classes) &&
(@classes = &proc::os_list_scheduling_classes())) {
print &ui_table_row($text{'advanced_sclass'},
&ui_select("sclass", $gconfig{'sclass'},
[ [ undef, $text{'default'} ],
@classes ]));
@prios = &proc::os_list_scheduling_priorities();
print &ui_table_row($text{'advanced_sprio'},
&ui_select("sprio", $gconfig{'sprio'},
[ [ undef, $text{'default'} ],
@prios ]));
}
}
# Extra HTTP headers
print &ui_table_row($text{'advanced_headers'},
&ui_textarea("headers",
join("\n", split(/\t/, $gconfig{'extra_headers'})), 5, 80));
# Sort config file's keys alphabetically
print &ui_table_row($text{'advanced_sortconfigs'},
&ui_yesno_radio("sortconfigs", $gconfig{'sortconfigs'}));
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+40
View File
@@ -0,0 +1,40 @@
#!/usr/local/bin/perl
# edit_anon.cgi
# Display anonymous access form
require './webmin-lib.pl';
&ui_print_header(undef, $text{'anon_title'}, "");
&get_miniserv_config(\%miniserv);
# Build list of users
print $text{'anon_desc'},"<br>\n";
print "<b>",$text{'anon_desc2'},"</b><p>\n";
foreach $a (split(/\s+/, $miniserv{'anonymous'})) {
if ($a =~ /^([^=]+)=(\S+)$/) {
push(@anon, [ $1, $2 ]);
}
}
# Build table data
$i = 0;
foreach my $a (@anon, [ ], [ ]) {
push(@table, [ &ui_textbox("url_$i", $a->[0], 40),
&ui_textbox("user_$i", $a->[1], 30) ]);
$i++;
}
# Show the table
print &ui_form_columns_table(
"change_anon.cgi",
[ [ undef, $text{'save'} ] ],
0,
undef,
undef,
[ $text{'anon_url'}, $text{'anon_user'} ],
undef,
\@table,
undef,
1);
&ui_print_footer("", $text{'index_return'});
+40
View File
@@ -0,0 +1,40 @@
#!/usr/local/bin/perl
require './webmin-lib.pl';
@modules = grep { &check_os_support($_) &&
!$_->{'hidden'} } &get_all_module_infos();
@modules = sort { $a->{'desc'} cmp $b->{'desc'} } @modules;
&read_file("$config_directory/webmin.catnames", \%catnames);
&ui_print_header(undef, $text{'assignment_title'}, undef);
print $text{'assignment_desc'},"<p>\n";
print &ui_form_start("save_assignment.cgi", "post");
@grid = ( );
foreach ( @modules ){
push(@grid, $_->{'desc'} || $_->{'dir'});
push(@grid, &cats($_->{'dir'}, $_->{'category'}));
}
print &ui_grid_table(\@grid, 4, 100, [ "valign=middle","valign=middle","valign=middle","valign=middle" ], undef, $text{'assignment_header'});
print &ui_form_end([ [ undef, $text{'assignment_ok'} ] ]);
&ui_print_footer("", $text{'index_return'});
sub cats {
my $cats;
my %cats;
foreach (keys %text) {
next unless /^category_/;
my $desc = $text{$_};
s/^category_//;
$cats{$_} = $desc;
}
foreach (keys %catnames) {
$cats{$_} = $catnames{$_};
}
return &ui_select($_[0], $_[1],
[ map { [ $_, $cats{$_} ] }
sort { $cats{$a} cmp $cats{$b} } keys %cats ]);
}
+105
View File
@@ -0,0 +1,105 @@
#!/usr/local/bin/perl
# edit_bind.cgi
# Display port / address form
require './webmin-lib.pl';
&ui_print_header(undef, $text{'bind_title'}, "");
&get_miniserv_config(\%miniserv);
print $text{'bind_desc'},"<p>\n";
print &ui_form_start("change_bind.cgi", "post");
print &ui_table_start($text{'bind_header'}, undef, 2, [ "width=30%" ]);
# Build list of sockets
@sockets = &get_miniserv_sockets(\%miniserv);
# Show table of all bound IPs and ports
$stable = &ui_columns_start([ $text{'bind_sip'}, $text{'bind_sport'} ]);
my $i = 0;
my @ports;
foreach my $s (@sockets, [ undef, "*" ]) {
# IP address
my @cols;
push(@cols, &ui_select("ip_def_$i", $s->[0] eq "" ? 0 :
$s->[0] eq "*" ? 1 : 2,
[ [ 0, "&nbsp;" ],
[ 1, $text{'bind_sip1'} ],
[ 2, $text{'bind_sip2'} ] ])." ".
&ui_textbox("ip_$i", $s->[0] eq "*" ? undef : $s->[0], 20));
# Port
push(@cols, &ui_select("port_def_$i", $s->[1] eq "*" ? 0 : 1,
[ $i ? ( [ 0, $text{'bind_sport0'} ] ) : ( ),
[ 1, $text{'bind_sport1'} ] ])." ".
&ui_textbox("port_$i", $s->[1] eq "*" ? undef : $s->[1],5));
$stable .= &ui_columns_row(\@cols, [ "nowrap", "nowrap" ]);
push(@ports, $s->[1]) if ($s->[1] && $s->[1] ne "*");
$i++;
}
$stable .= &ui_columns_end();
if (&foreign_check("firewall") || &foreign_check("firewalld")) {
$stable .= &ui_checkbox("firewall", 1, $text{'bind_firewall'}, 1);
}
print &ui_table_row($text{'bind_sockets'}, $stable);
# WebSocket based port
print &ui_table_row($text{'bind_websocport'},
&ui_radio("websocket_base_port_def",
$miniserv{"websocket_base_port"} ? 0 : 1,
[ [ 1, $text{'bind_websocport_none'} ],
[ 0, &ui_textbox("websocket_base_port",
$miniserv{"websocket_base_port"}, 6) ] ]));
# Hostname for WebSocket connections
print &ui_table_row($text{'bind_websoc_host'},
&ui_radio("websocket_host_def",
$miniserv{"websocket_host"} ? 0 : 1,
[ [ 1, $text{'bind_websoc_host_auto'} ],
[ 0, &ui_textbox("websocket_host",
$miniserv{"websocket_host"}, 25) ] ]));
# IPv6 enabled?
print &ui_table_row($text{'bind_ipv6'},
&ui_yesno_radio("ipv6", $miniserv{'ipv6'}));
# Show UDP listen address
print &ui_table_row($text{'bind_listen'},
&ui_radio("listen_def", $miniserv{"listen"} ? 0 : 1,
[ [ 1, $text{'bind_none'} ],
[ 0, &ui_textbox("listen", $miniserv{"listen"}, 6) ] ]));
# Show web server hostname
print &ui_table_row($text{'bind_hostname'},
&ui_radio("hostname_def", $miniserv{"host"} ? 0 : 1,
[ [ 1, $text{'bind_auto'} ],
[ 0, &ui_textbox("hostname", $miniserv{"host"}, 25) ] ]));
# Reverse-lookup hostname
print &ui_table_row($text{'bind_resolv_myname'},
&ui_radio("no_resolv_myname", int($miniserv{'no_resolv_myname'}),
[ [ 0, $text{'yes'} ], [ 1, $text{'no'} ] ]));
# Max concurrent connections
print &ui_table_row($text{'bind_maxconns'},
&ui_opt_textbox("maxconns", $miniserv{'maxconns'}, 5,
$text{'default'}." (50)"));
print &ui_table_row($text{'bind_maxconns_per_ip'},
&ui_opt_textbox("maxconns_per_ip", $miniserv{'maxconns_per_ip'}, 5,
$text{'default'}." (25)"));
print &ui_table_row($text{'bind_maxconns_per_net'},
&ui_opt_textbox("maxconns_per_net", $miniserv{'maxconns_per_net'}, 5,
$text{'default'}." (35)"));
# Max subprocess lifetime
print &ui_table_row($text{'bind_maxlifetime'},
&ui_opt_textbox("maxlifetime", $miniserv{'maxlifetime'}, 5,
$text{'bind_maxlifetime_def'})." ".
$text{'bind_maxlifetime_secs'});
print &ui_table_end();
print &ui_hidden("oldports", join(" ", @ports));
print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+35
View File
@@ -0,0 +1,35 @@
#!/usr/local/bin/perl
# Show a list of blocked users and hosts
require './webmin-lib.pl';
&ui_print_header(undef, $text{'blocked_title'}, "");
&get_miniserv_config(\%miniserv);
@blocked = &get_blocked_users_hosts(\%miniserv);
if (@blocked) {
print &ui_columns_start([ $text{'blocked_type'},
$text{'blocked_who'},
$text{'blocked_fails'},
$text{'blocked_when'},
]);
foreach $b (@blocked) {
print &ui_columns_row([
$text{'blocked_'.$b->{'type'}},
$b->{'user'} || $b->{'host'},
$b->{'fails'},
&make_date($b->{'when'}),
], [ "valign=middle","valign=middle","valign=middle","valign=middle" ]);
}
print &ui_columns_end();
print &ui_hr();
print &ui_buttons_start();
print &ui_buttons_row("clear_blocked.cgi",
$text{'blocked_clear'},
$text{'blocked_cleardesc'});
print &ui_buttons_end();
}
else {
print "<b>$text{'blocked_none'}</b><p>\n";
}
&ui_print_footer("", $text{'index_return'});
+88
View File
@@ -0,0 +1,88 @@
#!/usr/local/bin/perl
# edit_ca.cgi
# Display the current CA or a form for creating one
require './webmin-lib.pl';
ui_print_header(undef, $text{'ca_title'}, "");
get_miniserv_config(\%miniserv);
%aclconfig = foreign_config("acl");
foreign_require("acl", "acl-lib.pl");
if (!$ENV{"MINISERV_CONFIG"}) {
print "<p>$text{'ca_eminiserv'}<p>\n";
ui_print_footer("", $text{'index_return'});
exit;
}
elsif (uc($ENV{'HTTPS'}) ne 'ON') {
print "<p>$text{'ca_essl'}<p>\n";
ui_print_footer("", $text{'index_return'});
exit;
}
elsif (!defined(&Net::SSLeay::X509_STORE_CTX_get_current_cert) ||
!defined(&Net::SSLeay::CTX_load_verify_locations) ||
!defined(&Net::SSLeay::CTX_set_verify)) {
print "<p>$text{'ca_eversion'}<p>\n";
ui_print_footer("", $text{'index_return'});
exit;
}
elsif (!acl::get_ssleay()) {
print "<p>",text('ca_essleay',
"<tt>$aclconfig{'ssleay'}</tt>"),"<p>\n";
ui_print_footer("", $text{'index_return'});
exit;
}
print -r $miniserv{'ca'} ? $text{'ca_newmsg1'} : $text{'ca_newmsg1'},"<p>\n";
print ui_form_start("setup_ca.cgi", "post");
print ui_table_start($text{'ca_header1'}, undef, 2);
print &ui_table_row($text{'ca_cn'},
&ui_textbox("commonName", undef, 30), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ca_email'},
&ui_textbox("emailAddress", undef, 30), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ca_ou'},
&ui_textbox("organizationalUnitName", undef, 30), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ca_o'},
&ui_textbox("organizationName", undef, 30), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ca_sp'},
&ui_textbox("stateOrProvinceName", undef, 15), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ca_c'},
&ui_textbox("countryName", undef, 2), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ssl_size'},
&ui_opt_textbox("size", undef, 6,
"$text{'default'} ($default_key_size)").
" ".$text{'ssl_bits'}, undef, [ "valign=middle","valign=middle" ]);
print ui_table_end();
print ui_form_end([ [ "create", $text{'ca_create'} ] ]);
print ui_hr();
print -r $miniserv{'ca'} ? $text{'ca_oldmsg1'} : $text{'ca_oldmsg2'},"<p>\n";
print ui_form_start("change_ca.cgi", "form-data");
print ui_table_start($text{'ca_header2'}, undef, 2);
print ui_table_row(undef,
&ui_textarea("rows",
$miniserv{'ca'} ? &read_file_contents($miniserv{'ca'}) : undef,
20, 70));
print ui_table_end();
print ui_form_end([ [ "save", $text{'save'} ] ]);
if (-r $miniserv{'ca'}) {
print ui_hr();
print &ui_buttons_start();
print &ui_buttons_row("stop_ca.cgi", $text{'ca_stop'},
$text{'ca_stopmsg'});
print &ui_buttons_end();
}
ui_print_footer("", $text{'index_return'});
+61
View File
@@ -0,0 +1,61 @@
#!/usr/local/bin/perl
# Show a form for editing custom category names
require './webmin-lib.pl';
ReadParse();
ui_print_header(undef, $text{'categories_title'}, undef);
# Show language selector
print ui_form_start("edit_categories.cgi");
print "<b>$text{'categories_lang'}</b>\n";
print ui_select("lang", $in{'lang'},
[ [ "", "&lt;$text{'default'}&gt;" ],
map { [ $_->{'lang'}, "$_->{'desc'}" ] }
list_languages() ]),"\n";
print ui_submit($text{'categories_langok'}),"\n";
print ui_form_end();
print "$text{'categories_desc'}<p>\n";
print ui_form_start("save_categories.cgi");
print ui_hidden("lang", $in{'lang'});
print &ui_columns_start([ $text{'categories_code'},
$text{'categories_name'} ]);
# Show the existing categories
$file = "$config_directory/webmin.catnames";
$file .= ".".$in{'lang'} if ($in{'lang'});
read_file($file, \%catnames);
$catnames{''} ||= $catnames{'other'};
foreach $t (keys %text) {
$t =~ s/^category_// || next;
$field = $t || "other";
print &ui_columns_row([
$t || "<i>other</i>",
&ui_opt_textbox($field, $catnames{$t}, 30,
$text{'default'}, $text{'categories_custom'}),
], [ "valign=middle","valign=middle" ]);
$realcat{$t}++;
$realcat{'other'}++ if ($t eq '');
}
# Show new categories
$i = 0;
foreach $c (keys %catnames) {
if (!$realcat{$c}) {
print &ui_columns_row([
&ui_textbox("cat_$i", $c, 10),
&ui_textbox("desc_$i", $catnames{$c}, 30),
], [ "valign=middle","valign=middle" ]);
$i++;
}
}
print &ui_columns_row([
&ui_textbox("cat_$i", "", 10),
&ui_textbox("desc_$i", "", 30),
], [ "valign=middle","valign=middle" ]);
print &ui_columns_end();
print ui_form_end([ [ "ok", $text{'categories_ok'} ] ]);
ui_print_footer("", $text{'index_return'});
+59
View File
@@ -0,0 +1,59 @@
#!/usr/local/bin/perl
# Display debugging mode options
require './webmin-lib.pl';
&ui_print_header(undef, $text{'debug_title'}, "");
print &ui_form_start("change_debug.cgi", "post");
print &ui_table_start($text{'debug_header'}, undef, 2);
# Debugging mode enabled
print &ui_table_row($text{'debug_enabled'},
&ui_yesno_radio("debug_enabled", $gconfig{'debug_enabled'}), undef, [ "valign=middle","valign=middle" ]);
# What to log
print &ui_table_row($text{'debug_what'},
join("<br>\n",
map { &ui_checkbox('debug_what_'.$_, 1, $text{'debug_what_'.$_},
$gconfig{'debug_what_'.$_}) }
@debug_what_events));
# Log to where
print &ui_table_row($text{'debug_file'},
&ui_opt_textbox("debug_file", $gconfig{'debug_file'},
50, $text{'default'}.
" (<tt>$main::default_debug_log_file</tt>)"), undef, [ "valign=middle","valign=middle" ]);
# Maximum size
print &ui_table_row($text{'debug_size'},
&ui_radio("debug_size_def", $gconfig{'debug_size'} ? 0 : 1,
[ [ 1, $text{'default'}.
" (".&html_strip(&nice_size($main::default_debug_log_size)).")" ],
[ 0, &ui_bytesbox("debug_size", $gconfig{'debug_size'}) ] ]
), undef, [ "valign=middle","valign=middle" ]);
# Debug background processes?
print &ui_table_row($text{'debug_procs'},
&ui_checkbox("debug_web", 1, $text{'debug_web'},
!$gconfig{'debug_noweb'})."\n".
&ui_checkbox("debug_cmd", 1, $text{'debug_cmd'},
!$gconfig{'debug_nocmd'})."\n".
&ui_checkbox("debug_cron", 1, $text{'debug_cron'},
!$gconfig{'debug_nocron'}), undef, [ "valign=middle","valign=middle" ]);
# Modules to debug
# Modules to log in
print &ui_table_row($text{'debug_inmods'},
&ui_radio("mall", $gconfig{'debug_modules'} ? 0 : 1,
[ [ 1, $text{'log_mall'} ], [ 0, $text{'log_modules'} ] ]).
"<br>\n".
&ui_select("modules", [ split(/\s+/, $gconfig{'debug_modules'}) ],
[ map { [ $_->{'dir'}, $_->{'desc'} ] }
sort { $a->{'desc'} cmp $b->{'desc'} }
&get_all_module_infos() ], 5, 1));
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+52
View File
@@ -0,0 +1,52 @@
#!/usr/local/bin/perl
# Show module description overrides
require './webmin-lib.pl';
&ui_print_header(undef, $text{'descs_title'}, undef);
print "$text{'descs_info'}<p>\n";
&read_file("$config_directory/webmin.descs", \%descs);
print &ui_form_start("save_descs.cgi");
@tds = ( "width=50%", "width=50%" );
# Show override titles for real modules
print &ui_columns_start([ $text{'descs_mod'},
$text{'descs_desc'} ], "100%", 0, \@tds);
$i = 0;
@mods = sort { $a->{'realdesc'} cmp $b->{'realdesc'} } &get_all_module_infos();
foreach $d ((sort { $a cmp $b } (keys %descs)), undef, undef, undef) {
next if ($d =~ /^(\S+)\s+(\S+)$/);
print &ui_columns_row([
&ui_select("mod_$i", $d,
[ [ "", "&nbsp;" ],
map { [ $_->{'dir'}, $_->{'realdesc'} ] } @mods ]),
&ui_textbox("desc_$i", $descs{$d}, 40) ]);
$i++;
}
print &ui_columns_end();
# Show clone titles, if any
@clones = grep { $_->{'clone'} } @mods;
if (@clones) {
print &ui_columns_start([ $text{'descs_cmod'},
$text{'descs_cdesc'} ], "100%", 0, \@tds);
$i = 0;
foreach $mod (grep { $_->{'clone'} } @mods) {
%orig = &get_module_info(&get_clone_source($mod->{'dir'}));
if (%orig) {
$cdesc = $orig{'desc'}." (".$mod->{'dir'}.")";
}
else {
$cdesc = $mod->{'dir'};
}
print &ui_columns_row([
&ui_hidden("clone_$i", $mod->{'dir'}).$cdesc,
&ui_textbox("title_$i", $mod->{'desc'}, 40) ]);
$i++;
}
print &ui_columns_end();
}
print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+57
View File
@@ -0,0 +1,57 @@
#!/usr/local/bin/perl
# Show an IP-specific SSL key
require './webmin-lib.pl';
&ReadParse();
&get_miniserv_config(\%miniserv);
if ($in{'new'}) {
&ui_print_header(undef, $text{'ipkey_title1'}, "");
}
else {
&ui_print_header(undef, $text{'ipkey_title2'}, "");
@ipkeys = &get_ipkeys(\%miniserv);
$ipkey = $ipkeys[$in{'idx'}];
}
print &ui_form_start("save_ipkey.cgi", "post");
print &ui_hidden("new", $in{'new'}),"\n";
print &ui_hidden("idx", $in{'idx'}),"\n";
print &ui_table_start($text{'ipkey_header'}, undef, 2);
print &ui_table_row($text{'ipkey_ips2'},
&ui_textarea("ips", join("\n", @{$ipkey->{'ips'}}),
3, 60));
print &ui_table_row($text{'ssl_key'},
&ui_textbox("key", $ipkey->{'key'}, 40)."\n".
&file_chooser_button("key"), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ssl_cert'},
&ui_opt_textbox("cert", $ipkey->{'cert'}, 40,
$text{'ssl_cert_def'})."&nbsp;".
&file_chooser_button("cert"), undef, [ "valign=middle","valign=middle" ]);
$mode = $ipkey->{'extracas'} eq "none" ? 2 :
$ipkey->{'extracas'} ? 1 : 0;
print &ui_table_row($text{'ssl_extracas'},
&ui_radio("extracas_mode", $mode,
[ [ 0, $text{'ssl_extracasdef'} ],
[ 2, $text{'ssl_extracasnone'} ],
[ 1, $text{'ssl_extracasbelow'} ] ])."<br>\n".
&ui_textarea("extracas",
$mode == 1 ? join("\n",split(/\s+/, $ipkey->{'extracas'}))
: "",
3, 60)." ".
"<br>".&file_chooser_button("extracas", 0, undef, undef, 1));
print &ui_table_end();
if ($in{'new'}) {
print &ui_form_end([ [ "create", $text{'create'} ] ]);
}
else {
print &ui_form_end([ [ "save", $text{'save'} ],
[ "delete", $text{'delete'} ] ]);
}
&ui_print_footer("edit_ssl.cgi", $text{'ssl_return'});
+53
View File
@@ -0,0 +1,53 @@
#!/usr/local/bin/perl
# edit_lang.cgi
# Language config form
require './webmin-lib.pl';
&ui_print_header(undef, $text{'lang_title'}, "");
print $text{'lang_intro'},"<p>\n";
print &ui_form_start("change_lang.cgi", "post");
print &ui_table_start($text{'lang_title2'}, undef, 2, [ "width=40%" ]);
# Language
$clang = $gconfig{'lang'} ? safe_language($gconfig{'lang'}) : $default_lang;
my ($linfo) = grep { $_->{'lang'} eq $clang } &list_languages();
my $clangauto = defined($gconfig{'langauto'}) ? $gconfig{'langauto'} : $linfo->{'auto'};
print &ui_table_row($text{'lang_lang'},
&ui_select("lang", $clang,
[ map { [ $_->{'lang'}, "$_->{'desc'}" ] }
&list_languages() ])." ".
&ui_checkbox("langauto", 1, $text{'langauto_include'}, $clangauto));
# Old datetime format or a new locale
eval "use DateTime; use DateTime::Locale; use DateTime::TimeZone;";
if (!$@ && $] > 5.011) {
my $locales = &list_locales();
my %localesrev = reverse %{$locales};
my $locale_auto = &parse_accepted_language();
print &ui_table_row($text{'lang_locale'},
&ui_select("locale", $locale_auto || $gconfig{'locale'} || &get_default_system_locale(),
[ map { [ $localesrev{$_}, $_ ] } sort values %{$locales} ]).
&ui_hidden("dateformat", $gconfig{'dateformat'}),
undef, [ "valign=middle","valign=middle" ]);
}
else {
print &ui_table_row($text{'lang_dateformat'},
&ui_select("dateformat", $gconfig{'dateformat'} || "dd/mon/yyyy",
[ map { [ $_, $text{'lang_dateformat_'.$_} ] }
@webmin_date_formats ]).
&ui_hidden("locale", $gconfig{'locale'}),
undef, [ "valign=middle","valign=middle" ]);
}
# Use language from browser?
print &ui_table_row($text{'lang_accept'},
&ui_yesno_radio("acceptlang", int($gconfig{'acceptlang'})));
print &ui_table_end();
print &ui_form_end([ [ "", $text{'lang_ok'} ] ]);
&ui_print_footer("", $text{'index_return'});
+78
View File
@@ -0,0 +1,78 @@
#!/usr/local/bin/perl
# Display the locking form
require './webmin-lib.pl';
&ui_print_header(undef, $text{'lock_title'}, "");
print $text{'lock_desc'},"<p>\n";
print &ui_form_start("change_lock.cgi", "post");
print &ui_table_start($text{'lock_header'}, undef, 2);
print &ui_table_row($text{'lock_mode'},
&ui_radio("lockmode", int($gconfig{'lockmode'}),
[ [ 0, $text{'lock_all'} ],
[ 1, $text{'lock_none'} ],
[ 2, $text{'lock_only'} ],
[ 3, $text{'lock_except'} ] ])."<br>\n".
&ui_textarea("lockdirs",
join("\n", split(/\t+/, $gconfig{'lockdirs'})), 10, 60));
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ] ]);
print &ui_table_hr();
my @locks = &list_active_locks();
my @tds;
push(@tds, "width=5");
my $locked_content;
if (@locks) {
my $now = time();
$locked_content = &ui_form_start("kill_lock.cgi", "post");
$locked_content .= &ui_columns_start(
[ "", $text{'lock_pid'}, $text{'lock_cmd'},
$text{'lock_file'}, $text{'lock_age'} ]);
foreach my $p (@locks) {
foreach my $l (@{$p->{'locks'}}) {
my $age = $now - $l->{'time'};
if ($age < 2*60) {
$age .= " ".$text{'lock_s'};
}
elsif ($age < 2*60*60) {
$age = int($age/60)." ".$text{'lock_m'};
}
else {
$age = int($age/60/60)." ".$text{'lock_h'};
}
my $cmd = $p->{'proc'}->{'args'};
$locked_content .= &ui_checked_columns_row(
[
&foreign_available('proc') ?
&ui_link("@{[&get_webprefix()]}/proc/edit_proc.cgi?$p->{'pid'}", $p->{'pid'}) :
$p->{'pid'},
"<tt>".&html_escape($cmd)."</tt>",
"<tt>".&html_escape($l->{'lock'})."</tt>",
$age
], \@tds, "d", $p->{'pid'}.'-'.$l->{'num'});
}
}
$locked_content .= &ui_columns_end();
$locked_content .= &ui_form_end([ [ 'term', $text{'lock_term'} ],
[ 'kill', $text{'lock_kill'} ] ]);
print &ui_details({
'title' => $text{'lock_files'},
'class' => 'default',
'content' => "$text{'lock_msg'}<br>" . $locked_content,
'html' => 1}, 1);
}
else {
print &ui_details({
'title' => $text{'lock_nfiles'},
'class' => 'default',
'content' => $text{'lock_noneopen'},
'html' => 1});
}
&ui_print_footer("", $text{'index_return'});
+104
View File
@@ -0,0 +1,104 @@
#!/usr/local/bin/perl
# edit_log.cgi
# Logging config form
require './webmin-lib.pl';
&ui_print_header(undef, $text{'log_title'}, "");
&foreign_require("acl", "acl-lib.pl");
&get_miniserv_config(\%miniserv);
print &text('log_desc', "<tt>$miniserv{'logfile'}</tt>"),"<p>\n";
print &text('log_desc2', "<tt>$webmin_logfile</tt>"),"<p>\n";
print &ui_form_start("change_log.cgi", "post");
print &ui_table_start($text{'log_header'}, undef, 2);
# Is logging enabled?
print &ui_table_row($text{'log_status'},
&ui_radio("log", $miniserv{'log'} ? 1 : 0,
[ [ 1, $text{'log_enable'} ],
[ 0, $text{'log_disable'} ] ]));
# Log resolved hostnames
print &ui_table_row($text{'log_resolv'},
&ui_yesno_radio("loghost", int($miniserv{'loghost'})));
# Log IP provided by proxy?
print &ui_table_row($text{'log_trust'},
&ui_yesno_radio("logtrust", int($miniserv{'logtrust'})));
# Use common log format
print &ui_table_row($text{'log_clf'},
&ui_yesno_radio("logclf", int($miniserv{'logclf'})));
# Clear logs regularly
print &ui_table_row($text{'log_clear2'},
&ui_radio("logclear", int($miniserv{'logclear'}),
[ [ 1, &text('log_period',
&ui_textbox("logtime", $miniserv{'logtime'}, 10)) ],
[ 0, $text{'no'} ] ]));
print &ui_table_hr();
# Webmin users to log for
print &ui_table_row($text{'log_forusers'},
&ui_radio("uall", $gconfig{'logusers'} ? 0 : 1,
[ [ 1, $text{'log_uall'} ], [ 0, $text{'log_users'} ] ]).
"<br>\n".
&ui_select("users", [ split(/\s+/, $gconfig{'logusers'}) ],
[ map { [ $_->{'name'} ] }
sort { $a->{'name'} cmp $b->{'name'} }
&acl::list_users() ],
5, 1));
# Create list of modules for which logging is possible
@logmods = ( [ "global", $text{'log_global'} ],
map { [ $_->{'dir'}, $_->{'desc'} ] }
grep { -r &module_root_directory($_)."/log_parser.pl" }
sort { lc($a->{'desc'}) cmp lc($b->{'desc'}) }
&get_all_module_infos() );
# Modules to log in
print &ui_table_row($text{'log_inmods'},
&ui_radio("mall", $gconfig{'logmodules'} ? 0 : 1,
[ [ 1, $text{'log_mall'} ], [ 0, $text{'log_modules'} ] ]).
"<br>\n".
&ui_select("modules", [ split(/\s+/, $gconfig{'logmodules'}) ],
\@logmods, 5, 1));
# Log logins and logouts?
if (!$miniserv{'login_script'} ||
$miniserv{'login_script'} eq $record_login_cmd) {
print &ui_table_row($text{'log_login'},
&ui_yesno_radio("login",
$miniserv{'login_script'} eq $record_login_cmd));
}
# Log scheduled actions?
print &ui_table_row($text{'log_sched'},
&ui_yesno_radio("logsched", $gconfig{'logsched'}));
# Log file changes?
print &ui_table_row($text{'log_files'},
&ui_yesno_radio("logfiles", int($gconfig{'logfiles'})));
# Log full files?
print &ui_table_row($text{'log_fullfiles'},
&ui_yesno_radio("logfullfiles", int($gconfig{'logfullfiles'})));
# Logfile permissions
print &ui_table_row($text{'log_perms'},
&ui_opt_textbox("perms", $gconfig{'logperms'}, 5, $text{'default'}));
# Also log to syslog?
eval "use Sys::Syslog qw(:DEFAULT setlogsock)";
if (!$@) {
print &ui_table_row($text{'log_syslog'},
&ui_yesno_radio("logsyslog", int($gconfig{'logsyslog'})));
}
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+36
View File
@@ -0,0 +1,36 @@
#!/usr/local/bin/perl
# Display options specific to mobile devices
require './webmin-lib.pl';
&ReadParse();
&ui_print_header(undef, $text{'mobile_title'}, "");
&get_miniserv_config(\%miniserv);
print &ui_form_start("change_mobile.cgi");
print &ui_table_start($text{'mobile_header'}, undef, 2);
# Custom theme for mobile devices
@themes = &list_themes();
$m = $miniserv{'mobile_preroot'};
print &ui_table_row($text{'mobile_theme'},
&ui_select("theme", defined($m) ? $m : "*",
[ [ "*", $text{'mobile_themeglob'} ],
map { [ $_->{'dir'}, $_->{'desc'} ] } @themes ]), undef, [ "valign=middle","valign=middle" ]);
# Skip session login for mobile devices
print &ui_table_row($text{'mobile_nosession'},
&ui_yesno_radio("nosession", int($miniserv{'mobile_nosession'})), undef, [ "valign=middle","valign=middle" ]);
# Extra user agents
print &ui_table_row($text{'mobile_agents'},
&ui_textarea("agents",
join("\n", split(/\t+/, $miniserv{'mobile_agents'})), 5, 50));
# Hostname prefixes for mobile
print &ui_table_row($text{'mobile_prefixes'},
&ui_textbox("prefixes", $miniserv{'mobile_prefixes'}, 50), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+148
View File
@@ -0,0 +1,148 @@
#!/usr/local/bin/perl
# edit_mods.cgi
# Form for installing and removing modules
require './webmin-lib.pl';
&ReadParse();
&ui_print_header(undef, $text{'mods_title'}, "");
@mlist = sort { $a->{'desc'} cmp $b->{'desc'} }
grep { &check_os_support($_) } &get_all_module_infos();
$version = &get_webmin_version();
if (&shared_root_directory()) {
&ui_print_endpage($text{'mods_eroot'});
}
# Show tabs
@tabs = ( [ "install", $text{'mods_tabinstall'}, "edit_mods.cgi?mode=install" ],
[ "clone", $text{'mods_tabclone'}, "edit_mods.cgi?mode=clone" ],
[ "delete", $text{'mods_tabdelete'}, "edit_mods.cgi?mode=delete" ],
[ "export", $text{'mods_tabexport'}, "edit_mods.cgi?mode=export" ],
);
print &ui_tabs_start(\@tabs, "mode", $in{'mode'} || "install", 1);
# Display installation form
print &ui_tabs_start_tab("mode", "install");
print "$text{'mods_desc1'}<p>\n";
print &ui_form_start("install_mod.cgi", "form-data");
print &ui_table_start($text{'mods_install'}, undef, 2);
print &ui_table_row($text{'mods_installsource'},
&ui_radio_table("source", 0,
[ [ 0, $text{'mods_local'},
&ui_textbox("file", undef, 40)." ".
&file_chooser_button("file", 0) ],
[ 1, $text{'mods_uploaded'},
&ui_upload("upload", 40) ],
[ 2, $text{'mods_ftp'},
&ui_textbox("url", undef, 40) ],
[ 4, $text{'mods_third'},
&ui_textbox("third", undef, 40)." ".
&third_chooser_button("third") ] ]));
print &ui_table_row($text{'mods_nodeps'},
&ui_yesno_radio("nodeps", 0));
print &ui_table_row($text{'mods_grantto'},
&ui_radio("grant", 0,
[ [ 0, $text{'mods_grant2'}."&nbsp;".
&ui_textbox("grantto", $base_remote_user, 30)."<br>" ],
[ 1, $text{'mods_grant1'} ] ]));
print &ui_table_row($text{'mods_checksig'},
&ui_yesno_radio("checksig", 0));
print &ui_table_end();
print &ui_form_end([ [ "", $text{'mods_installok'} ] ]);
print &ui_tabs_end_tab();
# Display cloning form
print &ui_tabs_start_tab("mode", "clone");
print "$text{'mods_desc2'}<p>";
print &ui_form_start("clone_mod.cgi", "post");
print &ui_table_start($text{'mods_clone'}, undef, 2);
# Source module
print &ui_table_row($text{'mods_cname'},
&ui_select("mod", undef,
[ map { [ $_->{'dir'}, $_->{'desc'} ] }
grep { $_->{'dir'} ne 'webmin' && !$_->{'clone'} }
@mlist ]));
# New description
print &ui_table_row($text{'mods_cnew'},
&ui_textbox("desc", undef, 40));
# New category
%cats = &list_categories(\@mlist, 1);
print &ui_table_row($text{'mods_ccat'},
&ui_select("cat", "*",
[ [ "*", $text{'mods_csame'} ],
map { [ $_, $cats{$_} ] }
sort { lc($a) cmp lc($b) } (keys %cats) ]));
print &ui_table_row($text{'mods_creset'},
&ui_yesno_radio("creset", 0));
print &ui_table_end();
print &ui_form_end([ [ "", $text{'mods_cloneok'} ] ]);
print &ui_tabs_end_tab();
# Display deletion form
print &ui_tabs_start_tab("mode", "delete");
print "$text{'mods_desc3'}<p>\n";
print &ui_form_start("delete_mod.cgi", "post");
print &ui_table_start($text{'mods_delete'}, undef, 2);
my $home = $root_directory eq '/usr/local/webadmin';
@opts = ( );
foreach $m (@mlist) {
if ($m->{'dir'} ne 'webmin' && &check_os_support($m)) {
my @st = stat(&module_root_directory($m->{'dir'}));
my @tm = localtime($st[9]);
my $vstr = $m->{'version'} == $version ? "" :
$m->{'version'} ? "(v. $m->{'version'})" :
$home ? "" :
sprintf "(%d/%d/%d)",
$tm[3], $tm[4]+1, $tm[5]+1900;
push(@opts, [ $m->{'dir'}, $m->{'desc'}." ".$vstr ]);
}
}
print &ui_table_row(undef,
&ui_select("mod", undef, \@opts, 10, 1)."<br>\n".
&ui_checkbox("nodeps", 1, $text{'mods_nodeps2'}, 0), 2);
print &ui_table_end();
print &ui_form_end([ [ "", $text{'mods_deleteok'} ] ]);
print &ui_tabs_end_tab();
# Display export form
print &ui_tabs_start_tab("mode", "export");
print "$text{'mods_desc4'}<p>\n";
print &ui_form_start("export_mod.cgi/module.wbm.gz");
print &ui_table_start($text{'mods_header4'}, undef, 2);
print &ui_table_row($text{'mods_exportmods'},
&ui_select("mod", undef,
[ map { [ $_->{'dir'},
$_->{'desc'}.($_->{'version'} == $version ? "" :
$_->{'version'} ? "(v. $_->{'version'})" : "")
] } @mlist ], 10, 1));
print &ui_table_row($text{'mods_exportto'},
&ui_radio("to", 0,
[ [ 0, $text{'mods_exportshow'}."<br>" ],
[ 1, &text('mods_exportfile',
&ui_textbox("file", undef, 40)) ] ]));
print &ui_table_end();
print &ui_form_end([ [ "ok", $text{'mods_exportok'} ] ]);
print &ui_tabs_end_tab();
print &ui_tabs_end(1);
&ui_print_footer("", $text{'index_return'});
+101
View File
@@ -0,0 +1,101 @@
#!/usr/local/bin/perl
# edit_os.cgi
# Show the current OS according to Webmin, and some environment settings
require './webmin-lib.pl';
&ui_print_header(undef, $text{'os_title'}, "");
&get_miniserv_config(\%miniserv);
print $text{'os_desc3'},"<br>\n";
print $text{'os_desc2'},"<p>\n";
print &ui_form_start("change_os.cgi", "post");
print &ui_table_start($text{'os_header'}, undef, 2, [ "width=40%" ]);
# OS according to Webmin
print &ui_table_row($text{'os_webmin'},
&ui_select("type", $gconfig{'real_os_type'},
[ map { [ $_ ] } sort { $a cmp $b } &unique(map { $_->{'realtype'} }
&list_operating_systems()) ])." ".
&ui_textbox("version", $gconfig{'real_os_version'}, 10), undef, [ "valign=middle","valign=middle" ]);
# Internal OS code
print &ui_table_row($text{'os_iwebmin'},
&ui_select("itype", $gconfig{'os_type'},
[ map { [ $_ ] } sort { $a cmp $b } &unique(map { $_->{'type'} }
&list_operating_systems()) ])." ".
&ui_textbox("iversion", $gconfig{'os_version'}, 10), undef, [ "valign=middle","valign=middle" ]);
# Detected OS
%osinfo = &detect_operating_system();
if ($osinfo{'real_os_type'}) {
print &ui_table_row($text{'os_detect'},
"$osinfo{'real_os_type'} $osinfo{'real_os_version'}\n".
($osinfo{'os_type'} ne $gconfig{'os_type'} ||
$osinfo{'os_version'} ne $gconfig{'os_version'} ?
"<br>".&ui_checkbox("update", 1, $text{'os_update'}) :
""), undef, [ "valign=middle","valign=middle" ]);
# Before EOL message is shown (months)
if ($gconfig{'os_eol'}) {
print &ui_table_row($text{'os_eol_type1'},
"$text{'os_eol_until'} $gconfig{'os_eol'}");
if ($gconfig{'os_ext_eol'}) {
print &ui_table_row($text{'os_eol_type2'},
"$text{'os_eol_until'} $gconfig{'os_ext_eol'}");
}
print &ui_table_row($text{'os_eol'},
&ui_textbox("os_eol_before",
$gconfig{'os_eol_before'} // 3, 2).
"&nbsp;$text{'os_eol_countdown'}");
}
}
else {
print &ui_table_row($text{'os_detect'},
"<i>$text{'os_cannot'}</i>");
}
print &ui_table_hr();
# Search path
print &ui_table_row($text{'os_path'},
&ui_textarea("path",
join("\n", split($path_separator, $gconfig{'path'})),
5, 30)."<br>".
&ui_checkbox("syspath", 1, $text{'os_syspath'}, !$gconfig{'syspath'}));
# Shared library path
if ($gconfig{'ld_env'}) {
print &ui_table_row($text{'os_ld_path'},
&ui_textarea("ld_path",
join("\n", split($path_separator, $gconfig{'ld_path'})),
5, 30));
}
# Perl search path
print &ui_table_row($text{'os_perllib'},
&ui_textarea("perllib",
join("\n", split(":", $miniserv{'perllib'})), 3, 30));
# Global environment variables
$atable = &ui_columns_start([ $text{'os_name'}, $text{'os_value'} ]);
$i = 0;
foreach $e (keys %miniserv) {
if ($e =~ /^env_(\S+)$/ &&
$1 ne "WEBMIN_CONFIG" && $1 ne "WEBMIN_VAR") {
$atable .= &ui_columns_row([
&ui_textbox("name_$i", $1, 20),
&ui_textbox("value_$i", $miniserv{$e}, 30)
]);
$i++;
}
}
$atable .= &ui_columns_row([ &ui_textbox("name_$i", undef, 20),
&ui_textbox("value_$i", undef, 30) ]);
$atable .= &ui_columns_end();
print &ui_table_row($text{'os_envs'}, $atable);
print &ui_table_end();
print &ui_form_end([ [ "", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+105
View File
@@ -0,0 +1,105 @@
#!/usr/local/bin/perl
# edit_proxy.cgi
# Proxy servers config form
require './webmin-lib.pl';
&ReadParse();
&ui_print_header(undef, $text{'proxy_title'}, "");
# Show tabs
@tabs = ( [ "proxy", $text{'proxy_tabproxy'}, "edit_proxy.cgi?mode=proxy" ],
[ "down", $text{'proxy_tabdown'}, "edit_proxy.cgi?mode=down" ] );
print &ui_tabs_start(\@tabs, "pd", $in{'mode'} || "proxy", 1);
print &ui_tabs_start_tab("pd", "proxy");
print $text{'proxy_desc'},"<p>\n";
print &ui_form_start("change_proxy.cgi", "post");
print &ui_table_start($text{'proxy_header'}, undef, 2, [ "width=30%" ]);
# HTTP proxy
print &ui_table_row($text{'proxy_http'},
&ui_opt_textbox("http", $gconfig{'http_proxy'}, 50,
$text{'proxy_none'}), undef, [ "valign=middle","valign=middle" ]);
# FTP proxy
print &ui_table_row($text{'proxy_ftp'},
&ui_opt_textbox("ftp", $gconfig{'ftp_proxy'}, 50,
$text{'proxy_none'}), undef, [ "valign=middle","valign=middle" ]);
# No proxy for domains
print &ui_table_row($text{'proxy_nofor'},
&ui_textbox("noproxy", $gconfig{'noproxy'}, 60), undef, [ "valign=middle","valign=middle" ]);
# User and password
print &ui_table_row($text{'proxy_user'},
&ui_textbox("puser", $gconfig{'proxy_user'}, 20), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'proxy_pass'},
&ui_password("ppass", $gconfig{'proxy_pass'}, 20), undef, [ "valign=middle","valign=middle" ]);
# Bind to address for outgoing connections
print &ui_table_row($text{'proxy_bind'},
&ui_opt_textbox("bind", $gconfig{'bind_proxy'}, 35, $text{'default'}), undef, [ "valign=middle","valign=middle" ]);
# Fallback to direct
print &ui_table_row($text{'proxy_fallback'},
&ui_yesno_radio("fallback", int($gconfig{'proxy_fallback'})), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ] ]);
print &ui_tabs_end_tab();
# OSDN mirror form
print &ui_tabs_start_tab("pd", "down");
print $text{'proxy_desc2'},"<p>\n";
print &ui_form_start("change_osdn.cgi");
print &ui_table_start($text{'proxy_header2'}, undef, 2);
# Cache size
print &ui_table_row($text{'proxy_cache'},
&ui_radio("cache_def", $gconfig{'cache_size'} ? 0 : 1,
[ [ 1, $text{'proxy_cache1'} ],
[ 0, $text{'proxy_cache0'} ] ])."\n".
&ui_bytesbox("cache", $gconfig{'cache_size'}, 8), undef, [ "valign=middle","valign=middle" ]);
# Cache time
print &ui_table_row($text{'proxy_daysmax'},
&ui_opt_textbox("days", $gconfig{'cache_days'}, 5,
$text{'proxy_daysdef'})." ".$text{'proxy_days'}, undef, [ "valign=middle","valign=middle" ]);
# Modules to cache in
$excl = ($gconfig{'cache_mods'} =~ s/^\!//);
@mods = split(/\s+/, $gconfig{'cache_mods'});
print &ui_table_row($text{'proxy_mods'},
&ui_radio("mods_def", !$gconfig{'cache_mods'} ? 0 :
$excl ? 2 : 1,
[ [ 0, $text{'proxy_mods0'} ],
[ 1, $text{'proxy_mods1'} ],
[ 2, $text{'proxy_mods2'} ] ])."<br>\n".
&ui_select("mods", \@mods,
[ map { [ $_->{'dir'}, $_->{'desc'} ] }
sort { lc($a->{'desc'}) cmp lc($b->{'desc'}) }
&get_all_module_infos() ],
10, 1));
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ],
[ "clear", $text{'proxy_clear'} ] ]);
@cached = &list_cached_files();
if (@cached) {
# Show cache management and clearing buttons
print &ui_hr();
print &ui_buttons_start();
print &ui_buttons_row("cache.cgi", $text{'proxy_cacheb'},
$text{'proxy_cachebdesc'});
$sz = &nice_size(&disk_usage_kb($main::http_cache_directory)*1024);
print &ui_buttons_row("clear_cache.cgi", $text{'proxy_clear'},
&text('proxy_cleardesc', scalar(@cached), $sz));
print &ui_buttons_end();
}
print &ui_tabs_end_tab();
print &ui_tabs_end(1);
&ui_print_footer("", $text{'index_return'});
+30
View File
@@ -0,0 +1,30 @@
#!/usr/local/bin/perl
# edit_referers.cgi
# Display a list of trusted referers
require './webmin-lib.pl';
&ui_print_header(undef, $text{'referers_title'}, "");
print $text{'referers_desc'},"<br>\n";
print &ui_form_start("change_referers.cgi");
print &ui_table_start(undef, undef, 2);
print &ui_table_row($text{'referers_referer'},
&ui_radio("referer", $gconfig{'referer'} ? 1 : 0,
[ [ 0, $text{'yes'} ], [ 1, $text{'no'} ] ]));
print &ui_table_row($text{'referers_list'},
&ui_textarea("referers",
join("\n", split(/\s+/, $gconfig{'referers'})),
5, 60)."<br>\n".
(!$gconfig{'referers_none'} ?
&ui_checkbox("referers_none", 1,
$text{'referers_none'}."<br>".
&ui_text_color($text{'referers_none2'}, 'warn'),
!$gconfig{'referers_none'}) : ""));
print &ui_table_end();
print &ui_form_end([ [ undef, $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+114
View File
@@ -0,0 +1,114 @@
#!/usr/local/bin/perl
# Show mail sending options
require './webmin-lib.pl';
&ui_print_header(undef, $text{'sendmail_title'}, "");
&foreign_require("mailboxes");
%mconfig = &foreign_config("mailboxes");
print $text{'sendmail_desc'},"<p>\n";
print &ui_form_start("save_sendmail.cgi", "post");
print &ui_table_start($text{'sendmail_header'}, undef, 2);
# Mail server type
$ms = $mconfig{'mail_system'};
print &ui_table_row($text{'sendmail_system'},
$mailboxes::text{'index_system'.$ms});
# SMTP server
$smtp = $mconfig{'send_mode'};
$mode = $smtp eq "" ? 0 :
$smtp eq "localhost" || $smtp eq "127.0.0.1" ? 1 : 2;
$port = $mconfig{'smtp_port'};
print &ui_table_row($text{'sendmail_smtp'},
&ui_radio("mode", $mode, [ [ 0, $text{'sendmail_smtp0'}."<br>" ],
[ 1, $text{'sendmail_smtp1'}."<br>" ],
[ 2, $text{'sendmail_smtp2'} ] ]).
" ".&ui_textbox("smtp", $mode == 2 ? $smtp : "", 40));
# SMTP port
print &ui_table_row($text{'sendmail_port'},
&ui_opt_textbox("port", $port, 6, $text{'sendmail_portdef'},
$text{'sendmail_portsel'}));
# SMTP encryption
print &ui_table_row($text{'sendmail_ssl'},
&ui_select("ssl", int($mconfig{'smtp_ssl'}),
[ [ 0, $text{'sendmail_ssl0'} ],
[ 1, $text{'sendmail_ssl1'} ],
[ 2, $text{'sendmail_ssl2'} ] ]));
# SMTP login and password
$user = $mconfig{'smtp_user'};
$pass = $mconfig{'smtp_pass'};
print &ui_table_row($text{'sendmail_login'},
&ui_radio("login_def", $user ? 0 : 1,
[ [ 1, $text{'sendmail_login1'}."<br>" ],
[ 0, $text{'sendmail_login0'} ] ])." ".
&ui_textbox("login_user", $user, 12)."&nbsp;".
$text{'sendmail_pass'}."&nbsp;&nbsp;".
&ui_textbox("login_pass", $pass, 12));
# Authentication method
$auth = $mconfig{'smtp_auth'};
print &ui_table_row($text{'sendmail_auth'},
&ui_select("auth", $auth,
[ [ undef, $text{'sendmail_authdef'} ],
"Cram-MD5", "Digest-MD5", "Plain", "Login" ]));
# From address
$from = $mconfig{'webmin_from'};
$fromdef = "webmin-noreply\@".&mailboxes::get_from_domain();
print &ui_table_row($text{'sendmail_from'},
&ui_radio_table("from_def", $from ? 0 : 1,
[ [ 1, "", &text('sendmail_fromdef', $fromdef) ],
[ 0, "", $text{'sendmail_fromaddr'}." ".
&ui_textbox("from", $from, 40)."<br>\n".
$text{'sendmail_name'}." ".
&ui_textbox("from_name", $mconfig{'webmin_from_name'}, 30) ] ]), 3);
# Default to address for notifications
$to = $gconfig{'webmin_email_to'};
print &ui_table_row($text{'sendmail_toaddr'},
&ui_opt_textbox("to", $to, 40, $text{'sendmail_to_def'}));
# URL for use in emails
$url = $gconfig{'webmin_email_url'};
$defurl = &get_webmin_email_url(undef, undef, 1);
print &ui_table_row($text{'sendmail_url'},
&ui_opt_textbox("url", $url, 40,
&text('sendmail_url_def', "<tt>$defurl</tt>")."<br>",
$text{'sendmail_url_custom'}));
print &ui_table_end();
print &ui_form_end([ [ "", $text{'save'} ] ]);
print &ui_hr();
print $text{'sendmail_desc2'},"<p>\n";
print &ui_form_start("test_sendmail.cgi", "post");
print &ui_table_start($text{'sendmail_header2'}, undef, 2);
print &ui_table_row($text{'sendmail_to'},
&ui_textbox("to", $to, 40));
print &ui_table_row($text{'sendmail_subject'},
&ui_textbox("subject", "Test email from Webmin", 40));
$msg = "This is a test message from Webmin, sent with the settings :\n".
"\n".
"Mail server: ".$mailboxes::text{'index_system'.$ms}."\n".
"Sent via: ".($smtp || "Local mail server")."\n".
"SMTP login: ".($user || "None")."\n".
"SMTP authentication: ".($auth || "Default")."\n";
print &ui_table_row($text{'sendmail_body'},
&ui_textarea("body", $msg, 8, 80));
print &ui_table_end();
print &ui_form_end([ [ "", $text{'sendmail_send'} ] ]);
&ui_print_footer("", $text{'index_return'});
+186
View File
@@ -0,0 +1,186 @@
#!/usr/local/bin/perl
# edit_session.cgi
# Edit session login options
require './webmin-lib.pl';
print "Set-Cookie: sessiontest=1; path=/\n";
ui_print_header(undef, $text{'session_title'}, "");
get_miniserv_config(\%miniserv);
foreign_require("acl");
print "$text{'session_desc1'}<p>\n";
print ui_form_start("change_session.cgi", "post");
print ui_table_start($text{'session_header'}, undef, 2);
# Bad password delay
print &ui_table_row(&hlink($text{'session_ptimeout'}, 'ptimeout'),
&ui_radio("passdelay", $miniserv{'passdelay'} ? 1 : 0,
[ [ 0, $text{'session_pdisable'}."<br>\n" ],
[ 1, $text{'session_penable'} ] ]));
# Block bad hosts
print &ui_table_row($text{'session_pblock'},
&ui_checkbox("blockhost_on", 1,
text('session_blockhost',
ui_textbox("blockhost_failures", $miniserv{'blockhost_failures'}, 2),
ui_textbox("blockhost_time", $miniserv{'blockhost_time'}, 2)),
$miniserv{'blockhost_failures'} ? 1 : 0));
# Block bad users
print &ui_table_row("",
&ui_checkbox("blockuser_on", 1,
text('session_blockuser',
ui_textbox("blockuser_failures", $miniserv{'blockuser_failures'}, 2),
ui_textbox("blockuser_time", $miniserv{'blockuser_time'}, 2)),
$miniserv{'blockuser_failures'} ? 1 : 0));
# Lock Webmin users who failed login too many times
print &ui_table_row("",
ui_checkbox("blocklock", 1, $text{'session_blocklock'},
$miniserv{'blocklock'}));
# Enable forgotten password recovery
print &ui_table_row($text{'session_forgot'},
&ui_radio("forgot", $gconfig{'forgot_pass'},
[ [ 0, $text{'no'}."<br>" ],
[ 1, $text{'yes'}."<br>" ],
[ 2, $text{'forgot_nossl'} ] ]));
# Block bad password requests
$gconfig{'passreset_failures'} //= 3;
$gconfig{'passreset_time'} //= 60;
print &ui_table_row($text{'session_passresetdesc'},
&ui_checkbox("blockpass_on", 1,
text('session_passreset',
&ui_textbox("passreset_failures", $gconfig{'passreset_failures'}, 2),
&ui_textbox("passreset_time", $gconfig{'passreset_time'}, 2)),
$gconfig{'passreset_failures'} ? 1 : 0));
# Password reset link expiry
$gconfig{'passreset_timeout'} ||= 15;
print &ui_table_row($text{'session_passtimeoutdesc'},
&text('session_passtimeout',
&ui_textbox("passreset_timeout",
$gconfig{'passreset_timeout'}, 2)));
# Enable password change API?
$url = &get_webmin_browser_url("passwd", "change_passwd.cgi");
(undef, $found) = &acl::get_anonymous_access($password_change_path, \%miniserv);
print &ui_table_row($text{'session_passapi'},
&ui_radio("passapi", $found >= 0 ? 1 : 0,
[ [ 0, $text{'session_passapi0'}."<br>" ],
[ 1, $text{'session_passapi1'} . "&nbsp;" .
&ui_help(&text('session_passurl', "<tt>$url</tt>")) ] ]));
# Log to syslog
eval "use Sys::Syslog qw(:DEFAULT setlogsock)";
if (!$@) {
print &ui_table_row($text{'session_syslog3'},
&ui_yesno_radio("syslog", $miniserv{'syslog'}));
}
else {
print ui_hidden('syslog', $miniserv{'syslog'});
}
# Session authentication (on by default)
if (!$miniserv{'session'}) {
print &ui_table_row($text{'session_stype'},
&ui_radio("session", $miniserv{'session'} ? 1 : 0,
[ [ 0, $text{'session_disable'}."<br>" ],
[ 1, $text{'session_enable'} ] ]));
}
# Session auth options
print &ui_table_row($text{'session_sopts'},
&ui_checkbox("logouttime_on", 1,
&text('session_logouttime',
&ui_textbox("logouttime", $miniserv{'logouttime'}, 3)),
$miniserv{'logouttime'} ? 1 : 0).
"<br>\n".
&ui_checkbox("remember", 1, $text{'session_remember'},
$gconfig{'noremember'} ? 0 : 1).
"<br>\n".
&ui_checkbox("realname", 1, $text{'session_realname'},
$gconfig{'realname'} ? 1 : 0).
"<br>\n".
&ui_checkbox("session_ip", 1, $text{'session_ip'},
$miniserv{'session_ip'} ? 1 : 0).
"<br>\n".
&ui_checkbox("utmp", 1, $text{'session_utmp'},
$miniserv{'utmp'} ? 1 : 0));
# Pre-login banner
print &ui_table_row($text{'session_banner'},
&ui_radio("banner_def", $gconfig{'loginbanner'} ? 0 : 1,
[ [ 1, $text{'session_banner1'}."<br>" ],
[ 0, $text{'session_banner0'} ] ]).
&ui_filebox("banner", $gconfig{'loginbanner'}, 50));
# Local authentication (deprecated)
if ($miniserv{'localauth'}) {
print &ui_table_row($text{'session_local'},
&ui_radio("localauth", $miniserv{'localauth'} ? 1 : 0,
[ [ 0, $text{'session_localoff'}."<br>" ],
[ 1, $text{'session_localon'} ] ]));
}
# Use PAM or shadow file?
print &ui_table_row($text{'session_pam'},
&ui_radio("no_pam", $miniserv{'no_pam'} ? 1 : 0,
[ [ 0, $text{'session_pamon'}."<br>" ],
[ 1, $text{'session_pamoff'} ] ]));
print &ui_table_row($text{'session_popts'},
ui_checkbox("pam_conv", 1, $text{'session_pamconv'},
$miniserv{'pam_conv'}).
"<br>".
ui_checkbox("pam_end", 1, $text{'session_pamend'},
$miniserv{'pam_end'}).
"<br>\n".
&text('session_pfile',
&ui_textbox("passwd_file", $miniserv{'passwd_file'}, 12),
&ui_textbox("passwd_uindex", $miniserv{'passwd_uindex'}, 2),
&ui_textbox("passwd_pindex", $miniserv{'passwd_pindex'}, 2)));
# Unix password change
print &ui_table_row($text{'session_cmddef'},
&ui_oneradio("cmd_def", 1, $text{'session_cmddef1'},
!$gconfig{'passwd_cmd'}).
"<br>".
&ui_oneradio("cmd_def", 0, $text{'session_cmddef0'},
$gconfig{'passwd_cmd'}).
" ".
&ui_textbox("cmd", $gconfig{'passwd_cmd'}, 60));
# Password expiry policy
print &ui_table_row($text{'session_pmodedesc3'},
&ui_radio("passwd_mode", $miniserv{'passwd_mode'} || 0,
[ [ 0, $text{'session_pmode0'}."<br>" ],
[ 1, $text{'session_pmode1'}."<br>" ],
[ 2, $text{'session_pmode2'} ] ]));
# Squid-style authentication program (deprecated)
if ($miniserv{'extauth'}) {
print &ui_table_row($text{'session_extauth'},
&ui_textbox("extauth", $miniserv{'extauth'}, 60));
}
# Password encryption format
print &ui_table_row($text{'session_md5'},
&ui_radio("md5pass", $gconfig{'md5pass'} || 0,
[ [ 0, $text{'session_md5off'}."<br>" ],
[ 1, $text{'session_md5on'}."<br>" ],
[ 2, $text{'session_sha512'}."<br>" ],
[ 3, $text{'session_yescrypt'} ] ]));
# RPC timeout
print &ui_table_row(&hlink($text{'session_rpc_timeout'}, 'rpc_timeout'),
&ui_textbox("rpc_timeout", $gconfig{'rpc_timeout'} || 60, 3).
" ".$text{'time_seconds'});
print ui_table_end();
print ui_form_end([ [ "save", $text{'save'} ] ]);
ui_print_footer("", $text{'index_return'});
+442
View File
@@ -0,0 +1,442 @@
#!/usr/bin/perl
# Webserver SSL form
use strict;
use warnings;
no warnings 'redefine';
no warnings 'uninitialized';
require "./webmin-lib.pl";
# Globals
our %text;
our %miniserv;
our %in;
our $config_directory;
our $module_name;
our $strong_ssl_ciphers;
our $pfs_ssl_ciphers;
our $info;
our $root_directory;
our %config;
our $letsencrypt_cmd;
ui_print_header(undef, $text{'ssl_title'}, "");
ReadParse();
get_miniserv_config(\%miniserv);
# Check if we even *have* SSL support
$@ = undef;
eval "use Net::SSLeay";
if ($@) {
print text('ssl_essl', "https://webmin.com/ssl.html"),"<p>\n";
if (foreign_available("cpan")) {
print text('ssl_cpan', "../cpan/download.cgi?source=3&cpan=Net::SSLeay&mode=2&return=/$module_name/&returndesc=".urlize($text{'index_return'})),"<p>\n";
}
my $err = $@;
$err =~ s/\s+at.*line\s+\d+[\000-\377]*$//;
print text('ssl_emessage', "<tt>$err</tt>"),"<p>\n";
ui_print_footer("", $text{'index_return'});
exit;
}
# Show tabs
my @tabs = map { [ $_, $text{'ssl_tab'.$_}, "edit_ssl.cgi?mode=$_" ] }
( "ssl", "current", "ips", "create", "csr", "upload", "lets" );
print ui_tabs_start(\@tabs, "mode", $in{'mode'} || $tabs[0]->[0], 1);
# Basic SSL settings
print ui_tabs_start_tab("mode", "ssl");
print $text{'ssl_desc1'},"<p>\n";
print ui_form_start("change_ssl.cgi", "post");
print ui_table_start($text{'ssl_header'}, undef, 2);
print ui_table_row($text{'ssl_on'},
ui_yesno_radio("ssl", $miniserv{'ssl'}));
print ui_table_row($text{'ssl_enforce'},
ui_radio("ssl_enforce", $miniserv{'ssl_enforce'} // 1,
[ [ 2, $text{'ssl_hsts'} ],
[ 1, $text{'yes'} ],
[ 0, $text{'no'} ] ]));
print ui_table_row($text{'ssl_key'},
ui_textbox("key", $miniserv{'keyfile'}, 40)." ".
file_chooser_button("key"));
print ui_table_row($text{'ssl_cert'},
ui_opt_textbox("cert", $miniserv{'certfile'}, 40,
$text{'ssl_cert_def'}."<br>",$text{'ssl_cert_oth'})." ".
file_chooser_button("cert"));
print ui_table_row($text{'ssl_version'},
ui_opt_textbox("version", $miniserv{'ssl_version'}, 4,
$text{'ssl_auto'}));
print ui_table_row($text{'ssl_deny'},
ui_checkbox("no_ssl2", 1, "SSLv2", $miniserv{'no_ssl2'})."\n".
ui_checkbox("no_ssl3", 1, "SSLv3", $miniserv{'no_ssl3'})."\n".
ui_checkbox("no_tls1", 1, "TLSv1.0", $miniserv{'no_tls1'})."\n".
ui_checkbox("no_tls1_1", 1, "TLSv1.1", $miniserv{'no_tls1_1'})."\n".
ui_checkbox("no_tls1_2", 1, "TLSv1.2", $miniserv{'no_tls1_2'})."\n"
);
print ui_table_row($text{'ssl_compression'},
ui_yesno_radio("ssl_compression", !$miniserv{'no_sslcompression'}));
print ui_table_row($text{'ssl_honorcipherorder'},
ui_yesno_radio("ssl_honorcipherorder",
$miniserv{'ssl_honorcipherorder'}));
my $clist = $miniserv{'ssl_cipher_list'};
my $clist_def = $miniserv{'cipher_list_def'};
my $cmode = !$clist ? 1 :
($clist_def && $clist eq $strong_ssl_ciphers) ? 2 :
($clist_def && $clist eq $pfs_ssl_ciphers) ? 3 :
0;
print ui_table_row($text{'ssl_cipher_list'},
ui_radio("cipher_list_def", $cmode,
[ [ 1, $text{'ssl_auto'}."<br>" ],
[ 2, $text{'ssl_strong'}."<br>" ],
[ 3, $text{'ssl_pfs'}."<br>" ],
[ 0, $text{'ssl_clist'}." ".
ui_textbox("cipher_list",
$cmode == 0 ? $clist : "", 50) ] ]));
my $extracas;
if (defined $miniserv{'extracas'}) { $extracas = $miniserv{'extracas'}; }
else { $extracas = ""; }
print ui_table_row($text{'ssl_extracas'},
ui_textarea("extracas", join("\n",split(/\s+/, $extracas)),
3, 60)." ".
"<br>".file_chooser_button("extracas", 0, undef, undef, 1)."<p><br><p>");
print ui_table_end();
print ui_form_end([ [ "", $text{'save'} ] ]);
print ui_tabs_end_tab();
# Page showing current cert
print ui_tabs_start_tab("mode", "current");
print "$text{'ssl_current'}<p>\n";
print ui_table_start($text{'ssl_cheader'}, undef, 4);
$info = &cert_info($miniserv{'certfile'} || $miniserv{'keyfile'});
foreach my $i ('cn', 'alt', 'o', 'email', 'issuer_cn', 'issuer_o',
'issuer_email', 'notafter', 'type') {
if ($info->{$i}) {
print ui_table_row($text{'ca_'.$i},
ref($info->{$i}) ? join(", ", @{$info->{$i}})
: $info->{$i});
}
}
my @clinks = (
ui_link("download_cert.cgi/cert.pem", $text{'ssl_pem'}),
ui_link("download_cert.cgi/cert.p12", $text{'ssl_pkcs12'})
);
print ui_table_row($text{'ssl_download'}, &ui_links_row(\@clinks));
print ui_table_end();
print ui_tabs_end_tab();
# Table listing per-IP / domain SSL certs
print ui_tabs_start_tab("mode", "ips");
print "$text{'ssl_ipkeys'}<p>\n";
my @ipkeys = get_ipkeys(\%miniserv);
if (@ipkeys) {
print ui_columns_start([ $text{'ssl_ips'},
$text{'ssl_key'},
$text{'ssl_cert'} ]);
foreach my $k (@ipkeys) {
print ui_columns_row([
ui_link("edit_ipkey.cgi?idx=".$k->{'index'},
join(", ", @{$k->{'ips'}}) ),
"<tt>$k->{'key'}</tt>",
$k->{'cert'} ? "<tt>$k->{'cert'}</tt>"
: $text{'ssl_cert_def'},
]);
}
print ui_columns_end();
}
else {
print "<b>$text{'ssl_ipkeynone'}</b><p>\n";
}
print ui_link("edit_ipkey.cgi?new=1", $text{'ssl_addipkey'});
print "<p>\n";
print ui_tabs_end_tab();
# SSL key generation form
print ui_tabs_start_tab("mode", "create");
print "$text{'ssl_newkey'}<p>\n";
my $curkey = read_file_contents($miniserv{'keyfile'});
my $origkey = read_file_contents("$root_directory/miniserv.pem");
if ($curkey eq $origkey) {
# System is using the original (insecure) Webmin key!
print "<b>$text{'ssl_hole'}</b><p>\n";
}
print ui_form_start("newkey.cgi");
print ui_table_start($text{'ssl_header1'}, undef, 2);
my $host = $ENV{'HTTP_HOST'};
$host =~ s/:.*//;
print show_ssl_key_form($host, undef,
"Webmin Webserver on ".get_system_hostname());
print ui_table_row($text{'ssl_newfile'},
ui_textbox("newfile", "$config_directory/miniserv.pem", 40));
print ui_table_row($text{'ssl_usenew'},
ui_yesno_radio("usenew", 1));
print ui_table_end();
print ui_form_end([ [ "", $text{'ssl_create'} ] ]);
print ui_tabs_end_tab();
# SSL CSR generation form
my $keydata = read_file_contents("$config_directory/miniserv.newkey");
my $csrdata = read_file_contents("$config_directory/miniserv.csr");
print ui_tabs_start_tab("mode", "csr");
print "$text{'ssl_newcsr'}<p>\n";
print ui_form_start("newcsr.cgi");
print ui_table_start($text{'ssl_header2'}, undef, 2);
print show_ssl_key_form($host, undef,
"Webmin Webserver on ".get_system_hostname());
print ui_table_row($text{'ssl_newfile'},
ui_textbox("newfile", "$config_directory/miniserv.newkey", 40));
print ui_table_row($text{'ssl_csrfile'},
ui_textbox("csrfile", "$config_directory/miniserv.csr", 40));
print ui_table_end();
print ui_form_end([ [ "", $text{'ssl_create'} ] ]);
if ($keydata) {
# Show most recent CSR and key
print "<p>\n";
print ui_hidden_start($text{'ssl_csralready'}, "already", 0);
print $text{'ssl_already1'},"<p>\n";
print "<pre>".html_escape($keydata)."</pre>\n";
print $text{'ssl_already2'},"<p>\n";
print "<pre>".html_escape($csrdata)."</pre>\n";
print ui_hidden_end("already");
}
print ui_tabs_end_tab();
# SSL key upload form
print ui_tabs_start_tab("mode", "upload");
print "$text{'ssl_savekey'}<p>\n";
print ui_form_start("savekey.cgi", "form-data");
print ui_table_start($text{'ssl_saveheader'}, undef, 2);
print ui_table_row($text{'ssl_privkey'},
ui_textarea("key", $keydata, 7, 70)."<br>\n".
"<b>$text{'ssl_upload'}</b>\n".
ui_upload("keyfile").
($keydata ? "<br>".$text{'ssl_fromcsr'} : ""));
print ui_table_row($text{'ssl_privcert'},
ui_radio("cert_def", 1,
[ [ 1, $text{'ssl_same'} ],
[ 0, $text{'ssl_below'} ] ])."<br>\n".
ui_textarea("cert", undef, 7, 70)."<br>\n".
"<b>$text{'ssl_upload'}</b>\n".
ui_upload("certfile", undef, undef,
"onChange='form.cert_def.value = 0'"));
print ui_table_row($text{'ssl_privchain'},
ui_radio("chain_def", 1,
[ [ 1, $miniserv{'extracas'} ? $text{'ssl_leavechain'}
: $text{'ssl_nochain'} ],
[ 0, $text{'ssl_below'} ] ])."<br>\n".
ui_textarea("chain", undef, 7, 70)."<br>\n".
"<b>$text{'ssl_upload'}</b>\n".
ui_upload("chainfile", undef, undef,
"onChange='form.chain_def.value = 0'"));
print ui_table_end();
print ui_form_end([ [ "save", $text{'save'} ] ]);
print ui_tabs_end_tab();
# Let's Encrypt form
print ui_tabs_start_tab("mode", "lets");
my $err = &check_letsencrypt();
print $text{'ssl_letsdesc'};
if (!$err) {
print &ui_tag('span',
&ui_details({
'class' => 'inline inlined',
'title' => '',
'content' => $text{'ssl_letsdesc2'},
}))."\n".
&ui_tag('style',
".ui--span>details.inline>summary+span {\n".
"margin-top: 0;\n".
"}\n");
}
print "<p>\n";
if ($err) {
print "<b>",&text('ssl_letserr', $err),"</b><p>\n";
print &get_letsencrypt_install_message(
"/$module_name/edit_ssl.cgi?mode=lets", $text{'ssl_title'});
print "<p>\n";
print &text('ssl_letserr2', "../config.cgi?$module_name"),"<p>\n";
}
else {
# Show form to create a cert
print &ui_form_start("letsencrypt.cgi");
print &ui_table_start($text{'ssl_letsheader'}, undef, 2);
# For domain names
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)."<br>\n".
&ui_checkbox("subset", 1, $text{'ssl_subset'},
$config{'letsencrypt_subset'}));
# Apache vhost or other path
my @opts;
my $certbot_by_webmin = $letsencrypt_cmd
? &is_webmin_listening_on_port(80)
: 0;
my $certbot_warning = $letsencrypt_cmd
? &get_letsencrypt_certbot_port_error()
: undef;
my $webroot = $config{'letsencrypt_webroot'};
my $hasapache = &foreign_installed("apache");
my $saved_mode = $config{'letsencrypt_mode'} || "web";
my $mode = $saved_mode eq 'dns' ? 3 :
$saved_mode eq 'certbot' ? 4 :
$webroot ? 2 :
$hasapache ? 0 :
$letsencrypt_cmd ? 4 : 2;
if ($hasapache) {
&foreign_require("apache");
my $conf = &apache::get_config();
my @snames;
foreach my $virt (&apache::find_directive_struct(
"VirtualHost", $conf)) {
my $sn = &apache::find_directive(
"ServerName", $virt->{'members'});
push(@snames, [ $sn,
$sn || "&lt;".$text{'default'}."&gt;" ]);
}
my %done;
@snames = grep { !$done{$_->[0]}++ } @snames;
if (@snames) {
@snames = sort { $a->[0] cmp $b->[0] } @snames;
push(@opts, [ 0, $text{'ssl_letsmode0'} ]);
push(@opts, [ 1, $text{'ssl_letsmode1'},
&ui_select("vhost", undef, \@snames) ]);
}
else {
$webroot ||= &apache::find_directive("DocumentRoot", $conf);
}
}
push(@opts, [ 2, $text{'ssl_letsmode2'},
&ui_textbox("webroot", $webroot, 40) ]);
if ($letsencrypt_cmd && &foreign_installed("bind8")) {
push(@opts, [ 3, $text{'ssl_letsmode3'} ]);
}
if ($letsencrypt_cmd) {
push(@opts, [ 4, $text{'ssl_letsmode4'} ]);
}
my $mode_html = &ui_radio_table("webroot_mode", $mode, \@opts);
if ($certbot_warning) {
# Keep the warning aligned with the validation options (hacky as
# we have no API for this yet)
$certbot_warning .= " ".$text{'ssl_certbotprehook'}
if (!$certbot_by_webmin && $config{'letsencrypt_before'});
my $warning_note = &ui_note($certbot_warning, 0);
my $warning_html =
"<tr><td colspan='2'>".
&ui_tag('div', $warning_note,
{ 'style' => 'padding-left: 19px; '.
'margin-top: -8px !important' }).
"</td></tr>\n";
$mode_html =~ s#</table>\s*$#$warning_html</table>#;
}
print &ui_table_row($text{'ssl_letsmode'},
$mode_html);
# Install in Webmin now?
print &ui_table_row($text{'ssl_usewebmin'},
&ui_yesno_radio("use", !$config{'letsencrypt_nouse'}));
# SSL key size
print &ui_table_row($text{'ssl_size'},
&ui_opt_textbox("size", undef, 6, $text{'default'}).
" ".$text{'ssl_bits'});
# Staging mode
print &ui_table_row($text{'ssl_staging'},
&ui_radio("staging", 0,
[ [ 0, $text{'ssl_staging0'} ],
[ 1, $text{'ssl_staging1'} ] ]));
my $acme_extra = &ui_table_start(undef, undef, 2);
$acme_extra .= &ui_table_row($text{'ssl_acmedir'},
&ui_textbox("directory_url",
$config{'letsencrypt_directory_url'}, 60)."<br>\n".
&ui_note($text{'ssl_acmedirdesc'}, 0));
$acme_extra .= &ui_table_row($text{'ssl_acmekid'},
&ui_textbox("eab_kid",
$config{'letsencrypt_eab_kid'}, 40)."<br>\n".
&ui_note($text{'ssl_acmekiddesc'}, 0));
$acme_extra .= &ui_table_row($text{'ssl_acmehmac'},
&ui_password("eab_hmac",
$config{'letsencrypt_eab_hmac'}, 50)."<br>\n".
&ui_note($text{'ssl_acmehmacdesc'}, 0));
$acme_extra .= &ui_table_end();
print &ui_table_row($text{'ssl_acmeopts'},
&ui_details({
'class' => 'inline inlined',
'html' => 1,
'title' => $text{'ssl_acmeextra'},
'content' => $acme_extra,
})."\n".
&ui_tag('style',
"tr>td>details.inline>summary+span {\n".
"margin-left: 0;\n".
"}\n"));
# Renewal option
my $job = &find_letsencrypt_cron_job();
my $has_ip_doms = &letsencrypt_doms_have_ips(\@doms);
my $renew_unit = $has_ip_doms ? "days" :
($config{'letsencrypt_renew_unit'} || "months");
my $renew;
if ($job && $renew_unit eq "days" && $job->{'interval'}) {
$renew = int($job->{'interval'} / (24*60*60));
}
elsif ($job && $job->{'months'} =~ /^\*\/(\d+)$/) {
$renew_unit = "months";
$renew = $1;
}
elsif ($job && $job->{'interval'}) {
$renew_unit = "months";
$renew = int($job->{'interval'} / (30*24*60*60));
}
my @renew_units = ( [ "months", $text{'ssl_letsrenew_months'} ],
[ "days", $text{'ssl_letsrenew_days'} ] );
my $renew_disabled = $renew eq '';
print &ui_table_row(&hlink($text{'ssl_letsrenew'}, "letsrenew"),
&ui_opt_textbox("renew", $renew, 4, $text{'ssl_letsnotrenew'},
undef, undef, [ "renew_unit" ])." ".
&ui_select("renew_unit", $renew_unit, \@renew_units,
undef, undef, undef, $renew_disabled));
print &ui_table_end();
print &ui_form_end([ [ undef, $text{'ssl_letsok'} ],
[ 'save', $text{'ssl_letsonly'} ] ]);
}
print ui_tabs_end_tab();
print ui_tabs_end(1);
ui_print_footer("", $text{'index_return'});
+45
View File
@@ -0,0 +1,45 @@
#!/usr/local/bin/perl
# edit_startpage.cgi
# Startpage config form
require './webmin-lib.pl';
&ui_print_header(undef, $text{'startpage_title'}, "");
print $text{'startpage_intro2'},"<p>\n";
print &ui_form_start("change_startpage.cgi", "post");
print &ui_table_start($text{'startpage_title'}, undef, 2);
print &ui_table_row($text{'startpage_nocol'},
&ui_opt_textbox("nocols", $gconfig{'nocols'}, 5, $text{'default'}));
print &ui_table_row($text{'startpage_tabs'},
&ui_radio("notabs", $gconfig{'notabs'} ? 1 : 0,
[ [ 0, $text{'yes'} ], [ 1, $text{'no'} ] ]));
@modules = &get_all_module_infos();
%cats = &list_categories(\@modules);
print &ui_table_row($text{'startpage_deftab'},
&ui_select("deftab", $gconfig{'deftab'} || 'webmin',
[ map { [ $_, $cats{$_} ] }
sort { $cats{$a} cmp $cats{$b} } (keys %cats) ]));
print &ui_table_row($text{'startpage_nohost'},
&ui_radio("nohostname", $gconfig{'nohostname'} ? 1 : 0,
[ [ 0, $text{'yes'} ], [ 1, $text{'no'} ] ]));
print &ui_table_row($text{'startpage_gotoone'},
&ui_yesno_radio("gotoone", int($gconfig{'gotoone'})));
print &ui_table_row($text{'startpage_gotomodule'},
&ui_select("gotomodule", $gconfig{'gotomodule'},
[ [ "", $text{'startpage_gotonone'} ],
map { [ $_->{'dir'}, $_->{'desc'} ] }
sort { $a->{'desc'} cmp $b->{'desc'} }
grep { !$_->{'hidden'} && !$_->{'webmin_hidden'} } @modules ]));
print &ui_table_end();
print &ui_form_end([ [ "", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+40
View File
@@ -0,0 +1,40 @@
#!/usr/local/bin/perl
# Display status collection options
require './webmin-lib.pl';
&foreign_require("system-status");
&ui_print_header(undef, $text{'status_title'}, "");
print &ui_form_start("change_status.cgi", "post");
print &ui_table_start($text{'status_header'}, undef, 2);
# Status collection enabled and gap
$i = $system_status::config{'collect_interval'};
print &ui_table_row($text{'status_interval'},
&ui_opt_textbox("interval", $i eq 'none' ? undef : $i, 5,
$text{'status_interval1'}, $text{'status_interval0'}).
" ".$text{'status_mins'});
# Collect packages?
print &ui_table_row($text{'status_pkgs'},
&ui_yesno_radio("pkgs", $system_status::config{'collect_pkgs'}));
# Collect CPU temerature?
print &ui_table_row($text{'status_temp2'},
&ui_yesno_radio("temp2", !$system_status::config{'collect_notemp2'}));
# Collect drive temps?
print &ui_table_row($text{'status_temp'},
&ui_yesno_radio("temp", !$system_status::config{'collect_notemp'}));
# Units for temps
print &ui_table_row($text{'status_units'},
&ui_radio("units", $system_status::config{'collect_units'} || 0,
[ [ 0, $text{'status_celsius'} ],
[ 1, $text{'status_fahrenheit'} ] ]));
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+128
View File
@@ -0,0 +1,128 @@
#!/usr/local/bin/perl
# edit_themes.cgi
# Display all themes, and allow installation of a new one
require './webmin-lib.pl';
&ReadParse();
&ui_print_header(undef, $text{'themes_title'}, "");
($gtheme, $goverlay) = split(/\s+/, $gconfig{'theme'});
@all = &list_visible_themes($gtheme);
@themes = grep { !$_->{'overlay'} } @all;
@overlays = grep { $_->{'overlay'} } @all;
$prog = "edit_themes.cgi?mode=";
$curr_theme_selected = $gconfig{"theme_$base_remote_user"} || $gtheme;
($curr_theme) = grep { $_->{'dir'} eq $curr_theme_selected } @themes;
# Start tabs
if (@themes) {
@tabs = ( [ "change", $text{'themes_tabchange'}, $prog."change" ] );
}
if (@overlays) {
push(@tabs, [ "overlay", $text{'themes_taboverlay'}, $prog."overlay" ]);
}
if (!&shared_root_directory()) {
push(@tabs, [ "install", $text{'themes_tabinstall'}, $prog."install" ]);
}
if (!&shared_root_directory() && @all) {
push(@tabs, [ "delete", $text{'themes_tabdelete'}, $prog."delete" ]);
}
if (@themes || @overlays) {
push(@tabs, [ "export", $text{'themes_tabexport'}, $prog."export" ] );
}
print &ui_tabs_start(\@tabs, "mode", $in{'mode'} || $tabs[0]->[0], 1);
# Display theme change form
if (@themes) {
print &ui_tabs_start_tab("mode", "change");
print "$text{'themes_desc'}<p>\n";
print &ui_form_start("change_theme.cgi");
print "<b>$text{'themes_sel'}</b>&nbsp;&nbsp;\n";
print &ui_select("theme", $gtheme,
[ !$gtheme ? [ '', $text{'themes_default'} ] : (),
map { [ $_->{'dir'}, $_->{'desc'} ] } @themes ]);
if ($curr_theme->{'config_link'} &&
$gtheme eq $curr_theme->{'dir'}) {
print &ui_link(
"@{[&get_webprefix()]}/$curr_theme->{'config_link'}",
&ui_tag('span', '⚙',
{ class => 'theme-config-char',
title => $text{'themes_configure'} }),
'text-link');
}
print &ui_form_end([ [ undef, $text{'themes_change'} ] ]);
print &ui_tabs_end_tab("mode", "change");
}
# Display overlay change form
if (@overlays && $gtheme) {
print &ui_tabs_start_tab("mode", "overlay");
print "$text{'themes_overdesc'}<p>\n";
print &ui_form_start("change_overlay.cgi");
print "<b>$text{'themes_overlay'}</b>\n";
print &ui_select("overlay", $goverlay,
[ [ '', $text{'themes_none'} ],
map { [ $_->{'dir'}, $_->{'desc'} ] } @overlays ]),"<br>\n";
print &ui_form_end([ [ undef, $text{'themes_change'} ] ]);
print &ui_tabs_end_tab("mode", "overlay");
}
if (!&shared_root_directory()) {
# Display install form
print &ui_tabs_start_tab("mode", "install");
print "$text{'themes_installdesc'}<p>\n";
print &ui_form_start("install_theme.cgi", "form-data");
print &ui_table_start(undef, undef, 2);
print &ui_table_row($text{'mods_installsource'},
&ui_radio_table("source", 0,
[ [ 0, $text{'mods_local'}, &ui_filebox("file", undef ,40) ],
[ 1, $text{'mods_uploaded'}, &ui_upload("upload") ],
[ 2, $text{'mods_ftp'}, &ui_textbox("url", undef, 40) ] ]));
print &ui_table_row($text{'mods_checksig'},
&ui_yesno_radio("checksig", 0));
print &ui_table_end();
print &ui_form_end([ [ undef, $text{'themes_installok'} ] ]);
print &ui_tabs_end_tab("mode", "install");
}
if (!&shared_root_directory() && @all) {
# Display deletion form
print &ui_tabs_start_tab("mode", "delete");
print "$text{'themes_delete'}<p>\n";
print &ui_form_start("delete_mod.cgi");
print "<b>$text{'themes_delok'}</b>&nbsp;&nbsp;\n";
print &ui_select("mod", undef,
[ map { [ $_->{'dir'}, $_->{'desc'} ] } @all ]),"<br>\n";
print &ui_form_end([ [ undef, $text{'delete'} ] ]);
print &ui_tabs_end_tab("mode", "delete");
}
# Display export form
print &ui_tabs_start_tab("mode", "export");
print "$text{'themes_desc4'}<p>\n";
print &ui_form_start("export_mod.cgi/theme.wbt.gz");
print &ui_table_start(undef, undef, 2);
print &ui_table_row($text{'themes_exportmods'},
&ui_select("mod", undef,
[ map { [ $_->{'dir'}, $_->{'desc'} ] } @themes ], 5, 1));
print &ui_table_row($text{'mods_exportto'},
&ui_radio("to", 0,
[ [ 0, $text{'mods_exportshow'}."<br>" ],
[ 1, &text('mods_exportfile',
&ui_textbox("file", undef, 40)) ] ]));
print &ui_table_end();
print &ui_form_end([ [ "ok", $text{'themes_exportok'} ] ]);
print &ui_tabs_end_tab("mode", "export");
print &ui_tabs_end(1);
&ui_print_footer("", $text{'index_return'});
+52
View File
@@ -0,0 +1,52 @@
#!/usr/local/bin/perl
# Show two-factor authentication options
require './webmin-lib.pl';
ui_print_header(undef, $text{'twofactor_title'}, "", "twofactor");
get_miniserv_config(\%miniserv);
$miniserv{'session'} || &error($text{'twofactor_esession'});
print "$text{'twofactor_desc'}<p>\n";
print <<EOF;
<style>
.opener_shown {display:inline}
.opener_hidden {display:none}
</style>
EOF
@provs = &list_twofactor_providers();
print "<script>\n";
print "function show_prov(name) {\n";
foreach $p (@provs) {
print "d = document.getElementById(\"hiddendiv_$p->[0]\");\n";
print "d && (d.className = name == \"$p->[0]\" ? \"opener_shown\" : \"opener_hidden\");\n";
}
print "}\n";
print "</script>\n";
print ui_form_start("change_twofactor.cgi", "post");
print ui_table_start($text{'twofactor_header'}, undef, 2);
# Two-factor provider
print ui_table_row($text{'twofactor_provider'},
ui_select("twofactor_provider", $miniserv{'twofactor_provider'},
[ [ "", "&lt;".$text{'twofactor_none'}."&gt;" ],
map { [ $_->[0], $_->[1] ] } @provs ],
1, 0, 0, 0, "onChange='show_prov(value)'"), undef, [ "valign=middle","valign=middle" ]);
foreach $p (@provs) {
my $sfunc = "show_twofactor_apikey_".$p->[0];
if (defined(&$sfunc)) {
print &ui_hidden_table_row_start(undef, $p->[0],
$p->[0] eq $miniserv{'twofactor_provider'}, undef);
print &$sfunc(\%miniserv);
print &ui_hidden_table_row_end($p->[0]);
}
}
print ui_table_end();
print ui_form_end([ [ "save", $text{'save'} ] ]);
ui_print_footer("", $text{'index_return'});
+68
View File
@@ -0,0 +1,68 @@
#!/usr/local/bin/perl
# edit_ui.cgi
# Edit user interface options
require './webmin-lib.pl';
&ui_print_header(undef, $text{'ui_title'}, "");
print $text{'ui_desc'},"<p>\n";
print &ui_form_start("change_ui.cgi", "post");
print &ui_table_start($text{'ui_header'}, undef, 2);
for($i=0; $i<@cs_names; $i++) {
$cd = $cs_codes[$i];
print &ui_table_row($cs_names[$i],
&ui_opt_textbox($cd, $gconfig{$cd}, 8, $text{'ui_default'},
$text{'ui_rgb'}), undef, [ "valign=middle","valign=middle" ]);
}
print &ui_table_row($text{'ui_sysinfo'},
&ui_select("sysinfo", int($gconfig{'sysinfo'}),
[ map { [ $_, $text{'ui_sysinfo'.$_} ] } (0, 1, 4, 2, 3) ]), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ui_hostnamemode'},
&ui_select("hostnamemode", int($gconfig{'hostnamemode'}),
[ map { [ $_, $text{'ui_hnm'.$_} ] } (0 .. 3) ]).
" ".&ui_textbox("hostnamedisplay", $gconfig{'hostnamedisplay'}, 20), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ui_showlogin'},
&ui_yesno_radio("showlogin", int($gconfig{'showlogin'})), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ui_showhost'},
&ui_yesno_radio("showhost", int($gconfig{'showhost'})), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ui_feedback'},
&ui_opt_textbox("feedback", $gconfig{'feedback_to'}, 20,
$webmin_feedback_address), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ui_feedbackmode'},
&ui_radio("nofeedbackcc", int($gconfig{'nofeedbackcc'}),
[ [ 0, $text{'yes'} ], [ 1, $text{'ui_feednocc'} ],
[ 2, $text{'no'} ] ]), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ui_width'},
&ui_opt_textbox("width", $gconfig{'help_width'}, 5,
"$text{'default'} (400)"), undef, [ "valign=middle","valign=middle" ]);
print &ui_table_row($text{'ui_height'},
&ui_opt_textbox("height", $gconfig{'help_height'}, 5,
"$text{'default'} (400)"), undef, [ "valign=middle","valign=middle" ]);
# Dialog box size options
print &ui_table_hr();
foreach $db ("file", "user", "users", "date", "module", "modules") {
($w, $h) = split(/x/, $gconfig{'db_size'.$db});
print &ui_table_row($text{'ui_size'.$db},
&ui_radio("size".$db."_def", $w ? 0 : 1,
[ [ 1, $text{'default'} ],
[ 0, &ui_textbox("size".$db."_w", $w, 4)." X ".
&ui_textbox("size".$db."_h", $h, 4) ] ]), undef, [ "valign=middle","valign=middle" ]);
}
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+148
View File
@@ -0,0 +1,148 @@
#!/usr/local/bin/perl
# edit_upgrade.cgi
# Display a form for upgrading all of webmin from a tarfile
require './webmin-lib.pl';
&ReadParse();
&ui_print_header(undef, $text{'upgrade_title'}, "");
if (&shared_root_directory()) {
&ui_print_endpage($text{'upgrade_eroot'});
}
# what kind of install was this?
$mode = &get_install_type();
# was the install to a target directory?
if (open(DIR, "<$config_directory/install-dir")) {
chop($dir = <DIR>);
close(DIR);
}
if ($mode eq "solaris-pkg") {
$skip_upgrade = $text{'upgrade_esolaris'};
}
elsif ($mode eq "zip") {
$skip_upgrade = $text{'upgrade_ezip'};
}
elsif ($mode eq "portage") {
$skip_upgrade = $text{'upgrade_eportage'};
}
# Show tabs
@tabs = map { [ $_, $text{'upgrade_tab'.$_}, "edit_upgrade.cgi?mode=$_" ] }
( $skip_upgrade ? ( ) : ( "upgrade" ),
"grants", "update" );
print ui_tabs_start(\@tabs, "mode", $in{'mode'} || $tabs[0]->[0], 1);
if (!$skip_upgrade) {
# Display upgrade form
print ui_tabs_start_tab("mode", "upgrade");
print $text{"upgrade_desc$mode"},"<p>";
print ui_form_start("upgrade.cgi", "form-data");
print ui_hidden("mode", $mode);
print ui_hidden("dir", $dir);
print ui_table_start($text{'upgrade_title'}, undef, 1);
@opts = ( [ 0, $text{'upgrade_local'},
&ui_filebox("file", undef, 60) ],
[ 1, $text{'upgrade_uploaded'},
&ui_upload("upload") ],
[ 5, $text{'upgrade_url'},
&ui_textbox("url", undef, 60) ] );
if ($mode eq "gentoo") {
push(@opts, [ 4, $text{'upgrade_emerge'} ]);
}
elsif ($mode ne "sun-pkg") {
push(@opts, [ 2, $text{'upgrade_ftp'} ]);
}
($repotype, $repover) = &get_webmin_repo_version();
if ($repotype) {
push(@opts, [ 6, &text('upgrade_repo', uc($repotype)) ]);
}
print &ui_table_row($text{'upgrade_src'},
&ui_radio_table("source", $opts[$#opts]->[0], \@opts));
@cbs = ( );
if (!$mode && !$dir) {
# Checkbox to delete original directory
push(@cbs, &ui_checkbox("delete", 1, $text{'upgrade_delete'},
$gconfig{'upgrade_delete'}));
}
if ((!$mode || $mode eq "rpm") && &foreign_check("proc")) {
# Checkbox to check signature
($ec, $emsg) = &gnupg_setup();
push(@cbs, &ui_checkbox("sig", 1, $text{'upgrade_sig'}, $ec));
}
if (!$mode) {
# Checkbox to not install missing modules
push(@cbs, &ui_checkbox("only", 1, $text{'upgrade_only'},
-r "$root_directory/minimal-install"));
}
push(@cbs, &ui_checkbox("force", 1, $text{'upgrade_force'}, 0));
if ($main::session_id) {
# Checkbox to disconnect other sessions
push(@cbs, &ui_checkbox("disc", 1, $text{'upgrade_disc'}, 0));
}
print &ui_table_row($text{'upgrade_opts'},
join("<br>\n", @cbs));
print ui_table_end();
print &ui_form_end([ [ undef, $text{'upgrade_ok'} ] ]);
print ui_tabs_end_tab();
}
# Display new module grants form
print ui_tabs_start_tab("mode", "grants");
print "$text{'newmod_desc'}<p>\n";
print ui_form_start("save_newmod.cgi", "post");
print ui_table_start($text{'newmod_header'});
$newmod = &get_newmodule_users();
print &ui_table_row(undef,
&ui_opt_textbox("newmod", $newmod ? join(" ", @$newmod) : "", 60,
$text{'newmod_def'}."<br>\n",
$text{'newmod_users'}), 2);
print ui_table_end();
print ui_form_end([ [ undef, $text{'save'} ] ]);
print ui_tabs_end_tab();
# Display module update form
print ui_tabs_start_tab("mode", "update");
print "$text{'update_desc1'}<p>\n";
print ui_form_start("update.cgi", "post");
print ui_table_start($text{'update_header1'}, undef, 2);
print &ui_table_row($text{'update_src'},
&ui_radio("source", $config{'upsource'} ? 1 : 0,
[ [ 0, $text{'update_webmin'}."<br>" ],
[ 1, $text{'update_other'} ] ])."<br>\n".
&ui_textarea("other", join("\n", split(/\t+/, $config{'upsource'})),
2, 50));
print &ui_table_row($text{'update_opts'},
&ui_checkbox("show", 1, $text{'update_show'},
$config{'upshow'}).
"<br>\n".
&ui_checkbox("missing", 1, $text{'update_missing'},
$config{'upmissing'}).
"<br>\n".
&ui_checkbox("third", 1, $text{'update_third'},
$config{'upthird'}).
"<br>\n".
&ui_checkbox("checksig", 1, $text{'update_checksig'},
$config{'upchecksig'}));
print &ui_table_row($text{'update_user'},
&ui_textbox("upuser", $config{'upuser'}, 30));
print &ui_table_row($text{'update_pass'},
&ui_password("uppass", $config{'uppass'}, 30));
print ui_table_end();
print ui_form_end([ [ undef, $text{'update_ok'} ] ]);
print ui_tabs_end_tab();
print &ui_tabs_end(1);
&ui_print_footer("", $text{'index_return'});
+87
View File
@@ -0,0 +1,87 @@
#!/usr/local/bin/perl
# Show the web serving options form
require './webmin-lib.pl';
&ui_print_header(undef, $text{'web_title'}, "");
&get_miniserv_config(\%miniserv);
print &ui_form_start("change_web.cgi", "post");
print &ui_table_start($text{'web_header'}, undef, 2);
# Default content expiry time
print &ui_table_row($text{'web_expires'},
&ui_opt_textbox("expires", $miniserv{'expires'}, 10,
$text{'web_expiresdef'}, $text{'web_expiressecs'}), undef);
# Additional expiry times based on path
my @expires_paths;
foreach my $pe (split(/\t+/, $miniserv{'expires_paths'})) {
my ($p, $e) = split(/=/, $pe);
if ($p && $e ne '') {
push(@expires_paths, [ $p, $e ]);
}
}
push(@expires_paths, [ undef, $miniserv{'expires'} || 86400 ]);
my $etable = &ui_columns_start([ $text{'web_expirespath'},
$text{'web_expirestime'} ]);
for(my $i=0; $i<@expires_paths; $i++) {
$etable .= &ui_columns_row([
&ui_textbox("expirespath_$i", $expires_paths[$i]->[0], 40),
&ui_textbox("expirestime_$i", $expires_paths[$i]->[1], 10),
]);
}
$etable .= &ui_columns_end();
print &ui_table_row($text{'web_expirespaths'}, $etable);
# Display redirects
my $rtable = &ui_columns_start([ $text{'web_redirhost'},
$text{'web_redirport'},
$text{'web_redirpref'},
$text{'web_redirssl'} ], 'auto');
$rtable .= &ui_columns_row([
&ui_textbox('redirect_host', $miniserv{'redirect_host'}, 30),
&ui_textbox('redirect_port', $miniserv{'redirect_port'}, 5),
&ui_textbox('redirect_prefix', $miniserv{'redirect_prefix'}, 10),
&ui_checkbox("redirect_ssl", 1, $text{'redirect_ssl'},
$miniserv{'redirect_ssl'}),
], ['', '', '', ' style="text-align: center"']);
$rtable .= &ui_columns_end();
print &ui_table_row($text{'web_redirdesc'}, $rtable);
# Show call stack on error
print &ui_table_row($text{'advanced_stack'},
&ui_yesno_radio("stack", int($gconfig{'error_stack'})), undef);
# Show CGI errors
print &ui_table_row($text{'advanced_showstderr'},
&ui_yesno_radio("showstderr", int(!$miniserv{'noshowstderr'})), undef);
if (!$miniserv{'session'}) {
# Pass passwords to CGI programs
print &ui_table_row($text{'advanced_pass_desc'},
&ui_yesno_radio("pass", int($miniserv{'pass_password'})).
&ui_help($text{'advanced_pass_help'}), undef);
}
# Gzip static files?
print &ui_table_row($text{'advanced_gzip'},
&ui_radio("gzip", $miniserv{'gzip'},
[ [ '', $text{'advanced_gzipauto'} ],
[ 0, $text{'advanced_gzip0'} ],
[ 1, $text{'advanced_gzip1'} ] ]), undef);
# Redirect type
print &ui_table_row($text{'advanced_redir'},
&ui_radio("redir", $gconfig{'relative_redir'} ? 1 : 0,
[ [ 1, $text{'advanced_redir1'} ],
[ 0, $text{'advanced_redir0'} ] ]), undef);
# Allow directory listing
print &ui_table_row($text{'advanced_listdir'},
&ui_yesno_radio("listdir", !$miniserv{'nolistdir'}));
print &ui_table_end();
print &ui_form_end([ [ "save", $text{'save'} ] ]);
&ui_print_footer("", $text{'index_return'});
+46
View File
@@ -0,0 +1,46 @@
#!/usr/local/bin/perl
# Show a list of Webmin cron jobs
require './webmin-lib.pl';
&ui_print_header(undef, $text{'webmincron_title'}, "");
if (!&foreign_check("webmincron")) {
&ui_print_endpage($text{'webmincron_emodule'});
}
&foreign_require("webmincron");
&foreign_require("cron");
my @wcrons = &webmincron::list_webmin_crons();
@wcrons = sort { $a->{'module'} cmp $b->{'module'} ||
$a->{'func'} cmp $b->{'func'} ||
join(" ", @{$a->{'args'}}) cmp join(" ", @{$b->{'args'}}) }
@wcrons;
if (@wcrons) {
my @tds = ( "width=5 valign=top", "valign=top", "valign=top", "valign=top" );
print &ui_form_start("delete_webmincron.cgi");
print &ui_columns_start([ "",
$text{'webmincron_module'},
$text{'webmincron_func'},
$text{'webmincron_args'},
$text{'webmincron_when'},
],
100, 0, \@tds);
foreach my $w (@wcrons) {
my %minfo = &get_module_info($w->{'module'});
print &ui_checked_columns_row([
&ui_link("view_webmincron.cgi?id=".$w->{'id'},
($minfo{'desc'} || $w->{'module'}) ),
$w->{'func'},
join(" ", @{$w->{'args'}}),
&cron::when_text($w, 1),
], \@tds, "d", $w->{'id'});
}
print &ui_columns_end();
print &ui_form_end([ [ "delete", $text{'webmincron_delete'} ],
[ "run", $text{'webmincron_run'} ] ]);
}
else {
print "<b>$text{'webmincron_none'}</b><p>\n";
}
&ui_print_footer("", $text{'index_return'});
+48
View File
@@ -0,0 +1,48 @@
#!/usr/local/bin/perl
# Create and output a wbm.gz file of selected modules
require './webmin-lib.pl';
&ReadParse();
&error_setup($text{'export_err'});
@mods = split(/\0/, $in{'mod'});
@mods || &error($text{'delete_enone'});
# Make sure we have the needed commands
&has_command("tar") || &error(&text('export_ecmd', "<tt>tar</tt>"));
&has_command("gzip") || &error(&text('export_ecmd', "<tt>gzip</tt>"));
$in{'to'} == 0 || $in{'file'} =~ /^\// || &error($text{'export_efile'});
# Make the tar.gz file
$temp = $in{'to'} ? $in{'file'} : &transname();
chdir(&module_root_directory($mods[0])."/..");
$cmd = "tar chf -";
foreach $m (@mods) {
$cmd .= " $m";
}
$cmd .= " | gzip -c >".quotemeta($temp);
$out = &backquote_logged("($cmd) 2>&1 </dev/null");
$? && &error("<pre>$out</pre>");
if ($in{'to'} == 0) {
# Output the file
print "Content-type: application/x-gzip\n\n";
open(TEMP, "<$temp");
my $buf;
my $bs = &get_buffer_size();
while(read(TEMP, $buf, $bs)) {
print $buf;
}
close(TEMP);
unlink($temp);
}
else {
# Tell the user
&ui_print_header(undef, $text{'export_title'}, "");
print &text('export_done', "<tt>$in{'file'}</tt>"),"<p>\n";
&ui_print_footer("/$module_name/edit_mods.cgi", $text{'mods_return'},
"", $text{'index_return'});
}
+11
View File
@@ -0,0 +1,11 @@
do 'webmin-lib.pl';
sub feedback_files
{
return ( "$config_directory/miniserv.conf",
"$config_directory/config" );
}
1;
+11
View File
@@ -0,0 +1,11 @@
#!/usr/local/bin/perl
# Set OS to automatically detected version
require './webmin-lib.pl';
&ReadParse();
%osinfo = &detect_operating_system();
&apply_new_os_version(\%osinfo);
&webmin_log("os");
&redirect(get_referer_relative());
+70
View File
@@ -0,0 +1,70 @@
#!/usr/local/bin/perl
# Fix the Webmin repository URL and key
require './webmin-lib.pl';
&ReadParse();
my $devkey = "$module_root_directory/developers-key.asc";
if (-r $webmin_yum_repo_file) {
# Fix up YUM repo
&lock_file($webmin_yum_repo_file);
my $lref = &read_file_lines($webmin_yum_repo_file);
foreach my $l (@$lref) {
if ($l =~ /^\s*baseurl\s*=\s*(\S+)/) {
$l = "baseurl=".$webmin_yum_repo_url;
}
elsif ($l =~ /^\s*mirrorlist\s*=\s*(\S+)/) {
$l = "mirrorlist=".$webmin_yum_repo_mirrorlist;
}
elsif ($l =~ /^\s*gpgkey\s*=\s*file:\/\/(\S+)/) {
&copy_source_dest($devkey, $webmin_yum_repo_key)
if (!-r $webmin_yum_repo_key);
$l = "gpgkey=file://".$webmin_yum_repo_key;
}
}
&flush_file_lines($webmin_yum_repo_file);
&unlock_file($webmin_yum_repo_file);
&system_logged("rpm --import $webmin_yum_repo_key >/dev/null 2>&1");
}
my $ffixed = 0;
foreach my $repo ($webmin_apt_repo_file, $global_apt_repo_file) {
# Fix APT repo
next if (!-r $repo);
&lock_file($repo);
my $lref = &read_file_lines($repo);
my $fixed = 0;
my $lreffix = sub {
my ($l) = @_;
if ($ffixed) {
return "";
}
else {
return $l;
}
};
foreach my $l (@$lref) {
if ($l =~ /^\s*deb\s+.*?((http|https):\/\/download.webmin.com\/download\/repository)\s+sarge\s+contrib/) {
$l = &$lreffix("deb [signed-by=$webmin_apt_repo_key] $webmin_apt_repo_url stable contrib");
$fixed++;
}
}
&flush_file_lines($repo);
&unlock_file($repo);
if ($fixed) {
$ffixed++;
}
}
if ($ffixed) {
# Put the new key into place
&system_logged("gpg --import $devkey >/dev/null 2>&1");
my ($asckey, $err);
my $ex = &execute_command("gpg --dearmor", $devkey, \$asckey, \$err);
&error(&html_escape($err)) if ($ex);
&lock_file($webmin_apt_repo_key);
&write_file_contents($webmin_apt_repo_key, $asckey);
&unlock_file($webmin_apt_repo_key);
}
&webmin_log("fixrepo");
&redirect(get_referer_relative());
+592
View File
@@ -0,0 +1,592 @@
# gnupg-lib.pl
# Functions for managing gnupg keys, signing, encrypting and so on
BEGIN { push(@INC, ".."); };
use strict;
use warnings;
no warnings 'redefine';
no warnings 'uninitialized';
use WebminCore;
our ($module_name, %config, $user_module_config_directory, %text);
if (!$module_name) {
# Only do this if we are the primary library for the usermin gnupg mod
&init_config();
&switch_to_remote_user();
&create_user_config_dirs();
}
&foreign_require("proc", "proc-lib.pl");
our $gpgpath = $config{'gpg'} || "gpg";
# list_keys()
# Returns an array of all GnuPG keys
sub list_keys
{
my (@rv, %kmap);
&clean_language();
open(GPG, "$gpgpath --list-keys 2>/dev/null |");
while(<GPG>) {
if (/^pub\s+([a-z0-9]+)(\s+)([\d]{4}-[\d]{2}-[\d]{2})/ ||
/^pub\s+(\S+)\/(\S+)\s+(\S+)\s+(.*)\s+<(\S+)>/ ||
/^pub\s+(\S+)\/(\S+)\s+(\S+)\s+(.*)/) {
my $k = { 'size' => $1,
'key' => $2,
'date' => $3,
'name' => &filter_javascript($4) ? [ &filter_javascript($4) ] : [ ],
'email' => &filter_javascript($5) ? [ &filter_javascript($5) ] : &filter_javascript($4) ? [ "" ] : [ ],
'index' => scalar(@rv) };
if ($k->{'name'}->[0] &&
$k->{'name'}->[0] =~ /\[(expires|expired):\s+(\S+)\]/) {
# Expiry date, the actual name
$k->{'expires'} = $2;
$k->{'expired'} = 1 if ($1 eq 'expired');
shift(@{$k->{'name'}});
}
$kmap{$k->{'key'}} = $k;
while(1) {
$_ = <GPG>;
last if ($_ !~ /\S/);
if (/^sub\s+(\S+)\/(\S+)\s+/) {
push(@{$k->{'key2'}}, $2);
}
elsif (/^uid\s+\[[^\]]+\]\s+(.*)\s+<(\S+)>/ ||
/^uid\s+(.*)\s+<(\S+)>/ ||
/^uid\s+(.*)/) {
push(@{$k->{'name'}}, &filter_javascript($1));
push(@{$k->{'email'}}, &filter_javascript($2));
}
elsif (/^\s+([A-F0-9]{0,40})/) {
$k->{'key'} = $1;
$kmap{$1} = $k;
}
}
push(@rv, $k);
}
}
close(GPG);
open(GPG, "$gpgpath --list-secret-keys 2>/dev/null |");
while(<GPG>) {
if ((/^sec\s+(\S+)\/(\S+)\s+(\S+)\s+(.*)/ ||
/^(\s+)([A-F0-9]{0,40})/) && $kmap{$2}) {
$kmap{$2}->{'secret'}++;
}
}
close(GPG);
&reset_environment();
return @rv;
}
# list_keys_sorted()
# Returns a list of all keys, sorted by name
sub list_keys_sorted
{
return sort { lc($a->{'name'}->[0]) cmp lc($b->{'name'}->[0]) }
&list_keys();
}
# list_secret_keys()
# List list_keys, but only returns secret ones
sub list_secret_keys
{
return grep { $_->{'secret'} } &list_keys();
}
# key_matches_id(id, &key)
# Returns 1 if some GnuPG key ID or fingerprint refers to the given key
sub key_matches_id
{
my ($id, $key) = @_;
$id = lc($id);
return 1 if (lc($key->{'key'}) eq $id || lc($key->{'key'}) =~ /\Q$id\E$/);
foreach my $key2 (@{$key->{'key2'}}) {
return 1 if (lc($key2) eq $id || lc($key2) =~ /\Q$id\E$/);
}
return 0;
}
# key_fingerprint(&key)
sub key_fingerprint
{
my $fp;
local $_;
&clean_language();
open(GPG, "$gpgpath --fingerprint ".quotemeta($_[0]->{'name'}->[0])." 2>/dev/null |");
while(<GPG>) {
if (/([0-9A-F]{4}\s+[0-9A-F]{4}\s+[0-9A-F]{4}\s+[0-9A-F]{4}\s+[0-9A-F]{4}\s+[0-9A-F]{4}\s+[0-9A-F]{4}\s+[0-9A-F]{4}\s+[0-9A-F]{4}\s+[0-9A-F]{4})/i) {
$fp = $1;
}
}
close(GPG);
&reset_environment();
return $fp;
}
# get_passphrase(&key)
# Returns the passphrase for a key, or undef if we don't have one
sub get_passphrase
{
my ($key) = @_;
my $file = &get_passphrase_file($key);
open(PASS, "<", $file) || return undef;
my $pass = <PASS>;
close(PASS);
chomp($pass);
return $pass;
}
# get_passphrase_file(&key)
# Returns the stored passphrase file for a key, falling back through full
# fingerprint, long and short key IDs, and the old generic passphrase file.
sub get_passphrase_file
{
my ($key) = @_;
if ($key && $key->{'key'}) {
my @keys = ( $key->{'key'} );
push(@keys, $1) if ($key->{'key'} =~ /([A-F0-9]{16})$/i);
push(@keys, $1) if ($key->{'key'} =~ /([A-F0-9]{8})$/i);
foreach my $k (@keys) {
my $file = "$user_module_config_directory/pass.$k";
return $file if (-r $file);
}
}
my $file = "$user_module_config_directory/pass";
return $file if (-r $file);
return $key && $key->{'key'} ?
"$user_module_config_directory/pass.$key->{'key'}" : $file;
}
# put_passphrase(pass, &key)
sub put_passphrase
{
my $fh;
&open_tempfile($fh, ">$user_module_config_directory/pass.$_[1]->{'key'}");
&print_tempfile($fh, $_[0],"\n");
&close_tempfile($fh);
chmod(0700, "$user_module_config_directory/pass.$_[1]->{'key'}");
}
# encrypt_data(data, &result, &key|&keys, ascii)
# Encrypts some data with the given public key and returns the result, and
# returns an error message or undef on failure
sub encrypt_data
{
my ($data, $out, $keys, $ascii) = @_;
my $srcfile = &transname();
my @keys = ref($keys) eq 'ARRAY' ? @$keys : ( $keys );
my $rcpt = join(" ", map { "--recipient ".quotemeta($_->{'name'}->[0]) } @keys);
&write_file_contents($srcfile, $data);
my $dstfile = &transname();
my $asciiflag = $ascii ? "--armor" : "";
my $comp = $config{'compress'} eq '' ? "" :
" --compress-algo ".quotemeta($config{'compress'});
&clean_language();
my $cmd = "$gpgpath --output ".quotemeta($dstfile).
" $rcpt $asciiflag $comp --encrypt ".quotemeta($srcfile);
my ($fh, $fpid) = &proc::pty_process_exec($cmd);
while(1) {
my $rv = &wait_for($fh, "anyway");
if ($rv == 0) {
syswrite($fh, "yes\n", length("yes\n"));
}
elsif ($rv < 0) {
last;
}
}
close($fh);
&reset_environment();
unlink($srcfile);
my $dst = &read_file_contents($dstfile);
unlink($dstfile);
if ($dst) {
$$out = $dst;
return undef;
}
else {
return $wait_for_input;
}
}
# decrypt_data(data, &result, [&key])
# Decrypts some data encrypted for the current GnuPG user, and puts the results
# into &result. Returns an error message or undef on success.
sub decrypt_data
{
my ($data, $out, $key) = @_;
my $srcfile = &transname();
&write_file_contents($srcfile, $data);
my $dstfile = &transname();
&clean_language();
my $pflag = "";
my $pass;
if (!$key) {
# No key was given, but if we have only one try it
my @keys = &list_secret_keys();
if (@keys == 1) {
$key = $keys[0];
}
}
if ($key) {
# Key was given, use it's passphrase
$pass = &get_passphrase($key);
return $text{'gnupg_esignpass'} if (!$key);
$pflag = "--batch --passphrase-file ".
quotemeta(&get_passphrase_file($key));
}
my ($error, $seen_pass, $keyid);
my $retry = 0;
while(1) {
unlink($dstfile);
my $cmd = "$gpgpath --pinentry-mode loopback $pflag".
" --output ".quotemeta($dstfile).
" --decrypt ".quotemeta($srcfile);
my ($fh, $fpid) = &proc::pty_process_exec($cmd);
my $rerun = 0;
$error = $seen_pass = $keyid = undef;
while(1) {
my $rv = &wait_for($fh, "passphrase:", "key,\\s+ID\\s+(\\S+),", "failed.*\\n", "error.*\\n", "invalid.*\\n", "signal caught.*\\n");
if ($rv == 0) {
# Only needed if caller didn't supply a key with passphrase
last if ($seen_pass++);
sleep(1);
syswrite($fh, "$pass\n", length("$pass\n"));
}
elsif ($rv == 1) {
# Only needed if caller didn't supply a key
$keyid = $matches[1];
my $rkey;
($rkey) = grep { &key_matches_id($matches[1], $_) }
&list_secret_keys();
if ($rkey && $key) {
# Does discovered key match?
return &text('gnupg_ecryptkey2', "<tt>$keyid</tt>")
if (!&key_matches_id($keyid, $key));
}
elsif ($rkey && !$key) {
# Discovered the key to use. Retry with a stored
# passphrase file for newer GnuPG versions
$pass = &get_passphrase($rkey);
$key = $rkey;
if (defined($pass) && !$retry++) {
$pflag = "--batch --passphrase-file ".
quotemeta(
&get_passphrase_file(
$key));
$rerun++;
last;
}
}
}
elsif ($rv > 1) {
$error++;
last;
}
elsif ($rv < 0) {
last;
}
}
if ($rerun) {
kill('TERM', $fpid);
close($fh);
next;
}
close($fh);
last;
}
&reset_environment();
unlink($srcfile);
my $dst = &read_file_contents($dstfile);
unlink($dstfile);
if (!$keyid && !$key) {
return $text{'gnupg_ecryptid'};
}
elsif (!$key) {
return &text('gnupg_ecryptkey', "<tt>$keyid</tt>");
}
elsif (!defined($pass)) {
return &text('gnupg_ecryptpass', $key->{'name'}->[0]).". ".
&text('gnupg_canset', "/gnupg/edit_key.cgi?key=$key->{'key'}").".";
}
elsif ($error || $seen_pass > 1) {
return "<pre>".&html_escape($wait_for_input)."</pre>";
}
else {
$$out = $dst;
return undef;
}
}
# sign_data(data, \&result, &key, mode)
# Signs the given data and returns the result. Mode 0 = binary signature
# mode 1 = ascii signature at end, mode 2 = ascii signature only
sub sign_data
{
my ($data, $out, $key, $mode) = @_;
my $srcfile = &transname();
&write_file_contents($srcfile, $data);
my $dstfile = &transname();
my $pass = &get_passphrase($key);
if (!defined($pass)) {
return $text{'gnupg_esignpass'}.". ".
&text('gnupg_canset', "/gnupg/edit_key.cgi?key=$key->{'key'}").".";
}
my $pflag = "--batch --pinentry-mode loopback --passphrase-file ".
quotemeta(&get_passphrase_file($key));
my $cmd;
if ($mode == 0) {
$cmd = "$gpgpath $pflag --output ".quotemeta($dstfile)." --default-key $key->{'key'} --sign ".quotemeta($srcfile);
}
elsif ($mode == 1) {
$cmd = "$gpgpath $pflag --output ".quotemeta($dstfile)." --default-key $key->{'key'} --clearsign ".quotemeta($srcfile);
}
elsif ($mode == 2) {
$cmd = "$gpgpath $pflag --armor --output ".quotemeta($dstfile)." --default-key $key->{'key'} --detach-sig ".quotemeta($srcfile);
}
&clean_language();
my ($fh, $fpid) = &proc::pty_process_exec($cmd);
&reset_environment();
my ($error, $seen_pass);
while(1) {
my $rv = &wait_for($fh, "passphrase:", "failed", "error");
if ($rv == 0) {
# This should never happen since we supply the passphrase
# on the command line already
last if ($seen_pass++);
sleep(1);
syswrite($fh, "$pass\n", length("$pass\n"));
}
elsif ($rv > 0) {
$error++;
last;
}
elsif ($rv < 0) {
last;
}
}
close($fh);
unlink($srcfile);
my $dst = &read_file_contents($dstfile);
unlink($dstfile);
if ($error || $seen_pass > 1) {
return "<pre>".&html_escape($wait_for_input)."</pre>";
}
else {
$$out = $dst;
return undef;
}
}
# verify_data(data, [signature])
# Verifies the signature on some data, and returns a status code and a message
# code 0 = verified successfully, message contains signer
# code 1 = verified successfully but no trust chain, message contains signer
# code 2 = failed to verify, message contains signer
# code 3 = do not have signers public key, message contains ID
# code 4 = verification totally failed, message contains reason
sub verify_data
{
my ($data, $sig) = @_;
my $datafile = &transname();
&write_file_contents($datafile, $data);
my $cmd;
my $sigfile;
if (!$sig) {
$cmd = "$gpgpath --verify ".quotemeta($datafile);
}
else {
$sigfile = &transname();
&write_file_contents($sigfile, $sig);
$cmd = "$gpgpath --verify ".quotemeta($sigfile)." ".quotemeta($datafile);
}
#local ($fh, $fpid) = &proc::pty_process_exec($cmd);
#&wait_for($fh);
#close($fh);
#local $out = $wait_for_input;
&clean_language();
my $out = &backquote_command("$cmd 2>&1 </dev/null") || "";
&reset_environment();
unlink($datafile);
unlink($sigfile) if ($sigfile);
if ($out =~ /BAD signature from "(.*)"/i) {
return (2, $1);
}
elsif ($out =~ /key ID (\S+).*\n.*not found/i) {
return (3, $1);
}
elsif ($out =~ /Good signature from "(.*)"/i) {
my $signer = $1;
if ($out =~ /warning/) {
return (1, $signer);
}
else {
return (0, $signer);
}
}
else {
return (4, $out);
}
}
# get_trust_level(&key)
# Returns the trust level of a key
sub get_trust_level
{
my ($key) = @_;
&clean_language();
my $cmd = "$gpgpath --edit-key ".quotemeta($key->{'name'}->[0]);
my ($fh, $fpid) = &proc::pty_process_exec($cmd);
my $rv = &wait_for($fh, "trust:\\s+(.)", "command>");
my $tr;
if ($rv == 0) {
$tr = $matches[1] eq "q" ? 1 : $matches[1] eq "n" ? 2 :
$matches[1] eq "m" ? 3 : $matches[1] eq "f" ? 4 : 0;
}
else {
$tr = -1;
}
syswrite($fh, "quit\n", length("quit\n"));
close($fh);
&reset_environment();
return $tr;
}
# delete_key(&key)
# Delete one public or secret key
sub delete_key
{
my ($key) = @_;
if ($key->{'secret'}) {
&clean_language();
my $cmd = "$gpgpath --delete-secret-key ".
quotemeta($key->{'name'}->[0]);
my ($fh, $fpid) = &proc::pty_process_exec($cmd);
&wait_for($fh, "\\?");
syswrite($fh, "y\n");
&wait_for($fh, "\\?");
syswrite($fh, "y\n");
sleep(1);
close($fh);
&reset_environment();
}
&clean_language();
my $cmd = "$gpgpath --delete-key ".quotemeta($key->{'name'}->[0]);
my ($fh, $fpid) = &proc::pty_process_exec($cmd);
&wait_for($fh, "\\?");
syswrite($fh, "y\n");
sleep(1);
close($fh);
&reset_environment();
}
# default_email_address()
# Returns the current user's email address, or undef if not possible
sub default_email_address
{
if (&foreign_check("mailbox")) {
&foreign_require("mailbox", "mailbox-lib.pl");
my ($fromaddr) = &mailbox::split_addresses(
&mailbox::get_preferred_from_address());
if ($fromaddr) {
return $fromaddr->[0];
}
}
return undef;
}
# fetch_gpg_key(id)
# Imports a key by ID from the configured keyserver. Returns 0 on success,
# 1 on failure, 2 if there was no change, 3 if the import appeared to succeed
# but the key isn't visible.
sub fetch_gpg_key
{
my ($id) = @_;
my $out = &backquote_command(
"$gpgpath --keyserver ".quotemeta($config{'keyserver'}).
" --recv-key ".quotemeta($id)." 2>&1 </dev/null") || "";
my @keys = &list_keys();
my ($key) = grep { lc($_->{'key'}) eq lc($id) } @keys;
if ($?) {
return wantarray ? (1, $out) : 1;
}
elsif ($out =~ /not\s+changed/) {
return wantarray ? (2, $key) : 2;
}
else {
if ($key) {
return (0, $key);
}
else {
return (3, $out);
}
}
}
# search_gpg_keys(word)
# Searches the configured keyserver for GPG keys matching some name or email
# address, and returns them as a list of hash refs
sub search_gpg_keys
{
my ($word) = @_;
my $cmd = "$gpgpath --keyserver ".quotemeta($config{'keyserver'}).
" --search-keys ".quotemeta($word);
my ($fh, $fpid) = &proc::pty_process_exec($cmd);
my @rv;
while(1) {
$wait_for_input = undef;
my $rv = &wait_for($fh, "N.ext, or Q.uit");
if ($rv < 0) { last; }
my $count = 0;
my $key;
foreach my $l (split(/\r?\n/, $wait_for_input)) {
if ($l =~ /^\(\d+\)\s+(\d+)\s+bit\s+(\S+)\s+key\s+(\S+)/) {
# Key with no name .. skip!
}
elsif ($l =~ /^\(\d+\)\s+(\S.*)\s+<(\S+)>/ ||
$l =~ /^\(\d+\)\s+(\S.*)/) {
# First name and email for a key
$key = { 'name' => [ $1 ],
'email' => [ $2 ] };
$key->{'name'} =~ s/\s+$//;
push(@rv, $key);
$count++;
}
elsif ($l =~ /^\s+(\S.*)\s+<(\S+)>/ && $key) {
# Additional name and email
push(@{$key->{'name'}}, $1);
push(@{$key->{'email'}}, $2);
}
elsif ($l =~ /\s+(\d+)\s+bit\s+(\S+)\s+key\s+(\S+),\s+created:\s+(\S+)/ && $key) {
# Size and ID
$key->{'size'} = $1;
$key->{'key'} = $3;
$key->{'date'} = $4;
if ($l =~ /revoked/) {
$key->{'revoked'} = 1;
}
$key = undef;
}
}
if ($count) {
&sysprint($fh, "N\n");
}
else {
last;
}
}
close($fh);
return @rv;
}
# returns current version of gpg command
sub get_gpg_version
{
my ($gpg) = @_;
$gpg = "gpg" if (!$gpg);
$gpg = quotemeta($gpg);
$gpg = `$gpg --version`;
$gpg =~ /(\*|\d+(\.\d+){0,2})/;
return $1;
}
1;
+25
View File
@@ -0,0 +1,25 @@
<header>Trusted proxy addresses</header>
A list of IP addresses or networks (one per line, in the same format as the
allowed addresses field above) that are permitted to provide proxy headers
such as <tt>X-Forwarded-For</tt>, <tt>X-Real-IP</tt>, <tt>X-SSL-Client-DN</tt>
and <tt>X-SSL-Client-Verify</tt>.
<p>
When this list is set, headers received from any other peer are ignored,
preventing a client that can reach Webmin directly from spoofing its source
IP or impersonating a user via a fake SSL client certificate header.
<p>
This field is required when the trust level is set to trust both the remote
IP and SSL certificate provided by proxies. It is strongly recommended
whenever any proxy header trust is enabled.
<p>
Example:
<pre>
10.0.0.5
192.168.1.0/24
2001:DB8::/32
</pre>
<p></p>
@@ -0,0 +1 @@
<header>مستوى الثقة لرؤوس الوكيل</header> استخدم هذا الإعداد لتحديد ما إذا كان يجب على Webmin الثقة بالرؤوس من الوكيل لتحديد عنوان IP للمستخدم وشهادة SSL:<ul style=";text-align:right;direction:rtl"><li style=";text-align:right;direction:rtl"> لا، لا تثق بأي رؤوس من الوكيل.</li><li style=";text-align:right;direction:rtl"> نعم، ثق في عنوان IP البعيد الذي توفره الوكلاء. إذا تم تمكينه، فسيستخدم Webmin رأسًا يوفره وكيل لتحديد عنوان IP الحقيقي للمتصفح لأغراض التسجيل والتحكم في الوصول، مثل <tt>X-Forwarded-For</tt> أو <tt>X-Real-IP</tt> . يجب تمكين هذا <em>فقط</em> عندما يكون نظام Webmin الخاص بك خلف وكيل، ولا يوجد وصول مباشر من العملاء؛ وإلا، فقد يتم إرسال رأس مزيف لتجاوز قيود التحكم في الوصول إلى IP.</li><li style=";text-align:right;direction:rtl"> نعم، يمكنك الوثوق بكل من عنوان IP البعيد وشهادة SSL التي يوفرها الوكلاء. إذا تم تمكين ذلك، فسيستخدم Webmin رأسًا يوفره وكيل لتحديد شهادة SSL الخاصة بعميل المستخدم لأغراض المصادقة، مثل <tt>X-SSL-Client-DN</tt> . يجب تمكين ذلك <em>فقط</em> عندما يكون نظام Webmin الخاص بك خلف وكيل، ولا يوجد وصول مباشر من العملاء؛ وإلا، فقد يتم إرسال رأس مزيف لتسجيل الدخول كمستخدم مختلف.</li></ul><p style=";text-align:right;direction:rtl"></p>

Some files were not shown because too many files have changed in this diff Show More