// Package ldaputil normalizes LDAP server addresses supplied by administrators. package ldaputil import ( "fmt" "net" "net/url" "strings" ) // DialURL accepts an IP address or domain name, with an optional port. Bare // addresses use LDAPS on port 636. Existing ldap:// and ldaps:// values remain // supported for backward compatibility. func DialURL(address string) (string, error) { address = strings.TrimSpace(address) if address == "" { return "", fmt.Errorf("LDAP 服务器地址不能为空") } if strings.Contains(address, "://") { u, err := url.Parse(address) if err != nil || (u.Scheme != "ldap" && u.Scheme != "ldaps") || u.Host == "" || u.Path != "" || u.RawQuery != "" || u.Fragment != "" { return "", fmt.Errorf("LDAP 服务器地址格式无效") } port := "389" if u.Scheme == "ldaps" { port = "636" } host, err := withDefaultPort(u.Host, port) if err != nil { return "", err } u.Host = host return u.String(), nil } host, err := withDefaultPort(address, "636") if err != nil { return "", err } return "ldaps://" + host, nil } func withDefaultPort(address, defaultPort string) (string, error) { if strings.ContainsAny(address, " \t\r\n/?#@") { return "", fmt.Errorf("LDAP 服务器地址格式无效") } if host, port, err := net.SplitHostPort(address); err == nil { if host == "" || port == "" { return "", fmt.Errorf("LDAP 服务器地址格式无效") } return address, nil } host := strings.TrimSuffix(strings.TrimPrefix(address, "["), "]") if host == "" || (strings.Contains(host, ":") && net.ParseIP(host) == nil) { return "", fmt.Errorf("LDAP 服务器地址格式无效") } return net.JoinHostPort(host, defaultPort), nil } // Hostname returns the hostname or IP for TLS ServerName selection. func Hostname(dialURL string) string { u, err := url.Parse(dialURL) if err != nil { return "" } return u.Hostname() }