module EhcHardenTarget
EhcHardenTarget — resolve !ehc harden args to host/IP/URL (admin scans). Public: resolve, shell_safe_host?, valid_ipv4? Depends: EhcUrl, GeoLookup, UrlLink Tests: test/lib/ehc_harden_target_test.rb
Constants
- NICK_RE
- SHELL_SAFE_HOST_RE
Public Instance Methods
Source
# File lib/ehc_harden_target.rb, line 126 def extract_irc_host_ip(host) text = host.to_s.strip return text if valid_ipv4?(text) tail = text.split("@").last.to_s.strip return tail if valid_ipv4?(tail) GeoLookup.extract_ip(text) end
Source
# File lib/ehc_harden_target.rb, line 100 def find_channel_user(channel_users, nick) target = nick.to_s.strip return nil if target.empty? Array(channel_users).find do |entry| entry_nick = entry.is_a?(Hash) ? (entry[:nick] || entry["nick"]) : entry.respond_to?(:nick) ? entry.nick : nil entry_nick.to_s.casecmp?(target) end end
Source
# File lib/ehc_harden_target.rb, line 86 def harden_result(url:, host:, label:, ip:, nick: nil, kind:) return { harden_target: true, error: :usage } unless shell_safe_host?(host.to_s.sub(/:.*\z/, "")) { harden_target: true, kind: kind, url: url, host: host, label: label, ip: ip, nick: nick } end
Source
# File lib/ehc_harden_target.rb, line 110 def nick_token?(token) token.to_s.match?(NICK_RE) end
Source
# File lib/ehc_harden_target.rb, line 114 def private_url_allowed?(text) url = UrlLink.normalize_url(text.split(/\s+/, 2).first) uri = URI.parse(url) return false unless %w[http https].include?(uri.scheme) return false if uri.host.to_s.strip.empty? ip = GeoLookup.extract_ip(uri.host) ip && GeoLookup.private_ip?(ip) rescue URI::InvalidURIError false end
Source
# File lib/ehc_harden_target.rb, line 20 def resolve(args:, channel_users: nil, admin: false) stripped = args.to_s.strip return { harden_target: false } if stripped.empty? return { harden_target: false } if stripped.match?(/\Aissue\s+\d+\z/i) return resolve_url(stripped, admin: admin) if stripped.match?(%r{\Ahttps?://}i) token, = stripped.split(/\s+/, 2) return resolve_ip(token) if valid_ipv4?(token) return { harden_target: false } if stripped.match?(/\A\d+\z/) return resolve_nick(token, channel_users: channel_users) if nick_token?(token) { harden_target: false, error: :usage } end
Source
# File lib/ehc_harden_target.rb, line 66 def resolve_ip(ip) return { harden_target: true, error: :usage } unless valid_ipv4?(ip) host = ip url = "http://#{ip}/" harden_result(url: url, host: host, label: ip, ip: ip, kind: :ip) end
Source
# File lib/ehc_harden_target.rb, line 74 def resolve_nick(nick, channel_users:) user = find_channel_user(channel_users, nick) return { harden_target: false, error: :usage } unless user host = user[:host] || user["host"] ip = extract_irc_host_ip(host) return { harden_target: true, error: :host, kind: :nick } if ip.nil? || ip.empty? label = "#{nick} (#{ip})" harden_result(url: "http://#{ip}/", host: ip, label: label, ip: ip, nick: nick, kind: :nick) end
Source
# File lib/ehc_harden_target.rb, line 48 def resolve_url(text, admin:) parsed = EhcUrl.parse_command(text) if parsed[:error] if admin && private_url_allowed?(text) url = UrlLink.normalize_url(text.split(/\s+/, 2).first) host = EhcUrl.host_from_url(url) return usage_error unless UrlLink.valid_url?(url) && !host.empty? && shell_safe_host?(host) return harden_result(url: url, host: host, label: host, ip: GeoLookup.extract_ip(host), kind: :url) end error = parsed[:error] == EhcUrl.unsafe_message ? :unsafe : :usage return { harden_target: true, error: error, kind: :url } end harden_result(url: parsed[:url], host: parsed[:host], label: parsed[:host], ip: GeoLookup.extract_ip(parsed[:host]), kind: :url) end
Source
# File lib/ehc_harden_target.rb, line 44 def shell_safe_host?(host) host.to_s.match?(SHELL_SAFE_HOST_RE) end
Source
# File lib/ehc_harden_target.rb, line 136 def usage_error { harden_target: true, error: :usage } end
Source
# File lib/ehc_harden_target.rb, line 37 def valid_ipv4?(ip) text = ip.to_s.strip return false unless text.match?(GeoLookup::IPV4) text.split(".").all? { |octet| octet.to_i.between?(0, 255) } end