Vault Automation 0c6c13dd38
license: update headers to IBM Corp. (#10229) (#10233)
* license: update headers to IBM Corp.
* `make proto`
* update offset because source file changed

Signed-off-by: Ryan Cragun <me@ryan.ec>
Co-authored-by: Ryan Cragun <me@ryan.ec>
2025-10-21 15:20:20 -06:00

110 lines
2.8 KiB
Go

// Copyright IBM Corp. 2016, 2025
// SPDX-License-Identifier: BUSL-1.1
package configutil
import (
"net"
"net/url"
"strings"
)
// NormalizeAddr takes a string of a Host, Host:Port, URL, or Destination
// Address and returns a copy where any IP addresses have been normalized to be
// conformant with RFC 5942 §4. If the input string does not match any of the
// supported syntaxes, or the "host" section is not an IP address, the input
// will be returned unchanged. Supported syntaxes are:
//
// Host host or [host]
// Host:Port host:port or [host]:port
// URL scheme://user@host/path?query#frag or scheme://user@[host]/path?query#frag
// Destination Address user@host:port or user@[host]:port
//
// See:
//
// https://rfc-editor.org/rfc/rfc3986.html
// https://rfc-editor.org/rfc/rfc5942.html
// https://rfc-editor.org/rfc/rfc5952.html
func NormalizeAddr(addr string) string {
if addr == "" {
return ""
}
// Host
ip := net.ParseIP(addr)
if ip != nil {
// net.IP.String() is RFC 5942 §4 compliant
return ip.String()
}
// [Host]
if strings.HasPrefix(addr, "[") && strings.HasSuffix(addr, "]") {
if len(addr) < 3 {
return addr
}
// If we've been given a bracketed IP address, return the address
// normalized without brackets.
ip := net.ParseIP(addr[1 : len(addr)-1])
if ip != nil {
return ip.String()
}
// Our input is not a valid schema.
return addr
}
// Host:Port
host, port, err := net.SplitHostPort(addr)
if err == nil {
ip := net.ParseIP(host)
if ip == nil {
// Our host isn't an IP address so we can return it unchanged
return addr
}
// net.JoinHostPort handles bracketing for RFC 5952 §6
return net.JoinHostPort(ip.String(), port)
}
// URL
u, err := url.Parse(addr)
if err == nil {
uhost := u.Hostname()
ip := net.ParseIP(uhost)
if ip == nil {
// Our URL doesn't contain an IP address so we can return our input unchanged.
return addr
} else {
uhost = ip.String()
}
if uport := u.Port(); uport != "" {
uhost = net.JoinHostPort(uhost, uport)
} else {
if !strings.HasPrefix(uhost, "[") && !strings.HasSuffix(uhost, "]") {
// Ensure the IPv6 URL host is bracketed post-normalization.
// When*url.URL.String() reassembles the URL it will not consider
// whether or not the *url.URL.Host is RFC 5952 §6 and RFC 3986 §3.2.2
// conformant.
uhost = "[" + uhost + "]"
}
}
u.Host = uhost
return u.String()
}
// Destination Address
if idx := strings.LastIndex(addr, "@"); idx > 0 {
if idx+1 > len(addr) {
return addr
}
return addr[:idx+1] + NormalizeAddr(addr[idx+1:])
}
// Our input did not match our supported schemas. Return it unchanged.
return addr
}