ronin-rb/ronin-recon

View on GitHub
lib/ronin/recon/importer.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true
#
# ronin-recon - A micro-framework and tool for performing reconnaissance.
#
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
#
# ronin-recon is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ronin-recon is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with ronin-recon.  If not, see <https://www.gnu.org/licenses/>.
#

require_relative 'values'

require 'ronin/db'

module Ronin
  module Recon
    #
    # Handles importing recon values into [ronin-db].
    #
    # [ronin-db]: https://github.com/ronin-rb/ronin-db#readme
    #
    # ## Examples
    #
    #     require 'ronin/db'
    #     require 'ronin/recon/importer'
    #
    #     Ronin::DB.connect
    #
    #     values = [Ronin::Recon::Values::Domain.new('...'), ...]
    #
    #     Ronin::Recon::Engine.run(values) do |engine|
    #       engine.on(:value) do |value|
    #         puts "Fond new value #{value}"
    #         Ronin::Recon::Importer.import_value(value)
    #       end
    #     end
    #
    module Importer
      #
      # Imports the connection between two values.
      #
      # @param [Value] value
      #   A discovered recon value to import.
      #
      # @param [Value] parent
      #   The parent value of the discovered recon value.
      #
      # @return [(Ronin::DB::Model, Ronin::DB::Model)]
      #   The imported value and the imported parent value.
      #
      def self.import_connection(value,parent)
        imported_value  = import_value(value)
        imported_parent = import_value(parent)

        if imported_value.kind_of?(DB::IPAddress) &&
           imported_parent.kind_of?(DB::HostName)
          imported_value.host_name_ip_addresses.find_or_create_by(
            host_name: imported_parent
          )
        elsif imported_value.kind_of?(DB::Cert) &&
              imported_parent.kind_of?(DB::OpenPort)
          imported_parent.update(cert: imported_value)
        end

        return imported_value, imported_parent
      end

      #
      # Imports a value into the database.
      #
      # @param [Value] value
      #   A discovered recon value to import.
      #
      # @return [Ronin::DB::HostName,
      #          Ronin::DB::IPAddress,
      #          Ronin::DB::OpenPort,
      #          Ronin::DB::URL,
      #          Ronin::DB::Cert]
      #   The imported record.
      #
      def self.import_value(value)
        case value
        when Values::Host     then import_host_name(value.name)
        when Values::IP       then import_ip_address(value.address)
        when Values::OpenPort then import_open_port(value)
        when Values::URL      then import_url(value.uri)
        when Values::Cert     then import_cert(value.cert)
        end
      end

      #
      # Imports a host value.
      #
      # @param [String] host_name
      #   The host name to import.
      #
      # @return [Ronin::DB::HostName]
      #   The imported host name record.
      #
      def self.import_host_name(host_name)
        DB::HostName.transaction do
          DB::HostName.find_or_import(host_name)
        end
      end

      #
      # Imports a IP address.
      #
      # @param [String] address
      #   The IP address to import.
      #
      # @return [Ronin::DB::IPAddress]
      #   The imported IP address record.
      #
      def self.import_ip_address(address)
        DB::IPAddress.transaction do
          DB::IPAddress.find_or_import(address)
        end
      end

      #
      # Imports a URL.
      #
      # @param [URI::HTTP, String] url
      #   The URL string to import.
      #
      # @return [Ronin::DB::URL]
      #   The imported URL record.
      #
      def self.import_url(url)
        DB::URL.transaction do
          DB::URL.find_or_import(url)
        end
      end

      #
      # Imports a port number.
      #
      # @param [:tcp, :udp] protocol
      #   The protocol that the port uses.
      #
      # @param [Integer] number
      #   The port number to import.
      #
      # @return [Ronin::DB::Port]
      #   The imported port record.
      #
      def self.import_port(protocol,number)
        DB::Port.transaction do
          DB::Port.find_or_create_by(
            protocol: protocol,
            number:   number
          )
        end
      end

      #
      # Imports a service name.
      #
      # @param [String] service
      #   The service name to import.
      #
      # @return [Ronin::DB::Service]
      #   The imported service record.
      #
      def self.import_service(service)
        DB::Service.transaction do
          DB::Service.find_or_import(service)
        end
      end

      #
      # Imports an open port value.
      #
      # @param [Values::OpenPort] open_port
      #   The open port value to import.
      #
      # @return [Ronin::DB::Open_port]
      #   The imported open port record.
      #
      def self.import_open_port(open_port)
        imported_ip_address = import_ip_address(open_port.address)
        imported_port       = import_port(open_port.protocol,open_port.number)
        imported_service    = if (service = open_port.service)
                                import_service(service)
                              end
        imported_open_port  = DB::OpenPort.transaction do
                                DB::OpenPort.find_or_create_by(
                                  ip_address: imported_ip_address,
                                  port:       imported_port,
                                  service:    imported_service
                                )
                              end

        return imported_open_port
      end

      #
      # Imports a SSL/TLS certificate.
      #
      # @param [Ronin::Support::Crypto::Cert, OpenSSL::X509::Certificate] cert
      #   The SSL/TLS certificate to import.
      #
      # @return [Ronin::DB::Cert]
      #   The imported certificate.
      #
      def self.import_cert(cert)
        DB::Cert.transaction do
          DB::Cert.find_or_import(cert)
        end
      end
    end
  end
end