diff options
-rw-r--r-- | app/class/Application.php | 32 | ||||
-rw-r--r-- | app/class/Config.php | 116 | ||||
-rw-r--r-- | app/class/Controllerconnect.php | 9 | ||||
-rw-r--r-- | app/class/Modelauthtoken.php | 10 | ||||
-rw-r--r-- | app/class/Modeluser.php | 20 | ||||
-rw-r--r-- | app/fn/fn.php | 13 |
6 files changed, 123 insertions, 77 deletions
diff --git a/app/class/Application.php b/app/class/Application.php index 70c899f..4ddf37e 100644 --- a/app/class/Application.php +++ b/app/class/Application.php @@ -41,7 +41,7 @@ class Application } else { if(Config::readconfig()) { - if(!Config::checkbasepath() || empty(Config::pagetable()) || !is_dir(Model::RENDER_DIR) || !Config::checkdomain()) { + if(!Config::checkbasepath() || empty(Config::pagetable()) || !is_dir(Model::RENDER_DIR) || !Config::checkdomain() || empty(Config::secretkey())) { echo '<ul>'; if(!Config::checkbasepath()) { echo '<li>Wrong path</li>'; @@ -55,6 +55,9 @@ class Application if(!is_dir(Model::RENDER_DIR)) { echo '<li>Render path not existing</li>'; } + if(!is_dir(Model::RENDER_DIR)) { + echo '<li>Secret Key not set or not valid</li>'; + } echo '</ul>'; $this->configform(); exit; @@ -84,18 +87,25 @@ class Application <form action="" method="post"> <div> - <h2> - <label for="basepath">Path to W-CMS</label> - </h2> - <input type="text" name="configinit[basepath]" value="<?= Config::basepath() ?>" id="basepath"> - <p><i>Leave it empty if W-CMS is in your root folder, otherwise, indicate the subfolder(s) in witch you installed the CMS</i></p> + <h2> + <label for="basepath">Path to W-CMS</label> + </h2> + <input type="text" name="configinit[basepath]" value="<?= Config::basepath() ?>" id="basepath"> + <p><i>Leave it empty if W-CMS is in your root folder, otherwise, indicate the subfolder(s) in witch you installed the CMS</i></p> </div> <div> - <h2> - <label for="pagetable">Name of your database table</label> - </h2> - <input type="text" name="configinit[pagetable]" value="<?= Config::pagetable() ?>" id="pagetable"> - <p><i>Set the name of the first folder that is going to store all your work</i></p> + <h2> + <label for="pagetable">Name of your database table</label> + </h2> + <input type="text" name="configinit[pagetable]" value="<?= Config::pagetable() ?>" id="pagetable"> + <p><i>Set the name of the first folder that is going to store all your work</i></p> + </div> + <div> + <h2> + <label for="secretkey">Secret Key</label> + </h2> + <input type="text" name="configinit[secretkey]" value="<?= bin2hex(random_bytes(10)) ?>" id="secretkey" minlength="16" maxlength="128" required> + <p><i>The secret key is used to secure cookies. There are no need to remind it. (16 to 128 characters)</i></p> </div> <input type="submit" value="set"> </form> diff --git a/app/class/Config.php b/app/class/Config.php index 2cfdcd3..4736410 100644 --- a/app/class/Config.php +++ b/app/class/Config.php @@ -11,7 +11,7 @@ abstract class Config protected static $domain = ''; protected static $fontsize = 15; protected static $basepath = ''; - protected static $route404; + protected static $route404; protected static $alerttitle = ''; protected static $alertlink = ''; protected static $alertlinktext = ''; @@ -22,10 +22,10 @@ abstract class Config protected static $privatepass = false; protected static $notpublishedpass = false; protected static $alertcss = false; - protected static $defaultbody = '%HEADER%'. PHP_EOL .PHP_EOL . '%NAV%'. PHP_EOL .PHP_EOL . '%ASIDE%'. PHP_EOL .PHP_EOL . '%MAIN%'. PHP_EOL .PHP_EOL . '%FOOTER%'; + protected static $defaultbody = '%HEADER%' . PHP_EOL . PHP_EOL . '%NAV%' . PHP_EOL . PHP_EOL . '%ASIDE%' . PHP_EOL . PHP_EOL . '%MAIN%' . PHP_EOL . PHP_EOL . '%FOOTER%'; protected static $defaultfavicon = ''; protected static $defaultthumbnail = ''; - protected static $analytics = ''; + protected static $analytics = ''; protected static $externallinkblank = true; protected static $internallinkblank = false; protected static $reccursiverender = true; @@ -34,10 +34,14 @@ abstract class Config protected static $homeredirect = null; protected static $interfacecss = null; protected static $bookmark = []; + protected static $secretkey = null; protected static $sentrydsn = ''; + const SECRET_KEY_MIN = 16; + const SECRET_KEY_MAX = 128; -// _______________________________________ F U N _______________________________________ + + // _______________________________________ F U N _______________________________________ @@ -92,9 +96,9 @@ abstract class Config /** * Calculate Domain name */ - public static function getdomain() - { - self::$domain = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST']; + public static function getdomain() + { + self::$domain = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST']; } /** @@ -109,12 +113,12 @@ abstract class Config * Generate full url adress where W is installed * @return string url adress finished by a slash "/" */ - public static function url($endslash = true) : string + public static function url($endslash = true): string { return self::$domain . (!empty(self::$basepath) ? '/' . self::$basepath : "") . ($endslash ? '/' : ''); } -// ________________________________________ G E T _______________________________________ + // ________________________________________ G E T _______________________________________ public static function pagetable() { @@ -134,9 +138,9 @@ abstract class Config /** * @param bool $trailingslash If not empty basepath, add a trailing slash after the basepath */ - public static function basepath(bool $trailingslash = false) : string + public static function basepath(bool $trailingslash = false): string { - if($trailingslash && !empty(self::$basepath)) { + if ($trailingslash && !empty(self::$basepath)) { return self::$basepath . '/'; } else { return self::$basepath; @@ -187,12 +191,12 @@ abstract class Config { return self::$privatepass; } - + public static function notpublishedpass() { return self::$notpublishedpass; } - + public static function alertcss() { return self::$alertcss; @@ -258,13 +262,18 @@ abstract class Config return self::$bookmark; } + public static function secretkey() + { + return self::$secretkey; + } + public static function sentrydsn() { return self::$sentrydsn; } -// __________________________________________ S E T ______________________________________ + // __________________________________________ S E T ______________________________________ public static function setpagetable($pagetable) { @@ -291,68 +300,68 @@ abstract class Config public static function setroute404($id) { - if(is_string($id)) { + if (is_string($id)) { self::$route404 = idclean($id); } } public static function setalerttitle($alerttitle) { - if(is_string($alerttitle)) { + if (is_string($alerttitle)) { self::$alerttitle = strip_tags($alerttitle); } } public static function setalertlink($alertlink) { - if(is_string($alertlink)) { + if (is_string($alertlink)) { self::$alertlink = idclean(strip_tags($alertlink)); } } public static function setalertlinktext($alertlinktext) { - if(is_string($alertlinktext)) { + if (is_string($alertlinktext)) { self::$alertlinktext = strip_tags($alertlinktext); } } public static function setexistnot($existnot) { - if(is_string($existnot)) { + if (is_string($existnot)) { self::$existnot = strip_tags($existnot); } } public static function setprivate($private) { - if(is_string($private)) { + if (is_string($private)) { self::$private = strip_tags($private); } } public static function setnotpublished($notpublished) { - if(is_string($notpublished)) { + if (is_string($notpublished)) { self::$notpublished = strip_tags($notpublished); } } - + public static function setexistnotpass($existnotpass) { self::$existnotpass = boolval($existnotpass); } - + public static function setprivatepass($privatepass) { self::$privatepass = boolval($privatepass); } - + public static function setnotpublishedpass($notpublishedpass) { self::$notpublishedpass = boolval($notpublishedpass); } - + public static function setalertcss($alertcss) { self::$alertcss = boolval($alertcss); @@ -360,32 +369,32 @@ abstract class Config public static function setdefaultbody($defaultbody) { - if(is_string($defaultbody)) { + if (is_string($defaultbody)) { self::$defaultbody = $defaultbody; } } public static function setdefaultfavicon($defaultfavicon) { - if(is_string($defaultfavicon)) { + if (is_string($defaultfavicon)) { self::$defaultfavicon = $defaultfavicon; } } public static function setdefaultthumbnail($defaultthumbnail) { - if(is_string($defaultthumbnail)) { + if (is_string($defaultthumbnail)) { self::$defaultthumbnail = $defaultthumbnail; } } public static function setanalytics($analytics) { - if(is_string($analytics) && strlen($analytics) < 25) { + if (is_string($analytics) && strlen($analytics) < 25) { self::$analytics = $analytics; } } - + public static function setexternallinkblank($externallinkblank) { self::$externallinkblank = boolval($externallinkblank); @@ -404,21 +413,21 @@ abstract class Config public static function setdefaultprivacy($defaultprivacy) { $defaultprivacy = intval($defaultprivacy); - if($defaultprivacy >= 0 && $defaultprivacy <= 2) { + if ($defaultprivacy >= 0 && $defaultprivacy <= 2) { self::$defaultprivacy = $defaultprivacy; } } public static function sethomepage($homepage) { - if(in_array($homepage, Model::HOMEPAGE)) { + if (in_array($homepage, Model::HOMEPAGE)) { self::$homepage = $homepage; } } public static function sethomeredirect($homeredirect) { - if(is_string($homeredirect) && strlen($homeredirect) > 0) { + if (is_string($homeredirect) && strlen($homeredirect) > 0) { self::$homeredirect = idclean($homeredirect); } else { self::$homeredirect = null; @@ -427,7 +436,7 @@ abstract class Config public static function setinterfacecss($interfacecss) { - if(is_string($interfacecss) && file_exists(Model::CSS_DIR . $interfacecss)) { + if (is_string($interfacecss) && file_exists(Model::CSS_DIR . $interfacecss)) { self::$interfacecss = $interfacecss; } else { self::$interfacecss = null; @@ -436,11 +445,24 @@ abstract class Config public static function setbookmark($bookmark) { - if(is_array($bookmark)) { + if (is_array($bookmark)) { self::$bookmark = $bookmark; } } + public static function setsecretkey($secretkey) + { + if (is_string($secretkey)) { + $stripedsecretkey = strip_tags($secretkey); + if ($stripedsecretkey === $secretkey) { + $length = strlen($secretkey); + if ($length < self::SECRET_KEY_MAX && $length > self::SECRET_KEY_MIN) { + self::$secretkey = $secretkey; + } + } + } + } + public static function setsentrydsn($sentrydsn) { if (is_string($sentrydsn)) { @@ -457,31 +479,17 @@ abstract class Config public static function addbookmark(string $id, string $query) { - if(!empty($id) && !empty($query)) { - $id = idclean($id); - $id = substr($id, 0, 16); - self::$bookmark[$id] = $query; + if (!empty($id) && !empty($query)) { + $id = idclean($id); + $id = substr($id, 0, 16); + self::$bookmark[$id] = $query; } } public static function deletebookmark(string $id) { - if(key_exists($id, self::$bookmark)) { + if (key_exists($id, self::$bookmark)) { unset(self::$bookmark[$id]); } } - - - - } - - - - - - - - - -?>
\ No newline at end of file diff --git a/app/class/Controllerconnect.php b/app/class/Controllerconnect.php index 816d69b..e9af86a 100644 --- a/app/class/Controllerconnect.php +++ b/app/class/Controllerconnect.php @@ -100,14 +100,16 @@ class Controllerconnect extends Controller /** * Create a cookie called `authtoken` * - * @param string $id Token string + * @param string $token Token string * @param int $conservation Time in day to keep the token * * @return bool True in cas of success, otherwise, false. */ - public function creatauthcookie(string $id, int $conservation): bool + public function creatauthcookie(string $token, int $conservation): bool { - return setcookie('authtoken', $id, time() + $conservation * 24 * 3600, null, null, false, true); + $hash = secrethash($token); + $cookie = $token . ':' . $hash; + return setcookie('authtoken', $cookie, time() + $conservation * 24 * 3600, null, null, false, true); } /** @@ -120,4 +122,5 @@ class Controllerconnect extends Controller //deleteauthcookie } + } diff --git a/app/class/Modelauthtoken.php b/app/class/Modelauthtoken.php index 0a55e64..18ef6a7 100644 --- a/app/class/Modelauthtoken.php +++ b/app/class/Modelauthtoken.php @@ -8,7 +8,7 @@ class Modelauthtoken extends Modeldb { const AUTHTOKEN_REPO_NAME = 'authtoken'; - + const AUTHTOKEN_ID_LENGTH = 30; public function __construct() { @@ -29,6 +29,14 @@ class Modelauthtoken extends Modeldb 'creationdate' => '1' ]; $tokendata = new Document($datas); + + $exist = true; + while ($exist !== false) { + $id = bin2hex(random_bytes(self::AUTHTOKEN_ID_LENGTH)); + $exist = $this->repo->findById($id); + } + + $tokendata->setId($id); return $this->repo->store($tokendata); } diff --git a/app/class/Modeluser.php b/app/class/Modeluser.php index 3f51920..9ee04ba 100644 --- a/app/class/Modeluser.php +++ b/app/class/Modeluser.php @@ -43,15 +43,19 @@ class Modeluser extends Modeldb return $user; } - if(isset($_COOKIE['authtoken'])) { + if(isset($_COOKIE['authtoken']) && strpos($_COOKIE['authtoken'], ':')) { + list($cookietoken, $cookiemac) = explode(':', $_COOKIE['authtoken']); $authtokenmanager = new Modelauthtoken(); - $token = $authtokenmanager->getbytoken($_COOKIE['authtoken']); - if ($token !== false) { - $user = $this->get($token->user); - if ($user !== false) { - $this->writesession($user, $_COOKIE['authtoken']); + $dbtoken = $authtokenmanager->getbytoken($cookietoken); + + if ($dbtoken !== false) { + if(hash_equals($cookiemac, secrethash($dbtoken->getId()))) { + $user = $this->get($dbtoken->user); + if ($user !== false) { + $this->writesession($user, $_COOKIE['authtoken']); + } + return $user; } - return $user; } } @@ -70,7 +74,7 @@ class Modeluser extends Modeldb /** - * @return array list of User objects + * @return User[] associative array of User objects `id => User` */ public function getlister() { diff --git a/app/fn/fn.php b/app/fn/fn.php index 3ca31c9..01e643b 100644 --- a/app/fn/fn.php +++ b/app/fn/fn.php @@ -324,6 +324,19 @@ function options(array $options, $selected = null) : string } +/** + * Hash a Token using secret key and sha256 + * + * @param string $token Input token + * + * @return string Hashed mac + */ +function secrethash(string $token) : string +{ + return hash_hmac('sha256', $token, Wcms\Config::secretkey()); +} + + |