net-ldap 0.3.1 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of net-ldap might be problematic. Click here for more details.

@@ -23,7 +23,7 @@
23
23
  class Net::LDAP::Filter
24
24
  ##
25
25
  # Known filter types.
26
- FilterTypes = [ :ne, :eq, :ge, :le, :and, :or, :not, :ex ]
26
+ FilterTypes = [ :ne, :eq, :ge, :le, :and, :or, :not, :ex, :bineq ]
27
27
 
28
28
  def initialize(op, left, right) #:nodoc:
29
29
  unless FilterTypes.include?(op)
@@ -65,6 +65,23 @@ class Net::LDAP::Filter
65
65
  new(:eq, attribute, value)
66
66
  end
67
67
 
68
+ ##
69
+ # Creates a Filter object indicating a binary comparison.
70
+ # this prevents the search data from being forced into a UTF-8 string.
71
+ #
72
+ # This is primarily used for Microsoft Active Directory to compare
73
+ # GUID values.
74
+ #
75
+ # # for guid represented as hex charecters
76
+ # guid = "6a31b4a12aa27a41aca9603f27dd5116"
77
+ # guid_bin = [guid].pack("H*")
78
+ # f = Net::LDAP::Filter.bineq("objectGUID", guid_bin)
79
+ #
80
+ # This filter does not perform any escaping.
81
+ def bineq(attribute, value)
82
+ new(:bineq, attribute, value)
83
+ end
84
+
68
85
  ##
69
86
  # Creates a Filter object indicating extensible comparison. This Filter
70
87
  # object is currently considered EXPERIMENTAL.
@@ -274,11 +291,11 @@ class Net::LDAP::Filter
274
291
  case b.ber_identifier
275
292
  when 0x80 # context-specific primitive 0, SubstringFilter "initial"
276
293
  raise Net::LDAP::LdapError, "Unrecognized substring filter; bad initial value." if str.length > 0
277
- str += b
294
+ str += escape(b)
278
295
  when 0x81 # context-specific primitive 0, SubstringFilter "any"
279
- str += "*#{b}"
296
+ str += "*#{escape(b)}"
280
297
  when 0x82 # context-specific primitive 0, SubstringFilter "final"
281
- str += "*#{b}"
298
+ str += "*#{escape(b)}"
282
299
  final = true
283
300
  end
284
301
  }
@@ -399,6 +416,8 @@ class Net::LDAP::Filter
399
416
  "!(#{@left}=#{@right})"
400
417
  when :eq
401
418
  "#{@left}=#{@right}"
419
+ when :bineq
420
+ "#{@left}=#{@right}"
402
421
  when :ex
403
422
  "#{@left}:=#{@right}"
404
423
  when :ge
@@ -490,17 +509,17 @@ class Net::LDAP::Filter
490
509
  first = nil
491
510
  ary.shift
492
511
  else
493
- first = ary.shift.to_ber_contextspecific(0)
512
+ first = unescape(ary.shift).to_ber_contextspecific(0)
494
513
  end
495
514
 
496
515
  if ary.last.empty?
497
516
  last = nil
498
517
  ary.pop
499
518
  else
500
- last = ary.pop.to_ber_contextspecific(2)
519
+ last = unescape(ary.pop).to_ber_contextspecific(2)
501
520
  end
502
521
 
503
- seq = ary.map { |e| e.to_ber_contextspecific(1) }
522
+ seq = ary.map { |e| unescape(e).to_ber_contextspecific(1) }
504
523
  seq.unshift first if first
505
524
  seq.push last if last
506
525
 
@@ -508,6 +527,9 @@ class Net::LDAP::Filter
508
527
  else # equality
509
528
  [@left.to_s.to_ber, unescape(@right).to_ber].to_ber_contextspecific(3)
510
529
  end
530
+ when :bineq
531
+ # make sure data is not forced to UTF-8
532
+ [@left.to_s.to_ber, unescape(@right).to_ber_bin].to_ber_contextspecific(3)
511
533
  when :ex
