diff --git a/lib/net/ber/core_ext.rb b/lib/net/ber/core_ext.rb index b176df7f..f46acb89 100644 --- a/lib/net/ber/core_ext.rb +++ b/lib/net/ber/core_ext.rb @@ -28,35 +28,35 @@ class String require 'net/ber/core_ext/array' # :stopdoc: -class Array +class Array include Net::BER::Extensions::Array end # :startdoc: require 'net/ber/core_ext/bignum' # :stopdoc: -class Bignum +class Bignum include Net::BER::Extensions::Bignum end # :startdoc: require 'net/ber/core_ext/fixnum' # :stopdoc: -class Fixnum +class Fixnum include Net::BER::Extensions::Fixnum end # :startdoc: require 'net/ber/core_ext/true_class' # :stopdoc: -class TrueClass +class TrueClass include Net::BER::Extensions::TrueClass end # :startdoc: require 'net/ber/core_ext/false_class' # :stopdoc: -class FalseClass +class FalseClass include Net::BER::Extensions::FalseClass end # :startdoc: diff --git a/lib/net/ber/core_ext/string.rb b/lib/net/ber/core_ext/string.rb index b4ad8039..e8a43e2c 100644 --- a/lib/net/ber/core_ext/string.rb +++ b/lib/net/ber/core_ext/string.rb @@ -16,13 +16,13 @@ def to_ber(code = 0x04) [code].pack('C') + raw_string.length.to_ber_length_encoding + raw_string end - ## - # Converts a string to a BER string but does *not* encode to UTF-8 first. - # This is required for proper representation of binary data for Microsoft - # Active Directory - def to_ber_bin(code = 0x04) - [code].pack('C') + length.to_ber_length_encoding + self - end + ## + # Converts a string to a BER string but does *not* encode to UTF-8 first. + # This is required for proper representation of binary data for Microsoft + # Active Directory + def to_ber_bin(code = 0x04) + [code].pack('C') + length.to_ber_length_encoding + self + end def raw_utf8_encoded if self.respond_to?(:encode) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index cbd7917c..4faaad7b 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -317,7 +317,7 @@ class LdapError < StandardError; end DefaultPort = 389 DefaultAuth = { :method => :anonymous } DefaultTreebase = "dc=com" - DefaultForceNoPage = false + DefaultForceNoPage = false StartTlsOid = "1.3.6.1.4.1.1466.20037" @@ -398,7 +398,7 @@ def initialize(args = {}) @verbose = false # Make this configurable with a switch on the class. @auth = args[:auth] || DefaultAuth @base = args[:base] || DefaultTreebase - @force_no_page = args[:force_no_page] || DefaultForceNoPage + @force_no_page = args[:force_no_page] || DefaultForceNoPage encryption args[:encryption] # may be nil if pr = @auth[:password] and pr.respond_to?(:call) @@ -486,7 +486,7 @@ def authenticate(username, password) # standard port for simple-TLS encrypted connections is 636. Be sure you # are using the correct port. # - # The :start_tls like the :simple_tls encryption method also encrypts all + # The :start_tls like the :simple_tls encryption method also encrypts all # communcations with the LDAP server. With the exception that it operates # over the standard TCP port. def encryption(args) @@ -1168,10 +1168,10 @@ def search_subschema_entry # MUST refactor the root_dse call out. #++ def paged_searches_supported? - # active directory returns that it supports paged results. However - # it returns binary data in the rfc2696_cookie which throws an - # encoding exception breaking searching. - return false if @force_no_page + # active directory returns that it supports paged results. However + # it returns binary data in the rfc2696_cookie which throws an + # encoding exception breaking searching. + return false if @force_no_page @server_caps ||= search_root_dse @server_caps[:supportedcontrol].include?(Net::LDAP::LDAPControls::PAGED_RESULTS) end diff --git a/lib/net/ldap/entry.rb b/lib/net/ldap/entry.rb index f27380e3..06943a93 100644 --- a/lib/net/ldap/entry.rb +++ b/lib/net/ldap/entry.rb @@ -115,7 +115,7 @@ def [](name) ## # Read the first value for the provided attribute. The attribute name - # is canonicalized prior to reading. Returns nil if the attribute does + # is canonicalized prior to reading. Returns nil if the attribute does # not exist. def first(name) self[name].first diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 9df345b8..5d91f9f6 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -242,7 +242,7 @@ def present?(attribute) # http://tools.ietf.org/html/rfc4515 lists these exceptions from UTF1 # charset for filters. All of the following must be escaped in any normal - # string using a single backslash ('\') as escape. + # string using a single backslash ('\') as escape. # ESCAPES = { "\0" => '00', # NUL = %x00 ; null character @@ -251,10 +251,10 @@ def present?(attribute) ')' => '29', # RPARENS = %x29 ; right parenthesis (")") '\\' => '5C', # ESC = %x5C ; esc (or backslash) ("\") } - # Compiled character class regexp using the keys from the above hash. + # Compiled character class regexp using the keys from the above hash. ESCAPE_RE = Regexp.new( - "[" + - ESCAPES.keys.map { |e| Regexp.escape(e) }.join + + "[" + + ESCAPES.keys.map { |e| Regexp.escape(e) }.join + "]") ## @@ -310,8 +310,8 @@ def parse_ber(ber) present?(ber.to_s) when 0xa9 # context-specific constructed 9, "extensible comparison" raise Net::LDAP::LdapError, "Invalid extensible search filter, should be at least two elements" if ber.size<2 - - # Reassembles the extensible filter parts + + # Reassembles the extensible filter parts # (["sn", "2.4.6.8.10", "Barbara Jones", '1']) type = value = dn = rule = nil ber.each do |element| @@ -327,7 +327,7 @@ def parse_ber(ber) attribute << type if type attribute << ":#{dn}" if dn attribute << ":#{rule}" if rule - + ex(attribute, value) else raise Net::LDAP::LdapError, "Invalid BER tag-value (#{ber.ber_identifier}) in search filter." diff --git a/lib/net/ldap/password.rb b/lib/net/ldap/password.rb index 929f55ec..47ab03f4 100644 --- a/lib/net/ldap/password.rb +++ b/lib/net/ldap/password.rb @@ -21,17 +21,17 @@ class << self # attribute_value = "" def generate(type, str) - case type - when :md5 - attribute_value = '{MD5}' + Base64.encode64(Digest::MD5.digest(str)).chomp! - when :sha - attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp! - when :ssha - salt = SecureRandom.random_bytes(16) - attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp! - else - raise Net::LDAP::LdapError, "Unsupported password-hash type (#{type})" - end + case type + when :md5 + attribute_value = '{MD5}' + Base64.encode64(Digest::MD5.digest(str)).chomp! + when :sha + attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp! + when :ssha + salt = SecureRandom.random_bytes(16) + attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp! + else + raise Net::LDAP::LdapError, "Unsupported password-hash type (#{type})" + end return attribute_value end end diff --git a/lib/net/snmp.rb b/lib/net/snmp.rb index 3f9e5fb1..501df851 100644 --- a/lib/net/snmp.rb +++ b/lib/net/snmp.rb @@ -3,268 +3,262 @@ # :stopdoc: module Net - class SNMP - VERSION = Net::LDAP::VERSION + class SNMP + VERSION = Net::LDAP::VERSION + AsnSyntax = Net::BER.compile_syntax({ + :application => { + :primitive => { + 1 => :integer, # Counter32, (RFC2578 sec 2) + 2 => :integer, # Gauge32 or Unsigned32, (RFC2578 sec 2) + 3 => :integer # TimeTicks32, (RFC2578 sec 2) + }, + :constructed => {} + }, + :context_specific => { + :primitive => {}, + :constructed => { + 0 => :array, # GetRequest PDU (RFC1157 pgh 4.1.2) + 1 => :array, # GetNextRequest PDU (RFC1157 pgh 4.1.3) + 2 => :array # GetResponse PDU (RFC1157 pgh 4.1.4) + } + } + }) - AsnSyntax = Net::BER.compile_syntax({ - :application => { - :primitive => { - 1 => :integer, # Counter32, (RFC2578 sec 2) - 2 => :integer, # Gauge32 or Unsigned32, (RFC2578 sec 2) - 3 => :integer # TimeTicks32, (RFC2578 sec 2) - }, - :constructed => { - } - }, - :context_specific => { - :primitive => { - }, - :constructed => { - 0 => :array, # GetRequest PDU (RFC1157 pgh 4.1.2) - 1 => :array, # GetNextRequest PDU (RFC1157 pgh 4.1.3) - 2 => :array # GetResponse PDU (RFC1157 pgh 4.1.4) - } - } - }) - - # SNMP 32-bit counter. - # Defined in RFC1155 (Structure of Mangement Information), section 6. - # A 32-bit counter is an ASN.1 application [1] implicit unsigned integer - # with a range from 0 to 2^^32 - 1. - class Counter32 - def initialize value - @value = value - end - def to_ber - @value.to_ber_application(1) - end - end - - # SNMP 32-bit gauge. - # Defined in RFC1155 (Structure of Mangement Information), section 6. - # A 32-bit counter is an ASN.1 application [2] implicit unsigned integer. - # This is also indistinguishable from Unsigned32. (Need to alias them.) - class Gauge32 - def initialize value - @value = value - end - def to_ber - @value.to_ber_application(2) - end - end - - # SNMP 32-bit timer-ticks. - # Defined in RFC1155 (Structure of Mangement Information), section 6. - # A 32-bit counter is an ASN.1 application [3] implicit unsigned integer. - class TimeTicks32 - def initialize value - @value = value - end - def to_ber - @value.to_ber_application(3) - end - end + # SNMP 32-bit counter. + # Defined in RFC1155 (Structure of Mangement Information), section 6. + # A 32-bit counter is an ASN.1 application [1] implicit unsigned integer + # with a range from 0 to 2^^32 - 1. + class Counter32 + def initialize value + @value = value + end + def to_ber + @value.to_ber_application(1) + end end - class SnmpPdu - class Error < StandardError; end - - PduTypes = [ - :get_request, - :get_next_request, - :get_response, - :set_request, - :trap - ] - ErrorStatusCodes = { # Per RFC1157, pgh 4.1.1 - 0 => "noError", - 1 => "tooBig", - 2 => "noSuchName", - 3 => "badValue", - 4 => "readOnly", - 5 => "genErr" - } + # SNMP 32-bit gauge. + # Defined in RFC1155 (Structure of Mangement Information), section 6. + # A 32-bit counter is an ASN.1 application [2] implicit unsigned integer. + # This is also indistinguishable from Unsigned32. (Need to alias them.) + class Gauge32 + def initialize value + @value = value + end + def to_ber + @value.to_ber_application(2) + end + end - class << self - def parse ber_object - n = new - n.send :parse, ber_object - n - end - end + # SNMP 32-bit timer-ticks. + # Defined in RFC1155 (Structure of Mangement Information), section 6. + # A 32-bit counter is an ASN.1 application [3] implicit unsigned integer. + class TimeTicks32 + def initialize value + @value = value + end + def to_ber + @value.to_ber_application(3) + end + end + end - attr_reader :version, :community, :pdu_type, :variables, :error_status - attr_accessor :request_id, :error_index + class SnmpPdu + class Error < StandardError; end + PduTypes = [ + :get_request, + :get_next_request, + :get_response, + :set_request, + :trap + ] + ErrorStatusCodes = { # Per RFC1157, pgh 4.1.1 + 0 => "noError", + 1 => "tooBig", + 2 => "noSuchName", + 3 => "badValue", + 4 => "readOnly", + 5 => "genErr" + } + class << self + def parse ber_object + n = new + n.send :parse, ber_object + n + end + end - def initialize args={} - @version = args[:version] || 0 - @community = args[:community] || "public" - @pdu_type = args[:pdu_type] # leave nil unless specified; there's no reasonable default value. - @error_status = args[:error_status] || 0 - @error_index = args[:error_index] || 0 - @variables = args[:variables] || [] - end + attr_reader :version, :community, :pdu_type, :variables, :error_status + attr_accessor :request_id, :error_index - #-- - def parse ber_object - begin - parse_ber_object ber_object - rescue Error - # Pass through any SnmpPdu::Error instances - raise $! - rescue - # Wrap any basic parsing error so it becomes a PDU-format error - raise Error.new( "snmp-pdu format error" ) - end - end - private :parse + def initialize args={} + @version = args[:version] || 0 + @community = args[:community] || "public" + @pdu_type = args[:pdu_type] # leave nil unless specified; there's no reasonable default value. + @error_status = args[:error_status] || 0 + @error_index = args[:error_index] || 0 + @variables = args[:variables] || [] + end - def parse_ber_object ber_object - send :version=, ber_object[0].to_i - send :community=, ber_object[1].to_s + #-- + def parse ber_object + begin + parse_ber_object ber_object + rescue Error + # Pass through any SnmpPdu::Error instances + raise $! + rescue + # Wrap any basic parsing error so it becomes a PDU-format error + raise Error.new( "snmp-pdu format error" ) + end + end + private :parse - data = ber_object[2] - case (app_tag = data.ber_identifier & 31) - when 0 - send :pdu_type=, :get_request - parse_get_request data - when 1 - send :pdu_type=, :get_next_request - # This PDU is identical to get-request except for the type. - parse_get_request data - when 2 - send :pdu_type=, :get_response - # This PDU is identical to get-request except for the type, - # the error_status and error_index values are meaningful, - # and the fact that the variable bindings will be non-null. - parse_get_response data - else - raise Error.new( "unknown snmp-pdu type: #{app_tag}" ) - end - end - private :parse_ber_object + def parse_ber_object ber_object + send :version=, ber_object[0].to_i + send :community=, ber_object[1].to_s - #-- - # Defined in RFC1157, pgh 4.1.2. - def parse_get_request data - send :request_id=, data[0].to_i - # data[1] is error_status, always zero. - # data[2] is error_index, always zero. - send :error_status=, 0 - send :error_index=, 0 - data[3].each {|n,v| - # A variable-binding, of which there may be several, - # consists of an OID and a BER null. - # We're ignoring the null, we might want to verify it instead. - unless v.is_a?(Net::BER::BerIdentifiedNull) - raise Error.new(" invalid variable-binding in get-request" ) - end - add_variable_binding n, nil - } - end - private :parse_get_request + data = ber_object[2] + case (app_tag = data.ber_identifier & 31) + when 0 + send :pdu_type=, :get_request + parse_get_request data + when 1 + send :pdu_type=, :get_next_request + # This PDU is identical to get-request except for the type. + parse_get_request data + when 2 + send :pdu_type=, :get_response + # This PDU is identical to get-request except for the type, + # the error_status and error_index values are meaningful, + # and the fact that the variable bindings will be non-null. + parse_get_response data + else + raise Error.new( "unknown snmp-pdu type: #{app_tag}" ) + end + end + private :parse_ber_object - #-- - # Defined in RFC1157, pgh 4.1.4 - def parse_get_response data - send :request_id=, data[0].to_i - send :error_status=, data[1].to_i - send :error_index=, data[2].to_i - data[3].each {|n,v| - # A variable-binding, of which there may be several, - # consists of an OID and a BER null. - # We're ignoring the null, we might want to verify it instead. - add_variable_binding n, v - } - end - private :parse_get_response + #-- + # Defined in RFC1157, pgh 4.1.2. + def parse_get_request data + send :request_id=, data[0].to_i + # data[1] is error_status, always zero. + # data[2] is error_index, always zero. + send :error_status=, 0 + send :error_index=, 0 + data[3].each do |n,v| + # A variable-binding, of which there may be several, + # consists of an OID and a BER null. + # We're ignoring the null, we might want to verify it instead. + unless v.is_a?(Net::BER::BerIdentifiedNull) + raise Error.new(" invalid variable-binding in get-request" ) + end + add_variable_binding n, nil + end + end + private :parse_get_request + #-- + # Defined in RFC1157, pgh 4.1.4 + def parse_get_response data + send :request_id=, data[0].to_i + send :error_status=, data[1].to_i + send :error_index=, data[2].to_i + data[3].each do |n,v| + # A variable-binding, of which there may be several, + # consists of an OID and a BER null. + # We're ignoring the null, we might want to verify it instead. + add_variable_binding n, v + end + end + private :parse_get_response - def version= ver - unless [0,2].include?(ver) - raise Error.new("unknown snmp-version: #{ver}") - end - @version = ver - end - def pdu_type= t - unless PduTypes.include?(t) - raise Error.new("unknown pdu-type: #{t}") - end - @pdu_type = t - end + def version= ver + unless [0,2].include?(ver) + raise Error.new("unknown snmp-version: #{ver}") + end + @version = ver + end - def error_status= es - unless ErrorStatusCodes.has_key?(es) - raise Error.new("unknown error-status: #{es}") - end - @error_status = es - end + def pdu_type= t + unless PduTypes.include?(t) + raise Error.new("unknown pdu-type: #{t}") + end + @pdu_type = t + end - def community= c - @community = c.to_s - end + def error_status= es + unless ErrorStatusCodes.has_key?(es) + raise Error.new("unknown error-status: #{es}") + end + @error_status = es + end - #-- - # Syntactic sugar - def add_variable_binding name, value=nil - @variables ||= [] - @variables << [name, value] - end + def community= c + @community = c.to_s + end - def to_ber_string - [ - version.to_ber, - community.to_ber, - pdu_to_ber_string - ].to_ber_sequence - end + #-- + # Syntactic sugar + def add_variable_binding name, value=nil + @variables ||= [] + @variables << [name, value] + end - #-- - # Helper method that returns a PDU payload in BER form, - # depending on the PDU type. - def pdu_to_ber_string - case pdu_type - when :get_request - [ - request_id.to_ber, - error_status.to_ber, - error_index.to_ber, - [ - @variables.map {|n,v| - [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence - } - ].to_ber_sequence - ].to_ber_contextspecific(0) - when :get_next_request - [ - request_id.to_ber, - error_status.to_ber, - error_index.to_ber, - [ - @variables.map {|n,v| - [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence - } - ].to_ber_sequence - ].to_ber_contextspecific(1) - when :get_response - [ - request_id.to_ber, - error_status.to_ber, - error_index.to_ber, - [ - @variables.map {|n,v| - [n.to_ber_oid, v.to_ber].to_ber_sequence - } - ].to_ber_sequence - ].to_ber_contextspecific(2) - else - raise Error.new( "unknown pdu-type: #{pdu_type}" ) - end - end - private :pdu_to_ber_string + def to_ber_string + [ + version.to_ber, + community.to_ber, + pdu_to_ber_string, + ].to_ber_sequence + end + #-- + # Helper method that returns a PDU payload in BER form, + # depending on the PDU type. + def pdu_to_ber_string + case pdu_type + when :get_request + [ + request_id.to_ber, + error_status.to_ber, + error_index.to_ber, + [ + @variables.map {|n,v| + [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence + } + ].to_ber_sequence + ].to_ber_contextspecific(0) + when :get_next_request + [ + request_id.to_ber, + error_status.to_ber, + error_index.to_ber, + [ + @variables.map {|n,v| + [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence + } + ].to_ber_sequence + ].to_ber_contextspecific(1) + when :get_response + [ + request_id.to_ber, + error_status.to_ber, + error_index.to_ber, + [ + @variables.map {|n,v| + [n.to_ber_oid, v.to_ber].to_ber_sequence + } + ].to_ber_sequence + ].to_ber_contextspecific(2) + else + raise Error.new( "unknown pdu-type: #{pdu_type}" ) + end end + private :pdu_to_ber_string + end end # :startdoc: diff --git a/test/test_password.rb b/test/test_password.rb index 26ed54af..87b47d91 100644 --- a/test/test_password.rb +++ b/test/test_password.rb @@ -3,15 +3,8 @@ require_relative 'test_helper' class TestPassword < Test::Unit::TestCase - def test_psw - assert_equal( - "{MD5}xq8jwrcfibi0sZdZYNkSng==", - Net::LDAP::Password.generate( :md5, "cashflow" )) - - assert_equal( - "{SHA}YE4eGkN4BvwNN1f5R7CZz0kFn14=", - Net::LDAP::Password.generate( :sha, "cashflow" )) + assert_equal("{MD5}xq8jwrcfibi0sZdZYNkSng==", Net::LDAP::Password.generate( :md5, "cashflow" )) + assert_equal("{SHA}YE4eGkN4BvwNN1f5R7CZz0kFn14=", Net::LDAP::Password.generate( :sha, "cashflow" )) end - end