1
0
mirror of https://github.com/docker/docker-credential-helpers.git synced 2026-06-14 08:21:28 +05:30

Fix storing URLs without scheme (#72)

* Fix storing URLs without scheme

If secrets are stored without specifying a scheme
(https://), the keychain-helper would interpret the
hostname as _path_, causing lookup of secrets to fail.

This patch makes sure that a scheme is added (if missing).

If no scheme is specified, https:// is used as a default.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

* Have pre go1.8 compiler able to compile

Signed-off-by: Tibor Vass <teabee89@gmail.com>

* Fix URL parsing with port and no scheme

Signed-off-by: Nassim 'Nass' Eddequiouaq <eddequiouaq.nassim@gmail.com>

* Improve parseURL comment

Signed-off-by: Nassim 'Nass' Eddequiouaq <eddequiouaq.nassim@gmail.com>
This commit is contained in:
Sebastiaan van Stijn
2017-06-15 10:58:17 +02:00
committed by Nassim Eddequiouaq
parent 94be56b6f4
commit e1d4c012bc
7 changed files with 289 additions and 22 deletions
+38 -12
View File
@@ -135,30 +135,27 @@ func (h Osxkeychain) List() (map[string]string, error) {
}
func splitServer(serverURL string) (*C.struct_Server, error) {
u, err := url.Parse(serverURL)
u, err := parseURL(serverURL)
if err != nil {
return nil, err
}
hostAndPort := strings.Split(u.Host, ":")
host := hostAndPort[0]
proto := C.kSecProtocolTypeHTTPS
if u.Scheme == "http" {
proto = C.kSecProtocolTypeHTTP
}
var port int
if len(hostAndPort) == 2 {
p, err := strconv.Atoi(hostAndPort[1])
p := getPort(u)
if p != "" {
port, err = strconv.Atoi(p)
if err != nil {
return nil, err
}
port = p
}
proto := C.kSecProtocolTypeHTTPS
if u.Scheme != "https" {
proto = C.kSecProtocolTypeHTTP
}
return &C.struct_Server{
proto: C.SecProtocolType(proto),
host: C.CString(host),
host: C.CString(getHostname(u)),
port: C.uint(port),
path: C.CString(u.Path),
}, nil
@@ -168,3 +165,32 @@ func freeServer(s *C.struct_Server) {
C.free(unsafe.Pointer(s.host))
C.free(unsafe.Pointer(s.path))
}
// parseURL parses and validates a given serverURL to an url.URL, and
// returns an error if validation failed. Querystring parameters are
// omitted in the resulting URL, because they are not used in the helper.
//
// If serverURL does not have a valid scheme, `//` is used as scheme
// before parsing. This prevents the hostname being used as path,
// and the credentials being stored without host.
func parseURL(serverURL string) (*url.URL, error) {
// Check if serverURL has a scheme, otherwise add `//` as scheme.
if !strings.Contains(serverURL, "://") && !strings.HasPrefix(serverURL, "//") {
serverURL = "//" + serverURL
}
u, err := url.Parse(serverURL)
if err != nil {
return nil, err
}
if u.Scheme != "" && u.Scheme != "https" && u.Scheme != "http" {
return nil, errors.New("unsupported scheme: " + u.Scheme)
}
if getHostname(u) == "" {
return nil, errors.New("no hostname in URL")
}
u.RawQuery = ""
return u, nil
}