ba64342702
phpMyAdmin login was broken because phpmyadmin_install.sh never wired the private phpMyAdmin copy into the web server: no Apache Alias was registered via DirectAdmin CustomBuild, so the SSO redirect target was unreachable. Add configure_apache_alias()/apply_apache_alias() (Alias + Directory blocks, ./build rewrite_confs, httpd reload), detect the real Apache group instead of hardcoding diradmin:diradmin, stop silently swallowing chown/chmod failures, and verify an optional SHA256 for the downloaded phpMyAdmin tarball. Extend phpmyadmin_health_check.sh to detect a missing/incorrect Apache alias and to probe HTTP reachability. Security hardening: scope temporary phpMyAdmin SSO MySQL roles to 127.0.0.1 instead of '%', tighten SSO ticket file permissions to 0640 (they contain a plaintext MySQL password), and log MySQL connection failures for diagnosis instead of swallowing them silently. Bump version to 1.2.12 and rebuild the release archive.
620 lines
19 KiB
Bash
620 lines
19 KiB
Bash
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
PHPMYADMIN_PRIVATE_DIR="${PHPMYADMIN_PRIVATE_DIR:-${PHPMYADMIN_DIR:-/var/www/html/alt-mysql-phpmyadmin}}"
|
|
PHPMYADMIN_URL_PATH="${PHPMYADMIN_URL_PATH:-/alt-mysql-phpmyadmin}"
|
|
PHPMYADMIN_VERSION="${PHPMYADMIN_VERSION:-5.2.3}"
|
|
PHPMYADMIN_TARBALL_URL="${PHPMYADMIN_TARBALL_URL:-https://files.phpmyadmin.net/phpMyAdmin/5.2.3/phpMyAdmin-5.2.3-all-languages.tar.gz}"
|
|
PHPMYADMIN_TARBALL_SHA256="${PHPMYADMIN_TARBALL_SHA256:-}"
|
|
PHPMYADMIN_DOWNLOAD_DIR="${PHPMYADMIN_DOWNLOAD_DIR:-/usr/local/src}"
|
|
PHPMYADMIN_SOURCE_DIR="${PHPMYADMIN_SOURCE_DIR:-}"
|
|
RUNTIME_DIR="${PHPMYADMIN_PRIVATE_DIR}/runtime"
|
|
TICKETS_DIR="${RUNTIME_DIR}/tickets"
|
|
CONFIG_INC="${PHPMYADMIN_PRIVATE_DIR}/config.inc.php"
|
|
SIGNON_SCRIPT="${PHPMYADMIN_PRIVATE_DIR}/da_signon.php"
|
|
SIGNON_URL_PAGE="${PHPMYADMIN_PRIVATE_DIR}/da_login.php"
|
|
BLOWFISH_SECRET_FILE="${RUNTIME_DIR}/blowfish_secret"
|
|
CUSTOMBUILD_DIR="${CUSTOMBUILD_DIR:-/usr/local/directadmin/custombuild}"
|
|
CB_BUILD="${CUSTOMBUILD_DIR}/build"
|
|
APACHE_ALIAS_CUSTOM="${CUSTOMBUILD_DIR}/custom/ap2/conf/extra/httpd-alias.conf"
|
|
APACHE_ALIAS_SOURCE="/etc/httpd/conf/extra/httpd-alias.conf"
|
|
APACHE_ALIAS_CONFIGURE="${CUSTOMBUILD_DIR}/configure/ap2/conf/extra/httpd-alias.conf"
|
|
|
|
if [ "${PHPMYADMIN_INSTALL_ASSUME_ROOT:-0}" != "1" ] && [ "${EUID:-$(id -u)}" -ne 0 ]; then
|
|
echo "Skrypt musi być uruchomiony jako root." >&2
|
|
exit 1
|
|
fi
|
|
|
|
log() {
|
|
printf 'phpMyAdmin alt-mysql: %s\n' "$*"
|
|
}
|
|
|
|
warn() {
|
|
printf 'phpMyAdmin alt-mysql: WARNING: %s\n' "$*" >&2
|
|
}
|
|
|
|
die() {
|
|
printf 'phpMyAdmin alt-mysql: %s\n' "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
chown_or_warn() {
|
|
local owner="$1" errfile
|
|
shift
|
|
errfile="$(mktemp)"
|
|
chown "$owner" "$@" 2>"$errfile" || warn "chown $owner $* failed: $(cat "$errfile")"
|
|
rm -f "$errfile"
|
|
}
|
|
|
|
chmod_or_warn() {
|
|
local mode="$1" errfile
|
|
shift
|
|
errfile="$(mktemp)"
|
|
chmod "$mode" "$@" 2>"$errfile" || warn "chmod $mode $* failed: $(cat "$errfile")"
|
|
rm -f "$errfile"
|
|
}
|
|
|
|
detect_apache_group() {
|
|
local group_name=""
|
|
|
|
if [ -f /etc/httpd/conf/httpd.conf ]; then
|
|
group_name="$(awk 'tolower($1)=="group" {print $2; exit}' /etc/httpd/conf/httpd.conf | tr -d '[:space:]')"
|
|
fi
|
|
|
|
if [ -z "$group_name" ] && [ -f /etc/apache2/apache2.conf ]; then
|
|
group_name="$(awk 'tolower($1)=="group" {print $2; exit}' /etc/apache2/apache2.conf | tr -d '[:space:]')"
|
|
fi
|
|
|
|
if [ -z "$group_name" ]; then
|
|
for candidate in apache www-data nobody; do
|
|
if getent group "$candidate" >/dev/null 2>&1; then
|
|
group_name="$candidate"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
printf '%s\n' "${group_name:-diradmin}"
|
|
}
|
|
|
|
install_private_copy_from_source() {
|
|
local source_dir="$1"
|
|
[ -d "$source_dir" ] || die "Katalog źródłowy phpMyAdmin nie istnieje: $source_dir"
|
|
[ -f "$source_dir/index.php" ] || die "Katalog źródłowy nie wygląda jak phpMyAdmin: $source_dir"
|
|
|
|
mkdir -p "$PHPMYADMIN_PRIVATE_DIR"
|
|
cp -a "$source_dir"/. "$PHPMYADMIN_PRIVATE_DIR"/
|
|
}
|
|
|
|
download_private_copy() {
|
|
local tarball extracted tmp_dir
|
|
|
|
command -v curl >/dev/null 2>&1 || die "Brak curl; ustaw PHPMYADMIN_SOURCE_DIR albo doinstaluj curl."
|
|
command -v tar >/dev/null 2>&1 || die "Brak tar."
|
|
|
|
mkdir -p "$PHPMYADMIN_DOWNLOAD_DIR"
|
|
tarball="$PHPMYADMIN_DOWNLOAD_DIR/phpMyAdmin-${PHPMYADMIN_VERSION}-all-languages.tar.gz"
|
|
if [ ! -s "$tarball" ]; then
|
|
log "Pobieram prywatny phpMyAdmin ${PHPMYADMIN_VERSION}."
|
|
curl -fL --retry 3 --connect-timeout 20 -o "$tarball" "$PHPMYADMIN_TARBALL_URL"
|
|
fi
|
|
|
|
if [ -n "$PHPMYADMIN_TARBALL_SHA256" ]; then
|
|
command -v sha256sum >/dev/null 2>&1 || die "Brak sha256sum do weryfikacji archiwum phpMyAdmin."
|
|
local actual_sum
|
|
actual_sum="$(sha256sum "$tarball" | awk '{print $1}')"
|
|
[ "$actual_sum" = "$PHPMYADMIN_TARBALL_SHA256" ] || {
|
|
rm -f "$tarball"
|
|
die "Niezgodna suma SHA256 archiwum phpMyAdmin. Oczekiwano: ${PHPMYADMIN_TARBALL_SHA256}, otrzymano: ${actual_sum}"
|
|
}
|
|
fi
|
|
|
|
tmp_dir="$(mktemp -d)"
|
|
tar -xzf "$tarball" -C "$tmp_dir"
|
|
extracted="$(find "$tmp_dir" -mindepth 1 -maxdepth 1 -type d -name 'phpMyAdmin-*' -print -quit)"
|
|
[ -n "$extracted" ] || {
|
|
rm -rf "$tmp_dir"
|
|
die "Tarball phpMyAdmin nie zawiera oczekiwanego katalogu."
|
|
}
|
|
|
|
install_private_copy_from_source "$extracted"
|
|
rm -rf "$tmp_dir"
|
|
}
|
|
|
|
ensure_private_copy() {
|
|
if [ -f "$PHPMYADMIN_PRIVATE_DIR/index.php" ]; then
|
|
return 0
|
|
fi
|
|
|
|
rm -rf "$PHPMYADMIN_PRIVATE_DIR"
|
|
if [ -n "$PHPMYADMIN_SOURCE_DIR" ]; then
|
|
install_private_copy_from_source "$PHPMYADMIN_SOURCE_DIR"
|
|
else
|
|
download_private_copy
|
|
fi
|
|
}
|
|
|
|
generate_secret() {
|
|
if [ -r "$BLOWFISH_SECRET_FILE" ]; then
|
|
local existing
|
|
existing="$(tr -d '\r\n' < "$BLOWFISH_SECRET_FILE")"
|
|
if [ -n "$existing" ]; then
|
|
printf '%s\n' "$existing"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
if command -v openssl >/dev/null 2>&1; then
|
|
openssl rand -hex 32
|
|
return 0
|
|
fi
|
|
|
|
tr -dc 'a-f0-9' </dev/urandom | head -c 64
|
|
printf '\n'
|
|
}
|
|
|
|
write_private_config() {
|
|
local secret
|
|
|
|
mkdir -p "$RUNTIME_DIR" "$TICKETS_DIR"
|
|
secret="$(generate_secret)"
|
|
printf '%s\n' "$secret" > "$BLOWFISH_SECRET_FILE"
|
|
chmod 600 "$BLOWFISH_SECRET_FILE" 2>/dev/null || true
|
|
cat > "$RUNTIME_DIR/.htaccess" <<'EOF'
|
|
Require all denied
|
|
Deny from all
|
|
EOF
|
|
cat > "$TICKETS_DIR/.htaccess" <<'EOF'
|
|
Require all denied
|
|
Deny from all
|
|
EOF
|
|
printf '%s\n' '<!doctype html><title>Forbidden</title>' > "$RUNTIME_DIR/index.html"
|
|
printf '%s\n' '<!doctype html><title>Forbidden</title>' > "$TICKETS_DIR/index.html"
|
|
|
|
cat > "$CONFIG_INC" <<'PHP'
|
|
<?php
|
|
declare(strict_types=1);
|
|
|
|
const DA_MYSQL_PMA_DEFAULT_CONF = '/usr/local/directadmin/conf/alt-mysql.conf';
|
|
const DA_MYSQL_PMA_RUNTIME_CONFIG = __DIR__ . '/runtime/config.json';
|
|
const DA_MYSQL_PMA_BLOWFISH_SECRET_FILE = __DIR__ . '/runtime/blowfish_secret';
|
|
|
|
function da_mysql_phpmyadmin_runtime_config(): array
|
|
{
|
|
if (!is_readable(DA_MYSQL_PMA_RUNTIME_CONFIG)) {
|
|
return [];
|
|
}
|
|
|
|
$raw = file_get_contents(DA_MYSQL_PMA_RUNTIME_CONFIG);
|
|
if (!is_string($raw) || $raw === '') {
|
|
return [];
|
|
}
|
|
|
|
$decoded = json_decode($raw, true);
|
|
return is_array($decoded) ? $decoded : [];
|
|
}
|
|
|
|
function da_mysql_phpmyadmin_parse_conf(string $path): array
|
|
{
|
|
$data = [
|
|
'host' => '127.0.0.1',
|
|
'port' => '33033',
|
|
'socket' => '',
|
|
];
|
|
|
|
if (!is_readable($path)) {
|
|
return $data;
|
|
}
|
|
|
|
$lines = file($path, FILE_IGNORE_NEW_LINES);
|
|
if ($lines === false) {
|
|
return $data;
|
|
}
|
|
|
|
foreach ($lines as $line) {
|
|
$line = trim($line);
|
|
if ($line === '' || $line[0] === '#' || strpos($line, '=') === false) {
|
|
continue;
|
|
}
|
|
[$key, $value] = explode('=', $line, 2);
|
|
$key = strtolower(trim($key));
|
|
$value = trim(trim($value), "\"'");
|
|
if ($key === 'host' && $value !== '') {
|
|
$data['host'] = $value;
|
|
} elseif (($key === 'port' || $key === 'mysql_port') && ctype_digit($value)) {
|
|
$data['port'] = $value;
|
|
} elseif (($key === 'socket' || $key === 'mysql_socket') && $value !== '') {
|
|
$data['socket'] = $value;
|
|
}
|
|
}
|
|
|
|
if ($data['host'] === '' || $data['host'] === 'localhost') {
|
|
$data['host'] = '127.0.0.1';
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
function da_mysql_phpmyadmin_blowfish_secret(): string
|
|
{
|
|
if (is_readable(DA_MYSQL_PMA_BLOWFISH_SECRET_FILE)) {
|
|
$secret = trim((string)file_get_contents(DA_MYSQL_PMA_BLOWFISH_SECRET_FILE));
|
|
if ($secret !== '') {
|
|
return $secret;
|
|
}
|
|
}
|
|
|
|
return 'alt-mysql-phpmyadmin-secret-change-me';
|
|
}
|
|
|
|
function da_mysql_phpmyadmin_url_path(array $runtimeConfig): string
|
|
{
|
|
$path = trim((string)($runtimeConfig['phpmyadmin_url_path'] ?? '/alt-mysql-phpmyadmin'));
|
|
if ($path === '') {
|
|
return '/alt-mysql-phpmyadmin';
|
|
}
|
|
if ($path[0] !== '/') {
|
|
$path = '/' . $path;
|
|
}
|
|
|
|
$path = rtrim($path, '/');
|
|
return $path !== '' ? $path : '/alt-mysql-phpmyadmin';
|
|
}
|
|
|
|
function da_mysql_phpmyadmin_public_base_url(array $runtimeConfig): string
|
|
{
|
|
$configured = trim((string)($runtimeConfig['phpmyadmin_public_base_url'] ?? ''));
|
|
if (preg_match('#^https?://#i', $configured) === 1) {
|
|
return rtrim($configured, '/');
|
|
}
|
|
|
|
$scheme = 'http';
|
|
$https = strtolower((string)($_SERVER['HTTPS'] ?? ''));
|
|
if ($https !== '' && $https !== 'off' && $https !== '0') {
|
|
$scheme = 'https';
|
|
} elseif (strtolower((string)($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '')) === 'https') {
|
|
$scheme = 'https';
|
|
} elseif (strtolower((string)($_SERVER['REQUEST_SCHEME'] ?? '')) === 'https') {
|
|
$scheme = 'https';
|
|
}
|
|
|
|
$host = trim((string)($_SERVER['HTTP_HOST'] ?? ''));
|
|
if ($host === '') {
|
|
$host = trim((string)($_SERVER['SERVER_NAME'] ?? 'localhost'));
|
|
}
|
|
if ($host === '') {
|
|
$host = 'localhost';
|
|
}
|
|
|
|
return $scheme . '://' . $host;
|
|
}
|
|
|
|
function da_mysql_phpmyadmin_signon_url(array $runtimeConfig): string
|
|
{
|
|
return da_mysql_phpmyadmin_public_base_url($runtimeConfig)
|
|
. da_mysql_phpmyadmin_url_path($runtimeConfig)
|
|
. '/da_login.php';
|
|
}
|
|
|
|
$runtimeConfig = da_mysql_phpmyadmin_runtime_config();
|
|
$credentialsFile = (string)($runtimeConfig['credentials_file'] ?? DA_MYSQL_PMA_DEFAULT_CONF);
|
|
if ($credentialsFile === '') {
|
|
$credentialsFile = DA_MYSQL_PMA_DEFAULT_CONF;
|
|
}
|
|
$daMysqlServer = da_mysql_phpmyadmin_parse_conf($credentialsFile);
|
|
|
|
$cfg = [];
|
|
$cfg['blowfish_secret'] = da_mysql_phpmyadmin_blowfish_secret();
|
|
$cfg['TempDir'] = __DIR__ . '/runtime/tmp';
|
|
$cfg['LoginCookieValidity'] = 900;
|
|
|
|
$i = 0;
|
|
$i++;
|
|
$cfg['Servers'][$i]['host'] = $daMysqlServer['host'];
|
|
$cfg['Servers'][$i]['port'] = $daMysqlServer['port'];
|
|
$cfg['Servers'][$i]['socket'] = $daMysqlServer['host'] === 'localhost' ? $daMysqlServer['socket'] : '';
|
|
$cfg['Servers'][$i]['auth_type'] = 'signon';
|
|
$cfg['Servers'][$i]['SignonScript'] = __DIR__ . '/da_signon.php';
|
|
$cfg['Servers'][$i]['SignonSession'] = 'DA_MYSQL_PHPMYADMIN';
|
|
$cfg['Servers'][$i]['SignonURL'] = da_mysql_phpmyadmin_signon_url($runtimeConfig);
|
|
$cfg['Servers'][$i]['LogoutURL'] = da_mysql_phpmyadmin_signon_url($runtimeConfig);
|
|
$cfg['Servers'][$i]['AllowNoPassword'] = false;
|
|
$cfg['Servers'][$i]['verbose'] = 'DirectAdmin alt-mysql';
|
|
$cfg['Servers'][$i]['only_db'] = '';
|
|
$cfg['ServerDefault'] = 1;
|
|
$cfg['AllowArbitraryServer'] = false;
|
|
PHP
|
|
|
|
cat > "$SIGNON_URL_PAGE" <<'PHP'
|
|
<?php
|
|
declare(strict_types=1);
|
|
|
|
const DA_MYSQL_SESSION = 'DA_MYSQL_PHPMYADMIN';
|
|
const DA_MYSQL_RUNTIME_CONFIG = __DIR__ . '/runtime/config.json';
|
|
|
|
function da_mysql_login_runtime_config(): array
|
|
{
|
|
if (!is_readable(DA_MYSQL_RUNTIME_CONFIG)) {
|
|
return [];
|
|
}
|
|
|
|
$raw = file_get_contents(DA_MYSQL_RUNTIME_CONFIG);
|
|
if (!is_string($raw) || $raw === '') {
|
|
return [];
|
|
}
|
|
|
|
$decoded = json_decode($raw, true);
|
|
return is_array($decoded) ? $decoded : [];
|
|
}
|
|
|
|
function da_mysql_login_url_path(array $runtimeConfig): string
|
|
{
|
|
$path = trim((string)($runtimeConfig['phpmyadmin_url_path'] ?? '/alt-mysql-phpmyadmin'));
|
|
if ($path === '') {
|
|
return '/alt-mysql-phpmyadmin';
|
|
}
|
|
if ($path[0] !== '/') {
|
|
$path = '/' . $path;
|
|
}
|
|
|
|
$path = rtrim($path, '/');
|
|
return $path !== '' ? $path : '/alt-mysql-phpmyadmin';
|
|
}
|
|
|
|
function da_mysql_login_ticket_dir(array $runtimeConfig): string
|
|
{
|
|
$dir = trim((string)($runtimeConfig['ticket_dir'] ?? ''));
|
|
if ($dir !== '') {
|
|
return rtrim($dir, '/');
|
|
}
|
|
|
|
return __DIR__ . '/runtime/tickets';
|
|
}
|
|
|
|
function da_mysql_login_error(string $message): void
|
|
{
|
|
http_response_code(400);
|
|
header('Content-Type: text/html; charset=UTF-8');
|
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
|
header('Pragma: no-cache');
|
|
$safe = htmlspecialchars($message, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
|
echo '<!doctype html><html lang="en"><head><meta charset="utf-8"><title>alt-mysql phpMyAdmin</title></head><body>';
|
|
echo '<h1>alt-mysql phpMyAdmin</h1><p>' . $safe . '</p>';
|
|
echo '</body></html>';
|
|
exit;
|
|
}
|
|
|
|
function da_mysql_login_consume_ticket(array $runtimeConfig): array
|
|
{
|
|
$token = strtolower((string)($_GET['ticket'] ?? ''));
|
|
if (preg_match('/\A[a-f0-9]{64}\z/', $token) !== 1) {
|
|
da_mysql_login_error('Missing or invalid phpMyAdmin login ticket.');
|
|
}
|
|
|
|
$path = da_mysql_login_ticket_dir($runtimeConfig) . '/' . $token . '.json';
|
|
if (!is_readable($path)) {
|
|
da_mysql_login_error('The phpMyAdmin login ticket is not available or has already been used.');
|
|
}
|
|
|
|
$raw = file_get_contents($path);
|
|
@unlink($path);
|
|
$ticket = is_string($raw) ? json_decode($raw, true) : null;
|
|
if (!is_array($ticket)) {
|
|
da_mysql_login_error('The phpMyAdmin login ticket is invalid.');
|
|
}
|
|
|
|
if ((int)($ticket['expires_at'] ?? 0) < time()) {
|
|
da_mysql_login_error('The phpMyAdmin login ticket has expired.');
|
|
}
|
|
|
|
$auth = $ticket['auth'] ?? [];
|
|
if (!is_array($auth) || (string)($auth['user'] ?? '') === '' || (string)($auth['password'] ?? '') === '') {
|
|
da_mysql_login_error('The phpMyAdmin login ticket does not contain credentials.');
|
|
}
|
|
|
|
return $ticket;
|
|
}
|
|
|
|
function da_mysql_login_redirect_target(array $ticket): string
|
|
{
|
|
$route = (string)($ticket['route'] ?? '/database/structure');
|
|
if (preg_match('#^/[A-Za-z0-9_./-]+$#', $route) !== 1 || strpos($route, '//') !== false) {
|
|
$route = '/';
|
|
}
|
|
|
|
$query = ['route' => $route];
|
|
$db = (string)($ticket['db'] ?? ($ticket['auth']['db'] ?? ''));
|
|
if ($db !== '') {
|
|
$query['db'] = $db;
|
|
}
|
|
|
|
return 'index.php?' . http_build_query($query);
|
|
}
|
|
|
|
$runtimeConfig = da_mysql_login_runtime_config();
|
|
$ticket = da_mysql_login_consume_ticket($runtimeConfig);
|
|
$secure = false;
|
|
$https = strtolower((string)($_SERVER['HTTPS'] ?? ''));
|
|
if ($https !== '' && $https !== 'off' && $https !== '0') {
|
|
$secure = true;
|
|
} elseif (strtolower((string)($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '')) === 'https') {
|
|
$secure = true;
|
|
}
|
|
|
|
session_name(DA_MYSQL_SESSION);
|
|
session_set_cookie_params([
|
|
'lifetime' => 0,
|
|
'path' => da_mysql_login_url_path($runtimeConfig),
|
|
'secure' => $secure,
|
|
'httponly' => true,
|
|
'samesite' => 'Lax',
|
|
]);
|
|
session_start();
|
|
$_SESSION['DA_MYSQL_PHPMYADMIN_AUTH'] = $ticket['auth'];
|
|
session_write_close();
|
|
|
|
header('Cache-Control: no-store, no-cache, must-revalidate');
|
|
header('Pragma: no-cache');
|
|
header('Location: ' . da_mysql_login_redirect_target($ticket), true, 302);
|
|
exit;
|
|
PHP
|
|
|
|
cat > "$SIGNON_SCRIPT" <<'PHP'
|
|
<?php
|
|
declare(strict_types=1);
|
|
|
|
const DA_MYSQL_SESSION = 'DA_MYSQL_PHPMYADMIN';
|
|
const DA_MYSQL_DEFAULT_CONF = '/usr/local/directadmin/conf/alt-mysql.conf';
|
|
const DA_MYSQL_RUNTIME_CONFIG = __DIR__ . '/runtime/config.json';
|
|
|
|
function da_mysql_runtime_config(): array
|
|
{
|
|
if (!is_readable(DA_MYSQL_RUNTIME_CONFIG)) {
|
|
return [];
|
|
}
|
|
|
|
$raw = file_get_contents(DA_MYSQL_RUNTIME_CONFIG);
|
|
if (!is_string($raw) || $raw === '') {
|
|
return [];
|
|
}
|
|
|
|
$decoded = json_decode($raw, true);
|
|
return is_array($decoded) ? $decoded : [];
|
|
}
|
|
|
|
function da_mysql_signon_session_auth(): array
|
|
{
|
|
$payload = $_SESSION['DA_MYSQL_PHPMYADMIN_AUTH'] ?? [];
|
|
return is_array($payload) ? $payload : [];
|
|
}
|
|
|
|
function da_mysql_signon_read_auth(): array
|
|
{
|
|
$previousActive = session_status() === PHP_SESSION_ACTIVE;
|
|
$previousName = session_name();
|
|
$previousId = $previousActive ? session_id() : '';
|
|
|
|
if ($previousActive && $previousName === DA_MYSQL_SESSION) {
|
|
return da_mysql_signon_session_auth();
|
|
}
|
|
|
|
if ($previousActive) {
|
|
session_write_close();
|
|
}
|
|
|
|
session_name(DA_MYSQL_SESSION);
|
|
session_id('');
|
|
$ssoSessionId = (string)($_COOKIE[DA_MYSQL_SESSION] ?? '');
|
|
if ($ssoSessionId !== '' && preg_match('/\A[A-Za-z0-9,-]+\z/', $ssoSessionId) === 1) {
|
|
session_id($ssoSessionId);
|
|
}
|
|
session_start();
|
|
$payload = da_mysql_signon_session_auth();
|
|
session_write_close();
|
|
|
|
if ($previousActive) {
|
|
session_name($previousName);
|
|
if ($previousId !== '') {
|
|
session_id($previousId);
|
|
}
|
|
session_start();
|
|
} elseif ($previousName !== '') {
|
|
session_name($previousName);
|
|
}
|
|
|
|
return $payload;
|
|
}
|
|
|
|
function get_login_credentials($user = ''): array
|
|
{
|
|
$payload = da_mysql_signon_read_auth();
|
|
$username = (string)($payload['user'] ?? '');
|
|
$password = (string)($payload['password'] ?? '');
|
|
return [$username, $password];
|
|
}
|
|
PHP
|
|
|
|
local apache_group
|
|
apache_group="$(detect_apache_group)"
|
|
|
|
mkdir -p "$RUNTIME_DIR/tmp"
|
|
chown_or_warn root:root "$PHPMYADMIN_PRIVATE_DIR"
|
|
chmod_or_warn 755 "$PHPMYADMIN_PRIVATE_DIR"
|
|
chown_or_warn "diradmin:${apache_group}" "$RUNTIME_DIR" "$TICKETS_DIR" "$RUNTIME_DIR/tmp" "$CONFIG_INC" "$SIGNON_SCRIPT" "$SIGNON_URL_PAGE"
|
|
chmod_or_warn 711 "$RUNTIME_DIR" "$RUNTIME_DIR/tmp"
|
|
chmod_or_warn 2733 "$TICKETS_DIR"
|
|
chmod_or_warn 644 "$CONFIG_INC" "$SIGNON_SCRIPT" "$SIGNON_URL_PAGE" "$RUNTIME_DIR/.htaccess" "$TICKETS_DIR/.htaccess" "$RUNTIME_DIR/index.html" "$TICKETS_DIR/index.html"
|
|
}
|
|
|
|
configure_apache_alias() {
|
|
if [ ! -d "$CUSTOMBUILD_DIR" ]; then
|
|
warn "Brak katalogu CustomBuild: ${CUSTOMBUILD_DIR} - pomijam konfigurację aliasu Apache. Skonfiguruj go ręcznie: Alias ${PHPMYADMIN_URL_PATH} ${PHPMYADMIN_PRIVATE_DIR}"
|
|
return 0
|
|
fi
|
|
|
|
mkdir -p "$(dirname "$APACHE_ALIAS_CUSTOM")"
|
|
|
|
if [ ! -f "$APACHE_ALIAS_CUSTOM" ]; then
|
|
if [ -f "$APACHE_ALIAS_SOURCE" ]; then
|
|
cp -p "$APACHE_ALIAS_SOURCE" "$APACHE_ALIAS_CUSTOM"
|
|
elif [ -f "$APACHE_ALIAS_CONFIGURE" ]; then
|
|
cp -p "$APACHE_ALIAS_CONFIGURE" "$APACHE_ALIAS_CUSTOM"
|
|
else
|
|
warn "Nie znaleziono źródłowego httpd-alias.conf - tworzę pusty szablon custom."
|
|
: > "$APACHE_ALIAS_CUSTOM"
|
|
fi
|
|
fi
|
|
|
|
local tmp_file
|
|
tmp_file="$(mktemp)"
|
|
awk '
|
|
BEGIN { skip = 0 }
|
|
/^# BEGIN ALT_MYSQL_PHPMYADMIN$/ { skip = 1; next }
|
|
/^# END ALT_MYSQL_PHPMYADMIN$/ { skip = 0; next }
|
|
skip == 0 { print }
|
|
' "$APACHE_ALIAS_CUSTOM" > "$tmp_file"
|
|
|
|
cat >> "$tmp_file" <<EOF
|
|
|
|
# BEGIN ALT_MYSQL_PHPMYADMIN
|
|
Alias ${PHPMYADMIN_URL_PATH} ${PHPMYADMIN_PRIVATE_DIR}
|
|
|
|
<Directory "${PHPMYADMIN_PRIVATE_DIR}">
|
|
AllowOverride None
|
|
Options -Indexes
|
|
Require all granted
|
|
</Directory>
|
|
|
|
<Directory "${RUNTIME_DIR}">
|
|
AllowOverride None
|
|
Options -Indexes
|
|
Require all denied
|
|
</Directory>
|
|
# END ALT_MYSQL_PHPMYADMIN
|
|
EOF
|
|
|
|
mv "$tmp_file" "$APACHE_ALIAS_CUSTOM"
|
|
chmod_or_warn 644 "$APACHE_ALIAS_CUSTOM"
|
|
}
|
|
|
|
apply_apache_alias() {
|
|
if [ -x "$CB_BUILD" ]; then
|
|
(cd "$CUSTOMBUILD_DIR" && ./build rewrite_confs) || warn "rewrite_confs zakończyło się błędem - uruchom ręcznie: cd ${CUSTOMBUILD_DIR} && ./build rewrite_confs"
|
|
else
|
|
warn "Brak ${CB_BUILD} - uruchom ręcznie: cd ${CUSTOMBUILD_DIR} && ./build rewrite_confs"
|
|
fi
|
|
|
|
if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet httpd 2>/dev/null; then
|
|
systemctl reload httpd || warn "Nie udało się przeładować httpd."
|
|
fi
|
|
}
|
|
|
|
ensure_private_copy
|
|
write_private_config
|
|
configure_apache_alias
|
|
if [ "${PHPMYADMIN_SKIP_APACHE_RELOAD:-0}" != "1" ]; then
|
|
apply_apache_alias
|
|
fi
|
|
|
|
log "Prywatna kopia phpMyAdmin dla alt-mysql jest gotowa w ${PHPMYADMIN_PRIVATE_DIR}."
|