func TestLocalSearch(t *testing.T) { fmt.Printf("TestLocalSearch: starting...\n") l := ldap.NewLDAPConnection(server, port) err := l.Connect() if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error(err) return } search_request := ldap.NewSimpleSearchRequest( base_dn, ldap.ScopeWholeSubtree, filters[0], attributes, ) sr, err := l.Search(search_request) if err != nil { t.Error(err) return } fmt.Printf("TestLocalSearch: %s -> num of entries = %d\n", search_request.Filter, len(sr.Entries)) }
func TestLocalMultiGoroutineSearch(t *testing.T) { fmt.Printf("TestLocalMultiGoroutineSearch: starting...\n") l := ldap.NewLDAPConnection(server, port) err := l.Connect() if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error(err) return } results := make([]chan *ldap.SearchResult, len(filters)) for i := range filters { results[i] = make(chan *ldap.SearchResult) go testLocalMultiGoroutineSearch(t, l, results[i], i) } for i := range filters { sr := <-results[i] if sr == nil { t.Errorf("Did not receive results from goroutine for %q", filters[i]) } else { fmt.Printf("TestLocalMultiGoroutineSearch(%d): %s -> num of entries = %d\n", i, filters[i], len(sr.Entries)) } } }
func TestLocalAddAndDelete(t *testing.T) { fmt.Printf("TestLocalAddAndDelete: starting...\n") l := ldap.NewLDAPConnection(server, port) err := l.Connect() if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error(err) return } addReq := ldap.NewAddRequest(addDNs[0]) for _, attr := range addAttrs { addReq.AddAttribute(&attr) } fmt.Printf("Adding: %s\n", addDNs[0]) err = l.Add(addReq) if err != nil { t.Errorf("Add : %s : %s\n", addDNs[0], err) return } fmt.Printf("Deleting: %s\n", addDNs[0]) delRequest := ldap.NewDeleteRequest(addDNs[0]) err = l.Delete(delRequest) if err != nil { t.Errorf("Delete : %s : %s\n", addDNs[0], err) return } }
func (l *LDAPStorageHandler) Connect() bool { conn := ldap.NewLDAPConnection(l.LDAPServer, l.LDAPPort) if err := conn.Connect(); err != nil { log.Error("LDAP server connection failed: ", err) return false } log.Info("LDAP: Connection established") l.store = conn return true }
func TestLocalConnect(t *testing.T) { fmt.Printf("TestLocalConnect: starting...\n") l := ldap.NewLDAPConnection(server, port) err := l.Connect() if err != nil { t.Error(err) return } defer l.Close() fmt.Printf("TestLocalConnect: finished...\n") }
func TestLocalConnectTimeout(t *testing.T) { fmt.Printf("TestLocalConnectTimeout: starting...\n") fmt.Printf("Expecting a %v error\n", ldap.ErrorNetwork) l := ldap.NewLDAPConnection(server, port) l.NetworkConnectTimeout = 1 * time.Microsecond err := l.Connect() if err != nil { fmt.Print(err) // not an error return } defer l.Close() fmt.Print("TestLocalConnectTimeout: finished...\n") }
func TestLocalSearchPagingWithHandler(t *testing.T) { fmt.Printf("TestLocalSearchPagingWithHandler: starting...\n") l := ldap.NewLDAPConnection(server, port) err := l.Connect() // l.Debug = true if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error(err) return } search_request := ldap.NewSimpleSearchRequest( base_dn, ldap.ScopeWholeSubtree, filters[0], attributes, ) l.Debug = false pagingControl := ldap.NewControlPaging(2) search_request.Controls = append(search_request.Controls, pagingControl) for { sr := new(ldap.SearchResult) err = l.SearchWithHandler(search_request, sr, nil) if err != nil { t.Error(err) return } _, pagingResponsePacket := ldap.FindControl(sr.Controls, ldap.ControlTypePaging) if pagingResponsePacket == nil { t.Errorf("Expected Paging Control.") } pagingControl.Cookie = pagingResponsePacket.(*ldap.ControlPaging).Cookie ldap.ReplaceControl(search_request.Controls, pagingControl) fmt.Printf("TestLocalSearchPagingWithHandler: %s entries = %d, Referrals = %d\n", search_request.Filter, len(sr.Entries), len(sr.Referrals)) if len(pagingControl.Cookie) == 0 { return } } }
func TestLocalOrderedSearch(t *testing.T) { fmt.Printf("TestLocalOrderedSearch: starting...\n") l := ldap.NewLDAPConnection(server, port) err := l.Connect() // l.Debug = true if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error(err) return } search_request := ldap.NewSimpleSearchRequest( base_dn, ldap.ScopeWholeSubtree, filters[3], attributes, ) serverSideSortAttrRuleOrder := ldap.ServerSideSortAttrRuleOrder{ AttributeName: "cn", OrderingRule: "", ReverseOrder: false, } sortKeyList := make([]ldap.ServerSideSortAttrRuleOrder, 0, 1) sortKeyList = append(sortKeyList, serverSideSortAttrRuleOrder) sortControl := ldap.NewControlServerSideSortRequest(sortKeyList, true) fmt.Println(sortControl.String()) search_request.AddControl(sortControl) l.Debug = false sr, err := l.Search(search_request) if err != nil { t.Error(err) return } _, sssResponse := ldap.FindControl(sr.Controls, ldap.ControlTypeServerSideSortResponse) if sssResponse != nil { fmt.Println(sssResponse.String()) } fmt.Printf("TestLocalSearch: %s -> num of entries = %d\n", search_request.Filter, len(sr.Entries)) }
func backendAuthenticateLDAP(user, password string) bool { c := ldap.NewLDAPConnection(ldapServer, uint16(ldapPort)) err := c.Connect() if err != nil { log.Println("ldap:", err) return false } err = c.Bind(fmt.Sprintf(ldapBind, user), password) if err != nil { log.Printf("ldap: %q: %s", user, err) return false } defer c.Close() return true }
// Really just a test of setting the timeout. func TestLocalBindWithTimeout(t *testing.T) { fmt.Printf("TestLocalBindWithTimeout: starting...\n") l := ldap.NewLDAPConnection(server, port) l.NetworkConnectTimeout = 5 * time.Second l.ReadTimeout = 5 * time.Second err := l.Connect() if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error("Timed out in with a bind timeout of 5 seconds!") return } fmt.Printf("TestLocalBindWithTimeout: finished...\n") }
func TestLocalBind(t *testing.T) { fmt.Printf("TestLocalBind: starting...\n") l := ldap.NewLDAPConnection(server, port) l.Debug = true l.NetworkConnectTimeout = 5 * time.Second err := l.Connect() if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error(err) return } fmt.Printf("TestLocalBind: finished...\n") }
func TestLocalVlvSearch(t *testing.T) { fmt.Printf("TestLocalVlvSearch: starting...\n") l := ldap.NewLDAPConnection(server, port) err := l.Connect() // l.Debug = true if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error(err) return } search_request := ldap.NewSimpleSearchRequest( base_dn, ldap.ScopeWholeSubtree, "(cn=*)", attributes, ) vlvControl := new(ldap.ControlVlvRequest) vlvControl.BeforeCount = 0 vlvControl.AfterCount = 3 offset := new(ldap.VlvOffSet) offset.Offset = 1 offset.ContentCount = 3 vlvControl.ByOffset = offset //pack, _ := vlvControl.Encode() //fmt.Println(hex.Dump(pack.Bytes())) search_request.AddControl(vlvControl) serverSideSortAttrRuleOrder := ldap.ServerSideSortAttrRuleOrder{ AttributeName: "cn", OrderingRule: "", ReverseOrder: false, } sortKeyList := make([]ldap.ServerSideSortAttrRuleOrder, 0, 1) sortKeyList = append(sortKeyList, serverSideSortAttrRuleOrder) sortControl := ldap.NewControlServerSideSortRequest(sortKeyList, true) search_request.AddControl(sortControl) l.Debug = false sr, err := l.Search(search_request) if err != nil { t.Error(err) return } _, vlvResp := ldap.FindControl(sr.Controls, ldap.ControlTypeVlvResponse) if vlvResp != nil { fmt.Println(vlvResp.String()) } for _, entry := range sr.Entries { fmt.Println(entry.GetAttributeValues("cn")[0]) } fmt.Printf("TestLocalVlvSearch (byOffSet): %s -> num of entries = %d\n", search_request.Filter, len(sr.Entries)) search_request = ldap.NewSimpleSearchRequest( base_dn, ldap.ScopeWholeSubtree, "(cn=*)", attributes, ) vlvControl = new(ldap.ControlVlvRequest) vlvControl.BeforeCount = 0 vlvControl.AfterCount = 3 vlvControl.GreaterThanOrEqual = "Aaren Amar" //pack, _ := vlvControl.Encode() //fmt.Println(hex.Dump(pack.Bytes())) search_request.AddControl(vlvControl) search_request.AddControl(sortControl) sr, err = l.Search(search_request) if err != nil { t.Error(err) return } _, vlvResp = ldap.FindControl(sr.Controls, ldap.ControlTypeVlvResponse) if vlvResp != nil { fmt.Println(vlvResp.String()) } for _, entry := range sr.Entries { fmt.Println(entry.GetAttributeValues("cn")[0]) } fmt.Printf("TestLocalVlvSearch (value): %s -> num of entries = %d\n", search_request.Filter, len(sr.Entries)) fmt.Printf("TestLocalVlvSearch: Finished.\n") }
func TestLocalSearchWithHandler(t *testing.T) { fmt.Printf("TestLocalSearchWithHandler: starting...\n") l := ldap.NewLDAPConnection(server, port) err := l.Connect() // l.Debug = true if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error(err) return } search_request := ldap.NewSimpleSearchRequest( base_dn, ldap.ScopeWholeSubtree, filters[0], attributes, ) l.Debug = false // Blocking fmt.Println("Blocking version...") resultCounter := new(counter) err = l.SearchWithHandler(search_request, resultCounter, nil) if err != nil { t.Error(err) return } fmt.Printf("TestLocalSearchWithHandler: %s entries = %d, Referrals = %d\n", search_request.Filter, resultCounter.EntryCount, resultCounter.ReferenceCount) // Non-Blocking fmt.Println("Non-Blocking version...") resultChan := make(chan error) resultCounter = new(counter) go l.SearchWithHandler(search_request, resultCounter, resultChan) fmt.Println("do stuff ...") err = <-resultChan if err != nil { t.Error(err) return } fmt.Printf("TestLocalSearchWithHandler - go routine: %s entries = %d, Referrals = %d\n", search_request.Filter, resultCounter.EntryCount, resultCounter.ReferenceCount) // TODO blocking + abandon non-trival version. // Non-Blocking + Abandoning fmt.Println("Non-Blocking + Abandon version...") resultChan = make(chan error) resultCounter = new(counter) resultCounter.AbandonAtEntryCount = 4 go l.SearchWithHandler(search_request, resultCounter, resultChan) err = <-resultChan if err != nil { t.Error(err) return } fmt.Printf("TestLocalSearchWithHandler - go routine: %s entries = %d, Referrals = %d\n", search_request.Filter, resultCounter.EntryCount, resultCounter.ReferenceCount) }
func TestLocalControlMatchedValuesRequest(t *testing.T) { fmt.Printf("LocalControlMatchedValuesRequest: starting...\n") l := ldap.NewLDAPConnection(server, port) err := l.Connect() if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error(err) return } addReq := ldap.NewAddRequest(addDNs[0]) for _, attr := range addAttrs { addReq.AddAttribute(&attr) } fmt.Printf("Adding: %s\n", addDNs[0]) err = l.Add(addReq) if err != nil { t.Errorf("Add : %s : %s\n", addDNs[0], err) return } fmt.Printf("Modify: %s = {aaa, bbb, ccc}\n", "description") mod := ldap.NewMod(ldap.ModAdd, "description", []string{"aaa", "bbb", "ccc", "aabb"}) modreq := ldap.NewModifyRequest(addDNs[0]) modreq.AddMod(mod) err = l.Modify(modreq) if err != nil { t.Errorf("Modify: %s : %s\n", addDNs[0], err) return } control := ldap.NewControlMatchedValuesRequest(true, "(description=aaa)") fmt.Println(control.String()) fmt.Printf("Search: (objectclass=*), (description=aaa) via MatchedValuesRequest\n") search_request := ldap.NewSimpleSearchRequest( addDNs[0], ldap.ScopeBaseObject, "(objectclass=*)", []string{"description"}, ) search_request.AddControl(control) //l.Debug = true sr, err := l.Search(search_request) if err != nil { t.Errorf("Search: %s : %s\n", addDNs[0], err) return } //l.Debug = false fmt.Println("Search Result:") fmt.Print(sr) control = ldap.NewControlMatchedValuesRequest(true, "(description=a*)") fmt.Println(control.String()) fmt.Printf("Search: (objectclass=*), (description=a*) via MatchedValuesRequest\n") search_request = ldap.NewSimpleSearchRequest( addDNs[0], ldap.ScopeBaseObject, "(objectclass=*)", []string{"description"}, ) search_request.AddControl(control) //l.Debug = true sr, err = l.Search(search_request) if err != nil { t.Errorf("Search: %s : %s\n", addDNs[0], err) return } //l.Debug = false fmt.Println("Search Result:") fmt.Print(sr) fmt.Printf("Deleting: %s\n", addDNs[0]) delRequest := ldap.NewDeleteRequest(addDNs[0]) err = l.Delete(delRequest) if err != nil { t.Errorf("Delete : %s : %s\n", addDNs[0], err) return } }
func TestLocalCompare(t *testing.T) { fmt.Printf("TestLocalCompare: starting...\n") l := ldap.NewLDAPConnection(server, port) err := l.Connect() if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error(err) return } addReq := ldap.NewAddRequest(addDNs[0]) for _, attr := range addAttrs { addReq.AddAttribute(&attr) } fmt.Printf("Adding: %s\n", addDNs[0]) err = l.Add(addReq) if err != nil { t.Errorf("Add : %s : %s\n", addDNs[0], err) return } fmt.Printf("Comparing: %s : sn=Boy which is True\n", addDNs[0]) compareReq := ldap.NewCompareRequest(addDNs[0], "sn", "Boy") result, cerr := l.Compare(compareReq) if cerr != nil { t.Error(err) return } if result != true { t.Error("Compare Result should have been true") return } fmt.Printf("Compare Result : %v\n", result) fmt.Printf("Comparing: %s : sn=BoyIsThisWrong which is False\n", addDNs[0]) compareReq = ldap.NewCompareRequest(addDNs[0], "sn", "BoyIsThisWrong") result, cerr = l.Compare(compareReq) if cerr != nil { t.Error(cerr) return } if result == true { t.Error("Compare Result should have been false") return } fmt.Printf("Compare Result : %v\n", result) fmt.Printf("Deleting: %s\n", addDNs[0]) delRequest := ldap.NewDeleteRequest(addDNs[0]) err = l.Delete(delRequest) if err != nil { t.Errorf("Delete : %s : %s\n", addDNs[0], err) return } }
func TestLocalControlPermissiveModifyRequest(t *testing.T) { fmt.Printf("ControlPermissiveModifyRequest: starting...\n") l := ldap.NewLDAPConnection(server, port) err := l.Connect() if err != nil { t.Error(err) return } defer l.Close() err = l.Bind(binddn, passwd) if err != nil { t.Error(err) return } addReq := ldap.NewAddRequest(addDNs[0]) for _, attr := range addAttrs { addReq.AddAttribute(&attr) } fmt.Printf("Adding: %s\n", addDNs[0]) err = l.Add(addReq) if err != nil { t.Errorf("Add : %s : %s\n", addDNs[0], err) return } modreq := ldap.NewModifyRequest(addDNs[0]) mod := ldap.NewMod(ldap.ModAdd, "description", []string{"aaa"}) modreq.AddMod(mod) fmt.Println(modreq) err = l.Modify(modreq) if err != nil { t.Errorf("Modify : %s : %s\n", addDNs[0], err) return } mod = ldap.NewMod(ldap.ModAdd, "description", []string{"aaa", "bbb", "ccc"}) modreq = ldap.NewModifyRequest(addDNs[0]) modreq.AddMod(mod) control := ldap.NewControlString(ldap.ControlTypePermissiveModifyRequest, true, "") fmt.Println(control.String()) modreq.AddControl(control) fmt.Println(modreq) err = l.Modify(modreq) if err != nil { t.Errorf("Modify (Permissive): %s : %s\n", addDNs[0], err) return } mod = ldap.NewMod(ldap.ModAdd, "description", []string{"aaa", "bbb", "ccc", "ddd"}) modreq = ldap.NewModifyRequest(addDNs[0]) modreq.AddMod(mod) control = ldap.NewControlPermissiveModifyRequest(false) fmt.Println(control.String()) modreq.AddControl(control) fmt.Println(modreq) err = l.Modify(modreq) if err != nil { t.Errorf("Modify (Permissive): %s : %s\n", addDNs[0], err) return } fmt.Printf("Deleting: %s\n", addDNs[0]) delRequest := ldap.NewDeleteRequest(addDNs[0]) err = l.Delete(delRequest) if err != nil { t.Errorf("Delete : %s : %s\n", addDNs[0], err) return } }
func LdapAuthenticator(options *LdapOptions) (martini.Handler, error) { hostInfo := HostExpr.FindStringSubmatch(options.Host) config := &ldapConfig{} switch hostInfo[1] { case "ldap": config.SSL = false case "ldaps": config.SSL = true default: return nil, fmt.Errorf("invalid ldap protocol: %s", hostInfo[1]) } config.Host = hostInfo[2] if hostInfo[4] != "" { port, err := strconv.ParseUint(hostInfo[4], 10, 16) if err != nil { return nil, fmt.Errorf("unable to parse ldap port: %s", err) } config.Port = uint16(port) } else { if config.SSL { config.Port = 636 } else { config.Port = 389 } } return func(res http.ResponseWriter, req *http.Request, c martini.Context, log *log.Logger) { // HACK TODO: do not put routing logic in the auth handler // The /ping endpoint does not have auth, so explicitly exclude it here if req.URL.Path == "/ping" { return } authHandler := auth.BasicFunc(func(username, password string) bool { // create the ldap server connection var conn *ldap.LDAPConnection if config.SSL { tlsConfig := tls.Config{ ServerName: config.Host, } conn = ldap.NewLDAPSSLConnection(config.Host, config.Port, &tlsConfig) } else { conn = ldap.NewLDAPConnection(config.Host, config.Port) } // attempt to connect to the ldap server if err := conn.Connect(); err != nil { log.Printf("Unable to connect to LDAP: %s", err) return false } // perform an anonymous search for the user's dn so we can attempt to bind as them req := ldap.SearchRequest{ BaseDN: options.BaseDN, Filter: fmt.Sprintf(options.UserFilter, ldap.EscapeFilterValue(username)), Scope: ldap.ScopeWholeSubtree, } res, err := conn.Search(&req) if err != nil { log.Printf("Error performing LDAP search: %s", err) return false } // Return false if the number of entries isn't exactly 1. If multiple // results were returned, there is an ambiguity so return false instead // of proceeding. If no entries were returned, we have no idea who this // is and cannot authenticate. if len(res.Entries) != 1 { if len(res.Entries) > 1 { log.Printf("User '%s' attempted to authenticate but multiple entries exists", username) } else { log.Printf("User '%s' attempted to authenticate but does not exist", username) } return false } dn := res.Entries[0].DN if err := conn.Bind(dn, password); err != nil { log.Printf("User '%s' attempted to authenticate but provided an invalid password", username) return false } log.Printf("Authenticated successfully as %s", username) return true }) authenticate := authHandler.(func(http.ResponseWriter, *http.Request, martini.Context)) authenticate(res, req, c) }, nil }