512
534
  seq = []
513
535
 
@@ -733,7 +755,7 @@ class Net::LDAP::Filter
733
755
  scanner.scan(/\s*/)
734
756
  if op = scanner.scan(/<=|>=|!=|:=|=/)
735
757
  scanner.scan(/\s*/)
736
- if value = scanner.scan(/(?:[-\w*.+@=,#\$%&!'\s]|\\[a-fA-F\d]{2})+/)
758
+ if value = scanner.scan(/(?:[-\w*.+@=,#\$%&!'\s\xC3\x80-\xCA\xAF]|[^\x00-\x7F]|\\[a-fA-F\d]{2})+/u)
737
759
  # 20100313 AZ: Assumes that "(uid=george*)" is the same as
738
760
  # "(uid=george* )". The standard doesn't specify, but I can find
739
761
  # no examples that suggest otherwise.
@@ -1,31 +1,37 @@
1
1
  # -*- ruby encoding: utf-8 -*-
2
2
  require 'digest/sha1'
3
3
  require 'digest/md5'
4
+ require 'base64'
4
5
 
5
6
  class Net::LDAP::Password
6
7
  class << self
7
8
  # Generate a password-hash suitable for inclusion in an LDAP attribute.
8
- # Pass a hash type (currently supported: :md5 and :sha) and a plaintext
9
+ # Pass a hash type as a symbol (:md5, :sha, :ssha) and a plaintext
9
10
  # password. This function will return a hashed representation.
10
11
  #
11
12
  #--
12
13
  # STUB: This is here to fulfill the requirements of an RFC, which
13
14
  # one?
14
15
  #
15
- # TODO, gotta do salted-sha and (maybe)salted-md5. Should we provide
16
- # sha1 as a synonym for sha1? I vote no because then should you also
17
- # provide ssha1 for symmetry?
16
+ # TODO:
17
+ # * maybe salted-md5
18
+ # * Should we provide sha1 as a synonym for sha1? I vote no because then
19
+ # should you also provide ssha1 for symmetry?
20
+ #
21
+ attribute_value = ""
18
22
  def generate(type, str)
19
- digest, digest_name = case type
20
- when :md5
21
- [Digest::MD5.new, 'MD5']
22
- when :sha
23
- [Digest::SHA1.new, 'SHA']
24
- else
25
- raise Net::LDAP::LdapError, "Unsupported password-hash type (#{type})"
26
- end
27
- digest << str.to_s
28
- return "{#{digest_name}}#{[digest.digest].pack('m').chomp }"
23
+ case type
24
+ when :md5
25
+ attribute_value = '{MD5}' + Base64.encode64(Digest::MD5.digest(str)).chomp!
26
+ when :sha
27
+ attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp!
28
+ when :ssha
29
+ srand; salt = (rand * 1000).to_i.to_s
30
+ attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp!
31
+ else
32
+ raise Net::LDAP::LdapError, "Unsupported password-hash type (#{type})"
33
+ end
34
+ return attribute_value
29
35
  end
30
36
  end
31
37
  end
@@ -112,6 +112,10 @@ class Net::LDAP::PDU
112
112
  @ldap_result || {}
113
113
  end
114
114
 
115
+ def error_message
116
+ result[:errorMessage] || ""
117
+ end
118
+
115
119
  ##
116
120
  # This returns an LDAP result code taken from the PDU, but it will be nil
117
121
  # if there wasn't a result code. That can easily happen depending on the
@@ -120,6 +124,18 @@ class Net::LDAP::PDU
120
124
  @ldap_result and @ldap_result[code]
121
125
  end
122
126
 
127
+ def status
128
+ result_code == 0 ? :success : :failure
129
+ end
130
+
131
+ def success?
132
+ status == :success
133
+ end
134
+
135
+ def failure?
136
+ !success?
137
+ end
138
+
123
139
  ##
124
140
  # Return serverSaslCreds, which are only present in BindResponse packets.
125
141
  #--
@@ -0,0 +1,5 @@
1
+ module Net
2
+ class LDAP
3
+ VERSION = "0.5.1"
4
+ end
5
+ end
@@ -1,8 +1,10 @@
1
1
  # -*- ruby encoding: utf-8 -*-
2
+ require 'net/ldap/version'
3
+
2
4
  # :stopdoc:
3
5
  module Net
4
6
  class SNMP
5
- VERSION = '0.3.1'
7
+ VERSION = Net::LDAP::VERSION
6
8
 
7
9
  AsnSyntax = Net::BER.compile_syntax({
8
10
  :application => {
@@ -1,11 +1,16 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'net/ldap/version'
5
+
2
6
  Gem::Specification.new do |s|
3
7
  s.name = %q{net-ldap}
4
- s.version = "0.3.1"
8
+ s.version = Net::LDAP::VERSION
9
+ s.license = "MIT"
5
10
 
6
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
7
- s.authors = ["Francis Cianfrocca", "Emiel van de Laar", "Rory O'Connell", "Kaspar Schiess", "Austin Ziegler"]
8
- s.date = %q{2011-03-17}
12
+ s.authors = ["Francis Cianfrocca", "Emiel van de Laar", "Rory O'Connell", "Kaspar Schiess", "Austin Ziegler", "Michael Schaarschmidt"]
13
+ s.date = %q{2012-02-28}
9
14
  s.description = %q{Net::LDAP for Ruby (also called net-ldap) implements client access for the
10
15
  Lightweight Directory Access Protocol (LDAP), an IETF standard protocol for
11
16
  accessing distributed directory services. Net::LDAP is written completely in
@@ -14,12 +19,12 @@ subset of server features as well.
14
19
 
15
20
  Net::LDAP has been tested against modern popular LDAP servers including
16
21
  OpenLDAP and Active Directory. The current release is mostly compliant with
17
- earlier versions of the IETF LDAP RFCs (22512256, 28292830, 3377, and 3771).
22
+ earlier versions of the IETF LDAP RFCs (2251-2256, 2829-2830, 3377, and 3771).
18
23
  Our roadmap for Net::LDAP 1.0 is to gain full <em>client</em> compliance with
19
- the most recent LDAP RFCs (45104519, plutions of 45204532).}
24
+ the most recent LDAP RFCs (4510-4519, plutions of 4520-4532).}
20
25
  s.email = ["blackhedd@rubyforge.org", "gemiel@gmail.com", "rory.ocon@gmail.com", "kaspar.schiess@absurd.li", "austin@rubyforge.org"]
21
26
  s.extra_rdoc_files = ["Manifest.txt", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "README.rdoc"]
22
- s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif"]
27
+ s.files = [".autotest", ".rspec", "Contributors.rdoc", "Hacking.rdoc", "History.rdoc", "License.rdoc", "Manifest.txt", "README.rdoc", "Rakefile", "autotest/discover.rb", "lib/net-ldap.rb", "lib/net/ber.rb", "lib/net/ber/ber_parser.rb", "lib/net/ber/core_ext.rb", "lib/net/ber/core_ext/array.rb", "lib/net/ber/core_ext/bignum.rb", "lib/net/ber/core_ext/false_class.rb", "lib/net/ber/core_ext/fixnum.rb", "lib/net/ber/core_ext/string.rb", "lib/net/ber/core_ext/true_class.rb", "lib/net/ldap.rb", "lib/net/ldap/dataset.rb", "lib/net/ldap/dn.rb", "lib/net/ldap/entry.rb", "lib/net/ldap/filter.rb", "lib/net/ldap/password.rb", "lib/net/ldap/pdu.rb", "lib/net/snmp.rb", "net-ldap.gemspec", "spec/integration/ssl_ber_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/ber/ber_spec.rb", "spec/unit/ber/core_ext/string_spec.rb", "spec/unit/ldap/dn_spec.rb", "spec/unit/ldap/entry_spec.rb", "spec/unit/ldap/filter_spec.rb", "spec/unit/ldap_spec.rb", "test/common.rb", "test/test_entry.rb", "test/test_filter.rb", "test/test_ldap_connection.rb", "test/test_ldif.rb", "test/test_password.rb", "test/test_rename.rb", "test/test_snmp.rb", "test/testdata.ldif", "testserver/ldapserver.rb", "testserver/testdata.ldif", "lib/net/ldap/version.rb"]
23
28
  s.homepage = %q{http://github.com.org/ruby-ldap/ruby-net-ldap}
24
29
  s.rdoc_options = ["--main", "README.rdoc"]
25
30
  s.require_paths = ["lib"]
@@ -36,14 +41,14 @@ the most recent LDAP RFCs (4510–4519, plutions of 4520–4532).}
36
41
  s.add_development_dependency(%q<hoe-git>, ["~> 1"])
37
42
  s.add_development_dependency(%q<hoe-gemspec>, ["~> 1"])
38
43
  s.add_development_dependency(%q<metaid>, ["~> 1"])
39
- s.add_development_dependency(%q<flexmock>, ["~> 0.9.0"])
44
+ s.add_development_dependency(%q<flexmock>, [">= 1.3.0"])
40
45
  s.add_development_dependency(%q<rspec>, ["~> 2.0"])
41
46
  s.add_development_dependency(%q<hoe>, [">= 2.9.1"])
42
47
  else
43
48
  s.add_dependency(%q<hoe-git>, ["~> 1"])
44
49
  s.add_dependency(%q<hoe-gemspec>, ["~> 1"])
45
50
  s.add_dependency(%q<metaid>, ["~> 1"])
46
- s.add_dependency(%q<flexmock>, ["~> 0.9.0"])
51
+ s.add_dependency(%q<flexmock>, [">= 1.3.0"])
47
52
  s.add_dependency(%q<rspec>, ["~> 2.0"])
48
53
  s.add_dependency(%q<hoe>, [">= 2.9.1"])
49
54
  end
@@ -51,7 +56,7 @@ the most recent LDAP RFCs (4510–4519, plutions of 4520–4532).}
51
56
  s.add_dependency(%q<hoe-git>, ["~> 1"])
52
57
  s.add_dependency(%q<hoe-gemspec>, ["~> 1"])
53
58
  s.add_dependency(%q<metaid>, ["~> 1"])
54
- s.add_dependency(%q<flexmock>, ["~> 0.9.0"])
59
+ s.add_dependency(%q<flexmock>, [">= 1.3.0"])
55
60
  s.add_dependency(%q<rspec>, ["~> 2.0"])
56
61
  s.add_dependency(%q<hoe>, [">= 2.9.1"])
57
62
  end
@@ -84,9 +84,14 @@ describe "BER encoding of" do
84
84
  it "should properly encode strings encodable as UTF-8" do
85
85
  "teststring".encode("US-ASCII").to_ber.should == "\x04\nteststring"
86
86
  end
87
- it "should fail on strings that can not be converted to UTF-8" do
87
+ it "should properly encode binary data strings using to_ber_bin" do
88
+ # This is used for searching for GUIDs in Active Directory
89
+ ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").to_ber_bin.should ==
90
+ "\x04\x10" + "j1\xB4\xA1*\xA2zA\xAC\xA9`?'\xDDQ\x16"
91
+ end
92
+ it "should not fail on strings that can not be converted to UTF-8" do
88
93
  error = Encoding::UndefinedConversionError
89
- lambda {"\x81".to_ber }.should raise_exception(error)
94
+ lambda {"\x81".to_ber }.should_not raise_exception(error)
90
95
  end
91
96
  end
92
97
  end
@@ -107,3 +112,30 @@ describe "BER decoding of" do
107
112
  end
108
113
  end
109
114
  end
115
+
116
+ describe Net::BER::BerIdentifiedString do
117
+ describe "initialize" do
118
+ subject { Net::BER::BerIdentifiedString.new(data) }
119
+
120
+ context "binary data" do
121
+ let(:data) { ["6a31b4a12aa27a41aca9603f27dd5116"].pack("H*").force_encoding("ASCII-8BIT") }
122
+
123
+ its(:valid_encoding?) { should be_true }
124
+ specify { subject.encoding.name.should == "ASCII-8BIT" }
125
+ end
126
+
127
+ context "ascii data in UTF-8" do
128
+ let(:data) { "some text".force_encoding("UTF-8") }
129
+
130
+ its(:valid_encoding?) { should be_true }
131
+ specify { subject.encoding.name.should == "UTF-8" }
132
+ end
133
+
134
+ context "UTF-8 data in UTF-8" do
135
+ let(:data) { ["e4b8ad"].pack("H*").force_encoding("UTF-8") }
136
+
137
+ its(:valid_encoding?) { should be_true }
138
+ specify { subject.encoding.name.should == "UTF-8" }
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'metaid'
3
+
4
+ describe Array, "when extended with BER core extensions" do
5
+
6
+ it "should correctly convert a control code array" do
7
+ control_codes = []
8
+ control_codes << ['1.2.3'.to_ber, true.to_ber].to_ber_sequence
9
+ control_codes << ['1.7.9'.to_ber, false.to_ber].to_ber_sequence
10
+ control_codes = control_codes.to_ber_sequence
11
+ res = [['1.2.3', true],['1.7.9',false]].to_ber_control
12
+ res.should eq(control_codes)
13
+ end
14
+
15
+ it "should wrap the array in another array if a nested array is not passed" do
16
+ result1 = ['1.2.3', true].to_ber_control
17
+ result2 = [['1.2.3', true]].to_ber_control
18
+ result1.should eq(result2)
19
+ end
20
+
21
+ it "should return an empty string if an empty array is passed" do
22
+ [].to_ber_control.should be_empty
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Net::LDAP::Filter::FilterParser do
5
+
6
+ describe "#parse" do
7
+ context "Given ASCIIs as filter string" do
8
+ let(:filter_string) { "(cn=name)" }
9
+ specify "should generate filter object" do
10
+ expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter
11
+ end
12
+ end
13
+ context "Given string including multibyte chars as filter string" do
14
+ let(:filter_string) { "(cn=名前)" }
15
+ specify "should generate filter object" do
16
+ expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter
17
+ end
18
+ end
19
+ end
20
+ end
@@ -81,4 +81,35 @@ describe Net::LDAP::Filter do
81
81
  Net::LDAP::Filter.escape("\0*()\\").should == "\\00\\2A\\28\\29\\5C"
82
82
  end
83
83
  end
84
+
85
+ context 'with a well-known BER string' do
86
+ ber = "\xa4\x2d" \
87
+ "\x04\x0b" "objectclass" \
88
+ "\x30\x1e" \
89
+ "\x80\x08" "foo" "*\\" "bar" \
90
+ "\x81\x08" "foo" "*\\" "bar" \
91
+ "\x82\x08" "foo" "*\\" "bar"
92
+
93
+ describe "<- .to_ber" do
94
+ [
95
+ "foo" "\\2A\\5C" "bar",
96
+ "foo" "\\2a\\5c" "bar",
97
+ "foo" "\\2A\\5c" "bar",
98
+ "foo" "\\2a\\5C" "bar"
99
+ ].each do |escaped|
100
+ it 'unescapes escaped characters' do
101
+ filter = Net::LDAP::Filter.eq("objectclass", "#{escaped}*#{escaped}*#{escaped}")
102
+ filter.to_ber.should == ber
103
+ end
104
+ end
105
+ end
106
+
107
+ describe '<- .parse_ber' do
108
+ it 'escapes characters' do
109
+ escaped = Net::LDAP::Filter.escape("foo" "*\\" "bar")
110
+ filter = Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax))
111
+ filter.to_s.should == "(objectclass=#{escaped}*#{escaped}*#{escaped})"
112
+ end
113
+ end
114
+ end
84
115
  end
@@ -0,0 +1,35 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ describe Net::LDAP, "search method" do
4
+ class FakeConnection
5
+ def search(args)
6
+ OpenStruct.new(:result_code => 1, :message => "error", :success? => false)
7
+ end
8
+ end
9
+
10
+ before(:each) do
11
+ @connection = Net::LDAP.new
12
+ @connection.instance_variable_set(:@open_connection, FakeConnection.new)
13
+ end
14
+
15
+ context "when :return_result => true" do
16
+ it "should return nil upon error" do
17
+ result_set = @connection.search(:return_result => true)
18
+ result_set.should be_nil
19
+ end
20
+ end
21
+
22
+ context "when :return_result => false" do
23
+ it "should return false upon error" do
24
+ result = @connection.search(:return_result => false)
25
+ result.should be_false
26
+ end
27
+ end
28
+
29
+ context "When :return_result is not given" do
30
+ it "should return nil upon error" do
31
+ result_set = @connection.search
32
+ result_set.should be_nil
33
+ end
34
+ end
35
+ end
@@ -7,11 +7,11 @@ describe Net::LDAP::Connection do
7
7
  flexmock(TCPSocket).
8
8
  should_receive(:new).and_raise(Errno::ECONNREFUSED)
9
9
  end
10
-
10
+
11
11
  it "should raise LdapError" do
12
12
  lambda {
13
13
  Net::LDAP::Connection.new(
14
- :server => 'test.mocked.com',
14
+ :server => 'test.mocked.com',
15
15
  :port => 636)
16
16
  }.should raise_error(Net::LDAP::LdapError)
17
17
  end
@@ -21,11 +21,11 @@ describe Net::LDAP::Connection do
21
21
  flexmock(TCPSocket).
22
22
  should_receive(:new).and_raise(SocketError)
23
23
  end
24
-
24
+
25
25
  it "should raise LdapError" do
26
26
  lambda {
27
27
  Net::LDAP::Connection.new(
28
- :server => 'test.mocked.com',
28
+ :server => 'test.mocked.com',
29
29
  :port => 636)
30
30
  }.should raise_error(Net::LDAP::LdapError)
31
31
  end
@@ -35,14 +35,44 @@ describe Net::LDAP::Connection do
35
35
  flexmock(TCPSocket).
36
36
  should_receive(:new).and_raise(NameError)
37
37
  end
38
-
38
+
39
39
  it "should rethrow the exception" do
40
40
  lambda {
41
41
  Net::LDAP::Connection.new(
42
- :server => 'test.mocked.com',
42
+ :server => 'test.mocked.com',
43
43
  :port => 636)
44
44
  }.should raise_error(NameError)
45
45
  end
46
46
  end
47
47
  end
48
- end
48
+
49
+ context "populate error messages" do
50
+ before do
51
+ @tcp_socket = flexmock(:connection)
52
+ @tcp_socket.should_receive(:write)
53
+ flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket)
54
+ end
55
+
56
+ subject { Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636) }
57
+
58
+ it "should get back error messages if operation fails" do
59
+ ber = Net::BER::BerIdentifiedArray.new([53, "", "The provided password value was rejected by a password validator: The provided password did not contain enough characters from the character set 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. The minimum number of characters from that set that must be present in user passwords is 1"])
60
+ ber.ber_identifier = 7
61
+ @tcp_socket.should_receive(:read_ber).and_return([2, ber])
62
+
63
+ result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]])
64
+ result.should be_failure
65
+ result.error_message.should == "The provided password value was rejected by a password validator: The provided password did not contain enough characters from the character set 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. The minimum number of characters from that set that must be present in user passwords is 1"
66
+ end
67
+
68
+ it "shouldn't get back error messages if operation succeeds" do
69
+ ber = Net::BER::BerIdentifiedArray.new([0, "", ""])
70
+ ber.ber_identifier = 7
71
+ @tcp_socket.should_receive(:read_ber).and_return([2, ber])
72
+
73
+ result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]])
74
+ result.should be_success
75
+ result.error_message.should == ""
76
+ end
77
+ end
78
+ end