---
--@output
-- |  HTTP Auth: HTTP Service requires authentication\n
-- |_   Auth type: Basic, realm = DSL Router\n

-- HTTP authentication information gathering script
-- rev 1.1 (2007-05-25)

-- http-dict.nse builds on the HTTP Auth script
-- adds digest authentication (md5) and implements a larger
-- username/password dictionary
--
-- Updated by        Derek Chadwell  <dechadwe@ncsu.edu>
--                   Philip Mcclellan II  <pamcclel@ncsu.edu>
--                   Vishal Nandwani <vlnandwa@ncsu.edu>
--                   Hua Cheng <hcheng2@ncsu.edu"

id = "HTTP Auth"

description = "If a web server requires authentication, prints accepted username/password pairs"

author = "Thomas Buchanan <tbuchanan@thecompassgrp.net>"




license = "Same as Nmap--See http://nmap.org/book/man-legal.html"

categories = {"default", "auth", "intrusive"}

require "shortport"
require "http"
require "base64"
require "openssl"

portrule = shortport.port_or_service({80, 443, 8080}, {"http","https"})

action = function(host, port)
  local realm,scheme,result
  local basic = false
  local digest = false

  namelist={"", "admin","Admin","Administrator","Administrator",
                    "manager","monitor","public","root","Root","router",
                    "security","user","User","guest"}
  passlist={"","1234","admin","Admin","manager","monitor","password",
                 "Password","public","router","security","user","guest"}

  local answer = http.get( host, port, "/" )

  --- check for 401 response code
  if answer.status == 401 then
    result = "HTTP Service requires authentication\n"

    -- split www-authenticate header
    local auth_headers = {}
    local pcre = pcre.new('\\w+( (\\w+=("[^"]+"|\\w+), *)*(\\w+=("[^"]+"|\\w+)))?',0,"C")
    local match = function( match ) table.insert(auth_headers, match) end
    pcre:gmatch( answer.header['www-authenticate'], match )

    for _, value in pairs( auth_headers ) do
      result = result .. "  Auth type: "
      scheme, realm = string.match(value, "(%a+).-[Rr]ealm=\"(.-)\"")
	nonce = string.match(value, "[Nn]once=\"(.-)\"")
	algorithm = string.match(value, "[Aa]lgorithm=(.-),")
	qop = string.match(value, "[Qq]op=\"(.-)\"")
			
      if scheme == "Basic" then
        basic = true
      end
	if scheme == "Digest" then
	  digest = true
	end
      if realm ~= nil then
        result = result .. scheme .. ", realm = " .. realm .. "\n"
      else
        result = result .. string.match(value, "(%a+)") .. "\n"
      end
    end
  end

  if basic then
    for i,user in ipairs(namelist) do
       for k,password in ipairs(passlist) do
             userpass = user .. ":" .. password
		 userpass = base64.enc(userpass)
            answer = http.get(host, port, '/', {header={Authorization="Basic "..userpass}})
             if answer.status ~= 401 and answer.status ~= 403 then
					result = result .. "  HTTP server may accept user=".. user ..  " with password="..
					 password .." for Basic authentication\n"
			 end
		end
	end
   end

if digest then
	for i,u in ipairs(namelist) do
         for k,p in ipairs(passlist) do
		A3 = "" .. u .. ":" .. realm .. ":" .. p
		A3 = "" .. u .. ":" .. realm .. ":" .. p
		A3 = openssl.md5(A3)
		A3 = openssl.bignum_bin2bn(A3)
		A3 = openssl.bignum_bn2hex(A3)
		A3 = string.lower(A3)
		A2 = "GET:/"
		A2 = openssl.md5(A2)
		A2 = openssl.bignum_bin2bn(A2)
		A2 = openssl.bignum_bn2hex(A2)
		A2 = string.lower(A2)
		nc = "00000001"
		cnonce = "f5d6811482d3ab57d18f06dfe240f390"
		response = A3 .. ":" .. nonce .. ":" .. nc .. ":" .. cnonce .. ":" .. qop .. ":" .. A2
		response = openssl.md5(response)
		response = openssl.bignum_bin2bn(response)
		response = openssl.bignum_bn2hex(response)
		response = string.lower(response)
		auth = scheme .. " "
		auth = auth .. "username=\"" .. u .. "\","
		auth = auth .. "realm=\"" .. realm .. "\","
		auth = auth .. "nonce=\"" .. nonce .. "\","
		auth = auth .. "uri=\"/\","
		auth = auth .. "cnonce=\"" .. cnonce .. "\","
		auth = auth .. "nc=" .. nc .. ","
		auth = auth .. "algorithm=" .. algorithm .. ","
		auth = auth .. "response=\"" .. response .. "\","
		auth = auth .. "qop=\"" .. qop .. "\""
		answer = http.get(host, port, '/', {header={Authorization=auth}})
		if answer.status ~= 401 and answer.status ~= 403 then
					result = result .. "  HTTP server may accept user=".. u ..  " with password="..
					 p .." for Digest authentication\n"
		end



		if answer.status == 401 then

    

    -- split www-authenticate header
    local auth_headers = {}
    local pcre = pcre.new('\\w+( (\\w+=("[^"]+"|\\w+), *)*(\\w+=("[^"]+"|\\w+)))?',0,"C")
    local match = function( match ) table.insert(auth_headers, match) end
    pcre:gmatch( answer.header['www-authenticate'], match )

    for _, value in pairs( auth_headers ) do
      scheme, realm = string.match(value, "(%a+).-[Rr]ealm=\"(.-)\"")
	nonce = string.match(value, "[Nn]once=\"(.-)\"")
		
			
    
    end
  end

	   end
	end
end
  return result


end
