developer/stuff/methods/class_httpd.php

472 lines
20 KiB
PHP
Raw Normal View History

<?php
/**
* File: class_httpd.php.
* Author: Ulrich Block
* Date: 08.03.14
* Contact: <ulrich.block@easy-wi.com>
*
* This file is part of Easy-WI.
*
* Easy-WI is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Easy-WI is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Easy-WI. If not, see <http://www.gnu.org/licenses/>.
*
* Diese Datei ist Teil von Easy-WI.
*
* Easy-WI ist Freie Software: Sie koennen es unter den Bedingungen
* der GNU General Public License, wie von der Free Software Foundation,
* Version 3 der Lizenz oder (nach Ihrer Wahl) jeder spaeteren
* veroeffentlichten Version, weiterverbreiten und/oder modifizieren.
*
* Easy-WI wird in der Hoffnung, dass es nuetzlich sein wird, aber
* OHNE JEDE GEWAEHELEISTUNG, bereitgestellt; sogar ohne die implizite
* Gewaehrleistung der MARKTFAEHIGKEIT oder EIGNUNG FUER EINEN BESTIMMTEN ZWECK.
* Siehe die GNU General Public License fuer weitere Details.
*
* Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
* Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
*/
2016-03-20 10:24:41 +01:00
// Include PHPSeclib if not already included
if (!class_exists('SSH2')) {
include(EASYWIDIR . '/third_party/phpseclib/autoloader.php');
}
class HttpdManagement {
// Data
private $sql, $aeskey, $resellerID, $hostID, $ssh2Pass, $hostData = array(), $vhostData = false, $dataPrepared = false;
public $ssh2Object = false, $sftpObject = false, $masterNotfound = false;
public function __destruct() {
2014-11-08 12:56:01 +01:00
unset($this->sql, $this->aeskey, $this->hostID, $this->ssh2Object, $this->sftpObject);
}
public function __construct($hostID, $resellerID) {
// retrieve global vars
global $sql, $aeskey;
// define internal vars
$this->sql = $sql;
$this->aeskey = $aeskey;
$this->resellerID = $resellerID;
$query = $this->sql->prepare("SELECT *,AES_DECRYPT(`user`,:aeskey) AS `decrypteduser`,AES_DECRYPT(`pass`,:aeskey) AS `decryptedpass` FROM `webMaster` WHERE `webMasterID`=:id AND `resellerID`=:resellerID LIMIT 1");
$query->execute(array(':aeskey' => $this->aeskey, ':id' => $hostID, ':resellerID' => $this->resellerID));
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
if ($row['active'] == 'N') {
return false;
}
2015-05-14 18:06:34 +02:00
$this->hostData['defaultdns'] = $row['defaultdns'];
$this->hostData['ip'] = $row['ip'];
$this->hostData['port'] = $row['port'];
$this->hostData['ftpIP'] = (strlen($row['ftpIP']) > 0) ? $row['ftpIP'] : $row['ip'];
$this->hostData['ftpPort'] = $row['ftpPort'];
$this->hostData['user'] = $row['decrypteduser'];
$this->hostData['httpdCmd'] = $row['httpdCmd'];
$this->hostData['userGroup'] = $row['userGroup'];
$this->hostData['userAddCmd'] = $row['userAddCmd'];
$this->hostData['userModCmd'] = $row['userModCmd'];
$this->hostData['userDelCmd'] = $row['userDelCmd'];
$this->hostData['vhostStoragePath'] = $row['vhostStoragePath'];
$this->hostData['vhostConfigPath'] = $row['vhostConfigPath'];
$this->hostData['vhostTemplate'] = $row['vhostTemplate'];
$this->hostData['blocksize'] = $row['blocksize'];
$this->hostData['inodeBlockRatio'] = $row['inodeBlockRatio'];
$this->hostData['dirHttpd'] = $row['dirHttpd'];
$this->hostData['dirLogs'] = $row['dirLogs'];
2015-05-01 17:27:18 +02:00
$this->hostData['usageType'] = $row['usageType'];
2016-12-11 19:57:42 +01:00
$this->hostData['serverType'] = $row['serverType'];
$this->hostData['fpmConfigPath'] = $row['fpmConfigPath'];
$this->hostData['fpmTemplate'] = $row['fpmTemplate'];
$this->hostData['fpmCmd'] = $row['fpmCmd'];
$this->hostData['skelDir'] = $this->removeNotNeededSlashes($this->hostData['vhostStoragePath'] . '/' . $this->hostData['user'] . '/skel/');
if ($row['quotaActive'] == 'Y') {
$this->hostData['quotaCmd'] = $row['quotaCmd'];
$this->hostData['repquotaCmd'] = $row['repquotaCmd'];
}
if ($row['publickey'] != 'N') {
$privateKey = EASYWIDIR . '/keys/' . removePub($row['keyname']);
if (!file_exists($privateKey)) {
return false;
}
2016-03-20 10:24:41 +01:00
$this->ssh2Pass = new phpseclib\Crypt\RSA();
if ($row['publickey'] == 'B') {
2016-06-01 20:55:57 +02:00
$this->ssh2Pass->setPassword($row['decryptedpass']);
}
$this->ssh2Pass->loadKey(file_get_contents($privateKey));
} else {
$this->ssh2Pass = $row['decryptedpass'];
}
$this->dataPrepared = true;
return true;
}
$this->masterNotfound = true;
return false;
}
private function removeNotNeededSlashes ($value) {
return str_replace(array('//', '///'), '/', $value);
}
2016-12-11 19:57:42 +01:00
private function replacePHPConfiguration($phpConfigurationVhost, $templateFileContentTemp, $asIni = false) {
if ($phpConfigurationVhost and $this->hostData['usageType'] == 'W') {
preg_match('/(\s{1,}%phpConfiguration%)/', $templateFileContentTemp, $matches);
$match = array_shift($matches);
$whiteSpace = str_replace('%phpConfiguration%', '', $match);
$phpOptions = '';
foreach ($phpConfigurationVhost as $phpOption) {
if ($asIni) {
$phpOptions .= str_replace(' ', '] = ', str_replace('php_admin_flag ', 'php_admin_value[', str_replace('php_admin_value ', 'php_admin_value[', $phpOption))) . "\r\n";
} else {
$phpOptions .= $whiteSpace . $phpOption;
}
}
$templateFileContentTemp = str_replace('%phpConfiguration%', $phpOptions, $templateFileContentTemp);
} else {
$templateFileContentTemp = str_replace('%phpConfiguration%', '', $templateFileContentTemp);
}
return $templateFileContentTemp;
}
private function getVhostData ($vhostID) {
if ($this->vhostData == false) {
2016-12-11 19:57:42 +01:00
$query = $this->sql->prepare("SELECT v.`active`,v.`userID`,v.`description`,v.`hdd`,v.`ftpUser`,v.`phpConfiguration`,v.`defaultDomain`,v.`ownFPM`,v.`fpmConfiguration`,AES_DECRYPT(v.`ftpPassword`,?) AS `decryptedFTPPass`,u.`mail` FROM `webVhost` AS v INNER JOIN `userdata` AS u ON u.`id`=v.`userID` WHERE v.`webVhostID`=? AND v.`resellerID`=? LIMIT 1");
$query->execute(array($this->aeskey, $vhostID, $this->resellerID));
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
$this->vhostData['userID'] = $row['userID'];
$this->vhostData['hdd'] = $row['hdd'];
$this->vhostData['ftpUser'] = $row['ftpUser'];
$this->vhostData['ftpPassword'] = $row['decryptedFTPPass'];
2015-05-14 18:06:34 +02:00
$this->vhostData['vhostConfigFile'] = $this->removeNotNeededSlashes($this->hostData['vhostConfigPath'] . '/' . $this->vhostData['ftpUser']) . '.conf';
$this->vhostData['vhostHomeDir'] = $this->removeNotNeededSlashes($this->hostData['vhostStoragePath'] . '/' . $this->vhostData['ftpUser']);
$this->vhostData['description'] = (strlen($row['description']) > 0) ? $row['description'] : 'web-' . $vhostID;
$this->vhostData['defaultDomain'] = (isdomain($row['defaultDomain'])) ? $row['defaultDomain'] : 'web-' . $vhostID . '.' . $this->hostData['defaultdns'];
2015-05-01 17:27:18 +02:00
$phpConfigurationVhost = @json_decode($row['phpConfiguration']);
2015-05-14 18:06:34 +02:00
$this->vhostData['dns'] = array();
2016-12-11 19:57:42 +01:00
if (($this->hostData['serverType'] == 'N' or $this->hostData['serverType'] == 'L') and $this->hostData['usageType'] == 'W') {
$this->vhostData['fpmConfigPath'] = $this->removeNotNeededSlashes($this->hostData['fpmConfigPath'] . '/' . $this->vhostData['ftpUser']) . '.conf';
$this->vhostData['fpmFileContent'] = "; DO NOT EDIT DIRECTLY!\r\n; This file is autogenerated by easy-wi.com.\r\n; Date and time of generation was " . date('Y-m-d H:i:s') . "\r\n\r\n";
$fpmTemplate = $this->replacePHPConfiguration($phpConfigurationVhost, ($row['ownFPM'] == 'Y') ? $row['fpmConfiguration'] : $this->hostData['fpmTemplate'], true);
$this->vhostData['fpmFileContent'] .= str_replace(array('%user%', '%group%', '%vhostpath%', '%email%', '%htdocs%', '%logDir%'), array($row['ftpUser'], $this->hostData['userGroup'], $this->hostData['vhostStoragePath'], $row['mail'], $this->hostData['dirHttpd'], $this->hostData['dirLogs']), $fpmTemplate) . "\r\n";
}
2015-05-14 18:06:34 +02:00
// Workaround for migrations and other admin is breaking something faults
$query2 = $this->sql->prepare("SELECT 1 FROM `webVhostDomain` WHERE `webVhostID`=? LIMIT 1");
$query2->execute(array($vhostID));
if ($query2->rowCount() == 0) {
2015-05-01 17:27:18 +02:00
2015-05-14 18:06:34 +02:00
try {
$query2 = $this->sql->prepare("INSERT INTO `webVhostDomain` (`webVhostID`,`userID`,`resellerID`,`domain`,`path`,`ownVhost`,`vhostTemplate`) VALUES (?,?,?,?,'','N',?)");
$query2->execute(array($vhostID, $row['userID'], $this->resellerID, $this->vhostData['defaultDomain'], $this->hostData['vhostTemplate']));
// There is always a catch ...
} catch(PDOException $error) {
$error = $error->getMessage();
}
}
$this->vhostData['templateFileContent'] = "# DO NOT EDIT DIRECTLY!\r\n# This file is autogenerated by easy-wi.com.\r\n# Date and time of generation was " . date('Y-m-d H:i:s') . "\r\n\r\n";
2015-05-01 17:27:18 +02:00
2015-05-14 18:06:34 +02:00
$query2 = $this->sql->prepare("SELECT `path`,`domain`,`ownVhost`,`vhostTemplate` FROM `webVhostDomain` WHERE `webVhostID`=?");
$query2->execute(array($vhostID));
while ($row2 = $query2->fetch(PDO::FETCH_ASSOC)) {
2015-05-01 17:27:18 +02:00
$this->vhostData['dns'][] = $row2['domain'];
2016-12-11 19:57:42 +01:00
$templateFileContentTemp = $this->replacePHPConfiguration($phpConfigurationVhost, ($row2['ownVhost'] == 'Y') ? $row2['vhostTemplate'] : $this->hostData['vhostTemplate']);
2016-12-11 15:21:07 +01:00
$templateFileContentTemp = str_replace(array('%user%', '%group%', '%vhostpath%', '%email%', '%htdocs%', '%logDir%'), array($row['ftpUser'], $this->hostData['userGroup'], $this->hostData['vhostStoragePath'], $row['mail'], $this->hostData['dirHttpd'], $this->hostData['dirLogs']), $templateFileContentTemp) . "\r\n";
$templateFileContentTemp = str_replace(array('%path%', '%url%', '%domain%'), array($row2['path'], $row2['domain'], $row2['domain']), $templateFileContentTemp) . "\r\n";
2015-05-01 17:27:18 +02:00
2015-05-14 18:06:34 +02:00
$this->vhostData['templateFileContent'] .= $templateFileContentTemp;
2015-05-01 17:27:18 +02:00
}
return true;
}
} else {
return true;
}
return false;
}
private function addVhost ($vhostID, $fullAdd = true, $reinstall = false) {
if ($this->getVhostData($vhostID) != false) {
if ($this->ssh2Object != false) {
if ($fullAdd == true) {
$mailConnectInfo = array(
'ip' => $this->hostData['ftpIP'],
'port' => $this->hostData['ftpPort']
);
sendmail('emailserverinstall', $this->vhostData['userID'], $this->vhostData['description'], implode(', ', $this->vhostData['dns']), $mailConnectInfo);
$removeCmd = '';
if ($reinstall == true) {
$removeCmd = str_replace('%cmd%', ' -fr ' . $this->vhostData['ftpUser'], $this->hostData['userDelCmd']) . ' > /dev/null 2>&1; ';
}
$cmd = 'a() { ' . $removeCmd . str_replace('%cmd%', ' -md ' . $this->vhostData['vhostHomeDir'] . ' -p `perl -e \'print crypt("' . $this->vhostData['ftpPassword'] . '","Sa")\'` -g ' . $this->hostData['userGroup'] . ' -s /bin/false -k ' . $this->hostData['skelDir'] . ' '. $this->vhostData['ftpUser'], $this->hostData['userAddCmd']) . ' > /dev/null 2>&1; }; a';
$this->ssh2Object->exec($cmd);
}
if (isset($this->hostData['quotaCmd']) and strlen($this->hostData['quotaCmd']) > 0) {
// setquota works with KibiByte and Inodes
$sizeInKibiByte = $this->vhostData['hdd'] * 1024;
$sizeInByte = $this->vhostData['hdd'] * 1048576;
$blockAmount = round(($sizeInByte / $this->hostData['blocksize']));
$inodeAmount = round($blockAmount / $this->hostData['inodeBlockRatio']);
$cmd = 'q() { ' . str_replace('%cmd%', ' -u ' . $this->vhostData['ftpUser'] . ' ' . $sizeInKibiByte . ' ' . $sizeInKibiByte . ' ' . $inodeAmount . ' ' . $inodeAmount . ' -a ' . $this->removeNotNeededSlashes($this->hostData['vhostStoragePath'] . '/'), $this->hostData['quotaCmd']) . ' > /dev/null 2>&1; }; q&';
$this->ssh2Object->exec($cmd);
}
}
if ($this->sftpObject != false) {
2016-12-11 19:57:42 +01:00
$this->sftpObject->put($this->vhostData['vhostConfigFile'], $this->vhostData['templateFileContent']);
2016-12-11 19:57:42 +01:00
2018-01-06 13:12:03 +01:00
if (array_key_exists('fpmFileContent', $this->vhostData) and $this->vhostData['fpmFileContent'] != '') {
2016-12-11 19:57:42 +01:00
$this->sftpObject->put($this->vhostData['fpmConfigPath'], $this->vhostData['fpmFileContent']);
}
}
}
}
private function removeVhost ($vhostID, $fullRemove = true) {
if ($this->getVhostData($vhostID) != false) {
if ($this->sftpObject != false) {
$this->sftpObject->delete($this->vhostData['vhostConfigFile'], true);
2016-12-11 19:57:42 +01:00
if ($this->vhostData['fpmFileContent'] != '') {
$this->sftpObject->delete($this->vhostData['fpmConfigPath']);
}
}
if ($this->ssh2Object != false and $fullRemove == true) {
$cmd = 'r() { ' . str_replace('%cmd%', ' -fr ' . $this->vhostData['ftpUser'], $this->hostData['userDelCmd']) . ' > /dev/null 2>&1; }; r&';
$this->ssh2Object->exec($cmd);
}
$this->vhostData = false;
}
}
2016-06-01 20:55:57 +02:00
public function changePassword($vhostID, $newPassword = false) {
if ($this->getVhostData($vhostID) != false) {
if ($this->ssh2Object != false) {
$this->getVhostData($vhostID);
$password = ($newPassword == false) ? $this->vhostData['ftpPassword'] : $newPassword;
$cmd = 'p() { ' . str_replace('%cmd%', '-p `perl -e \'print crypt("' . $password . '","Sa")\'` ' . $this->vhostData['ftpUser'], $this->hostData['userModCmd']) . ' > /dev/null 2>&1; }; p&';
$this->ssh2Object->exec($cmd);
}
}
}
2016-06-01 20:55:57 +02:00
public function sftpConnect() {
if ($this->dataPrepared == false) {
return false;
}
2016-03-20 10:24:41 +01:00
$this->sftpObject = new phpseclib\Net\SFTP($this->hostData['ip'], $this->hostData['port']);
if ($this->sftpObject->login($this->hostData['user'], $this->ssh2Pass)) {
return true;
}
return false;
}
2016-06-01 20:55:57 +02:00
public function ssh2Connect() {
if ($this->dataPrepared == false) {
return false;
}
2016-03-20 10:24:41 +01:00
$this->ssh2Object = new phpseclib\Net\SSH2($this->hostData['ip'], $this->hostData['port']);
if ($this->ssh2Object->login($this->hostData['user'], $this->ssh2Pass)) {
return true;
}
return false;
}
2016-06-01 20:55:57 +02:00
public function setInactive($vhostID) {
2015-05-14 18:06:34 +02:00
$this->changePassword($vhostID, passwordgenerate(10));
$this->removeVhost($vhostID, false);
$this->vhostData = false;
}
2016-06-01 20:55:57 +02:00
public function vhostMod($vhostID) {
$this->addVhost($vhostID, false);
$this->changePassword ($vhostID);
$this->vhostData = false;
}
public function vhostCreate ($vhostID) {
$this->addVhost($vhostID);
$this->vhostData = false;
}
public function vhostDelete ($vhostID) {
$this->removeVhost($vhostID);
$this->vhostData = false;
}
public function vhostReinstall ($vhostID) {
$this->addVhost($vhostID, true, true);
$this->vhostData = false;
}
public function restartHttpdServer () {
if ($this->ssh2Object != false) {
2014-08-09 13:31:48 +02:00
$cmd = 'r() { ' . $this->hostData['httpdCmd'] . ' > /dev/null 2>&1; }; r&';
$this->ssh2Object->exec($cmd);
2016-12-11 19:57:42 +01:00
if (($this->hostData['serverType'] == 'N' or $this->hostData['serverType'] == 'L') and $this->hostData['usageType'] == 'W') {
$cmd = 'f() { ' . $this->hostData['fpmCmd'] . ' > /dev/null 2>&1; }; f&';
$this->ssh2Object->exec($cmd);
}
}
}
public function checkQuotaUsage () {
global $dbConnect;
if ($this->ssh2Object != false and isset($this->hostData['repquotaCmd']) and strlen($this->hostData['repquotaCmd']) > 0) {
2016-03-05 12:29:54 +01:00
$cmd = 'for DIR in `grep -E \'usrjquota=|usrquota\' /etc/fstab | awk \'{print $2}\'`; do for USER in `' . str_replace('%cmd%', '' ,$this->hostData['repquotaCmd']) . ' -u -v -s $DIR 2>/dev/null | grep \'web-\' | awk \'{print $1":"$3}\'`; do USERS="$USERS;$USER"; done; done; echo "$USERS;"';
$return = $this->ssh2Object->exec($cmd);
if (isset($dbConnect['debug']) and $dbConnect['debug'] == 1) {
echo "Execute command: {$cmd}\r\n";
echo "Command returns: {$return}\r\n";
}
2015-07-17 22:43:58 +02:00
$splitIntoHosts = preg_split('/;/', trim(preg_replace('/\s+/', '', $return)), -1, PREG_SPLIT_NO_EMPTY);
$query = $this->sql->prepare("UPDATE `webVhost` SET `hddUsage`=? WHERE `webVhostID`=? LIMIT 1");
2016-03-05 12:29:54 +01:00
if (count($splitIntoHosts) == 0) {
print "No web user found in server return: {$return}\r\n";
}
foreach ($splitIntoHosts as $ftpUser) {
unset($user, $usage, $webVhostID);
@list($user, $usage) = explode(':', $ftpUser);
@list($prefix, $webVhostID) = explode('-', $user);
if (isset($usage) and isset($webVhostID)) {
$webVhostID = (int) $webVhostID;
2015-07-17 22:29:33 +02:00
if (substr($usage, -1) == 'K') {
2015-07-17 22:43:58 +02:00
$usage = round(((int) substr($usage, 0, (strlen($usage) - 1))) / 1000);
2015-07-17 22:29:33 +02:00
} else if (substr($usage, -1) == 'M') {
$usage = (int) substr($usage, 0, (strlen($usage) - 1));
} else if (substr($usage, -1) == 'G') {
$usage = ((int) substr($usage, 0, (strlen($usage) - 1))) * 1000;
} else {
2015-07-17 22:43:58 +02:00
$usage = 0;
2015-07-17 22:29:33 +02:00
}
$query->execute(array($usage, $webVhostID));
if ($query->rowCount() > 0) {
print "Found and updated webhost with FTP user {$user}, webVhostID {$webVhostID} and a usage of {$usage} MB\r\n";
} else {
print "Cannot find or no update for webhost with FTP user {$user}, webVhostID {$webVhostID} which has a usage of {$usage} MB\r\n";
}
2016-03-05 12:29:54 +01:00
} else {
print "Cannot parse server return {$ftpUser}\r\n";
}
}
2016-02-27 08:27:48 +01:00
} else {
print "No SSH Connection or quota not allowed\r\n";
}
}
}