description = [[
Performs password guessing against IBM DB2
]]

---
-- @output
-- 50000/tcp open  ibm-db2
-- | db2-brute:  
-- |   db2noob:db2noob => Login Correct
-- |_  db2admin:db2admin => Login Correct

author = "Patrik Karlsson"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories={"intrusive", "auth"}

require "stdnse"
require "shortport"
require "db2"
require "unpwdb"

-- Version 0.1
-- Created 05/08/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>


portrule = shortport.port_or_service({50000,60000},"ibm-db2", "tcp", {"open", "open|filtered"})

action = function( host, port )

	local result, response, status = {}, nil, nil
	local valid_accounts = {}	
	local usernames, passwords
	local username, password
	local helper = db2.Helper:new()
	local database = nmap.registry.args['db2-auth.dbname'] or "SAMPLE"

 	status, usernames = unpwdb.usernames()
	if ( not(status) ) then
		return "Failed to load usernames"
	end
	status, passwords = unpwdb.passwords()
	if ( not(status) ) then
		return "Failed to load passwords"
	end
	
	for username in usernames do
		for password in passwords do
				
			helper = db2.Helper:new()
			helper:connect( host, port )		
			stdnse.print_debug( "Trying %s/%s ...", username, password )
			status, response = helper:login( database, username, password )
			helper:close()
			
			if status then				
				-- Add credentials for future db2 scripts to use
				if nmap.registry.db2users == nil then
					nmap.registry.db2users = {}
				end	
				nmap.registry.db2users[username]=password
				
				table.insert( valid_accounts, string.format("%s:%s => Login Correct", username, password:len()>0 and password or "<empty>" ) )
				break
			elseif ( response:match("Database not found") ) then
				return ("The databases %s was not found. (Use --script-args db2-auth.dbname=<dbname> to specify database)"):format(database)
			end
			
		end
		passwords("reset")
	end

	local output = stdnse.format_output(true, valid_accounts)	

	return output

end
