home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Networking / nmap-5.00-setup.exe / nselib / pop3.lua < prev    next >
Text File  |  2009-07-06  |  6KB  |  228 lines

  1. --- POP3 functions.
  2. -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html
  3.  
  4. module(... or "pop3",package.seeall)
  5.  
  6. local HAVE_SSL = false
  7.  
  8. require 'base64'
  9. require 'bit'
  10. require 'stdnse'
  11.  
  12. if pcall(require,'openssl') then
  13.   HAVE_SSL = true
  14. end
  15.   
  16.  
  17.  
  18. err = {
  19.    none = 0,
  20.    userError = 1,
  21.    pwError = 2,
  22.    informationMissing = 3,
  23.    OpenSSLMissing = 4,
  24. }
  25.  
  26. ---
  27. -- Check a POP3 response for <code>"+OK"</code>.
  28. -- @param line First line returned from an POP3 request.
  29. -- @return The string <code>"+OK"</code> if found or <code>nil</code> otherwise.
  30. function stat(line)
  31.    return string.match(line, "+OK")
  32. end
  33.  
  34.  
  35.  
  36. ---
  37. -- Try to log in using the <code>USER</code>/<code>PASS</code> commands.
  38. -- @param socket Socket connected to POP3 server.
  39. -- @param user User string.
  40. -- @param pw Password string.
  41. -- @return Status (true or false).
  42. -- @return Error code if status is false.
  43. function login_user(socket, user, pw)
  44.    socket:send("USER " .. user .. "\r\n")
  45.    status, line = socket:receive_lines(1)
  46.    if not stat(line) then return false, err.user_error end
  47.    socket:send("PASS " .. pw .. "\r\n")
  48.       
  49.    status, line = socket:receive_lines(1)
  50.       
  51.    if stat(line) then return true, err.none 
  52.    else return false, err.pwError
  53.    end
  54. end
  55.  
  56.  
  57. ---
  58. -- Try to login using the the <code>AUTH</code> command using SASL/Plain method.
  59. -- @param socket Socket connected to POP3 server.
  60. -- @param user User string.
  61. -- @param pw Password string.
  62. -- @return Status (true or false).
  63. -- @return Error code if status is false.
  64. function login_sasl_plain(socket, user, pw)
  65.    
  66.    local auth64 = base64.enc(user .. "\0" .. user .. "\0" .. pw)
  67.    socket:send("AUTH PLAIN " .. auth64 .. "\r\n")
  68.    
  69.    status, line = socket:receive_lines(1)
  70.    
  71.    if stat(line) then 
  72.       return true, err.none
  73.    else 
  74.       return false, err.pwError
  75.    end
  76. end
  77.  
  78. ---
  79. -- Try to login using the <code>AUTH</code> command using SASL/Login method.
  80. -- @param user User string.
  81. -- @param pw Password string.
  82. -- @param pw String containing password to login.
  83. -- @return Status (true or false).
  84. -- @return Error code if status is false.
  85. function login_sasl_login(socket, user, pw)
  86.  
  87.    local user64 = base64.enc(user)
  88.    
  89.    local pw64 = base64.enc(pw)
  90.  
  91.    socket:send("AUTH LOGIN\r\n")
  92.       
  93.    status, line = socket:receive_lines(1)
  94.    if not base64.dec(string.sub(line, 3)) == "User Name:" then 
  95.       return false, err.userError 
  96.    end
  97.  
  98.    socket:send(user64)
  99.       
  100.    status, line = socket:receive_lines(1)
  101.  
  102.    if not base64.dec(string.sub(line, 3)) == "Password:" then 
  103.       return false, err.userError
  104.    end
  105.  
  106.    socket:send(pw64)
  107.       
  108.    status, line = socket:receive_lines(1)
  109.     
  110.    if stat(line) then
  111.       return true, err.none
  112.    else
  113.       return false, err.pwError
  114.    end
  115. end
  116.  
  117. ---
  118. -- Try to login using the <code>APOP</code> command.
  119. -- @param socket Socket connected to POP3 server.
  120. -- @param user User string.
  121. -- @param pw Password string.
  122. -- @param challenge String containing challenge from POP3 server greeting.
  123. -- @return Status (true or false).
  124. -- @return Error code if status is false.
  125. function login_apop(socket, user, pw, challenge)
  126.    if type(challenge) ~= "string" then return false, err.informationMissing end
  127.  
  128.    local apStr = stdnse.tohex(openssl.md5(challenge .. pw))
  129.    socket:send(("APOP %s %s\r\n"):format(user, apStr))
  130.       
  131.    status, line = socket:receive_lines(1)
  132.    
  133.    if (stat(line)) then 
  134.       return true, err.none
  135.    else
  136.       return false, err.pwError
  137.    end
  138. end
  139.  
  140. ---
  141. -- Asks a POP3 server for capabilities.
  142. --
  143. -- See RFC 2449.
  144. -- @param host Host to be queried.
  145. -- @param port Port to connect to.
  146. -- @return Table containing capabilities or nil on error.
  147. -- @return nil or String error message.
  148. function capabilities(host, port)
  149.    local socket = nmap.new_socket()
  150.    local capas = {}
  151.    socket:set_timeout(10000)
  152.    local proto = (port.version and port.version.service_tunnel == "ssl" and "ssl") or "tcp"
  153.    if not socket:connect(host.ip, port.number, proto) then return nil, "Could Not Connect" end
  154.  
  155.    status, line = socket:receive_lines(1)
  156.    if not stat(line) then return nil, "No Response" end
  157.    
  158.    if string.find(line, "<[%p%w]+>") then capas.APOP = true end
  159.    
  160.    socket:send("CAPA\r\n")
  161.    status, line = socket:receive_buf("\r\n", false)
  162.    if not stat(line) then 
  163.       capas.capa = false
  164.    else 
  165.       status, line = socket:receive_buf("\r\n", false)
  166.       while line do
  167.      if line ~= "." then
  168.         local capability = string.sub(line, string.find(line, "[%w-]+"))
  169.         line = string.sub(line, #capability + 1)
  170.         capas[capability] = true
  171.         local args = {}
  172.         local w
  173.         for w in string.gmatch(line, "[%w-]+") do
  174.            table.insert(args, w)
  175.         end
  176.         if #args == 1 then capas[capability] = args[1]
  177.         else if #args > 1 then capas[capability] = args 
  178.         end end
  179.      else
  180.         break 
  181.      end
  182.      status, line = socket:receive_buf("\r\n", false)
  183.       end
  184.    end
  185.    socket:close()
  186.    return capas
  187. end
  188.  
  189. ---
  190. -- Try to login using the <code>AUTH</code> command using SASL/CRAM-MD5 method.
  191. -- @param socket Socket connected to POP3 server.
  192. -- @param user User string.
  193. -- @param pw Password string.
  194. -- @return Status (true or false).
  195. -- @return Error code if status is false.
  196. function login_sasl_crammd5(socket, user, pw)
  197.  
  198.    socket:send("AUTH CRAM-MD5\r\n")
  199.    
  200.    status, line = socket:receive_lines(1)
  201.    
  202.    local challenge = base64.dec(string.sub(line, 3))
  203.  
  204.    local digest = stdnse.tohex(openssl.hmac('md5', pw, challenge))
  205.    local authStr = base64.enc(user .. " " .. digest)
  206.    socket:send(authStr .. "\r\n")
  207.       
  208.    status, line = socket:receive_lines(1)
  209.    
  210.    if stat(line) then 
  211.       return true, err.none
  212.    else 
  213.       return false, err.pwError
  214.    end
  215. end
  216.  
  217. -- Overwrite functions requiring OpenSSL if we got no OpenSSL.
  218. if not HAVE_SSL then
  219.  
  220.   local no_ssl = function()
  221.     return false, err.OpenSSLMissing
  222.   end
  223.  
  224.   login_apop = no_ssl
  225.   login_sasl_crammd5 = no_ssl
  226. end
  227.  
  228.