Skip to content

Many specific exceptions instead of one LdapError #61

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 50 additions & 23 deletions lib/net/ldap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,33 @@ class Net::LDAP
VERSION = "0.4.0"

class LdapError < StandardError; end
class AlreadyOpenedError < LdapError; end
class SocketError < LdapError; end
class ConnectionRefusedError < LdapError; end
class NoOpenSSLError < LdapError; end
class NoStartTLSResultError < LdapError; end
class StartTLSError < LdapError; end
class EncryptionUnsupportedError < LdapError; end
class EncMethodUnsupportedError < LdapError; end
class AuthMethodUnsupportedError < LdapError; end
class BindingInformationInvalidError < LdapError; end
class NoBindResultError < LdapError; end
class SASLChallengeOverflowError < LdapError; end
class SearchSizeInvalidError < LdapError; end
class SearchScopeInvalidError < LdapError; end
class ResponseTypeInvalidError < LdapError; end
class ResponseMissingOrInvalidError < LdapError; end
class EmptyDNError < LdapError; end
class HashTypeUnsupportedError < LdapError; end
class OperatorError < LdapError; end
class SubstringFilterError < LdapError; end
class SearchFilterError < LdapError; end
class BERInvalidError < LdapError; end
class SearchFilterTypeUnknownError < LdapError; end
class BadAttributeError < LdapError; end
class FilterTypeUnknownError < LdapError; end
class FilterSyntaxInvalidError < LdapError; end
class EntryOverflowError < LdapError; end

SearchScope_BaseObject = 0
SearchScope_SingleLevel = 1
Expand Down Expand Up @@ -563,7 +590,7 @@ def open
# anything with the bind results. We then pass self to the caller's
# block, where he will execute his LDAP operations. Of course they will
# all generate auth failures if the bind was unsuccessful.
raise Net::LDAP::LdapError, "Open already in progress" if @open_connection
raise Net::LDAP::AlreadyOpenedError, "Open already in progress" if @open_connection

begin
@open_connection = Net::LDAP::Connection.new(:host => @host,
Expand Down Expand Up @@ -1134,9 +1161,9 @@ def initialize(server)
begin
@conn = TCPSocket.new(server[:host], server[:port])
rescue SocketError
raise Net::LDAP::LdapError, "No such address or other socket error."
raise Net::LDAP::SocketError, "No such address or other socket error."
rescue Errno::ECONNREFUSED
raise Net::LDAP::LdapError, "Server #{server[:host]} refused connection on port #{server[:port]}."
raise Net::LDAP::ConnectionRefusedError, "Server #{server[:host]} refused connection on port #{server[:port]}."
end

if server[:encryption]
Expand All @@ -1153,7 +1180,7 @@ def getbyte
end

def self.wrap_with_ssl(io)
raise Net::LDAP::LdapError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL
raise Net::LDAP::NoOpenSSLError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL
ctx = OpenSSL::SSL::SSLContext.new
conn = OpenSSL::SSL::SSLSocket.new(io, ctx)
conn.connect
Expand Down Expand Up @@ -1202,16 +1229,16 @@ def setup_encryption(args)
request_pkt = [msgid, request].to_ber_sequence
@conn.write request_pkt
be = @conn.read_ber(Net::LDAP::AsnSyntax)
raise Net::LDAP::LdapError, "no start_tls result" if be.nil?
raise Net::LDAP::NoStartTLSResultError, "no start_tls result" if be.nil?
pdu = Net::LDAP::PDU.new(be)
raise Net::LDAP::LdapError, "no start_tls result" if pdu.nil?
raise Net::LDAP::NoStartTLSResultError, "no start_tls result" if pdu.nil?
if pdu.result_code.zero?
@conn = self.class.wrap_with_ssl(@conn)
else
raise Net::LDAP::LdapError, "start_tls failed: #{pdu.result_code}"
raise Net::LDAP::StartTLSError, "start_tls failed: #{pdu.result_code}"
end
else
raise Net::LDAP::LdapError, "unsupported encryption method #{args[:method]}"
raise Net::LDAP::EncryptionUnsupportedError, "unsupported encryption method #{args[:method]}"
end
end

Expand Down Expand Up @@ -1239,7 +1266,7 @@ def bind(auth)
elsif meth == :gss_spnego
bind_gss_spnego(auth)
else
raise Net::LDAP::LdapError, "Unsupported auth method (#{meth})"
raise Net::LDAP::AuthMethodUnsupportedError, "Unsupported auth method (#{meth})"
end
end

Expand All @@ -1254,15 +1281,15 @@ def bind_simple(auth)
["", ""]
end

raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw)
raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw)

