Package: phpbb2
Version: 2.0.13-2
Severity: wishlist
Tags: patch

This patch introduce the feature that force anonymous user to fill the
confirmation code before posting any messages into the forum.
This is the confirmation code like in the phpbb's registration page,
that present the image of distorted characters of the corresponding
confirmation code.

The patch has currently been used at http://linux.thai.net/phpbb2/ .
See http://linux.thai.net/phpbb2/posting.php?mode=newtopic&f=2 that
demonstrate how this patch is working.


-- System Information:
Debian Release: testing/unstable
Architecture: i386 (i686)
Kernel: Linux 2.6.10-5-386
Locale: LANG=C, LC_CTYPE=thai

Versions of packages phpbb2 depends on:
ii  apache [httpd]      1.3.31-6ubuntu0.9    Versatile, high-performance HTTP s
ii  debconf             1.4.29ubuntu4        Debian configuration management sy
ii  php4                4:4.3.8-3ubuntu7.12  A server-side, HTML-embedded scrip
ii  php4-cgi            4:4.3.10-10ubuntu4.3 server-side, HTML-embedded scripti
ii  php4-mysql          4:4.3.8-3ubuntu7.12  MySQL module for php4

-- debconf information:
* phpbb2/httpd: apache


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
diff -ur /usr/share/phpbb2/site/language/lang_english/lang_main.php phpbb2/site/language/lang_english/lang_main.php
--- /usr/share/phpbb2/site/language/lang_english/lang_main.php	2005-02-28 02:30:45.000000000 +0700
+++ phpbb2/site/language/lang_english/lang_main.php	2006-02-25 02:51:06.000000000 +0700
@@ -605,6 +605,7 @@
 $lang['Current_password_mismatch'] = 'The current password you supplied does not match that stored in the database.';
 $lang['Password_long'] = 'Your password must be no more than 32 characters.';
 $lang['Too_many_registers'] = 'You have made too many registration attempts. Please try again later.';
+$lang['Too_many_posts'] = 'You have made too many posting attempts. Please try again later.';
 $lang['Username_taken'] = 'Sorry, but this username has already been taken.';
 $lang['Username_invalid'] = 'Sorry, but this username contains an invalid character such as \'.';
 $lang['Username_disallowed'] = 'Sorry, but this username has been disallowed.';
@@ -663,6 +664,7 @@
 //
 $lang['Confirm_code_wrong'] = 'The confirmation code you entered was incorrect';
 $lang['Too_many_registers'] = 'You have exceeded the number of registration attempts for this session. Please try again later.';
+$lang['Too_many_posts'] = 'You have exceeded the number of posting attempts for this session. Please try again later.';
 $lang['Confirm_code_impaired'] = 'If you are visually impaired or cannot otherwise read this code please contact the %sAdministrator%s for help.';
 $lang['Confirm_code'] = 'Confirmation code';
 $lang['Confirm_code_explain'] = 'Enter the code exactly as you see it. The code is case sensitive and zero has a diagonal line through it.';
@@ -1022,4 +1024,4 @@
 // That's all, Folks!
 // -------------------------------------------------
 
-?>
\ No newline at end of file
+?>
diff -ur /usr/share/phpbb2/site/language/lang_thai/lang_main.php phpbb2/site/language/lang_thai/lang_main.php
--- /usr/share/phpbb2/site/language/lang_thai/lang_main.php	2003-04-20 19:30:18.000000000 +0700
+++ phpbb2/site/language/lang_thai/lang_main.php	2006-02-25 03:12:34.000000000 +0700
@@ -658,6 +658,18 @@
 
 
 //
+// Visual confirmation system strings
+//
+$lang['Confirm_code_wrong'] = 'The confirmation code you entered was incorrect';
+$lang['Too_many_registers'] = 'You have exceeded the number of registration attempts for this session. Please try again later.';
+$lang['Too_many_posts'] = 'You have exceeded the number of posting attempts for this session. Please try again later.';
+$lang['Confirm_code_impaired'] = 'If you are visually impaired or cannot otherwise read this code please contact the %sAdministrator%s for help.';
+$lang['Confirm_code'] = 'Confirmation code';
+$lang['Confirm_code_explain'] = 'Enter the code exactly as you see it. The code is case sensitive and zero has a diagonal line through it.';
+
+
+
+//
 // Memberslist
 //
 $lang['Select_sort_method'] = 'àÅ×Í¡ÇÔ¸ÕàÃÕ§ÅӴѺ';
