Index: nselib/brute.lua
===================================================================
--- nselib/brute.lua	(revision 24581)
+++ nselib/brute.lua	(working copy)
@@ -256,13 +256,13 @@
 	--
 	-- @return string representation of object
 	toString = function( self )
-		local creds
+		local c
 		if ( #self.username > 0 ) then
-			creds = ("%s:%s"):format( self.username, #self.password > 0 and self.password or "<empty>" )
+			c = ("%s:%s"):format( self.username, #self.password > 0 and self.password or "<empty>" )
 		else
-			creds = ("%s"):format( ( self.password and #self.password > 0 ) and self.password or "<empty>" )
+			c = ("%s"):format( ( self.password and #self.password > 0 ) and self.password or "<empty>" )
 		end
-		return ( "%s => %s"):format(creds, self.state.msg )
+		return ( "%s => %s"):format(c, creds.StateMsg[self.state] )
 	end,
 			
 }
@@ -460,16 +460,16 @@
 					return false
 				end
 				
-				local creds
+				local c
 				-- Do we have a username or not?
 				if ( username and #username > 0 ) then
-					creds = ("%s/%s"):format(username, #password > 0 and password or "<empty>")
+					c = ("%s/%s"):format(username, #password > 0 and password or "<empty>")
 				else
-					creds = ("%s"):format(#password > 0 and password or "<empty>")
+					c = ("%s"):format(#password > 0 and password or "<empty>")
 				end
 			
 				local msg = ( retries ~= self.options.max_retries ) and "Re-trying" or "Trying"
-				stdnse.print_debug(2, "%s %s against %s:%d", msg, creds, self.host.ip, self.port.number )
+				stdnse.print_debug(2, "%s %s against %s:%d", msg, c, self.host.ip, self.port.number )
 				status, response = driver:login( username, password )
 
 				driver:disconnect()
@@ -591,15 +591,15 @@
 			if ( not(f) ) then
 				return false, ("Failed to open credfile (%s)"):format(credfile)
 			end
-			local creds = {}
+			local c = {}
 			for line in f:lines() do
 				local trim = function(s) return s:match('^()%s*$') and '' or s:match('^%s*(.*%S)') end 
 				line = trim(line)
 				local user, pass = line:match("^([^%/]*)%/(.*)$")
-				table.insert(creds, { [user]=pass } )
+				table.insert(c, { [user]=pass } )
 			end
 		
-			table.insert( self.iterators, Iterators.credential_iterator( creds ) )
+			table.insert( self.iterators, Iterators.credential_iterator( c ) )
 		elseif ( mode and mode == 'user' ) then
 			table.insert( self.iterators, Iterators.user_pw_iterator( usernames, passwords ) )
 		elseif( mode and mode == 'pass' ) then
Index: nselib/creds.lua
===================================================================
--- nselib/creds.lua	(revision 24581)
+++ nselib/creds.lua	(working copy)
@@ -24,8 +24,8 @@
 -- credentials:
 -- <code>
 --	local c = creds.Credentials:new(creds.ALL_DATA, host, port)
--- 	for _, cred in pairs(c:getCredentials(creds.State.VALID)) do
---		chowContentForUser(cred.user, cred.pass)
+-- 	for cred in c:getCredentials(creds.State.VALID) do
+--		showContentForUser(cred.user, cred.pass)
 -- 	end
 -- </code>
 --
@@ -34,25 +34,39 @@
 -- @author "Patrik Karlsson <patrik@cqure.net>"
 -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html
 
--- Version 0.1
+-- Version 0.3
 -- Created 2011/02/06 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
 -- Revised 2011/27/06 - v0.2 - revised by Patrik Karlsson <patrik@cqure.net>
---								added documentation
---								added getCredentials function
+--								* added documentation
+--								* added getCredentials function
 --
+-- Revised 2011/05/07 - v0.3 - revised by Patrik Karlsson <patrik@cqure.net>
+--                              * modified getCredentials to return an iterator
+--                              * added support for adding credentials as
+--                                script arguments
 
 module(... or "creds", package.seeall)
 
 require('ipOps')
+require('bit')
 
 -- Table containing the different account states
 State = {
-	LOCKED = { msg = 'Account is locked' },
-	VALID = { msg = 'Account is valid' },
-	DISABLED = { msg = 'Account is disabled' },
-	CHANGEPW = { msg = 'Password needs to be changed at next logon' },
+	LOCKED = 1,
+	VALID = 2,
+	DISABLED = 4,
+	CHANGEPW = 8,
+	PARAM = 16,
 }
 
+StateMsg = {
+	[State.LOCKED] = 'Account is locked',
+	[State.VALID] = 'Account is valid',
+	[State.DISABLED] = 'Account is disabled',
+	[State.CHANGEPW] = 'Password needs to be changed at next logon',
+}
+
+
 ALL_DATA = "all_script_data"
 
 -- The RegStorage class
@@ -107,13 +121,12 @@
 	--
 	-- @return table containing all credential records
 	getAll = function( self )
-		local tbl = nmap.registry.creds
 		local new_tbl = {}
 		local host, port = self.filter.host, self.filter.port
 
-		if ( not(tbl) ) then return end
+		if ( not(nmap.registry.creds) ) then return end
 		
-		for _, v in pairs(tbl) do
+		for _, v in pairs(nmap.registry.creds) do
 			local h = ( v.host.ip or v.host )
 			if ( not(host) and not(port) ) then
 				if ( not(self.filter.state) or ( v.state == self.filter.state ) ) then 
@@ -128,7 +141,7 @@
 					table.insert(new_tbl, v) 
 				end
 			elseif ( ( host and ( h == host or h == host.ip ) ) and port.number == v.port ) then
-				if ( not(self.filter.state) or ( v.state == self.filter.state ) ) then 
+				if ( not(self.filter.state) or ( v.state == bit.band(self.filter.state, v.state) ) ) then 
 					table.insert(new_tbl, v) 
 				end
 			end
@@ -160,9 +173,6 @@
 	
 	--- Add a discovered credential
 	--
-	-- @param host host table, name or ip
-	-- @param port number containing the port of the service
-	-- @param service the name of the service
 	-- @param user the name of the user
 	-- @param pass the password of the user
 	-- @param state of the account
@@ -180,24 +190,61 @@
 		end
 	end,
 	
-	--- Returns all accounts for a given state, or all states if no filter is set
+	--- Returns a credential iterator
 	--
-	-- @param state table containing a value from the <Code>State</code> table
-	-- @return table containing accounts matching the state, or all accounts if
-	--         no state was given. Accounts have the following fields:
+	-- @param state mask containing values from the <Code>State</code> table
+	-- @return credential iterator, returning a credential each time it's 
+	--         called. Unless filtered by the state mask all credentials
+	--         for the host, port match are iterated over.
+	--         The credential table has the following fields:
 	--         <code>host</code> - table as received by the action function
 	--         <code>port</code> - number containing the port number
 	--         <code>user</code> - string containing the user name
 	--         <code>pass</code> - string containing the user password
-	--         <code>state</code> - a state table @see <code>State</code>
+	--         <code>state</code> - a state number @see <code>State</code>
 	--         <code>service</code> - string containing the name of the service
 	--         <code>scriptname</code> - string containing the name of the
 	--                                   script that added the credential
 	getCredentials = function(self, state)
-		if ( state ) then 
-			self.storage:setFilter(self.host, { number=self.port, service = self.service }, state)
+		local function next_credential()
+			if ( state ) then 
+				self.storage:setFilter(self.host, { number=self.port, service = self.service }, state)
+			end
+
+			local tmp_table = self.storage:getAll()
+			local creds_table = {}
+
+			for _, cred in ipairs(self.storage:getAll()) do
+				if ( ( self.scriptname == ALL_DATA ) or
+					 ( cred.scriptname == self.scriptname ) ) then
+					coroutine.yield(cred)
+				end
+			end
+
+			if ( state and State.PARAM == bit.band(state, State.PARAM) ) then
+				local creds_global = stdnse.get_script_args('creds.global') or ""
+				local creds_service= stdnse.get_script_args('creds.' .. self.service ) or ""
+				local creds_params = creds_service .. "," .. creds_global
+
+				for _, cred in ipairs(stdnse.strsplit(",", creds_params)) do
+					-- if the credential contains a ':' we have a user + pass pair
+					-- if not, we only have a user with an empty password
+					local user, pass
+					if ( cred:match(":") ) then
+						user, pass = cred:match("^(.-):(.-)$")
+					else
+						user = cred:match("^(.*)$")
+					end
+					coroutine.yield( { host = self.host, 
+					port = self.port,
+					user = user, 
+					pass = pass,
+					state = State.PARAM,
+					service = self.service } )
+				end
+			end
 		end
-		return self.storage:getAll()
+		return coroutine.wrap( next_credential )
 	end,
 	
 	--- Returns a table of credentials
@@ -214,9 +261,9 @@
 			local svc = ("%s/%s"):format(v.port,v.service)
 			local c 
 			if ( v.user and #v.user > 0 ) then
-				c = ("%s:%s - %s"):format(v.user, v.pass, v.state.msg)
+				c = ("%s:%s - %s"):format(v.user, v.pass, StateMsg[v.state])
 			else
-				c = ("%s - %s"):format(v.pass, v.state.msg)
+				c = ("%s - %s"):format(v.pass, StateMsg[v.state])
 			end
 			local script = v.scriptname
 			assert(type(h)=="string", "Could not determine a valid host")
