mirror of
https://github.com/valyala/fasthttp.git
synced 2026-06-14 15:56:44 +03:00
Fix username:password@ validation in urls (#2080)
This commit is contained in:
@@ -298,8 +298,11 @@ func (u *URI) parse(host, uri []byte, isTLS bool) error {
|
||||
u.SetSchemeBytes(strHTTPS)
|
||||
}
|
||||
|
||||
if n := bytes.IndexByte(host, '@'); n >= 0 {
|
||||
if n := bytes.LastIndexByte(host, '@'); n >= 0 {
|
||||
auth := host[:n]
|
||||
if !validUserinfo(auth) {
|
||||
return ErrorInvalidURI
|
||||
}
|
||||
host = host[n+1:]
|
||||
|
||||
if n := bytes.IndexByte(auth, ':'); n >= 0 {
|
||||
@@ -356,6 +359,26 @@ func (u *URI) parse(host, uri []byte, isTLS bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validUserinfo(userinfo []byte) bool {
|
||||
for _, c := range userinfo {
|
||||
switch {
|
||||
case 'A' <= c && c <= 'Z':
|
||||
continue
|
||||
case 'a' <= c && c <= 'z':
|
||||
continue
|
||||
case '0' <= c && c <= '9':
|
||||
continue
|
||||
}
|
||||
switch c {
|
||||
case '-', '.', '_', ':', '~', '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=', '%', '@':
|
||||
continue
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// parseHost parses host as an authority without user
|
||||
// information. That is, as host[:port].
|
||||
//
|
||||
|
||||
+38
@@ -151,6 +151,44 @@ func testURIUpdate(t *testing.T, base, update, result string) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestURIRejectInvalidUserinfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
bad := []string{
|
||||
"http://[normal.com@]vulndetector.com/",
|
||||
"http://normal.com[user@vulndetector].com/",
|
||||
"http://normal.com[@]vulndetector.com/",
|
||||
}
|
||||
|
||||
for _, raw := range bad {
|
||||
var u URI
|
||||
if err := u.Parse(nil, []byte(raw)); err == nil {
|
||||
t.Fatalf("expected error parsing %q", raw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestURIAllowAtInUserinfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var u URI
|
||||
if err := u.Parse(nil, []byte("http://user:p@ss@example.com/")); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if got := string(u.Host()); got != "example.com" {
|
||||
t.Fatalf("unexpected host %q", got)
|
||||
}
|
||||
|
||||
if got := string(u.Username()); got != "user" {
|
||||
t.Fatalf("unexpected username %q", got)
|
||||
}
|
||||
|
||||
if got := string(u.Password()); got != "p@ss" {
|
||||
t.Fatalf("unexpected password %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestURIPathNormalize(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.SkipNow()
|
||||
|
||||
Reference in New Issue
Block a user