@@ -1009,4 +1021,4 @@
 // That's all Folks!
 // -------------------------------------------------
 
-?>
\ No newline at end of file
+?>
diff -ur /usr/share/phpbb2/site/posting.php phpbb2/site/posting.php
--- /usr/share/phpbb2/site/posting.php	2005-02-28 02:30:46.000000000 +0700
+++ phpbb2/site/posting.php	2006-02-27 10:35:12.000000000 +0700
@@ -31,6 +31,7 @@
 // Check and set various parameters
 //
 $params = array('submit' => 'post', 'preview' => 'preview', 'delete' => 'delete', 'poll_delete' => 'poll_delete', 'poll_add' => 'add_poll_option', 'poll_edit' => 'edit_poll_option', 'mode' => 'mode');
+$params['confirm_code'] = 'confirm_code';
 while( list($var, $param) = @each($params) )
 {
 	if ( !empty($HTTP_POST_VARS[$param]) || !empty($HTTP_GET_VARS[$param]) )
@@ -545,6 +546,60 @@
 			$poll_length = ( isset($HTTP_POST_VARS['poll_length']) && $is_auth['auth_pollcreate'] ) ? $HTTP_POST_VARS['poll_length'] : '';
 			$bbcode_uid = '';
 
+			// Code copied from includes/usercp_register.php without modification,
+			// except the first condition line,
+			//    if ($board_config['enable_confirm'] && $mode == 'register')
+			if ($board_config['enable_confirm'] && !$userdata['session_logged_in'])
+			{
+				if (empty($HTTP_POST_VARS['confirm_id']))
+				{
+					$error = TRUE;
+					$error_msg .= ( ( isset($error_msg) ) ? '<br />' : '' ) . $lang['Confirm_code_wrong'];
+				}
+				else
+				{
+					$confirm_id = htmlspecialchars($HTTP_POST_VARS['confirm_id']);
+					if (!preg_match('/^[A-Za-z0-9]+$/', $confirm_id))
+					{
+						$confirm_id = '';
+					}
+					
+					$sql = 'SELECT code 
+						FROM ' . CONFIRM_TABLE . " 
+						WHERE confirm_id = '$confirm_id' 
+							AND session_id = '" . $userdata['session_id'] . "'";
+					if (!($result = $db->sql_query($sql)))
+					{
+						message_die(GENERAL_ERROR, 'Could not obtain confirmation code', __LINE__, __FILE__, $sql);
+					}
+		
+					if ($row = $db->sql_fetchrow($result))
+					{
+						if ($row['code'] != $confirm_code)
+						{
+							$error = TRUE;
+							$error_msg .= ( ( isset($error_msg) ) ? '<br />' : '' ) . $lang['Confirm_code_wrong'];
+						}
+						else
+						{
+							$sql = 'DELETE FROM ' . CONFIRM_TABLE . " 
+								WHERE confirm_id = '$confirm_id' 
+									AND session_id = '" . $userdata['session_id'] . "'";
+							if (!$db->sql_query($sql))
+							{
+								message_die(GENERAL_ERROR, 'Could not delete confirmation code', __LINE__, __FILE__, $sql);
+							}
+						}
+					}
+					else
+					{		
+						$error = TRUE;
+						$error_msg .= ( ( isset($error_msg) ) ? '<br />' : '' ) . $lang['Confirm_code_wrong'];
+					}
+					$db->sql_freeresult($result);
+				}
+			}
+
 			prepare_post($mode, $post_data, $bbcode_on, $html_on, $smilies_on, $error_msg, $username, $bbcode_uid, $subject, $message, $poll_title, $poll_options, $poll_length);
 
 			if ( $error_msg == '' )
@@ -638,6 +693,22 @@
 	
 	if( $preview )
 	{
+		// On preview action, do remove the current confirm_id entry in table, so
+		// that it won't be counted as attempts in ref_note{attempts} below
+		$confirm_id = htmlspecialchars($HTTP_POST_VARS['confirm_id']);
+		if (!preg_match('/^[A-Za-z0-9]+$/', $confirm_id))
+		{
+			$confirm_id = '';
+		}
+
+		$sql = 'DELETE FROM ' . CONFIRM_TABLE . " 
+			WHERE confirm_id = '$confirm_id' 
+				AND session_id = '" . $userdata['session_id'] . "'";
+		if (!$db->sql_query($sql))
+		{
+			message_die(GENERAL_ERROR, 'Could not delete confirmation code', __LINE__, __FILE__, $sql);
+		}
+
 		$orig_word = array();
 		$replacement_word = array();
 		obtain_word_list($orig_word, $replacement_word);
@@ -919,6 +990,102 @@
 
 $hidden_form_fields = '<input type="hidden" name="mode" value="' . $mode . '" />';
 
+$confirm_image = '';
+if( !$userdata['session_logged_in'] )
+{
+	// Visual Confirmation copied from includes/usercp_register.php with minor
+	// modification on the following 4 lines of code,
+	//    if (!empty($board_config['enable_confirm']) && $mode == 'register')
+	//    $s_hidden_fields .= '<input type="hidden" name="confirm_id" value="' . $confirm_id . '" />';
+	//    if ($row['attempts'] > 3)
+	//       message_die(GENERAL_MESSAGE, $lang['Too_many_registers']);
+	// This attempts checking won't prevent the brute force attack, because the
+	// cracker can open new session to reset this attempts count.
+	// Unlike registering a new account, the attempts checking on the post or
+	// reply action should be relaxed, because some users may prefer to open
+	// many reply pages at the same time to post their comments.
+	// But it should be limited to some extent to prevent the CONFIRM_TABLE from
+	// having too much confirm_id records.
+	// (All confirm_id records of the expired session will be automatically
+	// cleared.)
+	//
+	// Visual Confirmation
+	$confirm_image = '';
+	if (!empty($board_config['enable_confirm']))
+	{
+		$sql = 'SELECT session_id 
+			FROM ' . SESSIONS_TABLE; 
+		if (!($result = $db->sql_query($sql)))
+		{
+			message_die(GENERAL_ERROR, 'Could not select session data', '', __LINE__, __FILE__, $sql);
+		}
+
+		if ($row = $db->sql_fetchrow($result))
+		{
+			$confirm_sql = '';
+			do
+			{
+				$confirm_sql .= (($confirm_sql != '') ? ', ' : '') . "'" . $row['session_id'] . "'";
+			}
+			while ($row = $db->sql_fetchrow($result));
+		
+			$sql = 'DELETE FROM ' .  CONFIRM_TABLE . " 
+				WHERE session_id NOT IN ($confirm_sql)";
+			if (!$db->sql_query($sql))
+			{
+				message_die(GENERAL_ERROR, 'Could not delete stale confirm data', '', __LINE__, __FILE__, $sql);
+			}
+		}
+		$db->sql_freeresult($result);
+
+		$sql = 'SELECT COUNT(session_id) AS attempts 
+			FROM ' . CONFIRM_TABLE . " 
+			WHERE session_id = '" . $userdata['session_id'] . "'";
+		if (!($result = $db->sql_query($sql)))
+		{
+			message_die(GENERAL_ERROR, 'Could not obtain confirm code count', '', __LINE__, __FILE__, $sql);
+		}
+
+		if ($row = $db->sql_fetchrow($result))
+		{
+			// ref_note{attempts}
+			if ($row['attempts'] > 30)
+			{
+				message_die(GENERAL_MESSAGE, $lang['Too_many_posts']);
+			}
+		}
+		$db->sql_freeresult($result);
+		
+		$confirm_chars = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',  'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',  'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9');
+
+		list($usec, $sec) = explode(' ', microtime()); 
+		mt_srand($sec * $usec); 
+
+		$max_chars = count($confirm_chars) - 1;
+		$code = '';
+		for ($i = 0; $i < 6; $i++)
+		{
+			$code .= $confirm_chars[mt_rand(0, $max_chars)];
+		}
+
+		$confirm_id = md5(uniqid($user_ip));
+
+		$sql = 'INSERT INTO ' . CONFIRM_TABLE . " (confirm_id, session_id, code) 
+			VALUES ('$confirm_id', '". $userdata['session_id'] . "', '$code')";
+		if (!$db->sql_query($sql))
+		{
+			message_die(GENERAL_ERROR, 'Could not insert new confirm code information', '', __LINE__, __FILE__, $sql);
+		}
+
+		unset($code);
+		
+		$confirm_image = (@extension_loaded('zlib')) ? '<img src="' . append_sid("profile.$phpEx?mode=confirm&amp;id=$confirm_id") . '" alt="" title="" />' : '<img src="' . append_sid("profile.$phpEx?mode=confirm&amp;id=$confirm_id&amp;c=1") . '" alt="" title="" /><img src="' . append_sid("profile.$phpEx?mode=confirm&amp;id=$confirm_id&amp;c=2") . '" alt="" title="" /><img src="' . append_sid("profile.$phpEx?mode=confirm&amp;id=$confirm_id&amp;c=3") . '" alt="" title="" /><img src="' . append_sid("profile.$phpEx?mode=confirm&amp;id=$confirm_id&amp;c=4") . '" alt="" title="" /><img src="' . append_sid("profile.$phpEx?mode=confirm&amp;id=$confirm_id&amp;c=5") . '" alt="" title="" /><img src="' . append_sid("profile.$phpEx?mode=confirm&amp;id=$confirm_id&amp;c=6") . '" alt="" title="" />';
+		$hidden_form_fields .= '<input type="hidden" name="confirm_id" value="' . $confirm_id . '" />';
+
+		$template->assign_block_vars('switch_confirm', array());
+	}
+}
+
 switch( $mode )
 {
 	case 'newtopic':
@@ -971,12 +1138,17 @@
 //
 $template->assign_vars(array(
 	'USERNAME' => $username,
+	'CONFIRM_IMG' => $confirm_image, 
 	'SUBJECT' => $subject,
 	'MESSAGE' => $message,
 	'HTML_STATUS' => $html_status,
 	'BBCODE_STATUS' => sprintf($bbcode_status, '<a href="' . append_sid("faq.$phpEx?mode=bbcode") . '" target="_phpbbcode">', '</a>'), 
 	'SMILIES_STATUS' => $smilies_status, 
 
+	'L_CONFIRM_CODE_IMPAIRED'	=> sprintf($lang['Confirm_code_impaired'], '<a href="mailto:' . $board_config['board_email'] . '">', '</a>'), 
+	'L_CONFIRM_CODE'			=> $lang['Confirm_code'], 
+	'L_CONFIRM_CODE_EXPLAIN'	=> $lang['Confirm_code_explain'], 
+
 	'L_SUBJECT' => $lang['Subject'],
 	'L_MESSAGE_BODY' => $lang['Message_body'],
 	'L_OPTIONS' => $lang['Options'],
diff -ur /usr/share/phpbb2/templates/subSilver/posting_body.tpl phpbb2/templates/subSilver/posting_body.tpl
--- /usr/share/phpbb2/templates/subSilver/posting_body.tpl	2005-02-28 02:30:45.000000000 +0700
+++ phpbb2/templates/subSilver/posting_body.tpl	2006-02-24 17:38:25.000000000 +0700
@@ -279,6 +279,16 @@
 		<td class="row2"><span class="genmed"><input type="text" class="post" tabindex="1" name="username" size="25" maxlength="25" value="{USERNAME}" /></span></td>
 	</tr>
 	<!-- END switch_username_select -->
+	<!-- Visual Confirmation -->
+	<!-- BEGIN switch_confirm -->
+	<tr>
+		<td class="row1" colspan="2" align="center"><span class="gensmall">{L_CONFIRM_CODE_IMPAIRED}</span><br /><br />{CONFIRM_IMG}<br /><br /></td>
+	</tr>
+	<tr> 
+	  <td class="row1"><span class="gen">{L_CONFIRM_CODE}: * </span><br /><span class="gensmall">{L_CONFIRM_CODE_EXPLAIN}</span></td>
+	  <td class="row2"><input type="text" class="post" style="width: 200px" name="confirm_code" size="6" maxlength="6" value="" /></td>
+	</tr>
+	<!-- END switch_confirm -->
 	<!-- BEGIN switch_privmsg -->
 	<tr> 
 		<td class="row1"><span class="gen"><b>{L_USERNAME}</b></span></td>

Reply via email to