diff --git a/phpBB/admin/admin_board.php b/phpBB/admin/admin_board.php
index df8a5404e3..721b2f5b97 100644
--- a/phpBB/admin/admin_board.php
+++ b/phpBB/admin/admin_board.php
@@ -191,6 +191,14 @@ $template->assign_vars(array(
"L_MAX_POLL_OPTIONS" => $lang['Max_poll_options'],
"L_FLOOD_INTERVAL" => $lang['Flood_Interval'],
"L_FLOOD_INTERVAL_EXPLAIN" => $lang['Flood_Interval_explain'],
+
+ 'L_MAX_LOGIN_ATTEMPTS' => $lang['Max_login_attempts'],
+ 'L_MAX_LOGIN_ATTEMPTS_EXPLAIN' => $lang['Max_login_attempts_explain'],
+ 'L_LOGIN_RESET_TIME' => $lang['Login_reset_time'],
+ 'L_LOGIN_RESET_TIME_EXPLAIN' => $lang['Login_reset_time_explain'],
+ 'MAX_LOGIN_ATTEMPTS' => $new['max_login_attempts'],
+ 'LOGIN_RESET_TIME' => $new['login_reset_time'],
+
"L_BOARD_EMAIL_FORM" => $lang['Board_email_form'],
"L_BOARD_EMAIL_FORM_EXPLAIN" => $lang['Board_email_form_explain'],
"L_TOPICS_PER_PAGE" => $lang['Topics_per_page'],
diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html
index f4a3592ddf..42ffb42968 100644
--- a/phpBB/docs/CHANGELOG.html
+++ b/phpBB/docs/CHANGELOG.html
@@ -75,8 +75,11 @@ p,ul,td {font-size:10pt;}
[Fix] change truncation of username length in usercp_register.php - BFUK
[Fix] incorrect path to avatars in admin_users.php (Bug #667)
[Fix] fixed get_userdata to support correct sql escaping (non-mysql dbs) - jarnaez
+[Fix] fixed captcha for those not having the zlib extension enabled
+[Change] Placed version information above who is online in admin panel for better visual presence
[Sec] fixed XSS issue (only valid for Internet Explorer) within the url bbcode
[Sec] fixed XSS issue (only valid for Internet Explorer) if html tags are allowed and enabled
+[Sec] added configurable maximum login attempts to prevent dictionary attacks
diff --git a/phpBB/includes/usercp_confirm.php b/phpBB/includes/usercp_confirm.php
index fec308c9f9..24a94d728d 100644
--- a/phpBB/includes/usercp_confirm.php
+++ b/phpBB/includes/usercp_confirm.php
@@ -153,18 +153,15 @@ if (@extension_loaded('zlib'))
}
else
{
- if (!empty($HTTP_GET_VARS['c']))
- {
- $_png = define_raw_pngs();
+ $_png = define_raw_pngs();
- $char = substr($code, intval($HTTP_GET_VARS['c']) - 1, 1);
- header('Content-Type: image/png');
- header('Cache-control: no-cache, no-store');
- echo base64_decode($_png[$char]);
+ $char = substr($code, -1);
+ header('Content-Type: image/png');
+ header('Cache-control: no-cache, no-store');
+ echo base64_decode($_png[$char]);
- unset($_png);
- exit;
- }
+ unset($_png);
+ exit;
}
exit;
diff --git a/phpBB/includes/usercp_register.php b/phpBB/includes/usercp_register.php
index f6c5a451a0..591af76ad3 100644
--- a/phpBB/includes/usercp_register.php
+++ b/phpBB/includes/usercp_register.php
@@ -296,6 +296,12 @@ if ( isset($HTTP_POST_VARS['submit']) )
if ($row = $db->sql_fetchrow($result))
{
+ // Only compare one char if the zlib-extension is not loaded
+ if (!@extension_loaded('zlib'))
+ {
+ $row['code'] = substr($row['code'], -1);
+ }
+
if ($row['code'] != $confirm_code)
{
$error = TRUE;
diff --git a/phpBB/install/install.php b/phpBB/install/install.php
index 7db904f7b8..35b99804a2 100644
--- a/phpBB/install/install.php
+++ b/phpBB/install/install.php
@@ -333,7 +333,7 @@ $available_dbms = array(
'COMMENTS' => 'remove_remarks'
),
'mysql4' => array(
- 'LABEL' => 'MySQL 4.x',
+ 'LABEL' => 'MySQL 4.x/5.x',
'SCHEMA' => 'mysql',
'DELIM' => ';',
'DELIM_BASIC' => ';',
diff --git a/phpBB/install/schemas/ms_access_primer.zip b/phpBB/install/schemas/ms_access_primer.zip
index 7b66a0fb47..7da212ca37 100644
Binary files a/phpBB/install/schemas/ms_access_primer.zip and b/phpBB/install/schemas/ms_access_primer.zip differ
diff --git a/phpBB/install/schemas/mssql_basic.sql b/phpBB/install/schemas/mssql_basic.sql
index 94fd6c515f..42193efea5 100644
--- a/phpBB/install/schemas/mssql_basic.sql
+++ b/phpBB/install/schemas/mssql_basic.sql
@@ -51,6 +51,8 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_password','')
INSERT INTO phpbb_config (config_name, config_value) VALUES ('sendmail_fix','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('flood_interval','15');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_login_attempts', '5');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('login_reset_time', '30');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_form','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_filesize','6144');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_width','80');
diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql
index 06649eefbc..c4f92fa8af 100644
--- a/phpBB/install/schemas/mssql_schema.sql
+++ b/phpBB/install/schemas/mssql_schema.sql
@@ -342,6 +342,8 @@ CREATE TABLE [phpbb_users] (
[user_new_privmsg] [smallint] NOT NULL ,
[user_unread_privmsg] [smallint] NOT NULL ,
[user_last_privmsg] [int] NOT NULL ,
+ [user_login_tries] [smallint] NOT NULL ,
+ [user_last_login_try] [int] NOT NULL ,
[user_emailtime] [int] NOT NULL ,
[user_viewemail] [smallint] NULL ,
[user_attachsig] [smallint] NULL ,
@@ -613,6 +615,8 @@ ALTER TABLE [phpbb_users] WITH NOCHECK ADD
CONSTRAINT [DF_phpbb_users_user_new_privmsg] DEFAULT (0) FOR [user_new_privmsg],
CONSTRAINT [DF_phpbb_users_user_unread_privmsg] DEFAULT (0) FOR [user_unread_privmsg],
CONSTRAINT [DF_phpbb_users_user_last_privmsg] DEFAULT (0) FOR [user_last_privmsg],
+ CONSTRAINT [DF_phpbb_users_user_login_tries] DEFAULT (0) FOR [user_login_tries],
+ CONSTRAINT [DF_phpbb_users_user_last_login_try] DEFAULT (0) FOR [user_last_login_try],
CONSTRAINT [DF_phpbb_users_user_emailtime] DEFAULT (0) FOR [user_emailtime],
CONSTRAINT [DF_phpbb_users_user_viewemail] DEFAULT (1) FOR [user_viewemail],
CONSTRAINT [DF_phpbb_users_user_attachsig] DEFAULT (1) FOR [user_attachsig],
diff --git a/phpBB/install/schemas/mysql_basic.sql b/phpBB/install/schemas/mysql_basic.sql
index 247af3f2ab..2d1b4a5142 100644
--- a/phpBB/install/schemas/mysql_basic.sql
+++ b/phpBB/install/schemas/mysql_basic.sql
@@ -44,6 +44,8 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_password','')
INSERT INTO phpbb_config (config_name, config_value) VALUES ('sendmail_fix','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('flood_interval','15');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_login_attempts', '5');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('login_reset_time', '30');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_form','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_filesize','6144');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_width','80');
diff --git a/phpBB/install/schemas/mysql_schema.sql b/phpBB/install/schemas/mysql_schema.sql
index a914764fca..6944a3d8a5 100644
--- a/phpBB/install/schemas/mysql_schema.sql
+++ b/phpBB/install/schemas/mysql_schema.sql
@@ -492,6 +492,8 @@ CREATE TABLE phpbb_users (
user_new_privmsg smallint(5) UNSIGNED DEFAULT '0' NOT NULL,
user_unread_privmsg smallint(5) UNSIGNED DEFAULT '0' NOT NULL,
user_last_privmsg int(11) DEFAULT '0' NOT NULL,
+ user_login_tries smallint(5) UNSIGNED DEFAULT '0' NOT NULL,
+ user_last_login_try int(11) DEFAULT '0' NOT NULL,
user_emailtime int(11),
user_viewemail tinyint(1),
user_attachsig tinyint(1),
diff --git a/phpBB/install/schemas/postgres_basic.sql b/phpBB/install/schemas/postgres_basic.sql
index d530a85317..0e1c84dfd7 100644
--- a/phpBB/install/schemas/postgres_basic.sql
+++ b/phpBB/install/schemas/postgres_basic.sql
@@ -45,6 +45,8 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_password','')
INSERT INTO phpbb_config (config_name, config_value) VALUES ('sendmail_fix','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('flood_interval','15');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_login_attempts', '5');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('login_reset_time', '30');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_form','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_filesize','6144');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_width','80');
diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql
index 737f2f1f8b..ac24cff312 100644
--- a/phpBB/install/schemas/postgres_schema.sql
+++ b/phpBB/install/schemas/postgres_schema.sql
@@ -488,6 +488,8 @@ CREATE TABLE phpbb_users (
user_new_privmsg int2 DEFAULT '0' NOT NULL,
user_unread_privmsg int2 DEFAULT '0' NOT NULL,
user_last_privmsg int4 DEFAULT '0' NOT NULL,
+ user_login_tries int2 DEFAULT '0' NOT NULL,
+ user_last_login_try int4 DEFAULT '0' NOT NULL,
user_emailtime int4,
user_viewemail int2,
user_attachsig int2,
diff --git a/phpBB/install/update_to_latest.php b/phpBB/install/update_to_latest.php
index eeb282545e..6fc4d50f50 100644
--- a/phpBB/install/update_to_latest.php
+++ b/phpBB/install/update_to_latest.php
@@ -584,6 +584,48 @@ switch ($row['config_value'])
break;
}
+ case '.0.18':
+
+ // Add login columns to user table
+ switch (SQL_LAYER)
+ {
+ case 'mysql':
+ case 'mysql4':
+ $sql[] = "ALTER TABLE " . USERS_TABLE . "
+ ADD COLUMN user_login_tries smallint(5) UNSIGNED DEFAULT '0' NOT NULL";
+ $sql[] = "ALTER TABLE " . USERS_TABLE . "
+ ADD COLUMN user_last_login_try int(11) DEFAULT '0' NOT NULL";
+ break;
+
+ case 'postgresql':
+ $sql[] = "ALTER TABLE " . USERS_TABLE . "
+ ADD COLUMN user_login_tries int2";
+ $sql[] = "ALTER TABLE " . USERS_TABLE . "
+ ALTER COLUMN user_login_tries SET DEFAULT '0'";
+ $sql[] = "ALTER TABLE " . USERS_TABLE . "
+ ADD COLUMN user_last_login_try int4";
+ $sql[] = "ALTER TABLE " . USERS_TABLE . "
+ ALTER COLUMN user_last_login_try SET DEFAULT '0'";
+ break;
+
+ case 'mssql-odbc':
+ case 'mssql':
+ $sql[] = "ALTER TABLE " . USERS_TABLE . " ADD
+ user_login_tries smallint NOT NULL,
+ CONSTRAINT [DF_" . $table_prefix . "users_user_login_tries] DEFAULT (0) FOR [user_login_tries]";
+ $sql[] = "ALTER TABLE " . USERS_TABLE . " ADD
+ user_last_login_try int NOT NULL,
+ CONSTRAINT [DF_" . $table_prefix . "users_user_last_login_try] DEFAULT (0) FOR [user_last_login_try]";
+ break;
+
+ case 'msaccess':
+ $sql[] = "ALTER TABLE " . USERS_TABLE . " ADD
+ user_login_tries smallint NOT NULL";
+ $sql[] = "ALTER TABLE " . USERS_TABLE . " ADD
+ user_last_login_try int NOT NULL";
+ break;
+ }
+
break;
}
@@ -1002,6 +1044,17 @@ switch ($row['config_value'])
// We reset those having autologin enabled and forcing the re-assignment of a session id
$sql = 'DELETE FROM ' . SESSIONS_TABLE;
_sql($sql, $errored, $error_ary);
+
+ case '.0.18':
+
+ $sql = 'INSERT INTO ' . CONFIG_TABLE . " (config_name, config_value)
+ VALUES ('max_login_attempts', '5')";
+ _sql($sql, $errored, $error_ary);
+
+ $sql = 'INSERT INTO ' . CONFIG_TABLE . " (config_name, config_value)
+ VALUES ('login_reset_time', '30')";
+ _sql($sql, $errored, $error_ary);
+
break;
default:
diff --git a/phpBB/language/lang_english/lang_admin.php b/phpBB/language/lang_english/lang_admin.php
index 17436a3342..915c6648ea 100644
--- a/phpBB/language/lang_english/lang_admin.php
+++ b/phpBB/language/lang_english/lang_admin.php
@@ -743,6 +743,14 @@ $lang['Socket_functions_disabled'] = 'Unable to use socket functions.';
$lang['Mailing_list_subscribe_reminder'] = 'For the latest information on updates to phpBB, why not subscribe to our mailing list.';
$lang['Version_information'] = 'Version Information';
+//
+// Login attempts configuration
+//
+$lang['Max_login_attempts'] = 'Allowed login attempts';
+$lang['Max_login_attempts_explain'] = 'The number of allowed board login attempts.';
+$lang['Login_reset_time'] = 'Login lock time';
+$lang['Login_reset_time_explain'] = 'Time in minutes the user have to wait until he is allowed to login again after exceeding the number of allowed login attempts.';
+
//
// That's all Folks!
// -------------------------------------------------
diff --git a/phpBB/language/lang_english/lang_main.php b/phpBB/language/lang_english/lang_main.php
index defc3d36d8..d104025d32 100644
--- a/phpBB/language/lang_english/lang_main.php
+++ b/phpBB/language/lang_english/lang_main.php
@@ -1014,6 +1014,7 @@ $lang['An_error_occured'] = 'An Error Occurred';
$lang['A_critical_error'] = 'A Critical Error Occurred';
$lang['Admin_reauthenticate'] = 'To administer the board you must re-authenticate yourself.';
+$lang['Login_attempts_exceeded'] = 'The maximum number of %s login attempts has been exceeded. You are not allowed to login for the next %s minutes.';
//
// That's all, Folks!
diff --git a/phpBB/login.php b/phpBB/login.php
index 4844be3c2e..c8a572d7a9 100644
--- a/phpBB/login.php
+++ b/phpBB/login.php
@@ -57,7 +57,7 @@ if( isset($HTTP_POST_VARS['login']) || isset($HTTP_GET_VARS['login']) || isset($
$username = isset($HTTP_POST_VARS['username']) ? phpbb_clean_username($HTTP_POST_VARS['username']) : '';
$password = isset($HTTP_POST_VARS['password']) ? $HTTP_POST_VARS['password'] : '';
- $sql = "SELECT user_id, username, user_password, user_active, user_level
+ $sql = "SELECT user_id, username, user_password, user_active, user_level, user_login_tries, user_last_login_try
FROM " . USERS_TABLE . "
WHERE username = '" . str_replace("\\'", "''", $username) . "'";
if ( !($result = $db->sql_query($sql)) )
@@ -73,6 +73,20 @@ if( isset($HTTP_POST_VARS['login']) || isset($HTTP_GET_VARS['login']) || isset($
}
else
{
+ // If the last login is more than x minutes ago, then reset the login tries/time
+ if ($row['user_last_login_try'] && $board_config['login_reset_time'] && $row['user_last_login_try'] < (time() - ($board_config['login_reset_time'] * 60)))
+ {
+ $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_login_tries = 0, user_last_login_try = 0 WHERE user_id = ' . $row['user_id']);
+ $row['user_last_login_try'] = $row['user_login_tries'] = 0;
+ }
+
+ // Check to see if user is allowed to login again... if his tries are exceeded
+ if ($row['user_last_login_try'] && $board_config['login_reset_time'] && $board_config['max_login_attempts'] &&
+ $row['user_last_login_try'] >= (time() - ($board_config['login_reset_time'] * 60)) && $row['user_login_tries'] >= $board_config['max_login_attempts'])
+ {
+ message_die(GENERAL_MESSAGE, sprintf($lang['Login_attempts_exceeded'], $board_config['max_login_attempts'], $board_config['login_reset_time']));
+ }
+
if( md5($password) == $row['user_password'] && $row['user_active'] )
{
$autologin = ( isset($HTTP_POST_VARS['autologin']) ) ? TRUE : 0;
@@ -80,6 +94,9 @@ if( isset($HTTP_POST_VARS['login']) || isset($HTTP_GET_VARS['login']) || isset($
$admin = (isset($HTTP_POST_VARS['admin'])) ? 1 : 0;
$session_id = session_begin($row['user_id'], $user_ip, PAGE_INDEX, FALSE, $autologin, $admin);
+ // Reset login tries
+ $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_login_tries = 0, user_last_login_try = 0 WHERE user_id = ' . $row['user_id']);
+
if( $session_id )
{
$url = ( !empty($HTTP_POST_VARS['redirect']) ) ? str_replace('&', '&', htmlspecialchars($HTTP_POST_VARS['redirect'])) : "index.$phpEx";
@@ -92,6 +109,15 @@ if( isset($HTTP_POST_VARS['login']) || isset($HTTP_GET_VARS['login']) || isset($
}
else
{
+ // Save login tries and last login
+ if ($row['user_id'] != ANONYMOUS)
+ {
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_login_tries = user_login_tries + 1, user_last_login_try = ' . time() . '
+ WHERE user_id = ' . $row['user_id'];
+ $db->sql_query($sql);
+ }
+
$redirect = ( !empty($HTTP_POST_VARS['redirect']) ) ? str_replace('&', '&', htmlspecialchars($HTTP_POST_VARS['redirect'])) : '';
$redirect = str_replace('?', '&', $redirect);
diff --git a/phpBB/templates/subSilver/admin/board_config_body.tpl b/phpBB/templates/subSilver/admin/board_config_body.tpl
index 83b9bb320c..12d7bc6a87 100644
--- a/phpBB/templates/subSilver/admin/board_config_body.tpl
+++ b/phpBB/templates/subSilver/admin/board_config_body.tpl
@@ -55,6 +55,14 @@
{L_FLOOD_INTERVAL} {L_FLOOD_INTERVAL_EXPLAIN} |
|
+
+ {L_MAX_LOGIN_ATTEMPTS} {L_MAX_LOGIN_ATTEMPTS_EXPLAIN} |
+ |
+
+
+ {L_LOGIN_RESET_TIME} {L_LOGIN_RESET_TIME_EXPLAIN} |
+ |
+
{L_TOPICS_PER_PAGE} |
|
diff --git a/phpBB/templates/subSilver/admin/index_body.tpl b/phpBB/templates/subSilver/admin/index_body.tpl
index f8fe7c3c88..6e9f8d3862 100644
--- a/phpBB/templates/subSilver/admin/index_body.tpl
+++ b/phpBB/templates/subSilver/admin/index_body.tpl
@@ -43,6 +43,13 @@
{GZIP_COMPRESSION} |
+
+{L_VERSION_INFORMATION}
+
+{VERSION_INFO}
+
+
+
{L_WHO_IS_ONLINE}
-
-{L_VERSION_INFORMATION}
-
-{VERSION_INFO}
-
-