Compare commits

...

1 commit

Author SHA1 Message Date
Mariano Cano
7fa97bedec
Remove OIDC user regexp check
This commit removes the regular expression check on OIDC usernames.
Although it is not recommended to use any character in a username,
it is possible to create and use them. The tool useradd has the flag
--badname and adduser has --allow-badname and --allow-all-names to
create new users with any character.

Moreover, it is possible to create any username with the rest of
provisioners.

Fixes #1436
2023-07-19 11:05:01 -07:00
3 changed files with 18 additions and 17 deletions

View file

@ -4,7 +4,6 @@ import (
"context" "context"
"crypto/x509" "crypto/x509"
"net/http" "net/http"
"regexp"
"strings" "strings"
"time" "time"
@ -115,20 +114,18 @@ func DefaultIdentityFunc(_ context.Context, p Interface, email string) (*Identit
switch k := p.(type) { switch k := p.(type) {
case *OIDC: case *OIDC:
// OIDC principals would be: // OIDC principals would be:
// ~~1. Preferred usernames.~~ Note: Under discussion, currently disabled // ~~1. Preferred usernames.~~ Note: Under discussion, currently disabled
// 2. Sanitized local. // 2. Sanitized local.
// 3. Raw local (if different). // 3. Raw local (if different).
// 4. Email address. // 4. Email address.
name := SanitizeSSHUserPrincipal(email) name := SanitizeSSHUserPrincipal(email)
if !sshUserRegex.MatchString(name) {
return nil, errors.Errorf("invalid principal '%s' from email '%s'", name, email)
}
usernames := []string{name} usernames := []string{name}
if i := strings.LastIndex(email, "@"); i >= 0 { if i := strings.LastIndex(email, "@"); i >= 0 {
usernames = append(usernames, email[:i]) usernames = append(usernames, email[:i])
} }
usernames = append(usernames, email) usernames = append(usernames, email)
return &Identity{ return &Identity{
// Remove duplicated and empty usernames.
Usernames: SanitizeStringSlices(usernames), Usernames: SanitizeStringSlices(usernames),
}, nil }, nil
default: default:
@ -178,8 +175,6 @@ func DefaultAuthorizeSSHRenew(_ context.Context, p *Controller, cert *ssh.Certif
return nil return nil
} }
var sshUserRegex = regexp.MustCompile("^[a-z][-a-z0-9_]*$")
// SanitizeStringSlices removes duplicated an empty strings. // SanitizeStringSlices removes duplicated an empty strings.
func SanitizeStringSlices(original []string) []string { func SanitizeStringSlices(original []string) []string {
output := []string{} output := []string{}

View file

@ -167,6 +167,12 @@ func TestController_GetIdentity(t *testing.T) {
}}, args{ctx, "jane@doe.org"}, &Identity{ }}, args{ctx, "jane@doe.org"}, &Identity{
Usernames: []string{"jane"}, Usernames: []string{"jane"},
}, false}, }, false},
{"ok badname", fields{&OIDC{}, nil}, args{ctx, "1000@doe.org"}, &Identity{
Usernames: []string{"1000", "1000@doe.org"},
}, false},
{"ok sanitized badname", fields{&OIDC{}, nil}, args{ctx, "1000+10@doe.org"}, &Identity{
Usernames: []string{"1000_10", "1000+10", "1000+10@doe.org"},
}, false},
{"fail provisioner", fields{&JWK{}, nil}, args{ctx, "jane@doe.org"}, nil, true}, {"fail provisioner", fields{&JWK{}, nil}, args{ctx, "jane@doe.org"}, nil, true},
{"fail custom", fields{&OIDC{}, func(ctx context.Context, p Interface, email string) (*Identity, error) { {"fail custom", fields{&OIDC{}, func(ctx context.Context, p Interface, email string) (*Identity, error) {
return nil, fmt.Errorf("an error") return nil, fmt.Errorf("an error")

View file

@ -76,13 +76,6 @@ func TestDefaultIdentityFunc(t *testing.T) {
err: errors.New("provisioner type '*provisioner.X5C' not supported by identity function"), err: errors.New("provisioner type '*provisioner.X5C' not supported by identity function"),
} }
}, },
"fail/bad-ssh-regex": func(t *testing.T) test {
return test{
p: &OIDC{},
email: "$%^#_>@smallstep.com",
err: errors.New("invalid principal '______' from email '$%^#_>@smallstep.com'"),
}
},
"ok": func(t *testing.T) test { "ok": func(t *testing.T) test {
return test{ return test{
p: &OIDC{}, p: &OIDC{},
@ -142,6 +135,13 @@ func TestDefaultIdentityFunc(t *testing.T) {
identity: &Identity{Usernames: []string{"john", "john@smallstep.com"}}, identity: &Identity{Usernames: []string{"john", "john@smallstep.com"}},
} }
}, },
"ok/badname": func(t *testing.T) test {
return test{
p: &OIDC{},
email: "$%^#_>@smallstep.com",
identity: &Identity{Usernames: []string{"______", "$%^#_>", "$%^#_>@smallstep.com"}},
}
},
} }
for name, get := range tests { for name, get := range tests {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {