ronin-rb/ronin-recon

View on GitHub
lib/ronin/recon/output_formats/dot.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 'graph_format'
require_relative '../values/domain'
require_relative '../values/mailserver'
require_relative '../values/nameserver'
require_relative '../values/host'
require_relative '../values/ip'
require_relative '../values/ip_range'
require_relative '../values/open_port'
require_relative '../values/email_address'
require_relative '../values/cert'
require_relative '../values/url'
require_relative '../values/website'
require_relative '../values/wildcard'

require 'ronin/core/output_formats/output_file'
require 'set'

module Ronin
  module Recon
    module OutputFormats
      #
      # Represents a GraphViz DOT (`.dot`) output format.
      #
      class Dot < Core::OutputFormats::OutputFile

        include GraphFormat

        #
        # Initializes the GraphViz DOT (`.dot`) output format.
        #
        # @param [IO] io
        #   The output stream to write to.
        #
        def initialize(io)
          super(io)

          @io.puts "digraph {"
        end

        #
        # Returns the descriptive type name for the value object.
        #
        # @param [Value] value
        #   The value object.
        #
        # @return [String]
        #   The type name for the value object.
        #
        # @raise [NotImplementedError]
        #   The given value object was not supported.
        #
        def value_type(value)
          case value
          when Values::Domain       then "Domain"
          when Values::Mailserver   then "Mailserver"
          when Values::Nameserver   then "Nameserver"
          when Values::Host         then "Host"
          when Values::IP           then "IP address"
          when Values::IPRange      then "IP range"
          when Values::OpenPort     then "Open #{value.protocol.upcase} Port"
          when Values::EmailAddress then "Email Address"
          when Values::Cert         then "SSL/TLS Cert"
          when Values::URL          then "URL"
          when Values::Website      then "Website"
          when Values::Wildcard     then "Wildcard"
          else
            raise(NotImplementedError,"value class #{value.class} not supported")
          end
        end

        #
        # Returns the body text for the value object.
        #
        # @param [Value] value
        #   The value object.
        #
        # @return [String]
        #   The body text for the value object.
        #
        def value_text(value)
          case value
          when Values::URL
            "#{value.status} #{value}"
          when Values::Cert
            value.subject.to_h.map { |k,v| "#{k}: #{v}\n" }.join
          else
            value.to_s
          end
        end

        #
        # Writes a value to the GraphViz DOT output stream as a node
        # declaration.
        #
        # @param [Value] value
        #   The value object to write.
        #
        def <<(value)
          name  = value.to_s
          label = "#{value_type(value)}\n#{value_text(value)}"

          @io.puts "\t#{name.inspect} [label=#{label.inspect}]"
          @io.flush
        end

        #
        # Appends a value and it's parent value to the GraphViz DOT output
        # stream.
        #
        # @param [Value] value
        #   The value to append.
        #
        # @param [Value] parent
        #   The parent value of the given value.
        #
        # @return [self]
        #
        def []=(value,parent)
          @io.puts "\t#{parent.to_s.inspect} -> #{value.to_s.inspect}"
          @io.flush
        end

        #
        # Writes the complete JSON Array of values and closes the IO stream.
        #
        def close
          @io.puts "}"

          super
        end

      end
    end
  end
end