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>
This commit is contained in:
parent
f268b4896b
commit
6e423d5573
10 changed files with 166 additions and 130 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
address, err := auth.ParseRemoteAddr(form.MirrorAddress, form.MirrorUsername, form.MirrorPassword)
|
||||
if err == nil {
|
||||
err = migrations.IsMigrateURLAllowed(address, ctx.User)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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() {
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue