local afp = require "afp" local nmap = require "nmap" local outlib = require "outlib" local shortport = require "shortport" local stdnse = require "stdnse" local table = require "table" description = [[ Shows AFP server information. This information includes the server's hostname, IPv4 and IPv6 addresses, and hardware type (for example Macmini or MacBookPro). ]] --- -- @output -- PORT STATE SERVICE -- 548/tcp open afp -- | afp-serverinfo: -- | Server Flags: -- | Flags hex: 0x837d -- | Super Client: true -- | UUIDs: false -- | UTF8 Server Name: true -- | Open Directory: true -- | Reconnect: false -- | Server Notifications: true -- | TCP/IP: true -- | Server Signature: true -- | Server Messages: true -- | Password Saving Prohibited: true -- | Password Changing: false -- | Copy File: true -- | Server Name: foobardigital -- | Machine Type: Netatalk -- | AFP Versions: AFPVersion 1.1, AFPVersion 2.0, AFPVersion 2.1, AFP2.2, AFPX03, AFP3.1 -- | UAMs: DHX2 -- | Server Signature: bbeb480e00000000bbeb480e00000000 -- | Network Addresses: -- | 192.0.2.235 -- | foobardigital.com -- |_ UTF8 Server Name: foobardigital -- -- @xmloutput -- -- 0x837d -- true -- false -- true -- true -- false -- true -- true -- true -- true -- true -- false -- true --
-- foobardigital -- Netatalk -- -- AFPVersion 1.1 -- AFPVersion 2.0 -- AFPVersion 2.1 -- AFP2.2 -- AFPX03 -- AFP3.1 --
-- -- DHX2 --
-- -- bbeb480e00000000bbeb480e00000000 -- -- 192.0.2.235 -- foobardigital.com --
-- foobardigital -- Version 0.2 -- Created 2010/02/09 - v0.1 - created by Andrew Orr -- Revised 2010/02/10 - v0.2 - added checks for optional fields -- Revised 2015/02/25 - v0.3 - XML structured output author = "Andrew Orr" license = "Same as Nmap--See https://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} portrule = shortport.port_or_service(548, "afp") action = function(host, port) local socket = nmap.new_socket() local status local result = stdnse.output_table() local temp -- set a reasonable timeout value socket:set_timeout(5000) -- do some exception handling / cleanup local catch = function() socket:close() end local try = nmap.new_try(catch) try( socket:connect(host, port) ) -- get our data local afp_proto = afp.Proto:new( { socket=socket } ) local response = afp_proto:fp_get_server_info( socket ) response = response.result -- all the server information is output in the order it occurs in the server -- response. It might be better rearranged? -- output the server flags nicely -- Would like to just pass response.flags, but key ordering would be more -- work than it's worth. local flags = stdnse.output_table() flags["Flags hex"] = ("0x%04x"):format(response.flags.raw) flags["Super Client"] = response.flags.SuperClient flags["UUIDs"] = response.flags.UUIDs flags["UTF8 Server Name"] = response.flags.UTF8ServerName flags["Open Directory"] = response.flags.OpenDirectory flags["Reconnect"] = response.flags.Reconnect flags["Server Notifications"] = response.flags.ServerNotifications flags["TCP/IP"] = response.flags.TCPoverIP flags["Server Signature"] = response.flags.ServerSignature flags["Server Messages"] = response.flags.ServerMessages flags["Password Saving Prohibited"] = response.flags.NoPasswordSaving flags["Password Changing"] = response.flags.ChangeablePasswords flags["Copy File"] = response.flags.CopyFile result["Server Flags"] = flags -- other info result["Server Name"] = response.server_name result["Machine Type"] = response.machine_type -- list the supported AFP versions result["AFP Versions"] = response.afp_versions outlib.list_sep(result["AFP Versions"]) -- list the supported UAMs (User Authentication Modules) result["UAMs"] = response.uams outlib.list_sep(result["UAMs"]) -- server signature, not sure of the format here so just showing a hex string if response.flags.ServerSignature then result["Server Signature"] = stdnse.tohex(response.server_signature) end -- listing the network addresses one line each -- the default for Mac OS X AFP server is to bind everywhere, so this will -- list all network interfaces that the machine has if response.network_addresses_count > 0 then result["Network Addresses"] = response.network_addresses end -- similar to above if response.directory_names_count > 0 then result["Directory Names"] = response.directory_names end -- and finally the utf8 server name if response.flags.UTF8ServerName then result["UTF8 Server Name"] = response.utf8_server_name end return result end