Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/Extract Common Credential Module #98

Merged
merged 11 commits into from
Dec 29, 2014
Merged
3 changes: 2 additions & 1 deletion lib/nexpose.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@
require 'nexpose/api_request'
require 'nexpose/common'
require 'nexpose/console'
require 'nexpose/creds'
require 'nexpose/credential'
require 'nexpose/site_credential'
require 'nexpose/shared_cred'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to rename to "shared_credential" as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

require 'nexpose/data_table'
require 'nexpose/device'
Expand Down
107 changes: 107 additions & 0 deletions lib/nexpose/credential.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
module Nexpose

# Contains the shared methods for the SiteCredential and SharedCredential Objects.
# See Nexpose::SiteCredential or Nexpose::SharedCredential for additional info.
class Credential

# Mapping of Common Ports.
DEFAULT_PORTS = { 'cvs' => 2401,
'ftp' => 21,
'http' => 80,
'as400' => 449,
'notes' => 1352,
'tds' => 1433,
'sybase' => 5000,
'cifs' => 445,
'cifshash' => 445,
'oracle' => 1521,
'pop' => 110,
'postgresql' => 5432,
'remote execution' => 512,
'snmp' => 161,
'snmpv3' => 161,
'ssh' => 22,
'ssh-key' => 22,
'telnet' => 23,
'mysql' => 3306,
'db2' => 50000 }


