From d2d5d48f2993f2ffca415362a40b8a02127bd4a8 Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Sun, 23 Jun 2019 11:21:03 +0100 Subject: [PATCH] Allow signups to be blocked by MX host --- app/controllers/users_controller.rb | 16 +++++++++++++++- app/models/acl.rb | 23 +++++++++++++---------- db/migrate/20190623093642_add_mx_acls.rb | 9 +++++++++ db/structure.sql | 11 ++++++++++- test/models/acl_test.rb | 10 ++++++++-- 5 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 db/migrate/20190623093642_add_mx_acls.rb diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 1ec9ab8d8..17031848d 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -752,7 +752,13 @@ class UsersController < ApplicationController email.split("@").last end - if blocked = Acl.no_account_creation(request.remote_ip, domain) + mx_servers = if domain.nil? + nil + else + domain_mx_servers(domain) + end + + if blocked = Acl.no_account_creation(request.remote_ip, :domain => domain, :mx => mx_servers) logger.info "Blocked signup from #{request.remote_ip} for #{email}" render :action => "blocked" @@ -761,6 +767,14 @@ class UsersController < ApplicationController !blocked end + ## + # get list of MX servers for a domains + def domain_mx_servers(domain) + Resolv::DNS.open do |dns| + dns.getresources(domain, Resolv::DNS::Resource::IN::MX).collect(&:exchange).collect(&:to_s) + end + end + ## # check if this user has a gravatar and set the user pref is true def gravatar_enable(user) diff --git a/app/models/acl.rb b/app/models/acl.rb index cf83e673c..895ed61e4 100644 --- a/app/models/acl.rb +++ b/app/models/acl.rb @@ -7,34 +7,37 @@ # k :string not null # v :string # domain :string +# mx :string # # Indexes # # acls_k_idx (k) # index_acls_on_address (address) USING gist # index_acls_on_domain (domain) +# index_acls_on_mx (mx) # class Acl < ActiveRecord::Base validates :k, :presence => true - def self.match(address, domain = nil) - if domain - Acl.where("address >>= ? OR domain = ?", address, domain) - else - Acl.where("address >>= ?", address) - end + def self.match(address, options = {}) + acls = Acl.where("address >>= ?", address) + + acls = acls.or(Acl.where(:domain => options[:domain])) if options[:domain] + acls = acls.or(Acl.where(:mx => options[:mx])) if options[:mx] + + acls end - def self.no_account_creation(address, domain = nil) - match(address, domain).where(:k => "no_account_creation").exists? + def self.no_account_creation(address, options = {}) + match(address, options).where(:k => "no_account_creation").exists? end def self.no_note_comment(address, domain = nil) - match(address, domain).where(:k => "no_note_comment").exists? + match(address, :domain => domain).where(:k => "no_note_comment").exists? end def self.no_trace_download(address, domain = nil) - match(address, domain).where(:k => "no_trace_download").exists? + match(address, :domain => domain).where(:k => "no_trace_download").exists? end end diff --git a/db/migrate/20190623093642_add_mx_acls.rb b/db/migrate/20190623093642_add_mx_acls.rb new file mode 100644 index 000000000..754e2ee99 --- /dev/null +++ b/db/migrate/20190623093642_add_mx_acls.rb @@ -0,0 +1,9 @@ +class AddMxAcls < ActiveRecord::Migration[5.2] + def change + add_column :acls, :mx, :string + + safety_assured do + add_index :acls, :mx + end + end +end diff --git a/db/structure.sql b/db/structure.sql index 0818ae0e9..d115140d1 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -168,7 +168,8 @@ CREATE TABLE public.acls ( address inet, k character varying NOT NULL, v character varying, - domain character varying + domain character varying, + mx character varying ); @@ -2078,6 +2079,13 @@ CREATE INDEX index_acls_on_address ON public.acls USING gist (address inet_ops); CREATE INDEX index_acls_on_domain ON public.acls USING btree (domain); +-- +-- Name: index_acls_on_mx; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_acls_on_mx ON public.acls USING btree (mx); + + -- -- Name: index_changeset_comments_on_created_at; Type: INDEX; Schema: public; Owner: - -- @@ -2949,6 +2957,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20181020114000'), ('20181031113522'), ('20190518115041'), +('20190623093642'), ('21'), ('22'), ('23'), diff --git a/test/models/acl_test.rb b/test/models/acl_test.rb index d3d8f26fe..ad17fc1b0 100644 --- a/test/models/acl_test.rb +++ b/test/models/acl_test.rb @@ -15,8 +15,14 @@ class AclTest < ActiveSupport::TestCase end def test_no_account_creation_by_domain - assert_not Acl.no_account_creation("192.168.1.1", "example.com") + assert_not Acl.no_account_creation("192.168.1.1", :domain => "example.com") create(:acl, :domain => "example.com", :k => "no_account_creation") - assert Acl.no_account_creation("192.168.1.1", "example.com") + assert Acl.no_account_creation("192.168.1.1", :domain => "example.com") + end + + def test_no_account_creation_by_mx + assert_not Acl.no_account_creation("192.168.1.1", :mx => "mail.example.com") + create(:acl, :mx => "mail.example.com", :k => "no_account_creation") + assert Acl.no_account_creation("192.168.1.1", :mx => "mail.example.com") end end -- 2.43.2