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 "" ) + c = ("%s:%s"):format( self.username, #self.password > 0 and self.password or "" ) else - creds = ("%s"):format( ( self.password and #self.password > 0 ) and self.password or "" ) + c = ("%s"):format( ( self.password and #self.password > 0 ) and self.password or "" ) 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 "") + c = ("%s/%s"):format(username, #password > 0 and password or "") else - creds = ("%s"):format(#password > 0 and password or "") + c = ("%s"):format(#password > 0 and password or "") 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) @@ -44,15 +44,25 @@ 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 +117,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 +137,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 +169,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 @@ -182,14 +188,14 @@ --- Returns all accounts for a given state, or all states if no filter is set -- - -- @param state table containing a value from the State table + -- @param state mask containing values from the State table -- @return table containing accounts matching the state, or all accounts if -- no state was given. Accounts have the following fields: -- host - table as received by the action function -- port - number containing the port number -- user - string containing the user name -- pass - string containing the user password - -- state - a state table @see State + -- state - a state number @see State -- service - string containing the name of the service -- scriptname - string containing the name of the -- script that added the credential @@ -197,7 +203,44 @@ if ( state ) then self.storage:setFilter(self.host, { number=self.port, service = self.service }, state) end - return self.storage:getAll() + + local tmp_table = self.storage:getAll() + local creds_table = {} + + if ( self.scriptname == ALL_DATA ) then + creds_table = tmp_table + else + for _, cred in ipairs(tmp_table) do + if ( cred.scriptname == self.scriptname ) then + table.insert(creds_table, cred) + end + end + end + + if ( 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 + table.insert(creds_table, { host = self.host, + port = self.port, + user = user, + pass = pass, + state = State.PARAM, + service = self.service } ) + end + end + + return creds_table end, --- Returns a table of credentials @@ -214,9 +257,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")