New experimental login hashing
This commit is contained in:
parent
36fc968934
commit
8390f6fd42
@ -3,6 +3,13 @@
|
||||
Version 1.5 ()
|
||||
------------------------------------------------------------------------
|
||||
|
||||
* Change password hashing from plain md5 to salted SHA1. Logins
|
||||
should continue to work and are migrated to SHA1 keys upon
|
||||
first login. MD5-logins will only work successfully once. This
|
||||
mechanism will expire 6 months after the upgrade has been executed.
|
||||
EXPERIMENTAL! (http://blog.s9y.org/archives/205-hash.html)
|
||||
(garvinhicking)
|
||||
|
||||
* Allow admins to also approve comments awaiting user-confirmation
|
||||
(garvinhicking)
|
||||
|
||||
|
@ -516,7 +516,7 @@ if ( (int)$serendipity['GET']['step'] == 0 ) {
|
||||
echo ' <strong>' . DONE . '</strong><br />';
|
||||
|
||||
echo sprintf(CREATING_PRIMARY_AUTHOR, htmlspecialchars($_POST['user'])) .'...';
|
||||
$authorid = serendipity_addAuthor($_POST['user'], $_POST['pass'], $_POST['realname'], $_POST['email'], USERLEVEL_ADMIN);
|
||||
$authorid = serendipity_addAuthor($_POST['user'], $_POST['pass'], $_POST['realname'], $_POST['email'], USERLEVEL_ADMIN, 1);
|
||||
$mail_comments = (serendipity_db_bool($_POST['want_mail']) ? 1 : 0);
|
||||
serendipity_set_user_var('mail_comments', $mail_comments, $authorid);
|
||||
serendipity_set_user_var('mail_trackbacks', $mail_comments, $authorid);
|
||||
|
@ -19,7 +19,7 @@ if ($serendipity['GET']['adminAction'] == 'save' && serendipity_checkFormToken()
|
||||
echo '<div class="serendipityAdminMsgError"><img style="width: 22px; height: 22px; border: 0px; padding-right: 4px; vertical-align: middle" src="' . serendipity_getTemplateFile('admin/img/admin_msg_error.png') . '" alt="" />' . CREATE_NOT_AUTHORIZED_USERLEVEL . '</div>';
|
||||
} elseif (empty($_POST['username'])) {
|
||||
echo '<div class="serendipityAdminMsgError"><img style="width: 22px; height: 22px; border: 0px; padding-right: 4px; vertical-align: middle" src="' . serendipity_getTemplateFile('admin/img/admin_msg_error.png') . '" alt="" />' . USERCONF_CHECK_USERNAME_ERROR . '</div>';
|
||||
} elseif (!empty($_POST['password']) && $_POST['check_password'] != $_SESSION['serendipityPassword'] && md5($_POST['check_password']) != $_SESSION['serendipityPassword']) {
|
||||
} elseif (!empty($_POST['password']) && $_POST['check_password'] != $_SESSION['serendipityPassword'] && serendipity_passwordhash($_POST['check_password']) != $_SESSION['serendipityPassword']) {
|
||||
echo '<div class="serendipityAdminMsgError"><img style="width: 22px; height: 22px; border: 0px; padding-right: 4px; vertical-align: middle" src="' . serendipity_getTemplateFile('admin/img/admin_msg_error.png') . '" alt="" />' . USERCONF_CHECK_PASSWORD_ERROR . '</div>';
|
||||
} else {
|
||||
$valid_groups = serendipity_getGroups($serendipity['authorid'], true);
|
||||
|
@ -39,7 +39,7 @@ if (isset($_POST['SAVE_NEW']) && serendipity_checkFormToken()) {
|
||||
if (($serendipity['serendipityUserlevel'] < USERLEVEL_ADMIN && $_POST['userlevel'] >= $serendipity['serendipityUserlevel']) || !serendipity_checkPermission('adminUsersCreateNew')) {
|
||||
echo '<div class="serendipityAdminMsgError"><img style="width: 22px; height: 22px; border: 0px; padding-right: 4px; vertical-align: middle" src="' . serendipity_getTemplateFile('admin/img/admin_msg_error.png') . '" alt="" />' . CREATE_NOT_AUTHORIZED . '</div>';
|
||||
} else {
|
||||
$serendipity['POST']['user'] = serendipity_addAuthor($_POST['username'], $_POST['pass'], $_POST['realname'], $_POST['email'], $_POST['userlevel']);
|
||||
$serendipity['POST']['user'] = serendipity_addAuthor($_POST['username'], $_POST['pass'], $_POST['realname'], $_POST['email'], $_POST['userlevel'], 1);
|
||||
|
||||
$valid_groups = serendipity_getGroups($serendipity['authorid'], true);
|
||||
/* Save all the properties */
|
||||
|
@ -377,7 +377,7 @@ function serendipity_fetchUsers($user = '', $group = null, $is_count = false) {
|
||||
if ($serendipity['dbType'] == 'postgres' ||
|
||||
$serendipity['dbType'] == 'pdo-postgres') {
|
||||
// Why does PostgreSQL keep doing this to us? :-)
|
||||
$query_group = 'GROUP BY a.authorid, a.realname, a.username, a.password, a.mail_comments, a.mail_trackbacks, a.email, a.userlevel, a.right_publish';
|
||||
$query_group = 'GROUP BY a.authorid, a.realname, a.username, a.password, a.hashtype, a.mail_comments, a.mail_trackbacks, a.email, a.userlevel, a.right_publish';
|
||||
$query_distinct = 'DISTINCT';
|
||||
} else {
|
||||
$query_group = 'GROUP BY a.authorid';
|
||||
@ -392,6 +392,7 @@ function serendipity_fetchUsers($user = '', $group = null, $is_count = false) {
|
||||
a.realname,
|
||||
a.username,
|
||||
a.password,
|
||||
a.hashtype,
|
||||
a.mail_comments,
|
||||
a.mail_trackbacks,
|
||||
a.email,
|
||||
@ -418,6 +419,7 @@ function serendipity_fetchUsers($user = '', $group = null, $is_count = false) {
|
||||
a.realname,
|
||||
a.username,
|
||||
a.password,
|
||||
a.hashtype,
|
||||
a.mail_comments,
|
||||
a.mail_trackbacks,
|
||||
a.email,
|
||||
|
@ -22,15 +22,17 @@ if (defined('S9Y_FRAMEWORK_CONFIG')) {
|
||||
* @param int The userlevel of a user
|
||||
* @return int The new user ID of the added author
|
||||
*/
|
||||
function serendipity_addAuthor($username, $password, $realname, $email, $userlevel=0) {
|
||||
function serendipity_addAuthor($username, $password, $realname, $email, $userlevel=0, $hashtype=1) {
|
||||
global $serendipity;
|
||||
$password = md5($password);
|
||||
$query = "INSERT INTO {$serendipity['dbPrefix']}authors (username, password, realname, email, userlevel)
|
||||
$password = serendipity_hash($password);
|
||||
$query = "INSERT INTO {$serendipity['dbPrefix']}authors (username, password, realname, email, userlevel, hashtype)
|
||||
VALUES ('" . serendipity_db_escape_string($username) . "',
|
||||
'" . serendipity_db_escape_String($password) . "',
|
||||
'" . serendipity_db_escape_String($realname) . "',
|
||||
'" . serendipity_db_escape_String($email) . "',
|
||||
'" . serendipity_db_escape_String($userlevel) . "')";
|
||||
'" . serendipity_db_escape_String($userlevel) . "',
|
||||
'" . serendipity_db_escape_String($hashtype) . "'
|
||||
)";
|
||||
serendipity_db_query($query);
|
||||
$cid = serendipity_db_insert_id('authors', 'authorid');
|
||||
|
||||
@ -224,7 +226,7 @@ function serendipity_set_user_var($name, $val, $authorid, $copy_to_s9y = true) {
|
||||
return;
|
||||
}
|
||||
|
||||
$val = md5($val);
|
||||
$val = serendipity_hash($val);
|
||||
$copy_to_s9y = false;
|
||||
break;
|
||||
|
||||
@ -492,14 +494,14 @@ function serendipity_setAuthorToken() {
|
||||
* @param boolean Indicates whether to query external plugins for authentication
|
||||
* @return boolean True on success, False on error
|
||||
*/
|
||||
function serendipity_authenticate_author($username = '', $password = '', $is_md5 = false, $use_external = true) {
|
||||
function serendipity_authenticate_author($username = '', $password = '', $is_hashed = false, $use_external = true) {
|
||||
global $serendipity;
|
||||
|
||||
if (isset($_SESSION['serendipityUser']) && isset($_SESSION['serendipityPassword']) && isset($_SESSION['serendipityAuthedUser']) && $_SESSION['serendipityAuthedUser'] == true) {
|
||||
$username = $_SESSION['serendipityUser'];
|
||||
$password = $_SESSION['serendipityPassword'];
|
||||
// For safety reasons when multiple blogs are installed on the same host, we need to check the current author each time to not let him log into a different blog with the same sessiondata
|
||||
$is_md5 = true;
|
||||
$is_hashed = true;
|
||||
}
|
||||
|
||||
$is_authenticated = false;
|
||||
@ -510,42 +512,75 @@ function serendipity_authenticate_author($username = '', $password = '', $is_md5
|
||||
|
||||
if ($username != '') {
|
||||
if ($use_external) {
|
||||
serendipity_plugin_api::hook_event('backend_auth', $is_md5, array('username' => $username, 'password' => $password));
|
||||
}
|
||||
|
||||
if ($is_md5 === false && !empty($password)) {
|
||||
$password = md5($password);
|
||||
serendipity_plugin_api::hook_event('backend_auth', $is_hashed, array('username' => $username, 'password' => $password));
|
||||
}
|
||||
|
||||
$query = "SELECT DISTINCT
|
||||
email, realname, authorid, userlevel, right_publish
|
||||
email, password, realname, authorid, userlevel, right_publish, hashtype
|
||||
FROM
|
||||
{$serendipity['dbPrefix']}authors
|
||||
WHERE
|
||||
username = '" . serendipity_db_escape_string($username) . "'
|
||||
AND password = '" . serendipity_db_escape_string($password) . "'";
|
||||
$row =& serendipity_db_query($query, true, 'assoc');
|
||||
username = '" . serendipity_db_escape_string($username) . "'";
|
||||
$rows =& serendipity_db_query($query, false, 'assoc');
|
||||
if (is_array($rows)) {
|
||||
foreach($rows AS $row) {
|
||||
$is_valid_user = false;
|
||||
|
||||
if (is_array($row)) {
|
||||
serendipity_setCookie('old_session', session_id(), false);
|
||||
if (!$is_md5) {
|
||||
serendipity_setAuthorToken();
|
||||
// Old MD5 hashing routine. Will convert user.
|
||||
if (empty($row['hashtype']) || $row['hashtype'] == 0) {
|
||||
|
||||
if (isset($serendipity['hashkey']) && (time() - $serendipity['hashkey']) >= 15768000) {
|
||||
die('You can no longer login with an old-style MD5 hash to prevent MD5-Hostage abuse.
|
||||
Please ask the Administrator to set you a new password.');
|
||||
}
|
||||
|
||||
if ( ($is_hashed === false && (string)$row['password'] === (string)md5($password)) ||
|
||||
($is_hashed !== false && (string)$row['password'] === (string)$password) ) {
|
||||
|
||||
serendipity_db_query("UPDATE {$serendipity['dbPrefix']}authors
|
||||
SET password = '" . ($is_hashed === false ? serendipity_hash($password) : $password) . "',
|
||||
hashtype = 1
|
||||
WHERE authorid = '" . $row['authorid'] . "'");
|
||||
$is_valid_user = true;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if ( ($is_hashed === false && (string)$row['password'] === (string)serendipity_hash($password)) ||
|
||||
($is_hashed !== false && (string)$row['password'] === (string)$password) ) {
|
||||
|
||||
$is_valid_user = true;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// This code is only reached, if the password before is valid.
|
||||
if ($is_valid_user) {
|
||||
serendipity_setCookie('old_session', session_id(), false);
|
||||
if (!$is_hashed) {
|
||||
serendipity_setAuthorToken();
|
||||
}
|
||||
$_SESSION['serendipityUser'] = $serendipity['serendipityUser'] = $username;
|
||||
$_SESSION['serendipityRealname'] = $serendipity['serendipityRealname'] = $row['realname'];
|
||||
$_SESSION['serendipityPassword'] = $serendipity['serendipityPassword'] = $password;
|
||||
$_SESSION['serendipityEmail'] = $serendipity['serendipityEmail'] = $row['email'];
|
||||
$_SESSION['serendipityAuthorid'] = $serendipity['authorid'] = $row['authorid'];
|
||||
$_SESSION['serendipityUserlevel'] = $serendipity['serendipityUserlevel'] = $row['userlevel'];
|
||||
$_SESSION['serendipityAuthedUser'] = $serendipity['serendipityAuthedUser'] = true;
|
||||
$_SESSION['serendipityRightPublish']= $serendipity['serendipityRightPublish'] = $row['right_publish'];
|
||||
$_SESSION['serendipityHashType'] = $serendipity['serendipityHashType'] = $row['hashtype'];
|
||||
|
||||
serendipity_load_configuration($serendipity['authorid']);
|
||||
serendipity_setCookie('userDefLang', $serendipity['lang'], false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$_SESSION['serendipityUser'] = $serendipity['serendipityUser'] = $username;
|
||||
$_SESSION['serendipityRealname'] = $serendipity['serendipityRealname'] = $row['realname'];
|
||||
$_SESSION['serendipityPassword'] = $serendipity['serendipityPassword'] = $password;
|
||||
$_SESSION['serendipityEmail'] = $serendipity['serendipityEmail'] = $row['email'];
|
||||
$_SESSION['serendipityAuthorid'] = $serendipity['authorid'] = $row['authorid'];
|
||||
$_SESSION['serendipityUserlevel'] = $serendipity['serendipityUserlevel'] = $row['userlevel'];
|
||||
$_SESSION['serendipityAuthedUser'] = $serendipity['serendipityAuthedUser'] = true;
|
||||
$_SESSION['serendipityRightPublish']= $serendipity['serendipityRightPublish'] = $row['right_publish'];
|
||||
serendipity_load_configuration($serendipity['authorid']);
|
||||
serendipity_setCookie('userDefLang', $serendipity['lang'], false);
|
||||
return true;
|
||||
} else {
|
||||
$_SESSION['serendipityAuthedUser'] = false;
|
||||
serendipity_session_destroy();
|
||||
}
|
||||
|
||||
// Only reached, when proper login did not yet return true.
|
||||
$_SESSION['serendipityAuthedUser'] = false;
|
||||
serendipity_session_destroy();
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -2056,4 +2091,24 @@ function serendipity_hasPluginPermissions($plugin, $groupid = null) {
|
||||
}
|
||||
}
|
||||
|
||||
function serendipity_hash($string) {
|
||||
global $serendipity;
|
||||
|
||||
if (empty($serendipity['hashkey'])) {
|
||||
serendipity_set_config_var('hashkey', time(), 0);
|
||||
}
|
||||
|
||||
return sha1($serendipity['hashkey'] . $string);
|
||||
}
|
||||
|
||||
function serendipity_passwordhash($cleartext_password) {
|
||||
global $serendipity;
|
||||
|
||||
if ($_SESSION['serendipityHashType'] > 0) {
|
||||
return serendipity_hash($cleartext_password);
|
||||
} else {
|
||||
return md5($cleartext_password);
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set sts=4 ts=4 expandtab : */
|
||||
|
@ -41,7 +41,7 @@ if (defined('USE_MEMSNAP')) {
|
||||
}
|
||||
|
||||
// The version string
|
||||
$serendipity['version'] = '1.5-alpha1';
|
||||
$serendipity['version'] = '1.5-alpha2';
|
||||
|
||||
// Setting this to 'false' will enable debugging output. All alpa/beta/cvs snapshot versions will emit debug information by default. To increase the debug level (to enable Smarty debugging), set this flag to 'debug'.
|
||||
$serendipity['production'] = (preg_match('@\-(alpha|beta|cvs)@', $serendipity['version']) ? false : true);
|
||||
|
@ -14,13 +14,14 @@
|
||||
create table {PREFIX}authors (
|
||||
realname varchar(255) NOT NULL default '',
|
||||
username varchar(32) default null,
|
||||
password varchar(32) default null,
|
||||
password varchar(64) default null,
|
||||
authorid {AUTOINCREMENT} {PRIMARY},
|
||||
mail_comments int(1) default '1',
|
||||
mail_trackbacks int(1) default '1',
|
||||
email varchar(128) not null default '',
|
||||
userlevel int(4) {UNSIGNED} not null default '0',
|
||||
right_publish int(1) default '1'
|
||||
right_publish int(1) default '1',
|
||||
hashtype int(1) default '0'
|
||||
) {UTF_8};
|
||||
|
||||
create table {PREFIX}groups (
|
||||
|
2
sql/db_update_1.5-alpha1_1.5-alpha2_mysql.sql
Normal file
2
sql/db_update_1.5-alpha1_1.5-alpha2_mysql.sql
Normal file
@ -0,0 +1,2 @@
|
||||
ALTER TABLE {PREFIX}authors ADD COLUMN hashtype int(1);
|
||||
ALTER TABLE {PREFIX}authors CHANGE password password VARCHAR(64) NOT NULL;
|
8
sql/db_update_1.5-alpha1_1.5-alpha2_postgres.sql
Normal file
8
sql/db_update_1.5-alpha1_1.5-alpha2_postgres.sql
Normal file
@ -0,0 +1,8 @@
|
||||
ALTER TABLE {PREFIX}authors ADD COLUMN hashtype int(1);
|
||||
|
||||
ALTER TABLE {PREFIX}authors ADD COLUMN oldpw varchar(64);
|
||||
UPDATE {PREFIX}authors SET oldpw = password;
|
||||
ALTER TABLE {PREFIX}authors DROP password;
|
||||
ALTER TABLE {PREFIX}authors ADD COLUMN password varchar(64);
|
||||
UPDATE {PREFIX}authors SET password = oldpw;
|
||||
ALTER TABLE {PREFIX}authors DROP COLUMN oldpw;
|
39
sql/db_update_1.5-alpha1_1.5-alpha2_sqlite.sql
Normal file
39
sql/db_update_1.5-alpha1_1.5-alpha2_sqlite.sql
Normal file
@ -0,0 +1,39 @@
|
||||
ALTER TABLE {PREFIX}authors ADD COLUMN hashtype int(1);
|
||||
|
||||
create table {PREFIX}tempauthors (
|
||||
realname varchar(255) NOT NULL default '',
|
||||
username varchar(32) default null,
|
||||
password varchar(64) default null,
|
||||
authorid {AUTOINCREMENT} {PRIMARY},
|
||||
mail_comments int(1) default '1',
|
||||
mail_trackbacks int(1) default '1',
|
||||
email varchar(128) not null default '',
|
||||
userlevel int(4) {UNSIGNED} not null default '0',
|
||||
right_publish int(1) default '1',
|
||||
hashtype int(1) default '0'
|
||||
) {UTF_8};
|
||||
|
||||
INSERT INTO {PREFIX}tempauthors
|
||||
(realname,username,password,authorid,mail_comments,mail_trackbacks,email,userlevel,right_publish,hashtype) SELECT
|
||||
realname,username,password,authorid,mail_comments,mail_trackbacks,email,userlevel,right_publish FROM {PREFIX}authors;
|
||||
DROP TABLE {PREFIX}authors;
|
||||
|
||||
create table {PREFIX}authors (
|
||||
realname varchar(255) NOT NULL default '',
|
||||
username varchar(32) default null,
|
||||
password varchar(64) default null,
|
||||
authorid {AUTOINCREMENT} {PRIMARY},
|
||||
mail_comments int(1) default '1',
|
||||
mail_trackbacks int(1) default '1',
|
||||
email varchar(128) not null default '',
|
||||
userlevel int(4) {UNSIGNED} not null default '0',
|
||||
right_publish int(1) default '1',
|
||||
hashtype int(1) default '0'
|
||||
) {UTF_8};
|
||||
|
||||
|
||||
INSERT INTO {PREFIX}authors
|
||||
(realname,username,password,authorid,mail_comments,mail_trackbacks,email,userlevel,right_publish,hashtype) SELECT
|
||||
realname,username,password,authorid,mail_comments,mail_trackbacks,email,userlevel,right_publish,hashtype FROM {PREFIX}tempauthors;
|
||||
DROP TABLE {PREFIX}tempauthors;
|
||||
|
Loading…
x
Reference in New Issue
Block a user