Merge pull request #3970 from MrPetovan/task/3942-add-user-authenticate

Migrate password hashing Part 1: Add User::authenticate
This commit is contained in:
Michael Vogel 2017-11-27 15:14:36 +01:00 committed by GitHub
commit 3f448d9a42
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 205 additions and 268 deletions

View file

@ -1,22 +1,71 @@
<?php
/**
* @file src/Model/User.php
* @brief This file includes the User class with user related database functions
*/
namespace Friendica\Model;
use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBM;
use dba;
require_once 'boot.php';
require_once 'plugin.php';
require_once 'include/plugin.php';
/**
* @brief This class handles User related functions
*/
class User
{
public static function authenticate($user_info, $password)
{
if (is_object($user_info)) {
$user = (array) $user_info;
} elseif (is_int($user_info)) {
$user = dba::select('user',
['uid', 'password'],
[
'uid' => $user_info,
'blocked' => 0,
'account_expired' => 0,
'account_removed' => 0,
'verified' => 1
],
['limit' => 1]
);
} elseif (is_string($user_info)) {
$user = dba::fetch_first('SELECT `uid`, `password`
FROM `user`
WHERE (`email` = ? OR `username` = ? OR `nickname` = ?)
AND `blocked` = 0
AND `account_expired` = 0
AND `account_removed` = 0
AND `verified` = 1
LIMIT 1',
$user_info,
$user_info,
$user_info
);
} else {
$user = $user_info;
}
if (!DBM::is_result($user) || !isset($user['uid']) || !isset($user['password'])) {
return false;
}
$password_hashed = hash('whirlpool', $password);
if ($password_hashed !== $user['password']) {
return false;
}
return $user['uid'];
}
/**
* @param object $uid user to remove
* @return void
@ -29,21 +78,20 @@ class User
logger('Removing user: ' . $uid);
$r = dba::select('user', array(), array('uid' => $uid), array("limit" => 1));
$user = dba::select('user', [], ['uid' => $uid], ['limit' => 1]);
call_hooks('remove_user', $r);
call_hooks('remove_user', $user);
// save username (actually the nickname as it is guaranteed
// unique), so it cannot be re-registered in the future.
dba::insert('userd', array('username' => $r['nickname']));
dba::insert('userd', ['username' => $user['nickname']]);
// The user and related data will be deleted in "cron_expire_and_remove_users" (cronjobs.php)
q("UPDATE `user` SET `account_removed` = 1, `account_expires_on` = UTC_TIMESTAMP() WHERE `uid` = %d", intval($uid));
dba::update('user', ['account_removed' => true, 'account_expires_on' => datetime_convert()], ['uid' => $uid]);
Worker::add(PRIORITY_HIGH, "Notifier", "removeme", $uid);
// Send an update to the directory
Worker::add(PRIORITY_LOW, "Directory", $r['url']);
Worker::add(PRIORITY_LOW, "Directory", $user['url']);
if ($uid == local_user()) {
unset($_SESSION['authenticated']);

View file

@ -37,6 +37,7 @@ namespace Friendica\Util;
use Friendica\Core\Config;
use Friendica\Core\PConfig;
use Friendica\Database\DBM;
use Friendica\Model\User;
use dba;
require_once 'include/dba.php';
@ -217,8 +218,8 @@ class ExAuth
$aUser = dba::select('user', ['uid', 'password'], ['nickname' => $sUser], ['limit' => 1]);
if (DBM::is_result($aUser)) {
$uid = $aUser['uid'];
$Error = $aUser['password'] != hash('whirlpool', $aCommand[3]);
$uid = User::authenticate($aUser, $aCommand[3]);
$Error = $uid === false;
} else {
$this->writeLog(LOG_WARNING, 'user not found: ' . $sUser);
$Error = true;

View file

@ -140,7 +140,7 @@ class Delivery {
}
}
$r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
$r = q("SELECT `contact`.*, `user`.`prvkey` AS `uprvkey`,
`user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
`user`.`page-flags`, `user`.`account-type`, `user`.`prvnets`
FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`

View file

@ -108,7 +108,7 @@ class Notifier {
$recipients[] = $suggest[0]['cid'];
$item = $suggest[0];
} elseif ($cmd === 'removeme') {
$r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
$r = q("SELECT `contact`.*, `user`.`prvkey` AS `uprvkey`,
`user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
`user`.`page-flags`, `user`.`prvnets`, `user`.`account-type`, `user`.`guid`
FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
@ -173,7 +173,7 @@ class Notifier {
}
$r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
$r = q("SELECT `contact`.*, `user`.`prvkey` AS `uprvkey`,
`user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
`user`.`page-flags`, `user`.`prvnets`, `user`.`account-type`
FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`

View file

@ -1,4 +1,5 @@
<?php
/**
* @file src/Worker/Queue.php
*/
@ -19,7 +20,8 @@ require_once 'include/items.php';
require_once 'include/bbcode.php';
require_once 'include/salmon.php';
class Queue {
class Queue
{
public static function execute($queue_id = 0)
{
global $a;
@ -57,8 +59,8 @@ class Queue {
if (DBM::is_result($r)) {
foreach ($r as $q_item) {
logger('Call queue for id '.$q_item['id']);
Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "Queue", (int)$q_item['id']);
logger('Call queue for id ' . $q_item['id']);
Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "Queue", (int) $q_item['id']);
}
}
return;
@ -78,80 +80,71 @@ class Queue {
$q_item = $r[0];
$c = q(
"SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
intval($q_item['cid'])
);
if (!DBM::is_result($c)) {
$contact = dba::select('contact', [], ['id' => $q_item['cid']], ['limit' => 1]);
if (!DBM::is_result($contact)) {
remove_queue_item($q_item['id']);
return;
}
$dead = Cache::get($cachekey_deadguy.$c[0]['notify']);
$dead = Cache::get($cachekey_deadguy . $contact['notify']);
if (!is_null($dead) && $dead) {
logger('queue: skipping known dead url: '.$c[0]['notify']);
logger('queue: skipping known dead url: ' . $contact['notify']);
update_queue_time($q_item['id']);
return;
}
$server = PortableContact::detectServer($c[0]['url']);
$server = PortableContact::detectServer($contact['url']);
if ($server != "") {
$vital = Cache::get($cachekey_server.$server);
$vital = Cache::get($cachekey_server . $server);
if (is_null($vital)) {
logger("Check server ".$server." (".$c[0]["network"].")");
logger("Check server " . $server . " (" . $contact["network"] . ")");
$vital = PortableContact::checkServer($server, $c[0]["network"], true);
Cache::set($cachekey_server.$server, $vital, CACHE_QUARTER_HOUR);
$vital = PortableContact::checkServer($server, $contact["network"], true);
Cache::set($cachekey_server . $server, $vital, CACHE_QUARTER_HOUR);
}
if (!is_null($vital) && !$vital) {
logger('queue: skipping dead server: '.$server);
logger('queue: skipping dead server: ' . $server);
update_queue_time($q_item['id']);
return;
}
}
$u = q(
"SELECT `user`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`
FROM `user` WHERE `uid` = %d LIMIT 1",
intval($c[0]['uid'])
);
if (!DBM::is_result($u)) {
$user = dba::select('user', [], ['uid' => $contact['uid']], ['limit' => 1]);
if (!DBM::is_result($user)) {
remove_queue_item($q_item['id']);
return;
}
$data = $q_item['content'];
$public = $q_item['batch'];
$contact = $c[0];
$owner = $u[0];
$data = $q_item['content'];
$public = $q_item['batch'];
$owner = $user;
$deliver_status = 0;
switch ($contact['network']) {
case NETWORK_DFRN:
logger('queue: dfrndelivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>');
logger('queue: dfrndelivery: item ' . $q_item['id'] . ' for ' . $contact['name'] . ' <' . $contact['url'] . '>');
$deliver_status = DFRN::deliver($owner, $contact, $data);
if ($deliver_status == (-1)) {
update_queue_time($q_item['id']);
Cache::set($cachekey_deadguy.$contact['notify'], true, CACHE_QUARTER_HOUR);
Cache::set($cachekey_deadguy . $contact['notify'], true, CACHE_QUARTER_HOUR);
} else {
remove_queue_item($q_item['id']);
}
break;
case NETWORK_OSTATUS:
if ($contact['notify']) {
logger('queue: slapdelivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>');
logger('queue: slapdelivery: item ' . $q_item['id'] . ' for ' . $contact['name'] . ' <' . $contact['url'] . '>');
$deliver_status = slapper($owner, $contact['notify'], $data);
if ($deliver_status == (-1)) {
update_queue_time($q_item['id']);
Cache::set($cachekey_deadguy.$contact['notify'], true, CACHE_QUARTER_HOUR);
Cache::set($cachekey_deadguy . $contact['notify'], true, CACHE_QUARTER_HOUR);
} else {
remove_queue_item($q_item['id']);
}
@ -159,12 +152,12 @@ class Queue {
break;
case NETWORK_DIASPORA:
if ($contact['notify']) {
logger('queue: diaspora_delivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>');
logger('queue: diaspora_delivery: item ' . $q_item['id'] . ' for ' . $contact['name'] . ' <' . $contact['url'] . '>');
$deliver_status = Diaspora::transmit($owner, $contact, $data, $public, true);
if ($deliver_status == (-1)) {
update_queue_time($q_item['id']);
Cache::set($cachekey_deadguy.$contact['notify'], true, CACHE_QUARTER_HOUR);
Cache::set($cachekey_deadguy . $contact['notify'], true, CACHE_QUARTER_HOUR);
} else {
remove_queue_item($q_item['id']);
}
@ -182,7 +175,7 @@ class Queue {
}
break;
}
logger('Deliver status '.(int)$deliver_status.' for item '.$q_item['id'].' to '.$contact['name'].' <'.$contact['url'].'>');
logger('Deliver status ' . (int) $deliver_status . ' for item ' . $q_item['id'] . ' to ' . $contact['name'] . ' <' . $contact['url'] . '>');
return;
}