Skip to content

Commit

Permalink
Ensure valid git author names passed in signatures (#5774)
Browse files Browse the repository at this point in the history
* Ensure valid git author names passed in signatures

Fix #5772 - Git author names are not allowed to include `\n` `<` or `>` and
must not be empty. Ensure that the name passed in a signature is valid.

* Account for pathologically named external users

LDAP and the like usernames are not checked in the same way that users who signup are.
Therefore just ensure that user names are also git safe and if totally pathological -
Set them to "user-$UID"

* Add Tests and adjust test users

Make our testcases a little more pathological so that we be sure that integration
tests have a chance to spot these cases.

Signed-off-by: Andrew Thornton <[email protected]>
  • Loading branch information
zeripath authored and lafriks committed Jan 24, 2019
1 parent cd83c2c commit 44371b9
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 13 deletions.
17 changes: 11 additions & 6 deletions integrations/api_user_orgs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
"net/http"
"testing"

"code.gitea.io/gitea/models"
api "code.gitea.io/sdk/gitea"

"github.com/stretchr/testify/assert"
)

Expand All @@ -23,14 +25,16 @@ func TestUserOrgs(t *testing.T) {
req := NewRequest(t, "GET", urlStr)
resp := session.MakeRequest(t, req, http.StatusOK)
var orgs []*api.Organization
user3 := models.AssertExistsAndLoadBean(t, &models.User{Name: "user3"}).(*models.User)

DecodeJSON(t, resp, &orgs)

assert.Equal(t, []*api.Organization{
{
ID: 3,
UserName: "user3",
FullName: "User Three",
AvatarURL: "https://secure.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?d=identicon",
UserName: user3.Name,
FullName: user3.FullName,
AvatarURL: user3.AvatarLink(),
Description: "",
Website: "",
Location: "",
Expand All @@ -48,13 +52,14 @@ func TestMyOrgs(t *testing.T) {
resp := session.MakeRequest(t, req, http.StatusOK)
var orgs []*api.Organization
DecodeJSON(t, resp, &orgs)
user3 := models.AssertExistsAndLoadBean(t, &models.User{Name: "user3"}).(*models.User)

assert.Equal(t, []*api.Organization{
{
ID: 3,
UserName: "user3",
FullName: "User Three",
AvatarURL: "https://secure.gravatar.com/avatar/97d6d9441ff85fdc730e02a6068d267b?d=identicon",
UserName: user3.Name,
FullName: user3.FullName,
AvatarURL: user3.AvatarLink(),
Description: "",
Website: "",
Location: "",
Expand Down
1 change: 1 addition & 0 deletions integrations/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func TestRenameInvalidUsername(t *testing.T) {
"%2f..",
"%00",
"thisHas ASpace",
"p<A>tho>lo<gical",
}

session := loginUser(t, "user2")
Expand Down
6 changes: 3 additions & 3 deletions models/fixtures/user.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
id: 2
lower_name: user2
name: user2
full_name: User Two
full_name: " < U<se>r Tw<o > >< "
email: [email protected]
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password
type: 0 # individual
Expand All @@ -37,7 +37,7 @@
id: 3
lower_name: user3
name: user3
full_name: User Three
full_name: " <<<< >> >> > >> > >>> >> "
email: [email protected]
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password
type: 1 # organization
Expand All @@ -53,7 +53,7 @@
id: 4
lower_name: user4
name: user4
full_name: User Four
full_name: " "
email: [email protected]
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password
type: 0 # individual
Expand Down
2 changes: 1 addition & 1 deletion models/issue_reaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func TestIssueReactionCount(t *testing.T) {
reactions := issue1.Reactions.GroupByType()
assert.Len(t, reactions["heart"], 4)
assert.Equal(t, 2, reactions["heart"].GetMoreUserCount())
assert.Equal(t, "User One, User Two", reactions["heart"].GetFirstUsers())
assert.Equal(t, user1.DisplayName()+", "+user2.DisplayName(), reactions["heart"].GetFirstUsers())
assert.True(t, reactions["heart"].HasUser(1))
assert.False(t, reactions["heart"].HasUser(5))
assert.False(t, reactions["heart"].HasUser(0))
Expand Down
27 changes: 24 additions & 3 deletions models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ func (u *User) GetFollowing(page int) ([]*User, error) {
// NewGitSig generates and returns the signature of given user.
func (u *User) NewGitSig() *git.Signature {
return &git.Signature{
Name: u.DisplayName(),
Name: u.GitName(),
Email: u.getEmail(),
When: time.Now(),
}
Expand Down Expand Up @@ -630,12 +630,33 @@ func (u *User) GetOrganizations(all bool) error {
// DisplayName returns full name if it's not empty,
// returns username otherwise.
func (u *User) DisplayName() string {
if len(u.FullName) > 0 {
return u.FullName
trimmed := strings.TrimSpace(u.FullName)
if len(trimmed) > 0 {
return trimmed
}
return u.Name
}

func gitSafeName(name string) string {
return strings.TrimSpace(strings.NewReplacer("\n", "", "<", "", ">", "").Replace(name))
}

// GitName returns a git safe name
func (u *User) GitName() string {
gitName := gitSafeName(u.FullName)
if len(gitName) > 0 {
return gitName
}
// Although u.Name should be safe if created in our system
// LDAP users may have bad names
gitName = gitSafeName(u.Name)
if len(gitName) > 0 {
return gitName
}
// Totally pathological name so it's got to be:
return fmt.Sprintf("user-%d", u.ID)
}

// ShortName ellipses username to length
func (u *User) ShortName(length int) string {
return base.EllipsisString(u.Name, length)
Expand Down
32 changes: 32 additions & 0 deletions models/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package models

import (
"math/rand"
"strings"
"testing"

"code.gitea.io/gitea/modules/setting"
Expand Down Expand Up @@ -181,3 +182,34 @@ func TestGetOrgRepositoryIDs(t *testing.T) {
// User 5's team has no access to any repo
assert.Len(t, accessibleRepos, 0)
}

func TestNewGitSig(t *testing.T) {
users := make([]*User, 0, 20)
sess := x.NewSession()
defer sess.Close()
sess.Find(&users)

for _, user := range users {
sig := user.NewGitSig()
assert.NotContains(t, sig.Name, "<")
assert.NotContains(t, sig.Name, ">")
assert.NotContains(t, sig.Name, "\n")
assert.NotEqual(t, len(strings.TrimSpace(sig.Name)), 0)
}
}

func TestDisplayName(t *testing.T) {
users := make([]*User, 0, 20)
sess := x.NewSession()
defer sess.Close()
sess.Find(&users)

for _, user := range users {
displayName := user.DisplayName()
assert.Equal(t, strings.TrimSpace(displayName), displayName)
if len(strings.TrimSpace(user.FullName)) == 0 {
assert.Equal(t, user.Name, displayName)
}
assert.NotEqual(t, len(strings.TrimSpace(displayName)), 0)
}
}

0 comments on commit 44371b9

Please sign in to comment.