func getBindDN(cfg *ConfigEntry, c *ldap.Conn, username string) (string, error) { bindDN := "" if cfg.DiscoverDN || (cfg.BindDN != "" && cfg.BindPassword != "") { if err := c.Bind(cfg.BindDN, cfg.BindPassword); err != nil { return bindDN, fmt.Errorf("LDAP bind (service) failed: %v", err) } result, err := c.Search(&ldap.SearchRequest{ BaseDN: cfg.UserDN, Scope: 2, // subtree Filter: fmt.Sprintf("(%s=%s)", cfg.UserAttr, ldap.EscapeFilter(username)), }) if err != nil { return bindDN, fmt.Errorf("LDAP search for binddn failed: %v", err) } if len(result.Entries) != 1 { return bindDN, fmt.Errorf("LDAP search for binddn 0 or not unique") } bindDN = result.Entries[0].DN } else { if cfg.UPNDomain != "" { bindDN = fmt.Sprintf("%s@%s", EscapeLDAPValue(username), cfg.UPNDomain) } else { bindDN = fmt.Sprintf("%s=%s,%s", cfg.UserAttr, EscapeLDAPValue(username), cfg.UserDN) } } return bindDN, nil }
/* * Returns the DN of the object representing the authenticated user. */ func (b *backend) getUserDN(cfg *ConfigEntry, c *ldap.Conn, bindDN string) (string, error) { userDN := "" if cfg.UPNDomain != "" { // Find the distinguished name for the user if userPrincipalName used for login filter := fmt.Sprintf("(userPrincipalName=%s)", ldap.EscapeFilter(bindDN)) if b.Logger().IsDebug() { b.Logger().Debug("auth/ldap: Searching UPN", "userdn", cfg.UserDN, "filter", filter) } result, err := c.Search(&ldap.SearchRequest{ BaseDN: cfg.UserDN, Scope: 2, // subtree Filter: filter, }) if err != nil { return userDN, fmt.Errorf("LDAP search failed for detecting user: %v", err) } for _, e := range result.Entries { userDN = e.DN } } else { userDN = bindDN } return userDN, nil }
func inGroup(username, group string, config *Config, conn *ldap.Conn, attrs []string) (bool, map[string][]string, error) { groupDN, err := getDN(group, config, conn) if err != nil { if config.Debug { log.Printf("DEBUG: Error: %s\n", err) } return false, nil, err } search := ldap.NewSearchRequest( config.BaseDN, ldap.ScopeWholeSubtree, ldap.DerefAlways, 1, 0, false, fmt.Sprintf("(sAMAccountName=%s)", username), append(attrs, "memberOf"), nil, ) result, lErr := conn.Search(search) if lErr != nil { if config.Debug { log.Printf("DEBUG: LDAP Error %v\n", lErr) } return false, nil, lErr } if len(result.Entries) == 1 { entryAttrs := attrsToMap(result.Entries[0]) if groups, ok := entryAttrs["memberOf"]; ok { for _, g := range groups { if groupDN == g { for _, key := range attrs { if key == "memberOf" { return true, entryAttrs, nil } } delete(entryAttrs, "memberOf") return true, entryAttrs, nil } } } return false, entryAttrs, nil } return false, nil, LDAPError("Amount of Entries returned was not one") }
func getUserDN(cfg *ConfigEntry, c *ldap.Conn, bindDN string) (string, error) { userDN := "" if cfg.UPNDomain != "" { // Find the distinguished name for the user if userPrincipalName used for login result, err := c.Search(&ldap.SearchRequest{ BaseDN: cfg.UserDN, Scope: 2, // subtree Filter: fmt.Sprintf("(userPrincipalName=%s)", ldap.EscapeFilter(bindDN)), }) if err != nil { return userDN, fmt.Errorf("LDAP search failed for detecting user: %v", err) } for _, e := range result.Entries { userDN = e.DN } } else { userDN = bindDN } return userDN, nil }
// Search LDAP by cn filter func searchByName(l *ldap.Conn, name string) (*ldap.SearchResult, error) { filter := fmt.Sprintf("(cn=%v)", ReplaceAccents(name)) search := ldap.NewSearchRequest( baseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, filter, attributes, nil) sr, err := l.Search(search) if err != nil { return nil, err } switch { case len(sr.Entries) == 0: return sr, ErrNoResults case len(sr.Entries) > 1: return sr, ErrTooManyResults } return sr, nil }
func getAttrs(username string, config *Config, conn *ldap.Conn, attrs []string) (map[string][]string, error) { search := ldap.NewSearchRequest( config.BaseDN, ldap.ScopeWholeSubtree, ldap.DerefAlways, 1, 0, false, fmt.Sprintf("(sAMAccountName=%s)", username), attrs, nil, ) result, lErr := conn.Search(search) if lErr != nil { if config.Debug { log.Printf("DEBUG: LDAP Error %v\n", lErr) } return nil, lErr } if len(result.Entries) == 1 { return attrsToMap(result.Entries[0]), nil } return nil, LDAPError("Amount of Entries returned was not one") }
func getDN(cn string, config *Config, conn *ldap.Conn) (string, error) { search := ldap.NewSearchRequest( config.BaseDN, ldap.ScopeWholeSubtree, ldap.DerefAlways, 1, 0, false, fmt.Sprintf("(cn=%s)", cn), nil, nil, ) result, err := conn.Search(search) if err != nil { if config.Debug { log.Printf("DEBUG: LDAP Error %v\n", err) } return "", err } if len(result.Entries) > 0 { return result.Entries[0].DN, nil } return "", ConfigError(fmt.Sprintf("No DN found for: %s", cn)) }
//ldap search and return required attributes' value from searched entries //default return entry's DN value if you leave attrs array empty func (la *LDAPAuth) ldapSearch(l *ldap.Conn, baseDN *string, filter *string, attrs *[]string) (string, error) { if l == nil { return "", fmt.Errorf("No ldap connection!") } glog.V(2).Infof("Searching...basedDN:%s, filter:%s", *baseDN, *filter) searchRequest := ldap.NewSearchRequest( *baseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, *filter, *attrs, nil) sr, err := l.Search(searchRequest) if err != nil { return "", err } if len(sr.Entries) != 1 { return "", fmt.Errorf("User does not exist or too many entries returned.") } var buffer bytes.Buffer for _, entry := range sr.Entries { if len(*attrs) == 0 { glog.V(2).Infof("Entry DN = %s", entry.DN) buffer.WriteString(entry.DN) } else { for _, attr := range *attrs { values := strings.Join(entry.GetAttributeValues(attr), " ") glog.V(2).Infof("Entry %s = %s", attr, values) buffer.WriteString(values) } } } return buffer.String(), nil }
func getLdapGroups(cfg *ConfigEntry, c *ldap.Conn, userDN string, username string) ([]string, error) { // retrieve the groups in a string/bool map as a structure to avoid duplicates inside ldapMap := make(map[string]bool) // Fetch the optional memberOf property values on the user object // This is the most common method used in Active Directory setup to retrieve the groups result, err := c.Search(&ldap.SearchRequest{ BaseDN: userDN, Scope: 0, // base scope to fetch only the userDN Filter: "(cn=*)", // bogus filter, required to fetch the CN from userDN Attributes: []string{ "memberOf", }, }) // this check remains in case something happens with the ldap query or connection if err != nil { return nil, fmt.Errorf("LDAP fetch of distinguishedName=%s failed: %v", userDN, err) } // if there are more than one entry, we consider the results irrelevant and ignore them if len(result.Entries) == 1 { for _, attr := range result.Entries[0].Attributes { // Find the groups the user is member of from the 'memberOf' attribute extracting the CN if attr.Name == "memberOf" { for _, value := range attr.Values { memberOfDN, err := ldap.ParseDN(value) if err != nil || len(memberOfDN.RDNs) == 0 { continue } for _, rdn := range memberOfDN.RDNs { for _, rdnTypeAndValue := range rdn.Attributes { if strings.EqualFold(rdnTypeAndValue.Type, "CN") { ldapMap[rdnTypeAndValue.Value] = true } } } } } } } // Find groups by searching in groupDN for any of the memberUid, member or uniqueMember attributes // and retrieving the CN in the DN result if cfg.GroupDN != "" { result, err := c.Search(&ldap.SearchRequest{ BaseDN: cfg.GroupDN, Scope: 2, // subtree Filter: fmt.Sprintf("(|(memberUid=%s)(member=%s)(uniqueMember=%s))", ldap.EscapeFilter(username), ldap.EscapeFilter(userDN), ldap.EscapeFilter(userDN)), }) if err != nil { return nil, fmt.Errorf("LDAP search failed: %v", err) } for _, e := range result.Entries { dn, err := ldap.ParseDN(e.DN) if err != nil || len(dn.RDNs) == 0 { continue } for _, rdn := range dn.RDNs { for _, rdnTypeAndValue := range rdn.Attributes { if strings.EqualFold(rdnTypeAndValue.Type, "CN") { ldapMap[rdnTypeAndValue.Value] = true } } } } } ldapGroups := make([]string, len(ldapMap)) for key, _ := range ldapMap { ldapGroups = append(ldapGroups, key) } return ldapGroups, nil }
func indexHandler(w http.ResponseWriter, r *http.Request) { var ( xSearchPplMode = int(0) xSearch string xMessage string dn string dn_back string dn_back_tmp []string go_home_button string ldap_Search string ldapSearchMode = int(1) ckl1 int ldap_Attr []string xGetDN [1000]string xGetCkl int l *ldap.Conn err error xFRColor = string("#FFFFFF") xBGColor = string("#FFFFFF") LUserName = string("") setAdminMode = string("") ) username, userperm := CheckUserSession(r, w) //fmt.Printf("%s / %d\n", username, userperm) switch userperm { case roleAdmin: xFRColor = "#FF0000" xBGColor = "#FFFFFF" LUserName = username setAdminMode = "Yes" case roleUser: xFRColor = "#0000FF" xBGColor = "#FFFFFF" LUserName = username default: xFRColor = "#FFFFFF" xBGColor = "#FFFFFF" LUserName = "" } ldap_Attr = make([]string, len(rconf.WLB_LDAP_ATTR)) for ckl1 := 0; ckl1 < len(rconf.WLB_LDAP_ATTR); ckl1++ { ldap_Attr[ckl1] = rconf.WLB_LDAP_ATTR[ckl1][0] } SABModules.Log_ON(&rconf) defer SABModules.Log_OFF() get_dn := r.FormValue("dn") get_cn := r.FormValue("cn") get_fn := r.FormValue("FirstName") get_ln := r.FormValue("LastName") searchMode := r.FormValue("SearchMode") remIPClient := getIPAddress(r) // log.Printf("DN: %s --- CN: %s", get_dn, get_cn) if get_dn == "" { dn = rconf.LDAP_URL[ldap_count][3] } else { dn = get_dn } if len(dn) < len(rconf.LDAP_URL[ldap_count][3]) { dn = rconf.LDAP_URL[ldap_count][3] } log.Printf("->") log.Printf("--> %s", pVersion) log.Printf("->") ucurl, _ := strconv.Unquote(r.RequestURI) log.Println(remIPClient + " --> http://" + r.Host + ucurl) log.Printf("%s ++> DN: %s / CN: %s / Mode: %d / Def.DN: %s", remIPClient, dn, ldap_Search, ldapSearchMode, rconf.LDAP_URL[ldap_count][3]) if get_cn == "" && get_ln == "" && get_fn == "" { ldap_Search = rconf.LDAP_URL[ldap_count][4] } else { log.Printf("%s ++> SQL Search: %s/%s/%s\n", remIPClient, get_cn, get_fn, get_ln) dbpg, err := sql.Open("postgres", rconf.PG_DSN) if err != nil { log.Fatalf("PG_INIT::Open() error: %v\n", err) } defer dbpg.Close() queryx := "select x.dn from ldap_entries as x, ldapx_persons as y where x.uid=y.uid" if len(get_cn) > 2 { queryx = fmt.Sprintf("%s and lower(fullname) like lower('%%%s%%')", queryx, strings.ToLower(get_cn)) } if len(get_ln) > 2 { queryx = fmt.Sprintf("%s and lower(surname) like lower('%s%%')", queryx, strings.ToLower(get_ln)) } if len(get_fn) > 2 { queryx = fmt.Sprintf("%s and lower(name) like lower('%s%%')", queryx, strings.ToLower(get_fn)) } if len(get_cn) <= 2 && len(get_ln) <= 2 && len(get_fn) <= 2 { queryx = fmt.Sprintf("%s and 2=3;", queryx) } else { queryx = fmt.Sprintf("%s;", queryx) } // log.Printf("Search QUERY: %s\n", queryx) rows, err := dbpg.Query(queryx) if err != nil { fmt.Printf("SQL Error: %s\n", queryx) log.Printf("PG::Query() Check LDAP tables error: %v\n", err) return } xGetCkl = 0 for rows.Next() { rows.Scan(&xGetDN[xGetCkl]) //fmt.Println("XXX:", xGetDN[xGetCkl], dn) if strings.Contains(strings.ToLower(xGetDN[xGetCkl]), strings.ToLower(dn)) || searchMode == "Full" { log.Printf("%s <-- SQL Found: %s\n", remIPClient, xGetDN[xGetCkl]) xGetCkl++ if xGetCkl > userLimit { xMessage = fmt.Sprintf("Количество персон по вашему запросу превысило %d! Пожалуйста, задайте критерии более конкретно!", userLimit) break } } } xSearchPplMode = 1 ldapSearchMode = 2 } if strings.ToLower(dn) != strings.ToLower(rconf.LDAP_URL[ldap_count][3]) || xSearchPplMode == 1 { go_home_button = "+" } if ldapSearchMode != 2 { xSearch = "+" } if strings.ToLower(dn) != strings.ToLower(rconf.LDAP_URL[ldap_count][3]) { if ldapSearchMode == 1 && xSearchPplMode == 0 { dn_back_tmp = strings.Split(dn, ",") for ckl1 = 1; ckl1 < len(dn_back_tmp); ckl1++ { if ckl1 == 1 { dn_back = dn_back_tmp[ckl1] } else { dn_back += fmt.Sprintf(",%s", dn_back_tmp[ckl1]) } } } } // log.Printf("%s ... Initialize LDAP connector...", remIPClient) if initLDAPConnector() == "error" { return } l, err = ldap.Dial("tcp", rconf.LDAP_URL[ldap_count][0]) if err != nil { fmt.Fprintf(w, err.Error()) log.Printf("LDAP::Initialize() error: %v\n", err) return } // l.Debug = true defer l.Close() log.Printf("%s =!= Connected to server %d of %d: %s", remIPClient, ldap_count+1, len(rconf.LDAP_URL), rconf.LDAP_URL[ldap_count][0]) err = l.Bind(rconf.LDAP_URL[ldap_count][1], rconf.LDAP_URL[ldap_count][2]) if err != nil { fmt.Fprintf(w, err.Error()) log.Printf("LDAP::Bind() error: %v\n", err) return } t, err := template.ParseFiles("templates/header.html") if err != nil { fmt.Fprintf(w, err.Error()) log.Println(err.Error()) return } t.ExecuteTemplate(w, "header", template.FuncMap{"Pagetitle": rconf.WLB_HTML_Title, "FRColor": xFRColor, "BGColor": xBGColor}) t, err = template.ParseFiles("templates/search.html") if err != nil { fmt.Fprintf(w, err.Error()) log.Println(err.Error()) return } t.ExecuteTemplate(w, "search", template.FuncMap{"GoHome": go_home_button, "PrevDN": dn_back, "DN": dn, "xSearch": xSearch, "xMessage": xMessage, "LineColor": "#EEEEEE", "LUserName": LUserName, "LoginShow": "Yes", "RedirectDN": r.RequestURI}) t, err = template.ParseFiles("templates/index.html") if err != nil { fmt.Fprintf(w, err.Error()) log.Println(err.Error()) return } if xSearchPplMode == 0 { search := ldap.NewSearchRequest(dn, ldapSearchMode, ldap.NeverDerefAliases, 0, 0, false, ldap_Search, ldap_Attr, nil) // log.Printf("Search: %v\n%v\n%v\n%v\n%v\n%v\n", search, dn, ldapSearchMode, ldap.NeverDerefAliases, ldap_Search, ldap_Attr) sr, err := l.Search(search) if err != nil { fmt.Fprintf(w, err.Error()) log.Printf("LDAP::Search() error: %v\n", err) return } // fmt.Printf("\n\nSearch: %v", search) log.Printf("%s ++> search: %s // found: %d\n", remIPClient, search.Filter, len(sr.Entries)) if len(sr.Entries) > 0 { dnList := make(map[string]tList, len(sr.Entries)) for _, entry := range sr.Entries { fType := "" fField := make(map[string]string, len(rconf.WLB_LDAP_ATTR)) for _, attr := range entry.Attributes { for ckl1 := 0; ckl1 < len(rconf.WLB_LDAP_ATTR); ckl1++ { if attr.Name == rconf.WLB_LDAP_ATTR[ckl1][0] { fField[rconf.WLB_LDAP_ATTR[ckl1][1]] = fmt.Sprintf("%s", strings.Join(attr.Values, ",")) // fmt.Printf("Name: %s==%s --> %s = %s\n", attr.Name, rconf.WLB_LDAP_ATTR[ckl1][0], rconf.WLB_LDAP_ATTR[ckl1][1], fField[rconf.WLB_LDAP_ATTR[ckl1][1]]) if rconf.WLB_LDAP_ATTR[ckl1][1] == "ORGName" { fType = "Org" } if rconf.WLB_LDAP_ATTR[ckl1][1] == "USERName" { fType = "User" } } } } getMore(remIPClient, fField, fType, l, dnList, setAdminMode) } t.ExecuteTemplate(w, "index", dnList) } } else { dnList := make(map[string]tList, xGetCkl) for ckl1 = 0; ckl1 < xGetCkl; ckl1++ { // fmt.Printf("GET: %s / %d\n", xGetDN[ckl1], ckl1) search := ldap.NewSearchRequest(xGetDN[ckl1], 0, ldap.NeverDerefAliases, 0, 0, false, "(objectClass=inetOrgPerson)", ldap_Attr, nil) // fmt.Printf("GET: %v\n", search) sr, err := l.Search(search) if err != nil { fmt.Printf(err.Error()) // fmt.Fprintf(w, err.Error()) log.Printf("LDAP::Search() error: %v %v\n", search, err) continue } fType := "User" fField := make(map[string]string, len(rconf.WLB_LDAP_ATTR)) fField["DN"] = xGetDN[ckl1] if len(sr.Entries) > 0 { for _, entry := range sr.Entries { for _, attr := range entry.Attributes { for ckl2 := 0; ckl2 < len(rconf.WLB_LDAP_ATTR); ckl2++ { if attr.Name == rconf.WLB_LDAP_ATTR[ckl2][0] { fField[rconf.WLB_LDAP_ATTR[ckl2][1]] = fmt.Sprintf("%s", strings.Join(attr.Values, ",")) // fmt.Printf("Name: %s==%s --> %s = %s\n", attr.Name, rconf.WLB_LDAP_ATTR[ckl1][0], rconf.WLB_LDAP_ATTR[ckl1][1], fField[rconf.WLB_LDAP_ATTR[ckl1][1]]) } } } } } getMore(remIPClient, fField, fType, l, dnList, setAdminMode) } t.ExecuteTemplate(w, "index", dnList) } t, err = template.ParseFiles("templates/footer.html") if err != nil { fmt.Fprintf(w, err.Error()) log.Println(err.Error()) return } t.ExecuteTemplate(w, "footer", template.FuncMap{"WebBookVersion": pVersion, "xMailBT": rconf.WLB_MailBT, "LineColor": "#EEEEEE"}) }
func getMore(remIPClient string, fField map[string]string, fType string, l *ldap.Conn, dnList map[string]tList, setAdminMode string) { var ( fPath string fURL string fURLName string ckl1, ckl2, ckl3 int ldap_Attr []string aaa_login = string("") aaa_password = string("") aaa_fullname = string("") aaa_role = string("") aaa_cdavmode = int(0) newSABLogin string get_davdn = string("") err error ) dbpg, err := sql.Open("postgres", rconf.PG_DSN) if err != nil { log.Fatalf("PG_INIT::Open() error: %v\n", err) } defer dbpg.Close() if fField["DN"] != "" && (fField["USERName"] != "" || fField["ORGName"] != "") { fPath = fField["DN"] fPath = strings.Replace(strings.ToLower(fPath), ","+strings.ToLower(rconf.LDAP_URL[ldap_count][3]), "", -1) fPath_Split := strings.Split(fPath, ",") fURLName = "" for ckl1 = 0; ckl1 < len(fPath_Split)-1; ckl1++ { fPath_Strip := "" for ckl2 = ckl1 + 1; ckl2 < len(fPath_Split); ckl2++ { fPath_Strip = fmt.Sprintf("%s%s,", fPath_Strip, fPath_Split[ckl2]) } if fType == "User" { fPath_Strip = fmt.Sprintf("%s%s", fPath_Strip, rconf.LDAP_URL[ldap_count][3]) if ckl1 == 0 { fURL = fPath_Strip } // log.Printf("X1: %s", fPath_Strip) subsearch := ldap.NewSearchRequest(fPath_Strip, 0, ldap.NeverDerefAliases, 0, 0, false, rconf.LDAP_URL[ldap_count][4], ldap_Attr, nil) subsr, err := l.Search(subsearch) if err != nil { // fmt.Fprintf(w, err.Error()) log.Printf("LDAP::Search() error: %v\n", err) } // log.Printf("Y1: %s / %s / %d\n", fPath_Strip, rconf.LDAP_URL[ldap_count][4], len(subsr.Entries)) if len(subsr.Entries) > 0 { for _, subentry := range subsr.Entries { for _, subattr := range subentry.Attributes { for ckl3 = 0; ckl3 < len(rconf.WLB_LDAP_ATTR); ckl3++ { if subattr.Name == rconf.WLB_LDAP_ATTR[ckl3][0] { if rconf.WLB_LDAP_ATTR[ckl3][1] == "ORGName" { if ckl1 == 0 { fURLName = fmt.Sprintf("%s", strings.Join(subattr.Values, ",")) } else { fURLName = fmt.Sprintf("%s / %s", strings.Join(subattr.Values, ","), fURLName) } // log.Printf("Z1: %s", fURLName) } } } } } } } } fField["DN"] = strings.Replace(strings.ToLower(fField["DN"]), "/", ",", -1) fmt.Sprintf("/Go%s?dn=%s", fType, fField["DN"]) fField["DN"] = fmt.Sprintf("/Go%s?dn=%s", fType, fField["DN"]) fURL = fmt.Sprintf("/Go%s?dn=%s", fType, fURL) log.Printf("%s <-- %s", remIPClient, fField["DN"]) davDN := "LIST:\n" if setAdminMode == "Yes" { queryx := fmt.Sprintf("select x.dn from aaa_dns as x, aaa_logins as y where y.uid='%s' and y.id=x.userid;", fField["UID"]) //fmt.Printf("%s\n", queryx) rows, err := dbpg.Query(queryx) if err != nil { log.Printf("PG::Query() Select info from aaa_logins: %v\n", err) return } for rows.Next() { rows.Scan(&get_davdn) davDN = fmt.Sprintf("%s%s\n", davDN, get_davdn) } queryx = fmt.Sprintf("select login,password,fullname,role,cdavprefix from aaa_logins where uid='%s';", fField["UID"]) //fmt.Printf("%s\n", queryx) rows, err = dbpg.Query(queryx) if err != nil { log.Printf("PG::Query() Select info from aaa_logins: %v\n", err) return } rows.Next() rows.Scan(&aaa_login, &aaa_password, &aaa_fullname, &aaa_role, &aaa_cdavmode) if len(aaa_password) > 0 { aaa_password = "******" } else { aaa_password = "******" } xt, _ := strconv.Atoi(aaa_role) switch xt { case roleAdmin: aaa_role = "Administrator" case roleUser: aaa_role = "User" default: aaa_role = "Guest" } if len(fField["ADLogin"]) < 2 || len(fField["ADDomain"]) < 2 { newSABLogin = fField["Mail"] } else { newSABLogin = fmt.Sprintf("%s@%s", fField["ADLogin"], fField["ADDomain"]) } } dnList[fField["DN"]] = tList{URL: fURL, URLName: fURLName, ORGName: fField["ORGName"], USERName: fField["USERName"], FullName: fField["FullName"], Position: fField["Position"], PhoneInt: fField["PhoneInt"], Mobile: fField["Mobile"], PhoneExt: fField["PhoneExt"], Mail: fField["Mail"], ADLogin: fField["ADLogin"], ADDomain: fField["ADDomain"], AdminMode: setAdminMode, UID: fField["UID"], AAALogin: aaa_login, AAAPassword: aaa_password, AAAFullName: aaa_fullname, AAARole: aaa_role, NewSABLogin: newSABLogin, DavDN: davDN, AAACDMode: cDavMode[aaa_cdavmode], AAACDModeI: aaa_cdavmode} //fmt.Printf("%v\n", dnList) } }
/* * getLdapGroups queries LDAP and returns a slice describing the set of groups the authenticated user is a member of. * * The search query is constructed according to cfg.GroupFilter, and run in context of cfg.GroupDN. * Groups will be resolved from the query results by following the attribute defined in cfg.GroupAttr. * * cfg.GroupFilter is a go template and is compiled with the following context: [UserDN, Username] * UserDN - The DN of the authenticated user * Username - The Username of the authenticated user * * Example: * cfg.GroupFilter = "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))" * cfg.GroupDN = "OU=Groups,DC=myorg,DC=com" * cfg.GroupAttr = "cn" * * NOTE - If cfg.GroupFilter is empty, no query is performed and an empty result slice is returned. * */ func (b *backend) getLdapGroups(cfg *ConfigEntry, c *ldap.Conn, userDN string, username string) ([]string, error) { // retrieve the groups in a string/bool map as a structure to avoid duplicates inside ldapMap := make(map[string]bool) if cfg.GroupFilter == "" { b.Logger().Warn("auth/ldap: GroupFilter is empty, will not query server") return make([]string, 0), nil } if cfg.GroupDN == "" { b.Logger().Warn("auth/ldap: GroupDN is empty, will not query server") return make([]string, 0), nil } // If groupfilter was defined, resolve it as a Go template and use the query for // returning the user's groups if b.Logger().IsDebug() { b.Logger().Debug("auth/ldap: Compiling group filter", "group_filter", cfg.GroupFilter) } // Parse the configuration as a template. // Example template "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))" t, err := template.New("queryTemplate").Parse(cfg.GroupFilter) if err != nil { return nil, fmt.Errorf("LDAP search failed due to template compilation error: %v", err) } // Build context to pass to template - we will be exposing UserDn and Username. context := struct { UserDN string Username string }{ ldap.EscapeFilter(userDN), ldap.EscapeFilter(username), } var renderedQuery bytes.Buffer t.Execute(&renderedQuery, context) if b.Logger().IsDebug() { b.Logger().Debug("auth/ldap: Searching", "groupdn", cfg.GroupDN, "rendered_query", renderedQuery.String()) } result, err := c.Search(&ldap.SearchRequest{ BaseDN: cfg.GroupDN, Scope: 2, // subtree Filter: renderedQuery.String(), Attributes: []string{ cfg.GroupAttr, }, }) if err != nil { return nil, fmt.Errorf("LDAP search failed: %v", err) } for _, e := range result.Entries { dn, err := ldap.ParseDN(e.DN) if err != nil || len(dn.RDNs) == 0 { continue } // Enumerate attributes of each result, parse out CN and add as group values := e.GetAttributeValues(cfg.GroupAttr) if len(values) > 0 { for _, val := range values { groupCN := b.getCN(val) ldapMap[groupCN] = true } } else { // If groupattr didn't resolve, use self (enumerating group objects) groupCN := b.getCN(e.DN) ldapMap[groupCN] = true } } ldapGroups := make([]string, 0, len(ldapMap)) for key, _ := range ldapMap { ldapGroups = append(ldapGroups, key) } return ldapGroups, nil }