예제 #1
0
func initLDAPConnector() string {
	var (
		ckl = int(0)
		err error
		l   *ldap.Conn
	)

	for {
		if ckl > 9 {
			log.Printf("LDAP Init SRV ***** Error connect to all LDAP servers...")
			return "error"
		}

		ldap_count++
		if ldap_count > len(rconf.LDAP_URL)-1 {
			ldap_count = 0
		}

		log.Printf("LDAP Init SRV ***** Trying connect to server %d of %d: %s", ldap_count+1, len(rconf.LDAP_URL), rconf.LDAP_URL[ldap_count][0])
		l, err = ldap.Dial("tcp", rconf.LDAP_URL[ldap_count][0])
		if err != nil {
			continue
		}

		defer l.Close()

		break

		ckl++
	}
	return rconf.LDAP_URL[ldap_count][0]
}
예제 #2
0
/*
 * 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
}
예제 #3
0
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
}
예제 #4
0
// Bind binds to a given LDAP connection if a bind DN and password were given.
// Bind returns whether a bind occurred and whether an error occurred
func (l *LDAPClientConfig) Bind(connection *ldap.Conn) (bound bool, err error) {
	if len(l.BindDN) > 0 {
		if err := connection.Bind(l.BindDN, l.BindPassword); err != nil {
			return false, err
		} else {
			return true, nil
		}
	}

	return false, nil
}
예제 #5
0
파일: path_config.go 프로젝트: naunga/vault
func (c *ConfigEntry) DialLDAP() (*ldap.Conn, error) {

	u, err := url.Parse(c.Url)
	if err != nil {
		return nil, err
	}
	host, port, err := net.SplitHostPort(u.Host)
	if err != nil {
		host = u.Host
	}

	var conn *ldap.Conn
	var tlsConfig *tls.Config
	switch u.Scheme {
	case "ldap":
		if port == "" {
			port = "389"
		}
		conn, err = ldap.Dial("tcp", host+":"+port)
		if err != nil {
			break
		}
		if conn == nil {
			err = fmt.Errorf("empty connection after dialing")
			break
		}
		if c.StartTLS {
			tlsConfig, err = c.GetTLSConfig(host)
			if err != nil {
				break
			}
			err = conn.StartTLS(tlsConfig)
		}
	case "ldaps":
		if port == "" {
			port = "636"
		}
		tlsConfig, err = c.GetTLSConfig(host)
		if err != nil {
			break
		}
		conn, err = ldap.DialTLS("tcp", host+":"+port, tlsConfig)
	default:
		return nil, fmt.Errorf("invalid LDAP scheme")
	}
	if err != nil {
		return nil, fmt.Errorf("cannot connect to LDAP: %v", err)
	}

	return conn, nil
}
예제 #6
0
func (la *LDAPAuth) bindReadOnlyUser(l *ldap.Conn) error {
	if la.config.BindDN != "" {
		password, err := ioutil.ReadFile(la.config.BindPasswordFile)
		if err != nil {
			return err
		}
		glog.V(2).Infof("Bind read-only user %s", string(password))
		err = l.Bind(la.config.BindDN, string(password))
		if err != nil {
			return err
		}
	}
	return nil
}
예제 #7
0
파일: sync.go 프로젝트: whitby/vmanage
// modify enables or disables an LDAP account
func modify(l *ldap.Conn, entry *ldap.Entry, action string) error {
	useraccountcontrol := entry.Attributes[1].Values[0]
	if useraccountcontrol != action {
		modify := ldap.NewModifyRequest(entry.DN)
		modify.Replace("useraccountcontrol", []string{action})
		if err := l.Modify(modify); err != nil {
			log.Println("ERROR: %s\n", err.Error())
			return err
		}
		cn := entry.Attributes[0].Values[0]
		logMod(cn, action)
	}
	return nil
}
예제 #8
0
func (la *LDAPAuth) bindReadOnlyUser(l *ldap.Conn) error {
	if la.config.BindDN != "" {
		password, err := ioutil.ReadFile(la.config.BindPasswordFile)
		if err != nil {
			return err
		}
		password_str := strings.TrimSpace(string(password))
		glog.V(2).Infof("Bind read-only user (DN = %s)", la.config.BindDN)
		err = l.Bind(la.config.BindDN, password_str)
		if err != nil {
			return err
		}
	}
	return nil
}
예제 #9
0
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")
}
예제 #10
0
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
}
예제 #11
0
func (la *LDAPAuth) ldapConnection() (*ldap.Conn, error) {
	var l *ldap.Conn
	var err error
	if la.config.TLS == "" || la.config.TLS == "none" || la.config.TLS == "starttls" {
		glog.V(2).Infof("Dial: starting...%s", la.config.Addr)
		l, err = ldap.Dial("tcp", fmt.Sprintf("%s", la.config.Addr))
		if err == nil && la.config.TLS == "starttls" {
			glog.V(2).Infof("StartTLS...")
			if tlserr := l.StartTLS(&tls.Config{InsecureSkipVerify: la.config.InsecureTLSSkipVerify}); tlserr != nil {
				return nil, tlserr
			}
		}
	} else if la.config.TLS == "always" {
		glog.V(2).Infof("DialTLS: starting...%s", la.config.Addr)
		l, err = ldap.DialTLS("tcp", fmt.Sprintf("%s", la.config.Addr), &tls.Config{InsecureSkipVerify: la.config.InsecureTLSSkipVerify})
	}
	if err != nil {
		return nil, err
	}
	return l, nil
}
예제 #12
0
파일: sync.go 프로젝트: whitby/vmanage
// 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
}
예제 #13
0
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")
}
예제 #14
0
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))
}
예제 #15
0
//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
}
예제 #16
0
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"})
}
예제 #17
0
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
}
예제 #18
0
func davDNHandler(w http.ResponseWriter, r *http.Request) {
	var (
		uid       string
		uAction   string
		uFullname string
		queryx    string
		err       error
		l         *ldap.Conn
		xFRColor  = string("#FFFFFF")
		xBGColor  = string("#FFFFFF")
	)

	_, userperm := CheckUserSession(r, w)

	switch userperm {
	case roleAdmin:
		//xFRColor = "#FF0000"
		//xBGColor = "#FFFFFF"
	default:
		return
	}

	SABModules.Log_ON(&rconf)
	defer SABModules.Log_OFF()

	remIPClient := getIPAddress(r)

	uid = r.FormValue("uid")
	uAction = r.FormValue("action")

	dbpg, err := sql.Open("postgres", rconf.PG_DSN)
	if err != nil {
		log.Fatalf("PG_INIT::Open() error: %v\n", err)
	}

	defer dbpg.Close()

	queryx = fmt.Sprintf("select fullname from ldapx_persons where uid='%s';", uid)
	rows, err := dbpg.Query(queryx)
	if err != nil {
		log.Printf("%s\n", queryx)
		log.Printf("PG::Query() Get User Name for UID: %v\n", err)
		return
	}
	rows.Next()
	rows.Scan(&uFullname)

	if uAction == "SaveDN" && len(uFullname) > 0 {

		queryx = fmt.Sprintf("select id from aaa_logins where uid='%s';", uid)
		rows, err := dbpg.Query(queryx)
		if err != nil {
			log.Printf("%s\n", queryx)
			log.Printf("PG::Query() Get User ID for UID: %v\n", err)
			return
		}

		xId := 0
		rows.Next()
		rows.Scan(&xId)

		queryx = fmt.Sprintf("delete from aaa_dns where userid=%d;", xId)
		_, err = dbpg.Query(queryx)
		if err != nil {
			log.Printf("%s\n", queryx)
			log.Printf("PG::Query() Delete DNs for UID: %v\n", err)
			return
		}
		time.Sleep(time.Second)
		r.ParseForm()
		for parName := range r.Form {
			if strings.Contains(parName, "SaveDN") {

				queryx = fmt.Sprintf("insert into aaa_dns (userid,dn) select %d, dn from ldap_entries where uid='%s';", xId, r.FormValue(parName))
				//fmt.Printf("%s\n", queryx)
				_, err = dbpg.Query(queryx)
				if err != nil {
					log.Printf("%s\n", queryx)
					log.Printf("PG::Query() Insert DNs for UID: %v\n", err)
					return
				}
				//fmt.Fprintf(w, "%v\n", r.FormValue(parName))
			}
		}

		queryx = fmt.Sprintf("insert into aaa_dav_ntu (userid,updtime) select %d,%v where not exists (select userid from aaa_dav_ntu where userid=%d); update aaa_dav_ntu set updtime=%v where userid=%d;", xId, time.Now().Unix(), xId, time.Now().Unix(), xId)
		//fmt.Printf("%s\n", queryx)
		_, err = dbpg.Query(queryx)
		if err != nil {
			log.Printf("%s\n", queryx)
			log.Printf("PG::Query() Update NTU table: %v\n", err)
			return
		}

		log.Printf("%s --> Set DavDN List for %s", remIPClient, uFullname)

		time.Sleep(time.Second)
		fmt.Fprintf(w, "<script type=\"text/javascript\">window.close();</script>")

	} else {

		log.Printf("%s <-- Get DavDN List for %s", remIPClient, uFullname)

		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, "TREEOn": "Yes"})

		t, err = template.ParseFiles("templates/tree-00.html")
		if err != nil {
			fmt.Fprintf(w, err.Error())
			log.Println(err.Error())
			return
		}
		t.ExecuteTemplate(w, "tree-00", template.FuncMap{"UID": uid})

		queryx = fmt.Sprintf("select distinct uid from ldap_entries where lower(dn)=lower('%s') limit 1;", rconf.LDAP_URL[ldap_count][3])
		rows, err := dbpg.Query(queryx)
		if err != nil {
			log.Printf("%s\n", queryx)
			log.Printf("PG::Query() Get UID for DN: %v\n", err)
			return
		}
		rows.Next()
		uidDN := ""
		rows.Scan(&uidDN)

		queryx = fmt.Sprintf("select z.uid from aaa_dns as x, aaa_logins as y, ldap_entries as z where x.userid=y.id and x.dn=z.dn and y.uid='%s';", uid)
		//fmt.Printf("%s\n", queryx)
		rows, err = dbpg.Query(queryx)
		if err != nil {
			log.Printf("%s\n", queryx)
			log.Printf("PG::Query() Get UID for DN: %v\n", err)
			return
		}

		dnList := make([]string, 0)

		x := ""
		for rows.Next() {
			rows.Scan(&x)
			dnList = append(dnList, x)
			//fmt.Printf("%s\n", x)
		}

		//fmt.Printf("%v\n", dnList)

		getLDAPdnList(l, uidDN, 0, rconf.WLB_DavDNTreeDepLev, w, r, dnList)

		t, err = template.ParseFiles("templates/tree-10.html")
		if err != nil {
			fmt.Fprintf(w, err.Error())
			log.Println(err.Error())
			return
		}
		t.ExecuteTemplate(w, "tree-10", nil)

	}
}
예제 #19
0
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)
	}
}
예제 #20
0
/*
 * 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
}