# Credential type options.
module Type
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check to see if there are any new ones to go into the constants here. (Yes, unfortunately, it's a manual process.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All synced up, no new ones to add.

CVS = 'cvs' # Concurrent Versioning System (CVS)
FTP = 'ftp' # File Transfer Protocol (FTP)
HTTP = 'http' # Web Site HTTP Authentication
AS400 = 'as400' # IBM AS/400
NOTES = 'notes' # Lotus Notes/Domino
TDS = 'tds' # Microsoft SQL Server
SYBASE = 'sybase' # Sybase SQL Server
CIFS = 'cifs' # Microsoft Windows/Samba (SMB/CIFS)
CIFSHASH = 'cifshash' # Microsoft Windows/Samba LM/NTLM Hash (SMB/CIFS)
ORACLE = 'oracle' # Oracle
POP = 'pop' # Post Office Protocol (POP)
POSTGRESQL = 'postgresql' # PostgreSQL
REMOTE_EXECUTION = 'remote execution' # Remote Execution
SNMP = 'snmp' # Simple Network Management Protocol
SNMPV3 = 'snmpv3' # Simple Network Management Protocol v3
SSH = 'ssh' # Secure Shell (SSH)
SSH_KEY = 'ssh-key' # Secure Shell (SSH) Public Key
TELNET = 'telnet' # TELNET
MYSQL = 'mysql' # MySQL Server
DB2 = 'db2' # DB2
end


# Permission Elevation / Privilege Escalation Types.
module ElevationType
NONE = 'NONE'
SUDO = 'SUDO'
SUDOSU = 'SUDOSU'
SU = 'SU'
end


# Test this credential against a target where the credentials should apply.
# Only works for a newly created credential. Loading an existing credential
# will likely fail.
#
# @param [Connection] nsc An active connection to the security console.
# @param [String] target Target host to check credentials against.
# @param [Fixnum] engine_id ID of the engine to use for testing credentials.
# Will default to the local engine if none is provided.
#
def test(nsc, target, engine_id = nil)
unless engine_id
engine_id = nsc.engines.find { |e| e.name == 'Local scan engine' }.id
end
@port = Credential::DEFAULT_PORTS[@type] if @port.nil?
parameters = _to_param(target, engine_id, @port)
xml = AJAX.form_post(nsc, '/ajax/test_admin_credentials.txml', parameters)
result = REXML::XPath.first(REXML::Document.new(xml), 'TestAdminCredentialsResult')
result.attributes['success'].to_i == 1
end


def _to_param(target, engine_id, port)
{ engineid: engine_id,
sc_creds_dev: target,
sc_creds_svc: @type,
sc_creds_database: @database,
sc_creds_domain: @domain,
sc_creds_uname: @username,
sc_creds_password: @password,
sc_creds_pemkey: @pem_key,
sc_creds_port: port,
sc_creds_privilegeelevationusername: @privilege_username,
sc_creds_privilegeelevationpassword: @privilege_password,
sc_creds_privilegeelevationtype: @privilege_type,
sc_creds_snmpv3authtype: @auth_type,
sc_creds_snmpv3privtype: @privacy_type,
sc_creds_snmpv3privpassword: @privacy_password,
siteid: -1 }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field doesn't matter, right? Technically we could have a site ID for site credentials, but I don't think it would get used, unless for logging.

end

end


end
47 changes: 2 additions & 45 deletions lib/nexpose/shared_cred.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ def delete_shared_credential(id)
alias_method :delete_shared_cred, :delete_shared_credential
end

class SharedCredentialSummary
class SharedCredentialSummary < Credential

# Unique ID assigned to this credential by Nexpose.
attr_accessor :id
# Name to identify this credential.
attr_accessor :name
# The credential type. See Nexpose::Credential::Type.
# The site credential type. See Nexpose::Credential::Type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a "site" credential. Original was correct.

attr_accessor :type
# Domain or realm.
attr_accessor :domain
Expand Down Expand Up @@ -168,49 +168,6 @@ def to_xml
as_xml.to_s
end

# Test this credential against a target where the credentials should apply.
# Only works for a newly created credential. Loading an existing credential
# will likely fail.
#
# @param [Connection] nsc An active connection to the security console.
# @param [String] target Target host to check credentials against.
# @param [Fixnum] engine_id ID of the engine to use for testing credentials.
# Will default to the local engine if none is provided.
#
def test(nsc, target, engine_id = nil)
unless engine_id
local_engine = nsc.engines.find { |e| e.name == 'Local scan engine' }
engine_id = local_engine.id
end

parameters = _to_param(target, engine_id)
xml = AJAX.form_post(nsc, '/ajax/test_admin_credentials.txml', parameters)
result = REXML::XPath.first(REXML::Document.new(xml), 'TestAdminCredentialsResult')
result.attributes['success'].to_i == 1
end

def _to_param(target, engine_id)
port = @port
port = Credential::DEFAULT_PORTS[@type] if port.nil?

{ engineid: engine_id,
sc_creds_dev: target,
sc_creds_svc: @type,
sc_creds_database: @database,
sc_creds_domain: @domain,
sc_creds_uname: @username,
sc_creds_password: @password,
sc_creds_pemkey: @pem_key,
sc_creds_port: port,
sc_creds_privilegeelevationusername: @privilege_username,
sc_creds_privilegeelevationpassword: @privilege_password,
sc_creds_privilegeelevationtype: @privilege_type,
sc_creds_snmpv3authtype: @auth_type,
sc_creds_snmpv3privtype: @privacy_type,
sc_creds_snmpv3privpassword: @privacy_password,
siteid: -1 }
end

def self.parse(xml)
rexml = REXML::Document.new(xml)
rexml.elements.each('Credential') do |c|
Expand Down
2 changes: 1 addition & 1 deletion lib/nexpose/site.rb
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ def self.parse(rexml)
end

s.elements.each('Credentials/adminCredentials') do |cred|
site.credentials << Credential.parse(cred)
site.credentials << SiteCredential.parse(cred)
end

s.elements.each('ScanConfig') do |scan_config|
Expand Down
97 changes: 19 additions & 78 deletions lib/nexpose/creds.rb → lib/nexpose/site_credential.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,9 @@ module Nexpose
# be passed back as is during a Site Save operation. This object
# can only be used to create a new set of credentials.
#
class Credential
class SiteCredential < Credential
include XMLUtils

DEFAULT_PORTS = { 'cvs' => 2401,
'ftp' => 21,
'http' => 80,
'as400' => 449,
'notes' => 1352,
'tds' => 1433,
'sybase' => 5000,
'cifs' => 445,
'cifshash' => 445,
'oracle' => 1521,
'pop' => 110,
'postgresql' => 5432,
'remote execution' => 512,
'snmp' => 161,
'snmpv3' => 161,
'ssh' => 22,
'ssh-key' => 22,
'telnet' => 23,
'mysql' => 3306,
'db2' => 50000 }

# Security blob for an existing set of credentials
attr_accessor :blob
Expand Down Expand Up @@ -63,6 +43,22 @@ class Credential
# The privacy/encryption pass phrase to use with SNMP v3 credentials
attr_accessor :privacy_password

## Added temporarily while testing the test method.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment indicates that maybe these should be deleted?

# The site credential type. See Nexpose::Credential::Type.
attr_accessor :type
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does service == type? Otherwise, I don't know how site creds were working before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# Permission elevation type. See Nexpose::Credential::ElevationType.
attr_accessor :privilege_type
# User name.
attr_accessor :username
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the names are different, we can merge them in a couple ways. We could alias in the attributes, so that existing code isn't broken by changing "name" -> "username". Or, we could have an override of the #to_param method to put the fields in the right place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I setup an alias for username so that the old userid attr can point to username - for consistency with SharedCredential class.



def initialize(name, id = -1)
@name, @id = name, id.to_i
@sites = []
@disabled = []
end


def self.for_service(service, user, password, realm = nil, host = nil, port = nil)
cred = new
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need to be changed. Either the constructor needs to accept 0 args, or we need to just go ahead an fill them in in this method.

cred.service = service
Expand All @@ -80,7 +76,7 @@ def add_privilege_credentials(type, username, password)
@priv_username = username
@priv_password = password
end

def add_snmpv3_credentials(auth_type, privacy_type, privacy_password)
@auth_type = auth_type
@privacy_type = privacy_type
Expand Down Expand Up @@ -113,7 +109,7 @@ def as_xml
attributes['privilegeelevationtype'] = @priv_type if @priv_type
attributes['privilegeelevationusername'] = @priv_username if @priv_username
attributes['privilegeelevationpassword'] = @priv_password if @priv_password

attributes['snmpv3authtype'] = @auth_type if @auth_type
attributes['snmpv3privtype'] = @privacy_type if @privacy_type
attributes['snmpv3privpassword'] = @privacy_password if @privacy_password
Expand All @@ -139,61 +135,6 @@ def hash
to_xml.hash
end

# Credential type options.
#
module Type

# Concurrent Versioning System (CVS)
CVS = 'cvs'
# File Transfer Protocol (FTP)
FTP = 'ftp'
# Web Site HTTP Authentication
HTTP = 'http'
# IBM AS/400
AS400 = 'as400'
# Lotus Notes/Domino
NOTES = 'notes'
# Microsoft SQL Server
TDS = 'tds'
# Sybase SQL Server
SYBASE = 'sybase'
# Microsoft Windows/Samba (SMB/CIFS)
CIFS = 'cifs'
# Microsoft Windows/Samba LM/NTLM Hash (SMB/CIFS)
CIFSHASH = 'cifshash'
# Oracle
ORACLE = 'oracle'
# Post Office Protocol (POP)
POP = 'pop'
# PostgreSQL
POSTGRESQL = 'postgresql'
# Remote Execution
REMOTE_EXECUTION = 'remote execution'
# Simple Network Management Protocol
SNMP = 'snmp'
# Simple Network Management Protocol v3
SNMPV3 = 'snmpv3'
# Secure Shell (SSH)
SSH = 'ssh'
# Secure Shell (SSH) Public Key
SSH_KEY = 'ssh-key'
# TELNET
TELNET = 'telnet'
# MySQL Server
MYSQL = 'mysql'
# DB2
DB2 = 'db2'
end

# Permission Elevation Types
#
module ElevationType

NONE = 'NONE'
SUDO = 'SUDO'
SUDOSU = 'SUDOSU'
SU = 'SU'
end
end

# Object that represents Header name-value pairs, associated with Web Session Authentication.
Expand Down