msgid = next_msgid.to_ber
request = [LdapVersion.to_ber, user.to_ber,
psw.to_ber_contextspecific(0)].to_ber_appsequence(0)
request_pkt = [msgid, request].to_ber_sequence
@conn.write request_pkt

(be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result"
(be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::NoBindResultError, "no bind result"

pdu
end
Expand Down Expand Up @@ -1291,7 +1318,7 @@ def bind_simple(auth)
def bind_sasl(auth)
mech, cred, chall = auth[:mechanism], auth[:initial_credential],
auth[:challenge_response]
raise Net::LDAP::LdapError, "Invalid binding information" unless (mech && cred && chall)
raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (mech && cred && chall)

n = 0
loop {
Expand All @@ -1301,9 +1328,9 @@ def bind_sasl(auth)
request_pkt = [msgid, request].to_ber_sequence
@conn.write request_pkt

(be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result"
(be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::NoBindResultError, "no bind result"
return pdu unless pdu.result_code == 14 # saslBindInProgress
raise Net::LDAP::LdapError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges)
raise Net::LDAP::SASLChallengeOverflowError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges)

cred = chall.call(pdu.result_server_sasl_creds)
}
Expand All @@ -1327,7 +1354,7 @@ def bind_gss_spnego(auth)
require 'ntlm'

user, psw = [auth[:username] || auth[:dn], auth[:password]]
raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw)
raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw)

nego = proc { |challenge|
t2_msg = NTLM::Message.parse(challenge)
Expand Down Expand Up @@ -1389,12 +1416,12 @@ def search(args = {})
search_attributes = ((args && args[:attributes]) || []).map { |attr| attr.to_s.to_ber}
return_referrals = args && args[:return_referrals] == true
sizelimit = (args && args[:size].to_i) || 0
raise Net::LDAP::LdapError, "invalid search-size" unless sizelimit >= 0
raise Net::LDAP::SearchSizeInvalidError, "invalid search-size" unless sizelimit >= 0
paged_searches_supported = (args && args[:paged_searches_supported])

attributes_only = (args and args[:attributes_only] == true)
scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree
raise Net::LDAP::LdapError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope)
raise Net::LDAP::SearchScopeInvalidError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope)

sort_control = encode_sort_controls(args.fetch(:sort_controls){ false })
# An interesting value for the size limit would be close to A/D's
Expand Down Expand Up @@ -1490,7 +1517,7 @@ def search(args = {})
end
break
else
raise Net::LDAP::LdapError, "invalid response-type in search: #{pdu.app_tag}"
raise Net::LDAP::ResponseTypeInvalidError, "invalid response-type in search: #{pdu.app_tag}"
end
end

Expand Down Expand Up @@ -1563,7 +1590,7 @@ def modify(args)
pkt = [ next_msgid.to_ber, request ].to_ber_sequence
@conn.write pkt

(be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 7) or raise Net::LDAP::LdapError, "response missing or invalid"
(be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 7) or raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid"

