1) { $tld = array_pop($host); $dom = array_pop($host); $uid = $uid.'@'.$dom.'.'.$tld; } } $clientKey = $client . $uid; $totpKey = apc_fetch($clientKey); $username = substr($uid, 0, strpos($uid, '@')); $domain = substr($uid, strpos($uid, '@')+1); $file_db = new PDO('sqlite:/var/run/www-data/dovecot.sqlite'); $file_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $query = $file_db->prepare( "SELECT username || '@' || domain AS uid, password, http_totp FROM mailbox WHERE username = ? AND domain = ? LIMIT 1" ); $query->execute( array( $username, $domain)); $row = $query->fetch(PDO::FETCH_ASSOC); if($row) { syslog(LOG_ERR, "Found row for :" . $username .' :: '. $totpToken); $storedHash = $row['password']; if (strpos($storedHash, '}') > 0) { $storedHash = substr($storedHash, strpos($storedHash, '}') +1); } $hashMethod = substr($storedHash, 0, 3); $hashSalt = substr($storedHash, ($ll = strlen($hashMethod)), strpos($storedHash, '$', $ll) - $ll); $inputHash = crypt($password, $hashMethod);// . $hashSalt . '$'); if (crypt($password, $storedHash) === $storedHash) { syslog(LOG_ERR, "Found valid user!"); if (!isset($_SERVER['HTTP_AUTH_PERMIT_USERS'])) { $permit_auth = true; } else { $permited_users = explode(',', preg_replace('/,\s/', '', $_SERVER['HTTP_AUTH_PERMIT_USERS'])); if (in_array($uid, $permited_users) || in_array($username, $permited_users)) { $permit_auth = true; } } } $previousToken = apc_fetch($invalidKey); if ($permit_auth === true && $row['http_totp'] != null && strlen($row['http_totp']) === 16 && ( $previousToken === false || $previousToken !== $totpToken ) ) { $permit_auth = false; $TimeStamp = Google2FA::get_timestamp(); $secretkey = Google2FA::base32_decode($row['http_totp']); // Decode it into binary $otp = Google2FA::oath_hotp($secretkey, $TimeStamp); // Get current token if (Google2FA::verify_key($row['http_totp'], $totpToken, 1) === true) { syslog(LOG_INFO, 'Client ' . $_SERVER['REMOTE_ADDR'] . ' has passed two factor auth.'); $permit_auth = true; apc_store($invalidKey, $totpToken, $SESS_TTL); } else { syslog(LOG_INFO, 'Client ' . $_SERVER['REMOTE_ADDR'] . ' has FAILED two factor auth.'); } } if ($previousToken !== false && $previousToken === $totpToken) { syslog(LOG_WARNING, 'POSSIBLE REPLAY ATTACK FROM HOST: '. $_SERVER['REMOTE_ADDR']); $tries = $MAX_TRIES+1; } } } if ($permit_auth === true) { header('Content-Type: text/html; charset=utf-8', true); header('Content-Disposition: ""', true); header('Status: 200 OK', true); apc_store($sessionKey, $basicStr, $SESS_TTL); echo "\n\r"; // LEAVE ME HERE! exit(0); } else if ($permit_auth === false && $tries <= $MAX_TRIES) { syslog(LOG_ERR, 'HTTP Auth FAILED for ' . $uid . ' from ' . $_SERVER['REMOTE_ADDR']); apc_store($client, ++$tries, $BAN_TTL); sleep(1*$tries); // Delay them losers! } } if ($tries > $MAX_TRIES) { syslog(LOG_ERR, 'HTTP Auth FAILED for ' . $uid . ' from ' . $_SERVER['REMOTE_ADDR']); if ($tries == ($MAX_TRIES + 1)) { syslog(LOG_ERR, 'HTTP Auth BANNED for ' . $uid . ' from ' . $_SERVER['REMOTE_ADDR']); } apc_store($client, ++$tries, $BAN_TTL); sleep(1*$tries); } syslog(LOG_INFO, $realmMessage); header('Content-Type: text/html; charset=utf-8', true); header('Content-Disposition: ""', true); header('WWW-Authenticate: Basic realm='. $realmMessage, true); header('Status: 401 Unauthorized', true); echo "\n\r"; // LEAVE ME HERE! exit(0);