aboutsummaryrefslogtreecommitdiffstats
path: root/routers
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2021-03-15 21:52:11 +0000
committerGitHub <noreply@github.com>2021-03-15 17:52:11 -0400
commit6e423d5573c20b78d6e21cb044e8f4d5de5b288a (patch)
tree61d2e282bc652b8254271fdd9e19b87a386b5dc7 /routers
parentf268b4896b1030761b28f1f8923d77d87adb8f0b (diff)
downloadgitea-6e423d5573c20b78d6e21cb044e8f4d5de5b288a.tar.gz
gitea-6e423d5573c20b78d6e21cb044e8f4d5de5b288a.zip
Ensure validation occurs on clone addresses too (#14994)
* Ensure validation occurs on clone addresses too Fix #14984 Signed-off-by: Andrew Thornton <art27@cantab.net> * fix lint Signed-off-by: Andrew Thornton <art27@cantab.net> * fix test Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix api tests Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Diffstat (limited to 'routers')
-rw-r--r--routers/api/v1/repo/migrate.go17
-rw-r--r--routers/repo/migrate.go26
-rw-r--r--routers/repo/setting.go69
3 files changed, 60 insertions, 52 deletions
diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go
index 61cd12b991..1eefa78d57 100644
--- a/routers/api/v1/repo/migrate.go
+++ b/routers/api/v1/repo/migrate.go
@@ -96,15 +96,24 @@ func Migrate(ctx *context.APIContext) {
}
}
- remoteAddr, err := auth.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword, ctx.User)
+ remoteAddr, err := auth.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
+ if err == nil {
+ err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.User)
+ }
if err != nil {
if models.IsErrInvalidCloneAddr(err) {
- addrErr := err.(models.ErrInvalidCloneAddr)
+ addrErr := err.(*models.ErrInvalidCloneAddr)
switch {
case addrErr.IsURLError:
ctx.Error(http.StatusUnprocessableEntity, "", err)
case addrErr.IsPermissionDenied:
- ctx.Error(http.StatusUnprocessableEntity, "", "You are not allowed to import local repositories.")
+ if addrErr.LocalPath {
+ ctx.Error(http.StatusUnprocessableEntity, "", "You are not allowed to import local repositories.")
+ } else if len(addrErr.PrivateNet) == 0 {
+ ctx.Error(http.StatusUnprocessableEntity, "", "You are not allowed to import from blocked hosts.")
+ } else {
+ ctx.Error(http.StatusUnprocessableEntity, "", "You are not allowed to import from private IPs.")
+ }
case addrErr.IsInvalidPath:
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid local path, it does not exist or not a directory.")
default:
@@ -219,7 +228,7 @@ func handleMigrateError(ctx *context.APIContext, repoOwner *models.User, remoteA
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("The username '%s' contains invalid characters.", err.(models.ErrNameCharsNotAllowed).Name))
case models.IsErrNamePatternNotAllowed(err):
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("The pattern '%s' is not allowed in a username.", err.(models.ErrNamePatternNotAllowed).Pattern))
- case models.IsErrMigrationNotAllowed(err):
+ case models.IsErrInvalidCloneAddr(err):
ctx.Error(http.StatusUnprocessableEntity, "", err)
case base.IsErrNotSupported(err):
ctx.Error(http.StatusUnprocessableEntity, "", err)
diff --git a/routers/repo/migrate.go b/routers/repo/migrate.go
index e1ff8e1360..fbc4288c1e 100644
--- a/routers/repo/migrate.go
+++ b/routers/repo/migrate.go
@@ -13,6 +13,7 @@ import (
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
auth "code.gitea.io/gitea/modules/forms"
+ "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/migrations"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
@@ -97,7 +98,7 @@ func handleMigrateError(ctx *context.Context, owner *models.User, err error, nam
ctx.Data["Err_RepoName"] = true
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tpl, form)
default:
- remoteAddr, _ := auth.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword, owner)
+ remoteAddr, _ := auth.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
err = util.URLSanitizedError(err, remoteAddr)
if strings.Contains(err.Error(), "Authentication failed") ||
strings.Contains(err.Error(), "Bad credentials") ||
@@ -138,23 +139,36 @@ func MigratePost(ctx *context.Context) {
return
}
- remoteAddr, err := auth.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword, ctx.User)
+ remoteAddr, err := auth.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
+ if err == nil {
+ err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.User)
+ }
if err != nil {
if models.IsErrInvalidCloneAddr(err) {
ctx.Data["Err_CloneAddr"] = true
- addrErr := err.(models.ErrInvalidCloneAddr)
+ addrErr := err.(*models.ErrInvalidCloneAddr)
switch {
+ case addrErr.IsProtocolInvalid:
+ ctx.RenderWithErr(ctx.Tr("repo.mirror_address_protocol_invalid"), tpl, &form)
case addrErr.IsURLError:
ctx.RenderWithErr(ctx.Tr("form.url_error"), tpl, &form)
case addrErr.IsPermissionDenied:
- ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied"), tpl, &form)
+ if len(addrErr.PrivateNet) == 0 {
+ ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied_private_ip"), tpl, &form)
+ } else if !addrErr.LocalPath {
+ ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied_blocked"), tpl, &form)
+ } else {
+ ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied"), tpl, &form)
+ }
case addrErr.IsInvalidPath:
ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), tpl, &form)
default:
- ctx.ServerError("Unknown error", err)
+ log.Error("Error whilst updating url: %v", err)
+ ctx.RenderWithErr(ctx.Tr("form.url_error"), tpl, &form)
}
} else {
- ctx.ServerError("ParseRemoteAddr", err)
+ log.Error("Error whilst updating url: %v", err)
+ ctx.RenderWithErr(ctx.Tr("form.url_error"), tpl, &form)
}
return
}
diff --git a/routers/repo/setting.go b/routers/repo/setting.go
index 692d65b44c..6b31ac4c71 100644
--- a/routers/repo/setting.go
+++ b/routers/repo/setting.go
@@ -9,8 +9,6 @@ import (
"errors"
"fmt"
"io/ioutil"
- "net/url"
- "regexp"
"strings"
"time"
@@ -20,6 +18,7 @@ import (
auth "code.gitea.io/gitea/modules/forms"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/migrations"
"code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
@@ -30,8 +29,6 @@ import (
"code.gitea.io/gitea/services/mailer"
mirror_service "code.gitea.io/gitea/services/mirror"
repo_service "code.gitea.io/gitea/services/repository"
-
- "mvdan.cc/xurls/v2"
)
const (
@@ -44,8 +41,6 @@ const (
tplProtectedBranch base.TplName = "repo/settings/protected_branch"
)
-var validFormAddress *regexp.Regexp
-
// Settings show a repository's settings page
func Settings(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.settings")
@@ -169,40 +164,38 @@ func SettingsPost(ctx *context.Context) {
}
}
- // Validate the form.MirrorAddress
- u, err := url.Parse(form.MirrorAddress)
- if err != nil {
- ctx.Data["Err_MirrorAddress"] = true
- ctx.RenderWithErr(ctx.Tr("repo.mirror_address_url_invalid"), tplSettingsOptions, &form)
- return
+ address, err := auth.ParseRemoteAddr(form.MirrorAddress, form.MirrorUsername, form.MirrorPassword)
+ if err == nil {
+ err = migrations.IsMigrateURLAllowed(address, ctx.User)
}
-
- if u.Opaque != "" || !(u.Scheme == "http" || u.Scheme == "https" || u.Scheme == "git") {
- ctx.Data["Err_MirrorAddress"] = true
- ctx.RenderWithErr(ctx.Tr("repo.mirror_address_protocol_invalid"), tplSettingsOptions, &form)
- return
- }
-
- if form.MirrorUsername != "" || form.MirrorPassword != "" {
- u.User = url.UserPassword(form.MirrorUsername, form.MirrorPassword)
- }
-
- // Now use xurls
- address := validFormAddress.FindString(form.MirrorAddress)
- if address != form.MirrorAddress && form.MirrorAddress != "" {
- ctx.Data["Err_MirrorAddress"] = true
- ctx.RenderWithErr(ctx.Tr("repo.mirror_address_url_invalid"), tplSettingsOptions, &form)
- return
- }
-
- if u.EscapedPath() == "" || u.Host == "" || !u.IsAbs() {
+ if err != nil {
+ if models.IsErrInvalidCloneAddr(err) {
+ ctx.Data["Err_MirrorAddress"] = true
+ addrErr := err.(*models.ErrInvalidCloneAddr)
+ switch {
+ case addrErr.IsProtocolInvalid:
+ ctx.RenderWithErr(ctx.Tr("repo.mirror_address_protocol_invalid"), tplSettingsOptions, &form)
+ case addrErr.IsURLError:
+ ctx.RenderWithErr(ctx.Tr("form.url_error"), tplSettingsOptions, &form)
+ case addrErr.IsPermissionDenied:
+ if len(addrErr.PrivateNet) == 0 {
+ ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied_private_ip"), tplSettingsOptions, &form)
+ } else if !addrErr.LocalPath {
+ ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied_blocked"), tplSettingsOptions, &form)
+ } else {
+ ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied"), tplSettingsOptions, &form)
+ }
+ case addrErr.IsInvalidPath:
+ ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), tplSettingsOptions, &form)
+ default:
+ ctx.ServerError("Unknown error", err)
+ }
+ }
ctx.Data["Err_MirrorAddress"] = true
ctx.RenderWithErr(ctx.Tr("repo.mirror_address_url_invalid"), tplSettingsOptions, &form)
return
}
- address = u.String()
-
if err := mirror_service.UpdateAddress(ctx.Repo.Mirror, address); err != nil {
ctx.ServerError("UpdateAddress", err)
return
@@ -951,14 +944,6 @@ func DeleteDeployKey(ctx *context.Context) {
})
}
-func init() {
- var err error
- validFormAddress, err = xurls.StrictMatchingScheme(`(https?)|(git)://`)
- if err != nil {
- panic(err)
- }
-}
-
// UpdateAvatarSetting update repo's avatar
func UpdateAvatarSetting(ctx *context.Context, form auth.AvatarForm) error {
ctxRepo := ctx.Repo.Repository