Many fixes for security.

This commit is contained in:
deepend 2024-01-13 13:14:13 -07:00
parent 6f5cc58c21
commit a0d32ba8fe
7 changed files with 367 additions and 172 deletions

View File

@ -99,6 +99,18 @@ a:hover {
form {
text-align: center;
}
.error-messages {
background-color: #ffdddd;
border: 1px solid #ff0000;
color: #ff0000;
margin: 10px 0;
padding: 10px;
border-radius: 5px;
}
.error-messages p {
margin: 5px 0;
}
/* Aligning form inputs to the left */
form input[type="text"],

View File

@ -81,7 +81,7 @@ fclose($logFile);
// Git commit and push if there are changes
if ($changes) {
// exec('git add .');
// exec('git commit -m "Updated DNS files"');
// exec('git push origin master');
exec('git add .');
exec('git commit -m "Updated DNS files"');
exec('git push origin master');
}

View File

@ -3,9 +3,35 @@ require_once 'initdb.php';
session_start();
// Initialize error messages array if not set
if (!isset($_SESSION['error_messages'])) {
$_SESSION['error_messages'] = [];
}
// Session timeout logic
$timeout = 1800; // 30 minutes in seconds
if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > $timeout)) {
// Last request was more than 30 minutes ago
session_unset(); // Unset $_SESSION variable
session_destroy(); // Destroy session data
header("Location: /?page=login"); // Redirect to login page
exit;
}
$_SESSION['last_activity'] = time(); // Update last activity time
// Check if user IP or user agent has changed
if ((isset($_SESSION['user_ip']) && $_SESSION['user_ip'] !== $_SERVER['REMOTE_ADDR']) ||
(isset($_SESSION['user_agent']) && $_SESSION['user_agent'] !== $_SERVER['HTTP_USER_AGENT'])) {
session_unset();
session_destroy();
header("Location: /?page=login");
exit;
}
// Redirect to login if not logged in
if (!isset($_SESSION['username'])) {
header("Location: https://tildenic.org/?page=login");
header("Location: /?page=login");
exit;
}
@ -14,22 +40,41 @@ $restrictedDomains = ['master.tilde', 'nic.tilde', 'tilde.tilde']; // Add more a
// Function to register domain
function registerDomain($domain, $userId, $pdo, $restrictedDomains) {
// Ensure '.tilde' is appended only once
if (!str_ends_with($domain, '.tilde')) {
$domain .= '.tilde';
}
// Debug: Output the full domain name
// echo "Attempting to register domain: " . htmlspecialchars($domain) . "<br>";
// Validate domain format (excluding the '.tilde' part)
$domainNameWithoutSuffix = str_replace('.tilde', '', $domain);
if (!preg_match('/^[a-zA-Z0-9\-]+$/', $domainNameWithoutSuffix)) {
// echo "Error: Invalid domain format detected.<br>"; // Debug message
return "Error: Invalid domain format. Only letters, numbers, and hyphens are allowed.";
}
if (in_array($domain, $restrictedDomains)) {
// echo "Error: Domain is restricted.<br>"; // Debug message
return "Error: The domain '$domain' cannot be registered.";
}
try {
$stmt = $pdo->prepare("INSERT INTO domains (user_id, domain_name) VALUES (?, ?)");
$stmt->execute([$userId, $domain]);
// echo "Domain registered successfully.<br>"; // Debug message
return "Domain registered successfully: " . htmlspecialchars($domain);
} catch (PDOException $e) {
// echo "Database error occurred.<br>"; // Debug message
if ($e->getCode() == 23000) {
return "Error: The domain '$domain' is already registered.";
} else {
return "Error: An error occurred while registering the domain.";
}
}
return"Error: The domain '$domain' is already registered.";
} else {
return "Error: An error occurred while registering the domain.";
}
}
}
// Function to get user ID
function getUserId($username, $pdo) {

View File

@ -1,6 +1,5 @@
<?php
require_once 'initdb.php';
session_start();
// Function to check user credentials
@ -17,13 +16,42 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['login'])) {
$password = $_POST['password'];
if (checkCredentials($username, $password, $pdo)) {
// Regenerate session ID upon successful login
session_regenerate_id();
$_SESSION['username'] = $username;
$_SESSION['last_activity'] = time(); // track start of session
$_SESSION['user_ip'] = $_SERVER['REMOTE_ADDR']; // store user IP
$_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT']; // store user agent
header("Location: /?page=user_domains");
exit;
} else {
$error = "Invalid username or password.";
}
}
// Session timeout logic
$timeout = 1800; // 30 minutes in seconds
if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > $timeout)) {
// last request was more than 30 minutes ago
session_unset(); // unset $_SESSION variable
session_destroy(); // destroy session data
header("Location: /?page=login"); // redirect to login page
exit;
}
$_SESSION['last_activity'] = time(); // update last activity time
// Check if user IP or user agent has changed
if (isset($_SESSION['user_ip']) && $_SESSION['user_ip'] !== $_SERVER['REMOTE_ADDR'] ||
isset($_SESSION['user_agent']) && $_SESSION['user_agent'] !== $_SERVER['HTTP_USER_AGENT']) {
session_unset();
session_destroy();
header("Location: /?page=login");
exit;
}
?>
<!DOCTYPE html>
@ -50,4 +78,4 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['login'])) {
<p><?php echo $error; ?></p>
<?php endif; ?>
</body>
</html>
</html>

View File

@ -1,143 +1,133 @@
<?php
require_once 'initdb.php';
session_start();
// Logout handling
if (isset($_GET['action']) && $_GET['action'] == 'logout') {
session_destroy();
header('Location: /');
exit;
}
// Function to get DNS server information from BIND files
function getDnsServersInfo() {
$masterFile = '../dottilde/db.master.tilde';
$servers = [];
$nsFilter = ['ns1', 'ns2', 'ns3']; // Add more nameserver identifiers as needed
// Manually assigned geographical areas for each nameserver
$nsGeographicalAreas = [
'ns1' => 'Quebec, Canada', // Replace with actual locations
'ns2' => 'Frankfurt, Germany',
'ns3' => 'Sydney, Australia',
// Add more as needed
];
if (file_exists($masterFile)) {
$content = file_get_contents($masterFile);
// Regex to match A records (IPv4)
preg_match_all('/(\S+)\s+IN\s+A\s+(\S+)/', $content, $aMatches);
// Regex to match AAAA records (IPv6)
preg_match_all('/(\S+)\s+IN\s+AAAA\s+(\S+)/', $content, $aaaaMatches);
$ipv4Records = array_combine($aMatches[1], $aMatches[2]);
$ipv6Records = array_combine($aaaaMatches[1], $aaaaMatches[2]);
foreach ($nsFilter as $nsName) {
$ipv4 = isset($ipv4Records[$nsName]) ? $ipv4Records[$nsName] : 'IPv4 not found';
$ipv6 = isset($ipv6Records[$nsName]) ? $ipv6Records[$nsName] : 'IPv6 not found';
$geographicalArea = isset($nsGeographicalAreas[$nsName]) ? $nsGeographicalAreas[$nsName] : 'Unknown Location';
$servers[] = [
'hostname' => $nsName,
'ipv4' => $ipv4,
'ipv6' => $ipv6,
'location' => $geographicalArea
];
}
}
return $servers;
}
$dnsServers = getDnsServersInfo();
// Function to check server status
//function checkServerStatus($server) {
// Ping command varies depending on the operating system
// This is an example for a Unix-like system
// $output = [];
// $status = null;
// exec("ping -c 1 -W 5000 " . escapeshellarg($server), $output, $status);
//
// return $status === 0 ? "Online" : "Offline";
//}
function checkServerStatus($server) {
$port = 53; // DNS port, change if necessary
$timeout = 10; // Timeout in seconds
$fp = @fsockopen($server, $port, $errno, $errstr, $timeout);
if ($fp) {
fclose($fp);
return "Online";
} else {
return "Offline";
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>|--===TildeNIC ===--| Bringing .tilde to the Tildeverse!</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<header>
<nav>
<?php if (!isset($_SESSION['username'])): ?>
<a href="/?page=login">Login</a> |
<a href="/?page=register">Register</a>
<?php else: ?>
<a href="/?page=main">Home</a> |
<a href="/?page=user_domains">My Account</a> |
<a href="/?page=domain_register">Register Domain</a> |
<a href="/?page=main&action=logout">Logout</a><br><br>
<span>Welcome, <?php echo htmlspecialchars($_SESSION['username']); ?></span>
<?php endif; ?>
</nav>
</header>
<div class="content">
<h1>Welcome to TildeNIC</h1>
<div class="info-section">
<p>TildeNIC is where you can request your .tilde top level domain. To do so, you need to first change your DNS over to one of the resolvers we offer, or you can self-host one.</p>
<ul>
<li><a href="https://tildegit.org/tildenic/.tilde/wiki/Setting-up-a-.tilde-DNS-server" target="_blank">Self-host information</a></li>
</ul>
<p><strong>NOTE!</strong> None of the servers currently listed are functional. They are old IP addresses. New servers will be online very soon!</p>
<h3>
<a href="https://opennic.org/" target="_blank">OpenNIC Information</a>
</h3>
<p>
Domains offered by OpenNIC are also able to be resolved using our servers, Such as:
<ul>
<li>.geek</li>
<li>.bbs</li>
<li>.gopher and more.</li>
</ul>
Will all resolve using our dns servers. For more information about OpenNIC you can visit <a href="https://opennic.org/" target="_blank">http://opennic.org</a>
</p>
</div>
<div class="server-list">
<h2>TildeNIC Available DNS Servers</h2>
<ul>
<?php foreach ($dnsServers as $server): ?>
<li>
<?php echo htmlspecialchars($server['hostname']); ?> -
IPv4: <?php echo htmlspecialchars($server['ipv4']); ?>,
IPv6: <?php echo htmlspecialchars($server['ipv6']); ?>,
Location: <?php echo htmlspecialchars($server['location']); ?> -
<span class="status <?php echo checkServerStatus($server['hostname']) === 'Online' ? 'online' : 'offline'; ?>">
<?php echo checkServerStatus($server['hostname']); ?>
</span>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</body>
<?php
require_once 'initdb.php';
session_start();
// Logout handling
if (isset($_GET['action']) && $_GET['action'] == 'logout') {
session_destroy();
header('Location: /');
exit;
}
// Function to get DNS server information from BIND files
function getDnsServersInfo() {
$masterFile = '../dottilde/db.master.tilde';
$servers = [];
$nsFilter = ['ns1', 'ns2', 'ns3']; // Add more nameserver identifiers as needed
// Manually assigned geographical areas for each nameserver
$nsGeographicalAreas = [
'ns1' => 'Quebec, Canada', // Replace with actual locations
'ns2' => 'Frankfurt, Germany',
'ns3' => 'Sydney, Australia',
// Add more as needed
];
if (file_exists($masterFile)) {
$content = file_get_contents($masterFile);
// Regex to match A records (IPv4)
preg_match_all('/(\S+)\s+IN\s+A\s+(\S+)/', $content, $aMatches);
// Regex to match AAAA records (IPv6)
preg_match_all('/(\S+)\s+IN\s+AAAA\s+(\S+)/', $content, $aaaaMatches);
$ipv4Records = array_combine($aMatches[1], $aMatches[2]);
$ipv6Records = array_combine($aaaaMatches[1], $aaaaMatches[2]);
foreach ($nsFilter as $nsName) {
$ipv4 = isset($ipv4Records[$nsName]) ? $ipv4Records[$nsName] : 'IPv4 not found';
$ipv6 = isset($ipv6Records[$nsName]) ? $ipv6Records[$nsName] : 'IPv6 not found';
$geographicalArea = isset($nsGeographicalAreas[$nsName]) ? $nsGeographicalAreas[$nsName] : 'Unknown Location';
$servers[] = [
'hostname' => $nsName,
'ipv4' => $ipv4,
'ipv6' => $ipv6,
'location' => $geographicalArea
];
}
}
return $servers;
}
$dnsServers = getDnsServersInfo();
// Function to check server status
function checkServerStatus($server) {
$port = 53; // DNS port, change if necessary
$timeout = 10; // Timeout in seconds
$fp = @fsockopen($server, $port, $errno, $errstr, $timeout);
if ($fp) {
fclose($fp);
return "Online";
} else {
return "Offline";
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>|--===TildeNIC ===--| Bringing .tilde to the Tildeverse!</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<header>
<nav>
<?php if (!isset($_SESSION['username'])): ?>
<a href="/?page=login">Login</a> |
<a href="/?page=register">Register</a>
<?php else: ?>
<a href="/?page=main">Home</a> |
<a href="/?page=user_domains">My Account</a> |
<a href="/?page=domain_register">Register Domain</a> |
<a href="/?page=main&action=logout">Logout</a><br><br>
<span>Welcome, <?php echo htmlspecialchars($_SESSION['username']); ?></span>
<?php endif; ?>
</nav>
</header>
<div class="content">
<h1>Welcome to TildeNIC</h1>
<div class="info-section">
<p>TildeNIC is where you can request your .tilde top level domain. To do so, you need to first change your DNS over to one of the resolvers we offer, or you can self-host one.</p>
<ul>
<li><a href="https://tildegit.org/tildenic/.tilde/wiki/Setting-up-a-.tilde-DNS-server" target="_blank">Self-host information</a></li>
</ul>
<h3>
<a href="https://opennic.org/" target="_blank">OpenNIC Information</a>
</h3>
<p>
Domains offered by OpenNIC are also able to be resolved using our servers, Such as:
<ul>
<li>.geek</li>
<li>.bbs</li>
<li>.gopher and more.</li>
</ul>
Will all resolve using our dns servers. For more information about OpenNIC you can visit <a href="https://opennic.org/" target="_blank">http://opennic.org</a>
</p>
</div>
<div class="server-list">
<h2>TildeNIC Available DNS Servers</h2>
<ul>
<?php foreach ($dnsServers as $server): ?>
<li>
<?php echo htmlspecialchars($server['hostname']); ?> -
IPv4: <?php echo htmlspecialchars($server['ipv4']); ?>,
IPv6: <?php echo htmlspecialchars($server['ipv6']); ?>,
Location: <?php echo htmlspecialchars($server['location']); ?> -
<span class="status <?php echo checkServerStatus($server['hostname']) === 'Online' ? 'online' : 'offline'; ?>">
<?php echo checkServerStatus($server['hostname']); ?>
</span>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</body>
</html>

View File

@ -3,9 +3,35 @@ require_once 'initdb.php';
session_start();
// Initialize error messages array if not set
if (!isset($_SESSION['error_messages'])) {
$_SESSION['error_messages'] = [];
}
// Session timeout logic
$timeout = 1800; // 30 minutes in seconds
if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > $timeout)) {
// Last request was more than 30 minutes ago
session_unset(); // Unset $_SESSION variable
session_destroy(); // Destroy session data
header("Location: /?page=login"); // Redirect to login page
exit;
}
$_SESSION['last_activity'] = time(); // Update last activity time
// Check if user IP or user agent has changed
if ((isset($_SESSION['user_ip']) && $_SESSION['user_ip'] !== $_SERVER['REMOTE_ADDR']) ||
(isset($_SESSION['user_agent']) && $_SESSION['user_agent'] !== $_SERVER['HTTP_USER_AGENT'])) {
session_unset();
session_destroy();
header("Location: /?page=login");
exit;
}
// Redirect to login if not logged in
if (!isset($_SESSION['username'])) {
header("Location: https://tildenic.org/?page=login");
header("Location: /?page=login");
exit;
}
@ -24,31 +50,76 @@ function getUserDomains($userId, $pdo) {
}
// Function to remove a domain
function removeDomain($domainId, $pdo) {
function removeDomain($domainId, $userId, $pdo) {
// First, verify that the domain belongs to the user
$stmt = $pdo->prepare("SELECT COUNT(*) FROM domains WHERE id = ? AND user_id = ?");
$stmt->execute([$domainId, $userId]);
$count = $stmt->fetchColumn();
if ($count == 0) {
// The domain does not belong to the user
return false;
}
// Proceed with deletion since the domain belongs to the user
$stmt = $pdo->prepare("DELETE FROM domains WHERE id = ?");
$stmt->execute([$domainId]);
return true;
}
// Function to update domain's IP address
function updateDomainIP($domainId, $ipAddress, $pdo) {
$stmt = $pdo->prepare("UPDATE domains SET ip_address = ? WHERE id = ?"); // Updating ip_address
function updateDomainIP($domainId, $userId, $ipAddress, $pdo) {
// Validate the IP address
if (!filter_var($ipAddress, FILTER_VALIDATE_IP)) {
// The IP address is not valid
return false;
}
// Verify that the domain belongs to the user
$stmt = $pdo->prepare("SELECT COUNT(*) FROM domains WHERE id = ? AND user_id = ?");
$stmt->execute([$domainId, $userId]);
$count = $stmt->fetchColumn();
if ($count == 0) {
// The domain does not belong to the user
return false;
}
// Proceed with IP address update since the domain belongs to the user
$stmt = $pdo->prepare("UPDATE domains SET ip_address = ? WHERE id = ?");
$stmt->execute([$ipAddress, $domainId]);
return true;
}
// Handle domain removal
if (isset($_GET['remove'])) {
removeDomain($_GET['remove'], $pdo);
header("Location: https://tildenic.org/?page=user_domains");
exit;
$userId = getUserId($_SESSION['username'], $pdo);
$domainId = $_GET['remove'];
$result = removeDomain($domainId, $userId, $pdo);
if ($result !== true) {
$_SESSION['error_messages'][] = "Error: You do not have permission to delete this domain.";
} else {
header("Location: https://tildenic.org/?page=user_domains");
exit;
}
}
// Handle IP address update
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['update_ip'])) {
$domainId = $_POST['domain_id'];
$userId = getUserId($_SESSION['username'], $pdo);
$ipAddress = $_POST['ip_address'];
updateDomainIP($domainId, $ipAddress, $pdo);
header("Location: https://tildenic.org/?page=user_domains");
exit;
$result = updateDomainIP($domainId, $userId, $ipAddress, $pdo);
if ($result !== true) {
$_SESSION['error_messages'][] = "Error: Invalid IP address or you do not have permission to update the IP address for this domain.";
} else {
header("Location: https://tildenic.org/?page=user_domains");
exit;
}
}
// Handle logout
if (isset($_POST['logout'])) {
@ -56,23 +127,62 @@ if (isset($_POST['logout'])) {
header("Location: https://tildenic.org/?page=login");
exit;
}
// Handle form submission
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Handle form submission for domain removal
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['remove_domain'])) {
$domainId = $_POST['domain_id'];
$userId = getUserId($_SESSION['username'], $pdo);
if (isset($_POST['update_ip'])) {
// Update IP address
$ipAddress = $_POST['ip_address'];
updateDomainIP($domainId, $ipAddress, $pdo);
} elseif (isset($_POST['remove_domain'])) {
// Remove domain
removeDomain($domainId, $pdo);
if (!removeDomain($domainId, $userId, $pdo)) {
$_SESSION['error_messages'][] = "Error: You do not have permission to delete this domain.";
} else {
header("Location: https://tildenic.org/?page=user_domains");
exit;
}
}
// Redirect to the user domains page after processing the form
if ($_SERVER["REQUEST_METHOD"] == "POST") {
header("Location: https://tildenic.org/?page=user_domains");
exit;
}
// Function to validate and update IP addresses for a user's domains
function validateAndUpdateIPs($userId, $pdo) {
// Fetch all domains for the user
$stmt = $pdo->prepare("SELECT id, ip_address FROM domains WHERE user_id = ?");
$stmt->execute([$userId]);
$domains = $stmt->fetchAll();
$invalidIPs = [];
foreach ($domains as $domain) {
$domainId = $domain['id'];
$ipAddress = $domain['ip_address'];
// Check if the IP address is valid
if (!empty($ipAddress) && !filter_var($ipAddress, FILTER_VALIDATE_IP)) {
// IP address is invalid, update the domain to remove the IP address
$updateStmt = $pdo->prepare("UPDATE domains SET ip_address = NULL WHERE id = ?");
$updateStmt->execute([$domainId]);
// Add to the list of domains with invalid IPs
$invalidIPs[] = $domainId;
}
}
return $invalidIPs;
}
// When the user accesses their domain management page
$userId = getUserId($_SESSION['username'], $pdo);
$invalidIPDomains = validateAndUpdateIPs($userId, $pdo);
if (!empty($invalidIPDomains)) {
// Inform the user that some IP addresses were invalid and have been removed
echo "Invalid IP addresses were found and removed from the following domains: " . implode(", ", $invalidIPDomains) . ". Please update them.";
}
$userId = getUserId($_SESSION['username'], $pdo);
$domains = getUserDomains($userId, $pdo);
?>
@ -99,6 +209,15 @@ $domains = getUserDomains($userId, $pdo);
<?php endif; ?>
</nav>
</header>
<!-- Error message display -->
<?php if (!empty($_SESSION['error_messages'])): ?>
<div class="error-messages">
<?php foreach ($_SESSION['error_messages'] as $message): ?>
<p><?php echo htmlspecialchars($message); ?></p>
<?php endforeach; ?>
<?php $_SESSION['error_messages'] = []; // Clear error messages after displaying ?>
</div>
<?php endif; ?><br>
<h2>Your Domains</h2>
<ul>
<?php foreach ($domains as $domain): ?>

1
webchangelog.log Normal file
View File

@ -0,0 +1 @@
2024-01-13 13:12:01 - Updated named.conf.local