Add a CAPTCHA to protect against automated account creation. The CAPTCHA
changes whenever three new accounts are registered.

Signed-off-by: Lukas Fleischer <[email protected]>
---
This is a first attempt to stop the recent wave of spammers. Other
counter-measures will be implemented if it is not effective.

 web/html/register.php              | 14 +++++-
 web/lib/acctfuncs.inc.php          | 74 +++++++++++++++++++++++++++++-
 web/template/account_edit_form.php | 11 +++++
 3 files changed, 95 insertions(+), 4 deletions(-)

diff --git a/web/html/register.php b/web/html/register.php
index 368999a..a426482 100644
--- a/web/html/register.php
+++ b/web/html/register.php
@@ -36,7 +36,12 @@ if (in_request("Action") == "NewAccount") {
                0,
                in_request("CN"),
                in_request("UN"),
-               in_request("ON"));
+               in_request("ON"),
+               0,
+               "",
+               in_request("captcha_salt"),
+               in_request("captcha"),
+       );
 
        print $message;
 
@@ -59,7 +64,12 @@ if (in_request("Action") == "NewAccount") {
                        0,
                        in_request("CN"),
                        in_request("UN"),
-                       in_request("ON"));
+                       in_request("ON"),
+                       0,
+                       "",
+                       in_request("captcha_salt"),
+                       in_request("captcha")
+               );
        }
 } else {
        print '<p>' . __("Use this form to create an account.") . '</p>';
diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php
index dc44484..b0513c6 100644
--- a/web/lib/acctfuncs.inc.php
+++ b/web/lib/acctfuncs.inc.php
@@ -62,17 +62,25 @@ function html_format_pgp_fingerprint($fingerprint) {
  * @param string $ON Whether to notify of ownership changes
  * @param string $UID The user ID of the displayed user
  * @param string $N The username as present in the database
+ * @param string $captcha_salt The salt used for the CAPTCHA.
+ * @param string $captcha The CAPTCHA answer.
  *
  * @return void
  */
 function 
display_account_form($A,$U="",$T="",$S="",$E="",$H="",$P="",$C="",$R="",
-               
$L="",$TZ="",$HP="",$I="",$K="",$PK="",$J="",$CN="",$UN="",$ON="",$UID=0,$N="") 
{
+               
$L="",$TZ="",$HP="",$I="",$K="",$PK="",$J="",$CN="",$UN="",$ON="",$UID=0,$N="",$captcha_salt="",$captcha="")
 {
        global $SUPPORTED_LANGS;
 
        if ($TZ == "") {
                $TZ = config_get("options", "default_timezone");
        }
 
+       if ($captcha_salt != get_captcha_salt()) {
+               $captcha_salt = get_captcha_salt();
+               $captcha = "";
+       }
+       $captcha_challenge = get_captcha_challenge($captcha_salt);
+
        include("account_edit_form.php");
        return;
 }
@@ -103,11 +111,13 @@ function 
display_account_form($A,$U="",$T="",$S="",$E="",$H="",$P="",$C="",$R=""
  * @param string $ON Whether to notify of ownership changes
  * @param string $UID The user ID of the modified account
  * @param string $N The username as present in the database
+ * @param string $captcha_salt The salt used for the CAPTCHA.
+ * @param string $captcha The CAPTCHA answer.
  *
  * @return array Boolean indicating success and message to be printed
  */
 function 
process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$P="",$C="",
-               
$R="",$L="",$TZ="",$HP="",$I="",$K="",$PK="",$J="",$CN="",$UN="",$ON="",$UID=0,$N="")
 {
+               
$R="",$L="",$TZ="",$HP="",$I="",$K="",$PK="",$J="",$CN="",$UN="",$ON="",$UID=0,$N="",$captcha_salt="",$captcha="")
 {
        global $SUPPORTED_LANGS;
 
        $error = '';
@@ -269,6 +279,18 @@ function 
process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$P="",$C=""
                }
        }
 
+       if (!$error && $TYPE == "new" && empty($captcha)) {
+               $error = __("The CAPTCHA is missing.");
+       }
+
+       if (!$error && $TYPE == "new" && $captcha_salt != get_captcha_salt()) {
+               $error = __("This CAPTCHA has expired. Please try again.");
+       }
+
+       if (!$error && $TYPE == "new" && $captcha != 
get_captcha_answer($captcha_salt)) {
+               $error = __("The entered CAPTCHA answer is invalid.");
+       }
+
        if ($error) {
                $message = "<ul class='errorlist'><li>".$error."</li></ul>\n";
                return array(false, $message);
@@ -1445,3 +1467,51 @@ function account_comments_count($uid) {
        $result = $dbh->query($q);
        return $result->fetchColumn();
 }
+
+/*
+ * Compute the CAPTCHA salt. The salt changes based on the number of registered
+ * users. This ensures that new users always use a different salt.
+ *
+ * @return string The current salt.
+ */
+function get_captcha_salt() {
+       $dbh = DB::connect();
+       $q = "SELECT count(*) FROM Users";
+       $result = $dbh->query($q);
+       $user_count = $result->fetchColumn();
+       return 'aurweb-' . floor($user_count / 3);
+}
+
+/*
+ * Return the CAPTCHA challenge for a given salt.
+ *
+ * @param string $salt The salt to be used for the CAPTCHA computation.
+ *
+ * @return string The challenge as a string.
+ */
+function get_captcha_challenge($salt) {
+       $token = substr(md5($salt), 0, 3);
+       return "pacman -V|sed -r 's#[0-9]+#" . $token . "#g'|md5sum|cut -c1-6";
+}
+
+/*
+ * Compute CAPTCHA answer for a given salt.
+ *
+ * @param string $salt The salt to be used for the CAPTCHA computation.
+ *
+ * @return string The correct answer as a string.
+ */
+function get_captcha_answer($salt) {
+       $token = substr(md5($salt), 0, 3);
+       $text = <<<EOD
+
+ .--.                  Pacman v$token.$token.$token - libalpm 
v$token.$token.$token
+/ _.-' .-.  .-.  .-.   Copyright (C) $token-$token Pacman Development Team
+\  '-. '-'  '-'  '-'   Copyright (C) $token-$token Judd Vinet
+ '--'
+                       This program may be freely redistributed under
+                       the terms of the GNU General Public License.
+
+EOD;
+       return substr(md5($text . "\n"), 0, 6);
+}
diff --git a/web/template/account_edit_form.php 
b/web/template/account_edit_form.php
index 38d5274..5e84aa7 100644
--- a/web/template/account_edit_form.php
+++ b/web/template/account_edit_form.php
@@ -174,6 +174,17 @@
                </p>
        </fieldset>
 
+       <?php if ($A != "UpdateAccount"): ?>
+       <fieldset>
+               <legend><?= __("To protect the AUR against automated account 
creation, we kindly ask you to provide the output of the following command:") 
?> <code><?= htmlspecialchars($captcha_challenge) ?></code></legend>
+               <p>
+                       <label for="id_captcha"><?= __("Answer") ?>:</label>
+                       <input type="text" size="30" maxlength="6" 
name="captcha" id="id_captcha" value="<?= htmlspecialchars($captcha, 
ENT_QUOTES) ?>" /> (<?= __("required") ?>)
+                       <input type="hidden" name="captcha_salt" value="<?= 
htmlspecialchars($captcha_salt) ?>" />
+               </p>
+       </fieldset>
+       <?php endif; ?>
+
        <fieldset>
                <p>
                        <label></label>
-- 
2.23.0

Reply via email to