class Inspec::Resources::LsofPorts
extracts udp and tcp ports from the lsof command
Attributes
lsof[R]
Public Class Methods
new(inspec, lsofpath = nil)
click to toggle source
Calls superclass method
Inspec::Resources::PortsInfo::new
# File lib/inspec/resources/port.rb, line 167 def initialize(inspec, lsofpath = nil) @lsof = lsofpath || "lsof" super(inspec) end
Public Instance Methods
info()
click to toggle source
# File lib/inspec/resources/port.rb, line 172 def info ports = [] # check that lsof is available, otherwise fail raise "Please ensure `lsof` is available on the machine." unless inspec.command(@lsof.to_s).exist? # -F p=pid, c=command, P=protocol name, t=type, n=internet addresses # see 'OUTPUT FOR OTHER PROGRAMS' in LSOF(8) lsof_cmd = inspec.command("#{@lsof} -nP -i -FpctPn") return nil if lsof_cmd.exit_status.to_i != 0 # map to desired return struct lsof_parser(lsof_cmd).each do |process, port_ids| pid, cmd = process.split(":") port_ids.each do |port_str| # should not break on ipv6 addresses ipv, proto, port, host = port_str.split(":", 4) ports.push({ "port" => port.to_i, "address" => host, "protocol" => ipv == "ipv6" ? proto + "6" : proto, "process" => cmd, "pid" => pid.to_i }) end end ports end
lsof_parser(lsof_cmd)
click to toggle source
rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/AbcSize
# File lib/inspec/resources/port.rb, line 202 def lsof_parser(lsof_cmd) procs = {} # build this with formatted output (-F) from lsof # procs = { # '123:sshd' => [ # 'ipv4:tcp:22:127.0.0.1', # 'ipv6:tcp:22:::1', # 'ipv4:tcp:*', # 'ipv6:tcp:*', # ], # '456:ntpd' => [ # 'ipv4:udp:123:*', # 'ipv6:udp:123:*', # ] # } proc_id = port_id = nil lsof_cmd.stdout.each_line do |line| line.chomp! key = line.slice!(0) case key when "p" proc_id = line port_id = nil when "c" proc_id += ":" + line when "t" port_id = line.downcase when "P" port_id += ":" + line.downcase when "n" src, dst = line.split("->") # skip active comm streams next if dst host, port = /^(\S+):(\d+|\*)$/.match(src)[1, 2] # skip channels from port 0 - what does this mean? next if port == "*" # create new array stub if !exist? procs[proc_id] = [] unless procs.key?(proc_id) # change address '*' to zero host = port_id =~ /^ipv6:/ ? "[::]" : "0.0.0.0" if host == "*" # entrust URI to scrub the host and port begin uri = URI("addr://#{host}:#{port}") uri.host && uri.port rescue => e warn "could not parse URI 'addr://#{host}:#{port}' - #{e}" next end # e.g. 'ipv4:tcp:22:127.0.0.1' # strip ipv6 squares for inspec port_id += ":" + port + ":" + host.gsub(/^\[|\]$/, "") # lsof will give us another port unless it's done procs[proc_id] << port_id end end procs end