11package ldap
22
33import (
4+ "bytes"
45 "errors"
56 "fmt"
67 "io"
@@ -90,27 +91,6 @@ func TestWrappedError(t *testing.T) {
9091 }
9192}
9293
93- // TestNilPacket tests that nil packets don't cause a panic.
94- func TestNilPacket (t * testing.T ) {
95- // Test for nil packet
96- err := GetLDAPError (nil )
97- if ! IsErrorWithCode (err , ErrorUnexpectedResponse ) {
98- t .Errorf ("Should have an 'ErrorUnexpectedResponse' error in nil packets, got: %v" , err )
99- }
100-
101- // Test for nil result
102- kids := []* ber.Packet {
103- {}, // Unused
104- nil , // Can't be nil
105- }
106- pack := & ber.Packet {Children : kids }
107- err = GetLDAPError (pack )
108-
109- if ! IsErrorWithCode (err , ErrorUnexpectedResponse ) {
110- t .Errorf ("Should have an 'ErrorUnexpectedResponse' error in nil packets, got: %v" , err )
111- }
112- }
113-
11494// TestConnReadErr tests that an unexpected error reading from underlying
11595// connection bubbles up to the goroutine which makes a request.
11696func TestConnReadErr (t * testing.T ) {
@@ -138,8 +118,16 @@ func TestConnReadErr(t *testing.T) {
138118 }
139119}
140120
141- // TestGetLDAPError tests parsing of result with a error response.
142- func TestGetLDAPError (t * testing.T ) {
121+ type testCorpusErrorEntry struct {
122+ packet * ber.Packet
123+ expectedResultCode uint16
124+ expectedMessage string
125+ shouldError bool
126+ }
127+
128+ func generateGetLDAPErrorCorpus () map [string ]testCorpusErrorEntry {
129+ corpus := make (map [string ]testCorpusErrorEntry )
130+
143131 diagnosticMessage := "Detailed error message"
144132 bindResponse := ber .Encode (ber .ClassApplication , ber .TypeConstructed , ApplicationBindResponse , nil , "Bind Response" )
145133 bindResponse .AppendChild (ber .Encode (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , int64 (LDAPResultInvalidCredentials ), "resultCode" ))
@@ -148,39 +136,144 @@ func TestGetLDAPError(t *testing.T) {
148136 packet := ber .NewSequence ("LDAPMessage" )
149137 packet .AppendChild (ber .Encode (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , int64 (0 ), "messageID" ))
150138 packet .AppendChild (bindResponse )
151- err := GetLDAPError (packet )
152- if err == nil {
153- t .Errorf ("Did not get error response" )
139+ corpus ["detailed errror message" ] = testCorpusErrorEntry {
140+ packet : packet ,
141+ expectedResultCode : LDAPResultInvalidCredentials ,
142+ expectedMessage : diagnosticMessage ,
143+ shouldError : true ,
154144 }
155145
156- ldapError := err .(* Error )
157- if ldapError .ResultCode != LDAPResultInvalidCredentials {
158- t .Errorf ("Got incorrect error code in LDAP error; got %v, expected %v" , ldapError .ResultCode , LDAPResultInvalidCredentials )
159- }
160- if ldapError .Err .Error () != diagnosticMessage {
161- t .Errorf ("Got incorrect error message in LDAP error; got %v, expected %v" , ldapError .Err .Error (), diagnosticMessage )
146+ bindResponse = ber .Encode (ber .ClassApplication , ber .TypeConstructed , ApplicationBindResponse , nil , "Bind Response" )
147+ bindResponse .AppendChild (ber .Encode (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , int64 (0 ), "resultCode" ))
148+ bindResponse .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , "" , "matchedDN" ))
149+ bindResponse .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , "" , "diagnosticMessage" ))
150+ packet = ber .NewSequence ("LDAPMessage" )
151+ packet .AppendChild (ber .Encode (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , int64 (0 ), "messageID" ))
152+ packet .AppendChild (bindResponse )
153+ corpus ["no error" ] = testCorpusErrorEntry {
154+ packet : packet ,
155+ expectedResultCode : ErrorNetwork ,
156+ expectedMessage : "" ,
162157 }
163- }
164158
165- // TestGetLDAPErrorInvalidResponse tests that responses with an unexpected ordering or combination of children
166- // don't cause a panic.
167- func TestGetLDAPErrorInvalidResponse (t * testing.T ) {
168- bindResponse := ber .Encode (ber .ClassApplication , ber .TypeConstructed , ApplicationBindResponse , nil , "Bind Response" )
159+ // Test that responses with an unexpected ordering or combination of children
160+ // don't cause a panic.
161+ bindResponse = ber .Encode (ber .ClassApplication , ber .TypeConstructed , ApplicationBindResponse , nil , "Bind Response" )
169162 bindResponse .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , "dc=example,dc=org" , "matchedDN" ))
170163 bindResponse .AppendChild (ber .Encode (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , int64 (LDAPResultInvalidCredentials ), "resultCode" ))
171164 bindResponse .AppendChild (ber .Encode (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , int64 (LDAPResultInvalidCredentials ), "resultCode" ))
172- packet := ber .NewSequence ("LDAPMessage" )
165+ packet = ber .NewSequence ("LDAPMessage" )
166+ packet .AppendChild (ber .Encode (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , int64 (0 ), "messageID" ))
167+ packet .AppendChild (bindResponse )
168+ corpus ["unexpected ordering" ] = testCorpusErrorEntry {
169+ packet : packet ,
170+ expectedResultCode : ErrorNetwork ,
171+ expectedMessage : "Invalid packet format" ,
172+ shouldError : true ,
173+ }
174+
175+ // Test that a nil ber Packet errors correctly and does not cause a panic.
176+ corpus ["nil packet" ] = testCorpusErrorEntry {
177+ packet : nil ,
178+ expectedResultCode : ErrorUnexpectedResponse ,
179+ expectedMessage : "Empty packet" ,
180+ shouldError : true ,
181+ }
182+
183+ // Test that a nil first child errors correctly and does not cause a panic.
184+ kids := []* ber.Packet {
185+ {}, // Unused
186+ nil , // Can't be nil
187+ }
188+ packet = & ber.Packet {Children : kids }
189+ corpus ["nil first child" ] = testCorpusErrorEntry {
190+ packet : packet ,
191+ expectedResultCode : ErrorUnexpectedResponse ,
192+ expectedMessage : "Empty response in packet" ,
193+ shouldError : true ,
194+ }
195+
196+ // Test that if the result code is nil, we get an appropriate error instead of a panic.
197+ // Panic message would be "interface conversion: interface {} is nil, not int64"
198+ diagnosticMessage = "Invalid result code in packet"
199+ bindResponse = ber .Encode (ber .ClassApplication , ber .TypeConstructed , ApplicationBindResponse , nil , "Bind Response" )
200+ bindResponse .AppendChild (ber .Encode (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , nil , "resultCode" ))
201+ bindResponse .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , "dc=example,dc=org" , "matchedDN" ))
202+ bindResponse .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , diagnosticMessage , "diagnosticMessage" ))
203+ packet = ber .NewSequence ("LDAPMessage" )
173204 packet .AppendChild (ber .Encode (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , int64 (0 ), "messageID" ))
174205 packet .AppendChild (bindResponse )
175- err := GetLDAPError (packet )
176- if err == nil {
177- t .Errorf ("Did not get error response" )
206+ corpus ["nil result code" ] = testCorpusErrorEntry {
207+ packet : packet ,
208+ expectedResultCode : ErrorNetwork ,
209+ expectedMessage : diagnosticMessage ,
210+ shouldError : true ,
178211 }
179212
180- ldapError := err .(* Error )
181- if ldapError .ResultCode != ErrorNetwork {
182- t .Errorf ("Got incorrect error code in LDAP error; got %v, expected %v" , ldapError .ResultCode , ErrorNetwork )
213+ // Test that if the matchedDN is nil, we get an appropriate error instead of a panic.
214+ // Panic message would be "interface conversion: interface {} is nil, not string"
215+ panic_data := []byte ("07A\x01 0\x7f \xff 00\x02 \x01 0D\" 0000000000000000000000000000000000D\x01 0A\x01 0A\x01 0" )
216+ packet , err := ber .ReadPacket (bytes .NewReader (panic_data ))
217+ if err != nil {
218+ panic (fmt .Sprintf ("failed to read packet for panic test: %s" , err ))
183219 }
220+ corpus ["panic data" ] = testCorpusErrorEntry {
221+ packet : packet ,
222+ expectedResultCode : ErrorNetwork ,
223+ expectedMessage : "Invalid matchedDN in packet" ,
224+ shouldError : true ,
225+ }
226+
227+ return corpus
228+ }
229+
230+ func TestGetLDAPError (t * testing.T ) {
231+ corpus := generateGetLDAPErrorCorpus ()
232+
233+ for name , entry := range corpus {
234+ t .Run (name , func (t * testing.T ) {
235+ err := GetLDAPError (entry .packet )
236+
237+ if ! entry .shouldError {
238+ if err != nil {
239+ t .Errorf ("Did not expect an error, but got: %v" , err )
240+ }
241+ return
242+ } else if err == nil {
243+ t .Errorf ("Expected an error response" )
244+ return
245+ }
246+
247+ ldapError , ok := err .(* Error )
248+ if ! ok {
249+ t .Fatalf ("Expected error of type *Error, got %T" , err )
250+ }
251+
252+ if ldapError .ResultCode != entry .expectedResultCode {
253+ t .Errorf ("Got incorrect error code in LDAP error; got '%v', expected '%v'" , ldapError .ResultCode , entry .expectedResultCode )
254+ }
255+ if ldapError .Err .Error () != entry .expectedMessage {
256+ t .Errorf ("Got incorrect error message in LDAP error; got '%v', expected '%v'" , ldapError .Err .Error (), entry .expectedMessage )
257+ }
258+ })
259+ }
260+ }
261+
262+ func FuzzGetLDAPError (f * testing.F ) {
263+ corpus := generateGetLDAPErrorCorpus ()
264+ for _ , entry := range corpus {
265+ if entry .packet != nil {
266+ f .Add (entry .packet .ByteValue )
267+ }
268+ }
269+
270+ f .Fuzz (func (t * testing.T , data []byte ) {
271+ packet , err := ber .ReadPacket (bytes .NewReader (data ))
272+ if err != nil {
273+ return
274+ }
275+ _ = GetLDAPError (packet )
276+ })
184277}
185278
186279func TestErrorIs (t * testing.T ) {
@@ -201,21 +294,6 @@ func TestErrorAs(t *testing.T) {
201294 }
202295}
203296
204- // TestGetLDAPErrorSuccess tests parsing of a result with no error (resultCode == 0).
205- func TestGetLDAPErrorSuccess (t * testing.T ) {
206- bindResponse := ber .Encode (ber .ClassApplication , ber .TypeConstructed , ApplicationBindResponse , nil , "Bind Response" )
207- bindResponse .AppendChild (ber .Encode (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , int64 (0 ), "resultCode" ))
208- bindResponse .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , "" , "matchedDN" ))
209- bindResponse .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , "" , "diagnosticMessage" ))
210- packet := ber .NewSequence ("LDAPMessage" )
211- packet .AppendChild (ber .Encode (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , int64 (0 ), "messageID" ))
212- packet .AppendChild (bindResponse )
213- err := GetLDAPError (packet )
214- if err != nil {
215- t .Errorf ("Successful responses should not produce an error, but got: %v" , err )
216- }
217- }
218-
219297// signalErrConn is a helpful type used with TestConnReadErr. It implements the
220298// net.Conn interface to be used as a connection for the test. Most methods are
221299// no-ops but the Read() method blocks until it receives a signal which it
0 commit comments