2019-05-02 17:17:27 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2013-12-20 15:34:34 -06:00
|
|
|
# CommonPasswords will check a given password against a list of the most commonly used passwords.
|
2016-03-03 06:06:50 -06:00
|
|
|
# The list comes from https://github.com/danielmiessler/SecLists/tree/master/Passwords
|
|
|
|
# specifically the list of 10 million passwords, top 100k, filtered by length
|
|
|
|
#
|
2013-12-20 15:34:34 -06:00
|
|
|
# The list is stored in Redis at a key that is shared by all sites in a multisite config.
|
|
|
|
#
|
|
|
|
# If the password file is changed, you need to add a migration that deletes the list from redis
|
|
|
|
# so it gets re-populated:
|
|
|
|
#
|
2019-12-03 03:05:53 -06:00
|
|
|
# Discourse.redis.without_namespace.del CommonPasswords::LIST_KEY
|
2013-12-20 15:34:34 -06:00
|
|
|
|
|
|
|
class CommonPasswords
|
2016-03-03 06:06:50 -06:00
|
|
|
PASSWORD_FILE = File.join(Rails.root, "lib", "common_passwords", "10-char-common-passwords.txt")
|
2013-12-20 15:34:34 -06:00
|
|
|
LIST_KEY = "discourse-common-passwords"
|
|
|
|
|
|
|
|
@mutex = Mutex.new
|
|
|
|
|
|
|
|
def self.common_password?(password)
|
2024-05-27 05:27:13 -05:00
|
|
|
return false if password.blank?
|
2013-12-20 15:34:34 -06:00
|
|
|
password_list.include?(password)
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
class RedisPasswordList
|
|
|
|
def include?(password)
|
|
|
|
CommonPasswords.redis.sismember CommonPasswords::LIST_KEY, password
|
|
|
|
end
|
2018-06-07 00:28:18 -05:00
|
|
|
end
|
2013-12-20 15:34:34 -06:00
|
|
|
|
|
|
|
def self.password_list
|
2023-02-16 03:40:11 -06:00
|
|
|
@mutex.synchronize { load_passwords if redis.scard(LIST_KEY) <= 0 }
|
2013-12-20 15:34:34 -06:00
|
|
|
RedisPasswordList.new
|
2018-06-07 00:28:18 -05:00
|
|
|
end
|
2013-12-20 15:34:34 -06:00
|
|
|
|
|
|
|
def self.redis
|
2019-12-03 03:05:53 -06:00
|
|
|
Discourse.redis.without_namespace
|
2013-12-20 15:34:34 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.load_passwords
|
|
|
|
passwords = File.readlines(PASSWORD_FILE)
|
2023-08-27 23:58:47 -05:00
|
|
|
redis.sadd?(LIST_KEY, passwords.map!(&:chomp))
|
2013-12-20 15:34:34 -06:00
|
|
|
rescue Errno::ENOENT
|
|
|
|
# tolerate this so we don't block signups
|
|
|
|
Rails.logger.error "Common passwords file #{PASSWORD_FILE} is not found! Common password checking is skipped."
|
2018-06-07 00:28:18 -05:00
|
|
|
end
|
2013-12-20 15:34:34 -06:00
|
|
|
end
|