Commit ad16763e authored by Mark Harding's avatar Mark Harding
Browse files

(chore): remove thumbs and guard

parent 97c5bbf5
<?php
/**
* Twofactor required Exception
*/
namespace Minds\Plugin\Guard\Exceptions;
class TwoFactorRequired extends \Exception
{
protected $code = "403";
}
<?php
/**
* Minds Subscriptions
*
* @version 1
* @author Mark Harding
*/
namespace minds\plugin\guard\api\v1;
use Minds\Core;
use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\plugin\guard\lib;
class twoFactor implements Interfaces\Api, Interfaces\ApiIgnorePam
{
/**
* NOT AVAILABLE
*/
public function get($pages)
{
return Factory::response(array('status'=>'error', 'message'=>'GET is not supported for this endpoint'));
}
/**
* Registers a user
* @param array $pages
*
* @SWG\Post(
* summary="Create a new channel",
* path="/v1/register",
* @SWG\Response(name="200", description="Array")
* )
*/
public function post($pages)
{
if (!Core\Security\XSRF::validateRequest()) {
return false;
}
$twofactor = new lib\twofactor();
//get our one user twofactor token
$lookup = new Core\Data\lookup('twofactor');
$return = $lookup->get($_POST['token']);
$lookup->remove($pages[0]);
//we allow for 120 seconds (2 mins) after we send a code
if ($return['_guid'] && $return['ts'] > time()-120) {
$user = new Entities\User($return['_guid']);
$secret = $return['secret'];
} else {
header('HTTP/1.1 401 Unauthorized', true, 401);
$response['status'] = 'error';
$response['message'] = 'Invalid token';
}
if ($twofactor->verifyCode($secret, $_POST['code'], 1)) {
global $TWOFACTOR_SUCCESS;
$TWOFACTOR_SUCCESS = true;
\login($user, true);
$response['status'] = 'success';
$response['user'] = $user->export();
} else {
header('HTTP/1.1 401 Unauthorized', true, 401);
$response['status'] = 'error';
$response['message'] = 'Could not verify.';
}
return Factory::response($response);
}
public function put($pages)
{
}
public function delete($pages)
{
}
}
<?php
$english = array(
'guard:twofactor' => 'Two factor authentication'
);
add_translation("en", $english);
<?php
/**
* A twofactor authentication plugin
*
* --- ORIGINAL --
*
* PHP Class for handling Google Authenticator 2-factor authentication
*
* @author Michael Kliewe
* @copyright 2012 Michael Kliewe
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.phpgangsta.de/
*
* ----------------
*
*/
namespace minds\plugin\guard\lib;
use Minds\Core;
class twofactor
{
protected $_codeLength = 6;
/**
* Create new secret.
* 16 characters, randomly chosen from the allowed base32 characters.
*
* @param int $secretLength
* @return string
*/
public function createSecret($secretLength = 16)
{
$validChars = $this->_getBase32LookupTable();
unset($validChars[32]);
$secret = '';
for ($i = 0; $i < $secretLength; $i++) {
$secret .= $validChars[array_rand($validChars)];
}
return $secret;
}
/**
* Calculate the code, with given secret and point in time
*
* @param string $secret
* @param int|null $timeSlice
* @return string
*/
public function getCode($secret, $timeSlice = null)
{
if ($timeSlice === null) {
$timeSlice = floor(time() / 30);
}
$secretkey = $this->_base32Decode($secret);
// Pack time into binary string
$time = chr(0).chr(0).chr(0).chr(0).pack('N*', $timeSlice);
// Hash it with users secret key
$hm = hash_hmac('SHA1', $time, $secretkey, true);
// Use last nipple of result as index/offset
$offset = ord(substr($hm, -1)) & 0x0F;
// grab 4 bytes of the result
$hashpart = substr($hm, $offset, 4);
// Unpak binary value
$value = unpack('N', $hashpart);
$value = $value[1];
// Only 32 bits
$value = $value & 0x7FFFFFFF;
$modulo = pow(10, $this->_codeLength);
return str_pad($value % $modulo, $this->_codeLength, '0', STR_PAD_LEFT);
}
/**
* Get QR-Code URL for image, from google charts
*
* @param string $name
* @param string $secret
* @return string
*/
public function getQRCodeGoogleUrl($name, $secret)
{
$urlencoded = urlencode('otpauth://totp/'.$name.'?secret='.$secret.'');
return 'https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl='.$urlencoded.'';
}
/**
* Check if the code is correct. This will accept codes starting from $discrepancy*30sec ago to $discrepancy*30sec from now
*
* @param string $secret
* @param string $code
* @param int $discrepancy This is the allowed time drift in 30 second units (8 means 4 minutes before or after)
* @return bool
*/
public function verifyCode($secret, $code, $discrepancy = 1)
{
$currentTimeSlice = floor(time() / 30);
for ($i = -$discrepancy; $i <= $discrepancy; $i++) {
$calculatedCode = $this->getCode($secret, $currentTimeSlice + $i);
if ($calculatedCode == $code) {
return true;
}
}
return false;
}
/**
* Set the code length, should be >=6
*
* @param int $length
* @return PHPGangsta_GoogleAuthenticator
*/
public function setCodeLength($length)
{
$this->_codeLength = $length;
return $this;
}
/**
* Helper class to decode base32
*
* @param $secret
* @return bool|string
*/
protected function _base32Decode($secret)
{
if (empty($secret)) {
return '';
}
$base32chars = $this->_getBase32LookupTable();
$base32charsFlipped = array_flip($base32chars);
$paddingCharCount = substr_count($secret, $base32chars[32]);
$allowedValues = array(6, 4, 3, 1, 0);
if (!in_array($paddingCharCount, $allowedValues)) {
return false;
}
for ($i = 0; $i < 4; $i++) {
if ($paddingCharCount == $allowedValues[$i] &&
substr($secret, -($allowedValues[$i])) != str_repeat($base32chars[32], $allowedValues[$i])) {
return false;
}
}
$secret = str_replace('=', '', $secret);
$secret = str_split($secret);
$binaryString = "";
for ($i = 0; $i < count($secret); $i = $i+8) {
$x = "";
if (!in_array($secret[$i], $base32chars)) {
return false;
}
for ($j = 0; $j < 8; $j++) {
$x .= str_pad(base_convert(@$base32charsFlipped[@$secret[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
}
$eightBits = str_split($x, 8);
for ($z = 0; $z < count($eightBits); $z++) {
$binaryString .= (($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48) ? $y:"";
}
}
return $binaryString;
}
/**
* Helper class to encode base32
*
* @param string $secret
* @param bool $padding
* @return string
*/
protected function _base32Encode($secret, $padding = true)
{
if (empty($secret)) {
return '';
}
$base32chars = $this->_getBase32LookupTable();
$secret = str_split($secret);
$binaryString = "";
for ($i = 0; $i < count($secret); $i++) {
$binaryString .= str_pad(base_convert(ord($secret[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
}
$fiveBitBinaryArray = str_split($binaryString, 5);
$base32 = "";
$i = 0;
while ($i < count($fiveBitBinaryArray)) {
$base32 .= $base32chars[base_convert(str_pad($fiveBitBinaryArray[$i], 5, '0'), 2, 10)];
$i++;
}
if ($padding && ($x = strlen($binaryString) % 40) != 0) {
if ($x == 8) {
$base32 .= str_repeat($base32chars[32], 6);
} elseif ($x == 16) {
$base32 .= str_repeat($base32chars[32], 4);
} elseif ($x == 24) {
$base32 .= str_repeat($base32chars[32], 3);
} elseif ($x == 32) {
$base32 .= $base32chars[32];
}
}
return $base32;
}
/**
* Get array with all 32 characters for decoding from/encoding to base32
*
* @return array
*/
protected function _getBase32LookupTable()
{
return array(
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
'=' // padding char
);
}
}
<?php
/**
* Two factor pages
*/
namespace minds\plugin\guard\pages;
use Minds\Core;
use Minds\Interfaces;
use Minds\Entities;
use minds\plugin\guard\lib;
class twofactor extends core\page implements Interfaces\page
{
public $csrf = false;
/**
* Get requests
*/
public function get($pages)
{
\elgg_set_context('settings');
$twofactor = new lib\twofactor();
$content .= \elgg_view_form('guard/twofactor/setup', array('action'=>\elgg_get_site_url().'settings/twofactor/setup'));
$body = \elgg_view_layout('content', array('title'=>\elgg_echo('guard:twofactor'), 'content'=>$content));
echo $this->render(array('body'=>$body));
}
public function post($pages)
{
invalidate_cache_for_entity(\elgg_get_logged_in_user_guid());
$user = \elgg_get_logged_in_user_entity();
$twofactor = new lib\twofactor();
switch ($pages[0]) {
case 'setup':
if (\get_input('disable')) {
$user->twofactor = false;
$user->save();
return $this->forward(REFERRER);
;
}
$user = \elgg_get_logged_in_user_entity();
$user->telno = \get_input('tel');
$user->save();
\minds\plugin\guard\start::sendSMS($user->telno, $twofactor->getCode($secret));
$content = 'We just sent you a text message. Please enter the code below';
$content .= \elgg_view_form('guard/twofactor/check', array('action'=>\elgg_get_site_url().'settings/twofactor/check/'.$secret));
break;
case 'check':
$secret = $pages[1];
$code = \get_input('code');
if ($twofactor->verifyCode($secret, $code, 1)) {
$content = 'Success! You are now setup for two-factor authentication';
$user->twofactor = true;
} else {
$content = 'Something didn\'t go to plan.. Please try again.';
$user->twofactor = false;
}
$user->save();
break;
default:
return false;
}
$body = \elgg_view_layout('content', array('content'=>$content));
echo $this->render(array('body'=>$body));
}
public function put($pages)
{
}
public function delete($pages)
{
}
}
<?php
/**
* Two factor pages
*/
namespace minds\plugin\guard\pages\twofactor;
use Minds\Core;
use Minds\Interfaces;
use Minds\Entities;
use minds\plugin\guard\lib;
class authorise extends core\page implements Interfaces\page
{
public $csrf = false;
/**
* Get requests
*/
public function get($pages)
{
/**
* Send our twofactor code to the user
*/
$content .= \elgg_view_form('guard/twofactor/authorise', array('action'=>\elgg_get_site_url().'login/twofactor/'.$pages[0], 'class'=>'elgg-form elgg-form-login'));
$body = \elgg_view_layout('one_column', array('content'=>$content));
echo $this->render(array('body'=>$body));
}
public function post($pages)
{
$twofactor = new lib\twofactor();
//get our one user twofactor token
$lookup = new \Minds\Core\Data\lookup('twofactor');
$return = $lookup->get($pages[0]);
$lookup->remove($pages[0]);
//we allow for 120 seconds (2 mins) after we send a code
if ($return['_guid'] && $return['ts'] > time()-120) {
$user = new \ElggUser($return['_guid']);
$secret = $return['secret'];
} else {
//no user could be found.. maybe because the token expired?
\register_error('Your token was invalid');
$this->forward('login');
return false;
}
if ($twofactor->verifyCode($secret, \get_input('code'), 1)) {
global $TWOFACTOR_SUCCESS;
$TWOFACTOR_SUCCESS = true;
\login($user, true);
$this->forward($user->getURL());
} else {
\register_error('Sorry, we could not verify your account');
$this->forward('/login');
}
}
public function put($pages)
{
}
public function delete($pages)
{
}
}
<?php
/**
* A minds security plugin
*
* - Prevents spam
* - Enabled twofactor authentication
*/
namespace minds\plugin\guard;
use Minds\Core\Di\Di;
use Minds\Components;
use Minds\Core;
use Minds\Api;
class start extends Components\Plugin
{
public function __construct($plugin)
{
parent::__construct($plugin);
$this->init();
}
public function init()
{
Api\Routes::add('v1/authenticate/two-factor', "\\minds\\plugin\\guard\\api\\v1\\twoFactor");
\elgg_register_event_handler('create', 'object', array($this, 'createHook'));
\elgg_register_event_handler('update', 'object', array($this, 'createHook'));
\elgg_register_event_handler('login', 'user', array($this,'loginHook'));
$routes = core\Router::registerRoutes($this->registerRoutes());
}
/**
* Handler the pages
*
* @param array $pages - the page slugs
* @return bool
*/
public function registerRoutes()
{
$path = "minds\\plugin\\guard";
return array(
'/settings/twofactor' => "$path\\pages\\twofactor",
'/login/twofactor' => "$path\\pages\\twofactor\authorise"
);
}
protected function prohbitedDomains()
{
return [
//shorts
// 't.co', 'goo.gl', 'ow.ly', 'bitly.com', 'bit.ly','tinyurl.com','bit.do','go2.do',
// 'adf.ly', 'adcrun.ch', 'zpag.es','ity.im', 'q.gs', 'lnk.co', 'is.gd',
//full
'movieblog.tumblr.com', 'moviehdstream.wordpress.com', 'moviehq.tumblr.com', 'moviehq.webs.com',
'moviehq.wordpress.com', 'movieo.wordpress.com', 'movieonline.tumblr.com', 'movieonline.webs.com',
'movieonline.wordpress.com', 'movieonlinehd.tumblr.com', 'movieonlinehd.webs.com', 'movieonlinehd.wordpress.com',
'movies.tumblr.com', 'moviesf.tumblr.com', 'moviesgodetia.com', 'movieslinks4u', 'moviesmount.com',
'moviesmonster.biz', 'moviesondesktop', 'moviesonlinefree.biz', 'moviestream.wordpress.com',
'movieontop.com', 'afllivestreaming.com.au', 'londonolympiccorner', 'nrllivestreaming.com.au',
'24x7livestreamtvchannels.com', 'www.edogo.us', 'all4health.in', 'watches4a.co.uk', 'es.jennyjoseph.com',
'allsportslive24x7.blogspot.com', 'boxing-tv-2014-live-stream.blogspot.com', 'amarblogdalima.blogspot.com',
'www.officialtvstream.com.es', 'topsalor.com', 'busybo.org', 'www.nowvideo.sx', '180upload.com', 'allmyvideos.net',
'busybo.org', 'hdmovieshouse.biz', 'sportblog.info', 'psport.space', 'discus.space', 'euro2016.it.ua', 'neymar.space',
'espnstream.space', '2016.vn.u', 'blogstream.space', 'liveextratime.xyz', 'thebestlive.xyz', 'streamoffside.xyz', 'sportmaster2014.page.tl',
'bloggersdelight.dk', 'watchsportslive.space', 'freeforward.xyz', 'live4sports.xyz', 'streamfun.xyz', 'angelfire.com', 'streamtime.xyz',
'futebol2star.com', 'live2sport.com', 'newssports.space', 'onlineolympics.xyz', 'liveolympics.xyz', 'streamontv.xyz', 'londonschedule.com',
'onlineolympics.space', 'sportwinning.xyz', 'streamworld.xyz', 'streamtop.xyz', 'livechampion.xyz', 'playstreams.xyz', 'live4sport.xyz',
'streampage.xyz', 'calendarsport.space', 'fsport.space', 'euro2016.od.ua', 'streambig.xyz', 'sportprediction.xyz', 'streamwork.xyz',
'r041.donnael.com', '2016.lt.ua', 'vipleague.se', 'liveonline.company', 'liveolympics.space', 'seoandvideomarketing.com.au', 'vipbox.sx',
'germanypolandlivestream.club', 'sportgoal.xyz', 'ggdbsale.com', 'gorillasteroids.eu', 'watchlivesports.space', 'penaltyshootout.xyz',
'streamgroup.xyz', 'streamnew.xyz', 'cottonsport.space', 'gosport.space', 'streambest.xyz', 'penaltyspot.xyz', 'streamthe.xyz',
'liveevents.name', 'londonblog.work', 'testcollections.com', 'alfagy.com', 'teravide1974.full-design.com', 'selfnarhasbllaq1980-blog.logdown.com',
'neipononchoi1984.suomiblog.com', 'gemttranlonthe1985.blogzet.com', 'pitchero.com', 'blogolize.com', 'lisbopholsven1974.thezenweb.com',
'blogocial.com', 'tinyblogging.com', 'share.pho.to', 'community.vietfun.com', 'ockuderla1985.full-design.com', 'unmosimla1978.total-blog.com',
'gemttranlonthe1985.blogzet.com', 'rapptubizboe1978.blogminds.com', 'descduclighgon1973.full-design.com', 'ricphosati1972.full-design.com',
'fuddbluslanmaa1975.blogdigy.com', 'smarforcute1976.blogdigy.com', 'xn--90aizihgi.xn--p1ai', 'tinyurl.com', 'bit.ly', '123football.space', 'bitly.com',
'j.mp', 'livestreaming.one', 'livestreaming.life', 'forbest.pw', 'olizev.tdska2ll.ru', 'tdska2ll.ru', 'tdska1ll.ru', 'tdska3ll.ru', 'tdska4ll.ru', 'ihmail.ru',
'tdska5ll.ru', 'tdska6ll.ru', 'll.ru', 'shorl.com', 'scorestream.space', 'bestsplayer.xyz', 'worldwideevents.space', 'worldseries.space', 'best247chemist.net',
'9tn.ru', 'futbolkin2013.ru', 'playnowstore.com', 'qr-url.tk', 'watchonlinerugby.net', 'esecuritys.com', 'rufile.no-ip.ca', 'imzonline.com', 'femeedia.com',
'mediomatic.com', 'savemoneyeasily.com', 'option1pro.com', 'perron07.nl', 'movieonrails.com', 'topmoviestoday.com', 'playnowstore.com', 'g-files.biz',
'dawnloadonline.com', 'thedirsite.com', 'siteslocate.com', 'mydrugdir.com', 'find24hs.com', 'veeble.org', 'movieonrails.com', 'bestmoviehd.net', 'putmovies.info',
'awarefinance.com', 'shurll.com', 'acceptsearch.com', 'signforcover.com', 'raisengine.com', 'rocketcarrental.com', 'godsearchs.com', 'listenhanced.com', 'find24hs.com',
'findinform.com', 'sitesworlds.com', 'rocketcarrental.com', 'thedirsite.com', 'getboook.com', 'pokerarena88.com', 'aquamelia.com', 'beautyskintalks.com', 'getmooovie.com',
'getdriversss.com', 'getsoooft.com', 'getgamesss.com', 'abrts.pro', 'leadbit.biz', 'efght.pro', 'qyresearcheurope.com', 'plusfreemaxfr.com', 'getappmac.com', 'getharlemhealthy.org',
'goo.gl', 'getmooovie.com', 'marketreportscenter.com', 'getsooft.com'
];
}
protected function strposa($haystack, $needles, $offset = 0)
{
if (!is_array($needles)) {
$needles = array($needles);
}
foreach ($needles as $query) {
if (strpos($haystack, $query, $offset) !== false) {
return true;