diff --git a/public/include/autoloader.inc.php b/public/include/autoloader.inc.php
index 1c8dba45..5bf2652f 100644
--- a/public/include/autoloader.inc.php
+++ b/public/include/autoloader.inc.php
@@ -53,6 +53,7 @@ require_once(CLASS_DIR . '/bitcoinwrapper.class.php');
require_once(CLASS_DIR . '/monitoring.class.php');
require_once(CLASS_DIR . '/notification.class.php');
require_once(CLASS_DIR . '/user.class.php');
+require_once(CLASS_DIR . '/csrftoken.class.php');
require_once(CLASS_DIR . '/invitation.class.php');
require_once(CLASS_DIR . '/share.class.php');
require_once(CLASS_DIR . '/worker.class.php');
diff --git a/public/include/classes/base.class.php b/public/include/classes/base.class.php
index d3dd18c1..d8bb23bb 100644
--- a/public/include/classes/base.class.php
+++ b/public/include/classes/base.class.php
@@ -73,6 +73,9 @@ class Base {
public function setTokenType($tokentype) {
$this->tokentype = $tokentype;
}
+ public function setCSRFToken($token) {
+ $this->CSRFToken = $token;
+ }
public function setShare($share) {
$this->share = $share;
}
diff --git a/public/include/classes/csrftoken.class.php b/public/include/classes/csrftoken.class.php
new file mode 100644
index 00000000..68f8e427
--- /dev/null
+++ b/public/include/classes/csrftoken.class.php
@@ -0,0 +1,74 @@
+salt; $salt2 = $this->salty; $seed = $salt1;
+ $lead = $this->config['csrf']['leadtime'];
+ $lead_sec = ($lead <= 11 && $lead >= 0) ? $lead : 3;
+ if ($minute == 59 && $second > (60-$lead_sec)) {
+ $minute = 0;
+ $fhour = ($hour == 23) ? $hour = 0 : $hour+=1;
+ }
+ $seed.= (strpos($timing, 'm') !== false) ? $month : '';
+ $seed.= (strpos($timing, 'd') !== false) ? $day : '';
+ $seed.= (strpos($timing, 'y') !== false) ? $year : '';
+ $seed.= (strpos($timing, 'H') !== false) ? $hour : '';
+ $seed.= (strpos($timing, 'i') !== false) ? $minute : '';
+ $seed.= (strpos($timing, 's') !== false) ? $second : '';
+ $seed.= ($seedExtra !== '') ? $seedExtra.$salt2 : $salt2;
+ return $this->getHash($seed);
+ }
+
+ /**
+ * Convenience method to get a token expired message with a token type, and ? image with description
+ * @param string $tokentype if you want a specific tokentype, set it here
+ * @param string $dowhat What will be put in the string "Simply $dowhat again to...", default is try
+ */
+ public static function getErrorWithDescriptionHTML($tokentype="", $dowhat="try") {
+ return ($tokentype !== "") ? "$tokentype token expired, please try again ".self::getDescriptionImageHTML($dowhat) : "Token expired, please try again ".self::getDescriptionImageHTML($dowhat);
+ }
+
+ /**
+ * Gets the HTML image (?) with short csrf description for users for the incorrect token error message
+ * @param dowhat string What will be put in the string "Simply $dowhat again to...", default is try
+ * @return string HTML image with description
+ */
+ public static function getDescriptionImageHTML($dowhat="try") {
+ $string = "
";
+ return $string;
+ }
+
+ private function getHash($string) {
+ return hash('sha256', $this->salty.$string.$this->salt);
+ }
+}
+
+$csrftoken = new CSRFToken();
+$csrftoken->setDebug($debug);
+$csrftoken->setMysql($mysqli);
+$csrftoken->setSalt(SALT);
+$csrftoken->setSalty(SALTY);
+$csrftoken->setMail($mail);
+$csrftoken->setUser($user);
+$csrftoken->setToken($oToken);
+$csrftoken->setConfig($config);
+$csrftoken->setErrorCodes($aErrorCodes);
+?>
\ No newline at end of file
diff --git a/public/include/classes/news.class.php b/public/include/classes/news.class.php
index f83e4253..f71ab7d8 100644
--- a/public/include/classes/news.class.php
+++ b/public/include/classes/news.class.php
@@ -102,4 +102,5 @@ $news = new News();
$news->setDebug($debug);
$news->setMysql($mysqli);
$news->setUser($user);
+$news->setErrorCodes($aErrorCodes);
?>
diff --git a/public/include/classes/token.class.php b/public/include/classes/token.class.php
index 902a6b90..4bcfc033 100644
--- a/public/include/classes/token.class.php
+++ b/public/include/classes/token.class.php
@@ -6,6 +6,15 @@ if (!defined('SECURITY')) die('Hacking attempt');
class Token Extends Base {
protected $table = 'tokens';
+ /**
+ * Return time token was created
+ * @param id int Token ID
+ * @param time string Creation timestamp
+ **/
+ public function getCreationTime($token) {
+ return $this->getSingle($token, 'time', 'token', 's');
+ }
+
/**
* Fetch a token from our table
* @param name string Setting name
@@ -27,13 +36,34 @@ class Token Extends Base {
* @param account_id int Account id of user
* @param token string Token to check
* @param type int Type of token
+ * @param checkTimeExplicitly Check the token time for expiration; can cause issues w/ timezone & sync
* @return int 0 or 1
*/
- public function isTokenValid($account_id, $token, $type) {
- $stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE account_id = ? AND token = ? AND type = ? AND UNIX_TIMESTAMP(time) < NOW() LIMIT 1");
- if ($stmt && $stmt->bind_param('isi', $account_id, $token, $type) && $stmt->execute())
- return $stmt->get_result()->num_rows;
- return $this->sqlError();
+ public function isTokenValid($account_id, $token, $type, $checkTimeExplicitly=false) {
+ if (!is_int($account_id) || !is_int($type)) {
+ $this->setErrorMessage("Invalid token");
+ return 0;
+ }
+ $expiretime = $this->tokentype->getExpiration($type);
+ $ctimedata = new DateTime($this->getCreationTime($token));
+ $checktime = $ctimedata->getTimestamp() + $expiretime;
+ $now = time();
+ if ($checktime >= $now && $checkTimeExplicitly || !$checkTimeExplicitly) {
+ if ($checkTimeExplicitly) {
+ $stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE account_id = ? AND token = ? AND type = ? AND ? >= UNIX_TIMESTAMP() LIMIT 1");
+ $stmt->bind_param('isii', $account_id, $token, $type, $checktime);
+ } else {
+ $stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE account_id = ? AND token = ? AND type = ? LIMIT 1");
+ $stmt->bind_param('isi', $account_id, $token, $type);
+ }
+ if ($stmt->execute())
+ $res = $stmt->get_result();
+ return $res->num_rows;
+ return $this->sqlError();
+ } else {
+ $this->setErrorMessage("Token has expired or is invalid");
+ return 0;
+ }
}
/**
diff --git a/public/include/classes/tools.class.php b/public/include/classes/tools.class.php
index 1cf4f875..0c573369 100644
--- a/public/include/classes/tools.class.php
+++ b/public/include/classes/tools.class.php
@@ -70,20 +70,25 @@ class Tools extends Base {
// Check the API type for configured URL
if (!$strApiType = $this->getApiType($this->config['price']['url']))
return false;
- // Extract price depending on API type
- switch ($strApiType) {
- case 'coinchose':
- foreach ($aData as $aItem) {
- if($strCurrency == $aItem[0])
- return $aItem['price'];
+ // if api data is valid, extract price depending on API type
+ if (is_array($aData)) {
+ switch ($strApiType) {
+ case 'coinchose':
+ foreach ($aData as $aItem) {
+ if($strCurrency == $aItem[0])
+ return $aItem['price'];
+ }
+ break;
+ case 'btce':
+ return $aData['ticker']['last'];
+ break;
+ case 'cryptsy':
+ return @$aData['return']['markets'][$strCurrency]['lasttradeprice'];
+ break;
}
- break;
- case 'btce':
- return $aData['ticker']['last'];
- break;
- case 'cryptsy':
- return $aData['return']['markets'][$strCurrency]['lasttradeprice'];
- break;
+ } else {
+ $this->setErrorMessage("Got an invalid response from ticker API");
+ return false;
}
// Catchall, we have no data extractor for this API url
$this->setErrorMessage("Undefined API to getPrice() on URL " . $this->config['price']['url']);
diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php
index 80cc346a..9bf67a6a 100644
--- a/public/include/classes/user.class.php
+++ b/public/include/classes/user.class.php
@@ -25,6 +25,9 @@ class User extends Base {
public function getUserEmail($username, $lower=false) {
return $this->getSingle($username, 'email', 'username', 's', $lower);
}
+ public function getUserNotifyEmail($username, $lower=false) {
+ return $this->getSingle($username, 'notify_email', 'username', 's', $lower);
+ }
public function getUserNoFee($id) {
return $this->getSingle($id, 'no_fees', 'id');
}
@@ -58,6 +61,9 @@ class User extends Base {
public function isAdmin($id) {
return $this->getUserAdmin($id);
}
+ public function getSignupTime($id) {
+ return $this->getSingle($id, 'signup_timestamp', 'id');
+ }
public function changeNoFee($id) {
$field = array('name' => 'no_fees', 'type' => 'i', 'value' => !$this->isNoFee($id));
return $this->updateSingle($id, $field);
@@ -145,11 +151,14 @@ class User extends Base {
$notifs->setSetting($this->setting);
$notifs->setErrorCodes($this->aErrorCodes);
$ndata = $notifs->getNotificationSettings($uid);
- if ($ndata['success_login'] == 1) {
+ if (@$ndata['success_login'] == 1) {
// seems to be active, let's send it
$aDataN['username'] = $username;
$aDataN['email'] = $this->getUserEmail($username);
$aDataN['subject'] = 'Successful login notification';
+ $aDataN['LOGINIP'] = $this->getCurrentIP();
+ $aDataN['LOGINUSER'] = $this->user;
+ $aDataN['LOGINTIME'] = date('m/d/y H:i:s');
$notifs->sendNotification($uid, 'success_login', $aDataN);
}
return true;
@@ -654,15 +663,15 @@ class User extends Base {
! $this->setting->getValue('accounts_confirm_email_disabled') ? $is_locked = 1 : $is_locked = 0;
$is_admin = 0;
$stmt = $this->mysqli->prepare("
- INSERT INTO $this->table (username, pass, email, pin, api_key, is_locked)
- VALUES (?, ?, ?, ?, ?, ?)
+ INSERT INTO $this->table (username, pass, email, signup_timestamp, pin, api_key, is_locked)
+ VALUES (?, ?, ?, ?, ?, ?, ?)
");
} else {
$is_locked = 0;
$is_admin = 1;
$stmt = $this->mysqli->prepare("
- INSERT INTO $this->table (username, pass, email, pin, api_key, is_admin, is_locked)
- VALUES (?, ?, ?, ?, ?, 1, ?)
+ INSERT INTO $this->table (username, pass, email, signup_timestamp, pin, api_key, is_admin, is_locked)
+ VALUES (?, ?, ?, ?, ?, ?, 1, ?)
");
}
@@ -671,8 +680,9 @@ class User extends Base {
$pin_hash = $this->getHash($pin);
$apikey_hash = $this->getHash($username);
$username_clean = strip_tags($username);
+ $signup_time = time();
- if ($this->checkStmt($stmt) && $stmt->bind_param('sssssi', $username_clean, $password_hash, $email1, $pin_hash, $apikey_hash, $is_locked) && $stmt->execute()) {
+ if ($this->checkStmt($stmt) && $stmt->bind_param('sssissi', $username_clean, $password_hash, $email1, $signup_time, $pin_hash, $apikey_hash, $is_locked) && $stmt->execute()) {
if (! $this->setting->getValue('accounts_confirm_email_disabled') && $is_admin != 1) {
if ($token = $this->token->createToken('confirm_email', $stmt->insert_id)) {
$aData['username'] = $username_clean;
@@ -794,26 +804,36 @@ class User extends Base {
}
/**
- * Gets the current CSRF token for this user/type setting and time chunk
- * @param string User; for hash seed, if username isn't available use IP
- * @param string Type of token; for hash seed, should be unique per page/use
- * @return string CSRF token
+ * Convenience function to get IP address, no params is the same as REMOTE_ADDR
+ * @param trustremote bool must be FALSE to checkclient or checkforwarded
+ * @param checkclient bool check HTTP_CLIENT_IP for a valid ip first
+ * @param checkforwarded bool check HTTP_X_FORWARDED_FOR for a valid ip first
+ * @return string IP address
*/
- public function getCSRFToken($user, $type) {
- $date = date('m/d/y/H/i/s');
- $data = explode('/', $date);
- $month = $data[0]; $day = $data[1]; $year = $data[2];
- $hour = $data[3]; $minute = $data[4]; $second = $data[5];
- $seed = $this->salty;
- $lead = $this->config['csrf']['options']['leadtime'];
- if ($lead >= 11) { $lead = 10; }
- if ($lead <= 0) { $lead = 3; }
- if ($minute == 59 && $second > (60-$lead)) {
- $minute = 0;
- $fhour = ($hour == 23) ? $hour = 0 : $hour+=1;
+ public function getCurrentIP($trustremote=true, $checkclient=false, $checkforwarded=false) {
+ $client = (isset($_SERVER['HTTP_CLIENT_IP'])) ? $_SERVER['HTTP_CLIENT_IP'] : false;
+ $fwd = (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : false;
+ $remote = (isset($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : @$_SERVER['REMOTE_ADDR'];
+ // shared internet
+ if (filter_var($client, FILTER_VALIDATE_IP) && !$trustremote && $checkclient) {
+ return $client;
+ } else if (strpos($fwd, ',') !== false && !$trustremote && $checkforwarded) {
+ // multiple proxies
+ $ips = explode(',', $fwd);
+ $path = array();
+ foreach ($ips as $ip) {
+ if (filter_var($ip, FILTER_VALIDATE_IP)) {
+ $path[] = $ip;
+ }
+ }
+ return array_pop($path);
+ } else if (filter_var($fwd, FILTER_VALIDATE_IP) && !$trustremote && $checkforwarded) {
+ // single
+ return $fwd;
+ } else {
+ // as usual
+ return $remote;
}
- $seed = $seed.$month.$day.$user.$type.$year.$hour.$minute.$seed;
- return $this->getHash($seed);
}
}
@@ -822,7 +842,6 @@ $user = new User();
$user->setDebug($debug);
$user->setMysql($mysqli);
$user->setSalt(SALT);
-$user->setSalty(SALTY);
$user->setSmarty($smarty);
$user->setConfig($config);
$user->setMail($mail);
diff --git a/public/include/config/global.inc.dist.php b/public/include/config/global.inc.dist.php
index 7c9eebba..35178f35 100644
--- a/public/include/config/global.inc.dist.php
+++ b/public/include/config/global.inc.dist.php
@@ -7,7 +7,7 @@ if (!defined('SECURITY')) die('Hacking attempt');
* This is used in the version check to ensure you run the latest version of the configuration file.
* Once you upgraded your config, change the version here too.
**/
-$config['version'] = '0.0.4';
+$config['version'] = '0.0.5';
// Our include directory for additional features
define('INCLUDE_DIR', BASEPATH . 'include');
@@ -134,18 +134,19 @@ $config['twofactor']['options']['changepw'] = true;
* form is submitted.
*
* Options:
- * enabled = Whether or not we will generate/check for valid CSRF tokens
- * leadtime = Length of time in seconds to give as leeway, 1-10s
- * login = Use and check CSRF tokens for the login forms
- *
+ * enabled = Whether or not we will generate/check for valid CSRF tokens
+ * leadtime = Length of time in seconds to give as leeway between minute switches
+ * * Don't change this unless you know why you're changing it
+ * disabled_forms = Which forms you want to disable csrf protection on, if enabled
+ * * Valid options : login, contact, accountedit, workers, notifications, invite, register, passreset, unlockaccount
* Default:
- * enabled = true
- * leadtime = 3
- * login = true
+ * enabled = true
+ * leadtime = 3
+ * disabled_forms = array();
*/
$config['csrf']['enabled'] = true;
-$config['csrf']['options']['leadtime'] = 3;
-$config['csrf']['forms']['login'] = true;
+$config['csrf']['leadtime'] = 3;
+$config['csrf']['disabled_forms'] = array();
/**
* Lock account after maximum failed logins
diff --git a/public/include/pages/account/edit.inc.php b/public/include/pages/account/edit.inc.php
index 8df98502..68b603eb 100644
--- a/public/include/pages/account/edit.inc.php
+++ b/public/include/pages/account/edit.inc.php
@@ -6,42 +6,54 @@ if (!defined('SECURITY'))
// twofactor stuff
$cp_editable = $wf_editable = $ea_editable = $wf_sent = $ea_sent = $cp_sent = 0;
-$ea_token = (!isset($_POST['ea_token'])) ? '' : $_POST['ea_token'];
-$cp_token = (!isset($_POST['cp_token'])) ? '' : $_POST['cp_token'];
-$wf_token = (!isset($_POST['wf_token'])) ? '' : $_POST['wf_token'];
-// set old token and type so we can use it later
-$old_token = "";
-$old_token_type = 0;
-if ($ea_token !== "") {
- $old_token = $ea_token;
- $old_token_type = 5;
-} else if ($wf_token !== "") {
- $old_token = $wf_token;
- $old_token_type = 7;
-} else if ($cp_token !== "") {
- $old_token_type = 6;
- $old_token = $cp_token;
+
+// 2fa - set old token so we can use it if an error happens or we need to use post
+$oldtoken_ea = (isset($_POST['ea_token']) && $_POST['ea_token'] !== '') ? $_POST['ea_token'] : @$_GET['ea_token'];
+$oldtoken_cp = (isset($_POST['cp_token']) && $_POST['cp_token'] !== '') ? $_POST['cp_token'] : @$_GET['cp_token'];
+$oldtoken_wf = (isset($_POST['wf_token']) && $_POST['wf_token'] !== '') ? $_POST['wf_token'] : @$_GET['wf_token'];
+$updating = (@$_POST['do']) ? 1 : 0;
+
+// csrf stuff
+$csrfenabled = ($config['csrf']['enabled'] && !in_array('accountedit', $config['csrf']['disabled_forms'])) ? 1 : 0;
+if ($csrfenabled) {
+ $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'editaccount') == @$_POST['ctoken']) ? 1 : 0;
}
if ($user->isAuthenticated()) {
if ($config['twofactor']['enabled']) {
$popupmsg = 'E-mail confirmations are required for ';
$popuptypes = array();
- if ($config['twofactor']['options']['details']) {
+ if ($config['twofactor']['options']['details'] && $oldtoken_ea !== "") {
$popuptypes[] = 'editing your details';
- $ea_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $ea_token, 5);
+ $ea_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $oldtoken_ea, 5);
$ea_sent = $user->token->doesTokenExist('account_edit', $_SESSION['USERDATA']['id']);
}
- if ($config['twofactor']['options']['changepw']) {
+ if ($config['twofactor']['options']['changepw'] && $oldtoken_cp !== "") {
$popuptypes[] = 'changing your password';
- $cp_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $cp_token, 6);
+ $cp_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $oldtoken_cp, 6);
$cp_sent = $user->token->doesTokenExist('change_pw', $_SESSION['USERDATA']['id']);
}
- if ($config['twofactor']['options']['withdraw']) {
+ if ($config['twofactor']['options']['withdraw'] && $oldtoken_wf !== "") {
$popuptypes[] = 'withdrawals';
- $wf_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $wf_token, 7);
+ $wf_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $oldtoken_wf, 7);
$wf_sent = $user->token->doesTokenExist('withdraw_funds', $_SESSION['USERDATA']['id']);
}
+
+ // get the status of a token if set
+ $message_tokensent_invalid = 'A token was sent to your e-mail that will allow you to ';
+ $message_tokensent_valid = 'You can currently ';
+ $messages_tokensent_status = array(
+ 'ea' => 'edit your account details',
+ 'wf' => 'withdraw funds',
+ 'cp' => 'change your password'
+ );
+ // build the message we're going to show them for their token(s)
+ $eaprep_sent = ($ea_sent) ? $message_tokensent_valid.$messages_tokensent_status['ea'] : "";
+ $eaprep_edit = ($ea_editable) ? $message_tokensent_invalid.$messages_tokensent_status['ea'] : "";
+ $wfprep_sent = ($wf_sent) ? $message_tokensent_valid.$messages_tokensent_status['wf'] : "";
+ $wfprep_edit = ($wf_editable) ? $message_tokensent_invalid.$messages_tokensent_status['wf'] : "";
+ $cpprep_sent = ($cp_sent) ? $message_tokensent_valid.$messages_tokensent_status['cp'] : "";
+ $cpprep_edit = ($cp_editable) ? $message_tokensent_invalid.$messages_tokensent_status['cp'] : "";
$ptc = 0;
$ptcn = count($popuptypes);
foreach ($popuptypes as $pt) {
@@ -53,13 +65,19 @@ if ($user->isAuthenticated()) {
}
$ptc++;
}
+ // display global notice about tokens being in use and for which bits they're active
$_SESSION['POPUP'][] = array('CONTENT' => $popupmsg, 'TYPE' => 'info');
}
+
if (isset($_POST['do']) && $_POST['do'] == 'genPin') {
- if ($user->generatePin($_SESSION['USERDATA']['id'], $_POST['currentPassword'])) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Your PIN # has been sent to your email.', 'TYPE' => 'success');
+ if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ if ($user->generatePin($_SESSION['USERDATA']['id'], $_POST['currentPassword'])) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Your PIN # has been sent to your email.', 'TYPE' => 'success');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg');
+ }
} else {
- $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg');
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
}
}
else {
@@ -71,26 +89,18 @@ if ($user->isAuthenticated()) {
$isvalid = in_array($_POST['utype'],$validtypes);
if ($isvalid) {
$ctype = strip_tags($_POST['utype']);
- $send = $user->sendChangeConfigEmail($ctype, $_SESSION['USERDATA']['id']);
- if ($send) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'A confirmation was sent to your e-mail, follow that link to continue', 'TYPE' => 'success');
+ if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ $send = $user->sendChangeConfigEmail($ctype, $_SESSION['USERDATA']['id']);
+ if ($send) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'A confirmation was sent to your e-mail, follow that link to continue', 'TYPE' => 'success');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg');
+ }
} else {
- $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg');
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
}
}
} else {
- // back to get, was only post to fix for old token
- $ea_token = (!isset($_GET['ea_token'])) ? '' : $_GET['ea_token'];
- $cp_token = (!isset($_GET['cp_token'])) ? '' : $_GET['cp_token'];
- $wf_token = (!isset($_GET['wf_token'])) ? '' : $_GET['wf_token'];
- if ($ea_token == '' && isset($_POST['ea_token']) && strlen($_POST['ea_token']) > 1) {
- $ea_token = $_POST['ea_token'];
- } else if ($ea_token == '' && isset($_POST['cp_token']) && strlen($_POST['cp_token']) > 1) {
- $cp_token = $_POST['cp_token'];
- } else if ($wf_token == '' && isset($_POST['wf_token']) && strlen($_POST['wf_token']) > 1) {
- $wf_token = $_POST['wf_token'];
- }
-
switch (@$_POST['do']) {
case 'cashOut':
if ($setting->getValue('disable_payouts') == 1 || $setting->getValue('disable_manual_payouts') == 1) {
@@ -100,10 +110,14 @@ if ($user->isAuthenticated()) {
$dBalance = $aBalance['confirmed'];
if ($dBalance > $config['txfee']) {
if (!$oPayout->isPayoutActive($_SESSION['USERDATA']['id'])) {
- if ($iPayoutId = $oPayout->createPayout($_SESSION['USERDATA']['id'], $wf_token)) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Created new manual payout request with ID #' . $iPayoutId);
+ if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ if ($iPayoutId = $oPayout->createPayout($_SESSION['USERDATA']['id'], $oldtoken_wf)) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Created new manual payout request with ID #' . $iPayoutId);
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $iPayoutId->getError(), 'TYPE' => 'errormsg');
+ }
} else {
- $_SESSION['POPUP'][] = array('CONTENT' => $iPayoutId->getError(), 'TYPE' => 'errormsg');
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
}
} else {
$_SESSION['POPUP'][] = array('CONTENT' => 'You already have one active manual payout request.', 'TYPE' => 'errormsg');
@@ -115,54 +129,74 @@ if ($user->isAuthenticated()) {
break;
case 'updateAccount':
- if ($user->updateAccount($_SESSION['USERDATA']['id'], $_POST['paymentAddress'], $_POST['payoutThreshold'], $_POST['donatePercent'], $_POST['email'], $_POST['is_anonymous'], $ea_token)) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Account details updated', 'TYPE' => 'success');
- } else {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update your account: ' . $user->getError(), 'TYPE' => 'errormsg');
- }
+ if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ if ($user->updateAccount($_SESSION['USERDATA']['id'], $_POST['paymentAddress'], $_POST['payoutThreshold'], $_POST['donatePercent'], $_POST['email'], $_POST['is_anonymous'], $oldtoken_ea)) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Account details updated', 'TYPE' => 'success');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update your account: ' . $user->getError(), 'TYPE' => 'errormsg');
+ }
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
+ }
break;
case 'updatePassword':
- if ($user->updatePassword($_SESSION['USERDATA']['id'], $_POST['currentPassword'], $_POST['newPassword'], $_POST['newPassword2'], $cp_token)) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Password updated', 'TYPE' => 'success');
- } else {
- $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg');
- }
+ if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ if ($user->updatePassword($_SESSION['USERDATA']['id'], $_POST['currentPassword'], $_POST['newPassword'], $_POST['newPassword2'], $oldtoken_cp)) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Password updated', 'TYPE' => 'success');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg');
+ }
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
+ }
break;
}
}
}
}
}
+
+
// 2fa - one last time so we can sync with changes we made during this page
if ($user->isAuthenticated() && $config['twofactor']['enabled']) {
- // set the token to be the old token so we still have it if it errors out
- if ($old_token_type == 5) {
- $ea_token = $old_token;
- } else if ($old_token_type == 7) {
- $wf_token = $old_token;
- } else if ($old_token_type == 6) {
- $cp_token = $old_token;
- }
- if ($config['twofactor']['options']['details']) {
+ // set the token to be the old token, just in case an error occured
+ $ea_token = (@$oldtoken_ea !== '') ? $oldtoken_ea : @$ea_token;
+ $wf_token = (@$oldtoken_wf !== '') ? $oldtoken_wf : @$wf_token;
+ $cp_token = (@$oldtoken_cp !== '') ? $oldtoken_cp : @$cp_token;
+ if ($config['twofactor']['options']['details'] && $ea_token !== "") {
$ea_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $ea_token, 5);
$ea_sent = $user->token->doesTokenExist('account_edit', $_SESSION['USERDATA']['id']);
}
- if ($config['twofactor']['options']['changepw']) {
+ if ($config['twofactor']['options']['changepw'] && $cp_token !== "") {
$cp_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $cp_token, 6);
$cp_sent = $user->token->doesTokenExist('change_pw', $_SESSION['USERDATA']['id']);
}
- if ($config['twofactor']['options']['withdraw']) {
+ if ($config['twofactor']['options']['withdraw'] && $wf_token !== "") {
$wf_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $wf_token, 7);
$wf_sent = $user->token->doesTokenExist('withdraw_funds', $_SESSION['USERDATA']['id']);
}
+
+ // display token info per each - only when sent and editable or just sent, not by default
+ (!empty($eaprep_sent) && !empty($eaprep_edit)) ? $_SESSION['POPUP'][] = array('CONTENT' => $eaprep_sent, 'TYPE' => 'success'):"";
+ (!empty($eaprep_sent) && empty($eaprep_edit)) ? $_SESSION['POPUP'][] = array('CONTENT' => $message_tokensent_invalid.$messages_tokensent_status['ea'], 'TYPE' => 'success'):"";
+ (!empty($wfprep_sent) && !empty($wfprep_edit)) ? $_SESSION['POPUP'][] = array('CONTENT' => $wfprep_sent, 'TYPE' => 'success'):"";
+ (!empty($wfprep_sent) && empty($wfprep_edit)) ? $_SESSION['POPUP'][] = array('CONTENT' => $message_tokensent_invalid.$messages_tokensent_status['wf'], 'TYPE' => 'success'):"";
+ (!empty($cpprep_sent) && !empty($cpprep_edit)) ? $_SESSION['POPUP'][] = array('CONTENT' => $cpprep_sent, 'TYPE' => 'success'):"";
+ (!empty($cpprep_sent) && empty($cpprep_edit)) ? $_SESSION['POPUP'][] = array('CONTENT' => $message_tokensent_invalid.$messages_tokensent_status['cp'], 'TYPE' => 'success'):"";
}
-// Tempalte specifics
-$smarty->assign("CONTENT", "default.tpl");
+
+// csrf stuff
$smarty->assign("CHANGEPASSUNLOCKED", $cp_editable);
$smarty->assign("WITHDRAWUNLOCKED", $wf_editable);
$smarty->assign("DETAILSUNLOCKED", $ea_editable);
$smarty->assign("CHANGEPASSSENT", $cp_sent);
$smarty->assign("WITHDRAWSENT", $wf_sent);
$smarty->assign("DETAILSSENT", $ea_sent);
+if ($csrfenabled && !in_array('accountedit', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'editaccount');
+ $smarty->assign('CTOKEN', $token);
+}
+// Tempalte specifics
+$smarty->assign("CONTENT", "default.tpl");
?>
diff --git a/public/include/pages/account/invitations.inc.php b/public/include/pages/account/invitations.inc.php
index 1fada08d..e3328f01 100644
--- a/public/include/pages/account/invitations.inc.php
+++ b/public/include/pages/account/invitations.inc.php
@@ -5,13 +5,22 @@ if (!defined('SECURITY')) die('Hacking attempt');
if ($user->isAuthenticated()) {
if (!$setting->getValue('disable_invitations')) {
+ // csrf stuff
+ $csrfenabled = ($config['csrf']['enabled'] && !in_array('invitations', $config['csrf']['disabled_forms'])) ? 1 : 0;
+ if ($csrfenabled) {
+ $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'invitations') == @$_POST['ctoken']) ? 1 : 0;
+ }
if ($invitation->getCountInvitations($_SESSION['USERDATA']['id']) >= $config['accounts']['invitations']['count']) {
$_SESSION['POPUP'][] = array('CONTENT' => 'You have exceeded the allowed invitations of ' . $config['accounts']['invitations']['count'], 'TYPE' => 'errormsg');
} else if (isset($_POST['do']) && $_POST['do'] == 'sendInvitation') {
- if ($invitation->sendInvitation($_SESSION['USERDATA']['id'], $_POST['data'])) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Invitation sent', 'TYPE' => 'success');
+ if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ if ($invitation->sendInvitation($_SESSION['USERDATA']['id'], $_POST['data'])) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Invitation sent', 'TYPE' => 'success');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to send invitation to recipient: ' . $invitation->getError(), 'TYPE' => 'errormsg');
+ }
} else {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to send invitation to recipient: ' . $invitation->getError(), 'TYPE' => 'errormsg');
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
}
}
$aInvitations = $invitation->getInvitations($_SESSION['USERDATA']['id']);
@@ -21,5 +30,10 @@ if ($user->isAuthenticated()) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Invitations are disabled', 'TYPE' => 'errormsg');
}
}
+// csrf token
+if ($csrfenabled && !in_array('invitations', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'invitations');
+ $smarty->assign('CTOKEN', $token);
+}
$smarty->assign('CONTENT', 'default.tpl');
?>
diff --git a/public/include/pages/account/notifications.inc.php b/public/include/pages/account/notifications.inc.php
index 49e18496..ff2f7c28 100644
--- a/public/include/pages/account/notifications.inc.php
+++ b/public/include/pages/account/notifications.inc.php
@@ -7,11 +7,21 @@ if ($user->isAuthenticated()) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Notification system disabled by admin.', 'TYPE' => 'info');
$smarty->assign('CONTENT', 'empty');
} else {
+ // csrf stuff
+ $csrfenabled = ($config['csrf']['enabled'] && !in_array('notifications', $config['csrf']['disabled_forms'])) ? 1 : 0;
+ if ($csrfenabled) {
+ $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'editnotifs') == @$_POST['ctoken']) ? 1 : 0;
+ }
+
if (@$_REQUEST['do'] == 'save') {
- if ($notification->updateSettings($_SESSION['USERDATA']['id'], $_REQUEST['data'])) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Updated notification settings', 'TYPE' => 'success');
+ if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ if ($notification->updateSettings($_SESSION['USERDATA']['id'], $_REQUEST['data'])) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Updated notification settings', 'TYPE' => 'success');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $notification->getError(), 'TYPE' => 'errormsg');
+ }
} else {
- $_SESSION['POPUP'][] = array('CONTENT' => $notification->getError(), 'TYPE' => 'errormsg');
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
}
}
@@ -22,6 +32,11 @@ if ($user->isAuthenticated()) {
// Fetch user notification settings
$aSettings = $notification->getNotificationSettings($_SESSION['USERDATA']['id']);
+ // csrf token
+ if ($csrfenabled && !in_array('notifications', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'editnotifs');
+ $smarty->assign('CTOKEN', $token);
+ }
$smarty->assign('NOTIFICATIONS', $aNotifications);
$smarty->assign('SETTINGS', $aSettings);
$smarty->assign('CONTENT', 'default.tpl');
diff --git a/public/include/pages/account/unlock.inc.php b/public/include/pages/account/unlock.inc.php
index fef18761..3fb4667e 100644
--- a/public/include/pages/account/unlock.inc.php
+++ b/public/include/pages/account/unlock.inc.php
@@ -3,18 +3,33 @@
// Make sure we are called from index.php
if (!defined('SECURITY')) die('Hacking attempt');
+// csrf stuff
+$csrfenabled = ($config['csrf']['enabled'] && !in_array('unlockaccount', $config['csrf']['disabled_forms'])) ? 1 : 0;
+if ($csrfenabled) {
+ $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'unlockaccount') == @$_POST['ctoken']) ? 1 : 0;
+}
+
// Confirm an account by token
if (!isset($_GET['token']) || empty($_GET['token'])) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Missing token', 'TYPE' => 'errormsg');
} else if (!$aToken = $oToken->getToken($_GET['token'], 'account_unlock')) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to re-activate your account. Invalid token.', 'TYPE' => 'errormsg');
} else {
- if ($user->setUserFailed($aToken['account_id'], 0) && $user->setUserPinFailed($aToken['account_id'], 0) && $user->changeLocked($aToken['account_id'])) {
- $oToken->deleteToken($aToken['token']);
- $_SESSION['POPUP'][] = array('CONTENT' => 'Account re-activated. Please login.');
+ if (!$csrfenabled || $csrfenabled && !$nocsrf) {
+ if ($user->setUserFailed($aToken['account_id'], 0) && $user->setUserPinFailed($aToken['account_id'], 0) && $user->changeLocked($aToken['account_id'])) {
+ $oToken->deleteToken($aToken['token']);
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Account re-activated. Please login.');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Failed to re-activate account. Contact site support.', 'TYPE' => 'errormsg');
+ }
} else {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Failed to re-activate account. Contact site support.', 'TYPE' => 'errormsg');
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
}
}
+// csrf token
+if ($csrfenabled && !in_array('unlockaccount', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'unlockaccount');
+ $smarty->assign('CTOKEN', $token);
+}
$smarty->assign('CONTENT', 'default.tpl');
?>
diff --git a/public/include/pages/account/workers.inc.php b/public/include/pages/account/workers.inc.php
index 3ccacfd3..42e03b3e 100644
--- a/public/include/pages/account/workers.inc.php
+++ b/public/include/pages/account/workers.inc.php
@@ -3,6 +3,12 @@
if (!defined('SECURITY')) die('Hacking attempt');
if ($user->isAuthenticated()) {
+ // csrf stuff
+ $csrfenabled = ($config['csrf']['enabled'] && !in_array('workers', $config['csrf']['disabled_forms'])) ? 1 : 0;
+ if ($csrfenabled) {
+ $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'workers') == @$_POST['ctoken']) ? 1 : 0;
+ }
+
switch (@$_REQUEST['do']) {
case 'delete':
if ($worker->deleteWorker($_SESSION['USERDATA']['id'], $_GET['id'])) {
@@ -12,17 +18,25 @@ if ($user->isAuthenticated()) {
}
break;
case 'add':
- if ($worker->addWorker($_SESSION['USERDATA']['id'], $_POST['username'], $_POST['password'])) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Worker added', 'TYPE' => 'success');
+ if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ if ($worker->addWorker($_SESSION['USERDATA']['id'], $_POST['username'], $_POST['password'])) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Worker added', 'TYPE' => 'success');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $worker->getError(), 'TYPE' => 'errormsg');
+ }
} else {
- $_SESSION['POPUP'][] = array('CONTENT' => $worker->getError(), 'TYPE' => 'errormsg');
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
}
break;
case 'update':
- if ($worker->updateWorkers($_SESSION['USERDATA']['id'], @$_POST['data'])) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Worker updated', 'TYPE' => 'success');
+ if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ if ($worker->updateWorkers($_SESSION['USERDATA']['id'], @$_POST['data'])) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Worker updated', 'TYPE' => 'success');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $worker->getError(), 'TYPE' => 'errormsg');
+ }
} else {
- $_SESSION['POPUP'][] = array('CONTENT' => $worker->getError(), 'TYPE' => 'errormsg');
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
}
break;
}
@@ -32,7 +46,10 @@ if ($user->isAuthenticated()) {
$smarty->assign('WORKERS', $aWorkers);
}
-
+// csrf token
+if ($csrfenabled && !in_array('workers', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'workers');
+ $smarty->assign('CTOKEN', $token);
+}
$smarty->assign('CONTENT', 'default.tpl');
-
?>
diff --git a/public/include/pages/contactform.inc.php b/public/include/pages/contactform.inc.php
index ad4a54c7..821f1a77 100644
--- a/public/include/pages/contactform.inc.php
+++ b/public/include/pages/contactform.inc.php
@@ -14,7 +14,11 @@ if ($setting->getValue('disable_contactform')) {
require_once(INCLUDE_DIR . '/lib/recaptchalib.php');
$smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key')));
}
-
+ // csrf token
+ if ($config['csrf']['enabled'] && !in_array('contact', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'contact');
+ $smarty->assign('CTOKEN', $token);
+ }
// Tempalte specifics
$smarty->assign("CONTENT", "default.tpl");
}
diff --git a/public/include/pages/contactform/contactform.inc.php b/public/include/pages/contactform/contactform.inc.php
index 28425bfd..3c85df09 100644
--- a/public/include/pages/contactform/contactform.inc.php
+++ b/public/include/pages/contactform/contactform.inc.php
@@ -3,7 +3,6 @@
// Make sure we are called from index.php
if (!defined('SECURITY')) die('Hacking attempt');
-
if ($setting->getValue('recaptcha_enabled')) {
// Load re-captcha specific data
require_once(INCLUDE_DIR . '/lib/recaptchalib.php');
@@ -15,19 +14,30 @@ if ($setting->getValue('recaptcha_enabled')) {
);
}
+// csrf if enabled
+$csrfenabled = ($config['csrf']['enabled'] && !in_array('contact', $config['csrf']['disabled_forms'])) ? 1 : 0;
+if ($csrfenabled) {
+ $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'contact') == @$_POST['ctoken']) ? 1 : 0;
+}
+
if ($setting->getValue('disable_contactform')) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Contactform is currently disabled. Please try again later.', 'TYPE' => 'errormsg');
} else if ($setting->getValue('disable_contactform') && !$user->isAuthenticated(false)) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Contactform is disabled for guests.', 'TYPE' => 'errormsg');
} else {
- // Check if recaptcha is enabled, process form data if valid
- if($setting->getValue('recaptcha_enabled') && $_POST["recaptcha_response_field"] && $_POST["recaptcha_response_field"]!=''){
+ if ($setting->getValue('recaptcha_enabled') && $_POST["recaptcha_response_field"] && $_POST["recaptcha_response_field"]!=''){
+ // Check if recaptcha is enabled, process form data if valid
if ($rsp->is_valid) {
- $smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key')));
- if ($mail->contactform($_POST['senderName'], $_POST['senderEmail'], $_POST['senderSubject'], $_POST['senderMessage'])) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Thanks for sending your message! We will get back to you shortly');
+ // Check if csrf is enabled and fail if token is invalid
+ if (!$nocsrf && $csrfenabled) {
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
} else {
- $_SESSION['POPUP'][] = array('CONTENT' => 'There was a problem sending your message. Please try again.' . $user->getError(), 'TYPE' => 'errormsg');
+ $smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key')));
+ if ($mail->contactform($_POST['senderName'], $_POST['senderEmail'], $_POST['senderSubject'], $_POST['senderMessage'])) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Thanks for sending your message! We will get back to you shortly');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'There was a problem sending your message. Please try again.' . $user->getError(), 'TYPE' => 'errormsg');
+ }
}
} else {
$smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key'), $rsp->error));
@@ -39,15 +49,22 @@ if ($setting->getValue('disable_contactform')) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Empty Captcha, please try again.', 'TYPE' => 'errormsg');
// Captcha disabled
} else {
- if ($mail->contactform($_POST['senderName'], $_POST['senderEmail'], $_POST['senderSubject'], $_POST['senderMessage'])) {
+ // Check if csrf is enabled and fail if token is invalid
+ if (!$nocsrf && $csrfenabled) {
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
+ } else if ($mail->contactform($_POST['senderName'], $_POST['senderEmail'], $_POST['senderSubject'], $_POST['senderMessage'])) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Thanks for sending your message! We will get back to you shortly');
- } else {
+ } else {
$_SESSION['POPUP'][] = array('CONTENT' => 'There was a problem sending your message. Please try again. ' . $user->getError(), 'TYPE' => 'errormsg');
}
}
}
+// csrf token
+if ($config['csrf']['enabled'] && !in_array('contact', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'contact');
+ $smarty->assign('CTOKEN', $token);
+}
// Tempalte specifics
$smarty->assign("CONTENT", "default.tpl");
-
?>
diff --git a/public/include/pages/home.inc.php b/public/include/pages/home.inc.php
index 4dffeb8a..3033c160 100644
--- a/public/include/pages/home.inc.php
+++ b/public/include/pages/home.inc.php
@@ -22,12 +22,11 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
} else {
$debug->append('Using cached page', 3);
}
-// csrf token - update if it's enabled
-$token = '';
-if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) {
- $token = $user->getCSRFToken($_SERVER['REMOTE_ADDR'], 'login');
+// csrf token
+if ($config['csrf']['enabled'] && !in_array('login', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'login');
+ $smarty->assign('CTOKEN', $token);
}
// Load news entries for Desktop site and unauthenticated users
$smarty->assign("CONTENT", "default.tpl");
-$smarty->assign('CTOKEN', $token);
?>
diff --git a/public/include/pages/login.inc.php b/public/include/pages/login.inc.php
index 7122d22b..09f5e1e8 100644
--- a/public/include/pages/login.inc.php
+++ b/public/include/pages/login.inc.php
@@ -3,6 +3,11 @@
// Make sure we are called from index.php
if (!defined('SECURITY')) die('Hacking attempt');
+// csrf if enabled
+$csrfenabled = ($config['csrf']['enabled'] && !in_array('login', $config['csrf']['disabled_forms'])) ? 1 : 0;
+if ($csrfenabled) {
+ $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'login') == @$_POST['ctoken']) ? 1 : 0;
+}
// ReCaptcha handling if enabled
if ($setting->getValue('recaptcha_enabled') && $setting->getValue('recaptcha_enabled_logins')) {
@@ -26,8 +31,18 @@ if ($setting->getValue('maintenance') && !$user->isAdmin($user->getUserId($_POST
$_SESSION['POPUP'][] = array('CONTENT' => 'You are not allowed to login during maintenace.', 'TYPE' => 'info');
} else if (!empty($_POST['username']) && !empty($_POST['password'])) {
$nocsrf = 1;
+ $recaptchavalid = 0;
+ if ($setting->getValue('recaptcha_enabled') && $setting->getValue('recaptcha_enabled_logins') && $rsp->is_valid) {
+ if ($rsp->is_valid) {
+ // recaptcha is enabled and valid
+ $recaptchavalid = 1;
+ } else {
+ // error out, invalid captcha
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to login: The captcha you entered was incorrect', 'TYPE' => 'errormsg');
+ }
+ }
if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) {
- if ((isset($_POST['ctoken']) && $_POST['ctoken'] !== $user->getCSRFToken($_SERVER['REMOTE_ADDR'], 'login')) || (!isset($_POST['ctoken']))) {
+ if ((isset($_POST['ctoken']) && $_POST['ctoken'] !== $csrftoken->getBasic($user->getCurrentIP(), 'login')) || (!isset($_POST['ctoken']))) {
// csrf protection is on and this token is invalid, error out -> time expired
$nocsrf = 0;
}
@@ -43,18 +58,15 @@ if ($setting->getValue('maintenance') && !$user->isAdmin($user->getUserId($_POST
} else {
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to login: '. $user->getError(), 'TYPE' => 'errormsg');
}
- } else if ($nocsrf == 0) {
- $img = "
";
- $_SESSION['POPUP'][] = array('CONTENT' => "Login token expired, please try again $img", 'TYPE' => 'info');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
}
}
-// csrf token - update if it's enabled
-$token = '';
-if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) {
- $token = $user->getCSRFToken($_SERVER['REMOTE_ADDR'], 'login');
+// csrf token
+if ($csrfenabled && !in_array('login', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'login');
+ $smarty->assign('CTOKEN', $token);
}
-
// Load login template
$smarty->assign('CONTENT', 'default.tpl');
-$smarty->assign('CTOKEN', $token);
?>
diff --git a/public/include/pages/logout.inc.php b/public/include/pages/logout.inc.php
index 6a537c1d..30425851 100644
--- a/public/include/pages/logout.inc.php
+++ b/public/include/pages/logout.inc.php
@@ -7,5 +7,4 @@ if (!defined('SECURITY'))
// This probably (?) never fails
$user->logoutUser();
$smarty->assign("CONTENT", "default.tpl");
-// header('Location: index.php?page=home');
?>
diff --git a/public/include/pages/password.inc.php b/public/include/pages/password.inc.php
index aecab054..adc1047a 100644
--- a/public/include/pages/password.inc.php
+++ b/public/include/pages/password.inc.php
@@ -4,6 +4,11 @@
if (!defined('SECURITY'))
die('Hacking attempt');
+// csrf token
+if ($config['csrf']['enabled'] && !in_array('passreset', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'resetpass');
+ $smarty->assign('CTOKEN', $token);
+}
// Tempalte specifics
$smarty->assign("CONTENT", "default.tpl");
?>
diff --git a/public/include/pages/password/change.inc.php b/public/include/pages/password/change.inc.php
index d8815b1d..2c3e08a0 100644
--- a/public/include/pages/password/change.inc.php
+++ b/public/include/pages/password/change.inc.php
@@ -4,13 +4,31 @@
if (!defined('SECURITY'))
die('Hacking attempt');
-if (isset($_POST['do']) && $_POST['do'] == 'resetPassword') {
- if ($user->resetPassword($_POST['token'], $_POST['newPassword'], $_POST['newPassword2'])) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Password reset complete! Please login.', 'TYPE' => 'success');
- } else {
- $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg');
- }
+// csrf stuff
+$csrfenabled = ($config['csrf']['enabled'] && !in_array('passreset', $config['csrf']['disabled_forms'])) ? 1 : 0;
+if ($csrfenabled) {
+ // we have to use editaccount token because this that's where we'll get pushed here from
+ $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'editaccount') == @$_POST['ctoken']) ? 1 : 0;
}
+
+if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ if (isset($_POST['do']) && $_POST['do'] == 'resetPassword') {
+ if ($user->resetPassword($_POST['token'], $_POST['newPassword'], $_POST['newPassword2'])) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Password reset complete! Please login.', 'TYPE' => 'success');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg');
+ }
+ }
+} else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
+}
+
+// csrf token
+if ($config['csrf']['enabled'] && !in_array('passreset', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'editaccount');
+ $smarty->assign('CTOKEN', $token);
+}
+
// Tempalte specifics
$smarty->assign("CONTENT", "default.tpl");
diff --git a/public/include/pages/password/reset.inc.php b/public/include/pages/password/reset.inc.php
index cefba0ac..a32ce104 100644
--- a/public/include/pages/password/reset.inc.php
+++ b/public/include/pages/password/reset.inc.php
@@ -3,13 +3,28 @@
// Make sure we are called from index.php
if (!defined('SECURITY')) die('Hacking attempt');
-// Process password reset request
-if ($user->initResetPassword($_POST['username'], $smarty)) {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mail account to finish your password reset', 'TYPE' => 'success');
-} else {
- $_SESSION['POPUP'][] = array('CONTENT' => htmlentities($user->getError(), ENT_QUOTES), 'TYPE' => 'errormsg');
+// csrf stuff
+$csrfenabled = ($config['csrf']['enabled'] && !in_array('passreset', $config['csrf']['disabled_forms'])) ? 1 : 0;
+if ($csrfenabled) {
+ $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'resetpass') == @$_POST['ctoken']) ? 1 : 0;
}
+// Process password reset request
+if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ if ($user->initResetPassword($_POST['username'], $smarty)) {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mail account to finish your password reset', 'TYPE' => 'success');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => htmlentities($user->getError(), ENT_QUOTES), 'TYPE' => 'errormsg');
+ }
+} else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
+}
+
+// csrf token
+if ($config['csrf']['enabled'] && !in_array('passreset', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'resetpass');
+ $smarty->assign('CTOKEN', $token);
+}
// Tempalte specifics, user default template by parent page
$smarty->assign("CONTENT", "../default.tpl");
?>
diff --git a/public/include/pages/register.inc.php b/public/include/pages/register.inc.php
index 692c3e42..487e67cb 100644
--- a/public/include/pages/register.inc.php
+++ b/public/include/pages/register.inc.php
@@ -14,6 +14,12 @@ if ($setting->getValue('lock_registration') && $setting->getValue('disable_invit
require_once(INCLUDE_DIR . '/lib/recaptchalib.php');
$smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key'), null, true));
}
+ // csrf token
+ if ($config['csrf']['enabled'] && !in_array('register', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'register');
+ $smarty->assign('CTOKEN', $token);
+ }
+ // Load news entries for Desktop site and unauthenticated users
$smarty->assign("CONTENT", "default.tpl");
}
?>
diff --git a/public/include/pages/register/register.inc.php b/public/include/pages/register/register.inc.php
index 7090a1c4..26fd12f5 100644
--- a/public/include/pages/register/register.inc.php
+++ b/public/include/pages/register/register.inc.php
@@ -14,6 +14,13 @@ if ($setting->getValue('recaptcha_enabled') && $setting->getValue('recaptcha_ena
);
$smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key'), $rsp->error, true));
if (!$rsp->is_valid) $_SESSION['POPUP'][] = array('CONTENT' => 'Invalid Captcha, please try again.', 'TYPE' => 'errormsg');
+ $recaptcha = ($rsp->isvalid) ? 1 : 0;
+}
+
+// csrf if enabled
+$csrfenabled = ($config['csrf']['enabled'] && !in_array('register', $config['csrf']['disabled_forms'])) ? 1 : 0;
+if ($csrfenabled) {
+ $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'register') == $_POST['ctoken']) ? 1 : 0;
}
if ($setting->getValue('disable_invitations') && $setting->getValue('lock_registration')) {
@@ -21,17 +28,27 @@ if ($setting->getValue('disable_invitations') && $setting->getValue('lock_regist
} else if ($setting->getValue('lock_registration') && !$setting->getValue('disable_invitations') && !isset($_POST['token'])) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Only invited users are allowed to register.', 'TYPE' => 'errormsg');
} else {
- // Check if recaptcha is enabled, process form data if valid or disabled
- if ($setting->getValue('recaptcha_enabled') != 1 || $setting->getValue('recaptcha_enabled_registrations') != 1 || $rsp->is_valid) {
- isset($_POST['token']) ? $token = $_POST['token'] : $token = '';
- if ($user->register(@$_POST['username'], @$_POST['password1'], @$_POST['password2'], @$_POST['pin'], @$_POST['email1'], @$_POST['email2'], @$_POST['tac'], $token)) {
- ! $setting->getValue('accounts_confirm_email_disabled') ? $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mailbox to activate this account') : $_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
- } else {
- $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg');
+ // Check if csrf is enabled and fail if token is invalid
+ if (!$csrfenabled || $csrfenabled && $nocsrf) {
+ if ($setting->getValue('recaptcha_enabled') != 1 || $setting->getValue('recaptcha_enabled_registrations') != 1 || $rsp->is_valid) {
+ // Check if recaptcha is enabled, process form data if valid or disabled
+ isset($_POST['token']) ? $token = $_POST['token'] : $token = '';
+ if ($user->register(@$_POST['username'], @$_POST['password1'], @$_POST['password2'], @$_POST['pin'], @$_POST['email1'], @$_POST['email2'], @$_POST['tac'], $token)) {
+ ! $setting->getValue('accounts_confirm_email_disabled') ? $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mailbox to activate this account') : $_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg');
+ }
}
+ } else {
+ $_SESSION['POPUP'][] = array('CONTENT' => $csrftoken->getErrorWithDescriptionHTML(), 'TYPE' => 'info');
}
}
// We load the default registration template instead of an action specific one
$smarty->assign("CONTENT", "../default.tpl");
+// csrf token
+if ($config['csrf']['enabled'] && !in_array('register', $config['csrf']['disabled_forms'])) {
+ $token = $csrftoken->getBasic($user->getCurrentIP(), 'register');
+ $smarty->assign('CTOKEN', $token);
+}
?>
diff --git a/public/include/version.inc.php b/public/include/version.inc.php
index 21dd0010..c5734b85 100644
--- a/public/include/version.inc.php
+++ b/public/include/version.inc.php
@@ -4,8 +4,8 @@
if (!defined('SECURITY')) die('Hacking attempt');
define('MPOS_VERSION', '0.0.2');
-define('DB_VERSION', '0.0.3');
-define('CONFIG_VERSION', '0.0.4');
+define('DB_VERSION', '0.0.4');
+define('CONFIG_VERSION', '0.0.5');
// Fetch installed database version
$db_version = $setting->getValue('DB_VERSION');
diff --git a/public/templates/mail/notifications/success_login.tpl b/public/templates/mail/notifications/success_login.tpl
index df92934b..e1a07bac 100644
--- a/public/templates/mail/notifications/success_login.tpl
+++ b/public/templates/mail/notifications/success_login.tpl
@@ -1,6 +1,9 @@
Your account has successfully logged in
+User: {$LOGINUSER}
+IP: {$LOGINIP}
+Time: {$LOGINTIME}
If you initiated this login, you can ignore this message. If you did NOT, please notify an administrator.