PageRenderTime 59ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/nselib/omp2.lua

https://github.com/prakashgamit/nmap
Lua | 181 lines | 101 code | 35 blank | 45 comment | 17 complexity | cf9913dde87c8537688d35e8f6b380fc MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0, LGPL-2.1
  1. ---
  2. -- This library was written to ease interaction with OpenVAS Manager servers
  3. -- using OMP (OpenVAS Management Protocol) version 2.
  4. --
  5. -- A very small subset of the protocol is implemented.
  6. -- * Connection/authentication
  7. -- * Targets enumeration
  8. --
  9. -- The library can also store accounts in the registry to share them between
  10. -- scripts.
  11. --
  12. -- The complete protocol documentation is available on the official OpenVAS
  13. -- website: http://www.openvas.org/omp-2-0.html
  14. --
  15. -- Sample use:
  16. -- <code>
  17. -- local session = omp2.Session:new()
  18. -- local status, err = session:connect(host, port)
  19. -- local status, err = session:authenticate(username, password)
  20. -- ...
  21. -- session:close()
  22. -- </code>
  23. --
  24. -- @author Henri Doreau
  25. -- @copyright Same as Nmap -- See http://nmap.org/book/man-legal.html
  26. --
  27. -- @args omp2.username The username to use for authentication.
  28. -- @args omp2.password The password to use for authentication.
  29. --
  30. local nmap = require "nmap"
  31. local stdnse = require "stdnse"
  32. local table = require "table"
  33. _ENV = stdnse.module("omp2", stdnse.seeall)
  34. local HAVE_SSL = false
  35. if pcall(require,'openssl') then
  36. HAVE_SSL = true
  37. end
  38. --- A Session class holds connection and interaction with the server
  39. Session = {
  40. --- Creates a new session object
  41. new = function(self, o)
  42. o = o or {}
  43. setmetatable(o, self)
  44. self.__index = self
  45. o.username = nmap.registry.args["omp2.username"]
  46. o.password = nmap.registry.args["omp2.password"]
  47. o.socket = nmap.new_socket()
  48. return o
  49. end,
  50. --- Establishes the (SSL) connection to the remote server
  51. connect = function(self, host, port)
  52. if not HAVE_SSL then
  53. return false, "The OMP2 module requires OpenSSL support"
  54. end
  55. return self.socket:connect(host, port, "ssl")
  56. end,
  57. --- Closes connection
  58. close = function(self)
  59. return self.socket:close()
  60. end,
  61. --- Attempts to authenticate on the current connection
  62. authenticate = function(self, username, password)
  63. local status, err, xmldata
  64. -- TODO escape credentials
  65. status, err = self.socket:send("<authenticate><credentials>"
  66. .. "<username>" .. username .. "</username>"
  67. .. "<password>" .. password .. "</password>"
  68. .. "</credentials></authenticate>")
  69. if not status then
  70. stdnse.print_debug("ERROR: %s", err)
  71. return false, err
  72. end
  73. status, xmldata = self.socket:receive()
  74. if not status then
  75. stdnse.print_debug("ERROR: %s", xmldata)
  76. return false, xmldata
  77. end
  78. return xmldata:match('status="200"')
  79. end,
  80. --- Lists targets defined on the remote server
  81. ls_targets = function(self)
  82. local status, err, xmldata
  83. local res, target_names, target_hosts = {}, {}, {}
  84. status, err = self.socket:send("<get_targets/>")
  85. if not status then
  86. stdnse.print_debug("ERROR: %s", err)
  87. return false, err
  88. end
  89. status, xmldata = self.socket:receive()
  90. if not status then
  91. stdnse.print_debug("ERROR: %s", xmldata)
  92. return false, xmldata
  93. end
  94. -- As NSE has no XML parser yet, we use regexp to extract the data from the
  95. -- XML output. Targets are defined as a name and the corresponding host(s).
  96. -- Thus we gather both and return an associative array, using names as keys
  97. -- and hosts as values.
  98. local i = 0
  99. for name in xmldata:gmatch("<name>(.-)</name>") do
  100. -- XXX this is hackish: skip the second and third "<name>" tags, as they
  101. -- describe other components than the targets.
  102. -- see: http://www.openvas.org/omp-2-0.html#command_get_targets
  103. if i % 3 == 0 then
  104. table.insert(target_names, name)
  105. end
  106. i = i + 1
  107. end
  108. for hosts in xmldata:gmatch("<hosts>(.-)</hosts>") do
  109. table.insert(target_hosts, hosts)
  110. end
  111. for i, _ in ipairs(target_names) do
  112. res[target_names[i]] = target_hosts[i]
  113. end
  114. return res
  115. end,
  116. }
  117. --- Registers OMP2 credentials for a given host
  118. function add_account(host, username, password)
  119. if not nmap.registry[host.ip] then
  120. nmap.registry[host.ip] = {}
  121. end
  122. if not nmap.registry[host.ip]["omp2accounts"] then
  123. nmap.registry[host.ip]["omp2accounts"] = {}
  124. end
  125. table.insert(nmap.registry[host.ip]["omp2accounts"], {["username"] = username, ["password"] = password})
  126. end
  127. --- Retrieves the list of accounts for a given host
  128. function get_accounts(host)
  129. local accounts = {}
  130. local username, password
  131. username = nmap.registry.args["omp2.username"]
  132. password = nmap.registry.args["omp2.password"]
  133. if username and password then
  134. table.insert(accounts, {["username"] = username, ["password"] = password})
  135. end
  136. if nmap.registry[host.ip] and nmap.registry[host.ip]["omp2accounts"] then
  137. for _, account in pairs(nmap.registry[host.ip]["omp2accounts"]) do
  138. table.insert(accounts, account)
  139. end
  140. end
  141. if #accounts > 0 then
  142. return accounts
  143. end
  144. return nil
  145. end
  146. return _ENV;