pdu
end
Expand All @@ -1576,7 +1603,7 @@ def modify(args)
# to the error message and the matched-DN returned by the server.
#++
def add(args)
add_dn = args[:dn] or raise Net::LDAP::LdapError, "Unable to add empty DN"
add_dn = args[:dn] or raise Net::LDAP::EmptyDNError, "Unable to add empty DN"
add_attrs = []
a = args[:attributes] and a.each { |k, v|
add_attrs << [ k.to_s.to_ber, Array(v).map { |m| m.to_ber}.to_ber_set ].to_ber_sequence
Expand All @@ -1589,7 +1616,7 @@ def add(args)
(be = @conn.read_ber(Net::LDAP::AsnSyntax)) &&
(pdu = Net::LDAP::PDU.new(be)) &&
(pdu.app_tag == 9) or
raise Net::LDAP::LdapError, "response missing or invalid"
raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid"

pdu
end
Expand All @@ -1611,7 +1638,7 @@ def rename(args)

(be = @conn.read_ber(Net::LDAP::AsnSyntax)) &&
(pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == 13) or
raise Net::LDAP::LdapError.new( "response missing or invalid" )
raise Net::LDAP::ResponseMissingOrInvalidError.new( "response missing or invalid" )

pdu
end
Expand All @@ -1626,7 +1653,7 @@ def delete(args)
pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence
@conn.write pkt

(be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 11) or raise Net::LDAP::LdapError, "response missing or invalid"
(be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 11) or raise Net::LDAP::ResponseMissingOrInvalidError, "response missing or invalid"

pdu
end
Expand Down
2 changes: 1 addition & 1 deletion lib/net/ldap/entry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def from_single_ldif_string(ldif)

return nil if ds.empty?

raise Net::LDAP::LdapError, "Too many LDIF entries" unless ds.size == 1
raise Net::LDAP::EntryOverflowError, "Too many LDIF entries" unless ds.size == 1

entry = ds.to_entries.first

Expand Down
16 changes: 8 additions & 8 deletions lib/net/ldap/filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Net::LDAP::Filter

def initialize(op, left, right) #:nodoc:
unless FilterTypes.include?(op)
raise Net::LDAP::LdapError, "Invalid or unsupported operator #{op.inspect} in LDAP Filter."
raise Net::LDAP::OperatorError, "Invalid or unsupported operator #{op.inspect} in LDAP Filter."
end
@op = op
@left = left
Expand Down Expand Up @@ -290,7 +290,7 @@ def parse_ber(ber)
ber.last.each { |b|
case b.ber_identifier
when 0x80 # context-specific primitive 0, SubstringFilter "initial"
raise Net::LDAP::LdapError, "Unrecognized substring filter; bad initial value." if str.length > 0
raise Net::LDAP::SubstringFilterError, "Unrecognized substring filter; bad initial value." if str.length > 0
str += b
when 0x81 # context-specific primitive 0, SubstringFilter "any"
str += "*#{b}"
Expand All @@ -309,7 +309,7 @@ def parse_ber(ber)
# call to_s to get rid of the BER-identifiedness of the incoming string.
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
raise Net::LDAP::SearchFilterError, "Invalid extensible search filter, should be at least two elements" if ber.size<2

# Reassembles the extensible filter parts
# (["sn", "2.4.6.8.10", "Barbara Jones", '1'])
Expand All @@ -330,7 +330,7 @@ def parse_ber(ber)

ex(attribute, value)
else
raise Net::LDAP::LdapError, "Invalid BER tag-value (#{ber.ber_identifier}) in search filter."
raise Net::LDAP::BERInvalidError, "Invalid BER tag-value (#{ber.ber_identifier}) in search filter."
end
end

Expand All @@ -357,7 +357,7 @@ def parse_ldap_filter(obj)
when 0xa3 # equalityMatch. context-specific constructed 3.
eq(obj[0], obj[1])
else
raise Net::LDAP::LdapError, "Unknown LDAP search-filter type: #{obj.ber_identifier}"
raise Net::LDAP::SearchFilterTypeUnknownError, "Unknown LDAP search-filter type: #{obj.ber_identifier}"
end
end
end
Expand Down Expand Up @@ -534,7 +534,7 @@ def to_ber
seq = []

unless @left =~ /^([-;\w]*)(:dn)?(:(\w+|[.\w]+))?$/
raise Net::LDAP::LdapError, "Bad attribute #{@left}"
raise Net::LDAP::BadAttributeError, "Bad attribute #{@left}"
end
type, dn, rule = $1, $2, $4

Expand Down Expand Up @@ -641,7 +641,7 @@ def match(entry)
l = entry[@left] and l = Array(l) and l.index(@right)
end
else
raise Net::LDAP::LdapError, "Unknown filter type in match: #{@op}"
raise Net::LDAP::FilterTypeUnknownError, "Unknown filter type in match: #{@op}"
end
end

Expand Down Expand Up @@ -674,7 +674,7 @@ def parse(ldap_filter_string)
def initialize(str)
require 'strscan' # Don't load strscan until we need it.
@filter = parse(StringScanner.new(str))
raise Net::LDAP::LdapError, "Invalid filter syntax." unless @filter
raise Net::LDAP::FilterSyntaxInvalidError, "Invalid filter syntax." unless @filter
end

##
Expand Down
2 changes: 1 addition & 1 deletion lib/net/ldap/password.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def generate(type, str)
srand; salt = (rand * 1000).to_i.to_s
attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp!
else
raise Net::LDAP::LdapError, "Unsupported password-hash type (#{type})"
raise Net::LDAP::HashTypeUnsupportedError, "Unsupported password-hash type (#{type})"
end
return attribute_value
end
Expand Down
4 changes: 2 additions & 2 deletions test/test_filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ def test_bug_7534_rfc2254
end

def test_invalid_filter_string
assert_raises(Net::LDAP::LdapError) { Filter.from_rfc2254("") }
assert_raises(Net::LDAP::FilterSyntaxInvalidError) { Filter.from_rfc2254("") }
end

def test_invalid_filter
assert_raises(Net::LDAP::LdapError) {
assert_raises(Net::LDAP::OperatorError) {
# This test exists to prove that our constructor blocks unknown filter
# types. All filters must be constructed using helpers.
Filter.__send__(:new, :xx, nil, nil)
Expand Down