diff --git a/registry/api/v2/names.go b/registry/api/v2/names.go index 14b7ea60a..5f340793c 100644 --- a/registry/api/v2/names.go +++ b/registry/api/v2/names.go @@ -15,10 +15,23 @@ const ( RepositoryNameTotalLengthMax = 255 ) +// domainLabelRegexp represents the following RFC-2396 BNF construct: +// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum +var domainLabelRegexp = regexp.MustCompile(`[a-z0-9](?:-*[a-z0-9])*`) + // RepositoryNameComponentRegexp restricts registry path component names to -// start with at least one letter or number, with following parts able to -// be separated by one period, dash or underscore. -var RepositoryNameComponentRegexp = regexp.MustCompile(`[a-z0-9]+(?:[._-][a-z0-9]+)*`) +// the allow valid hostnames according to: https://www.ietf.org/rfc/rfc2396.txt +// with the following differences: +// 1) It DOES NOT allow for fully-qualified domain names, which include a +// trailing '.', e.g. "google.com." +// 2) It DOES NOT restrict 'top-level' domain labels to start with just alpha +// characters. +// 3) It DOES allow for underscores to appear in the same situations as dots. +// +// RFC-2396 uses the BNF construct: +// hostname = *( domainlabel "." ) toplabel [ "." ] +var RepositoryNameComponentRegexp = regexp.MustCompile( + domainLabelRegexp.String() + `(?:[._]` + domainLabelRegexp.String() + `)*`) // RepositoryNameComponentAnchoredRegexp is the version of // RepositoryNameComponentRegexp which must completely match the content diff --git a/registry/api/v2/names_test.go b/registry/api/v2/names_test.go index 656ae8466..f4daf2e7f 100644 --- a/registry/api/v2/names_test.go +++ b/registry/api/v2/names_test.go @@ -164,22 +164,47 @@ var ( err: ErrRepositoryNameComponentInvalid, invalid: true, }, + { + input: "do__cker/docker", + err: ErrRepositoryNameComponentInvalid, + invalid: true, + }, + { + input: "docker./docker", + err: ErrRepositoryNameComponentInvalid, + invalid: true, + }, + { + input: ".docker/docker", + err: ErrRepositoryNameComponentInvalid, + invalid: true, + }, + { + input: "do..cker/docker", + err: ErrRepositoryNameComponentInvalid, + invalid: true, + }, + { + input: "docker-/docker", + err: ErrRepositoryNameComponentInvalid, + invalid: true, + }, + { + input: "-docker/docker", + err: ErrRepositoryNameComponentInvalid, + invalid: true, + }, { input: "b.gcr.io/test.example.com/my-app", // embedded domain component }, - // TODO(stevvooe): The following is a punycode domain name that we may - // want to allow in the future. Currently, this is not allowed but we - // may want to change this in the future. Adding this here as invalid - // for the time being. { - input: "xn--n3h.com/myimage", // http://☃.com in punycode - err: ErrRepositoryNameComponentInvalid, - invalid: true, + input: "xn--n3h.com/myimage", // http://☃.com in punycode }, { - input: "xn--7o8h.com/myimage", // http://🐳.com in punycode - err: ErrRepositoryNameComponentInvalid, - invalid: true, + input: "xn--7o8h.com/myimage", // http://🐳.com in punycode + }, + { + input: "registry.io/foo/project--id.module--name.ver---sion--name", // image with hostname }, } )