| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- package ldap
- import (
- "bytes"
- "log"
- "net"
- "os/exec"
- "strings"
- "testing"
- "time"
- )
- var listenString = "localhost:3389"
- var ldapURL = "ldap://" + listenString
- var timeout = 400 * time.Millisecond
- var serverBaseDN = "o=testers,c=test"
- /////////////////////////
- func TestBindAnonOK(t *testing.T) {
- quit := make(chan bool)
- done := make(chan bool)
- go func() {
- s := NewServer()
- s.QuitChannel(quit)
- s.BindFunc("", bindAnonOK{})
- if err := s.ListenAndServe(listenString); err != nil {
- t.Errorf("s.ListenAndServe failed: %s", err.Error())
- }
- }()
- go func() {
- cmd := exec.Command("ldapsearch", "-H", ldapURL, "-x", "-b", "o=testers,c=test")
- out, _ := cmd.CombinedOutput()
- if !strings.Contains(string(out), "result: 0 Success") {
- t.Errorf("ldapsearch failed: %v", string(out))
- }
- done <- true
- }()
- select {
- case <-done:
- case <-time.After(timeout):
- t.Errorf("ldapsearch command timed out")
- }
- quit <- true
- }
- /////////////////////////
- func TestBindAnonFail(t *testing.T) {
- quit := make(chan bool)
- done := make(chan bool)
- go func() {
- s := NewServer()
- s.QuitChannel(quit)
- if err := s.ListenAndServe(listenString); err != nil {
- t.Errorf("s.ListenAndServe failed: %s", err.Error())
- }
- }()
- time.Sleep(timeout)
- go func() {
- cmd := exec.Command("ldapsearch", "-H", ldapURL, "-x", "-b", "o=testers,c=test")
- out, _ := cmd.CombinedOutput()
- if !strings.Contains(string(out), "ldap_bind: Invalid credentials (49)") {
- t.Errorf("ldapsearch failed: %v", string(out))
- }
- done <- true
- }()
- select {
- case <-done:
- case <-time.After(timeout):
- t.Errorf("ldapsearch command timed out")
- }
- time.Sleep(timeout)
- quit <- true
- }
- /////////////////////////
- func TestBindSimpleOK(t *testing.T) {
- quit := make(chan bool)
- done := make(chan bool)
- go func() {
- s := NewServer()
- s.QuitChannel(quit)
- s.SearchFunc("", searchSimple{})
- s.BindFunc("", bindSimple{})
- if err := s.ListenAndServe(listenString); err != nil {
- t.Errorf("s.ListenAndServe failed: %s", err.Error())
- }
- }()
- serverBaseDN := "o=testers,c=test"
- go func() {
- cmd := exec.Command("ldapsearch", "-H", ldapURL, "-x",
- "-b", serverBaseDN, "-D", "cn=testy,"+serverBaseDN, "-w", "iLike2test")
- out, _ := cmd.CombinedOutput()
- if !strings.Contains(string(out), "result: 0 Success") {
- t.Errorf("ldapsearch failed: %v", string(out))
- }
- done <- true
- }()
- select {
- case <-done:
- case <-time.After(timeout):
- t.Errorf("ldapsearch command timed out")
- }
- quit <- true
- }
- /////////////////////////
- func TestBindSimpleFailBadPw(t *testing.T) {
- quit := make(chan bool)
- done := make(chan bool)
- go func() {
- s := NewServer()
- s.QuitChannel(quit)
- s.BindFunc("", bindSimple{})
- if err := s.ListenAndServe(listenString); err != nil {
- t.Errorf("s.ListenAndServe failed: %s", err.Error())
- }
- }()
- serverBaseDN := "o=testers,c=test"
- go func() {
- cmd := exec.Command("ldapsearch", "-H", ldapURL, "-x",
- "-b", serverBaseDN, "-D", "cn=testy,"+serverBaseDN, "-w", "BADPassword")
- out, _ := cmd.CombinedOutput()
- if !strings.Contains(string(out), "ldap_bind: Invalid credentials (49)") {
- t.Errorf("ldapsearch succeeded - should have failed: %v", string(out))
- }
- done <- true
- }()
- select {
- case <-done:
- case <-time.After(timeout):
- t.Errorf("ldapsearch command timed out")
- }
- quit <- true
- }
- /////////////////////////
- func TestBindSimpleFailBadDn(t *testing.T) {
- quit := make(chan bool)
- done := make(chan bool)
- go func() {
- s := NewServer()
- s.QuitChannel(quit)
- s.BindFunc("", bindSimple{})
- if err := s.ListenAndServe(listenString); err != nil {
- t.Errorf("s.ListenAndServe failed: %s", err.Error())
- }
- }()
- serverBaseDN := "o=testers,c=test"
- go func() {
- cmd := exec.Command("ldapsearch", "-H", ldapURL, "-x",
- "-b", serverBaseDN, "-D", "cn=testoy,"+serverBaseDN, "-w", "iLike2test")
- out, _ := cmd.CombinedOutput()
- if string(out) != "ldap_bind: Invalid credentials (49)\n" {
- t.Errorf("ldapsearch succeeded - should have failed: %v", string(out))
- }
- done <- true
- }()
- select {
- case <-done:
- case <-time.After(timeout):
- t.Errorf("ldapsearch command timed out")
- }
- quit <- true
- }
- /////////////////////////
- func TestBindSSL(t *testing.T) {
- ldapURLSSL := "ldaps://" + listenString
- longerTimeout := 300 * time.Millisecond
- quit := make(chan bool)
- done := make(chan bool)
- go func() {
- s := NewServer()
- s.QuitChannel(quit)
- s.BindFunc("", bindAnonOK{})
- if err := s.ListenAndServeTLS(listenString, "tests/cert_DONOTUSE.pem", "tests/key_DONOTUSE.pem"); err != nil {
- t.Errorf("s.ListenAndServeTLS failed: %s", err.Error())
- }
- }()
- go func() {
- time.Sleep(longerTimeout * 2)
- cmd := exec.Command("ldapsearch", "-H", ldapURLSSL, "-x", "-b", "o=testers,c=test")
- out, _ := cmd.CombinedOutput()
- if !strings.Contains(string(out), "result: 0 Success") {
- t.Errorf("ldapsearch failed: %v", string(out))
- }
- done <- true
- }()
- select {
- case <-done:
- case <-time.After(longerTimeout * 2):
- t.Errorf("ldapsearch command timed out")
- }
- quit <- true
- }
- /////////////////////////
- func TestBindPanic(t *testing.T) {
- quit := make(chan bool)
- done := make(chan bool)
- go func() {
- s := NewServer()
- s.QuitChannel(quit)
- s.BindFunc("", bindPanic{})
- if err := s.ListenAndServe(listenString); err != nil {
- t.Errorf("s.ListenAndServe failed: %s", err.Error())
- }
- }()
- go func() {
- cmd := exec.Command("ldapsearch", "-H", ldapURL, "-x", "-b", "o=testers,c=test")
- out, _ := cmd.CombinedOutput()
- if !strings.Contains(string(out), "ldap_bind: Operations error") {
- t.Errorf("ldapsearch should have returned operations error due to panic: %v", string(out))
- }
- done <- true
- }()
- select {
- case <-done:
- case <-time.After(timeout):
- t.Errorf("ldapsearch command timed out")
- }
- quit <- true
- }
- /////////////////////////
- type testStatsWriter struct {
- buffer *bytes.Buffer
- }
- func (tsw testStatsWriter) Write(buf []byte) (int, error) {
- tsw.buffer.Write(buf)
- return len(buf), nil
- }
- func TestSearchStats(t *testing.T) {
- w := testStatsWriter{&bytes.Buffer{}}
- log.SetOutput(w)
- quit := make(chan bool)
- done := make(chan bool)
- s := NewServer()
- go func() {
- s.QuitChannel(quit)
- s.SearchFunc("", searchSimple{})
- s.BindFunc("", bindAnonOK{})
- s.SetStats(true)
- if err := s.ListenAndServe(listenString); err != nil {
- t.Errorf("s.ListenAndServe failed: %s", err.Error())
- }
- }()
- go func() {
- cmd := exec.Command("ldapsearch", "-H", ldapURL, "-x", "-b", "o=testers,c=test")
- out, _ := cmd.CombinedOutput()
- if !strings.Contains(string(out), "result: 0 Success") {
- t.Errorf("ldapsearch failed: %v", string(out))
- }
- done <- true
- }()
- select {
- case <-done:
- case <-time.After(timeout):
- t.Errorf("ldapsearch command timed out")
- }
- stats := s.GetStats()
- log.Println(stats)
- if stats.Conns != 1 || stats.Binds != 1 {
- t.Errorf("Stats data missing or incorrect: %v", w.buffer.String())
- }
- quit <- true
- }
- /////////////////////////
- type bindAnonOK struct {
- }
- func (b bindAnonOK) Bind(bindDN, bindSimplePw string, conn net.Conn) (LDAPResultCode, error) {
- if bindDN == "" && bindSimplePw == "" {
- return LDAPResultSuccess, nil
- }
- return LDAPResultInvalidCredentials, nil
- }
- type bindSimple struct {
- }
- func (b bindSimple) Bind(bindDN, bindSimplePw string, conn net.Conn) (LDAPResultCode, error) {
- if bindDN == "cn=testy,o=testers,c=test" && bindSimplePw == "iLike2test" {
- return LDAPResultSuccess, nil
- }
- return LDAPResultInvalidCredentials, nil
- }
- type bindSimple2 struct {
- }
- func (b bindSimple2) Bind(bindDN, bindSimplePw string, conn net.Conn) (LDAPResultCode, error) {
- if bindDN == "cn=testy,o=testers,c=testz" && bindSimplePw == "ZLike2test" {
- return LDAPResultSuccess, nil
- }
- return LDAPResultInvalidCredentials, nil
- }
- type bindPanic struct {
- }
- func (b bindPanic) Bind(bindDN, bindSimplePw string, conn net.Conn) (LDAPResultCode, error) {
- panic("test panic at the disco")
- return LDAPResultInvalidCredentials, nil
- }
- type searchSimple struct {
- }
- func (s searchSimple) Search(boundDN string, searchReq SearchRequest, conn net.Conn) (ServerSearchResult, error) {
- entries := []*Entry{
- &Entry{"cn=ned,o=testers,c=test", []*EntryAttribute{
- &EntryAttribute{"cn", []string{"ned"}},
- &EntryAttribute{"o", []string{"ate"}},
- &EntryAttribute{"uidNumber", []string{"5000"}},
- &EntryAttribute{"accountstatus", []string{"active"}},
- &EntryAttribute{"uid", []string{"ned"}},
- &EntryAttribute{"description", []string{"ned via sa"}},
- &EntryAttribute{"objectclass", []string{"posixaccount"}},
- }},
- &Entry{"cn=trent,o=testers,c=test", []*EntryAttribute{
- &EntryAttribute{"cn", []string{"trent"}},
- &EntryAttribute{"o", []string{"ate"}},
- &EntryAttribute{"uidNumber", []string{"5005"}},
- &EntryAttribute{"accountstatus", []string{"active"}},
- &EntryAttribute{"uid", []string{"trent"}},
- &EntryAttribute{"description", []string{"trent via sa"}},
- &EntryAttribute{"objectclass", []string{"posixaccount"}},
- }},
- &Entry{"cn=randy,o=testers,c=test", []*EntryAttribute{
- &EntryAttribute{"cn", []string{"randy"}},
- &EntryAttribute{"o", []string{"ate"}},
- &EntryAttribute{"uidNumber", []string{"5555"}},
- &EntryAttribute{"accountstatus", []string{"active"}},
- &EntryAttribute{"uid", []string{"randy"}},
- &EntryAttribute{"objectclass", []string{"posixaccount"}},
- }},
- }
- return ServerSearchResult{entries, []string{}, []Control{}, LDAPResultSuccess}, nil
- }
- type searchSimple2 struct {
- }
- func (s searchSimple2) Search(boundDN string, searchReq SearchRequest, conn net.Conn) (ServerSearchResult, error) {
- entries := []*Entry{
- &Entry{"cn=hamburger,o=testers,c=testz", []*EntryAttribute{
- &EntryAttribute{"cn", []string{"hamburger"}},
- &EntryAttribute{"o", []string{"testers"}},
- &EntryAttribute{"uidNumber", []string{"5000"}},
- &EntryAttribute{"accountstatus", []string{"active"}},
- &EntryAttribute{"uid", []string{"hamburger"}},
- &EntryAttribute{"objectclass", []string{"posixaccount"}},
- }},
- }
- return ServerSearchResult{entries, []string{}, []Control{}, LDAPResultSuccess}, nil
- }
- type searchPanic struct {
- }
- func (s searchPanic) Search(boundDN string, searchReq SearchRequest, conn net.Conn) (ServerSearchResult, error) {
- entries := []*Entry{}
- panic("this is a test panic")
- return ServerSearchResult{entries, []string{}, []Control{}, LDAPResultSuccess}, nil
- }
- type searchControls struct {
- }
- func (s searchControls) Search(boundDN string, searchReq SearchRequest, conn net.Conn) (ServerSearchResult, error) {
- entries := []*Entry{}
- if len(searchReq.Controls) == 1 && searchReq.Controls[0].GetControlType() == "1.2.3.4.5" {
- newEntry := &Entry{"cn=hamburger,o=testers,c=testz", []*EntryAttribute{
- &EntryAttribute{"cn", []string{"hamburger"}},
- &EntryAttribute{"o", []string{"testers"}},
- &EntryAttribute{"uidNumber", []string{"5000"}},
- &EntryAttribute{"accountstatus", []string{"active"}},
- &EntryAttribute{"uid", []string{"hamburger"}},
- &EntryAttribute{"objectclass", []string{"posixaccount"}},
- }}
- entries = append(entries, newEntry)
- }
- return ServerSearchResult{entries, []string{}, []Control{}, LDAPResultSuccess}, nil
- }
|