summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorOmar Roth <omarroth@hotmail.com>2018-11-22 13:26:08 -0600
committerOmar Roth <omarroth@hotmail.com>2018-11-22 13:26:08 -0600
commit26eb59e00d9596adf69e3a3d5f8cb899f8a1da0a (patch)
tree195b43d335679df78389b7600a794fee53d2465c /src
parentca4e8b800c62e4747a61c7358322e2fbf1fcb5cb (diff)
downloadinvidious-26eb59e00d9596adf69e3a3d5f8cb899f8a1da0a.tar.gz
invidious-26eb59e00d9596adf69e3a3d5f8cb899f8a1da0a.tar.bz2
invidious-26eb59e00d9596adf69e3a3d5f8cb899f8a1da0a.zip
Add text CAPTCHA
Diffstat (limited to 'src')
-rw-r--r--src/invidious.cr87
-rw-r--r--src/invidious/views/login.ecr20
2 files changed, 85 insertions, 22 deletions
diff --git a/src/invidious.cr b/src/invidious.cr
index 76d772dc..cbba17c1 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -16,6 +16,7 @@
require "crypto/bcrypt/password"
require "detect_language"
+require "digest/md5"
require "kemal"
require "openssl/hmac"
require "option_parser"
@@ -82,10 +83,11 @@ PG_URL = URI.new(
path: CONFIG.db[:dbname],
)
-PG_DB = DB.open PG_URL
-YT_URL = URI.parse("https://www.youtube.com")
-REDDIT_URL = URI.parse("https://www.reddit.com")
-LOGIN_URL = URI.parse("https://accounts.google.com")
+PG_DB = DB.open PG_URL
+YT_URL = URI.parse("https://www.youtube.com")
+REDDIT_URL = URI.parse("https://www.reddit.com")
+LOGIN_URL = URI.parse("https://accounts.google.com")
+TEXTCAPTCHA_URL = URI.parse("http://textcaptcha.com/omarroth@hotmail.com.json")
crawl_threads.times do
spawn do
@@ -632,8 +634,25 @@ get "/login" do |env|
account_type = env.params.query["type"]?
account_type ||= "invidious"
+ captcha_type = env.params.query["captcha"]?
+ captcha_type ||= "image"
+
if account_type == "invidious"
- captcha = generate_captcha(HMAC_KEY, PG_DB)
+ if captcha_type == "image"
+ captcha = generate_captcha(HMAC_KEY, PG_DB)
+ else
+ response = HTTP::Client.get(TEXTCAPTCHA_URL).body
+ response = JSON.parse(response)
+
+ tokens = response["a"].as_a.map do |answer|
+ create_response(answer.as_s, "sign_in", HMAC_KEY, PG_DB)
+ end
+
+ text_captcha = {
+ question: response["q"].as_s,
+ tokens: tokens,
+ }
+ end
end
tfa = env.params.query["tfa"]?
@@ -827,27 +846,55 @@ post "/login" do |env|
end
elsif account_type == "invidious"
answer = env.params.body["answer"]?
+ text_answer = env.params.body["text_answer"]?
- if !answer
- error_message = "CAPTCHA is a required field"
- next templated "error"
- end
+ if answer
+ answer = answer.lstrip('0')
+ answer = OpenSSL::HMAC.hexdigest(:sha256, HMAC_KEY, answer)
- answer = answer.lstrip('0')
- answer = OpenSSL::HMAC.hexdigest(:sha256, HMAC_KEY, answer)
+ challenge = env.params.body["challenge"]?
+ token = env.params.body["token"]?
- challenge = env.params.body["challenge"]?
- token = env.params.body["token"]?
+ begin
+ validate_response(challenge, token, answer, "sign_in", HMAC_KEY, PG_DB)
+ rescue ex
+ if ex.message == "Invalid user"
+ error_message = "Invalid answer"
+ else
+ error_message = ex.message
+ end
- begin
- validate_response(challenge, token, answer, "sign_in", HMAC_KEY, PG_DB)
- rescue ex
- if ex.message && ex.message == "Invalid user"
- error_message = "Invalid CAPTCHA response"
- else
- error_message = ex.message
+ next templated "error"
+ end
+ elsif text_answer
+ text_answer = Digest::MD5.hexdigest(text_answer.downcase.strip)
+
+ challenges = env.params.body.select { |k, v| k.match(/text_challenge\d+/) }
+ tokens = env.params.body.select { |k, v| k.match(/text_token\d+/) }
+
+ found_valid_captcha = false
+
+ error_message = "Invalid CAPTCHA"
+ challenges.each_with_index do |challenge, i|
+ begin
+ challenge = challenge[1]
+ token = tokens[i][1]
+ validate_response(challenge, token, text_answer, "sign_in", HMAC_KEY, PG_DB)
+ found_valid_captcha = true
+ rescue ex
+ if ex.message == "Invalid user"
+ error_message = "Invalid answer"
+ else
+ error_message = ex.message
+ end
+ end
end
+ if !found_valid_captcha
+ next templated "error"
+ end
+ else
+ error_message = "CAPTCHA is a required field"
next templated "error"
end
diff --git a/src/invidious/views/login.ecr b/src/invidious/views/login.ecr
index 0243d900..69f04ed2 100644
--- a/src/invidious/views/login.ecr
+++ b/src/invidious/views/login.ecr
@@ -24,11 +24,27 @@
<label for="password">Password:</label>
<input required class="pure-input-1" name="password" type="password" placeholder="Password">
+ <% if captcha_type == "image" %>
<img style="width:100%" src='<%= captcha.not_nil![:image] %>'/>
<input type="hidden" name="token" value="<%= captcha.not_nil![:token] %>">
<input type="hidden" name="challenge" value="<%= captcha.not_nil![:challenge] %>">
- <label for="answer">Time (h:mm):</label>
- <input required type="text" name="answer" type="text>" placeholder="hh:mm">
+ <input required type="text" name="answer" type="text" placeholder="h:mm">
+
+ <label>
+ <a href="/login?referer=<%= URI.escape(referer) %>&type=invidious&captcha=text">Text CAPTCHA</a>
+ </label>
+ <% else %>
+ <% text_captcha.not_nil![:tokens].each_with_index do |token, i| %>
+ <input type="hidden" name="text_challenge<%= i %>" value="<%= token[0] %>">
+ <input type="hidden" name="text_token<%= i %>" value="<%= token[1] %>">
+ <% end %>
+ <label for="text_answer"><%= text_captcha.not_nil![:question] %></label>
+ <input required type="text" name="text_answer" type="text" placeholder="Answer">
+
+ <label>
+ <a href="/login?referer=<%= URI.escape(referer) %>&type=invidious">Image CAPTCHA</a>
+ </label>
+ <% end %>
<button type="submit" name="action" value="signin" class="pure-button pure-button-primary">Sign In</button>
<button type="submit" name="action" value="register" class="pure-button pure-button-primary">Register</button>