From 38ee83e45b4de7edf89bf9f0ef629eb4c6ad0fa8 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Thu, 12 May 2016 23:56:07 -0400 Subject: Moving to glide --- vendor/github.com/go-ldap/ldap/conn_test.go | 53 +++++ vendor/github.com/go-ldap/ldap/dn_test.go | 70 ++++++ vendor/github.com/go-ldap/ldap/error_test.go | 29 +++ vendor/github.com/go-ldap/ldap/example_test.go | 305 +++++++++++++++++++++++++ vendor/github.com/go-ldap/ldap/filter_test.go | 248 ++++++++++++++++++++ vendor/github.com/go-ldap/ldap/ldap_test.go | 275 ++++++++++++++++++++++ vendor/github.com/go-ldap/ldap/search_test.go | 31 +++ 7 files changed, 1011 insertions(+) create mode 100644 vendor/github.com/go-ldap/ldap/conn_test.go create mode 100644 vendor/github.com/go-ldap/ldap/dn_test.go create mode 100644 vendor/github.com/go-ldap/ldap/error_test.go create mode 100644 vendor/github.com/go-ldap/ldap/example_test.go create mode 100644 vendor/github.com/go-ldap/ldap/filter_test.go create mode 100644 vendor/github.com/go-ldap/ldap/ldap_test.go create mode 100644 vendor/github.com/go-ldap/ldap/search_test.go (limited to 'vendor/github.com/go-ldap') diff --git a/vendor/github.com/go-ldap/ldap/conn_test.go b/vendor/github.com/go-ldap/ldap/conn_test.go new file mode 100644 index 000000000..8394e5339 --- /dev/null +++ b/vendor/github.com/go-ldap/ldap/conn_test.go @@ -0,0 +1,53 @@ +package ldap + +import ( + "net" + "net/http" + "net/http/httptest" + "testing" + "time" + + "gopkg.in/asn1-ber.v1" +) + +func TestUnresponsiveConnection(t *testing.T) { + // The do-nothing server that accepts requests and does nothing + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + })) + defer ts.Close() + c, err := net.Dial(ts.Listener.Addr().Network(), ts.Listener.Addr().String()) + if err != nil { + t.Fatalf("error connecting to localhost tcp: %v", err) + } + + // Create an Ldap connection + conn := NewConn(c, false) + conn.SetTimeout(time.Millisecond) + conn.Start() + defer conn.Close() + + // Mock a packet + messageID := conn.nextMessageID() + packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request") + packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID")) + bindRequest := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request") + bindRequest.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version")) + packet.AppendChild(bindRequest) + + // Send packet and test response + channel, err := conn.sendMessage(packet) + if err != nil { + t.Fatalf("error sending message: %v", err) + } + packetResponse, ok := <-channel + if !ok { + t.Fatalf("no PacketResponse in response channel") + } + packet, err = packetResponse.ReadPacket() + if err == nil { + t.Fatalf("expected timeout error") + } + if err.Error() != "ldap: connection timed out" { + t.Fatalf("unexpected error: %v", err) + } +} diff --git a/vendor/github.com/go-ldap/ldap/dn_test.go b/vendor/github.com/go-ldap/ldap/dn_test.go new file mode 100644 index 000000000..39817c427 --- /dev/null +++ b/vendor/github.com/go-ldap/ldap/dn_test.go @@ -0,0 +1,70 @@ +package ldap_test + +import ( + "reflect" + "testing" + + "gopkg.in/ldap.v2" +) + +func TestSuccessfulDNParsing(t *testing.T) { + testcases := map[string]ldap.DN{ + "": ldap.DN{[]*ldap.RelativeDN{}}, + "cn=Jim\\2C \\22Hasse Hö\\22 Hansson!,dc=dummy,dc=com": ldap.DN{[]*ldap.RelativeDN{ + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"cn", "Jim, \"Hasse Hö\" Hansson!"}}}, + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"dc", "dummy"}}}, + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"dc", "com"}}}}}, + "UID=jsmith,DC=example,DC=net": ldap.DN{[]*ldap.RelativeDN{ + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"UID", "jsmith"}}}, + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "example"}}}, + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "net"}}}}}, + "OU=Sales+CN=J. Smith,DC=example,DC=net": ldap.DN{[]*ldap.RelativeDN{ + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{ + &ldap.AttributeTypeAndValue{"OU", "Sales"}, + &ldap.AttributeTypeAndValue{"CN", "J. Smith"}}}, + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "example"}}}, + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "net"}}}}}, + "1.3.6.1.4.1.1466.0=#04024869": ldap.DN{[]*ldap.RelativeDN{ + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"1.3.6.1.4.1.1466.0", "Hi"}}}}}, + "1.3.6.1.4.1.1466.0=#04024869,DC=net": ldap.DN{[]*ldap.RelativeDN{ + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"1.3.6.1.4.1.1466.0", "Hi"}}}, + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "net"}}}}}, + "CN=Lu\\C4\\8Di\\C4\\87": ldap.DN{[]*ldap.RelativeDN{ + &ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"CN", "Lučić"}}}}}, + } + + for test, answer := range testcases { + dn, err := ldap.ParseDN(test) + if err != nil { + t.Errorf(err.Error()) + continue + } + if !reflect.DeepEqual(dn, &answer) { + t.Errorf("Parsed DN %s is not equal to the expected structure", test) + for _, rdn := range dn.RDNs { + for _, attribs := range rdn.Attributes { + t.Logf("#%v\n", attribs) + } + } + } + } +} + +func TestErrorDNParsing(t *testing.T) { + testcases := map[string]string{ + "*": "DN ended with incomplete type, value pair", + "cn=Jim\\0Test": "Failed to decode escaped character: encoding/hex: invalid byte: U+0054 'T'", + "cn=Jim\\0": "Got corrupted escaped character", + "DC=example,=net": "DN ended with incomplete type, value pair", + "1=#0402486": "Failed to decode BER encoding: encoding/hex: odd length hex string", + } + + for test, answer := range testcases { + _, err := ldap.ParseDN(test) + if err == nil { + t.Errorf("Expected %s to fail parsing but succeeded\n", test) + } else if err.Error() != answer { + t.Errorf("Unexpected error on %s:\n%s\nvs.\n%s\n", test, answer, err.Error()) + } + } +} diff --git a/vendor/github.com/go-ldap/ldap/error_test.go b/vendor/github.com/go-ldap/ldap/error_test.go new file mode 100644 index 000000000..4ec720d9f --- /dev/null +++ b/vendor/github.com/go-ldap/ldap/error_test.go @@ -0,0 +1,29 @@ +package ldap + +import ( + "testing" + + "gopkg.in/asn1-ber.v1" +) + +// TestNilPacket tests that nil packets don't cause a panic. +func TestNilPacket(t *testing.T) { + // Test for nil packet + code, _ := getLDAPResultCode(nil) + if code != ErrorUnexpectedResponse { + t.Errorf("Should have an 'ErrorUnexpectedResponse' error in nil packets, got: %v", code) + } + + // Test for nil result + kids := []*ber.Packet{ + &ber.Packet{}, // Unused + nil, // Can't be nil + } + pack := &ber.Packet{Children: kids} + code, _ = getLDAPResultCode(pack) + + if code != ErrorUnexpectedResponse { + t.Errorf("Should have an 'ErrorUnexpectedResponse' error in nil packets, got: %v", code) + } + +} diff --git a/vendor/github.com/go-ldap/ldap/example_test.go b/vendor/github.com/go-ldap/ldap/example_test.go new file mode 100644 index 000000000..b018a9664 --- /dev/null +++ b/vendor/github.com/go-ldap/ldap/example_test.go @@ -0,0 +1,305 @@ +package ldap_test + +import ( + "crypto/tls" + "fmt" + "log" + + "gopkg.in/ldap.v2" +) + +// ExampleConn_Bind demonstrates how to bind a connection to an ldap user +// allowing access to restricted attrabutes that user has access to +func ExampleConn_Bind() { + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389)) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + err = l.Bind("cn=read-only-admin,dc=example,dc=com", "password") + if err != nil { + log.Fatal(err) + } +} + +// ExampleConn_Search demonstrates how to use the search interface +func ExampleConn_Search() { + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389)) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + searchRequest := ldap.NewSearchRequest( + "dc=example,dc=com", // The base dn to search + ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, + "(&(objectClass=organizationalPerson))", // The filter to apply + []string{"dn", "cn"}, // A list attributes to retrieve + nil, + ) + + sr, err := l.Search(searchRequest) + if err != nil { + log.Fatal(err) + } + + for _, entry := range sr.Entries { + fmt.Printf("%s: %v\n", entry.DN, entry.GetAttributeValue("cn")) + } +} + +// ExampleStartTLS demonstrates how to start a TLS connection +func ExampleConn_StartTLS() { + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389)) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + // Reconnect with TLS + err = l.StartTLS(&tls.Config{InsecureSkipVerify: true}) + if err != nil { + log.Fatal(err) + } + + // Opertations via l are now encrypted +} + +// ExampleConn_Compare demonstrates how to comapre an attribute with a value +func ExampleConn_Compare() { + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389)) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + matched, err := l.Compare("cn=user,dc=example,dc=com", "uid", "someuserid") + if err != nil { + log.Fatal(err) + } + + fmt.Println(matched) +} + +func ExampleConn_PasswordModify_admin() { + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389)) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + err = l.Bind("cn=admin,dc=example,dc=com", "password") + if err != nil { + log.Fatal(err) + } + + passwordModifyRequest := ldap.NewPasswordModifyRequest("cn=user,dc=example,dc=com", "", "NewPassword") + _, err = l.PasswordModify(passwordModifyRequest) + + if err != nil { + log.Fatalf("Password could not be changed: %s", err.Error()) + } +} + +func ExampleConn_PasswordModify_generatedPassword() { + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389)) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + err = l.Bind("cn=user,dc=example,dc=com", "password") + if err != nil { + log.Fatal(err) + } + + passwordModifyRequest := ldap.NewPasswordModifyRequest("", "OldPassword", "") + passwordModifyResponse, err := l.PasswordModify(passwordModifyRequest) + if err != nil { + log.Fatalf("Password could not be changed: %s", err.Error()) + } + + generatedPassword := passwordModifyResponse.GeneratedPassword + log.Printf("Generated password: %s\n", generatedPassword) +} + +func ExampleConn_PasswordModify_setNewPassword() { + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389)) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + err = l.Bind("cn=user,dc=example,dc=com", "password") + if err != nil { + log.Fatal(err) + } + + passwordModifyRequest := ldap.NewPasswordModifyRequest("", "OldPassword", "NewPassword") + _, err = l.PasswordModify(passwordModifyRequest) + + if err != nil { + log.Fatalf("Password could not be changed: %s", err.Error()) + } +} + +func ExampleConn_Modify() { + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389)) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + // Add a description, and replace the mail attributes + modify := ldap.NewModifyRequest("cn=user,dc=example,dc=com") + modify.Add("description", []string{"An example user"}) + modify.Replace("mail", []string{"user@example.org"}) + + err = l.Modify(modify) + if err != nil { + log.Fatal(err) + } +} + +// Example User Authentication shows how a typical application can verify a login attempt +func Example_userAuthentication() { + // The username and password we want to check + username := "someuser" + password := "userpassword" + + bindusername := "readonly" + bindpassword := "password" + + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389)) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + // Reconnect with TLS + err = l.StartTLS(&tls.Config{InsecureSkipVerify: true}) + if err != nil { + log.Fatal(err) + } + + // First bind with a read only user + err = l.Bind(bindusername, bindpassword) + if err != nil { + log.Fatal(err) + } + + // Search for the given username + searchRequest := ldap.NewSearchRequest( + "dc=example,dc=com", + ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, + fmt.Sprintf("(&(objectClass=organizationalPerson)&(uid=%s))", username), + []string{"dn"}, + nil, + ) + + sr, err := l.Search(searchRequest) + if err != nil { + log.Fatal(err) + } + + if len(sr.Entries) != 1 { + log.Fatal("User does not exist or too many entries returned") + } + + userdn := sr.Entries[0].DN + + // Bind as the user to verify their password + err = l.Bind(userdn, password) + if err != nil { + log.Fatal(err) + } + + // Rebind as the read only user for any futher queries + err = l.Bind(bindusername, bindpassword) + if err != nil { + log.Fatal(err) + } +} + +func Example_beherappolicy() { + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389)) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + controls := []ldap.Control{} + controls = append(controls, ldap.NewControlBeheraPasswordPolicy()) + bindRequest := ldap.NewSimpleBindRequest("cn=admin,dc=example,dc=com", "password", controls) + + r, err := l.SimpleBind(bindRequest) + ppolicyControl := ldap.FindControl(r.Controls, ldap.ControlTypeBeheraPasswordPolicy) + + var ppolicy *ldap.ControlBeheraPasswordPolicy + if ppolicyControl != nil { + ppolicy = ppolicyControl.(*ldap.ControlBeheraPasswordPolicy) + } else { + log.Printf("ppolicyControl response not avaliable.\n") + } + if err != nil { + errStr := "ERROR: Cannot bind: " + err.Error() + if ppolicy != nil && ppolicy.Error >= 0 { + errStr += ":" + ppolicy.ErrorString + } + log.Print(errStr) + } else { + logStr := "Login Ok" + if ppolicy != nil { + if ppolicy.Expire >= 0 { + logStr += fmt.Sprintf(". Password expires in %d seconds\n", ppolicy.Expire) + } else if ppolicy.Grace >= 0 { + logStr += fmt.Sprintf(". Password expired, %d grace logins remain\n", ppolicy.Grace) + } + } + log.Print(logStr) + } +} + +func Example_vchuppolicy() { + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389)) + if err != nil { + log.Fatal(err) + } + defer l.Close() + l.Debug = true + + bindRequest := ldap.NewSimpleBindRequest("cn=admin,dc=example,dc=com", "password", nil) + + r, err := l.SimpleBind(bindRequest) + + passwordMustChangeControl := ldap.FindControl(r.Controls, ldap.ControlTypeVChuPasswordMustChange) + var passwordMustChange *ldap.ControlVChuPasswordMustChange + if passwordMustChangeControl != nil { + passwordMustChange = passwordMustChangeControl.(*ldap.ControlVChuPasswordMustChange) + } + + if passwordMustChange != nil && passwordMustChange.MustChange { + log.Printf("Password Must be changed.\n") + } + + passwordWarningControl := ldap.FindControl(r.Controls, ldap.ControlTypeVChuPasswordWarning) + + var passwordWarning *ldap.ControlVChuPasswordWarning + if passwordWarningControl != nil { + passwordWarning = passwordWarningControl.(*ldap.ControlVChuPasswordWarning) + } else { + log.Printf("ppolicyControl response not available.\n") + } + if err != nil { + log.Print("ERROR: Cannot bind: " + err.Error()) + } else { + logStr := "Login Ok" + if passwordWarning != nil { + if passwordWarning.Expire >= 0 { + logStr += fmt.Sprintf(". Password expires in %d seconds\n", passwordWarning.Expire) + } + } + log.Print(logStr) + } +} diff --git a/vendor/github.com/go-ldap/ldap/filter_test.go b/vendor/github.com/go-ldap/ldap/filter_test.go new file mode 100644 index 000000000..ae1b79b0c --- /dev/null +++ b/vendor/github.com/go-ldap/ldap/filter_test.go @@ -0,0 +1,248 @@ +package ldap_test + +import ( + "strings" + "testing" + + "gopkg.in/asn1-ber.v1" + "gopkg.in/ldap.v2" +) + +type compileTest struct { + filterStr string + + expectedFilter string + expectedType int + expectedErr string +} + +var testFilters = []compileTest{ + compileTest{ + filterStr: "(&(sn=Miller)(givenName=Bob))", + expectedFilter: "(&(sn=Miller)(givenName=Bob))", + expectedType: ldap.FilterAnd, + }, + compileTest{ + filterStr: "(|(sn=Miller)(givenName=Bob))", + expectedFilter: "(|(sn=Miller)(givenName=Bob))", + expectedType: ldap.FilterOr, + }, + compileTest{ + filterStr: "(!(sn=Miller))", + expectedFilter: "(!(sn=Miller))", + expectedType: ldap.FilterNot, + }, + compileTest{ + filterStr: "(sn=Miller)", + expectedFilter: "(sn=Miller)", + expectedType: ldap.FilterEqualityMatch, + }, + compileTest{ + filterStr: "(sn=Mill*)", + expectedFilter: "(sn=Mill*)", + expectedType: ldap.FilterSubstrings, + }, + compileTest{ + filterStr: "(sn=*Mill)", + expectedFilter: "(sn=*Mill)", + expectedType: ldap.FilterSubstrings, + }, + compileTest{ + filterStr: "(sn=*Mill*)", + expectedFilter: "(sn=*Mill*)", + expectedType: ldap.FilterSubstrings, + }, + compileTest{ + filterStr: "(sn=*i*le*)", + expectedFilter: "(sn=*i*le*)", + expectedType: ldap.FilterSubstrings, + }, + compileTest{ + filterStr: "(sn=Mi*l*r)", + expectedFilter: "(sn=Mi*l*r)", + expectedType: ldap.FilterSubstrings, + }, + // substring filters escape properly + compileTest{ + filterStr: `(sn=Mi*함*r)`, + expectedFilter: `(sn=Mi*\ed\95\a8*r)`, + expectedType: ldap.FilterSubstrings, + }, + // already escaped substring filters don't get double-escaped + compileTest{ + filterStr: `(sn=Mi*\ed\95\a8*r)`, + expectedFilter: `(sn=Mi*\ed\95\a8*r)`, + expectedType: ldap.FilterSubstrings, + }, + compileTest{ + filterStr: "(sn=Mi*le*)", + expectedFilter: "(sn=Mi*le*)", + expectedType: ldap.FilterSubstrings, + }, + compileTest{ + filterStr: "(sn=*i*ler)", + expectedFilter: "(sn=*i*ler)", + expectedType: ldap.FilterSubstrings, + }, + compileTest{ + filterStr: "(sn>=Miller)", + expectedFilter: "(sn>=Miller)", + expectedType: ldap.FilterGreaterOrEqual, + }, + compileTest{ + filterStr: "(sn<=Miller)", + expectedFilter: "(sn<=Miller)", + expectedType: ldap.FilterLessOrEqual, + }, + compileTest{ + filterStr: "(sn=*)", + expectedFilter: "(sn=*)", + expectedType: ldap.FilterPresent, + }, + compileTest{ + filterStr: "(sn~=Miller)", + expectedFilter: "(sn~=Miller)", + expectedType: ldap.FilterApproxMatch, + }, + compileTest{ + filterStr: `(objectGUID='\fc\fe\a3\ab\f9\90N\aaGm\d5I~\d12)`, + expectedFilter: `(objectGUID='\fc\fe\a3\ab\f9\90N\aaGm\d5I~\d12)`, + expectedType: ldap.FilterEqualityMatch, + }, + compileTest{ + filterStr: `(objectGUID=абвгдеёжзийклмнопрстуфхцчшщъыьэюя)`, + expectedFilter: `(objectGUID=\d0\b0\d0\b1\d0\b2\d0\b3\d0\b4\d0\b5\d1\91\d0\b6\d0\b7\d0\b8\d0\b9\d0\ba\d0\bb\d0\bc\d0\bd\d0\be\d0\bf\d1\80\d1\81\d1\82\d1\83\d1\84\d1\85\d1\86\d1\87\d1\88\d1\89\d1\8a\d1\8b\d1\8c\d1\8d\d1\8e\d1\8f)`, + expectedType: ldap.FilterEqualityMatch, + }, + compileTest{ + filterStr: `(objectGUID=함수목록)`, + expectedFilter: `(objectGUID=\ed\95\a8\ec\88\98\eb\aa\a9\eb\a1\9d)`, + expectedType: ldap.FilterEqualityMatch, + }, + compileTest{ + filterStr: `(objectGUID=`, + expectedFilter: ``, + expectedType: 0, + expectedErr: "unexpected end of filter", + }, + compileTest{ + filterStr: `(objectGUID=함수목록`, + expectedFilter: ``, + expectedType: 0, + expectedErr: "unexpected end of filter", + }, + compileTest{ + filterStr: `(&(objectclass=inetorgperson)(cn=中文))`, + expectedFilter: `(&(objectclass=inetorgperson)(cn=\e4\b8\ad\e6\96\87))`, + expectedType: 0, + }, + // attr extension + compileTest{ + filterStr: `(memberOf:=foo)`, + expectedFilter: `(memberOf:=foo)`, + expectedType: ldap.FilterExtensibleMatch, + }, + // attr+named matching rule extension + compileTest{ + filterStr: `(memberOf:test:=foo)`, + expectedFilter: `(memberOf:test:=foo)`, + expectedType: ldap.FilterExtensibleMatch, + }, + // attr+oid matching rule extension + compileTest{ + filterStr: `(cn:1.2.3.4.5:=Fred Flintstone)`, + expectedFilter: `(cn:1.2.3.4.5:=Fred Flintstone)`, + expectedType: ldap.FilterExtensibleMatch, + }, + // attr+dn+oid matching rule extension + compileTest{ + filterStr: `(sn:dn:2.4.6.8.10:=Barney Rubble)`, + expectedFilter: `(sn:dn:2.4.6.8.10:=Barney Rubble)`, + expectedType: ldap.FilterExtensibleMatch, + }, + // attr+dn extension + compileTest{ + filterStr: `(o:dn:=Ace Industry)`, + expectedFilter: `(o:dn:=Ace Industry)`, + expectedType: ldap.FilterExtensibleMatch, + }, + // dn extension + compileTest{ + filterStr: `(:dn:2.4.6.8.10:=Dino)`, + expectedFilter: `(:dn:2.4.6.8.10:=Dino)`, + expectedType: ldap.FilterExtensibleMatch, + }, + compileTest{ + filterStr: `(memberOf:1.2.840.113556.1.4.1941:=CN=User1,OU=blah,DC=mydomain,DC=net)`, + expectedFilter: `(memberOf:1.2.840.113556.1.4.1941:=CN=User1,OU=blah,DC=mydomain,DC=net)`, + expectedType: ldap.FilterExtensibleMatch, + }, + + // compileTest{ filterStr: "()", filterType: FilterExtensibleMatch }, +} + +var testInvalidFilters = []string{ + `(objectGUID=\zz)`, + `(objectGUID=\a)`, +} + +func TestFilter(t *testing.T) { + // Test Compiler and Decompiler + for _, i := range testFilters { + filter, err := ldap.CompileFilter(i.filterStr) + if err != nil { + if i.expectedErr == "" || !strings.Contains(err.Error(), i.expectedErr) { + t.Errorf("Problem compiling '%s' - '%v' (expected error to contain '%v')", i.filterStr, err, i.expectedErr) + } + } else if filter.Tag != ber.Tag(i.expectedType) { + t.Errorf("%q Expected %q got %q", i.filterStr, ldap.FilterMap[uint64(i.expectedType)], ldap.FilterMap[uint64(filter.Tag)]) + } else { + o, err := ldap.DecompileFilter(filter) + if err != nil { + t.Errorf("Problem compiling %s - %s", i.filterStr, err.Error()) + } else if i.expectedFilter != o { + t.Errorf("%q expected, got %q", i.expectedFilter, o) + } + } + } +} + +func TestInvalidFilter(t *testing.T) { + for _, filterStr := range testInvalidFilters { + if _, err := ldap.CompileFilter(filterStr); err == nil { + t.Errorf("Problem compiling %s - expected err", filterStr) + } + } +} + +func BenchmarkFilterCompile(b *testing.B) { + b.StopTimer() + filters := make([]string, len(testFilters)) + + // Test Compiler and Decompiler + for idx, i := range testFilters { + filters[idx] = i.filterStr + } + + maxIdx := len(filters) + b.StartTimer() + for i := 0; i < b.N; i++ { + ldap.CompileFilter(filters[i%maxIdx]) + } +} + +func BenchmarkFilterDecompile(b *testing.B) { + b.StopTimer() + filters := make([]*ber.Packet, len(testFilters)) + + // Test Compiler and Decompiler + for idx, i := range testFilters { + filters[idx], _ = ldap.CompileFilter(i.filterStr) + } + + maxIdx := len(filters) + b.StartTimer() + for i := 0; i < b.N; i++ { + ldap.DecompileFilter(filters[i%maxIdx]) + } +} diff --git a/vendor/github.com/go-ldap/ldap/ldap_test.go b/vendor/github.com/go-ldap/ldap/ldap_test.go new file mode 100644 index 000000000..9f4305180 --- /dev/null +++ b/vendor/github.com/go-ldap/ldap/ldap_test.go @@ -0,0 +1,275 @@ +package ldap_test + +import ( + "crypto/tls" + "fmt" + "testing" + + "gopkg.in/ldap.v2" +) + +var ldapServer = "ldap.itd.umich.edu" +var ldapPort = uint16(389) +var ldapTLSPort = uint16(636) +var baseDN = "dc=umich,dc=edu" +var filter = []string{ + "(cn=cis-fac)", + "(&(owner=*)(cn=cis-fac))", + "(&(objectclass=rfc822mailgroup)(cn=*Computer*))", + "(&(objectclass=rfc822mailgroup)(cn=*Mathematics*))"} +var attributes = []string{ + "cn", + "description"} + +func TestDial(t *testing.T) { + fmt.Printf("TestDial: starting...\n") + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) + if err != nil { + t.Errorf(err.Error()) + return + } + defer l.Close() + fmt.Printf("TestDial: finished...\n") +} + +func TestDialTLS(t *testing.T) { + fmt.Printf("TestDialTLS: starting...\n") + l, err := ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapTLSPort), &tls.Config{InsecureSkipVerify: true}) + if err != nil { + t.Errorf(err.Error()) + return + } + defer l.Close() + fmt.Printf("TestDialTLS: finished...\n") +} + +func TestStartTLS(t *testing.T) { + fmt.Printf("TestStartTLS: starting...\n") + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) + if err != nil { + t.Errorf(err.Error()) + return + } + err = l.StartTLS(&tls.Config{InsecureSkipVerify: true}) + if err != nil { + t.Errorf(err.Error()) + return + } + fmt.Printf("TestStartTLS: finished...\n") +} + +func TestSearch(t *testing.T) { + fmt.Printf("TestSearch: starting...\n") + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) + if err != nil { + t.Errorf(err.Error()) + return + } + defer l.Close() + + searchRequest := ldap.NewSearchRequest( + baseDN, + ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false, + filter[0], + attributes, + nil) + + sr, err := l.Search(searchRequest) + if err != nil { + t.Errorf(err.Error()) + return + } + + fmt.Printf("TestSearch: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries)) +} + +func TestSearchStartTLS(t *testing.T) { + fmt.Printf("TestSearchStartTLS: starting...\n") + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) + if err != nil { + t.Errorf(err.Error()) + return + } + defer l.Close() + + searchRequest := ldap.NewSearchRequest( + baseDN, + ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false, + filter[0], + attributes, + nil) + + sr, err := l.Search(searchRequest) + if err != nil { + t.Errorf(err.Error()) + return + } + + fmt.Printf("TestSearchStartTLS: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries)) + + fmt.Printf("TestSearchStartTLS: upgrading with startTLS\n") + err = l.StartTLS(&tls.Config{InsecureSkipVerify: true}) + if err != nil { + t.Errorf(err.Error()) + return + } + + sr, err = l.Search(searchRequest) + if err != nil { + t.Errorf(err.Error()) + return + } + + fmt.Printf("TestSearchStartTLS: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries)) +} + +func TestSearchWithPaging(t *testing.T) { + fmt.Printf("TestSearchWithPaging: starting...\n") + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) + if err != nil { + t.Errorf(err.Error()) + return + } + defer l.Close() + + err = l.Bind("", "") + if err != nil { + t.Errorf(err.Error()) + return + } + + searchRequest := ldap.NewSearchRequest( + baseDN, + ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false, + filter[2], + attributes, + nil) + sr, err := l.SearchWithPaging(searchRequest, 5) + if err != nil { + t.Errorf(err.Error()) + return + } + + fmt.Printf("TestSearchWithPaging: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries)) + + searchRequest = ldap.NewSearchRequest( + baseDN, + ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false, + filter[2], + attributes, + []ldap.Control{ldap.NewControlPaging(5)}) + sr, err = l.SearchWithPaging(searchRequest, 5) + if err != nil { + t.Errorf(err.Error()) + return + } + + fmt.Printf("TestSearchWithPaging: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries)) + + searchRequest = ldap.NewSearchRequest( + baseDN, + ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false, + filter[2], + attributes, + []ldap.Control{ldap.NewControlPaging(500)}) + sr, err = l.SearchWithPaging(searchRequest, 5) + if err == nil { + t.Errorf("expected an error when paging size in control in search request doesn't match size given in call, got none") + return + } +} + +func searchGoroutine(t *testing.T, l *ldap.Conn, results chan *ldap.SearchResult, i int) { + searchRequest := ldap.NewSearchRequest( + baseDN, + ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false, + filter[i], + attributes, + nil) + sr, err := l.Search(searchRequest) + if err != nil { + t.Errorf(err.Error()) + results <- nil + return + } + results <- sr +} + +func testMultiGoroutineSearch(t *testing.T, TLS bool, startTLS bool) { + fmt.Printf("TestMultiGoroutineSearch: starting...\n") + var l *ldap.Conn + var err error + if TLS { + l, err = ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapTLSPort), &tls.Config{InsecureSkipVerify: true}) + if err != nil { + t.Errorf(err.Error()) + return + } + defer l.Close() + } else { + l, err = ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) + if err != nil { + t.Errorf(err.Error()) + return + } + if startTLS { + fmt.Printf("TestMultiGoroutineSearch: using StartTLS...\n") + err := l.StartTLS(&tls.Config{InsecureSkipVerify: true}) + if err != nil { + t.Errorf(err.Error()) + return + } + + } + } + + results := make([]chan *ldap.SearchResult, len(filter)) + for i := range filter { + results[i] = make(chan *ldap.SearchResult) + go searchGoroutine(t, l, results[i], i) + } + for i := range filter { + sr := <-results[i] + if sr == nil { + t.Errorf("Did not receive results from goroutine for %q", filter[i]) + } else { + fmt.Printf("TestMultiGoroutineSearch(%d): %s -> num of entries = %d\n", i, filter[i], len(sr.Entries)) + } + } +} + +func TestMultiGoroutineSearch(t *testing.T) { + testMultiGoroutineSearch(t, false, false) + testMultiGoroutineSearch(t, true, true) + testMultiGoroutineSearch(t, false, true) +} + +func TestEscapeFilter(t *testing.T) { + if got, want := ldap.EscapeFilter("a\x00b(c)d*e\\f"), `a\00b\28c\29d\2ae\5cf`; got != want { + t.Errorf("Got %s, expected %s", want, got) + } + if got, want := ldap.EscapeFilter("Lučić"), `Lu\c4\8di\c4\87`; got != want { + t.Errorf("Got %s, expected %s", want, got) + } +} + +func TestCompare(t *testing.T) { + fmt.Printf("TestCompare: starting...\n") + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort)) + if err != nil { + t.Fatal(err.Error()) + } + defer l.Close() + + dn := "cn=math mich,ou=User Groups,ou=Groups,dc=umich,dc=edu" + attribute := "cn" + value := "math mich" + + sr, err := l.Compare(dn, attribute, value) + if err != nil { + t.Errorf(err.Error()) + return + } + + fmt.Printf("TestCompare: -> %v\n", sr) +} diff --git a/vendor/github.com/go-ldap/ldap/search_test.go b/vendor/github.com/go-ldap/ldap/search_test.go new file mode 100644 index 000000000..efb8147d1 --- /dev/null +++ b/vendor/github.com/go-ldap/ldap/search_test.go @@ -0,0 +1,31 @@ +package ldap + +import ( + "reflect" + "testing" +) + +// TestNewEntry tests that repeated calls to NewEntry return the same value with the same input +func TestNewEntry(t *testing.T) { + dn := "testDN" + attributes := map[string][]string{ + "alpha": {"value"}, + "beta": {"value"}, + "gamma": {"value"}, + "delta": {"value"}, + "epsilon": {"value"}, + } + exectedEntry := NewEntry(dn, attributes) + + iteration := 0 + for { + if iteration == 100 { + break + } + testEntry := NewEntry(dn, attributes) + if !reflect.DeepEqual(exectedEntry, testEntry) { + t.Fatalf("consequent calls to NewEntry did not yield the same result:\n\texpected:\n\t%s\n\tgot:\n\t%s\n", exectedEntry, testEntry) + } + iteration = iteration + 1 + } +} -- cgit v1.2.3-1-g7c22